8787#include < algorithm>
8888#include " mp.h"
8989#include " memrev.h"
90+ #include " endianness.h"
91+
92+ #ifdef __BIG_ENDIAN__
93+ #define HALFWORD_0 1
94+ #define HALFWORD_1 0
95+ #else
96+ #define HALFWORD_0 0
97+ #define HALFWORD_1 1
98+ #endif
99+
100+ static inline uint16_t Get_HalfWord (const uint16_t * base, size_t offset)
101+ {
102+ #ifdef __BIG_ENDIAN__
103+ return base[offset ^ 1 ];
104+ #else
105+ return base[offset];
106+ #endif
107+ }
108+
109+ static inline void Set_HalfWord (uint16_t * base, size_t offset, uint16_t value)
110+ {
111+ #ifdef __BIG_ENDIAN__
112+ base[offset ^ 1 ] = value;
113+ #else
114+ base[offset] = value;
115+ #endif
116+ }
90117
91118/* **********************************************************************************************
92119 * _Byte_Precision -- Determines the number of bytes significant in long integer. *
@@ -306,11 +333,27 @@ unsigned XMP_Encode(unsigned char* to, unsigned tobytes, digit const* from, int
306333// #pragma warning 364 9
307334unsigned XMP_Encode (unsigned char * to, digit const * from, int precision)
308335{
336+ int i;
337+ #ifdef __BIG_ENDIAN__
338+ digit from_copy[precision];
339+ #endif
340+
309341 assert (to != NULL );
310342 assert (from != NULL );
311343 assert (precision > 0 );
312344
313345 bool is_negative = XMP_Is_Negative (from, precision);
346+
347+ #ifdef __BIG_ENDIAN__
348+ if (sizeof (digit) == 4 ) {
349+ for (i = 0 ; i < precision; i++) {
350+ from_copy[i] = le32toh (from[i]);
351+ }
352+ }
353+
354+ from = from_copy;
355+ #endif
356+
314357 unsigned char filler = (unsigned char )(is_negative ? 0xff : 0 );
315358 unsigned char * number_ptr;
316359
@@ -381,6 +424,12 @@ void XMP_Signed_Decode(digit* result, const unsigned char* from, int frombytes,
381424 for (index = 0 ; index < frombytes; index++) {
382425 *--dest = *from++;
383426 }
427+
428+ if (sizeof (digit) == 4 ) {
429+ for (index = 0 ; index < precision; index++) {
430+ result[index] = le32toh (result[index]);
431+ }
432+ }
384433}
385434
386435/* **********************************************************************************************
@@ -1068,18 +1117,58 @@ bool XMP_Add_Int(digit* result, const digit* left_number, digit right_number, bo
10681117 * HISTORY: *
10691118 * 07/01/1996 JLB : Created. *
10701119 *=============================================================================================*/
1120+ bool XMP_Sub (uint16_t * result,
1121+ size_t result_offset,
1122+ const uint16_t * left_number,
1123+ size_t left_number_offset,
1124+ const digit* right_number,
1125+ bool borrow,
1126+ int precision)
1127+ {
1128+ bool ret;
1129+
1130+ #ifdef __BIG_ENDIAN__
1131+ uint16_t temp_left_number[precision * 2 ];
1132+ uint16_t temp_result[precision * 2 ];
1133+ size_t i;
1134+
1135+ for (i = 0 ; i < precision * 2 ; i++) {
1136+ Set_HalfWord (temp_left_number, i, Get_HalfWord (left_number, left_number_offset + i));
1137+ }
1138+
1139+ ret = XMP_Sub ((digit*)temp_result, (const digit*)temp_left_number, right_number, borrow, precision);
1140+
1141+ for (i = 0 ; i < precision * 2 ; i++) {
1142+ Set_HalfWord (result, result_offset + i, Get_HalfWord (temp_result, i));
1143+ }
1144+ #else
1145+ ret = XMP_Sub ((digit*)(result + result_offset),
1146+ (const digit*)(left_number + left_number_offset),
1147+ right_number,
1148+ borrow,
1149+ precision);
1150+ #endif
1151+
1152+ return ret;
1153+ }
1154+
10711155bool XMP_Sub (digit* result, const digit* left_number, const digit* right_number, bool borrow, int precision)
10721156{
10731157 const uint16_t * left_number_ptr = (const uint16_t *)left_number;
1158+ size_t left_number_offset = 0 ;
10741159 const uint16_t * right_number_ptr = (const uint16_t *)right_number;
1160+ size_t right_number_offset = 0 ;
10751161 uint16_t * result_ptr = (uint16_t *)result;
1162+ size_t result_offset = 0 ;
10761163
10771164 precision *= 2 ;
10781165 while (precision--) {
1079- digit x = (digit)*left_number_ptr - (digit)*right_number_ptr - (digit)borrow;
1080- right_number_ptr++;
1081- left_number_ptr++;
1082- *result_ptr++ = (uint16_t )x;
1166+ digit x = (digit)Get_HalfWord (left_number_ptr, left_number_offset)
1167+ - (digit)Get_HalfWord (right_number_ptr, right_number_offset) - (digit)borrow;
1168+ right_number_offset++;
1169+ left_number_offset++;
1170+ Set_HalfWord (result_ptr, result_offset, x);
1171+ result_offset++;
10831172 borrow = (((1L << 16 ) & x) != 0L );
10841173 }
10851174 return (borrow);
@@ -1748,18 +1837,23 @@ void XMP_Decode_ASCII(char const* str, digit* mpn, int precision)
17481837 * HISTORY: *
17491838 * 07/02/1996 JLB : Created. *
17501839 *=============================================================================================*/
1751- void XMP_Hybrid_Mul (uint16_t * prod, uint16_t * multiplicand, uint16_t multiplier, int precision)
1840+ void XMP_Hybrid_Mul (uint16_t * prod,
1841+ size_t prod_offset,
1842+ uint16_t * multiplicand,
1843+ size_t multiplicand_offset,
1844+ uint16_t multiplier,
1845+ int precision)
17521846{
17531847 uint32_t carry = 0 ;
17541848 for (int i = 0 ; i < precision; ++i) {
1755- uint32_t p = (uint32_t )multiplier * * multiplicand++ ;
1756- p += * prod + carry;
1757- * prod++ = (uint16_t )p;
1849+ uint32_t p = (uint32_t )multiplier * Get_HalfWord ( multiplicand, multiplicand_offset++) ;
1850+ p += Get_HalfWord ( prod, prod_offset) + carry;
1851+ Set_HalfWord ( prod, prod_offset++, (uint16_t )p) ;
17581852 carry = p >> 16 ;
17591853 }
17601854
17611855 /* Add carry to the next higher word of product / dividend */
1762- * prod += (uint16_t )carry;
1856+ Set_HalfWord ( prod, prod_offset, Get_HalfWord (prod, prod_offset) + (uint16_t )carry) ;
17631857}
17641858
17651859/* **********************************************************************************************
@@ -1791,12 +1885,17 @@ void XMP_Double_Mul(digit* prod, const digit* multiplicand, const digit* multipl
17911885 */
17921886 XMP_Init (prod, 0 , precision * 2 );
17931887
1794- const uint16_t * multiplier_ptr = ( const uint16_t *)multiplier ;
1795- uint16_t * product_ptr = ( uint16_t *)prod ;
1888+ size_t multiplier_offset = 0 ;
1889+ size_t product_offset = 0 ;
17961890
17971891 // Multiply multiplicand by each word in multiplier, accumulating prod.
17981892 for (int i = 0 ; i < precision * 2 ; ++i) {
1799- XMP_Hybrid_Mul (product_ptr++, (uint16_t *)multiplicand, *multiplier_ptr++, precision * 2 );
1893+ XMP_Hybrid_Mul ((uint16_t *)prod,
1894+ product_offset++,
1895+ (uint16_t *)multiplicand,
1896+ 0 ,
1897+ Get_HalfWord ((const uint16_t *)multiplier, multiplier_offset++),
1898+ precision * 2 );
18001899 }
18011900}
18021901
@@ -1867,8 +1966,8 @@ int XMP_Prepare_Modulus(const digit* n_modulus, int precision)
18671966 _modulus_shift--; /* now 0 <= _modulus_shift <= 16 */
18681967 }
18691968 uint16_t * mpm = (uint16_t *)_mod_quotient;
1870- _reciprical_low_digit = * mpm++ ;
1871- _reciprical_high_digit = * mpm;
1969+ _reciprical_low_digit = Get_HalfWord ( mpm, 0 ) ;
1970+ _reciprical_high_digit = Get_HalfWord ( mpm, 1 ) ;
18721971
18731972 return 0 ;
18741973}
@@ -1928,9 +2027,10 @@ int XMP_Mod_Mult(digit* prod, const digit* multiplicand, const digit* multiplier
19282027 int nqd = dmi + 1 - _modulus_sub_precision; // number of quotient digits remaining to be generated
19292028
19302029 /* Set msb, lsb, and normal ptrs of dividend */
1931- uint16_t * dmph =
1932- ((uint16_t *)_double_staging_number) + dmi + 1 ; // points to one higher than precision would indicate
1933- uint16_t * dmpl = dmph - _modulus_sub_precision;
2030+ size_t dmph_offset = dmi + 1 ;
2031+ uint16_t * dmph = (uint16_t *)_double_staging_number;
2032+ size_t dmpl_offset = dmph_offset - _modulus_sub_precision;
2033+ uint16_t * dmpl = dmph;
19342034
19352035 /*
19362036 ** Divide loop.
@@ -1942,20 +2042,19 @@ int XMP_Mod_Mult(digit* prod, const digit* multiplicand, const digit* multiplier
19422042 ** modulus to get the proper negative remainder.
19432043 */
19442044 for (; nqd; nqd--) {
1945- --dmph ;
1946- --dmpl ;
2045+ --dmph_offset ;
2046+ --dmpl_offset ;
19472047
1948- uint16_t q = mp_quo_digit (dmph); // trial quotient digit
2048+ uint16_t q = mp_quo_digit (dmph, dmph_offset ); // trial quotient digit
19492049 if (q > 0 ) {
1950- XMP_Hybrid_Mul (dmpl, (uint16_t *)_scratch_modulus, q, precision * 2 );
2050+ XMP_Hybrid_Mul (dmpl, dmpl_offset, (uint16_t *)_scratch_modulus, 0 , q, precision * 2 );
19512051
19522052 /* Perform correction if q too large.
19532053 ** This rarely occurs.
19542054 */
1955- if (!(*dmph & SEMI_UPPER_MOST_BIT)) {
1956- uint16_t * dmp = dmpl;
1957- if (XMP_Sub ((uint32_t *)dmp, (uint32_t *)dmp, _scratch_modulus, false , precision)) {
1958- (*dmph)--;
2055+ if (!(Get_HalfWord (dmph, dmph_offset) & SEMI_UPPER_MOST_BIT)) {
2056+ if (XMP_Sub (dmpl, dmpl_offset, dmpl, dmpl_offset, _scratch_modulus, false , precision)) {
2057+ Set_HalfWord (dmph, dmph_offset, Get_HalfWord (dmph, dmph_offset) - 1 );
19592058 }
19602059 }
19612060 }
@@ -2024,7 +2123,7 @@ void XMP_Mod_Mult_Clear(int precision)
20242123** three MULTUNITs at dividend by the upper two MULTUNITs of the
20252124** modulus.
20262125*/
2027- uint16_t mp_quo_digit (uint16_t * dividend)
2126+ uint16_t mp_quo_digit (uint16_t * dividend, size_t dividend_offset )
20282127{
20292128 uint32_t q, q0, q1, q2;
20302129
@@ -2033,17 +2132,19 @@ uint16_t mp_quo_digit(uint16_t* dividend)
20332132 * The last terms of q1 and q2 perform upward rounding, which is
20342133 * needed to guarantee that the result not be too small.
20352134 */
2036- q1 = (dividend[-2 ] ^ SEMI_MASK) * (uint32_t )_reciprical_high_digit + _reciprical_high_digit;
2037- q2 = (dividend[-1 ] ^ SEMI_MASK) * (uint32_t )_reciprical_low_digit + (1L << 16 );
2135+ q1 = (Get_HalfWord (dividend, dividend_offset - 2 ) ^ SEMI_MASK) * (uint32_t )_reciprical_high_digit
2136+ + _reciprical_high_digit;
2137+ q2 = (Get_HalfWord (dividend, dividend_offset - 1 ) ^ SEMI_MASK) * (uint32_t )_reciprical_low_digit + (1L << 16 );
20382138 q0 = (q1 >> 1 ) + (q2 >> 1 ) + 1 ;
20392139
20402140 /* Compute the middle significant product group. */
2041- q1 = (dividend[- 1 ] ^ SEMI_MASK) * (uint32_t )_reciprical_high_digit;
2042- q2 = (dividend[ 0 ] ^ SEMI_MASK) * (uint32_t )_reciprical_low_digit;
2141+ q1 = (Get_HalfWord ( dividend, dividend_offset - 1 ) ^ SEMI_MASK) * (uint32_t )_reciprical_high_digit;
2142+ q2 = (Get_HalfWord ( dividend, dividend_offset) ^ SEMI_MASK) * (uint32_t )_reciprical_low_digit;
20432143 q = (q0 >> 16 ) + (q1 >> 1 ) + (q2 >> 1 ) + 1 ;
20442144
20452145 /* Compute the most significant term and add in the others */
2046- q = (q >> (16 - 2 )) + (((dividend[0 ] ^ SEMI_MASK) * (uint32_t )_reciprical_high_digit) << 1 );
2146+ q = (q >> (16 - 2 ))
2147+ + (((Get_HalfWord (dividend, dividend_offset) ^ SEMI_MASK) * (uint32_t )_reciprical_high_digit) << 1 );
20472148 q >>= _modulus_shift;
20482149
20492150 /* Prevent overflow and then wipe out the intermediate results. */
0 commit comments