Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merge 8.7 |
|---|---|
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
10bc1a9af54692d1e4d93cc21953c8e6 |
| User & Date: | jan.nijtmans 2020-01-23 10:41:38.773 |
Context
|
2020-01-23
| ||
| 13:15 | Merge 8.7 check-in: 37d65e3634 user: jan.nijtmans tags: trunk | |
| 10:43 | Merge trunk check-in: d6f3d7a2b0 user: jan.nijtmans tags: novem | |
| 10:41 | Merge 8.7 check-in: 10bc1a9af5 user: jan.nijtmans tags: trunk | |
| 10:33 | Add error-handling to all libtommath function calls. Most likely not perfect (open for further impro... check-in: 40c22004df user: jan.nijtmans tags: core-8-branch | |
| 09:47 | merge-mark check-in: 3541ad71e9 user: jan.nijtmans tags: trunk | |
Changes
Changes to generic/tclBasic.c.
| ︙ | ︙ | |||
6915 6916 6917 6918 6919 6920 6921 6922 |
break;
}
if (exact) {
Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) sqrt(d)));
} else {
mp_int root;
| > | > | > > > > | 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 |
break;
}
if (exact) {
Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) sqrt(d)));
} else {
mp_int root;
mp_err err;
err = mp_init(&root);
if (err == MP_OKAY) {
err = mp_sqrt(&big, &root);
}
mp_clear(&big);
if (err != MP_OKAY) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewBignumObj(&root));
}
return TCL_OK;
negarg:
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"square root of negative argument", -1));
|
| ︙ | ︙ | |||
6964 6965 6966 6967 6968 6969 6970 6971 |
#endif
if (code != TCL_OK) {
return TCL_ERROR;
}
if ((d >= 0.0) && TclIsInfinite(d)
&& (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK)) {
mp_int root;
| > | > | > > > > > | 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 |
#endif
if (code != TCL_OK) {
return TCL_ERROR;
}
if ((d >= 0.0) && TclIsInfinite(d)
&& (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK)) {
mp_int root;
mp_err err;
err = mp_init(&root);
if (err == MP_OKAY) {
err = mp_sqrt(&big, &root);
}
mp_clear(&big);
if (err != MP_OKAY) {
mp_clear(&root);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclBignumToDouble(&root)));
mp_clear(&root);
} else {
Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sqrt(d)));
}
return TCL_OK;
}
|
| ︙ | ︙ | |||
7133 7134 7135 7136 7137 7138 7139 |
return TCL_OK;
}
bytes++; numBytes--;
}
}
goto unChanged;
} else if (l == WIDE_MIN) {
| | > > | 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 |
return TCL_OK;
}
bytes++; numBytes--;
}
}
goto unChanged;
} else if (l == WIDE_MIN) {
if (mp_init_i64(&big, l) != MP_OKAY) {
return TCL_ERROR;
}
goto tooLarge;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-l));
return TCL_OK;
}
if (type == TCL_NUMBER_DOUBLE) {
|
| ︙ | ︙ | |||
7164 7165 7166 7167 7168 7169 7170 |
return TCL_OK;
}
if (type == TCL_NUMBER_BIG) {
if (mp_isneg((const mp_int *) ptr)) {
Tcl_GetBignumFromObj(NULL, objv[1], &big);
tooLarge:
| | > > | 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 |
return TCL_OK;
}
if (type == TCL_NUMBER_BIG) {
if (mp_isneg((const mp_int *) ptr)) {
Tcl_GetBignumFromObj(NULL, objv[1], &big);
tooLarge:
if (mp_neg(&big, &big) != MP_OKAY) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
} else {
unChanged:
Tcl_SetObjResult(interp, objv[1]);
}
return TCL_OK;
}
|
| ︙ | ︙ | |||
7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 |
if (fractPart <= -0.5) {
min++;
} else if (fractPart >= 0.5) {
max--;
}
if ((intPart >= (double)max) || (intPart <= (double)min)) {
mp_int big;
if (Tcl_InitBignumFromDouble(interp, intPart, &big) != TCL_OK) {
/* Infinity */
return TCL_ERROR;
}
if (fractPart <= -0.5) {
| > | | > > > | 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 |
if (fractPart <= -0.5) {
min++;
} else if (fractPart >= 0.5) {
max--;
}
if ((intPart >= (double)max) || (intPart <= (double)min)) {
mp_int big;
mp_err err = MP_OKAY;
if (Tcl_InitBignumFromDouble(interp, intPart, &big) != TCL_OK) {
/* Infinity */
return TCL_ERROR;
}
if (fractPart <= -0.5) {
err = mp_sub_d(&big, 1, &big);
} else if (fractPart >= 0.5) {
err = mp_add_d(&big, 1, &big);
}
if (err != MP_OKAY) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
return TCL_OK;
} else {
Tcl_WideInt result = (Tcl_WideInt)intPart;
if (fractPart <= -0.5) {
|
| ︙ | ︙ |
Changes to generic/tclExecute.c.
| ︙ | ︙ | |||
600 601 602 603 604 605 606 607 608 609 610 611 612 613 | /* * Markers for ExecuteExtendedBinaryMathOp. */ #define DIVIDED_BY_ZERO ((Tcl_Obj *) -1) #define EXPONENT_OF_ZERO ((Tcl_Obj *) -2) #define GENERAL_ARITHMETIC_ERROR ((Tcl_Obj *) -3) /* * Declarations for local procedures to this file: */ #ifdef TCL_COMPILE_STATS static int EvalStatsCmd(ClientData clientData, | > | 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 | /* * Markers for ExecuteExtendedBinaryMathOp. */ #define DIVIDED_BY_ZERO ((Tcl_Obj *) -1) #define EXPONENT_OF_ZERO ((Tcl_Obj *) -2) #define GENERAL_ARITHMETIC_ERROR ((Tcl_Obj *) -3) #define OUT_OF_MEMORY ((Tcl_Obj *) -4) /* * Declarations for local procedures to this file: */ #ifdef TCL_COMPILE_STATS static int EvalStatsCmd(ClientData clientData, |
| ︙ | ︙ | |||
1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 |
Tcl_Interp *interp,
Tcl_Obj *valuePtr,
Tcl_Obj *incrPtr)
{
ClientData ptr1, ptr2;
int type1, type2;
mp_int value, incr;
if (Tcl_IsShared(valuePtr)) {
Tcl_Panic("%s called with shared object", "TclIncrObj");
}
if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) {
/*
| > | 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 |
Tcl_Interp *interp,
Tcl_Obj *valuePtr,
Tcl_Obj *incrPtr)
{
ClientData ptr1, ptr2;
int type1, type2;
mp_int value, incr;
mp_err err;
if (Tcl_IsShared(valuePtr)) {
Tcl_Panic("%s called with shared object", "TclIncrObj");
}
if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) {
/*
|
| ︙ | ︙ | |||
1803 1804 1805 1806 1807 1808 1809 |
TclSetIntObj(valuePtr, sum);
return TCL_OK;
}
}
Tcl_TakeBignumFromObj(interp, valuePtr, &value);
Tcl_GetBignumFromObj(interp, incrPtr, &incr);
| | > > > | 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 |
TclSetIntObj(valuePtr, sum);
return TCL_OK;
}
}
Tcl_TakeBignumFromObj(interp, valuePtr, &value);
Tcl_GetBignumFromObj(interp, incrPtr, &incr);
err = mp_add(&value, &incr, &value);
mp_clear(&incr);
if (err != MP_OKAY) {
return TCL_ERROR;
}
Tcl_SetBignumObj(valuePtr, &value);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 |
goto divideByZero;
} else if (objResultPtr == EXPONENT_OF_ZERO) {
TRACE_APPEND(("EXPONENT OF ZERO\n"));
goto exponOfZero;
} else if (objResultPtr == GENERAL_ARITHMETIC_ERROR) {
TRACE_ERROR(interp);
goto gotError;
} else if (objResultPtr == NULL) {
TRACE_APPEND(("%s\n", O2S(valuePtr)));
NEXT_INST_F(1, 1, 0);
} else {
TRACE_APPEND(("%s\n", O2S(objResultPtr)));
NEXT_INST_F(1, 2, 1);
}
| > > > | 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 |
goto divideByZero;
} else if (objResultPtr == EXPONENT_OF_ZERO) {
TRACE_APPEND(("EXPONENT OF ZERO\n"));
goto exponOfZero;
} else if (objResultPtr == GENERAL_ARITHMETIC_ERROR) {
TRACE_ERROR(interp);
goto gotError;
} else if (objResultPtr == OUT_OF_MEMORY) {
TRACE_APPEND(("OUT OF MEMORY\n"));
goto outOfMemory;
} else if (objResultPtr == NULL) {
TRACE_APPEND(("%s\n", O2S(valuePtr)));
NEXT_INST_F(1, 1, 0);
} else {
TRACE_APPEND(("%s\n", O2S(objResultPtr)));
NEXT_INST_F(1, 2, 1);
}
|
| ︙ | ︙ | |||
7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 |
divideByZero:
Tcl_SetObjResult(interp, Tcl_NewStringObj("divide by zero", -1));
DECACHE_STACK_INFO();
Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero", NULL);
CACHE_STACK_INFO();
goto gotError;
/*
* Exponentiation of zero by negative number in an expression. Control
* only reaches this point by "goto exponOfZero".
*/
exponOfZero:
Tcl_SetObjResult(interp, Tcl_NewStringObj(
| > > > > > > > | 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 |
divideByZero:
Tcl_SetObjResult(interp, Tcl_NewStringObj("divide by zero", -1));
DECACHE_STACK_INFO();
Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero", NULL);
CACHE_STACK_INFO();
goto gotError;
outOfMemory:
Tcl_SetObjResult(interp, Tcl_NewStringObj("out of memory", -1));
DECACHE_STACK_INFO();
Tcl_SetErrorCode(interp, "ARITH", "OUTOFMEMORY", "out of memory", NULL);
CACHE_STACK_INFO();
goto gotError;
/*
* Exponentiation of zero by negative number in an expression. Control
* only reaches this point by "goto exponOfZero".
*/
exponOfZero:
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
| ︙ | ︙ | |||
7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 |
ClientData ptr1, ptr2;
double d1, d2, dResult;
Tcl_WideInt w1, w2, wResult;
mp_int big1, big2, bigResult, bigRemainder;
Tcl_Obj *objResultPtr;
int invalid, zero;
long shift;
(void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1);
(void) GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2);
switch (opcode) {
case INST_MOD:
/* TODO: Attempts to re-use unshared operands on stack */
| > | 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 |
ClientData ptr1, ptr2;
double d1, d2, dResult;
Tcl_WideInt w1, w2, wResult;
mp_int big1, big2, bigResult, bigRemainder;
Tcl_Obj *objResultPtr;
int invalid, zero;
long shift;
mp_err err;
(void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1);
(void) GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2);
switch (opcode) {
case INST_MOD:
/* TODO: Attempts to re-use unshared operands on stack */
|
| ︙ | ︙ | |||
7746 7747 7748 7749 7750 7751 7752 |
/* TODO: internals intrusion */
if ((w1 > ((Tcl_WideInt) 0)) ^ !mp_isneg(&big2)) {
/*
* Arguments are opposite sign; remainder is sum.
*/
| | > | | > > > > | | | > | | | > | > | > > > | 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 |
/* TODO: internals intrusion */
if ((w1 > ((Tcl_WideInt) 0)) ^ !mp_isneg(&big2)) {
/*
* Arguments are opposite sign; remainder is sum.
*/
err = mp_init_i64(&big1, w1);
if (err == MP_OKAY) {
err = mp_add(&big2, &big1, &big2);
mp_clear(&big1);
}
if (err != MP_OKAY) {
return OUT_OF_MEMORY;
}
BIG_RESULT(&big2);
}
/*
* Arguments are same sign; remainder is first operand.
*/
mp_clear(&big2);
return NULL;
}
Tcl_GetBignumFromObj(NULL, valuePtr, &big1);
Tcl_GetBignumFromObj(NULL, value2Ptr, &big2);
err = mp_init_multi(&bigResult, &bigRemainder, NULL);
if (err == MP_OKAY) {
err = mp_div(&big1, &big2, &bigResult, &bigRemainder);
}
if ((err == MP_OKAY) && !mp_iszero(&bigRemainder) && (bigRemainder.sign != big2.sign)) {
/*
* Convert to Tcl's integer division rules.
*/
if ((mp_sub_d(&bigResult, 1, &bigResult) != MP_OKAY)
|| (mp_add(&bigRemainder, &big2, &bigRemainder) != MP_OKAY)) {
return OUT_OF_MEMORY;
}
}
err = mp_copy(&bigRemainder, &bigResult);
mp_clear(&bigRemainder);
mp_clear(&big1);
mp_clear(&big2);
if (err != MP_OKAY) {
return OUT_OF_MEMORY;
}
BIG_RESULT(&bigResult);
case INST_LSHIFT:
case INST_RSHIFT: {
/*
* Reject negative shift argument.
*/
|
| ︙ | ︙ | |||
7901 7902 7903 7904 7905 7906 7907 | } WIDE_RESULT(w1 >> shift); } } Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); | | > | | | | > > > > | > | | | | | | | | | | > > > > | 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 |
}
WIDE_RESULT(w1 >> shift);
}
}
Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
err = mp_init(&bigResult);
if (err == MP_OKAY) {
if (opcode == INST_LSHIFT) {
err = mp_mul_2d(&big1, shift, &bigResult);
} else {
err = mp_signed_rsh(&big1, shift, &bigResult);
}
}
if (err != MP_OKAY) {
return OUT_OF_MEMORY;
}
mp_clear(&big1);
BIG_RESULT(&bigResult);
}
case INST_BITOR:
case INST_BITXOR:
case INST_BITAND:
if ((type1 != TCL_NUMBER_INT) || (type2 != TCL_NUMBER_INT)) {
Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
err = mp_init(&bigResult);
if (err == MP_OKAY) {
switch (opcode) {
case INST_BITAND:
err = mp_and(&big1, &big2, &bigResult);
break;
case INST_BITOR:
err = mp_or(&big1, &big2, &bigResult);
break;
case INST_BITXOR:
err = mp_xor(&big1, &big2, &bigResult);
break;
}
}
if (err != MP_OKAY) {
return OUT_OF_MEMORY;
}
mp_clear(&big1);
mp_clear(&big2);
BIG_RESULT(&bigResult);
}
|
| ︙ | ︙ | |||
7994 7995 7996 7997 7998 7999 8000 |
}
negativeExponent = (w2 < 0);
oddExponent = (int) (w2 & (Tcl_WideInt)1);
} else {
Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
negativeExponent = mp_isneg(&big2);
| | | | 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 |
}
negativeExponent = (w2 < 0);
oddExponent = (int) (w2 & (Tcl_WideInt)1);
} else {
Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
negativeExponent = mp_isneg(&big2);
err = mp_mod_2d(&big2, 1, &big2);
oddExponent = (err == MP_OKAY) && !mp_iszero(&big2);
mp_clear(&big2);
}
if (type1 == TCL_NUMBER_INT) {
w1 = *((const Tcl_WideInt *)ptr1);
if (negativeExponent) {
|
| ︙ | ︙ | |||
8152 8153 8154 8155 8156 8157 8158 |
|| (value2Ptr->typePtr != &tclIntType)
|| (Tcl_WideUInt)w2 >= (1<<28)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"exponent too large", -1));
return GENERAL_ARITHMETIC_ERROR;
}
Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
| | > | > > > > | 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 |
|| (value2Ptr->typePtr != &tclIntType)
|| (Tcl_WideUInt)w2 >= (1<<28)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"exponent too large", -1));
return GENERAL_ARITHMETIC_ERROR;
}
Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
err = mp_init(&bigResult);
if (err == MP_OKAY) {
err = mp_expt_u32(&big1, (unsigned int)w2, &bigResult);
}
if (err != MP_OKAY) {
return OUT_OF_MEMORY;
}
mp_clear(&big1);
BIG_RESULT(&bigResult);
}
case INST_ADD:
case INST_SUB:
case INST_MULT:
|
| ︙ | ︙ | |||
8300 8301 8302 8303 8304 8305 8306 |
WIDE_RESULT(wResult);
}
overflowBasic:
Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
| | > | | | | | | | | | | | | | > | > | | | | | | | > | | > | | > > | > | > > > > | > > > | > > > | 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 |
WIDE_RESULT(wResult);
}
overflowBasic:
Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
err = mp_init(&bigResult);
if (err == MP_OKAY) {
switch (opcode) {
case INST_ADD:
err = mp_add(&big1, &big2, &bigResult);
break;
case INST_SUB:
err = mp_sub(&big1, &big2, &bigResult);
break;
case INST_MULT:
err = mp_mul(&big1, &big2, &bigResult);
break;
case INST_DIV:
if (mp_iszero(&big2)) {
mp_clear(&big1);
mp_clear(&big2);
mp_clear(&bigResult);
return DIVIDED_BY_ZERO;
}
err = mp_init(&bigRemainder);
if (err == MP_OKAY) {
err = mp_div(&big1, &big2, &bigResult, &bigRemainder);
}
/* TODO: internals intrusion */
if (!mp_iszero(&bigRemainder)
&& (bigRemainder.sign != big2.sign)) {
/*
* Convert to Tcl's integer division rules.
*/
err = mp_sub_d(&bigResult, 1, &bigResult);
if (err == MP_OKAY) {
err = mp_add(&bigRemainder, &big2, &bigRemainder);
}
}
mp_clear(&bigRemainder);
break;
}
}
mp_clear(&big1);
mp_clear(&big2);
BIG_RESULT(&bigResult);
}
Tcl_Panic("unexpected opcode");
return NULL;
}
static Tcl_Obj *
ExecuteExtendedUnaryMathOp(
int opcode, /* What operation to perform. */
Tcl_Obj *valuePtr) /* The operand on the stack. */
{
ClientData ptr;
int type;
Tcl_WideInt w;
mp_int big;
Tcl_Obj *objResultPtr;
mp_err err = MP_OKAY;
(void) GetNumberFromObj(NULL, valuePtr, &ptr, &type);
switch (opcode) {
case INST_BITNOT:
if (type == TCL_NUMBER_INT) {
w = *((const Tcl_WideInt *) ptr);
WIDE_RESULT(~w);
}
Tcl_TakeBignumFromObj(NULL, valuePtr, &big);
/* ~a = - a - 1 */
err = mp_neg(&big, &big);
if (err == MP_OKAY) {
err = mp_sub_d(&big, 1, &big);
}
if (err != MP_OKAY) {
return OUT_OF_MEMORY;
}
BIG_RESULT(&big);
case INST_UMINUS:
switch (type) {
case TCL_NUMBER_DOUBLE:
DOUBLE_RESULT(-(*((const double *) ptr)));
case TCL_NUMBER_INT:
w = *((const Tcl_WideInt *) ptr);
if (w != WIDE_MIN) {
WIDE_RESULT(-w);
}
err = mp_init_i64(&big, w);
if (err != MP_OKAY) {
return OUT_OF_MEMORY;
}
break;
default:
Tcl_TakeBignumFromObj(NULL, valuePtr, &big);
}
err = mp_neg(&big, &big);
if (err != MP_OKAY) {
return OUT_OF_MEMORY;
}
BIG_RESULT(&big);
}
Tcl_Panic("unexpected opcode");
return NULL;
}
#undef WIDE_RESULT
|
| ︙ | ︙ |
Changes to generic/tclObj.c.
| ︙ | ︙ | |||
178 179 180 181 182 183 184 |
#define PACK_BIGNUM(bignum, objPtr) \
if ((bignum).used > 0x7fff) { \
mp_int *temp = (void *) Tcl_Alloc(sizeof(mp_int)); \
*temp = bignum; \
(objPtr)->internalRep.twoPtrValue.ptr1 = temp; \
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \
| < < | < | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
#define PACK_BIGNUM(bignum, objPtr) \
if ((bignum).used > 0x7fff) { \
mp_int *temp = (void *) Tcl_Alloc(sizeof(mp_int)); \
*temp = bignum; \
(objPtr)->internalRep.twoPtrValue.ptr1 = temp; \
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \
} else if (((bignum).alloc <= 0x7fff) || (mp_shrink(&(bignum))) == MP_OKAY) { \
(objPtr)->internalRep.twoPtrValue.ptr1 = (bignum).dp; \
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR( ((bignum).sign << 30) \
| ((bignum).alloc << 15) | ((bignum).used)); \
}
/*
* Prototypes for functions defined later in this file:
|
| ︙ | ︙ | |||
2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 |
TclGetString(objPtr)));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
}
return TCL_ERROR;
}
if (objPtr->typePtr == &tclBignumType) {
mp_int big;
Tcl_WideUInt value = 0, scratch;
size_t numBytes;
unsigned char *bytes = (unsigned char *) &scratch;
Tcl_GetBignumFromObj(NULL, objPtr, &big);
| > | > | > > > > | 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 |
TclGetString(objPtr)));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
}
return TCL_ERROR;
}
if (objPtr->typePtr == &tclBignumType) {
mp_int big;
mp_err err;
Tcl_WideUInt value = 0, scratch;
size_t numBytes;
unsigned char *bytes = (unsigned char *) &scratch;
Tcl_GetBignumFromObj(NULL, objPtr, &big);
err = mp_mod_2d(&big, (int) (CHAR_BIT * sizeof(Tcl_WideInt)), &big);
if (err == MP_OKAY) {
err = mp_to_ubin(&big, bytes, sizeof(Tcl_WideInt), &numBytes);
}
if (err != MP_OKAY) {
return TCL_ERROR;
}
while (numBytes-- > 0) {
value = (value << CHAR_BIT) | *bytes++;
}
*wideIntPtr = !big.sign ? (Tcl_WideInt)value : -(Tcl_WideInt)value;
mp_clear(&big);
return TCL_OK;
}
|
| ︙ | ︙ | |||
3133 3134 3135 3136 3137 3138 3139 |
{
do {
if (objPtr->typePtr == &tclBignumType) {
if (copy || Tcl_IsShared(objPtr)) {
mp_int temp;
TclUnpackBignum(objPtr, temp);
| | > > | | > > | 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 |
{
do {
if (objPtr->typePtr == &tclBignumType) {
if (copy || Tcl_IsShared(objPtr)) {
mp_int temp;
TclUnpackBignum(objPtr, temp);
if (mp_init_copy(bignumValue, &temp) != MP_OKAY) {
return TCL_ERROR;
}
} else {
TclUnpackBignum(objPtr, *bignumValue);
/* Optimized TclFreeIntRep */
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = NULL;
/*
* TODO: If objPtr has a string rep, this leaves
* it undisturbed. Not clear that's proper. Pure
* bignum values are converted to empty string.
*/
if (objPtr->bytes == NULL) {
TclInitStringRep(objPtr, NULL, 0);
}
}
return TCL_OK;
}
if (objPtr->typePtr == &tclIntType) {
if (mp_init_i64(bignumValue,
objPtr->internalRep.wideValue) != MP_OKAY) {
return TCL_ERROR;
}
return TCL_OK;
}
if (objPtr->typePtr == &tclDoubleType) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected integer but got \"%s\"",
TclGetString(objPtr)));
|
| ︙ | ︙ |
Changes to generic/tclStrToD.c.
| ︙ | ︙ | |||
299 300 301 302 303 304 305 | Tcl_WideUInt significand, int nSigDigs, long exponent); #ifdef IEEE_FLOATING_POINT static double MakeNaN(int signum, Tcl_WideUInt tag); #endif static double RefineApproximation(double approx, mp_int *exactSignificand, int exponent); | | | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | Tcl_WideUInt significand, int nSigDigs, long exponent); #ifdef IEEE_FLOATING_POINT static double MakeNaN(int signum, Tcl_WideUInt tag); #endif static double RefineApproximation(double approx, mp_int *exactSignificand, int exponent); static mp_err MulPow5(mp_int *, unsigned, mp_int *) MP_WUR; static int NormalizeRightward(Tcl_WideUInt *); static int RequiredPrecision(Tcl_WideUInt); static void DoubleToExpAndSig(double, Tcl_WideUInt *, int *, int *); static void TakeAbsoluteValue(Double *, int *); static char * FormatInfAndNaN(Double *, int *, char **); static char * FormatZero(int *, char **); |
| ︙ | ︙ | |||
529 530 531 532 533 534 535 536 537 538 539 540 541 542 |
* an acceptable number. */
size_t acceptLen; /* Number of characters following that
* point. */
int status = TCL_OK; /* Status to return to caller. */
char d = 0; /* Last hexadecimal digit scanned; initialized
* to avoid a compiler warning. */
int shift = 0; /* Amount to shift when accumulating binary */
#define ALL_BITS ((Tcl_WideUInt)-1)
#define MOST_BITS (ALL_BITS >> 1)
/*
* Initialize bytes to start of the object's string rep if the caller
* didn't pass anything else.
| > | 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 |
* an acceptable number. */
size_t acceptLen; /* Number of characters following that
* point. */
int status = TCL_OK; /* Status to return to caller. */
char d = 0; /* Last hexadecimal digit scanned; initialized
* to avoid a compiler warning. */
int shift = 0; /* Amount to shift when accumulating binary */
mp_err err = MP_OKAY;
#define ALL_BITS ((Tcl_WideUInt)-1)
#define MOST_BITS (ALL_BITS >> 1)
/*
* Initialize bytes to start of the object's string rep if the caller
* didn't pass anything else.
|
| ︙ | ︙ | |||
707 708 709 710 711 712 713 |
if ((octalSignificandWide != 0)
&& (((size_t)shift >=
CHAR_BIT*sizeof(Tcl_WideUInt))
|| (octalSignificandWide >
((Tcl_WideUInt)-1 >> shift)))) {
octalSignificandOverflow = 1;
| | > | | > > | | > > > > | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 |
if ((octalSignificandWide != 0)
&& (((size_t)shift >=
CHAR_BIT*sizeof(Tcl_WideUInt))
|| (octalSignificandWide >
((Tcl_WideUInt)-1 >> shift)))) {
octalSignificandOverflow = 1;
err = mp_init_u64(&octalSignificandBig,
octalSignificandWide);
}
}
if (!octalSignificandOverflow) {
octalSignificandWide =
(octalSignificandWide << shift) + (c - '0');
} else {
if (err == MP_OKAY) {
err = mp_mul_2d(&octalSignificandBig, shift,
&octalSignificandBig);
}
if (err == MP_OKAY) {
err = mp_add_d(&octalSignificandBig, (mp_digit)(c - '0'),
&octalSignificandBig);
}
}
if (err != MP_OKAY) {
return TCL_ERROR;
}
}
if (numSigDigs != 0) {
numSigDigs += numTrailZeros+1;
} else {
numSigDigs = 1;
}
|
| ︙ | ︙ | |||
772 773 774 775 776 777 778 |
* large shifts first.
*/
if (significandWide != 0 &&
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > ((Tcl_WideUInt)-1 >> shift))) {
significandOverflow = 1;
| | | | > | | > > > > | 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 |
* large shifts first.
*/
if (significandWide != 0 &&
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > ((Tcl_WideUInt)-1 >> shift))) {
significandOverflow = 1;
err = mp_init_u64(&significandBig,
significandWide);
}
}
if (!significandOverflow) {
significandWide = (significandWide << shift) + d;
} else if (err == MP_OKAY) {
err = mp_mul_2d(&significandBig, shift, &significandBig);
if (err == MP_OKAY) {
err = mp_add_d(&significandBig, (mp_digit) d, &significandBig);
}
}
}
if (err != MP_OKAY) {
return TCL_ERROR;
}
numTrailZeros = 0;
state = HEXADECIMAL;
break;
case BINARY:
acceptState = state;
|
| ︙ | ︙ | |||
814 815 816 817 818 819 820 |
* large shifts first.
*/
if (significandWide != 0 &&
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > ((Tcl_WideUInt)-1 >> shift))) {
significandOverflow = 1;
| | | | > | | > > > > | 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 |
* large shifts first.
*/
if (significandWide != 0 &&
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > ((Tcl_WideUInt)-1 >> shift))) {
significandOverflow = 1;
err = mp_init_u64(&significandBig,
significandWide);
}
}
if (!significandOverflow) {
significandWide = (significandWide << shift) + 1;
} else if (err == MP_OKAY) {
err = mp_mul_2d(&significandBig, shift, &significandBig);
if (err == MP_OKAY) {
err = mp_add_d(&significandBig, (mp_digit) 1, &significandBig);
}
}
}
if (err != MP_OKAY) {
return TCL_ERROR;
}
numTrailZeros = 0;
state = BINARY;
break;
case ZERO_D:
if (c == '0') {
|
| ︙ | ︙ | |||
1156 1157 1158 1159 1160 1161 1162 |
acceptState, bytes);
case BINARY:
shift = numTrailZeros;
if (!significandOverflow && significandWide != 0 &&
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > (MOST_BITS + signum) >> shift)) {
significandOverflow = 1;
| | | | > > > | | | > > > | | | | | | | > > > | | | | | | > > > | 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 |
acceptState, bytes);
case BINARY:
shift = numTrailZeros;
if (!significandOverflow && significandWide != 0 &&
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > (MOST_BITS + signum) >> shift)) {
significandOverflow = 1;
err = mp_init_u64(&significandBig, significandWide);
}
if (shift) {
if (!significandOverflow) {
significandWide <<= shift;
} else if (err == MP_OKAY) {
err = mp_mul_2d(&significandBig, shift, &significandBig);
}
}
if (err != MP_OKAY) {
return TCL_ERROR;
}
goto returnInteger;
case HEXADECIMAL:
/*
* Returning a hex integer. Final scaling step.
*/
shift = 4 * numTrailZeros;
if (!significandOverflow && significandWide !=0 &&
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > (MOST_BITS + signum) >> shift)) {
significandOverflow = 1;
err = mp_init_u64(&significandBig, significandWide);
}
if (shift) {
if (!significandOverflow) {
significandWide <<= shift;
} else if (err == MP_OKAY) {
err = mp_mul_2d(&significandBig, shift, &significandBig);
}
}
if (err != MP_OKAY) {
return TCL_ERROR;
}
goto returnInteger;
case OCTAL:
/*
* Returning an octal integer. Final scaling step.
*/
shift = 3 * numTrailZeros;
if (!octalSignificandOverflow && octalSignificandWide != 0 &&
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
octalSignificandWide > (MOST_BITS + signum) >> shift)) {
octalSignificandOverflow = 1;
err = mp_init_u64(&octalSignificandBig,
octalSignificandWide);
}
if (shift) {
if (!octalSignificandOverflow) {
octalSignificandWide <<= shift;
} else if (err == MP_OKAY) {
err = mp_mul_2d(&octalSignificandBig, shift,
&octalSignificandBig);
}
}
if (!octalSignificandOverflow) {
if ((err == MP_OKAY) && (octalSignificandWide > (MOST_BITS + signum))) {
err = mp_init_u64(&octalSignificandBig,
octalSignificandWide);
octalSignificandOverflow = 1;
} else {
objPtr->typePtr = &tclIntType;
if (signum) {
objPtr->internalRep.wideValue =
- (Tcl_WideInt) octalSignificandWide;
} else {
objPtr->internalRep.wideValue =
(Tcl_WideInt) octalSignificandWide;
}
}
}
if ((err == MP_OKAY) && octalSignificandOverflow) {
if (signum) {
err = mp_neg(&octalSignificandBig, &octalSignificandBig);
}
TclSetBignumIntRep(objPtr, &octalSignificandBig);
}
if (err != MP_OKAY) {
return TCL_ERROR;
}
break;
case ZERO:
case DECIMAL:
significandOverflow = AccumulateDecimalDigit(0, numTrailZeros-1,
&significandWide, &significandBig, significandOverflow);
if ((err == MP_OKAY) && !significandOverflow && (significandWide > MOST_BITS+signum)) {
significandOverflow = 1;
err = mp_init_u64(&significandBig, significandWide);
}
returnInteger:
if (!significandOverflow) {
if ((err == MP_OKAY) && (significandWide > MOST_BITS+signum)) {
err = mp_init_u64(&significandBig,
significandWide);
significandOverflow = 1;
} else {
objPtr->typePtr = &tclIntType;
if (signum) {
objPtr->internalRep.wideValue =
- (Tcl_WideInt) significandWide;
} else {
objPtr->internalRep.wideValue =
(Tcl_WideInt) significandWide;
}
}
}
if ((err == MP_OKAY) && significandOverflow) {
if (signum) {
err = mp_neg(&significandBig, &significandBig);
}
TclSetBignumIntRep(objPtr, &significandBig);
}
if (err != MP_OKAY) {
return TCL_ERROR;
}
break;
case FRACTION:
case EXPONENT:
/*
|
| ︙ | ︙ | |||
1425 1426 1427 1428 1429 1430 1431 |
} else if (numZeros >= maxpow10_wide
|| w > ((Tcl_WideUInt)-1-digit)/pow10_wide[numZeros+1]) {
/*
* Wide multiplication will overflow. Expand the number to a
* bignum and fall through into the bignum case.
*/
| | > > | | | > > | | | | | > | | > > | 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 |
} else if (numZeros >= maxpow10_wide
|| w > ((Tcl_WideUInt)-1-digit)/pow10_wide[numZeros+1]) {
/*
* Wide multiplication will overflow. Expand the number to a
* bignum and fall through into the bignum case.
*/
if (mp_init_u64(bignumRepPtr, w) != MP_OKAY) {
return 0;
}
} else {
/*
* Wide multiplication.
*/
*wideRepPtr = w * pow10_wide[numZeros+1] + digit;
return 0;
}
}
/*
* Bignum multiplication.
*/
if (numZeros < log10_DIGIT_MAX) {
/*
* Up to about 8 zeros - single digit multiplication.
*/
if ((mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[numZeros+1],
bignumRepPtr) != MP_OKAY)
|| (mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr) != MP_OKAY))
return 0;
} else {
mp_err err;
/*
* More than single digit multiplication. Multiply by the appropriate
* small powers of 5, and then shift. Large strings of zeroes are
* eaten 256 at a time; this is less efficient than it could be, but
* seems implausible. We presume that MP_DIGIT_BIT is at least 27. The
* first multiplication, by up to 10**7, is done with a one-DIGIT
* multiply (this presumes that MP_DIGIT_BIT >= 24).
*/
n = numZeros + 1;
err = mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr);
for (i = 3; (err == MP_OKAY) && (i <= 7); ++i) {
if (n & (1 << i)) {
err = mp_mul(bignumRepPtr, pow5+i, bignumRepPtr);
}
}
while ((err == MP_OKAY) && (n >= 256)) {
err = mp_mul(bignumRepPtr, pow5+8, bignumRepPtr);
n -= 256;
}
if ((err != MP_OKAY)
|| (mp_mul_2d(bignumRepPtr, (int)(numZeros+1)&~0x7, bignumRepPtr) != MP_OKAY)
|| (mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr) != MP_OKAY)) {
return 0;
}
}
return 1;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
1571 1572 1573 1574 1575 1576 1577 |
}
/*
* All the easy cases have failed. Promote ths significand to bignum and
* call MakeHighPrecisionDouble to do it the hard way.
*/
| | > > | 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 |
}
/*
* All the easy cases have failed. Promote ths significand to bignum and
* call MakeHighPrecisionDouble to do it the hard way.
*/
if (mp_init_u64(&significandBig, significand) != MP_OKAY) {
return 0.0;
}
retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs,
exponent);
mp_clear(&significandBig);
/*
* Come here to return the computed value.
*/
|
| ︙ | ︙ | |||
1620 1621 1622 1623 1624 1625 1626 |
MakeHighPrecisionDouble(
int signum, /* 1=negative, 0=nonnegative */
mp_int *significand, /* Exact significand of the number */
int numSigDigs, /* Number of significant digits */
long exponent) /* Power of 10 by which to multiply */
{
double retval;
| | | 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 |
MakeHighPrecisionDouble(
int signum, /* 1=negative, 0=nonnegative */
mp_int *significand, /* Exact significand of the number */
int numSigDigs, /* Number of significant digits */
long exponent) /* Power of 10 by which to multiply */
{
double retval;
int machexp = 0; /* Machine exponent of a power of 10. */
/*
* With gcc on x86, the floating point rounding mode is double-extended.
* This causes the result of double-precision calculations to be rounded
* twice: once to the precision of double-extended and then again to the
* precision of double. Double-rounding introduces gratuitous errors of 1
* ulp, so we need to change rounding mode to 53-bits.
|
| ︙ | ︙ | |||
1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 |
int rteExponent; /* Exponent of the round-to-even result */
int shift; /* Shift count for converting numerator
* and denominator of corrector to floating
* point */
Tcl_WideInt rteSigWide; /* Wide integer version of the significand
* for testing evenness */
int i;
/*
* The first approximation is always low. If we find that it's HUGE_VAL,
* we're done.
*/
if (approxResult == HUGE_VAL) {
| > | 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 |
int rteExponent; /* Exponent of the round-to-even result */
int shift; /* Shift count for converting numerator
* and denominator of corrector to floating
* point */
Tcl_WideInt rteSigWide; /* Wide integer version of the significand
* for testing evenness */
int i;
mp_err err = MP_OKAY;
/*
* The first approximation is always low. If we find that it's HUGE_VAL,
* we're done.
*/
if (approxResult == HUGE_VAL) {
|
| ︙ | ︙ | |||
1833 1834 1835 1836 1837 1838 1839 |
* Compute twoMv as 2*M*v, where v is the approximate value.
* This is done by bit-whacking to calculate 2**(M2+1)*significand,
* and then multiplying by 5**M5.
*/
msb = binExponent + M2; /* 1008 */
nDigits = msb / MP_DIGIT_BIT + 1;
| | > > | | > | > > > | | > | > > | > | | > > > > | | | > > > > > | 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 |
* Compute twoMv as 2*M*v, where v is the approximate value.
* This is done by bit-whacking to calculate 2**(M2+1)*significand,
* and then multiplying by 5**M5.
*/
msb = binExponent + M2; /* 1008 */
nDigits = msb / MP_DIGIT_BIT + 1;
if (mp_init_size(&twoMv, nDigits) != MP_OKAY) {
return approxResult;
}
i = (msb % MP_DIGIT_BIT + 1);
twoMv.used = nDigits;
significand *= SafeLdExp(1.0, i);
while (--nDigits >= 0) {
twoMv.dp[nDigits] = (mp_digit) significand;
significand -= (mp_digit) significand;
significand = SafeLdExp(significand, MP_DIGIT_BIT);
}
for (i = 0; i <= 8; ++i) {
if (M5 & (1 << i) && (mp_mul(&twoMv, pow5+i, &twoMv) != MP_OKAY)) {
mp_clear(&twoMv);
return approxResult;
}
}
/*
* Compute twoMd as 2*M*d, where d is the exact value.
* This is done by multiplying by 5**(M5+exponent) and then multiplying
* by 2**(M5+exponent+1), which is, of couse, a left shift.
*/
if (mp_init_copy(&twoMd, exactSignificand) != MP_OKAY) {
mp_clear(&twoMv);
return approxResult;
}
for (i = 0; (i <= 8); ++i) {
if ((M5 + exponent) & (1 << i)) {
err = mp_mul(&twoMd, pow5+i, &twoMd);
}
}
if (err == MP_OKAY) {
err = mp_mul_2d(&twoMd, M2+exponent+1, &twoMd);
}
/*
* Now let twoMd = twoMd - twoMv, the difference between the exact and
* approximate values.
*/
if (err == MP_OKAY) {
err = mp_sub(&twoMd, &twoMv, &twoMd);
}
/*
* The result, 2Mv-2Md, needs to be divided by 2M to yield a correction
* term. Because 2M may well overflow a double, we need to scale the
* denominator by a factor of 2**binExponent-mantBits. Place that factor
* times 1/2 ULP into twoMd.
*/
scale = binExponent - mantBits - 1;
mp_set_u64(&twoMv, 1);
for (i = 0; (i <= 8) && (err == MP_OKAY); ++i) {
if (M5 & (1 << i)) {
err = mp_mul(&twoMv, pow5+i, &twoMv);
}
}
multiplier = M2 + scale + 1;
if (err != MP_OKAY) {
mp_clear(&twoMd);
mp_clear(&twoMv);
return approxResult;
} else if (multiplier > 0) {
err = mp_mul_2d(&twoMv, multiplier, &twoMv);
} else if (multiplier < 0) {
err = mp_div_2d(&twoMv, -multiplier, &twoMv, NULL);
}
if (err != MP_OKAY) {
mp_clear(&twoMd);
mp_clear(&twoMv);
return approxResult;
}
/*
* Will the eventual correction term be less than, equal to, or
* greater than 1/2 ULP?
*/
|
| ︙ | ︙ | |||
1936 1937 1938 1939 1940 1941 1942 |
/*
* Reduce the numerator and denominator of the corrector term so that
* they will fit in the floating point precision.
*/
shift = mp_count_bits(&twoMv) - FP_PRECISION - 1;
if (shift > 0) {
| | > | > > > > > > | 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 |
/*
* Reduce the numerator and denominator of the corrector term so that
* they will fit in the floating point precision.
*/
shift = mp_count_bits(&twoMv) - FP_PRECISION - 1;
if (shift > 0) {
err = mp_div_2d(&twoMv, shift, &twoMv, NULL);
if (err == MP_OKAY) {
err = mp_div_2d(&twoMd, shift, &twoMd, NULL);
}
}
if (err != MP_OKAY) {
mp_clear(&twoMd);
mp_clear(&twoMv);
return approxResult;
}
/*
* Convert the numerator and denominator of the corrector term accurately
* to floating point numbers.
*/
|
| ︙ | ︙ | |||
1976 1977 1978 1979 1980 1981 1982 | * * Side effects: * Stores base*5**n in result. * *---------------------------------------------------------------------- */ | | > | | | | | > | 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 |
*
* Side effects:
* Stores base*5**n in result.
*
*----------------------------------------------------------------------
*/
static inline mp_err
MulPow5(
mp_int *base, /* Number to multiply. */
unsigned n, /* Power of 5 to multiply by. */
mp_int *result) /* Place to store the result. */
{
mp_int *p = base;
int n13 = n / 13;
int r = n % 13;
mp_err err = MP_OKAY;
if (r != 0) {
err = mp_mul_d(p, dpow5[r], result);
p = result;
}
r = 0;
while ((err == MP_OKAY) && (n13 != 0)) {
if (n13 & 1) {
err = mp_mul(p, pow5_13+r, result);
p = result;
}
n13 >>= 1;
++r;
}
if ((err == MP_OKAY) && (p != result)) {
err = mp_copy(p, result);
}
return err;
}
/*
*----------------------------------------------------------------------
*
* NormalizeRightward --
*
|
| ︙ | ︙ | |||
3201 3202 3203 3204 3205 3206 3207 |
/*
* Compare B and S-m - which is the same as comparing B+m and S - which we
* do by computing b+m and doing a bitwhack compare against
* 2**(MP_DIGIT_BIT*sd)
*/
| < | | 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 |
/*
* Compare B and S-m - which is the same as comparing B+m and S - which we
* do by computing b+m and doing a bitwhack compare against
* 2**(MP_DIGIT_BIT*sd)
*/
if ((mp_add(b, m, temp) != MP_OKAY) || (temp->used <= sd)) { /* Too few digits to be > s */
return 0;
}
if (temp->used > sd+1 || temp->dp[sd] > 1) {
/* >= 2s */
return 1;
}
for (i = sd-1; i >= 0; --i) {
|
| ︙ | ︙ | |||
3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 |
* converted. */
mp_int mplus, mminus; /* Bounds for roundoff. */
mp_digit digit; /* Current output digit. */
char *s = retval; /* Cursor in the output buffer. */
int i; /* Index in the output buffer. */
mp_int temp;
int r1;
/*
* b = bw * 2**b2 * 5**b5
* mminus = 5**m5
*/
| > | > > | > > > | > | > | | > | > > | > | | > | | > > | > | 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 |
* converted. */
mp_int mplus, mminus; /* Bounds for roundoff. */
mp_digit digit; /* Current output digit. */
char *s = retval; /* Cursor in the output buffer. */
int i; /* Index in the output buffer. */
mp_int temp;
int r1;
mp_err err = MP_OKAY;
/*
* b = bw * 2**b2 * 5**b5
* mminus = 5**m5
*/
if ((retval == NULL) || (mp_init_u64(&b, bw) != MP_OKAY)) {
return NULL;
}
if (mp_init_set(&mminus, 1) != MP_OKAY) {
mp_clear(&b);
return NULL;
}
err = MulPow5(&b, b5, &b);
if (err == MP_OKAY) {
err = mp_mul_2d(&b, b2, &b);
}
/*
* Adjust if the logarithm was guessed wrong.
*/
if ((err == MP_OKAY) && (b.used <= sd)) {
err = mp_mul_d(&b, 10, &b);
++m2plus; ++m2minus; ++m5;
ilim = ilim1;
--k;
}
/*
* mminus = 5**m5 * 2**m2minus
* mplus = 5**m5 * 2**m2plus
*/
if (err == MP_OKAY) {
err = mp_mul_2d(&mminus, m2minus, &mminus);
}
if (err == MP_OKAY) {
err = MulPow5(&mminus, m5, &mminus);
}
if ((err == MP_OKAY) && (m2plus > m2minus)) {
err = mp_init_copy(&mplus, &mminus);
if (err == MP_OKAY) {
err = mp_mul_2d(&mplus, m2plus-m2minus, &mplus);
}
}
if (err == MP_OKAY) {
err = mp_init(&temp);
}
/*
* Loop through the digits. Do division and mod by s == 2**(sd*MP_DIGIT_BIT)
* by mp_digit extraction.
*/
i = 0;
|
| ︙ | ︙ | |||
3385 3386 3387 3388 3389 3390 3391 | break; } /* * Advance to the next digit. */ | > | > > | > | | | | 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 |
break;
}
/*
* Advance to the next digit.
*/
if (err == MP_OKAY) {
err = mp_mul_d(&b, 10, &b);
}
if (err == MP_OKAY) {
err = mp_mul_d(&mminus, 10, &mminus);
}
if ((err == MP_OKAY) && (m2plus > m2minus)) {
err = mp_mul_2d(&mminus, m2plus-m2minus, &mplus);
}
++i;
}
/*
* Endgame - store the location of the decimal point and the end of the
* string.
*/
if (m2plus > m2minus) {
mp_clear(&mplus);
}
mp_clear_multi(&b, &mminus, &temp, NULL);
*s = '\0';
*decpt = k;
if (endPtr) {
*endPtr = s;
}
return (err == MP_OKAY) ? retval : NULL;
}
/*
*----------------------------------------------------------------------
*
* StrictBignumConversionPowD --
*
|
| ︙ | ︙ | |||
3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 |
char *retval = Tcl_Alloc(len + 1);
/* Output buffer. */
mp_int b; /* Numerator of the fraction being
* converted. */
mp_digit digit; /* Current output digit. */
char *s = retval; /* Cursor in the output buffer. */
int i; /* Index in the output buffer. */
/*
* b = bw * 2**b2 * 5**b5
*/
| > | > > | > | > | | | | 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 |
char *retval = Tcl_Alloc(len + 1);
/* Output buffer. */
mp_int b; /* Numerator of the fraction being
* converted. */
mp_digit digit; /* Current output digit. */
char *s = retval; /* Cursor in the output buffer. */
int i; /* Index in the output buffer. */
mp_err err;
/*
* b = bw * 2**b2 * 5**b5
*/
if (mp_init_u64(&b, bw) != MP_OKAY) {
return NULL;
}
err = MulPow5(&b, b5, &b);
if (err == MP_OKAY) {
err = mp_mul_2d(&b, b2, &b);
}
/*
* Adjust if the logarithm was guessed wrong.
*/
if ((err == MP_OKAY) && (b.used <= sd)) {
err = mp_mul_d(&b, 10, &b);
ilim = ilim1;
--k;
}
/*
* Loop through the digits. Do division and mod by s == 2**(sd*MP_DIGIT_BIT)
* by mp_digit extraction.
*/
i = 1;
while (err == MP_OKAY) {
if (b.used <= sd) {
digit = 0;
} else {
digit = b.dp[sd];
if (b.used > sd+1 || digit >= 10) {
Tcl_Panic("wrong digit!");
}
|
| ︙ | ︙ | |||
3512 3513 3514 3515 3516 3517 3518 | break; } /* * Advance to the next digit. */ | | | 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 |
break;
}
/*
* Advance to the next digit.
*/
err = mp_mul_d(&b, 10, &b);
++i;
}
/*
* Endgame - store the location of the decimal point and the end of the
* string.
*/
|
| ︙ | ︙ | |||
3594 3595 3596 3597 3598 3599 3600 |
int r;
mp_int temp;
/*
* Compare b and S-m: this is the same as comparing B+m and S.
*/
| | | > | 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 |
int r;
mp_int temp;
/*
* Compare b and S-m: this is the same as comparing B+m and S.
*/
if ((mp_init(&temp) != MP_OKAY) || (mp_add(b, m, &temp) != MP_OKAY)) {
return 0;
}
r = mp_cmp_mag(&temp, S);
mp_clear(&temp);
switch(r) {
case MP_LT:
return 0;
case MP_EQ:
return isodd;
|
| ︙ | ︙ | |||
3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 |
mp_int mplus; /* 1/2 ulp above the result. */
mp_int S; /* Denominator of the result. */
mp_int dig; /* Current digit of the result. */
int digit; /* Current digit of the result. */
int minit = 1; /* Fudge factor for when we misguess k. */
int i;
int r1;
/*
* b = bw * 2**b2 * 5**b5
* S = 2**s2 * 5*s5
*/
| > | > > | > | > > > > > | > | | > | > > | > | | > | > > | > | | | | 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 |
mp_int mplus; /* 1/2 ulp above the result. */
mp_int S; /* Denominator of the result. */
mp_int dig; /* Current digit of the result. */
int digit; /* Current digit of the result. */
int minit = 1; /* Fudge factor for when we misguess k. */
int i;
int r1;
mp_err err;
/*
* b = bw * 2**b2 * 5**b5
* S = 2**s2 * 5*s5
*/
if ((retval == NULL) || (mp_init_u64(&b, bw) != MP_OKAY)) {
return NULL;
}
err = mp_mul_2d(&b, b2, &b);
if (err == MP_OKAY) {
err = mp_init_set(&S, 1);
}
if (err == MP_OKAY) {
err = MulPow5(&S, s5, &S);
}
if (err == MP_OKAY) {
err = mp_mul_2d(&S, s2, &S);
}
/*
* Handle the case where we guess the position of the decimal point wrong.
*/
if ((err == MP_OKAY) && (mp_cmp_mag(&b, &S) == MP_LT)) {
err = mp_mul_d(&b, 10, &b);
minit = 10;
ilim =ilim1;
--k;
}
/*
* mminus = 2**m2minus * 5**m5
*/
if (err == MP_OKAY) {
err = mp_init_set(&mminus, minit);
}
if (err == MP_OKAY) {
err = mp_mul_2d(&mminus, m2minus, &mminus);
}
if ((err == MP_OKAY) && (m2plus > m2minus)) {
err = mp_init_copy(&mplus, &mminus);
if (err == MP_OKAY) {
err = mp_mul_2d(&mplus, m2plus-m2minus, &mplus);
}
}
/*
* Loop through the digits.
*/
if (err == MP_OKAY) {
err = mp_init(&dig);
}
i = 1;
while (err == MP_OKAY) {
err = mp_div(&b, &S, &dig, &b);
if (dig.used > 1 || dig.dp[0] >= 10) {
Tcl_Panic("wrong digit!");
}
digit = dig.dp[0];
/*
* Does the current digit leave us with a remainder small enough to
* round to it?
*/
r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus);
if (r1 == MP_LT || (r1 == MP_EQ && (dPtr->w.word1 & 1) == 0)) {
err = mp_mul_2d(&b, 1, &b);
if (ShouldBankerRoundUp(&b, &S, digit&1)) {
++digit;
if (digit == 10) {
*s++ = '9';
s = BumpUp(s, retval, &k);
break;
}
|
| ︙ | ︙ | |||
3742 3743 3744 3745 3746 3747 3748 | } /* * Have we converted all the requested digits? */ *s++ = '0' + digit; | | | | | > | > | | > | > | 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 |
}
/*
* Have we converted all the requested digits?
*/
*s++ = '0' + digit;
if ((err == MP_OKAY) && (i == ilim)) {
err = mp_mul_2d(&b, 1, &b);
if (ShouldBankerRoundUp(&b, &S, digit&1)) {
s = BumpUp(s, retval, &k);
}
break;
}
/*
* Advance to the next digit.
*/
if ((err == MP_OKAY) && (s5 > 0)) {
/*
* Can possibly shorten the denominator.
*/
err = mp_mul_2d(&b, 1, &b);
if (err == MP_OKAY) {
err = mp_mul_2d(&mminus, 1, &mminus);
}
if ((err == MP_OKAY) && (m2plus > m2minus)) {
err = mp_mul_2d(&mplus, 1, &mplus);
}
if (err == MP_OKAY) {
err = mp_div_d(&S, 5, &S, NULL);
}
--s5;
/*
* IDEA: It might possibly be a win to fall back to int64_t
* arithmetic here if S < 2**64/10. But it's a win only for
* a fairly narrow range of magnitudes so perhaps not worth
* bothering. We already know that we shorten the
|
| ︙ | ︙ | |||
3794 3795 3796 3797 3798 3799 3800 | * 10**38 12 trips * 10**39 13 trips * 10**40 14 trips * 10**41 15 trips * 10**42 16 trips * thereafter no gain. */ | | | > | > | | | 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 |
* 10**38 12 trips
* 10**39 13 trips
* 10**40 14 trips
* 10**41 15 trips
* 10**42 16 trips
* thereafter no gain.
*/
} else if (err == MP_OKAY) {
err = mp_mul_d(&b, 10, &b);
if (err == MP_OKAY) {
err = mp_mul_d(&mminus, 10, &mminus);
}
if ((err == MP_OKAY) && (m2plus > m2minus)) {
err = mp_mul_2d(&mplus, 10, &mplus);
}
}
++i;
}
/*
|
| ︙ | ︙ | |||
3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 |
char *s = retval; /* Cursor in the return value. */
mp_int b; /* Numerator of the result. */
mp_int S; /* Denominator of the result. */
mp_int dig; /* Current digit of the result. */
int digit; /* Current digit of the result. */
int g; /* Size of the current digit ground. */
int i, j;
/*
* b = bw * 2**b2 * 5**b5
* S = 2**s2 * 5*s5
*/
| > > | > | > > > | > | > > > > | > > | < | < | | | | > | > | > | > | | < | | 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 |
char *s = retval; /* Cursor in the return value. */
mp_int b; /* Numerator of the result. */
mp_int S; /* Denominator of the result. */
mp_int dig; /* Current digit of the result. */
int digit; /* Current digit of the result. */
int g; /* Size of the current digit ground. */
int i, j;
mp_err err;
/*
* b = bw * 2**b2 * 5**b5
* S = 2**s2 * 5*s5
*/
if (mp_init(&dig) != MP_OKAY) {
return NULL;
}
if (mp_init_u64(&b, bw) != MP_OKAY) {
mp_clear(&dig);
return NULL;
}
err = mp_mul_2d(&b, b2, &b);
if (err == MP_OKAY) {
err = mp_init_set(&S, 1);
}
if (err == MP_OKAY) {
err = MulPow5(&S, s5, &S);
if (err == MP_OKAY) {
err = mp_mul_2d(&S, s2, &S);
}
}
/*
* Handle the case where we guess the position of the decimal point wrong.
*/
if ((mp_cmp_mag(&b, &S) == MP_LT) && (mp_mul_d(&b, 10, &b) == MP_OKAY)) {
ilim =ilim1;
--k;
}
/*
* Convert the leading digit.
*/
i = 0;
err = mp_div(&b, &S, &dig, &b);
if (dig.used > 1 || dig.dp[0] >= 10) {
Tcl_Panic("wrong digit!");
}
digit = dig.dp[0];
/*
* Is a single digit all that was requested?
*/
*s++ = '0' + digit;
if (++i >= ilim) {
if ((mp_mul_2d(&b, 1, &b) == MP_OKAY) && ShouldBankerRoundUp(&b, &S, digit&1)) {
s = BumpUp(s, retval, &k);
}
} else {
while (err == MP_OKAY) {
/*
* Shift by a group of digits.
*/
g = ilim - i;
if (g > DIGIT_GROUP) {
g = DIGIT_GROUP;
}
if (s5 >= g) {
err = mp_div_d(&S, dpow5[g], &S, NULL);
s5 -= g;
} else if (s5 > 0) {
err = mp_div_d(&S, dpow5[s5], &S, NULL);
if (err == MP_OKAY) {
err = mp_mul_d(&b, dpow5[g - s5], &b);
}
s5 = 0;
} else {
err = mp_mul_d(&b, dpow5[g], &b);
}
if (err == MP_OKAY) {
err = mp_mul_2d(&b, g, &b);
}
/*
* As with the shortening bignum conversion, it's possible at this
* point that we will have reduced the denominator to less than
* 2**64/10, at which point it would be possible to fall back to
* to int64_t arithmetic. But the potential payoff is tremendously
* less - unless we're working in F format - because we know that
* three groups of digits will always suffice for %#.17e, the
* longest format that doesn't introduce empty precision.
*
* Extract the next group of digits.
*/
if ((err != MP_OKAY) || (mp_div(&b, &S, &dig, &b) != MP_OKAY) || (dig.used > 1)) {
Tcl_Panic("wrong digit!");
}
digit = dig.dp[0];
for (j = g-1; j >= 0; --j) {
int t = itens[j];
*s++ = digit / t + '0';
digit %= t;
}
i += g;
/*
* Have we converted all the requested digits?
*/
if (i == ilim) {
if ((mp_mul_2d(&b, 1, &b) == MP_OKAY) && ShouldBankerRoundUp(&b, &S, digit&1)) {
s = BumpUp(s, retval, &k);
}
break;
}
}
}
while (*--s == '0') {
|
| ︙ | ︙ | |||
4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 |
double d;
#ifdef IEEE_FLOATING_POINT
union {
double dv;
Tcl_WideUInt iv;
} bitwhack;
#endif
#if defined(__sgi) && defined(_COMPILER_VERSION)
union fpc_csr mipsCR;
mipsCR.fc_word = get_fpc_csr();
mipsCR.fc_struct.flush = 0;
set_fpc_csr(mipsCR.fc_word);
#endif
| > | 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 |
double d;
#ifdef IEEE_FLOATING_POINT
union {
double dv;
Tcl_WideUInt iv;
} bitwhack;
#endif
mp_err err = MP_OKAY;
#if defined(__sgi) && defined(_COMPILER_VERSION)
union fpc_csr mipsCR;
mipsCR.fc_word = get_fpc_csr();
mipsCR.fc_struct.flush = 0;
set_fpc_csr(mipsCR.fc_word);
#endif
|
| ︙ | ︙ | |||
4388 4389 4390 4391 4392 4393 4394 |
}
/*
* Initialize a table of large powers of five.
*/
for (i=0; i<9; ++i) {
| | | | | | > > > | 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 |
}
/*
* Initialize a table of large powers of five.
*/
for (i=0; i<9; ++i) {
err = err || mp_init(pow5 + i);
}
mp_set_u64(pow5, 5);
for (i=0; i<8; ++i) {
err = err || mp_sqr(pow5+i, pow5+i+1);
}
err = err || mp_init_u64(pow5_13, 1220703125);
for (i = 1; i < 5; ++i) {
err = err || mp_init(pow5_13 + i);
err = err || mp_sqr(pow5_13 + i - 1, pow5_13 + i);
}
if (err != MP_OKAY) {
Tcl_Panic("out of memory");
}
/*
* Determine the number of decimal digits to the left and right of the
* decimal point in the largest and smallest double, the smallest double
* that differs from zero, and the number of mp_digits needed to represent
* the significand of a double.
|
| ︙ | ︙ | |||
4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 |
Tcl_InitBignumFromDouble(
Tcl_Interp *interp, /* For error message. */
double d, /* Number to convert. */
mp_int *b) /* Place to store the result. */
{
double fract;
int expt;
/*
* Infinite values can't convert to bignum.
*/
if (TclIsInfinite(d)) {
if (interp != NULL) {
const char *s = "integer value too large to represent";
Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
}
return TCL_ERROR;
}
fract = frexp(d, &expt);
if (expt <= 0) {
| > | | > > | | | > > > | 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 |
Tcl_InitBignumFromDouble(
Tcl_Interp *interp, /* For error message. */
double d, /* Number to convert. */
mp_int *b) /* Place to store the result. */
{
double fract;
int expt;
mp_err err;
/*
* Infinite values can't convert to bignum.
*/
if (TclIsInfinite(d)) {
if (interp != NULL) {
const char *s = "integer value too large to represent";
Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
}
return TCL_ERROR;
}
fract = frexp(d, &expt);
if (expt <= 0) {
err = mp_init(b);
mp_zero(b);
} else {
Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits);
int shift = expt - mantBits;
err = mp_init_i64(b, w);
if (err != MP_OKAY) {
/* just skip */
} else if (shift < 0) {
err = mp_div_2d(b, -shift, b, NULL);
} else if (shift > 0) {
err = mp_mul_2d(b, shift, b);
}
}
if (err != MP_OKAY) {
return TCL_ERROR;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 |
double
TclBignumToDouble(
const mp_int *a) /* Integer to convert. */
{
mp_int b;
int bits, shift, i, lsb;
double r;
/*
* We need a 'mantBits'-bit significand. Determine what shift will
* give us that.
*/
| > | 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 |
double
TclBignumToDouble(
const mp_int *a) /* Integer to convert. */
{
mp_int b;
int bits, shift, i, lsb;
double r;
mp_err err;
/*
* We need a 'mantBits'-bit significand. Determine what shift will
* give us that.
*/
|
| ︙ | ︙ | |||
4572 4573 4574 4575 4576 4577 4578 |
* in length. If shift < 0, we will need to shift the significand right
* by the requisite number of bits, and round it. If the '1-shift'
* least significant bits are 0, but the 'shift'th bit is nonzero,
* then the significand lies exactly between two values and must be
* 'rounded to even'.
*/
| | > > | | | | | | | | > > | | | | > > > | | 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 |
* in length. If shift < 0, we will need to shift the significand right
* by the requisite number of bits, and round it. If the '1-shift'
* least significant bits are 0, but the 'shift'th bit is nonzero,
* then the significand lies exactly between two values and must be
* 'rounded to even'.
*/
err = mp_init(&b);
if (err != MP_OKAY) {
/* just skip */
} else if (shift == 0) {
err = mp_copy(a, &b);
} else if (shift > 0) {
err = mp_mul_2d(a, shift, &b);
} else if (shift < 0) {
lsb = mp_cnt_lsb(a);
if (lsb == -1-shift) {
/*
* Round to even
*/
err = mp_div_2d(a, -shift, &b, NULL);
if ((err == MP_OKAY) && mp_isodd(&b)) {
if (mp_isneg(&b)) {
err = mp_sub_d(&b, 1, &b);
} else {
err = mp_add_d(&b, 1, &b);
}
}
} else {
/*
* Ordinary rounding
*/
err = mp_div_2d(a, -1-shift, &b, NULL);
if (err != MP_OKAY) {
/* just skip */
} else if (mp_isneg(&b)) {
err = mp_sub_d(&b, 1, &b);
} else {
err = mp_add_d(&b, 1, &b);
}
err = mp_div_2d(&b, 1, &b, NULL);
}
}
/*
* Accumulate the result, one mp_digit at a time.
*/
if (err != MP_OKAY) {
return 0.0;
}
r = 0.0;
for (i = b.used-1; i>=0; --i) {
r = ldexp(r, MP_DIGIT_BIT) + b.dp[i];
}
mp_clear(&b);
/*
* Scale the result to the correct number of bits.
*/
|
| ︙ | ︙ | |||
4656 4657 4658 4659 4660 4661 4662 4663 |
double
TclCeil(
const mp_int *a) /* Integer to convert. */
{
double r = 0.0;
mp_int b;
| > | | | > > | | | > | > | | | > > > | 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 |
double
TclCeil(
const mp_int *a) /* Integer to convert. */
{
double r = 0.0;
mp_int b;
mp_err err;
err = mp_init(&b);
if ((err == MP_OKAY) && mp_isneg(a)) {
err = mp_neg(a, &b);
r = -TclFloor(&b);
} else {
int bits = mp_count_bits(a);
if (bits > DBL_MAX_EXP*log2FLT_RADIX) {
r = HUGE_VAL;
} else {
int i, exact = 1, shift = mantBits - bits;
if (err != MP_OKAY) {
/* just skip */
} else if (shift > 0) {
err = mp_mul_2d(a, shift, &b);
} else if (shift < 0) {
mp_int d;
err = mp_init(&d);
if (err == MP_OKAY) {
err = mp_div_2d(a, -shift, &b, &d);
}
exact = mp_iszero(&d);
mp_clear(&d);
} else {
err = mp_copy(a, &b);
}
if ((err == MP_OKAY) && !exact) {
err = mp_add_d(&b, 1, &b);
}
if (err != MP_OKAY) {
return 0.0;
}
for (i=b.used-1 ; i>=0 ; --i) {
r = ldexp(r, MP_DIGIT_BIT) + b.dp[i];
}
r = ldexp(r, bits - mantBits);
}
}
|
| ︙ | ︙ | |||
4713 4714 4715 4716 4717 4718 4719 4720 |
double
TclFloor(
const mp_int *a) /* Integer to convert. */
{
double r = 0.0;
mp_int b;
| > | | | | | | > > > | 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 |
double
TclFloor(
const mp_int *a) /* Integer to convert. */
{
double r = 0.0;
mp_int b;
mp_err err;
err = mp_init(&b);
if ((err == MP_OKAY) && mp_isneg(a)) {
err = mp_neg(a, &b);
r = -TclCeil(&b);
} else {
int bits = mp_count_bits(a);
if (bits > DBL_MAX_EXP*log2FLT_RADIX) {
r = DBL_MAX;
} else {
int i, shift = mantBits - bits;
if (shift > 0) {
err = mp_mul_2d(a, shift, &b);
} else if (shift < 0) {
err = mp_div_2d(a, -shift, &b, NULL);
} else {
err = mp_copy(a, &b);
}
if (err != MP_OKAY) {
return 0.0;
}
for (i=b.used-1 ; i>=0 ; --i) {
r = ldexp(r, MP_DIGIT_BIT) + b.dp[i];
}
r = ldexp(r, bits - mantBits);
}
}
|
| ︙ | ︙ | |||
4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 |
int *machexp) /* Power of two. */
{
mp_int b;
int bits;
int shift;
int i;
double r;
/*
* Determine how many bits we need, and extract that many from the input.
* Round to nearest unit in the last place.
*/
bits = mp_count_bits(a);
shift = mantBits - 2 - bits;
| > | > > | | | > | | > | 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 |
int *machexp) /* Power of two. */
{
mp_int b;
int bits;
int shift;
int i;
double r;
mp_err err = MP_OKAY;
/*
* Determine how many bits we need, and extract that many from the input.
* Round to nearest unit in the last place.
*/
bits = mp_count_bits(a);
shift = mantBits - 2 - bits;
if (mp_init(&b)) {
return 0.0;
}
if (shift > 0) {
err = mp_mul_2d(a, shift, &b);
} else if (shift < 0) {
err = mp_div_2d(a, -shift, &b, NULL);
} else {
err = mp_copy(a, &b);
}
/*
* Accumulate the result, one mp_digit at a time.
*/
r = 0.0;
if (err == MP_OKAY) {
for (i=b.used-1; i>=0; --i) {
r = ldexp(r, MP_DIGIT_BIT) + b.dp[i];
}
}
mp_clear(&b);
/*
* Return the result with the appropriate sign.
*/
|
| ︙ | ︙ |
Changes to generic/tclTestObj.c.
| ︙ | ︙ | |||
277 278 279 280 281 282 283 |
if (!Tcl_IsShared(varPtr[varIndex])) {
Tcl_SetBignumObj(varPtr[varIndex], &newValue);
} else {
SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&newValue));
}
break;
| | > > > > > | | > | | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
if (!Tcl_IsShared(varPtr[varIndex])) {
Tcl_SetBignumObj(varPtr[varIndex], &newValue);
} else {
SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&newValue));
}
break;
case BIGNUM_ISEVEN: {
mp_err err;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
return TCL_ERROR;
}
if (CheckIfVarUnset(interp, varPtr,varIndex)) {
return TCL_ERROR;
}
if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
&bignumValue) != TCL_OK) {
return TCL_ERROR;
}
err = mp_mod_2d(&bignumValue, 1, &bignumValue);
if (err == MP_OKAY && !mp_iszero(&bignumValue)) {
err = MP_ERR;
}
if (!Tcl_IsShared(varPtr[varIndex])) {
Tcl_SetIntObj(varPtr[varIndex], err == MP_OKAY);
} else {
SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(err == MP_OKAY));
}
mp_clear(&bignumValue);
}
break;
case BIGNUM_RADIXSIZE:
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
return TCL_ERROR;
}
if (CheckIfVarUnset(interp, varPtr,varIndex)) {
|
| ︙ | ︙ |
Changes to unix/Makefile.in.
| ︙ | ︙ | |||
278 279 280 281 282 283 284 |
#--------------------------------------------------------------------------
STUB_CC_SWITCHES = -I"${BUILD_DIR}" -I${UNIX_DIR} -I${GENERIC_DIR} -I${TOMMATH_DIR} \
${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
${AC_FLAGS} ${PROTO_FLAGS} ${ENV_FLAGS} ${EXTRA_CFLAGS} \
@EXTRA_CC_SWITCHES@
| | | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
#--------------------------------------------------------------------------
STUB_CC_SWITCHES = -I"${BUILD_DIR}" -I${UNIX_DIR} -I${GENERIC_DIR} -I${TOMMATH_DIR} \
${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
${AC_FLAGS} ${PROTO_FLAGS} ${ENV_FLAGS} ${EXTRA_CFLAGS} \
@EXTRA_CC_SWITCHES@
CC_SWITCHES = $(STUB_CC_SWITCHES) ${NO_DEPRECATED_FLAGS} -DMP_FIXED_CUTOFFS -DMP_NO_STDINT
APP_CC_SWITCHES = $(CC_SWITCHES) @EXTRA_APP_CC_SWITCHES@
LIBS = @TCL_LIBS@
DEPEND_SWITCHES = ${CFLAGS} -I${UNIX_DIR} -I${GENERIC_DIR} \
${AC_FLAGS} ${PROTO_FLAGS} ${EXTRA_CFLAGS} @EXTRA_CC_SWITCHES@
|
| ︙ | ︙ |
Changes to win/Makefile.in.
| ︙ | ︙ | |||
78 79 80 81 82 83 84 | CFLAGS_OPTIMIZE = @CFLAGS_OPTIMIZE@ # To change the compiler switches, for example to change from optimization to # debugging symbols, change the following line: #CFLAGS = $(CFLAGS_DEBUG) #CFLAGS = $(CFLAGS_OPTIMIZE) #CFLAGS = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE) | | | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | CFLAGS_OPTIMIZE = @CFLAGS_OPTIMIZE@ # To change the compiler switches, for example to change from optimization to # debugging symbols, change the following line: #CFLAGS = $(CFLAGS_DEBUG) #CFLAGS = $(CFLAGS_OPTIMIZE) #CFLAGS = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE) CFLAGS = @CFLAGS@ @CFLAGS_DEFAULT@ -D_ATL_XP_TARGETING -DMP_FIXED_CUTOFFS -DMP_NO_STDINT # To compile without backward compatibility and deprecated code uncomment the # following NO_DEPRECATED_FLAGS = #NO_DEPRECATED_FLAGS = -DTCL_NO_DEPRECATED # To enable compilation debugging reverse the comment characters on one of the |
| ︙ | ︙ |
Changes to win/makefile.vc.
| ︙ | ︙ | |||
433 434 435 436 437 438 439 | ### the left side of implicit rules. TOMMATHDIR = $(ROOT)\libtommath PKGSDIR = $(ROOT)\pkgs # Additional include and C macro definitions for the implicit rules # defined in rules.vc PRJ_INCLUDES = -I"$(TOMMATHDIR)" | | | 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 | ### the left side of implicit rules. TOMMATHDIR = $(ROOT)\libtommath PKGSDIR = $(ROOT)\pkgs # Additional include and C macro definitions for the implicit rules # defined in rules.vc PRJ_INCLUDES = -I"$(TOMMATHDIR)" PRJ_DEFINES = /DTCL_TOMMATH /DMP_PREC=4 /Dinline=__inline /DHAVE_ZLIB=1 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DMP_FIXED_CUTOFFS # Additional Link libraries needed beyond those in rules.vc PRJ_LIBS = netapi32.lib user32.lib userenv.lib ws2_32.lib #--------------------------------------------------------------------- # TclTest flags #--------------------------------------------------------------------- |
| ︙ | ︙ |