diff options
-rw-r--r-- | generic/tclExecute.c | 469 | ||||
-rw-r--r-- | generic/tclStubInit.c | 8 | ||||
-rw-r--r-- | generic/tclTomMath.decls | 15 | ||||
-rw-r--r-- | generic/tclTomMathDecls.h | 39 | ||||
-rw-r--r-- | tests/mathop.test | 30 | ||||
-rw-r--r-- | unix/Makefile.in | 19 | ||||
-rw-r--r-- | win/Makefile.in | 4 | ||||
-rw-r--r-- | win/makefile.vc | 4 |
8 files changed, 287 insertions, 301 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 112924a..189832f 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -8222,6 +8222,126 @@ FinalizeOONextFilter( } /* + * LongPwrSmallExpon -- , WidePwrSmallExpon -- + * + * Helpers to calculate small powers of integers whose result is long or wide. + */ +static inline long +LongPwrSmallExpon(long l1, long exponent) { + + long lResult; + + lResult = l1 * l1; /* b**2 */ + switch (exponent) { + case 2: + break; + case 3: + lResult *= l1; /* b**3 */ + break; + case 4: + lResult *= lResult; /* b**4 */ + break; + case 5: + lResult *= lResult; /* b**4 */ + lResult *= l1; /* b**5 */ + break; + case 6: + lResult *= l1; /* b**3 */ + lResult *= lResult; /* b**6 */ + break; + case 7: + lResult *= l1; /* b**3 */ + lResult *= lResult; /* b**6 */ + lResult *= l1; /* b**7 */ + break; + case 8: + lResult *= lResult; /* b**4 */ + lResult *= lResult; /* b**8 */ + break; + } + return lResult; +} +static inline Tcl_WideInt +WidePwrSmallExpon(Tcl_WideInt w1, long exponent) { + + Tcl_WideInt wResult; + + wResult = w1 * w1; /* b**2 */ + switch (exponent) { + case 2: + break; + case 3: + wResult *= w1; /* b**3 */ + break; + case 4: + wResult *= wResult; /* b**4 */ + break; + case 5: + wResult *= wResult; /* b**4 */ + wResult *= w1; /* b**5 */ + break; + case 6: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + break; + case 7: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + wResult *= w1; /* b**7 */ + break; + case 8: + wResult *= wResult; /* b**4 */ + wResult *= wResult; /* b**8 */ + break; + case 9: + wResult *= wResult; /* b**4 */ + wResult *= wResult; /* b**8 */ + wResult *= w1; /* b**9 */ + break; + case 10: + wResult *= wResult; /* b**4 */ + wResult *= w1; /* b**5 */ + wResult *= wResult; /* b**10 */ + break; + case 11: + wResult *= wResult; /* b**4 */ + wResult *= w1; /* b**5 */ + wResult *= wResult; /* b**10 */ + wResult *= w1; /* b**11 */ + break; + case 12: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + wResult *= wResult; /* b**12 */ + break; + case 13: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + wResult *= wResult; /* b**12 */ + wResult *= w1; /* b**13 */ + break; + case 14: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + wResult *= w1; /* b**7 */ + wResult *= wResult; /* b**14 */ + break; + case 15: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + wResult *= w1; /* b**7 */ + wResult *= wResult; /* b**14 */ + wResult *= w1; /* b**15 */ + break; + case 16: + wResult *= wResult; /* b**4 */ + wResult *= wResult; /* b**8 */ + wResult *= wResult; /* b**16 */ + break; + } + return wResult; +} +/* *---------------------------------------------------------------------- * * ExecuteExtendedBinaryMathOp, ExecuteExtendedUnaryMathOp -- @@ -8292,7 +8412,7 @@ ExecuteExtendedBinaryMathOp( Tcl_WideInt w1, w2, wResult; mp_int big1, big2, bigResult, bigRemainder; Tcl_Obj *objResultPtr; - int invalid, numPos, zero; + int invalid, zero; long shift; (void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1); @@ -8321,7 +8441,7 @@ ExecuteExtendedBinaryMathOp( w1 = *((const Tcl_WideInt *)ptr1); if (type2 != TCL_NUMBER_BIG) { Tcl_WideInt wQuotient, wRemainder; - Tcl_GetWideIntFromObj(NULL, value2Ptr, &w2); + TclGetWideIntFromObj(NULL, value2Ptr, &w2); wQuotient = w1 / w2; /* @@ -8520,16 +8640,7 @@ ExecuteExtendedBinaryMathOp( if (opcode == INST_LSHIFT) { mp_mul_2d(&big1, shift, &bigResult); } else { - mp_init(&bigRemainder); - mp_div_2d(&big1, shift, &bigResult, &bigRemainder); - if (mp_cmp_d(&bigRemainder, 0) == MP_LT) { - /* - * Convert to Tcl's integer division rules. - */ - - mp_sub_d(&bigResult, 1, &bigResult); - } - mp_clear(&bigRemainder); + mp_tc_div_2d(&big1, shift, &bigResult); } mp_clear(&big1); BIG_RESULT(&bigResult); @@ -8539,138 +8650,22 @@ ExecuteExtendedBinaryMathOp( case INST_BITXOR: case INST_BITAND: if ((type1 == TCL_NUMBER_BIG) || (type2 == TCL_NUMBER_BIG)) { - mp_int *First, *Second; - Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); - /* - * Count how many positive arguments we have. If only one of the - * arguments is negative, store it in 'Second'. - */ - - if (mp_cmp_d(&big1, 0) != MP_LT) { - numPos = 1 + (mp_cmp_d(&big2, 0) != MP_LT); - First = &big1; - Second = &big2; - } else { - First = &big2; - Second = &big1; - numPos = (mp_cmp_d(First, 0) != MP_LT); - } mp_init(&bigResult); switch (opcode) { case INST_BITAND: - switch (numPos) { - case 2: - /* - * Both arguments positive, base case. - */ - - mp_and(First, Second, &bigResult); - break; - case 1: - /* - * First is positive; second negative: - * P & N = P & ~~N = P&~(-N-1) = P & (P ^ (-N-1)) - */ - - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_xor(First, Second, &bigResult); - mp_and(First, &bigResult, &bigResult); - break; - case 0: - /* - * Both arguments negative: - * a & b = ~ (~a | ~b) = -(-a-1|-b-1)-1 - */ - - mp_neg(First, First); - mp_sub_d(First, 1, First); - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_or(First, Second, &bigResult); - mp_neg(&bigResult, &bigResult); - mp_sub_d(&bigResult, 1, &bigResult); - break; - } + mp_tc_and(&big1, &big2, &bigResult); break; case INST_BITOR: - switch (numPos) { - case 2: - /* - * Both arguments positive, base case. - */ - - mp_or(First, Second, &bigResult); - break; - case 1: - /* - * First is positive; second negative: - * N|P = ~(~N&~P) = ~((-N-1)&~P) = -((-N-1)&((-N-1)^P))-1 - */ - - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_xor(First, Second, &bigResult); - mp_and(Second, &bigResult, &bigResult); - mp_neg(&bigResult, &bigResult); - mp_sub_d(&bigResult, 1, &bigResult); - break; - case 0: - /* - * Both arguments negative: - * a | b = ~ (~a & ~b) = -(-a-1&-b-1)-1 - */ - - mp_neg(First, First); - mp_sub_d(First, 1, First); - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_and(First, Second, &bigResult); - mp_neg(&bigResult, &bigResult); - mp_sub_d(&bigResult, 1, &bigResult); - break; - } + mp_tc_or(&big1, &big2, &bigResult); break; case INST_BITXOR: - switch (numPos) { - case 2: - /* - * Both arguments positive, base case. - */ - - mp_xor(First, Second, &bigResult); - break; - case 1: - /* - * First is positive; second negative: - * P^N = ~(P^~N) = -(P^(-N-1))-1 - */ - - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_xor(First, Second, &bigResult); - mp_neg(&bigResult, &bigResult); - mp_sub_d(&bigResult, 1, &bigResult); - break; - case 0: - /* - * Both arguments negative: - * a ^ b = (~a ^ ~b) = (-a-1^-b-1) - */ - - mp_neg(First, First); - mp_sub_d(First, 1, First); - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_xor(First, Second, &bigResult); - break; - } + mp_tc_xor(&big1, &big2, &bigResult); break; } @@ -8735,8 +8730,11 @@ ExecuteExtendedBinaryMathOp( goto doubleResult; } l1 = l2 = 0; - if (type2 == TCL_NUMBER_LONG) { + w1 = w2 = 0; /* to silence compiler warning (maybe-uninitialized) */ + switch (type2) { + case TCL_NUMBER_LONG: l2 = *((const long *) ptr2); + pwrLongExpon: if (l2 == 0) { /* * Anything to the zero power is 1. @@ -8750,16 +8748,18 @@ ExecuteExtendedBinaryMathOp( return NULL; } - } - - switch (type2) { - case TCL_NUMBER_LONG: negativeExponent = (l2 < 0); oddExponent = (int) (l2 & 1); break; #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); + /* check it fits in long */ + l2 = (long)w2; + if (w2 == l2) { + type2 = TCL_NUMBER_LONG; + goto pwrLongExpon; + } negativeExponent = (w2 < 0); oddExponent = (int) (w2 & (Tcl_WideInt)1); break; @@ -8773,48 +8773,18 @@ ExecuteExtendedBinaryMathOp( break; } - if (type1 == TCL_NUMBER_LONG) { + switch (type1) { + case TCL_NUMBER_LONG: l1 = *((const long *)ptr1); - } - if (negativeExponent) { - if (type1 == TCL_NUMBER_LONG) { - switch (l1) { - case 0: - /* - * Zero to a negative power is div by zero error. - */ - - return EXPONENT_OF_ZERO; - case -1: - if (oddExponent) { - LONG_RESULT(-1); - } - /* fallthrough */ - case 1: - /* - * 1 to any power is 1. - */ - - return constants[1]; - } - } - - /* - * Integers with magnitude greater than 1 raise to a negative - * power yield the answer zero (see TIP 123). - */ - - return constants[0]; - } - - if (type1 == TCL_NUMBER_LONG) { + pwrLongBase: switch (l1) { case 0: /* * Zero to a positive power is zero. + * Zero to a negative power is div by zero error. */ - return constants[0]; + return (!negativeExponent) ? constants[0] : EXPONENT_OF_ZERO; case 1: /* * 1 to any power is 1. @@ -8822,11 +8792,44 @@ ExecuteExtendedBinaryMathOp( return constants[1]; case -1: - if (!oddExponent) { - return constants[1]; + if (!negativeExponent) { + if (!oddExponent) { + return constants[1]; + } + LONG_RESULT(-1); } - LONG_RESULT(-1); + /* negativeExponent */ + if (oddExponent) { + LONG_RESULT(-1); + } + return constants[1]; } + break; +#ifndef TCL_WIDE_INT_IS_LONG + case TCL_NUMBER_WIDE: + w1 = *((const Tcl_WideInt *) ptr1); + /* check it fits in long */ + l1 = (long)w1; + if (w1 == l1) { + type1 = TCL_NUMBER_LONG; + goto pwrLongBase; + } + break; +#endif + } + if (negativeExponent) { + + /* + * Integers with magnitude greater than 1 raise to a negative + * power yield the answer zero (see TIP 123). + */ + + return constants[0]; + } + + + if (type1 == TCL_NUMBER_BIG) { + goto overflowExpon; } /* @@ -8844,6 +8847,8 @@ ExecuteExtendedBinaryMathOp( return GENERAL_ARITHMETIC_ERROR; } + /* From here (up to overflowExpon) exponent is long (l2). */ + if (type1 == TCL_NUMBER_LONG) { if (l1 == 2) { /* @@ -8884,35 +8889,8 @@ ExecuteExtendedBinaryMathOp( /* * Small powers of 32-bit integers. */ + lResult = LongPwrSmallExpon(l1, l2); - lResult = l1 * l1; /* b**2 */ - switch (l2) { - case 2: - break; - case 3: - lResult *= l1; /* b**3 */ - break; - case 4: - lResult *= lResult; /* b**4 */ - break; - case 5: - lResult *= lResult; /* b**4 */ - lResult *= l1; /* b**5 */ - break; - case 6: - lResult *= l1; /* b**3 */ - lResult *= lResult; /* b**6 */ - break; - case 7: - lResult *= l1; /* b**3 */ - lResult *= lResult; /* b**6 */ - lResult *= l1; /* b**7 */ - break; - case 8: - lResult *= lResult; /* b**4 */ - lResult *= lResult; /* b**8 */ - break; - } LONG_RESULT(lResult); } @@ -8945,97 +8923,24 @@ ExecuteExtendedBinaryMathOp( } } #endif - } #if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) - if (type1 == TCL_NUMBER_LONG) { + /* Code below (up to overflowExpon) works with wide-int base */ w1 = l1; -#ifndef TCL_WIDE_INT_IS_LONG - } else if (type1 == TCL_NUMBER_WIDE) { - w1 = *((const Tcl_WideInt *) ptr1); #endif - } else { - goto overflowExpon; } + +#if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) + + /* From here (up to overflowExpon) base is wide-int (w1). */ + if (l2 - 2 < (long)MaxBase64Size && w1 <= MaxBase64[l2 - 2] && w1 >= -MaxBase64[l2 - 2]) { /* * Small powers of integers whose result is wide. */ + wResult = WidePwrSmallExpon(w1, l2); - wResult = w1 * w1; /* b**2 */ - switch (l2) { - case 2: - break; - case 3: - wResult *= l1; /* b**3 */ - break; - case 4: - wResult *= wResult; /* b**4 */ - break; - case 5: - wResult *= wResult; /* b**4 */ - wResult *= w1; /* b**5 */ - break; - case 6: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - break; - case 7: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - wResult *= w1; /* b**7 */ - break; - case 8: - wResult *= wResult; /* b**4 */ - wResult *= wResult; /* b**8 */ - break; - case 9: - wResult *= wResult; /* b**4 */ - wResult *= wResult; /* b**8 */ - wResult *= w1; /* b**9 */ - break; - case 10: - wResult *= wResult; /* b**4 */ - wResult *= w1; /* b**5 */ - wResult *= wResult; /* b**10 */ - break; - case 11: - wResult *= wResult; /* b**4 */ - wResult *= w1; /* b**5 */ - wResult *= wResult; /* b**10 */ - wResult *= w1; /* b**11 */ - break; - case 12: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - wResult *= wResult; /* b**12 */ - break; - case 13: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - wResult *= wResult; /* b**12 */ - wResult *= w1; /* b**13 */ - break; - case 14: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - wResult *= w1; /* b**7 */ - wResult *= wResult; /* b**14 */ - break; - case 15: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - wResult *= w1; /* b**7 */ - wResult *= wResult; /* b**14 */ - wResult *= w1; /* b**15 */ - break; - case 16: - wResult *= wResult; /* b**4 */ - wResult *= wResult; /* b**8 */ - wResult *= wResult; /* b**16 */ - break; - } WIDE_RESULT(wResult); } diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 1d15715..6290aa0 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -859,10 +859,10 @@ const TclTomMathStubs tclTomMathStubs = { TclBN_mp_set_long, /* 70 */ 0, /* 71 */ 0, /* 72 */ - 0, /* 73 */ - 0, /* 74 */ - 0, /* 75 */ - 0, /* 76 */ + TclBN_mp_tc_and, /* 73 */ + TclBN_mp_tc_or, /* 74 */ + TclBN_mp_tc_xor, /* 75 */ + TclBN_mp_tc_div_2d, /* 76 */ TclBN_mp_get_bit, /* 77 */ }; diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls index 09bf97d..6f4b4c3 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -240,6 +240,21 @@ declare 67 { declare 70 { int TclBN_mp_set_long(mp_int *a, unsigned long i) } + +# Added in libtommath 1.1.0 +declare 73 { + int TclBN_mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) +} +declare 74 { + int TclBN_mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c) +} +declare 75 { + int TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c) +} +declare 76 { + int TclBN_mp_tc_div_2d(const mp_int *a, int b, mp_int *c) +} + declare 77 { int TclBN_mp_get_bit(const mp_int *a, int b) } diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h index f287b84..9b525d2 100644 --- a/generic/tclTomMathDecls.h +++ b/generic/tclTomMathDecls.h @@ -96,6 +96,10 @@ #define mp_sqrt TclBN_mp_sqrt #define mp_sub TclBN_mp_sub #define mp_sub_d TclBN_mp_sub_d +#define mp_tc_and TclBN_mp_tc_and +#define mp_tc_div_2d TclBN_mp_tc_div_2d +#define mp_tc_or TclBN_mp_tc_or +#define mp_tc_xor TclBN_mp_tc_xor #define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin #define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n #define mp_toom_mul TclBN_mp_toom_mul @@ -307,10 +311,17 @@ EXTERN int TclBN_mp_expt_d_ex(const mp_int *a, mp_digit b, EXTERN int TclBN_mp_set_long(mp_int *a, unsigned long i); /* Slot 71 is reserved */ /* Slot 72 is reserved */ -/* Slot 73 is reserved */ -/* Slot 74 is reserved */ -/* Slot 75 is reserved */ -/* Slot 76 is reserved */ +/* 73 */ +EXTERN int TclBN_mp_tc_and(const mp_int *a, const mp_int *b, + mp_int *c); +/* 74 */ +EXTERN int TclBN_mp_tc_or(const mp_int *a, const mp_int *b, + mp_int *c); +/* 75 */ +EXTERN int TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, + mp_int *c); +/* 76 */ +EXTERN int TclBN_mp_tc_div_2d(const mp_int *a, int b, mp_int *c); /* 77 */ EXTERN int TclBN_mp_get_bit(const mp_int *a, int b); @@ -391,10 +402,10 @@ typedef struct TclTomMathStubs { int (*tclBN_mp_set_long) (mp_int *a, unsigned long i); /* 70 */ void (*reserved71)(void); void (*reserved72)(void); - void (*reserved73)(void); - void (*reserved74)(void); - void (*reserved75)(void); - void (*reserved76)(void); + int (*tclBN_mp_tc_and) (const mp_int *a, const mp_int *b, mp_int *c); /* 73 */ + int (*tclBN_mp_tc_or) (const mp_int *a, const mp_int *b, mp_int *c); /* 74 */ + int (*tclBN_mp_tc_xor) (const mp_int *a, const mp_int *b, mp_int *c); /* 75 */ + int (*tclBN_mp_tc_div_2d) (const mp_int *a, int b, mp_int *c); /* 76 */ int (*tclBN_mp_get_bit) (const mp_int *a, int b); /* 77 */ } TclTomMathStubs; @@ -552,10 +563,14 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBN_mp_set_long) /* 70 */ /* Slot 71 is reserved */ /* Slot 72 is reserved */ -/* Slot 73 is reserved */ -/* Slot 74 is reserved */ -/* Slot 75 is reserved */ -/* Slot 76 is reserved */ +#define TclBN_mp_tc_and \ + (tclTomMathStubsPtr->tclBN_mp_tc_and) /* 73 */ +#define TclBN_mp_tc_or \ + (tclTomMathStubsPtr->tclBN_mp_tc_or) /* 74 */ +#define TclBN_mp_tc_xor \ + (tclTomMathStubsPtr->tclBN_mp_tc_xor) /* 75 */ +#define TclBN_mp_tc_div_2d \ + (tclTomMathStubsPtr->tclBN_mp_tc_div_2d) /* 76 */ #define TclBN_mp_get_bit \ (tclTomMathStubsPtr->tclBN_mp_get_bit) /* 77 */ diff --git a/tests/mathop.test b/tests/mathop.test index f122b7b..a1a3f80 100644 --- a/tests/mathop.test +++ b/tests/mathop.test @@ -1206,6 +1206,8 @@ test mathop-25.5 { exp operator } {TestOp ** 1 5} 1 test mathop-25.6 { exp operator } {TestOp ** 5 1} 5 test mathop-25.7 { exp operator } {TestOp ** 4 3 2 1} 262144 test mathop-25.8 { exp operator } {TestOp ** 5.5 4} 915.0625 +test mathop-25.8a { exp operator } {TestOp ** 4.0 -1} 0.25 +test mathop-25.8b { exp operator } {TestOp ** 2.0 -2} 0.25 test mathop-25.9 { exp operator } {TestOp ** 16 3.5} 16384.0 test mathop-25.10 { exp operator } {TestOp ** 3.5 0} 1.0 test mathop-25.11 { exp operator } {TestOp ** 378 0} 1 @@ -1219,8 +1221,32 @@ test mathop-25.18 { exp operator } {TestOp ** -1 -2} 1 test mathop-25.19 { exp operator } {TestOp ** -1 3} -1 test mathop-25.20 { exp operator } {TestOp ** -1 4} 1 test mathop-25.21 { exp operator } {TestOp ** 2 63} 9223372036854775808 -test mathop-25.22 { exp operator } {TestOp ** 83756485763458746358734658473567847567473 2} 7015148907444467657897585474493757781161998914521537835809623408157343003287605729 -test mathop-25.23 { exp operator errors } { +test mathop-25.22 { exp operator } {TestOp ** 2 256} 115792089237316195423570985008687907853269984665640564039457584007913129639936 +set big 83756485763458746358734658473567847567473 +test mathop-25.23 { exp operator } {TestOp ** $big 2} 7015148907444467657897585474493757781161998914521537835809623408157343003287605729 +test mathop-25.24 { exp operator } {TestOp ** $big 0} 1 +test mathop-25.25 { exp operator } {TestOp ** $big 1} $big +test mathop-25.26 { exp operator } {TestOp ** $big -1} 0 +test mathop-25.27 { exp operator } {TestOp ** $big -2} 0 +test mathop-25.28 { exp operator } {TestOp ** $big -$big} 0 +test mathop-25.29 { exp operator } {expr {[set res [TestOp ** $big -1.0]] > 0 && $res < 1.2e-41}} 1 +test mathop-25.30 { exp operator } {expr {[set res [TestOp ** $big -1e-18]] > 0 && $res < 1}} 1 +test mathop-25.31 { exp operator } {expr {[set res [TestOp ** -$big -1.0]] > -1 && $res < 0}} 1 +test mathop-25.32 { exp operator } {expr {[set res [TestOp ** -$big -2.0]] > 0 && $res < 1}} 1 +test mathop-25.33 { exp operator } {expr {[set res [TestOp ** -$big -3.0]] > -1 && $res < 0}} 1 +test mathop-25.34 { exp operator } {TestOp ** $big -1e-30} 1.0 +test mathop-25.35 { exp operator } {TestOp ** $big -1e+30} 0.0 +test mathop-25.36 { exp operator } {TestOp ** 0 $big} 0 +test mathop-25.37 { exp operator } {TestOp ** 1 $big} 1 +test mathop-25.38 { exp operator } {TestOp ** -1 $big} -1 +test mathop-25.39 { exp operator } {TestOp ** -1 [expr {$big+1}]} 1 +test mathop-25.40 { exp operator (small exponent power helper and its boundaries) } { + set pwr 0 + set res 1 + while {[incr pwr] <= 17 && [set i [TestOp ** 15 $pwr]] == [set res [expr {$res * 15}]]} {} + list [incr pwr -1] $res +} {17 98526125335693359375} +test mathop-25.41 { exp operator errors } { set res {} set exp {} diff --git a/unix/Makefile.in b/unix/Makefile.in index bdab85a..8a4c72a 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -332,7 +332,8 @@ TOMMATH_OBJS = bn_reverse.o bn_fast_s_mp_mul_digs.o \ bn_mp_read_radix.o bn_mp_rshd.o bn_mp_set.o bn_mp_set_int.o \ bn_mp_set_long.o bn_mp_shrink.o \ bn_mp_sqr.o bn_mp_sqrt.o bn_mp_sub.o bn_mp_sub_d.o \ - bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o \ + bn_mp_tc_and.o bn_mp_tc_div_2d.o bn_mp_tc_or.o bn_mp_tc_xor.o \ + bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o \ bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_toradix_n.o \ bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o bn_s_mp_add.o \ bn_s_mp_mul_digs.o bn_s_mp_sqr.o bn_s_mp_sub.o @@ -536,6 +537,10 @@ TOMMATH_SRCS = \ $(TOMMATH_DIR)/bn_mp_sqrt.c \ $(TOMMATH_DIR)/bn_mp_sub.c \ $(TOMMATH_DIR)/bn_mp_sub_d.c \ + $(TOMMATH_DIR)/bn_mp_tc_and.c \ + $(TOMMATH_DIR)/bn_mp_tc_div_2d.c \ + $(TOMMATH_DIR)/bn_mp_tc_or.c \ + $(TOMMATH_DIR)/bn_mp_tc_xor.c \ $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c \ $(TOMMATH_DIR)/bn_mp_to_unsigned_bin_n.c \ $(TOMMATH_DIR)/bn_mp_toom_mul.c \ @@ -1517,6 +1522,18 @@ bn_mp_sub.o: $(TOMMATH_DIR)/bn_mp_sub.c $(MATHHDRS) bn_mp_sub_d.o: $(TOMMATH_DIR)/bn_mp_sub_d.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sub_d.c +bn_mp_tc_and.o: $(TOMMATH_DIR)/bn_mp_tc_and.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_tc_and.c + +bn_mp_tc_div_2d.o: $(TOMMATH_DIR)/bn_mp_tc_div_2d.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_tc_div_2d.c + +bn_mp_tc_or.o: $(TOMMATH_DIR)/bn_mp_tc_or.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_tc_or.c + +bn_mp_tc_xor.o: $(TOMMATH_DIR)/bn_mp_tc_xor.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_tc_xor.c + bn_mp_to_unsigned_bin.o: $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c diff --git a/win/Makefile.in b/win/Makefile.in index a427eee..cc3de21 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -365,6 +365,10 @@ TOMMATH_OBJS = \ bn_mp_sqrt.${OBJEXT} \ bn_mp_sub.${OBJEXT} \ bn_mp_sub_d.${OBJEXT} \ + bn_mp_tc_and.${OBJEXT} \ + bn_mp_tc_div_2d.${OBJEXT} \ + bn_mp_tc_or.${OBJEXT} \ + bn_mp_tc_xor.${OBJEXT} \ bn_mp_to_unsigned_bin.${OBJEXT} \ bn_mp_to_unsigned_bin_n.${OBJEXT} \ bn_mp_toom_mul.${OBJEXT} \ diff --git a/win/makefile.vc b/win/makefile.vc index 2e0198e..d1122a4 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -305,6 +305,10 @@ TOMMATHOBJS = \ $(TMP_DIR)\bn_mp_sqrt.obj \
$(TMP_DIR)\bn_mp_sub.obj \
$(TMP_DIR)\bn_mp_sub_d.obj \
+ $(TMP_DIR)\bn_mp_tc_and.obj \
+ $(TMP_DIR)\bn_mp_tc_div_2d.obj \
+ $(TMP_DIR)\bn_mp_tc_or.obj \
+ $(TMP_DIR)\bn_mp_tc_xor.obj \
$(TMP_DIR)\bn_mp_to_unsigned_bin.obj \
$(TMP_DIR)\bn_mp_to_unsigned_bin_n.obj \
$(TMP_DIR)\bn_mp_toom_mul.obj \
|