diff --git a/dap-sdk/core/include/dap_math_ops.h b/dap-sdk/core/include/dap_math_ops.h index 1423f6f39dd291f4424761724c8859ab8b6f3e3a..68b0ae07200b3cc2fb893c7af43dae7697dc5804 100755 --- a/dap-sdk/core/include/dap_math_ops.h +++ b/dap-sdk/core/include/dap_math_ops.h @@ -1,115 +1,462 @@ #pragma once #include <stdint.h> -#include "dap_common.h" #include <stdio.h> +#define __STDC_FORMAT_MACROS +#include <inttypes.h> -#ifdef DAP_GLOBAL_IS_INT128 +#include "dap_common.h" + +#if defined(__GNUC__) || defined (__clang__) + +#if __SIZEOF_INT128__ == 16 + +#define DAP_GLOBAL_IS_INT128 +typedef __int128 _dap_int128_t; + +#if !defined (int128_t) typedef __int128 int128_t; -typedef __uint128 uint128_t; -#else +#endif + +#if !defined (uint128_t) +typedef unsigned __int128 uint128_t; +#endif + + +#else // __SIZEOF_INT128__ == 16 + typedef union uint128 { - struct { - uint64_t hi; - uint64_t lo; - } DAP_ALIGN_PACKED; + struct{ + uint64_t hi; + uint64_t lo; + } DAP_ALIGN_PACKED; uint64_t u64[2]; uint32_t u32[4]; -} DAP_ALIGN_PACKED uint128_t; -#endif +} uint128_t; + +typedef union int128 { + int64_t i64[2]; + int32_t i32[4]; +} int128_t; -typedef struct unsign256 { +typedef struct uint256_t { uint128_t hi; uint128_t lo; -} DAP_ALIGN_PACKED uint256_t; - -static const uint128_t two_power_64={ .hi = 1, .lo = 0}; - -static const uint64_t lo_32=0xffffffff; -static const uint64_t hi_32=0xffffffff00000000; -static const uint64_t ones_64=0xffffffffffffffff; - -/** - * @brief SUM_64_64 - * @param a_arg1 - * @param a_arg2 - * @param a_result - * @return - */ -static inline int SUM_64_64(uint64_t a_arg1,uint64_t a_arg2,uint64_t* a_result ) -{ - int overflow_flag; - *a_result=a_arg1+a_arg2; - overflow_flag=(*a_result<a_arg1); - return overflow_flag; -} - -/** - * @brief SUM_64_128 - * @details !!! This function returns void because THERE CANNOT BE OVERFLOW IN A (64,64)->128 SUM!!!! - * @param a_arg1 - * @param a_arg2 - * @param a_result - */ -static inline void SUM_64_128(uint64_t a_arg1,uint64_t a_arg2,uint128_t* a_result ) -{ - int overflow_flag; - a_result->lo=a_arg1+a_arg2; - a_result->hi=(a_result->lo<a_arg1); -} - -/** - * @brief ADD_64_INTO_128 - * @details Mixed precision: add a uint64_t into a unsign128_t - * @param a_arg - * @param a_proc_value - * @return - */ -static inline int ADD_64_INTO_128(uint64_t a_arg,uint128_t* a_proc_value ) -{ - int overflow_flag; - uint64_t overflow_64; - uint64_t temp; - temp=a_proc_value->lo; - overflow_flag=SUM_64_64(a_arg,temp,&a_proc_value->lo); + + } uint256_t; + +typedef struct uint512_t { + uint256_t hi; + uint256_t lo; + + } uint512_t; + +typedef int128_t _dap_int128_t; + +#endif // __SIZEOF_INT128__ == 16 + +#endif //defined(__GNUC__) || defined (__clang__) + +uint128_t dap_uint128_substract(uint128_t a, uint128_t b); +uint128_t dap_uint128_add(uint128_t a, uint128_t b); +bool dap_uint128_check_equal(uint128_t a, uint128_t b); + + + +//////////////////////////////////////////////////////////////////////////////////////////////// + +const uint128_t two_power_64={ .hi = 1, .lo = 0}; +const uint128_t lo_64={ .hi = 0, .lo = 0xffffffffffffffff}; +const uint128_t hi_64={ .hi = 0xffffffffffffffff, .lo = 0}; +const uint128_t zero_128={.hi=0,.lo=0}; + +const uint256_t zero_256={.hi=zero_128,.lo=zero_128}; + +const uint64_t lo_32=0xffffffff; +const uint64_t hi_32=0xffffffff00000000; +const uint64_t ones_64=0xffffffffffffffff; + + + +static inline bool EQUAL_128(uint128_t a_128_bit, uint128_t b_128_bit){ +#ifdef DAP_GLOBAL_IS_INT128 + return a_128_bit == b_128_bit; +#else + return a_128_bit.lo==b_128_bit.lo && a_128_bit.hi==b_128_bit.hi; +#endif +} + +static inline bool EQUAL_256(uint256_t a_256_bit, uint256_t b_256_bit){ + +#ifdef DAP_GLOBAL_IS_INT128 + return a_256_bit.lo==b_256_bit.lo && a_256_bit.hi==b_256_bit.hi; + +#else + return a_256_bit.lo.lo==b_256_bit.lo.lo && + a_256_bit.lo.hi==b_256_bit.lo.hi && + a_256_bit.hi.lo==b_256_bit.hi.lo && + a_256_bit.hi.hi==b_256_bit.hi.hi; +#endif +} + +static inline uint128_t AND_128(uint128_t a_128_bit,uint128_t b_128_bit){ + +#ifdef DAP_GLOBAL_IS_INT128 + return a_128_bit&b_128_bit; + +#else + uint128_t output={ .hi = 0, .lo = 0}; + output.hi= a_128_bit.hi & b_128_bit.hi; + output.lo= a_128_bit.lo & b_128_bit.lo; + return output; + +#endif +} + +static inline uint128_t OR_128(uint128_t a_128_bit,uint128_t b_128_bit){ + +#ifdef DAP_GLOBAL_IS_INT128 + return a_128_bit|b_128_bit; + +#else + uint128_t output={ .hi = 0, .lo = 0}; + output.hi= a_128_bit.hi | b_128_bit.hi; + output.lo= a_128_bit.lo | b_128_bit.lo; + return output; + +#endif +} + +static inline uint256_t AND_256(uint256_t a_256_bit,uint256_t b_256_bit){ + +#ifdef DAP_GLOBAL_IS_INT128 + uint256_t output={ .hi = zero_128, .lo = zero_128}; + output.hi= a_256_bit.hi | b_256_bit.hi; + output.lo= a_256_bit.lo | b_256_bit.lo; + return output; + +#else + uint256_t output={ .hi = zero_128, .lo = zero_128}; + output.hi= AND_128(a_256_bit.hi, b_256_bit.hi); + output.lo= AND_128(a_256_bit.lo, b_256_bit.lo); + return output; + +#endif +} + +static inline uint256_t OR_256(uint256_t a_256_bit,uint256_t b_256_bit){ + +#ifdef DAP_GLOBAL_IS_INT128 + uint256_t output={ .hi = zero_128, .lo = zero_128}; + output.hi= a_256_bit.hi | b_256_bit.hi; + output.lo= a_256_bit.lo | b_256_bit.lo; + return output; + +#else + uint256_t output={ .hi = zero_128, .lo = zero_128}; + output.hi= OR_128(a_256_bit.hi, b_256_bit.hi); + output.lo= OR_128(a_256_bit.lo, b_256_bit.lo); + return output; + +#endif +} + +static inline void LEFT_SHIFT_128(uint128_t a_128_bit,uint128_t* b_128_bit,int n){ + assert (n <= 128); + +#ifdef DAP_GLOBAL_IS_INT128 + *b_128_bit=a_128_bit<<n; + +#else + if (n >= 64) // shifting 64-bit integer by more than 63 bits is not defined + { + a_128_bit.hi=a_128_bit.lo; + a_128_bit.lo=0; + LEFT_SHIFT_128(a_128_bit,b_128_bit,n-64); + } + if (n == 0) + { + b_128_bit->hi=a_128_bit.hi; + b_128_bit->lo=a_128_bit.lo; + } + else + { uint64_t shift_temp; + shift_temp=a_128_bit.lo<<n; + b_128_bit->lo=shift_temp; + b_128_bit->hi=(a_128_bit.hi<<n)|(a_128_bit.lo>>(64-n)); + } + +#endif +} + +static inline void RIGHT_SHIFT_128(uint128_t a_128_bit,uint128_t* b_128_bit,int n){ + assert (n <= 128); + +#ifdef DAP_GLOBAL_IS_INT128 + *a_128_bit=b_128_bit>>n; + +#else + + if (n >= 64) // shifting 64-bit integer by more than 63 bits is not defined + { + a_128_bit.lo=a_128_bit.hi; + a_128_bit.hi=0; + RIGHT_SHIFT_128(a_128_bit,b_128_bit,n-64); + } + if (n == 0) + { + b_128_bit->hi=a_128_bit.hi; + b_128_bit->lo=a_128_bit.lo; + } + else + { uint64_t shift_temp; + shift_temp=a_128_bit.hi>>n; + b_128_bit->hi=shift_temp; + b_128_bit->lo=(a_128_bit.lo>>n)|(a_128_bit.hi<<(64-n)); + } +#endif +} + + +static inline void LEFT_SHIFT_256(uint256_t a_256_bit,uint256_t* b_256_bit,int n){ + + assert (n <= 256); + +#ifdef DAP_GLOBAL_IS_INT128 + + if (n >= 128) + { + a_256_bit.hi=a_256_bit.lo; + a_256_bit.lo=0; + LEFT_SHIFT_256(a_256_bit,b_256_bit,n-128); + } + if (n == 0) + { + b_256_bit->hi=a_256_bit.hi; + b_256_bit->lo=a_256_bit.lo; + } + else + { uint128_t shift_temp; + shift_temp=a_256_bit.lo<<n; + b_256_bit->lo=shift_temp; + b_256_bit->hi=(a_256_bit.hi<<n)|(a_256_bit.lo>>(128-n)); + } + +#else + if (n >= 128) // shifting 64-bit integer by more than 63 bits is not defined + { + a_256_bit.hi=a_256_bit.lo; + a_256_bit.lo=zero_128; + LEFT_SHIFT_256(a_256_bit,b_256_bit,n-128); + } + if (n == 0) + { + b_256_bit->hi=a_256_bit.hi; + b_256_bit->lo=a_256_bit.lo; + } + if (n<128) + { uint128_t shift_temp{.hi=0, .lo=0}; + LEFT_SHIFT_128(a_256_bit.lo,&shift_temp,n); + b_256_bit->lo=shift_temp; + uint128_t shift_temp_or_left{.hi=0, .lo=0}; + uint128_t shift_temp_or_right{.hi=0, .lo=0}; + LEFT_SHIFT_128(a_256_bit.hi,&shift_temp_or_left,n); + RIGHT_SHIFT_128(a_256_bit.lo,&shift_temp_or_right,128-n); + b_256_bit->hi=OR_128(shift_temp_or_left,shift_temp_or_right); + } +#endif +} + +static inline void RIGHT_SHIFT_256(uint256_t a_256_bit,uint256_t* b_256_bit,int n){ + assert (n <= 256); + +#ifdef DAP_GLOBAL_IS_INT128 + + if (n >= 128) + { + a_256_bit.lo=a_256_bit.hi; + a_256_bit.hi=0; + RIGHT_SHIFT_256(a_256_bit,b_256_bit,n-128); + } + if (n == 0) + { + b_256_bit->hi=a_256_bit.hi; + b_256_bit->lo=a_256_bit.lo; + } + else + { uint64_t shift_temp; + shift_temp=a_256_bit.hi>>n; + b_256_bit->hi=shift_temp; + b_256_bit->lo=(a_256_bit.lo>>n)|(a_256_bit.hi<<(128-n)); + +#else + if (n >= 128) // shifting 64-bit integer by more than 63 bits is not defined + { + a_256_bit.lo=a_256_bit.hi; + a_256_bit.hi=zero_128; + RIGHT_SHIFT_256(a_256_bit,b_256_bit,n-128); + } + if (n == 0) + { + b_256_bit->hi=a_256_bit.hi; + b_256_bit->lo=a_256_bit.lo; + } + if (n<128) + { uint128_t shift_temp{.hi=0, .lo=0}; + RIGHT_SHIFT_128(a_256_bit.hi,&shift_temp,n); + b_256_bit->hi=shift_temp; + uint128_t shift_temp_or_left{.hi=0, .lo=0}; + uint128_t shift_temp_or_right{.hi=0, .lo=0}; + RIGHT_SHIFT_128(a_256_bit.lo,&shift_temp_or_left,n); + LEFT_SHIFT_128(a_256_bit.hi,&shift_temp_or_right,128-n); + b_256_bit->lo=OR_128(shift_temp_or_left,shift_temp_or_right); + } +#endif +} + +static inline void INCR_128(uint128_t* a_128_bit){ + +#ifdef DAP_GLOBAL_IS_INT128 + *a_128_bit++; + +#else + a_128_bit->lo++; + if(a_128_bit->lo == 0) + { + a_128_bit->hi++; + } +#endif +} + +//static inline void DECR_128(uint128_t* a_128_bit){ +// +//#ifdef DAP_GLOBAL_IS_INT128 +// *a_128_bit--; +// +//#else +// a_128_bit->lo--; +// if(a_128_bit->hi == 0) +// { +// a_128_bit->hi--; +// } +//#endif +//} +// +static inline void INCR_256(uint256_t* a_256_bit){ + +#ifdef DAP_GLOBAL_IS_INT128 + a_256_bit->lo++; + if(a_256_bit->lo == 0) + { + a_256_bit->hi++; + } + +#else + INCR_128(&a_256_bit->lo); + if(EQUAL_128(a_256_bit->lo, zero_128)) + { + INCR_128(&a_256_bit->hi); + } +#endif +} + +static inline int SUM_64_64(uint64_t a_64_bit,uint64_t b_64_bit,uint64_t* c_64_bit ) { + +int overflow_flag; +*c_64_bit=a_64_bit+b_64_bit; +overflow_flag=(*c_64_bit<a_64_bit); +return overflow_flag;} + + + +static inline int OVERFLOW_SUM_64_64(uint64_t a_64_bit,uint64_t b_64_bit) { + +int overflow_flag; +overflow_flag=(a_64_bit+b_64_bit<a_64_bit); +return overflow_flag;} + +static inline int MULT_64_64(uint64_t a_64_bit,uint64_t b_64_bit,uint64_t* c_64_bit ) { + +int overflow_flag; +*c_64_bit=a_64_bit*b_64_bit; +overflow_flag=(a_64_bit>ones_64/b_64_bit); +return overflow_flag;} + +static inline int OVERFLOW_MULT_64_64(uint64_t a_64_bit,uint64_t b_64_bit) { + +int overflow_flag; +overflow_flag=(a_64_bit>ones_64/b_64_bit); +return overflow_flag;} + +// +//static inline void SUM_64_128(uint64_t a_64_bit,uint64_t b_64_bit,uint128_t* c_128_bit ) { +//int overflow_flag; +//c_128_bit->lo=a_64_bit+b_64_bit; +//c_128_bit->hi=(c_128_bit->lo<a_64_bit);} + +//Mixed precision: add a uint64_t into a uint128_t +static inline int ADD_64_INTO_128(uint64_t a_64_bit,uint128_t* c_128_bit ) { + int overflow_flag=0; + uint64_t overflow_64=0; + uint64_t temp=0; + temp=c_128_bit->lo; + overflow_flag=SUM_64_64(a_64_bit,temp,&c_128_bit->lo); overflow_64=overflow_flag; - temp=a_proc_value->hi; - overflow_flag=SUM_64_64(overflow_64,temp,&a_proc_value->hi); - return overflow_flag; -} - -/** - * @brief SUM_128_128 - * @param a_arg1 - * @param a_arg2 - * @param a_result - * @return - */ -static inline int SUM_128_128(uint128_t a_arg1,uint128_t a_arg2,uint128_t* a_result) -{ + temp=c_128_bit->hi; + overflow_flag=SUM_64_64(overflow_64,temp,&c_128_bit->hi); + return overflow_flag;} + +static inline int SUM_128_128(uint128_t a_128_bit,uint128_t b_128_bit,uint128_t* c_128_bit){ int overflow_flag; - overflow_flag=SUM_64_64(a_arg1.lo,a_arg2.lo,&a_result->lo); + int overflow_flag_intermediate; + overflow_flag=SUM_64_64(a_128_bit.lo,b_128_bit.lo,&c_128_bit->lo); uint64_t carry_in_64=overflow_flag; uint64_t intermediate_value=0; overflow_flag=0; - overflow_flag=SUM_64_64(a_arg1.hi,a_arg2.hi,&intermediate_value); - carry_in_64=overflow_flag; - overflow_flag=0; - overflow_flag=SUM_64_64(carry_in_64,intermediate_value,&a_result->hi); - return overflow_flag; -} - -/** - * @brief SUM_256_256 - * @param a_arg1 - * @param a_arg2 - * @param a_result - * @return - */ -static inline int SUM_256_256(uint256_t a_arg1,uint256_t a_arg2,uint256_t* a_result) + overflow_flag=SUM_64_64(carry_in_64,a_128_bit.hi,&intermediate_value); + overflow_flag_intermediate=SUM_64_64(intermediate_value,b_128_bit.hi,&c_128_bit->hi); + int return_overflow=overflow_flag|overflow_flag_intermediate; + return return_overflow;} + +static inline int SUBTRACT_128_128(uint128_t a_128_bit, uint128_t b_128_bit,uint128_t* c_128_bit) { + c_128_bit->lo = a_128_bit.lo - b_128_bit.lo; + uint64_t carry = (((c_128_bit->lo & b_128_bit.lo) & 1) + (b_128_bit.lo >> 1) + (c_128_bit->lo >> 1)) >> 63; + c_128_bit->hi = a_128_bit.hi - (b_128_bit.hi + carry); + int underflow_flag=carry; + return underflow_flag; +} + +//static inline int SUBTRACT_256_256(uint256_t a_256_bit, uint256_t b_256_bit,uint256_t* c_256_bit){ +// +// if +// int carry=0; +// carry=SUBTRACT_128_128(a_256_bit.lo, b_256_bit.lo,&c_256_bit->lo); +// uint64_t carry_64=carry; +// uint128_t carry_128{.hi=0,.lo=carry_64}; +// uint128_t intermediate_val{.hi=0,.lo=0}; +// int dummy_overflow=0; +// dummy_overflow=SUM_128_128(b_256_bit.hi,carry_128,&intermediate_val); +// carry=SUBTRACT_128_128(a_256_bit.hi, intermediate_val,&c_256_bit->hi ); +// return carry; +//} +// +//Mixed precision: add a uint128_t into a uint256_t +static inline int ADD_128_INTO_256(uint128_t a_128_bit,uint256_t* c_256_bit) { + int overflow_flag=0; + uint128_t overflow_128={.hi=0,.lo=0}; + uint128_t temp={.hi=0,.lo=0}; + temp=c_256_bit->lo; + overflow_flag=SUM_128_128(a_128_bit,temp,&c_256_bit->lo); + overflow_128.lo=overflow_flag; + temp=c_256_bit->hi; + overflow_flag=SUM_128_128(overflow_128,temp,&c_256_bit->hi); + return overflow_flag;} + + +static inline int SUM_256_256(uint256_t a_256_bit,uint256_t b_256_bit,uint256_t* c_256_bit){ int overflow_flag; - overflow_flag=SUM_128_128(a_arg1.lo,a_arg2.lo,&a_result->lo); + overflow_flag=SUM_128_128(a_256_bit.lo,b_256_bit.lo,&c_256_bit->lo); uint128_t carry_in_128; carry_in_128.hi=0; carry_in_128.lo=overflow_flag; @@ -117,86 +464,423 @@ static inline int SUM_256_256(uint256_t a_arg1,uint256_t a_arg2,uint256_t* a_re intermediate_value.hi=0; intermediate_value.lo=0; overflow_flag=0; - overflow_flag=SUM_128_128(carry_in_128,a_arg1.hi,&intermediate_value); + overflow_flag=SUM_128_128(carry_in_128,a_256_bit.hi,&intermediate_value); //we store overflow_flag in case there is already overflow int overflow_flag_bis=0; - overflow_flag_bis=SUM_128_128(intermediate_value,a_arg2.hi,&a_result->hi); + overflow_flag_bis=SUM_128_128(intermediate_value,b_256_bit.hi,&c_256_bit->hi); overflow_flag=overflow_flag||overflow_flag_bis; - return overflow_flag; -} + return overflow_flag;} + +static inline int SUBTRACT_256_256(uint256_t a_256_bit,uint256_t b_256_bit,uint256_t* c_256_bit){ + +//(u64 rd[4], const u64 ad[4], const u64 bd[4]) + uint64_t t, r, borrow; + + t = a_256_bit.lo.lo; + r = t - b_256_bit.lo.lo; + borrow = (r > t); + c_256_bit->lo.lo = r; + + t = a_256_bit.lo.hi; + t -= borrow; + borrow = (t > a_256_bit.lo.hi); + r = t - b_256_bit.lo.hi; + borrow |= (r > t); + c_256_bit->lo.hi = r; + + t = a_256_bit.hi.lo; + t -= borrow; + borrow = (t > a_256_bit.hi.lo); + r = t - b_256_bit.hi.lo; + borrow |= (r > t); + c_256_bit->hi.lo = r; + + t = a_256_bit.hi.hi; + t -= borrow; + borrow = (t > a_256_bit.hi.hi); + r = t - b_256_bit.hi.hi; + borrow |= (r > t); + c_256_bit->hi.hi = r; + + return borrow; -/** - * @brief dap_uint128_add - * @param a_arg1 - * @param a_arg2 - * @return - */ -static inline uint128_t dap_uint128_add (uint128_t a_arg1, uint128_t a_arg2) + } + +//Mixed precision: add a uint256_t into a uint512_t +static inline int ADD_256_INTO_512(uint256_t a_256_bit,uint512_t* c_512_bit) { + int overflow_flag=0; + uint256_t overflow_256={.hi=zero_128,.lo=zero_128}; + uint256_t temp={.hi=zero_128,.lo=zero_128}; + temp=c_512_bit->lo; + overflow_flag=SUM_256_256(a_256_bit,temp,&c_512_bit->lo); + overflow_256.lo.lo=overflow_flag; + temp=c_512_bit->hi; + overflow_flag=SUM_256_256(overflow_256,temp,&c_512_bit->hi); + return overflow_flag;} + + +static inline void MULT_64_128(uint64_t a_64_bit, uint64_t b_64_bit, uint128_t* c_128_bit) { - uint128_t l_ret; - memset(&l_ret,0,sizeof(l_ret)); + uint64_t a_64_bit_hi = (a_64_bit & 0xffffffff); + uint64_t b_64_bit_hi = (b_64_bit & 0xffffffff); + uint64_t prod_hi = (a_64_bit_hi * b_64_bit_hi); + uint64_t w3 = (prod_hi & 0xffffffff); + uint64_t prod_hi_shift_right = (prod_hi >> 32); - SUM_128_128(a_arg1, a_arg2, & l_ret); - return l_ret; + a_64_bit >>= 32; + prod_hi = (a_64_bit * b_64_bit_hi) + prod_hi_shift_right; + prod_hi_shift_right = (prod_hi & 0xffffffff); + uint64_t w1 = (prod_hi >> 32); + + b_64_bit >>= 32; + prod_hi = (a_64_bit_hi * b_64_bit) + prod_hi_shift_right; + prod_hi_shift_right = (prod_hi >> 32); + + c_128_bit->hi = (a_64_bit * b_64_bit) + w1 + prod_hi_shift_right; + c_128_bit->lo = (prod_hi << 32) + w3; } -/** - * @brief dap_uint128_substract - * @param a - * @param b - * @return - */ -static inline uint128_t dap_uint128_substract(uint128_t a, uint128_t b) -{ -#ifdef DAP_GLOBAL_IS_INT128 - if (a < b) { - _log_it("dap_math_ops",L_WARNING, "Substract result overflow"); - return 0; + + +static inline void MULT_128_256(uint128_t a_128_bit,uint128_t b_128_bit,uint256_t* c_256_bit ) { + + //product of .hi terms - stored in .hi field of c_256_bit + MULT_64_128(a_128_bit.hi,b_128_bit.hi, &c_256_bit->hi); + + //product of .lo terms - stored in .lo field of c_256_bit + MULT_64_128(a_128_bit.lo,b_128_bit.lo, &c_256_bit->lo); + + uint128_t cross_product_one{.hi=0, .lo=0}; + uint128_t cross_product_two{.hi=0, .lo=0}; + MULT_64_128(a_128_bit.hi, b_128_bit.lo, &cross_product_one); + c_256_bit->lo.hi += cross_product_one.lo; + if(c_256_bit->lo.hi < cross_product_one.lo) // if overflow + { + INCR_128(&c_256_bit->hi); } - return a - b; -#else - uint128_t l_ret = {}; - if (a.u64[0] < b.u64[0] || (a.u64[0] == b.u64[0] && a.u64[1] < b.u64[1])) { - _log_it("dap_math_ops",L_WARNING, "Substract result overflow"); - return l_ret; - } - l_ret.u64[0] = a.u64[0] - b.u64[0]; - l_ret.u64[1] = a.u64[1] - b.u64[1]; - if (a.u64[1] < b.u64[1]) - l_ret.u64[0]--; - return l_ret; -#endif + c_256_bit->hi.lo += cross_product_one.hi; + if(c_256_bit->hi.lo < cross_product_one.hi) // if overflowed + { + c_256_bit->hi.hi+=1; + } + + MULT_64_128(a_128_bit.lo, b_128_bit.hi, &cross_product_two); + c_256_bit->lo.hi += cross_product_two.lo; + if(c_256_bit->lo.hi < cross_product_two.lo) // if overflowed + { + INCR_128(&c_256_bit->hi); + } + c_256_bit->hi.lo += cross_product_two.hi; + if(c_256_bit->hi.lo < cross_product_two.hi) // overflowed + { + c_256_bit->hi.hi+=1; + } +} + +static inline int MULT_128_128_NEW(uint128_t a_128_bit,uint128_t b_128_bit,uint128_t* accum_128_bit){ + int overflow=0; + int equal_flag=0; + uint256_t full_product_256{.hi=zero_128, .lo=zero_128}; + MULT_128_256(a_128_bit,b_128_bit,&full_product_256); + *accum_128_bit=full_product_256.lo; + equal_flag=EQUAL_128(full_product_256.hi,zero_128); + if (!equal_flag) + { + overflow=1; + } + return overflow; +} + +static inline int MULT_128_128(uint128_t a_128_bit,uint128_t b_128_bit,uint128_t* accum_128_bit) { + uint64_t A=(b_128_bit.lo & lo_32)*(a_128_bit.hi & lo_32); + uint64_t B_32_64=((b_128_bit.lo & lo_32)*(a_128_bit.hi & hi_32))&hi_32; + uint64_t C_32_64=((b_128_bit.lo & hi_32)*(a_128_bit.hi & lo_32))&hi_32; + uint64_t E=(a_128_bit.lo & lo_32)*(b_128_bit.hi & lo_32); + uint64_t F_32_64=((a_128_bit.lo & lo_32)*(b_128_bit.hi & hi_32))&hi_32; + uint64_t G_32_64=((a_128_bit.lo & hi_32)*(b_128_bit.hi & lo_32))&hi_32; + + //initialization of overflow counter + int overflow_ctr=0; + + //checking of overflow from ".hi terms" + int overflow_from_hi_calc=0; + overflow_from_hi_calc=(a_128_bit.hi*b_128_bit.hi>0); + overflow_ctr+=overflow_from_hi_calc; + + //product of two ".lo" terms + MULT_64_128(a_128_bit.lo,b_128_bit.lo,accum_128_bit); + + int overflow=0; + uint64_t temp=0; + + overflow=SUM_64_64(A,temp,&accum_128_bit->hi); + printf("accum_128_bit->hi after add in of A %" PRIu64 "\n",accum_128_bit->hi); + + overflow_ctr+=overflow; + temp=accum_128_bit->hi; + overflow=0; + + overflow=SUM_64_64(B_32_64,temp,&accum_128_bit->hi); + overflow_ctr+=overflow; + temp=accum_128_bit->hi; + overflow=0; + + overflow=SUM_64_64(C_32_64,temp,&accum_128_bit->hi); + overflow_ctr+=overflow; + temp=accum_128_bit->hi; + overflow=0; + + overflow=SUM_64_64(E,temp,&accum_128_bit->hi); + overflow_ctr+=overflow; + temp=accum_128_bit->hi; + overflow=0; + overflow=SUM_64_64(F_32_64,temp,&accum_128_bit->hi); + overflow_ctr+=overflow; + temp=accum_128_bit->hi; + overflow=0; + + overflow=SUM_64_64(G_32_64,temp,&accum_128_bit->hi); + overflow_ctr+=overflow; + temp=accum_128_bit->hi; + overflow=0; + + if(overflow_ctr>0){ + overflow=1;} + else{overflow=0;} + + return overflow; + } + +static inline void MULT_256_512(uint256_t a_256_bit,uint256_t b_256_bit,uint512_t* c_512_bit) { + int dummy_overflow; + //product of .hi terms - stored in .hi field of c_512_bit + MULT_128_256(a_256_bit.hi,b_256_bit.hi, &c_512_bit->hi); + + //product of .lo terms - stored in .lo field of c_512_bit + MULT_128_256(a_256_bit.lo,b_256_bit.lo, &c_512_bit->lo); + + //cross product of .hi and .lo terms + uint256_t cross_product_first_term{ .hi = zero_128, .lo = zero_128}; + uint256_t cross_product_second_term{ .hi = zero_128, .lo = zero_128}; + uint256_t cross_product{ .hi = zero_128, .lo = zero_128}; + uint256_t cross_product_shift_128{ .hi = zero_128, .lo = zero_128}; + uint256_t c_512_bit_lo_copy{ .hi = zero_128, .lo = zero_128}; + uint256_t c_512_bit_hi_copy{ .hi = zero_128, .lo = zero_128}; + int overflow=0; + + MULT_128_256(a_256_bit.hi,b_256_bit.lo,&cross_product_first_term); + MULT_128_256(a_256_bit.lo,b_256_bit.hi,&cross_product_second_term); + overflow=SUM_256_256(cross_product_first_term,cross_product_second_term,&cross_product); + + + LEFT_SHIFT_256(cross_product,&cross_product_shift_128,128); //the factor in front of cross product is 2**128 + c_512_bit_lo_copy=c_512_bit->lo; + dummy_overflow=SUM_256_256(c_512_bit_lo_copy,cross_product_shift_128,&c_512_bit->lo); + + cross_product_shift_128.hi = zero_128; + cross_product_shift_128.lo = zero_128; + RIGHT_SHIFT_256(cross_product,&cross_product_shift_128,128); + c_512_bit_hi_copy=c_512_bit->hi; + dummy_overflow=SUM_256_256(c_512_bit_hi_copy,cross_product_shift_128,&c_512_bit->hi); + } + + +static inline int MULT_256_256_NEW(uint256_t a_256_bit,uint256_t b_256_bit,uint256_t* accum_256_bit){ + + uint128_t two_0_coeff{.hi=0,.lo=0}; + MULT_64_128(a_256_bit.lo.lo,b_256_bit.lo.lo,&two_0_coeff); + accum_256_bit->lo.lo=two_0_coeff.lo; + + uint128_t two_64_coeff{.hi=0,.lo=0}; + uint128_t two_64_coeff_one{.hi=0,.lo=0}; + MULT_64_128(a_256_bit.lo.hi,b_256_bit.lo.lo,&two_64_coeff_one); + uint128_t two_64_coeff_two{.hi=0,.lo=0}; + MULT_64_128(a_256_bit.lo.lo,b_256_bit.lo.hi,&two_64_coeff_two); + uint128_t two_64_coeff_sum{.hi=0,.lo=0}; + int dummy_overflow=0; + dummy_overflow=SUM_128_128(two_64_coeff_one,two_64_coeff_two,&two_64_coeff_sum); + if (two_64_coeff_sum.lo+two_0_coeff.hi<two_64_coeff_sum.lo){ + + two_64_coeff.lo=two_64_coeff_sum.lo+two_0_coeff.hi; + two_64_coeff.hi=1+two_64_coeff_sum.hi;} + else{ + two_64_coeff.lo=two_64_coeff_sum.lo+two_0_coeff.hi; + two_64_coeff.hi=two_64_coeff_sum.hi; + } + accum_256_bit->lo.hi=two_64_coeff.lo; + + + uint128_t two_128_coeff{.hi=0,.lo=0}; + uint128_t two_128_coeff_one{.hi=0,.lo=0}; + MULT_64_128(a_256_bit.lo.lo,b_256_bit.hi.lo,&two_128_coeff_one); + uint128_t two_128_coeff_two{.hi=0,.lo=0}; + MULT_64_128(a_256_bit.hi.lo,b_256_bit.lo.lo,&two_128_coeff_two); + uint128_t two_128_coeff_three{.hi=0,.lo=0}; + MULT_64_128(a_256_bit.lo.hi,b_256_bit.lo.hi,&two_128_coeff_three); + uint128_t two_128_coeff_sum_one{.hi=0,.lo=0}; + dummy_overflow=SUM_128_128(two_128_coeff_one,two_128_coeff_two,&two_128_coeff_sum_one); + uint128_t two_128_coeff_sum_two{.hi=0,.lo=0}; + dummy_overflow=SUM_128_128(two_128_coeff_sum_one,two_128_coeff_three,&two_128_coeff_sum_two); + + if (two_128_coeff_sum_two.lo+two_64_coeff.hi<two_128_coeff_sum_two.lo){ + + two_128_coeff.lo=two_128_coeff_sum_two.lo+two_64_coeff.hi; + two_128_coeff.hi=1+two_128_coeff_sum_two.hi;} + else{ + two_128_coeff.lo=two_128_coeff_sum_two.lo+two_64_coeff.hi; + two_128_coeff.hi=two_128_coeff_sum_two.hi; + } + accum_256_bit->hi.lo=two_128_coeff.lo; + + + +// +// +// +// uint64_t two_192_coeff=0; +// uint64_t two_192_coeff_one=0; +// int overflow_two_192_coeff_one=0; +// overflow_two_192_coeff_one=MULT_64_64(a_256_bit.hi.hi,b_256_bit.lo.lo,&two_192_coeff_one); +// uint64_t two_192_coeff_two=0; +// int overflow_two_192_coeff_two=0; +// overflow_two_192_coeff_two=MULT_64_64(a_256_bit.lo.lo,b_256_bit.hi.hi,&two_192_coeff_two); +// uint64_t two_192_coeff_three=0; +// int overflow_two_192_coeff_three=0; +// overflow_two_192_coeff_three=MULT_64_64(a_256_bit.lo.hi,b_256_bit.hi.lo,&two_192_coeff_three); +// uint64_t two_192_coeff_four=0; +// int overflow_two_192_coeff_four=0; +// overflow_two_192_coeff_four=MULT_64_64(a_256_bit.hi.lo,b_256_bit.lo.hi,&two_192_coeff_four); +// uint64_t two_192_coeff_sum_one=0; +// int overflow_two_192_coeff_sum_one=0; + +// overflow_two_192_coeff_sum_one=SUM_64_64(two_192_coeff_one,two_192_coeff_two,&two_192_coeff_sum_one); +// uint64_t two_192_coeff_sum_two=0; +// int overflow_two_192_coeff_sum_two=0; +// overflow_two_192_coeff_sum_two=SUM_64_64(two_192_coeff_three,two_192_coeff_four,&two_192_coeff_sum_two); +// int overflow_two_192_coeff_sum=0; +// overflow_two_192_coeff_sum=SUM_64_64(two_192_coeff_sum_one,two_192_coeff_sum_two,&two_192_coeff); + + + return 0; + } +static inline int MULT_256_256(uint256_t a_256_bit,uint256_t b_256_bit,uint256_t* accum_256_bit){ + int overflow=0; + int equal_flag=0; + uint512_t full_product_512{.hi=zero_256,.lo=zero_256,}; + MULT_256_512(a_256_bit,b_256_bit,&full_product_512); + *accum_256_bit=full_product_512.lo; + equal_flag=EQUAL_256(full_product_512.hi,zero_256); + if (!equal_flag) + { + overflow=1; + } + return overflow; +} -/** - * @brief dap_uint128_check_equal - * @param a_arg1 - * @param a_arg2 - * @return - */ -static inline bool dap_uint128_check_equal(uint128_t a_arg1, uint128_t a_arg2) +int compare128(uint128_t N1, uint128_t N2) { -#ifdef DAP_GLOBAL_IS_INT128 - return a_128_bit == b_128_bit; -#else - return a_arg1.lo==a_arg2.lo && a_arg1.hi==a_arg2.hi; -#endif + return (((N1.hi > N2.hi) || ((N1.hi == N2.hi) && (N1.lo > N2.lo))) ? 1 : 0) + - (((N1.hi < N2.hi) || ((N1.hi == N2.hi) && (N1.lo < N2.lo))) ? 1 : 0); } -/** - * @brief dap_unsign256_t_check_equal - * @param a_arg1 - * @param a_arg2 - * @return - */ -static inline bool dap_unsign256_t_check_equal(uint256_t a_arg1, uint256_t a_arg2) +size_t nlz64(uint64_t N) { - return a_arg1.lo.lo==a_arg2.lo.lo && - a_arg1.lo.hi==a_arg2.lo.hi && - a_arg1.hi.lo==a_arg2.hi.lo && - a_arg1.hi.hi==a_arg2.hi.hi; + uint64_t I; + size_t C; + + I = ~N; + C = ((I ^ (I + 1)) & I) >> 63; + + I = (N >> 32) + 0xffffffff; + I = ((I & 0x100000000) ^ 0x100000000) >> 27; + C += I; N <<= I; + + I = (N >> 48) + 0xffff; + I = ((I & 0x10000) ^ 0x10000) >> 12; + C += I; N <<= I; + + I = (N >> 56) + 0xff; + I = ((I & 0x100) ^ 0x100) >> 5; + C += I; N <<= I; + + I = (N >> 60) + 0xf; + I = ((I & 0x10) ^ 0x10) >> 2; + C += I; N <<= I; + + I = (N >> 62) + 3; + I = ((I & 4) ^ 4) >> 1; + C += I; N <<= I; + + C += (N >> 63) ^ 1; + + return C; } + +size_t nlz128(uint128_t N) +{ + return (N.hi == 0) ? nlz64(N.lo) + 64 : nlz64(N.hi); +} + +void shiftleft128(uint128_t N, unsigned S, uint128_t* A) +{ + uint64_t M1, M2; + S &= 127; + + M1 = ((((S + 127) | S) & 64) >> 6) - 1llu; + M2 = (S >> 6) - 1llu; + S &= 63; + A->hi = (N.lo << S) & (~M2); + A->lo = (N.lo << S) & M2; + A->hi |= ((N.hi << S) | ((N.lo >> (64 - S)) & M1)) & M2; +} + +void shiftright128(uint128_t N, unsigned S, uint128_t* A) +{ + uint64_t M1, M2; + S &= 127; + + M1 = ((((S + 127) | S) & 64) >> 6) - 1llu; + M2 = (S >> 6) - 1llu; + S &= 63; + A->lo = (N.hi >> S) & (~M2); + A->hi = (N.hi >> S) & M2; + A->lo |= ((N.lo >> S) | ((N.hi << (64 - S)) & M1)) & M2; +} + +void sub128(uint128_t* Ans, uint128_t N, uint128_t M) +{ + Ans->lo = N.lo - M.lo; + uint64_t C = (((Ans->lo & M.lo) & 1) + (M.lo >> 1) + (Ans->lo >> 1)) >> 63; + Ans->hi = N.hi - (M.hi + C); +} +void bindivmod128(uint128_t M, uint128_t N, uint128_t* Q, uint128_t* R) +{ + Q->hi = Q->lo = 0; + size_t Shift = nlz128(N) - nlz128(M); + shiftleft128(N, Shift, &N); + + do + { + shiftleft128(*Q, 1, Q); + if(compare128(M, N) >= 0) + { + sub128(&M, N, M); + Q->lo |= 1; + } + + shiftright128(N, 1, &N); + }while(Shift-- != 0); + + R->hi = M.hi; + R->lo = M.lo; +} + + + + + diff --git a/dap-sdk/core/test/uint256_t/unit_test.cpp b/dap-sdk/core/test/uint256_t/unit_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac4371c00f3453e25c9e2b960ae34416a03eed21 --- /dev/null +++ b/dap-sdk/core/test/uint256_t/unit_test.cpp @@ -0,0 +1,898 @@ +#include <boost/multiprecision/cpp_int.hpp> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include "dap_math_ops.h" +#include <cmath> +#include <iostream> +#include <fstream> + +enum testing_mode{ +FULL=0, +BASIC=1, +SQUARE=2, +}; + +int main() +{ + //using namespace boost::multiprecision; + + //density constant value=2147483646 + std::uint64_t i; + std::uint64_t j; + std::uint64_t k; + std::uint64_t l; + std::uint64_t msb_one=0x7fffffffffffffff; + std::uint64_t lsb_one=1; + boost::uint64_t max_64=(std::numeric_limits<boost::uint64_t>::max)(); + + + /////testing output parameters + int verbose_output=1; + int testing_mode=0; + int density_constant=200; + int division_enabled=0; + + + //2147483646 + int density_index=0; + + int error_counter_sum_64_128=0; + + uint128_t dap_test_128_shift={.hi=0, .lo=0}; + uint128_t dap_test_128_one={.hi=0, .lo=0}; + uint128_t dap_test_128_two={.hi=0, .lo=0}; + uint128_t dap_test_128_sub={.hi=0, .lo=0}; + uint256_t dap_test_256_one={.hi=zero_128, .lo=zero_128}; + uint256_t dap_test_256_two={.hi=zero_128, .lo=zero_128}; + uint256_t dap_test_256_sum={.hi=zero_128, .lo=zero_128}; + uint256_t dap_test_256_sub={.hi=zero_128, .lo=zero_128}; + uint256_t dap_test_256_prod={.hi=zero_128, .lo=zero_128}; + uint256_t dap_test_256_shift={.hi=zero_128, .lo=zero_128}; + uint512_t dap_test_512_prod={.hi=zero_256, .lo=zero_256}; + int overflow_flag; + int overflow_flag_prod; + int borrow_flag_128; + int borrow_flag_256; + + //otherwise the sum structure is filled with garbage + dap_test_256_sum.lo.lo=0; + dap_test_256_sum.lo.hi=0; + dap_test_256_sum.hi.lo=0; + dap_test_256_sum.hi.hi=0; + + std::ofstream sum_256_256_file; + sum_256_256_file.open ("SUM_256_256.txt"); + + std::ofstream sub_128_128_file; + sub_128_128_file.open ("SUB_128_128.txt"); + + std::ofstream sub_256_256_file; + sub_256_256_file.open ("SUB_256_256.txt"); + + std::ofstream prod_64_128_file; + prod_64_128_file.open ("PROD_64_128.txt"); + + std::ofstream prod_128_128_file; + prod_128_128_file.open ("PROD_128_128.txt"); + + std::ofstream prod_128_256_file; + prod_128_256_file.open ("PROD_128_256.txt"); + + std::ofstream prod_256_256_file; + prod_256_256_file.open ("PROD_256_256.txt"); + + std::ofstream prod_256_512_file; + prod_256_512_file.open ("PROD_256_512.txt"); + + std::ofstream shift_left_128_file; + shift_left_128_file.open ("SHIFT_LEFT_128.txt"); + + std::ofstream shift_left_256_file; + shift_left_256_file.open ("SHIFT_LEFT_256.txt"); + +if (division_enabled==1){ + std::ofstream quot_128_file; + quot_128_file.open ("QUOT_128.txt"); +} + + + boost::multiprecision::uint128_t hi_64{"0xffffffffffffffff0000000000000000"}; + boost::multiprecision::uint128_t lo_64{"0x0000000000000000ffffffffffffffff"}; + boost::multiprecision::uint128_t max_128{"0xffffffffffffffffffffffffffffffff"}; + boost::multiprecision::uint128_t two_64{"0x000000000000000010000000000000000"}; + + boost::multiprecision::uint256_t boost_two_64{"0x00000000000000000000000000000000010000000000000000"}; + boost::multiprecision::uint256_t boost_two_128{"0x0000000000000000100000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_two_192{"0x1000000000000000000000000000000000000000000000000"}; + + boost::multiprecision::uint512_t boost_two_64_for_512_calc{"0x00000000000000000000000000000000010000000000000000"}; + boost::multiprecision::uint512_t boost_two_128_for_512_calc{"0x0000000000000000100000000000000000000000000000000"}; + boost::multiprecision::uint512_t boost_two_192_for_512_calc{"0x1000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint512_t boost_two_256_for_512_calc{"0x000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"}; + + boost::multiprecision::uint512_t boost_two_320_for_512_calc{"0x100000000000000000000000000000000000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint512_t boost_two_384_for_512_calc{"0x1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint512_t boost_two_448_for_512_calc{"0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}; + + boost::multiprecision::uint128_t boost_two_64_for_128_calc{"0x000000000000000010000000000000000"}; + + + + + boost::multiprecision::uint256_t boost_test_256_one{"0x0000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_test_256_two{"0x0000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_test_256_sum{"0x0000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_test_256_sub{"0x0000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_test_256_prod{"0x0000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_test_512_prod_hi_prod{"0x0000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_test_512_prod_lo_prod{"0x0000000000000000000000000000000000000000000000000"}; + + + boost::multiprecision::uint512_t boost_test_2_256_quotient{"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint512_t boost_test_2_256_remainder{"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint512_t boost_test_512_prod{"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}; + + boost::multiprecision::uint128_t boost_test_128_one{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_test_128_two{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_test_128_sub{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_test_256_one_lo{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_test_256_one_hi{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_test_256_two_lo{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_test_256_two_hi{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_dap_64_128_comparison{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_test_shift_left_128{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_test_shift_left_128_quotient_limb{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_test_shift_left_128_remainder_limb{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_dap_comparison_shift_left_128{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_test_64_128_prod{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_dap_128_prod_comparison{"0x000000000000000000000000000000000"}; + boost::multiprecision::uint128_t boost_dap_128_comparison_sub{"0x000000000000000000000000000000000"}; + + boost::multiprecision::uint256_t boost_dap_256_comparison{"0x0000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_dap_256_comparison_sub{"0x0000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_dap_256_comparison_prod{"0x0000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_test_shift_left_256{"0x0000000000000000000000000000000000000000000000000"}; + boost::multiprecision::uint256_t boost_dap_comparison_shift_left_256{"0x0000000000000000000000000000000000000000000000000"}; + + boost::multiprecision::uint512_t boost_dap_512_comparison_prod{"0x0"}; + + + + + int error_counter_sum=0; + int error_counter_prod=0; + int error_counter_sub_128=0; + int error_counter_sub_256=0; + int error_counter_prod_128_128=0; + int error_counter_prod_128_256=0; + int error_counter_prod_256_256=0; + int error_counter_prod_256_512=0; + int error_counter_shift_left_128=0; + int error_counter_shift_left_256=0; + int error_counter_quot_128=0; + + + + for (density_index = 0; density_index<density_constant; density_index+=1){ + + + /////////////////////output of 256+256-->256////////////////////// + + if (testing_mode==FULL){ + i=density_index; + j=2*density_index; + k=3*density_index; + l=4*density_index; + } + if (testing_mode==BASIC){ + i=density_index; + j=density_index; + k=density_index; + l=density_index; + } + + if (testing_mode==SQUARE){ + i=density_index; + j=density_index; + k=density_index; + l=density_index; + } + + + dap_test_256_one.lo.lo=i; + dap_test_256_one.lo.hi=j; + dap_test_256_one.hi.lo=k; + dap_test_256_one.hi.hi=l; + + + boost::multiprecision::uint256_t boost_test_256_one_coeff_2_0=i; + boost::multiprecision::uint256_t boost_test_256_one_coeff_2_64=j; + boost::multiprecision::uint256_t boost_test_256_one_coeff_2_128=k; + boost::multiprecision::uint256_t boost_test_256_one_coeff_2_192=l; + + + + boost_test_256_one=boost_test_256_one_coeff_2_0 + boost_test_256_one_coeff_2_64*boost_two_64 + +boost_test_256_one_coeff_2_128*boost_two_128+boost_test_256_one_coeff_2_192*boost_two_192; + +// boost_test_256_one_hi=boost_test_256_one_coeff_2_128+boost_two_64*boost_test_256_one_coeff_2_192; +// boost_test_256_one_lo=boost_test_256_one_coeff_2_0+boost_test_256_one_coeff_2_64*boost_two_64; + + if(testing_mode==FULL){ + i=max_64-(density_index+1); + j=max_64-2*(density_index+1); + k=max_64-3*(density_index+1); + l=max_64-4*(density_index+1); + } + + if (testing_mode==BASIC){ + i=density_index+1; + j=density_index+1; + k=density_index+1; + l=density_index+1; + } + + if (testing_mode==SQUARE){ + i=density_index; + j=density_index; + k=density_index; + l=density_index; + } + + + dap_test_256_two.lo.lo=i; + dap_test_256_two.lo.hi=j; + dap_test_256_two.hi.lo=k; + dap_test_256_two.hi.hi=l; + + + boost::multiprecision::uint256_t boost_test_256_two_coeff_2_0=i; + boost::multiprecision::uint256_t boost_test_256_two_coeff_2_64=j; + boost::multiprecision::uint256_t boost_test_256_two_coeff_2_128=k; + boost::multiprecision::uint256_t boost_test_256_two_coeff_2_192=l; + + + boost_test_256_two=boost_test_256_two_coeff_2_0 + boost_test_256_two_coeff_2_64*boost_two_64 + +boost_test_256_two_coeff_2_128*boost_two_128+boost_test_256_two_coeff_2_192*boost_two_192; + +// boost_test_256_two_hi=boost_test_256_two_coeff_2_128+boost_two_64*boost_test_256_two_coeff_2_192; +// boost_test_256_two_lo=boost_test_256_one_coeff_2_0+boost_test_256_two_coeff_2_64*boost_two_64; + +// add(boost_add_256, i, j); + + overflow_flag=SUM_256_256(dap_test_256_one,dap_test_256_two,&dap_test_256_sum); + add(boost_test_256_sum,boost_test_256_one,boost_test_256_two); + + boost_dap_256_comparison=dap_test_256_sum.lo.lo+dap_test_256_sum.lo.hi*boost_two_64+ + dap_test_256_sum.hi.lo*boost_two_128+dap_test_256_sum.hi.hi*boost_two_192; + + if(boost_dap_256_comparison!=boost_test_256_sum){ + error_counter_sum+=1; + sum_256_256_file << "incorrect output for density index=" << std::endl; + sum_256_256_file << density_index << std::endl;} + + + ///256 bit subtraction + + borrow_flag_256=SUBTRACT_256_256(dap_test_256_two,dap_test_256_one,&dap_test_256_sub); + subtract(boost_test_256_sub,boost_test_256_two,boost_test_256_one); + + boost_dap_256_comparison_sub=dap_test_256_sub.lo.lo+dap_test_256_sub.lo.hi*boost_two_64+ + dap_test_256_sub.hi.lo*boost_two_128+dap_test_256_sub.hi.hi*boost_two_192; + + if(boost_dap_256_comparison_sub!=boost_test_256_sub){ + error_counter_sub_256+=1; + sub_256_256_file << "incorrect output for density index=" << std::endl; + sub_256_256_file << density_index << std::endl;} + + + + + + /////////////////////output of 256*256-->256////////////////////// + + overflow_flag_prod=MULT_256_256(dap_test_256_one,dap_test_256_two,&dap_test_256_prod); + multiply(boost_test_256_prod,boost_test_256_one,boost_test_256_two); + multiply(boost_test_512_prod,boost_test_256_one,boost_test_256_two); +// multiply(boost_test_512_prod_hi_prod,boost_test_256_one_hi,boost_test_256_two_hi); +// multiply(boost_test_512_prod_lo_prod,boost_test_256_one_lo,boost_test_256_two_lo); + divide_qr(boost_test_512_prod,boost_two_256_for_512_calc,boost_test_2_256_quotient,boost_test_2_256_remainder); + + boost_dap_256_comparison_prod=dap_test_256_prod.lo.lo+dap_test_256_prod.lo.hi*boost_two_64+ + dap_test_256_prod.hi.lo*boost_two_128+dap_test_256_prod.hi.hi*boost_two_192; + + if(boost_dap_256_comparison_prod!=boost_test_256_prod){ + error_counter_prod_256_256+=1; + prod_256_256_file << "incorrect product output for density index=" << std::endl; + prod_256_256_file << density_index << std::endl;} + + /////////////////////output of 256*256-->512////////////////////// + dap_test_512_prod.lo=zero_256; + dap_test_512_prod.hi=zero_256; + uint256_t intermed_lo_prod; + uint256_t intermed_hi_prod; + MULT_128_256(dap_test_256_one.lo,dap_test_256_two.lo,&intermed_lo_prod); + MULT_128_256(dap_test_256_one.hi,dap_test_256_two.hi,&intermed_hi_prod); + + MULT_256_512(dap_test_256_one,dap_test_256_two,&dap_test_512_prod); + + + boost_dap_512_comparison_prod=dap_test_512_prod.lo.lo.lo+ + dap_test_512_prod.lo.lo.hi*boost_two_64_for_512_calc+ + dap_test_512_prod.lo.hi.lo*boost_two_128_for_512_calc+ + dap_test_512_prod.lo.hi.hi*boost_two_192_for_512_calc+ + dap_test_512_prod.hi.lo.lo*boost_two_256_for_512_calc+ + dap_test_512_prod.hi.lo.hi*boost_two_320_for_512_calc+ + dap_test_512_prod.hi.hi.lo*boost_two_384_for_512_calc+ + dap_test_512_prod.hi.hi.hi*boost_two_448_for_512_calc; + + if(boost_dap_512_comparison_prod!=boost_test_512_prod){ + error_counter_prod_256_512+=1; + prod_256_512_file << "incorrect product output for density index=" << std::endl; + prod_256_512_file << density_index << std::endl;} + + /////////////////////output of shift left 128///////////////////// + + if (density_index<=127){ + dap_test_128_one=dap_test_256_one.lo; + LEFT_SHIFT_128(dap_test_128_one,&dap_test_128_shift,density_index); + + boost_test_128_one=dap_test_128_one.lo+dap_test_128_one.hi*boost_two_64_for_128_calc; + boost_test_shift_left_128=boost_test_128_one<<density_index; + boost_dap_comparison_shift_left_128=dap_test_128_shift.lo+dap_test_128_shift.hi*boost_two_64_for_128_calc; + + divide_qr(boost_test_shift_left_128,boost_two_64_for_128_calc,boost_test_shift_left_128_quotient_limb,boost_test_shift_left_128_remainder_limb); + + if(boost_dap_comparison_shift_left_128!=boost_test_shift_left_128){ + error_counter_shift_left_128+=1; + shift_left_128_file << "incorrect shift left 128 output for density index=" << std::endl; + shift_left_128_file << density_index << std::endl;} + } + /////////////////////output of shift left 256///////////////////// + + if (density_index<=255){ + LEFT_SHIFT_256(dap_test_256_one,&dap_test_256_shift,density_index); + + boost_test_256_one=boost_test_256_one_coeff_2_0 + boost_test_256_one_coeff_2_64*boost_two_64 + +boost_test_256_one_coeff_2_128*boost_two_128+boost_test_256_one_coeff_2_192*boost_two_192; + boost_test_shift_left_256=boost_test_256_one<<density_index; + boost_dap_comparison_shift_left_256=dap_test_256_shift.lo.lo+dap_test_256_shift.lo.hi*boost_two_64+ + dap_test_256_shift.hi.lo*boost_two_128+dap_test_256_shift.hi.hi*boost_two_192; + + + if(boost_dap_comparison_shift_left_256!=boost_test_shift_left_256){ + error_counter_shift_left_256+=1; + shift_left_256_file << "incorrect shift left 256 output for density index=" << std::endl; + shift_left_256_file << density_index << std::endl;} + } + + /////////////////////output of 64*64-->128//////////////////////// + + + i=density_index; + j=max_64-(density_index+1); + uint128_t dap_test_64_128_prod; + dap_test_64_128_prod.lo=0; + dap_test_64_128_prod.hi=0; + + + + multiply(boost_test_64_128_prod, i, j); + MULT_64_128(i,j,&dap_test_64_128_prod); + boost_dap_128_prod_comparison=dap_test_64_128_prod.lo+dap_test_64_128_prod.hi*two_64; + + if(boost_dap_128_prod_comparison!=boost_test_64_128_prod){ + error_counter_prod+=1;} + + /////////////////////output of 128*128-->128//////////////////////// + + uint128_t dap_test_128_128_prod_one; + uint128_t dap_test_128_128_prod_two; + uint128_t dap_test_128_128_prod_prod; + dap_test_128_128_prod_one.lo=i; + dap_test_128_128_prod_one.hi=j; + dap_test_128_128_prod_two.lo=max_64-(i+1); + dap_test_128_128_prod_two.hi=max_64-2*(j+1); + dap_test_128_128_prod_prod.lo=0; + dap_test_128_128_prod_prod.hi=0; + + boost::multiprecision::uint128_t boost_test_128_128_prod; + boost::multiprecision::uint128_t boost_test_128_128_one; + boost::multiprecision::uint128_t boost_test_128_128_two; + boost::multiprecision::uint128_t boost_dap_128_128_prod_comparison; + + ////compute boost "factors" + boost_test_128_128_one=i+j*boost_two_64_for_128_calc; + boost_test_128_128_two=max_64-(i+1)+(max_64-2*(j+1))*boost_two_64_for_128_calc; + + + multiply(boost_test_128_128_prod, boost_test_128_128_one, boost_test_128_128_two); + MULT_128_128(dap_test_128_128_prod_one,dap_test_128_128_prod_two,&dap_test_128_128_prod_prod); + boost_dap_128_128_prod_comparison=dap_test_128_128_prod_prod.lo+dap_test_128_128_prod_prod.hi*boost_two_64_for_128_calc; + + if(boost_dap_128_128_prod_comparison!=boost_test_128_128_prod){ + error_counter_prod_128_128+=1;} + + + ///128 bit subtraction + + borrow_flag_128=SUBTRACT_128_128(dap_test_128_one,dap_test_128_two,&dap_test_128_sub); + subtract(boost_test_128_sub,boost_test_128_one,boost_test_128_two); + + boost_dap_128_comparison_sub=dap_test_128_sub.lo+dap_test_128_sub.hi*boost_two_64_for_128_calc; + + + if(boost_dap_128_comparison_sub!=boost_test_128_sub){ + error_counter_sub_128+=1; + sub_128_128_file << "incorrect output for density index=" << std::endl; + sub_128_128_file << density_index << std::endl;} + + + + + + /////////////////////output of 128*128-->256//////////////////////// + + + uint128_t dap_test_128_256_prod_one; + uint128_t dap_test_128_256_prod_two; + uint256_t dap_test_128_256_prod_prod; + dap_test_128_256_prod_one.lo=i; + dap_test_128_256_prod_one.hi=j; + dap_test_128_256_prod_two.lo=max_64-(i+1); + dap_test_128_256_prod_two.hi=max_64-2*(j+1); + dap_test_128_256_prod_prod.lo=zero_128; + dap_test_128_256_prod_prod.hi=zero_128; + + boost::multiprecision::uint256_t boost_test_128_256_prod; + boost::multiprecision::uint128_t boost_test_128_256_one; + boost::multiprecision::uint128_t boost_test_128_256_two; + boost::multiprecision::uint256_t boost_dap_128_256_prod_comparison; + + ////compute boost "factors" + boost_test_128_256_one=i+j*boost_two_64_for_128_calc; + boost_test_128_256_two=(max_64-(i+1))+(max_64-2*(j+1))*boost_two_64_for_128_calc; + + multiply(boost_test_128_256_prod, boost_test_128_256_one, boost_test_128_256_two); + MULT_128_256(dap_test_128_256_prod_one,dap_test_128_256_prod_two,&dap_test_128_256_prod_prod); + boost_dap_128_256_prod_comparison=dap_test_128_256_prod_prod.lo.lo+ + dap_test_128_256_prod_prod.lo.hi*boost_two_64+ + dap_test_128_256_prod_prod.hi.lo*boost_two_128+ + dap_test_128_256_prod_prod.hi.hi*boost_two_192; + + + + if(boost_dap_128_256_prod_comparison!=boost_test_128_256_prod){ + + error_counter_prod_128_256+=1; + + std::cout << ("boost_dap_128_256_prod_comparison")<< std::endl; + std::cout << (boost_dap_128_256_prod_comparison)<< std::endl; + std::cout << ("boost_test_128_256_prod")<< std::endl; + std::cout << (boost_test_128_256_prod)<< std::endl;} + + + /////////////////////output of 128/128-->128//////////////////////// +if(division_enabled==1){ + + i=density_index+1; + j=density_index+2; + uint128_t dap_test_128_quot_one; + uint128_t dap_test_128_quot_two; + uint128_t dap_test_128_quot_quot; + uint128_t dap_test_128_quot_rem; + dap_test_128_quot_one.lo=i; + dap_test_128_quot_one.hi=j; + dap_test_128_quot_two.lo=max_64-(i+1); + dap_test_128_quot_two.hi=max_64-2*(j+1); + dap_test_128_quot_quot.lo=0; + dap_test_128_quot_quot.hi=0; + dap_test_128_quot_rem.lo=0; + dap_test_128_quot_rem.hi=0; + + boost::multiprecision::uint128_t boost_test_128_quot_one; + boost::multiprecision::uint128_t boost_test_128_quot_two; + boost::multiprecision::uint128_t boost_test_128_quot_quot; + boost::multiprecision::uint128_t boost_test_128_quot_rem; + boost::multiprecision::uint128_t boost_dap_128_quot_comparison_quot; + boost::multiprecision::uint128_t boost_dap_128_quot_comparison_rem; + + ////compute boost "factors" + boost_test_128_quot_one=i+j*boost_two_64_for_128_calc; + boost_test_128_quot_two=(max_64-(i+1))+(max_64-2*(j+1))*boost_two_64_for_128_calc; + + divide_qr( boost_test_128_quot_two, boost_test_128_quot_one,boost_test_128_quot_quot,boost_test_128_quot_rem); + bindivmod128(dap_test_128_quot_one,dap_test_128_quot_two,&dap_test_128_quot_quot,&dap_test_128_quot_rem); + + + boost_dap_128_quot_comparison_quot=dap_test_128_quot_quot.lo+ + dap_test_128_quot_quot.hi*boost_two_64_for_128_calc; + + boost_dap_128_quot_comparison_rem=dap_test_128_quot_rem.lo+ + dap_test_128_quot_rem.hi*boost_two_64_for_128_calc; + + + if((boost_dap_128_quot_comparison_quot!=boost_test_128_quot_quot)||(boost_dap_128_quot_comparison_rem!=boost_test_128_quot_rem)){ + + error_counter_quot_128+=1; + + std::cout << ("boost_dap_128_quot_comparison_quot")<< std::endl; + std::cout << (boost_dap_128_quot_comparison_quot)<< std::endl; + std::cout << ("boost_dap_128_quot_comparison_rem")<< std::endl; + std::cout << (boost_dap_128_quot_comparison_rem)<< std::endl;} + +} + + + /////////////////////print to file section//////////////////////// + + + if(verbose_output==1){ + + if(boost_dap_256_comparison!=boost_test_256_sum){ + + sum_256_256_file << "dap_test_256_one"<< std::endl; + + sum_256_256_file << (dap_test_256_one.lo.lo)<< std::endl; + sum_256_256_file << (dap_test_256_one.lo.hi)<< std::endl; + sum_256_256_file << (dap_test_256_one.hi.lo)<< std::endl; + sum_256_256_file << (dap_test_256_one.hi.hi)<< std::endl; + + + sum_256_256_file << "dap_test_256_two"<< std::endl; + + sum_256_256_file << (dap_test_256_two.lo.lo)<< std::endl; + sum_256_256_file << (dap_test_256_two.lo.hi)<< std::endl; + sum_256_256_file << (dap_test_256_two.hi.lo)<< std::endl; + sum_256_256_file << (dap_test_256_two.hi.hi)<< std::endl; + + sum_256_256_file << "dap_test_256_sum"<< std::endl; + + sum_256_256_file << (dap_test_256_sum.lo.lo)<< std::endl; + sum_256_256_file << (dap_test_256_sum.lo.hi)<< std::endl; + sum_256_256_file << (dap_test_256_sum.hi.lo)<< std::endl; + sum_256_256_file << (dap_test_256_sum.hi.hi)<< std::endl; + + sum_256_256_file << "boost_test_256_one"<< std::endl; + + sum_256_256_file << (boost_test_256_one)<< std::endl; + + sum_256_256_file << "boost_test_256_one factor 0"<< std::endl; + + sum_256_256_file << (boost_test_256_one_coeff_2_0)<< std::endl; + + sum_256_256_file << "boost_test_256_one factor 1"<< std::endl; + + sum_256_256_file << (boost_test_256_one_coeff_2_64*boost_two_64)<< std::endl; + + sum_256_256_file << "boost_test_256_one factor 2"<< std::endl; + + sum_256_256_file << (boost_test_256_one_coeff_2_128*boost_two_128)<< std::endl; + + + sum_256_256_file << "boost_test_256_one factor 3"<< std::endl; + + sum_256_256_file << (boost_test_256_one_coeff_2_192*boost_two_192)<< std::endl; + + + + sum_256_256_file << "boost_test_256_two"<< std::endl; + + sum_256_256_file << (boost_test_256_two)<< std::endl; + + + sum_256_256_file << "boost sum is"<< std::endl; + + + sum_256_256_file << (boost_test_256_sum)<< std::endl; + + sum_256_256_file << "boost comparison is"<< std::endl; + + + sum_256_256_file << (boost_dap_256_comparison)<< std::endl;} + + + if(boost_dap_256_comparison_prod!=boost_test_256_prod){ + + prod_256_256_file << "dap_test_256_one"<< std::endl; + + prod_256_256_file << (dap_test_256_one.lo.lo)<< std::endl; + prod_256_256_file << (dap_test_256_one.lo.hi)<< std::endl; + prod_256_256_file << (dap_test_256_one.hi.lo)<< std::endl; + prod_256_256_file << (dap_test_256_one.hi.hi)<< std::endl; + + + prod_256_256_file << "dap_test_256_two"<< std::endl; + + prod_256_256_file << (dap_test_256_two.lo.lo)<< std::endl; + prod_256_256_file << (dap_test_256_two.lo.hi)<< std::endl; + prod_256_256_file << (dap_test_256_two.hi.lo)<< std::endl; + prod_256_256_file << (dap_test_256_two.hi.hi)<< std::endl; + + prod_256_256_file << "dap_test_256_prod"<< std::endl; + + prod_256_256_file << (dap_test_256_prod.lo.lo)<< std::endl; + prod_256_256_file << (dap_test_256_prod.lo.hi)<< std::endl; + prod_256_256_file << (dap_test_256_prod.hi.lo)<< std::endl; + prod_256_256_file << (dap_test_256_prod.hi.hi)<< std::endl; + + prod_256_256_file << "boost_test_256_one"<< std::endl; + + prod_256_256_file << (boost_test_256_one)<< std::endl; + + prod_256_256_file << "boost_test_256_one factor 0"<< std::endl; + + prod_256_256_file << (boost_test_256_one_coeff_2_0)<< std::endl; + + prod_256_256_file << "boost_test_256_one factor 1"<< std::endl; + + prod_256_256_file << (boost_test_256_one_coeff_2_64*boost_two_64)<< std::endl; + + prod_256_256_file << "boost_test_256_one factor 2"<< std::endl; + + prod_256_256_file << (boost_test_256_one_coeff_2_128*boost_two_128)<< std::endl; + + + prod_256_256_file << "boost_test_256_one factor 3"<< std::endl; + + prod_256_256_file << (boost_test_256_one_coeff_2_192*boost_two_192)<< std::endl; + + + + prod_256_256_file << "boost_test_256_two"<< std::endl; + + prod_256_256_file << (boost_test_256_two)<< std::endl; + + + + prod_256_256_file << "boost_test_256_two factor 0"<< std::endl; + + prod_256_256_file << (boost_test_256_two_coeff_2_0)<< std::endl; + + prod_256_256_file << "boost_test_256_two factor 1"<< std::endl; + + prod_256_256_file << (boost_test_256_two_coeff_2_64*boost_two_64)<< std::endl; + + prod_256_256_file << "boost_test_256_two factor 2"<< std::endl; + + prod_256_256_file << (boost_test_256_two_coeff_2_128*boost_two_128)<< std::endl; + + prod_256_256_file << "boost_test_256_two factor 3"<< std::endl; + + prod_256_256_file << (boost_test_256_two_coeff_2_192*boost_two_192)<< std::endl; + + + prod_256_256_file << "boost 256 prod is"<< std::endl; + + + prod_256_256_file << (boost_test_256_prod)<< std::endl; + + + prod_256_256_file << "boost 512 prod is"<< std::endl; + + + prod_256_256_file << (boost_test_512_prod)<< std::endl; + + + prod_256_256_file << "boost 2**256 quotient is"<< std::endl; + + + prod_256_256_file << (boost_test_2_256_quotient)<< std::endl; + + prod_256_256_file << "boost 2**256 remainder is"<< std::endl; + + + prod_256_256_file << (boost_test_2_256_remainder)<< std::endl; + + prod_256_256_file << "boost comparison is"<< std::endl; + + prod_256_256_file << (boost_dap_256_comparison_prod)<< std::endl;} + + if(boost_dap_512_comparison_prod!=boost_test_512_prod){ + + + prod_256_512_file << "dap_test_512_prod"<< std::endl; + + prod_256_512_file << (dap_test_512_prod.lo.lo.lo)<< std::endl; + prod_256_512_file << (dap_test_512_prod.lo.lo.hi)<< std::endl; + prod_256_512_file << (dap_test_512_prod.lo.hi.lo)<< std::endl; + prod_256_512_file << (dap_test_512_prod.lo.hi.hi)<< std::endl; + prod_256_512_file << (dap_test_512_prod.hi.lo.lo)<< std::endl; + prod_256_512_file << (dap_test_512_prod.hi.lo.hi)<< std::endl; + prod_256_512_file << (dap_test_512_prod.hi.hi.lo)<< std::endl; + prod_256_512_file << (dap_test_512_prod.hi.hi.hi)<< std::endl; + + + prod_256_512_file << "boost 512 prod is"<< std::endl; + + prod_256_512_file << (boost_test_512_prod)<< std::endl; + + prod_256_512_file << "boost comparison is"<< std::endl; + + prod_256_512_file << (boost_dap_512_comparison_prod)<< std::endl;} + + + if(boost_test_64_128_prod!=boost_dap_128_prod_comparison){ + + prod_64_128_file << " i is "<< std::endl; + + prod_64_128_file << (i)<< std::endl; + + prod_64_128_file << " j is "<< std::endl; + + prod_64_128_file << (j)<< std::endl; + + prod_64_128_file << "boost_dap_128_prod_comparison"<< std::endl; + + prod_64_128_file << (boost_dap_128_prod_comparison)<< std::endl; + + prod_64_128_file << "boost_test_64_128_prod"<< std::endl; + + prod_64_128_file << (boost_test_64_128_prod)<< std::endl; + + prod_64_128_file << "difference"<< std::endl; + + prod_64_128_file << (boost_dap_128_prod_comparison-boost_test_64_128_prod)<< std::endl; + +} + + + if(boost_test_128_128_prod!=boost_dap_128_128_prod_comparison){ + + prod_128_128_file << " i is "<< std::endl; + + prod_128_128_file << (i)<< std::endl; + + prod_128_128_file << " j is "<< std::endl; + + prod_128_128_file << (j)<< std::endl; + + prod_128_128_file << " boost_test_128_128_one is "<< std::endl; + + prod_128_128_file << (boost_test_128_128_one)<< std::endl; + + prod_128_128_file << " boost_test_128_128_two is "<< std::endl; + + prod_128_128_file << (boost_test_128_128_two)<< std::endl; + + prod_128_128_file << "boost_dap_128_128_prod_comparison"<< std::endl; + + prod_128_128_file << (boost_dap_128_128_prod_comparison)<< std::endl; + + prod_128_128_file << "dap_test_128_128_prod_prod.lo"<< std::endl; + + prod_128_128_file << (dap_test_128_128_prod_prod.lo)<< std::endl; + + prod_128_128_file << "dap_test_128_128_prod_prod.hi"<< std::endl; + + prod_128_128_file << (dap_test_128_128_prod_prod.hi)<< std::endl; + + + prod_128_128_file << "boost_test_128_128_prod"<< std::endl; + + prod_128_128_file << (boost_test_128_128_prod)<< std::endl;} + + + +if (density_index<=127){ + if(boost_dap_comparison_shift_left_128!=boost_test_shift_left_128){ + shift_left_128_file << " density_index is "<< std::endl; + + shift_left_128_file << (density_index)<< std::endl; + + shift_left_128_file << " dap_test_128_one is "<< std::endl; + + shift_left_128_file << (dap_test_128_one.lo)<< std::endl; + shift_left_128_file << (dap_test_128_one.hi)<< std::endl; + + shift_left_128_file << " dap_test_128_shift is "<< std::endl; + + shift_left_128_file << (dap_test_128_shift.lo)<< std::endl; + shift_left_128_file << (dap_test_128_shift.hi)<< std::endl; + + shift_left_128_file << " boost_test_shift_left_128 .lo is "<< std::endl; + shift_left_128_file << boost_test_shift_left_128_remainder_limb<< std::endl; + + shift_left_128_file << " boost_test_shift_left_128 .hi is "<< std::endl; + shift_left_128_file << boost_test_shift_left_128_quotient_limb<< std::endl; + + + } + } + + + if (density_index<=255){ + if(boost_dap_comparison_shift_left_256!=boost_test_shift_left_256){ + + + shift_left_256_file << " density_index is "<< std::endl; + + shift_left_256_file << (density_index)<< std::endl; + + shift_left_256_file << " dap_test_256_one is "<< std::endl; + + shift_left_256_file << (dap_test_256_one.lo.lo)<< std::endl; + shift_left_256_file << (dap_test_256_one.lo.hi)<< std::endl; + shift_left_256_file << (dap_test_256_one.hi.lo)<< std::endl; + shift_left_256_file << (dap_test_256_one.hi.hi)<< std::endl; + + + shift_left_256_file << " dap_test_256_shift is "<< std::endl; + + shift_left_256_file << (dap_test_256_shift.lo.lo)<< std::endl; + shift_left_256_file << (dap_test_256_shift.lo.hi)<< std::endl; + shift_left_256_file << (dap_test_256_shift.hi.lo)<< std::endl; + shift_left_256_file << (dap_test_256_shift.hi.hi)<< std::endl;} + } + } + + overflow_flag=0; + + } + + sum_256_256_file.close(); + + if(error_counter_sum==0){ + + std::cout<< "SUM_256_256 returns identical results to boost:: 256 bit addition"<< std::endl;} + + prod_64_128_file.close(); + + if(error_counter_sub_128==0){ + + std::cout<< "SUB_128_128 returns identical results to boost:: 128 bit subtraction"<< std::endl;} + + sub_128_128_file.close(); + + if(error_counter_sub_256==0){ + + std::cout<< "SUB_256_256 returns identical results to boost:: 256 bit subtraction"<< std::endl;} + + sub_256_256_file.close(); + + + if(error_counter_prod==0){ + + std::cout<< "PROD_64_128 returns identical results to boost:: multiplication"<< std::endl;} + + prod_128_128_file.close(); + + if(error_counter_prod_128_128==0){ + + std::cout<< "PROD_128_128 returns identical results to boost:: 128 bit multiplication"<< std::endl;} + + if(error_counter_prod_128_256==0){ + + std::cout<< "PROD_128_256 returns identical results to boost:: 128 bit multiplication"<< std::endl;} + + if(error_counter_prod_256_256==0){ + + std::cout<< "PROD_256_256 returns identical results to boost:: 256 bit multiplication"<< std::endl;} + + if(error_counter_prod_256_512==0){ + + std::cout<< "PROD_256_512 returns identical results to boost:: 256 bit multiplication"<< std::endl;} + + + + if(error_counter_shift_left_128==0){ + + std::cout<< "SHIFT_LEFT_128 returns identical results to boost:: 128 bit <<"<< std::endl;} + + + if(error_counter_shift_left_256==0){ + + std::cout<< "SHIFT_LEFT_256 returns identical results to boost:: 256 bit <<"<< std::endl;} + +if (division_enabled==1){ + + if(error_counter_quot_128==0){ + + std::cout<< "QUOT_128 returns identical results to boost:: 128 bit division"<< std::endl;} + +} + return 0; +} + +