diff --git a/src/bigmath/chain/chain_ops.hpp b/src/bigmath/chain/chain_ops.hpp new file mode 100644 index 0000000..e69de29 diff --git a/src/bigmath/chain/segment.cpp b/src/bigmath/chain/segment.cpp index 7c9791c..782421c 100644 --- a/src/bigmath/chain/segment.cpp +++ b/src/bigmath/chain/segment.cpp @@ -1,12 +1,11 @@ #include "segment.hpp" +#include + #include namespace bigmath { - u8 add(u8* a, const u8* b, u8* c, u8 carry, u8 length); - u8 sub(u8* a, const u8* b, u8* c, u8 borrow, u8 length); - const u8 segment::digit_count = 128; const u8 segment::byte_count = segment::digit_count / 2; @@ -85,65 +84,8 @@ namespace bigmath { segment low; segment high; - const u32 blen = segment::byte_count; - const u32 blen2 = blen * 2; - const u32 blen4 = blen * 4; - - // Step 1: Unpack raw BCD bytes into raw digit buffers (0-9) - u8 digits_a[blen2]; - u8 digits_b[blen2]; - const u8* bytes_a = bytes(); - const u8* bytes_b = s.bytes(); - - for (u32 i = 0; i < blen; ++i) { - u8 byte_a = bytes_a[i]; - u8 byte_b = bytes_b[i]; - - digits_a[i * 2] = byte_a & 0x0F; - digits_a[i * 2 + 1] = byte_a >> 4; - - digits_b[i * 2] = byte_b & 0x0F; - digits_b[i * 2 + 1] = byte_b >> 4; - } - - // Step 2: Accumulate digit products into temporary array of size blen4 - u16 accum[blen4] = {}; - - for (u32 i = 0; i < blen2; ++i) { - u8 d1 = digits_a[i]; - if (d1 == 0) continue; // Skip zeros - - for (u32 j = 0; j < blen2; ++j) { - u8 d2 = digits_b[j]; - accum[i + j] += static_cast(static_cast(d1) * static_cast(d2)); - } - } - - // Step 3: Base-10 Carry Propagation and Direct Packed BCD Storage - u32 carry = 0; - u8 out_digits[blen4]; - - for (u32 i = 0; i < blen4; ++i) { - u32 sum = accum[i] + carry; - out_digits[i] = static_cast(sum % 10); - carry = sum / 10; - } - - // Step 4: Pack result digits directly into low and high segment bytes - for (u32 i = 0; i < blen; ++i) { - u8 low_digit0 = out_digits[i * 2]; - u8 low_digit1 = out_digits[i * 2 + 1]; - - u8 high_digit0 = out_digits[i * 2 + blen2]; - u8 high_digit1 = out_digits[i * 2 + blen2 + 1]; - - low.set(static_cast(i * 2), low_digit0); - low.set(static_cast(i * 2 + 1), low_digit1); - - high.set(static_cast(i * 2), high_digit0); - high.set(static_cast(i * 2 + 1), high_digit1); - } - + bigmath::mul_long(digits, s.digits, high.digits, low.digits, byte_count); + return { low, high }; } diff --git a/src/bigmath/chain/segment.hpp b/src/bigmath/chain/segment.hpp index 8c86552..6433d5c 100644 --- a/src/bigmath/chain/segment.hpp +++ b/src/bigmath/chain/segment.hpp @@ -2,6 +2,8 @@ #include +#include + namespace bigmath { /** diff --git a/src/bigmath/chain/segment_ops.cpp b/src/bigmath/chain/segment_ops.cpp index f726b3e..fd8542e 100644 --- a/src/bigmath/chain/segment_ops.cpp +++ b/src/bigmath/chain/segment_ops.cpp @@ -69,4 +69,69 @@ namespace bigmath { return borrow; } + void mul_long(const u8* a, const u8* b, u8* c_high, u8* c_low, u8 length) { + const u32 blen = length; + const u32 blen2 = blen * 2; + const u32 blen4 = blen * 4; + + // Step 1: Unpack raw BCD bytes into raw digit buffers (0-9) + u8 digits_a[blen2]; + u8 digits_b[blen2]; + + for (u32 i = 0; i < blen; ++i) { + u8 byte_a = a[i]; + u8 byte_b = b[i]; + + digits_a[i * 2] = byte_a & 0x0F; + digits_a[i * 2 + 1] = byte_a >> 4; + + digits_b[i * 2] = byte_b & 0x0F; + digits_b[i * 2 + 1] = byte_b >> 4; + } + + // Step 2: Accumulate digit products into temporary array of size blen4 + u16 accum[blen4] = {}; + + for (u32 i = 0; i < blen2; ++i) { + u8 d1 = digits_a[i]; + if (d1 == 0) continue; // Skip zeros + + for (u32 j = 0; j < blen2; ++j) { + u8 d2 = digits_b[j]; + accum[i + j] += static_cast(static_cast(d1) * static_cast(d2)); + } + } + + // Step 3: Base-10 Carry Propagation and Direct Packed BCD Storage + u32 carry = 0; + u8 out_digits[blen4]; + + for (u32 i = 0; i < blen4; ++i) { + u32 sum = accum[i] + carry; + out_digits[i] = static_cast(sum % 10); + carry = sum / 10; + } + + // Step 4: Pack result digits directly into low and high segment bytes + for (u32 i = 0; i < blen; ++i) { + u8 low_digit0 = out_digits[i * 2]; + u8 low_digit1 = out_digits[i * 2 + 1]; + + u8 high_digit0 = out_digits[i * 2 + blen2]; + u8 high_digit1 = out_digits[i * 2 + blen2 + 1]; + + // No longer using the object version, + // so we set the bytes ourselves! + c_low[i] = low_digit0 | low_digit1 << 4; + //low.set(static_cast(i * 2), low_digit0); + //low.set(static_cast(i * 2 + 1), low_digit1); + + c_high[i] = high_digit0 | high_digit1 << 4; + //high.set(static_cast(i * 2), high_digit0); + //high.set(static_cast(i * 2 + 1), high_digit1); + } + + // end! + } + } diff --git a/src/bigmath/chain/segment_ops.hpp b/src/bigmath/chain/segment_ops.hpp new file mode 100644 index 0000000..cbb0d82 --- /dev/null +++ b/src/bigmath/chain/segment_ops.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include + +namespace bigmath { + + u8 add(u8* a, const u8* b, u8* c, u8 carry, u8 length); + + u8 sub(u8* a, const u8* b, u8* c, u8 borrow, u8 length); + + void mul_long(const u8* a, const u8* b, u8* c_high, u8* c_low, u8 length); + + void mul_karatsuba(const u8* a, const u8* b, u8* c_high, u8* c_low, u8 length); + + void div_long(const u8* a, const u8* b, u8* quot, u8* rem, u8 length); + + void div_newtonraphson(const u8* a, const u8* b, u8* quot, u8 length); + +} diff --git a/src/bigmath/dot_chain/dot_chain_ops.cpp b/src/bigmath/dot_chain/dot_chain_ops.cpp new file mode 100644 index 0000000..e69de29