Tcl Source Code

Check-in [5bc72628bd]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Update some libtommath functions to the latest trunk versions. Small step forward in the upgrade to (upcoming) libtommath 1.2. Advantage: simplify Tcl code accessing those functions.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | core-8-5-branch
Files: files | file ages | folders
SHA3-256: 5bc72628bd0af3e1c7a7a73cf44ba122dbf0be2f1d559b84b41d1cca7c8505a1
User & Date: jan.nijtmans 2019-05-29 22:48:50.305
Context
2019-06-10
18:24
Remove declarations that are never defined. check-in: 65ba73d0ea user: dgp tags: core-8-5-branch
2019-05-29
23:08
Merge 8.5 check-in: a5dc393eae user: jan.nijtmans tags: core-8-6-branch
22:48
Update some libtommath functions to the latest trunk versions. Small step forward in the upgrade to ... check-in: 5bc72628bd user: jan.nijtmans tags: core-8-5-branch
2019-05-28
21:38
Eliminate a set of libtommath-related files that don't do anything. There's no sense in it, keeping ... check-in: 55750caf85 user: jan.nijtmans tags: core-8-5-branch
Changes
Unified Diff Ignore Whitespace Patch
Changes to generic/tclBasic.c.
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
	     * deleted - We've already deleted a conflicting command
	     */
	    break;
        }

	/* An existing command conflicts. Try to delete it.. */
	cmdPtr = Tcl_GetHashValue(hPtr);
	
	/*
	 * Be careful to preserve
	 * any existing import links so we can restore them down below. That
	 * way, you can redefine a command and its import status will remain
	 * intact.
	 */








|







1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
	     * deleted - We've already deleted a conflicting command
	     */
	    break;
        }

	/* An existing command conflicts. Try to delete it.. */
	cmdPtr = Tcl_GetHashValue(hPtr);

	/*
	 * Be careful to preserve
	 * any existing import links so we can restore them down below. That
	 * way, you can redefine a command and its import status will remain
	 * intact.
	 */

2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
	    break;
        }

	/* An existing command conflicts. Try to delete it.. */
	cmdPtr = Tcl_GetHashValue(hPtr);

	/*
	 * [***] This is wrong.  See Tcl Bug a16752c252.  
	 * However, this buggy behavior is kept under particular
	 * circumstances to accommodate deployed binaries of the
	 * "tclcompiler" program. http://sourceforge.net/projects/tclpro/
	 * that crash if the bug is fixed.
	 */

	if (cmdPtr->objProc == TclInvokeStringCommand







|







2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
	    break;
        }

	/* An existing command conflicts. Try to delete it.. */
	cmdPtr = Tcl_GetHashValue(hPtr);

	/*
	 * [***] This is wrong.  See Tcl Bug a16752c252.
	 * However, this buggy behavior is kept under particular
	 * circumstances to accommodate deployed binaries of the
	 * "tclcompiler" program. http://sourceforge.net/projects/tclpro/
	 * that crash if the bug is fixed.
	 */

	if (cmdPtr->objProc == TclInvokeStringCommand
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198

	int nelements;
	Tcl_Obj **elements, *copyPtr = TclListObjCopy(NULL, objPtr);
	CmdFrame *eoFramePtr = (CmdFrame *)
		TclStackAlloc(interp, sizeof(CmdFrame));

	eoFramePtr->type = TCL_LOCATION_EVAL_LIST;
	eoFramePtr->level = (iPtr->cmdFramePtr == NULL?  1 
		: iPtr->cmdFramePtr->level + 1);
	eoFramePtr->framePtr = iPtr->framePtr;
	eoFramePtr->nextPtr = iPtr->cmdFramePtr;

	eoFramePtr->nline = 0;
	eoFramePtr->line = NULL;








|







5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198

	int nelements;
	Tcl_Obj **elements, *copyPtr = TclListObjCopy(NULL, objPtr);
	CmdFrame *eoFramePtr = (CmdFrame *)
		TclStackAlloc(interp, sizeof(CmdFrame));

	eoFramePtr->type = TCL_LOCATION_EVAL_LIST;
	eoFramePtr->level = (iPtr->cmdFramePtr == NULL?  1
		: iPtr->cmdFramePtr->level + 1);
	eoFramePtr->framePtr = iPtr->framePtr;
	eoFramePtr->nextPtr = iPtr->cmdFramePtr;

	eoFramePtr->nline = 0;
	eoFramePtr->line = NULL;

6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
	    }
	}
	break;
    case TCL_NUMBER_BIG:
	if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (SIGN(&big) == MP_NEG) {
	    mp_clear(&big);
	    goto negarg;
	}
	break;
    default:
	if (Tcl_GetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
	    return TCL_ERROR;







|







6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
	    }
	}
	break;
    case TCL_NUMBER_BIG:
	if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (mp_isneg(&big)) {
	    mp_clear(&big);
	    goto negarg;
	}
	break;
    default:
	if (Tcl_GetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
	    return TCL_ERROR;
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
	return TCL_OK;
    }
#endif

    if (type == TCL_NUMBER_BIG) {
	/* TODO: const correctness ? */
	if (mp_cmp_d((mp_int *) ptr, 0) == MP_LT) {
	    Tcl_GetBignumFromObj(NULL, objv[1], &big);
	tooLarge:
	    mp_neg(&big, &big);
	    Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
	} else {
	unChanged:
	    Tcl_SetObjResult(interp, objv[1]);







<
|







6613
6614
6615
6616
6617
6618
6619

6620
6621
6622
6623
6624
6625
6626
6627
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
	return TCL_OK;
    }
#endif

    if (type == TCL_NUMBER_BIG) {

	if (mp_cmp_d(ptr, 0) == MP_LT) {
	    Tcl_GetBignumFromObj(NULL, objv[1], &big);
	tooLarge:
	    mp_neg(&big, &big);
	    Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
	} else {
	unChanged:
	    Tcl_SetObjResult(interp, objv[1]);
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
	/*
	 * Truncate the bignum; keep only bits in long range.
	 */

	mp_int big;

	Tcl_GetBignumFromObj(NULL, objPtr, &big);
	mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	TclGetLongFromObj(NULL, objPtr, &iResult);
	Tcl_DecrRefCount(objPtr);
    }
    Tcl_SetObjResult(interp, Tcl_NewLongObj(iResult));
    return TCL_OK;







|







6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
	/*
	 * Truncate the bignum; keep only bits in long range.
	 */

	mp_int big;

	Tcl_GetBignumFromObj(NULL, objPtr, &big);
	mp_mod_2d(&big, CHAR_BIT * sizeof(long), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	TclGetLongFromObj(NULL, objPtr, &iResult);
	Tcl_DecrRefCount(objPtr);
    }
    Tcl_SetObjResult(interp, Tcl_NewLongObj(iResult));
    return TCL_OK;
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
	/*
	 * Truncate the bignum; keep only bits in wide int range.
	 */

	mp_int big;

	Tcl_GetBignumFromObj(NULL, objPtr, &big);
	mp_mod_2d(&big, (int) CHAR_BIT * sizeof(Tcl_WideInt), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	Tcl_GetWideIntFromObj(NULL, objPtr, &wResult);
	Tcl_DecrRefCount(objPtr);
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wResult));
    return TCL_OK;







|







6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
	/*
	 * Truncate the bignum; keep only bits in wide int range.
	 */

	mp_int big;

	Tcl_GetBignumFromObj(NULL, objPtr, &big);
	mp_mod_2d(&big, CHAR_BIT * sizeof(Tcl_WideInt), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	Tcl_GetWideIntFromObj(NULL, objPtr, &wResult);
	Tcl_DecrRefCount(objPtr);
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wResult));
    return TCL_OK;
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
	mp_int big;

	if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
	    /* TODO: more ::errorInfo here? or in caller? */
	    return TCL_ERROR;
	}

	mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	TclGetLongFromObj(NULL, objPtr, &i);
	Tcl_DecrRefCount(objPtr);
    }

    /*







|







7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
	mp_int big;

	if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
	    /* TODO: more ::errorInfo here? or in caller? */
	    return TCL_ERROR;
	}

	mp_mod_2d(&big, CHAR_BIT * sizeof(long), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	TclGetLongFromObj(NULL, objPtr, &i);
	Tcl_DecrRefCount(objPtr);
    }

    /*
Changes to generic/tclExecute.c.
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
 *  The object is shimmered to bytecode type.
 *
 *----------------------------------------------------------------------
 */

ByteCode *
TclCompileObj(
    Tcl_Interp *interp, 
    Tcl_Obj *objPtr,
    const CmdFrame *invoker,
    int word)
{
    register Interp *iPtr = (Interp *) interp;
    register ByteCode *codePtr;	/* Tcl Internal type of bytecode. */
    Namespace *namespacePtr = iPtr->varFramePtr->nsPtr;







|







1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
 *  The object is shimmered to bytecode type.
 *
 *----------------------------------------------------------------------
 */

ByteCode *
TclCompileObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    const CmdFrame *invoker,
    int word)
{
    register Interp *iPtr = (Interp *) interp;
    register ByteCode *codePtr;	/* Tcl Internal type of bytecode. */
    Namespace *namespacePtr = iPtr->varFramePtr->nsPtr;
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
		}
#endif
		{
		    mp_int big2;

		    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);

		    /* TODO: internals intrusion */
		    if ((l1 > 0) ^ (big2.sign == MP_ZPOS)) {
			/*
			 * Arguments are opposite sign; remainder is sum.
			 */

			mp_int big1;

			TclBNInitBignumFromLong(&big1, l1);
			mp_add(&big2, &big1, &big2);
			mp_clear(&big1);
			objResultPtr = Tcl_NewBignumObj(&big2);
			TRACE(("%s\n", O2S(objResultPtr)));
			NEXT_INST_F(1, 2, 1);
		    }

		    /*
		     * Arguments are same sign; remainder is first operand.
		     */





		    mp_clear(&big2);

		    TRACE(("%s\n", O2S(valuePtr)));
		    NEXT_INST_F(1, 1, 0);
		}
	    }
#ifndef NO_WIDE_TYPE
	    if (type1 == TCL_NUMBER_WIDE) {
		Tcl_WideInt w1 = *((const Tcl_WideInt *)ptr1);

		if (type2 != TCL_NUMBER_BIG) {







<
|

|


<
<
<
<
|
<
|
|



|


>
>
>
>
|
>
|
|







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
		}
#endif
		{
		    mp_int big2;

		    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);


		    if ((l1 > 0) ^ mp_isneg(&big2)) {
			/*
			 * Arguments are same sign; remainder is first operand.
			 */





			mp_clear(&big2);

			TRACE(("%s\n", O2S(valuePtr)));
			NEXT_INST_F(1, 1, 0);
		    }

		    /*
		     * Arguments are opposite sign; remainder is sum.
		     */

		    mp_int big1;

		    TclBNInitBignumFromLong(&big1, l1);
		    mp_add(&big2, &big1, &big2);
		    mp_clear(&big1);
		    objResultPtr = Tcl_NewBignumObj(&big2);
		    TRACE(("%s\n", O2S(objResultPtr)));
		    NEXT_INST_F(1, 2, 1);
		}
	    }
#ifndef NO_WIDE_TYPE
	    if (type1 == TCL_NUMBER_WIDE) {
		Tcl_WideInt w1 = *((const Tcl_WideInt *)ptr1);

		if (type2 != TCL_NUMBER_BIG) {
4995
4996
4997
4998
4999
5000
5001
5002
5003








5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
		    NEXT_INST_F(1, 2, 1);
		}
		{
		    mp_int big2;
		    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);

		    /* TODO: internals intrusion */
		    if ((w1 > ((Tcl_WideInt) 0)) ^ (big2.sign == MP_ZPOS)) {
			/*








			 * Arguments are opposite sign; remainder is sum.
			 */

			mp_int big1;

			TclBNInitBignumFromWideInt(&big1, w1);
			mp_add(&big2, &big1, &big2);
			mp_clear(&big1);
			objResultPtr = Tcl_NewBignumObj(&big2);
			TRACE(("%s\n", O2S(objResultPtr)));
			NEXT_INST_F(1, 2, 1);
		    }

		    /*
		     * Arguments are same sign; remainder is first operand.
		     */

		    mp_clear(&big2);
		    TRACE(("%s\n", O2S(valuePtr)));
		    NEXT_INST_F(1, 1, 0);
		}
	    }
#endif
	    {
		mp_int big1, big2, bigResult, bigRemainder;

		Tcl_GetBignumFromObj(NULL, valuePtr, &big1);
		Tcl_GetBignumFromObj(NULL, value2Ptr, &big2);
		mp_init(&bigResult);
		mp_init(&bigRemainder);
		mp_div(&big1, &big2, &bigResult, &bigRemainder);
		if (!mp_iszero(&bigRemainder)
			&& (bigRemainder.sign != big2.sign)) {
		    /*
		     * Convert to Tcl's integer division rules.
		     */

		    mp_sub_d(&bigResult, 1, &bigResult);
		    mp_add(&bigRemainder, &big2, &bigRemainder);
		}







|

>
>
>
>
>
>
>
>
|
|

|

|
|
|
|
|
|
|
<
<
<
<
<
<
<
<












|







4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022








5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
		    NEXT_INST_F(1, 2, 1);
		}
		{
		    mp_int big2;
		    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);

		    /* TODO: internals intrusion */
		    if ((w1 > ((Tcl_WideInt) 0)) ^ mp_isneg(&big2)) {
			/*
			 * Arguments are same sign; remainder is first operand.
			 */

			mp_clear(&big2);
			TRACE(("%s\n", O2S(valuePtr)));
			NEXT_INST_F(1, 1, 0);
		    }
		    /*
		     * Arguments are opposite sign; remainder is sum.
		     */

		    mp_int big1;

		    TclBNInitBignumFromWideInt(&big1, w1);
		    mp_add(&big2, &big1, &big2);
		    mp_clear(&big1);
		    objResultPtr = Tcl_NewBignumObj(&big2);
		    TRACE(("%s\n", O2S(objResultPtr)));
		    NEXT_INST_F(1, 2, 1);









		}
	    }
#endif
	    {
		mp_int big1, big2, bigResult, bigRemainder;

		Tcl_GetBignumFromObj(NULL, valuePtr, &big1);
		Tcl_GetBignumFromObj(NULL, value2Ptr, &big2);
		mp_init(&bigResult);
		mp_init(&bigRemainder);
		mp_div(&big1, &big2, &bigResult, &bigRemainder);
		if (!mp_iszero(&bigRemainder)
			&& (mp_isneg(&bigRemainder) != mp_isneg(&big2))) {
		    /*
		     * Convert to Tcl's integer division rules.
		     */

		    mp_sub_d(&bigResult, 1, &bigResult);
		    mp_add(&bigRemainder, &big2, &bigRemainder);
		}
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, value2Ptr);
	    CACHE_STACK_INFO();
	    goto checkForCatch;
	}

	if ((type1 == TCL_NUMBER_BIG) || (type2 == TCL_NUMBER_BIG)) {
	    mp_int big1, big2, bigResult, *First, *Second;
	    int numPos;

	    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 (*pc) {
	    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;
		}
		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;
		}
		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;
		}
		break;
	    }

	    mp_clear(&big1);
	    mp_clear(&big2);
	    TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
	    if (Tcl_IsShared(valuePtr)) {







|
<




<
<
<
<
<
<
<
<
<
<
<
<
<
<




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







5311
5312
5313
5314
5315
5316
5317
5318

5319
5320
5321
5322














5323
5324
5325
5326






























5327

5328
5329


5330


















5331

















5332
5333
5334

















5335















5336
5337
5338
5339
5340
5341
5342
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, value2Ptr);
	    CACHE_STACK_INFO();
	    goto checkForCatch;
	}

	if ((type1 == TCL_NUMBER_BIG) || (type2 == TCL_NUMBER_BIG)) {
	    mp_int big1, big2, bigResult;


	    Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
	    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);















	    mp_init(&bigResult);

	    switch (*pc) {
	    case INST_BITAND:






























		mp_and(&big1, &big2, &bigResult);

		break;



	    case INST_BITOR:


















		mp_or(&big1, &big2, &bigResult);

















		break;

	    case INST_BITXOR:

















		mp_xor(&big1, &big2, &bigResult);















		break;
	    }

	    mp_clear(&big1);
	    mp_clear(&big2);
	    TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
	    if (Tcl_IsShared(valuePtr)) {
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
		    mp_clear(&big1);
		    mp_clear(&big2);
		    mp_clear(&bigResult);
		    goto divideByZero;
		}
		mp_init(&bigRemainder);
		mp_div(&big1, &big2, &bigResult, &bigRemainder);
		/* TODO: internals intrusion */
		if (!mp_iszero(&bigRemainder)
			&& (bigRemainder.sign != big2.sign)) {
		    /*
		     * Convert to Tcl's integer division rules.
		     */

		    mp_sub_d(&bigResult, 1, &bigResult);
		    mp_add(&bigRemainder, &big2, &bigRemainder);
		}







<

|







6136
6137
6138
6139
6140
6141
6142

6143
6144
6145
6146
6147
6148
6149
6150
6151
		    mp_clear(&big1);
		    mp_clear(&big2);
		    mp_clear(&bigResult);
		    goto divideByZero;
		}
		mp_init(&bigRemainder);
		mp_div(&big1, &big2, &bigResult, &bigRemainder);

		if (!mp_iszero(&bigRemainder)
			&& (mp_isneg(&bigRemainder) != mp_isneg(&big2))) {
		    /*
		     * Convert to Tcl's integer division rules.
		     */

		    mp_sub_d(&bigResult, 1, &bigResult);
		    mp_add(&bigRemainder, &big2, &bigRemainder);
		}
Changes to generic/tclObj.c.
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
	(objPtr)->internalRep.ptrAndLongRep.ptr = (void*) temp; \
	(objPtr)->internalRep.ptrAndLongRep.value = (unsigned long)(-1); \
    } else { \
	if ((bignum).alloc > 0x7fff) { \
	    mp_shrink(&(bignum)); \
	} \
	(objPtr)->internalRep.ptrAndLongRep.ptr = (void*) (bignum).dp; \
	(objPtr)->internalRep.ptrAndLongRep.value = ( ((bignum).sign << 30) \
		| ((bignum).alloc << 15) | ((bignum).used)); \
    }

#define UNPACK_BIGNUM(objPtr, bignum) \
    if ((objPtr)->internalRep.ptrAndLongRep.value == (unsigned long)(-1)) { \
	(bignum) = *((mp_int *) ((objPtr)->internalRep.ptrAndLongRep.ptr)); \
    } else { \







|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
	(objPtr)->internalRep.ptrAndLongRep.ptr = (void*) temp; \
	(objPtr)->internalRep.ptrAndLongRep.value = (unsigned long)(-1); \
    } else { \
	if ((bignum).alloc > 0x7fff) { \
	    mp_shrink(&(bignum)); \
	} \
	(objPtr)->internalRep.ptrAndLongRep.ptr = (void*) (bignum).dp; \
	(objPtr)->internalRep.ptrAndLongRep.value = ( (mp_isneg(&bignum) << 30) \
		| ((bignum).alloc << 15) | ((bignum).used)); \
    }

#define UNPACK_BIGNUM(objPtr, bignum) \
    if ((objPtr)->internalRep.ptrAndLongRep.value == (unsigned long)(-1)) { \
	(bignum) = *((mp_int *) ((objPtr)->internalRep.ptrAndLongRep.ptr)); \
    } else { \
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
		unsigned long value = 0, numBytes = sizeof(long);
		long scratch;
		unsigned char *bytes = (unsigned char *)&scratch;
		if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
		    while (numBytes-- > 0) {
			value = (value << CHAR_BIT) | *bytes++;
		    }
		    if (big.sign) {
			*longPtr = - (long) value;
		    } else {
			*longPtr = (long) value;
		    }
		    return TCL_OK;
		}
	    }







|







2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
		unsigned long value = 0, numBytes = sizeof(long);
		long scratch;
		unsigned char *bytes = (unsigned char *)&scratch;
		if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
		    while (numBytes-- > 0) {
			value = (value << CHAR_BIT) | *bytes++;
		    }
		    if (mp_isneg(&big)) {
			*longPtr = - (long) value;
		    } else {
			*longPtr = (long) value;
		    }
		    return TCL_OK;
		}
	    }
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
		Tcl_WideInt scratch;
		unsigned char *bytes = (unsigned char *) &scratch;

		if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
		    while (numBytes-- > 0) {
			value = (value << CHAR_BIT) | *bytes++;
		    }
		    if (big.sign) {
			*wideIntPtr = - (Tcl_WideInt) value;
		    } else {
			*wideIntPtr = (Tcl_WideInt) value;
		    }
		    return TCL_OK;
		}
	    }







|







3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
		Tcl_WideInt scratch;
		unsigned char *bytes = (unsigned char *) &scratch;

		if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
		    while (numBytes-- > 0) {
			value = (value << CHAR_BIT) | *bytes++;
		    }
		    if (mp_isneg(&big)) {
			*wideIntPtr = - (Tcl_WideInt) value;
		    } else {
			*wideIntPtr = (Tcl_WideInt) value;
		    }
		    return TCL_OK;
		}
	    }
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
	unsigned char *bytes = (unsigned char *)&scratch;
	if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
	    goto tooLargeForLong;
	}
	while (numBytes-- > 0) {
	    value = (value << CHAR_BIT) | *bytes++;
	}
	if (value > (((~(unsigned long)0) >> 1) + bignumValue->sign)) {
	    goto tooLargeForLong;
	}
	if (bignumValue->sign) {
	    TclSetLongObj(objPtr, -(long)value);
	} else {
	    TclSetLongObj(objPtr, (long)value);
	}
	mp_clear(bignumValue);
	return;
    }







|


|







3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
	unsigned char *bytes = (unsigned char *)&scratch;
	if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
	    goto tooLargeForLong;
	}
	while (numBytes-- > 0) {
	    value = (value << CHAR_BIT) | *bytes++;
	}
	if (value > (((~(unsigned long)0) >> 1) + mp_isneg(bignumValue))) {
	    goto tooLargeForLong;
	}
	if (mp_isneg(bignumValue)) {
	    TclSetLongObj(objPtr, -(long)value);
	} else {
	    TclSetLongObj(objPtr, (long)value);
	}
	mp_clear(bignumValue);
	return;
    }
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
	unsigned char *bytes = (unsigned char *)&scratch;
	if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
	    goto tooLargeForWide;
	}
	while (numBytes-- > 0) {
	    value = (value << CHAR_BIT) | *bytes++;
	}
	if (value > (((~(Tcl_WideUInt)0) >> 1) + bignumValue->sign)) {
	    goto tooLargeForWide;
	}
	if (bignumValue->sign) {
	    TclSetWideIntObj(objPtr, -(Tcl_WideInt)value);
	} else {
	    TclSetWideIntObj(objPtr, (Tcl_WideInt)value);
	}
	mp_clear(bignumValue);
	return;
    }







|


|







3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
	unsigned char *bytes = (unsigned char *)&scratch;
	if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
	    goto tooLargeForWide;
	}
	while (numBytes-- > 0) {
	    value = (value << CHAR_BIT) | *bytes++;
	}
	if (value > (((~(Tcl_WideUInt)0) >> 1) + mp_isneg(bignumValue))) {
	    goto tooLargeForWide;
	}
	if (mp_isneg(bignumValue)) {
	    TclSetWideIntObj(objPtr, -(Tcl_WideInt)value);
	} else {
	    TclSetWideIntObj(objPtr, (Tcl_WideInt)value);
	}
	mp_clear(bignumValue);
	return;
    }
Changes to generic/tclStrToD.c.
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
				/* floor(FP_PRECISION*log(2)/log(5)) */
#define QUICK_MAX		14
				/* floor((FP_PRECISION-1)*log(2)/log(10)) - 1 */
#define BLETCH			0x10
				/* Highest power of two that is greater than
				 * DBL_MAX_10_EXP, divided by 16 */
#define DIGIT_GROUP		8
				/* floor(DIGIT_BIT*log(2)/log(10)) */

/* Union used to dismantle floating point numbers. */

typedef union Double {
    struct {
#ifdef WORDS_BIGENDIAN
	int word0;







|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
				/* floor(FP_PRECISION*log(2)/log(5)) */
#define QUICK_MAX		14
				/* floor((FP_PRECISION-1)*log(2)/log(10)) - 1 */
#define BLETCH			0x10
				/* Highest power of two that is greater than
				 * DBL_MAX_10_EXP, divided by 16 */
#define DIGIT_GROUP		8
				/* floor(MP_DIGIT_BIT*log(2)/log(10)) */

/* Union used to dismantle floating point numbers. */

typedef union Double {
    struct {
#ifdef WORDS_BIGENDIAN
	int word0;
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
		bignumRepPtr);
	mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr);
    } else {
	/*
	 * 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 DIGIT_BIT is at least 27. The
	 * first multiplication, by up to 10**7, is done with a one-DIGIT
	 * multiply (this presumes that DIGIT_BIT >= 24).
	 */

	n = numZeros + 1;
	mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr);
	for (i=3; i<=7; ++i) {
	    if (n & (1 << i)) {
		mp_mul(bignumRepPtr, pow5+i, bignumRepPtr);







|

|







1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
		bignumRepPtr);
	mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr);
    } else {
	/*
	 * 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;
	mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr);
	for (i=3; i<=7; ++i) {
	    if (n & (1 << i)) {
		mp_mul(bignumRepPtr, pow5+i, bignumRepPtr);
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
/*
 *-----------------------------------------------------------------------------
 *
 * ShouldBankerRoundUpPowD --
 *
 *	Test whether bankers' rounding should round a digit up. Assumption
 *	is made that the denominator of the fraction being tested is
 *	a power of 2**DIGIT_BIT.
 *
 * Results:
 *	Returns 1 iff the fraction is more than 1/2, or if the fraction
 *	is exactly 1/2 and the digit is odd.
 *
 *-----------------------------------------------------------------------------
 */

inline static int
ShouldBankerRoundUpPowD(mp_int* b,
				/* Numerator of the fraction */
			int sd,	/* Denominator is 2**(sd*DIGIT_BIT) */
			int isodd)
				/* 1 if the digit is odd, 0 if even */
{
    int i;
    static const mp_digit topbit = (1<<(MP_DIGIT_BIT-1));
    if (b->used < sd || (b->dp[sd-1] & topbit) == 0) {
	return 0;







|











|







3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
/*
 *-----------------------------------------------------------------------------
 *
 * ShouldBankerRoundUpPowD --
 *
 *	Test whether bankers' rounding should round a digit up. Assumption
 *	is made that the denominator of the fraction being tested is
 *	a power of 2**MP_DIGIT_BIT.
 *
 * Results:
 *	Returns 1 iff the fraction is more than 1/2, or if the fraction
 *	is exactly 1/2 and the digit is odd.
 *
 *-----------------------------------------------------------------------------
 */

inline static int
ShouldBankerRoundUpPowD(mp_int* b,
				/* Numerator of the fraction */
			int sd,	/* Denominator is 2**(sd*MP_DIGIT_BIT) */
			int isodd)
				/* 1 if the digit is odd, 0 if even */
{
    int i;
    static const mp_digit topbit = (1<<(MP_DIGIT_BIT-1));
    if (b->used < sd || (b->dp[sd-1] & topbit) == 0) {
	return 0;
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
3175
3176
3177
3178

inline static int
ShouldBankerRoundUpToNextPowD(mp_int* b,
				/* Numerator of the fraction */
			      mp_int* m,
				/* Numerator of the rounding tolerance */
			      int sd,
				/* Common denominator is 2**(sd*DIGIT_BIT) */
			      int convType,
				/* Conversion type: STEELE defeats
				 * round-to-even (Not sure why one wants to
				 * do this; I copied it from Gay) FIXME */
			      int isodd,
				/* 1 if the integer significand is odd */
			      mp_int* temp)
				/* Work area for the calculation */
{
    int i;

    /*
     * 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**(DIGIT_BIT*sd)
     */
    mp_add(b, m, temp);
    if (temp->used <= sd) {	/* too few digits to be > S */
	return 0;
    }
    if (temp->used > sd+1 || temp->dp[sd] > 1) {
				/* >= 2s */







|














|







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
3175
3176
3177
3178

inline static int
ShouldBankerRoundUpToNextPowD(mp_int* b,
				/* Numerator of the fraction */
			      mp_int* m,
				/* Numerator of the rounding tolerance */
			      int sd,
				/* Common denominator is 2**(sd*MP_DIGIT_BIT) */
			      int convType,
				/* Conversion type: STEELE defeats
				 * round-to-even (Not sure why one wants to
				 * do this; I copied it from Gay) FIXME */
			      int isodd,
				/* 1 if the integer significand is odd */
			      mp_int* temp)
				/* Work area for the calculation */
{
    int i;

    /*
     * 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)
     */
    mp_add(b, m, temp);
    if (temp->used <= sd) {	/* too few digits to be > S */
	return 0;
    }
    if (temp->used > sd+1 || temp->dp[sd] > 1) {
				/* >= 2s */
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
 *
 * ShorteningBignumConversionPowD --
 *
 *	Converts a double-precision number to the shortest string of
 *	digits that reconverts exactly to the given number, or to
 *	'ilim' digits if that will yield a shorter result. The denominator
 *	in David Gay's conversion algorithm is known to be a power of
 *	2**DIGIT_BIT, and hence the division in the main loop may be replaced
 *	by a digit shift and mask.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly
 *	allocated memory
 *
 * Side effects:







|







3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
 *
 * ShorteningBignumConversionPowD --
 *
 *	Converts a double-precision number to the shortest string of
 *	digits that reconverts exactly to the given number, or to
 *	'ilim' digits if that will yield a shorter result. The denominator
 *	in David Gay's conversion algorithm is known to be a power of
 *	2**MP_DIGIT_BIT, and hence the division in the main loop may be replaced
 *	by a digit shift and mask.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly
 *	allocated memory
 *
 * Side effects:
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
    MulPow5(&mminus, m5, &mminus);
    if (m2plus > m2minus) {
	mp_init_copy(&mplus, &mminus);
	mp_mul_2d(&mplus, m2plus-m2minus, &mplus);
    }
    mp_init(&temp);

    /* Loop through the digits. Do division and mod by s == 2**(sd*DIGIT_BIT)
     * by mp_digit extraction */

    i = 0;
    for (;;) {
	if (b.used <= sd) {
	    digit = 0;
	} else {







|







3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
    MulPow5(&mminus, m5, &mminus);
    if (m2plus > m2minus) {
	mp_init_copy(&mplus, &mminus);
	mp_mul_2d(&mplus, m2plus-m2minus, &mplus);
    }
    mp_init(&temp);

    /* Loop through the digits. Do division and mod by s == 2**(sd*MP_DIGIT_BIT)
     * by mp_digit extraction */

    i = 0;
    for (;;) {
	if (b.used <= sd) {
	    digit = 0;
	} else {
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
 *-----------------------------------------------------------------------------
 *
 * StrictBignumConversionPowD --
 *
 *	Converts a double-precision number to a fixed-lengt string of
 *	'ilim' digits (or 'ilim1' if log10(d) has been overestimated.)
 *	The denominator in David Gay's conversion algorithm is known to
 *	be a power of 2**DIGIT_BIT, and hence the division in the main
 *	loop may be replaced by a digit shift and mask.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly
 *	allocated memory.
 *
 * Side effects:







|







3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
 *-----------------------------------------------------------------------------
 *
 * StrictBignumConversionPowD --
 *
 *	Converts a double-precision number to a fixed-lengt string of
 *	'ilim' digits (or 'ilim1' if log10(d) has been overestimated.)
 *	The denominator in David Gay's conversion algorithm is known to
 *	be a power of 2**MP_DIGIT_BIT, and hence the division in the main
 *	loop may be replaced by a digit shift and mask.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly
 *	allocated memory.
 *
 * Side effects:
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
	mp_mul_d(&b, 10, &b);
	ilim = ilim1;
	--k;
    }
    mp_init(&temp);

    /*
     * Loop through the digits. Do division and mod by s == 2**(sd*DIGIT_BIT)
     * by mp_digit extraction
     */

    i = 1;
    for (;;) {
	if (b.used <= sd) {
	    digit = 0;







|







3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
	mp_mul_d(&b, 10, &b);
	ilim = ilim1;
	--k;
    }
    mp_init(&temp);

    /*
     * Loop through the digits. Do division and mod by s == 2**(sd*MP_DIGIT_BIT)
     * by mp_digit extraction
     */

    i = 1;
    for (;;) {
	if (b.used <= sd) {
	    digit = 0;
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
					     m2plus, m2minus, m5,
					     s2, s5, k, len, ilim, ilim1,
					     decpt, endPtr);
	} else if (s5 == 0) {
	    /*
	     * The denominator is a power of 2, so we can replace division
	     * by digit shifts. First we round up s2 to a multiple of
	     * DIGIT_BIT, and adjust m2 and b2 accordingly. Then we launch
	     * into a version of the comparison that's specialized for
	     * the 'power of mp_digit in the denominator' case.
	     */
	    if (s2 % MP_DIGIT_BIT != 0) {
		int delta = MP_DIGIT_BIT - (s2 % MP_DIGIT_BIT);
		b2 += delta;
		m2plus += delta;







|







4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
					     m2plus, m2minus, m5,
					     s2, s5, k, len, ilim, ilim1,
					     decpt, endPtr);
	} else if (s5 == 0) {
	    /*
	     * The denominator is a power of 2, so we can replace division
	     * by digit shifts. First we round up s2 to a multiple of
	     * MP_DIGIT_BIT, and adjust m2 and b2 accordingly. Then we launch
	     * into a version of the comparison that's specialized for
	     * the 'power of mp_digit in the denominator' case.
	     */
	    if (s2 % MP_DIGIT_BIT != 0) {
		int delta = MP_DIGIT_BIT - (s2 % MP_DIGIT_BIT);
		b2 += delta;
		m2plus += delta;
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
					 s2, s5, k, len, ilim, ilim1,
					 decpt, endPtr);

	} else if (s5 == 0) {
	    /*
	     * The denominator is a power of 2, so we can replace division
	     * by digit shifts. First we round up s2 to a multiple of
	     * DIGIT_BIT, and adjust m2 and b2 accordingly. Then we launch
	     * into a version of the comparison that's specialized for
	     * the 'power of mp_digit in the denominator' case.
	     */
	    if (s2 % MP_DIGIT_BIT != 0) {
		int delta = MP_DIGIT_BIT - (s2 % MP_DIGIT_BIT);
		b2 += delta;
		s2 += delta;







|







4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
					 s2, s5, k, len, ilim, ilim1,
					 decpt, endPtr);

	} else if (s5 == 0) {
	    /*
	     * The denominator is a power of 2, so we can replace division
	     * by digit shifts. First we round up s2 to a multiple of
	     * MP_DIGIT_BIT, and adjust m2 and b2 accordingly. Then we launch
	     * into a version of the comparison that's specialized for
	     * the 'power of mp_digit in the denominator' case.
	     */
	    if (s2 % MP_DIGIT_BIT != 0) {
		int delta = MP_DIGIT_BIT - (s2 % MP_DIGIT_BIT);
		b2 += delta;
		s2 += delta;
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
     * We need a 'mantBits'-bit significand.  Determine what shift will
     * give us that.
     */

    bits = mp_count_bits(a);
    if (bits > DBL_MAX_EXP*log2FLT_RADIX) {
	errno = ERANGE;
	if (a->sign == MP_ZPOS) {
	    return HUGE_VAL;
	} else {
	    return -HUGE_VAL;
	}
    }
    shift = mantBits - bits;

    /*
     * If shift > 0, shift the significand left by the requisite number of
     * bits.  If shift == 0, the significand is already exactly 'mantBits'







|
|

|







4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
     * We need a 'mantBits'-bit significand.  Determine what shift will
     * give us that.
     */

    bits = mp_count_bits(a);
    if (bits > DBL_MAX_EXP*log2FLT_RADIX) {
	errno = ERANGE;
	if (mp_isneg(a)) {
	    return -HUGE_VAL;
	} else {
	    return HUGE_VAL;
	}
    }
    shift = mantBits - bits;

    /*
     * If shift > 0, shift the significand left by the requisite number of
     * bits.  If shift == 0, the significand is already exactly 'mantBits'
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632

	    /*
	     * Round to even
	     */

	    mp_div_2d(a, -shift, &b, NULL);
	    if (mp_isodd(&b)) {
		if (b.sign == MP_ZPOS) {
		    mp_add_d(&b, 1, &b);
		} else {
		    mp_sub_d(&b, 1, &b);
		}
	    }
	} else {

	    /*
	     * Ordinary rounding
	     */

	    mp_div_2d(a, -1-shift, &b, NULL);
	    if (b.sign == MP_ZPOS) {
		mp_add_d(&b, 1, &b);
	    } else {
		mp_sub_d(&b, 1, &b);
	    }
	    mp_div_2d(&b, 1, &b, NULL);
	}
    }

    /*
     * Accumulate the result, one mp_digit at a time.







|
|

|









|
|

|







4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632

	    /*
	     * Round to even
	     */

	    mp_div_2d(a, -shift, &b, NULL);
	    if (mp_isodd(&b)) {
		if (mp_isneg(&b)) {
		    mp_sub_d(&b, 1, &b);
		} else {
		    mp_add_d(&b, 1, &b);
		}
	    }
	} else {

	    /*
	     * Ordinary rounding
	     */

	    mp_div_2d(a, -1-shift, &b, NULL);
	    if (mp_isneg(&b)) {
		mp_sub_d(&b, 1, &b);
	    } else {
		mp_add_d(&b, 1, &b);
	    }
	    mp_div_2d(&b, 1, &b, NULL);
	}
    }

    /*
     * Accumulate the result, one mp_digit at a time.
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661

    r = ldexp(r, bits - mantBits);

    /*
     * Return the result with the appropriate sign.
     */

    if (a->sign == MP_ZPOS) {
	return r;
    } else {
	return -r;
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * TclCeil --







|
|

|







4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661

    r = ldexp(r, bits - mantBits);

    /*
     * Return the result with the appropriate sign.
     */

    if (mp_isneg(a)) {
	return -r;
    } else {
	return r;
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * TclCeil --
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
    mp_clear(&b);

    /*
     * Return the result with the appropriate sign.
     */

    *machexp = bits - mantBits + 2;
    return ((a->sign == MP_ZPOS) ? r : -r);
}

/*
 *----------------------------------------------------------------------
 *
 * Pow10TimesFrExp --
 *







|







4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
    mp_clear(&b);

    /*
     * Return the result with the appropriate sign.
     */

    *machexp = bits - mantBits + 2;
    return (mp_isneg(a) ? -r : r);
}

/*
 *----------------------------------------------------------------------
 *
 * Pow10TimesFrExp --
 *
Changes to generic/tclStringObj.c.
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
	    } else if (useWide) {
		if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
		    Tcl_Obj *objPtr;

		    if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
			goto error;
		    }
		    mp_mod_2d(&big, (int) CHAR_BIT*sizeof(Tcl_WideInt), &big);
		    objPtr = Tcl_NewBignumObj(&big);
		    Tcl_IncrRefCount(objPtr);
		    Tcl_GetWideIntFromObj(NULL, objPtr, &w);
		    Tcl_DecrRefCount(objPtr);
		}
		isNegative = (w < (Tcl_WideInt)0);
	    } else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
		if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
		    Tcl_Obj *objPtr;

		    if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
			goto error;
		    }
		    mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
		    objPtr = Tcl_NewBignumObj(&big);
		    Tcl_IncrRefCount(objPtr);
		    TclGetLongFromObj(NULL, objPtr, &l);
		    Tcl_DecrRefCount(objPtr);
		} else {
		    l = Tcl_WideAsLong(w);
		}







|













|







2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
	    } else if (useWide) {
		if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
		    Tcl_Obj *objPtr;

		    if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
			goto error;
		    }
		    mp_mod_2d(&big, CHAR_BIT*sizeof(Tcl_WideInt), &big);
		    objPtr = Tcl_NewBignumObj(&big);
		    Tcl_IncrRefCount(objPtr);
		    Tcl_GetWideIntFromObj(NULL, objPtr, &w);
		    Tcl_DecrRefCount(objPtr);
		}
		isNegative = (w < (Tcl_WideInt)0);
	    } else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
		if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
		    Tcl_Obj *objPtr;

		    if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
			goto error;
		    }
		    mp_mod_2d(&big, CHAR_BIT * sizeof(long), &big);
		    objPtr = Tcl_NewBignumObj(&big);
		    Tcl_IncrRefCount(objPtr);
		    TclGetLongFromObj(NULL, objPtr, &l);
		    Tcl_DecrRefCount(objPtr);
		} else {
		    l = Tcl_WideAsLong(w);
		}
Changes to generic/tclTestObj.c.
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
	    return TCL_ERROR;
	}
	if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
		&bignumValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], mp_iseven(&bignumValue));
	} else {
	    SetVarToObj(varIndex, Tcl_NewIntObj(mp_iseven(&bignumValue)));
	}
	mp_clear(&bignumValue);
	break;

    case BIGNUM_RADIXSIZE:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");







|

|







265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
	    return TCL_ERROR;
	}
	if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
		&bignumValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], !mp_isodd(&bignumValue));
	} else {
	    SetVarToObj(varIndex, Tcl_NewIntObj(!mp_isodd(&bignumValue)));
	}
	mp_clear(&bignumValue);
	break;

    case BIGNUM_RADIXSIZE:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
Changes to generic/tclTomMath.decls.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# tclTomMath.decls --
#
#	This file contains the declarations for the functions in
#	'libtommath' that are contained within the Tcl library.
#	This file is used to generate the 'tclTomMathDecls.h' and
#	'tclStubInit.c' files.
#
# If you edit this file, advance the revision number (and the epoch
# if the new stubs are not backward compatible) in tclTomMathDecls.h
#
# Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the unsupported generic interfaces.

interface tclTomMath
# hooks {tclTomMathInt}


# Declare each of the functions in the Tcl tommath interface

declare 0 generic {
    int TclBN_epoch(void)
}
declare 1 generic {
    int TclBN_revision(void)
}

declare 2 generic {
    int TclBN_mp_add(mp_int *a, mp_int *b, mp_int *c)
}
declare 3 generic {
    int TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 4 generic {
    int TclBN_mp_and(mp_int *a, mp_int *b, mp_int *c)
}
declare 5 generic {
    void TclBN_mp_clamp(mp_int *a)
}
declare 6 generic {
    void TclBN_mp_clear(mp_int *a)
}
declare 7 generic {
    void TclBN_mp_clear_multi(mp_int *a, ...)
}
declare 8 generic {
    int TclBN_mp_cmp(mp_int *a, mp_int *b)
}
declare 9 generic {
    int TclBN_mp_cmp_d(mp_int *a, mp_digit b)
}
declare 10 generic {
    int TclBN_mp_cmp_mag(mp_int *a, mp_int *b)
}
declare 11 generic {
    int TclBN_mp_copy(mp_int *a, mp_int *b)
}
declare 12 generic {
    int TclBN_mp_count_bits(mp_int *a)
}
declare 13 generic {
    int TclBN_mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r)
}
declare 14 generic {
    int TclBN_mp_div_d(mp_int *a, mp_digit b, mp_int *q, mp_digit *r)
}
declare 15 generic {
    int TclBN_mp_div_2(mp_int *a, mp_int *q)
}
declare 16 generic {
    int TclBN_mp_div_2d(mp_int *a, int b, mp_int *q, mp_int *r)
}
declare 17 generic {
    int TclBN_mp_div_3(mp_int *a, mp_int *q, mp_digit *r)
}
declare 18 generic {
    void TclBN_mp_exch(mp_int *a, mp_int *b)
}
declare 19 generic {
    int TclBN_mp_expt_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 20 generic {
    int TclBN_mp_grow(mp_int *a, int size)
}
declare 21 generic {
    int TclBN_mp_init(mp_int *a)
}
declare 22 generic {
    int TclBN_mp_init_copy(mp_int *a, mp_int *b)
}
declare 23 generic {
    int TclBN_mp_init_multi(mp_int *a, ...)
}
declare 24 generic {
    int TclBN_mp_init_set(mp_int *a, mp_digit b)
}
declare 25 generic {
    int TclBN_mp_init_size(mp_int *a, int size)
}
declare 26 generic {
    int TclBN_mp_lshd(mp_int *a, int shift)
}
declare 27 generic {
    int TclBN_mp_mod(mp_int *a, mp_int *b, mp_int *r)
}
declare 28 generic {
    int TclBN_mp_mod_2d(mp_int *a, int b, mp_int *r)
}
declare 29 generic {
    int TclBN_mp_mul(mp_int *a, mp_int *b, mp_int *p)
}
declare 30 generic {
    int TclBN_mp_mul_d(mp_int *a, mp_digit b, mp_int *p)
}
declare 31 generic {
    int TclBN_mp_mul_2(mp_int *a, mp_int *p)
}
declare 32 generic {
    int TclBN_mp_mul_2d(mp_int *a, int d, mp_int *p)
}
declare 33 generic {
    int TclBN_mp_neg(mp_int *a, mp_int *b)
}
declare 34 generic {
    int TclBN_mp_or(mp_int *a, mp_int *b, mp_int *c)
}
declare 35 generic {
    int TclBN_mp_radix_size(mp_int *a, int radix, int *size)
}
declare 36 generic {
    int TclBN_mp_read_radix(mp_int *a, const char *str, int radix)
}
declare 37 generic {
    void TclBN_mp_rshd(mp_int *a, int shift)
}
declare 38 generic {
    int TclBN_mp_shrink(mp_int *a)
}
declare 39 generic {
    void TclBN_mp_set(mp_int *a, mp_digit b)
}
declare 40 generic {
    int TclBN_mp_sqr(mp_int *a, mp_int *b)
}
declare 41 generic {
    int TclBN_mp_sqrt(mp_int *a, mp_int *b)
}
declare 42 generic {
    int TclBN_mp_sub(mp_int *a, mp_int *b, mp_int *c)
}
declare 43 generic {
    int TclBN_mp_sub_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 44 generic {
    int TclBN_mp_to_unsigned_bin(mp_int *a, unsigned char *b)
}
declare 45 generic {
    int TclBN_mp_to_unsigned_bin_n(mp_int *a, unsigned char *b,
	    unsigned long *outlen)
}
declare 46 generic {
    int TclBN_mp_toradix_n(mp_int *a, char *str, int radix, int maxlen)
}
declare 47 generic {
    int TclBN_mp_unsigned_bin_size(mp_int *a)
}
declare 48 generic {
    int TclBN_mp_xor(mp_int *a, mp_int *b, mp_int *c)
}
declare 49 generic {
    void TclBN_mp_zero(mp_int *a)
}

# internal routines to libtommath - should not be called but must be
# exported to accommodate the "tommath" extension

declare 50 generic {
    void TclBN_reverse(unsigned char *s, int len)
}
declare 51 generic {
    int TclBN_fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs)
}
declare 52 generic {
    int TclBN_fast_s_mp_sqr(mp_int *a, mp_int *b)
}
declare 53 generic {
    int TclBN_mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c)
}
declare 54 generic {
    int TclBN_mp_karatsuba_sqr(mp_int *a, mp_int *b)
}
declare 55 generic {
    int TclBN_mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
}
declare 56 generic {
    int TclBN_mp_toom_sqr(mp_int *a, mp_int *b)
}
declare 57 generic {
    int TclBN_s_mp_add(mp_int *a, mp_int *b, mp_int *c)
}
declare 58 generic {
    int TclBN_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs)
}
declare 59 generic {
    int TclBN_s_mp_sqr(mp_int *a, mp_int *b)
}
declare 60 generic {
    int TclBN_s_mp_sub(mp_int *a, mp_int *b, mp_int *c)
}
declare 61 {
    int TclBN_mp_init_set_int(mp_int *a, unsigned long i)
}
declare 62 {
    int TclBN_mp_set_int(mp_int *a, unsigned long i)
}
declare 63 {
    int TclBN_mp_cnt_lsb(mp_int *a)
}


|
|
|
<















>



|


|



|


|


|
|

|


|


|


|
|

|
|

|
|

|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|
|

|


|


|


|


|


|


|


|


|


|


|



|


|


|
|

|






|


|


|


|


|


|


|


|


|


|


|











1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# tclTomMath.decls --
#
#	This file contains the declarations for the functions in 'libtommath'
#	that are contained within the Tcl library.  This file is used to
#	generate the 'tclTomMathDecls.h' and 'tclStubInit.c' files.

#
# If you edit this file, advance the revision number (and the epoch
# if the new stubs are not backward compatible) in tclTomMathDecls.h
#
# Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the unsupported generic interfaces.

interface tclTomMath
# hooks {tclTomMathInt}
scspec EXTERN

# Declare each of the functions in the Tcl tommath interface

declare 0 {
    int TclBN_epoch(void)
}
declare 1 {
    int TclBN_revision(void)
}

declare 2 {
    int TclBN_mp_add(mp_int *a, mp_int *b, mp_int *c)
}
declare 3 {
    int TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 4 {
    int TclBN_mp_and(const mp_int *a, const mp_int *b, mp_int *c)
}
declare 5 {
    void TclBN_mp_clamp(mp_int *a)
}
declare 6 {
    void TclBN_mp_clear(mp_int *a)
}
declare 7 {
    void TclBN_mp_clear_multi(mp_int *a, ...)
}
declare 8 {
    int TclBN_mp_cmp(const mp_int *a, const mp_int *b)
}
declare 9 {
    int TclBN_mp_cmp_d(const mp_int *a, mp_digit b)
}
declare 10 {
    int TclBN_mp_cmp_mag(const mp_int *a, const mp_int *b)
}
declare 11 {
    int TclBN_mp_copy(mp_int *a, mp_int *b)
}
declare 12 {
    int TclBN_mp_count_bits(mp_int *a)
}
declare 13 {
    int TclBN_mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r)
}
declare 14 {
    int TclBN_mp_div_d(mp_int *a, mp_digit b, mp_int *q, mp_digit *r)
}
declare 15 {
    int TclBN_mp_div_2(mp_int *a, mp_int *q)
}
declare 16 {
    int TclBN_mp_div_2d(mp_int *a, int b, mp_int *q, mp_int *r)
}
declare 17 {
    int TclBN_mp_div_3(mp_int *a, mp_int *q, mp_digit *r)
}
declare 18 {
    void TclBN_mp_exch(mp_int *a, mp_int *b)
}
declare 19 {
    int TclBN_mp_expt_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 20 {
    int TclBN_mp_grow(mp_int *a, int size)
}
declare 21 {
    int TclBN_mp_init(mp_int *a)
}
declare 22 {
    int TclBN_mp_init_copy(mp_int *a, mp_int *b)
}
declare 23 {
    int TclBN_mp_init_multi(mp_int *a, ...)
}
declare 24 {
    int TclBN_mp_init_set(mp_int *a, mp_digit b)
}
declare 25 {
    int TclBN_mp_init_size(mp_int *a, int size)
}
declare 26 {
    int TclBN_mp_lshd(mp_int *a, int shift)
}
declare 27 {
    int TclBN_mp_mod(mp_int *a, mp_int *b, mp_int *r)
}
declare 28 {
    int TclBN_mp_mod_2d(mp_int *a, int b, mp_int *r)
}
declare 29 {
    int TclBN_mp_mul(mp_int *a, mp_int *b, mp_int *p)
}
declare 30 {
    int TclBN_mp_mul_d(mp_int *a, mp_digit b, mp_int *p)
}
declare 31 {
    int TclBN_mp_mul_2(mp_int *a, mp_int *p)
}
declare 32 {
    int TclBN_mp_mul_2d(mp_int *a, int d, mp_int *p)
}
declare 33 {
    int TclBN_mp_neg(mp_int *a, mp_int *b)
}
declare 34 {
    int TclBN_mp_or(const mp_int *a, const mp_int *b, mp_int *c)
}
declare 35 {
    int TclBN_mp_radix_size(mp_int *a, int radix, int *size)
}
declare 36 {
    int TclBN_mp_read_radix(mp_int *a, const char *str, int radix)
}
declare 37 {
    void TclBN_mp_rshd(mp_int *a, int shift)
}
declare 38 {
    int TclBN_mp_shrink(mp_int *a)
}
declare 39 {
    void TclBN_mp_set(mp_int *a, mp_digit b)
}
declare 40 {
    int TclBN_mp_sqr(mp_int *a, mp_int *b)
}
declare 41 {
    int TclBN_mp_sqrt(mp_int *a, mp_int *b)
}
declare 42 {
    int TclBN_mp_sub(mp_int *a, mp_int *b, mp_int *c)
}
declare 43 {
    int TclBN_mp_sub_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 44 {
    int TclBN_mp_to_unsigned_bin(mp_int *a, unsigned char *b)
}
declare 45 {
    int TclBN_mp_to_unsigned_bin_n(mp_int *a, unsigned char *b,
	    unsigned long *outlen)
}
declare 46 {
    int TclBN_mp_toradix_n(mp_int *a, char *str, int radix, int maxlen)
}
declare 47 {
    int TclBN_mp_unsigned_bin_size(mp_int *a)
}
declare 48 {
    int TclBN_mp_xor(const mp_int *a, const mp_int *b, mp_int *c)
}
declare 49 {
    void TclBN_mp_zero(mp_int *a)
}

# internal routines to libtommath - should not be called but must be
# exported to accommodate the "tommath" extension

declare 50 {
    void TclBN_reverse(unsigned char *s, int len)
}
declare 51 {
    int TclBN_fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs)
}
declare 52 {
    int TclBN_fast_s_mp_sqr(mp_int *a, mp_int *b)
}
declare 53 {
    int TclBN_mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c)
}
declare 54 {
    int TclBN_mp_karatsuba_sqr(mp_int *a, mp_int *b)
}
declare 55 {
    int TclBN_mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
}
declare 56 {
    int TclBN_mp_toom_sqr(mp_int *a, mp_int *b)
}
declare 57 {
    int TclBN_s_mp_add(mp_int *a, mp_int *b, mp_int *c)
}
declare 58 {
    int TclBN_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs)
}
declare 59 {
    int TclBN_s_mp_sqr(mp_int *a, mp_int *b)
}
declare 60 {
    int TclBN_s_mp_sub(mp_int *a, mp_int *b, mp_int *c)
}
declare 61 {
    int TclBN_mp_init_set_int(mp_int *a, unsigned long i)
}
declare 62 {
    int TclBN_mp_set_int(mp_int *a, unsigned long i)
}
declare 63 {
    int TclBN_mp_cnt_lsb(mp_int *a)
}
Changes to generic/tclTomMath.h.
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298

/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);


/* error code to char* string */
/*
char *mp_error_to_string(int code);
*/

/* ---> init and deinit bignum functions <--- */
/* init a bignum */
/*
int mp_init(mp_int *a);
*/

/* free a bignum */
/*
void mp_clear(mp_int *a);
*/

/* init a null terminated series of arguments */
/*
int mp_init_multi(mp_int *mp, ...);
*/

/* clear a null terminated series of arguments */
/*
void mp_clear_multi(mp_int *mp, ...);
*/

/* exchange two ints */
/*
void mp_exch(mp_int *a, mp_int *b);
*/

/* shrink ram required for a bignum */
/*
int mp_shrink(mp_int *a);
*/

/* grow an int to a given size */
/*
int mp_grow(mp_int *a, int size);
*/

/* init to a given number of digits */
/*
int mp_init_size(mp_int *a, int size);
*/

/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)


/* set to zero */
/*
void mp_zero(mp_int *a);
*/

/* set to a digit */







|





|









|














|




|




|






>







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);


/* error code to char* string */
/*
const char *mp_error_to_string(mp_err code);
*/

/* ---> init and deinit bignum functions <--- */
/* init a bignum */
/*
mp_err mp_init(mp_int *a);
*/

/* free a bignum */
/*
void mp_clear(mp_int *a);
*/

/* init a null terminated series of arguments */
/*
mp_err mp_init_multi(mp_int *mp, ...);
*/

/* clear a null terminated series of arguments */
/*
void mp_clear_multi(mp_int *mp, ...);
*/

/* exchange two ints */
/*
void mp_exch(mp_int *a, mp_int *b);
*/

/* shrink ram required for a bignum */
/*
mp_err mp_shrink(mp_int *a);
*/

/* grow an int to a given size */
/*
mp_err mp_grow(mp_int *a, int size);
*/

/* init to a given number of digits */
/*
mp_err mp_init_size(mp_int *a, int size);
*/

/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
#define mp_isneg(a)  (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO)

/* set to zero */
/*
void mp_zero(mp_int *a);
*/

/* set to a digit */
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
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
int mp_prime_is_divisible(mp_int *a, int *result);
*/

/* performs one Fermat test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
/*
int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
*/

/* performs one Miller-Rabin test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
/*
int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
*/

/* This gives [for a given bit size] the number of trials required
 * such that Miller-Rabin gives a prob of failure lower than 2^-96
 */
/*
int mp_prime_rabin_miller_trials(int size);
*/

/* performs t rounds of Miller-Rabin on "a" using the first
 * t prime bases.  Also performs an initial sieve of trial
 * division.  Determines if "a" is prime with probability
 * of error no more than (1/4)**t.
 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
/*
int mp_prime_is_prime(mp_int *a, int t, int *result);
*/

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
/*
int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
*/

/* makes a truly random prime of a given size (bytes),
 * call with bbs = 1 if you want it to be congruent to 3 mod 4
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 * The prime generated will be larger than 2^(8*size).
 */
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 *
 *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
 *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
 *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */
/*







|






|

















|








|

















|
|
|







673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
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
741
int mp_prime_is_divisible(mp_int *a, int *result);
*/

/* performs one Fermat test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
/*
mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, mp_bool *result);
*/

/* performs one Miller-Rabin test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
/*
mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, mp_bool *result);
*/

/* This gives [for a given bit size] the number of trials required
 * such that Miller-Rabin gives a prob of failure lower than 2^-96
 */
/*
int mp_prime_rabin_miller_trials(int size);
*/

/* performs t rounds of Miller-Rabin on "a" using the first
 * t prime bases.  Also performs an initial sieve of trial
 * division.  Determines if "a" is prime with probability
 * of error no more than (1/4)**t.
 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
/*
mp_err mp_prime_is_prime(const mp_int *a, int t, mp_bool *result);
*/

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
/*
mp_err mp_prime_next_prime(mp_int *a, int t, int bbs_style);
*/

/* makes a truly random prime of a given size (bytes),
 * call with bbs = 1 if you want it to be congruent to 3 mod 4
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 * The prime generated will be larger than 2^(8*size).
 */
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 *
 *   MP_PRIME_BBS      - make prime congruent to 3 mod 4
 *   MP_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS)
 *   MP_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */
/*
Changes to generic/tclTomMathDecls.h.
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/* unused - no macro */

#define XMALLOC(x) TclBNAlloc(x)
#define XFREE(x) TclBNFree(x)
#define XREALLOC(x,n) TclBNRealloc(x,n)
#define XCALLOC(n,x) TclBNCalloc(n,x)

/* Rename the global symbols in libtommath to avoid linkage conflicts */

#define KARATSUBA_MUL_CUTOFF TclBNKaratsubaMulCutoff
#define KARATSUBA_SQR_CUTOFF TclBNKaratsubaSqrCutoff
#define TOOM_MUL_CUTOFF TclBNToomMulCutoff
#define TOOM_SQR_CUTOFF TclBNToomSqrCutoff

#define bn_reverse TclBN_reverse
#define s_mp_reverse TclBN_reverse
#define fast_s_mp_mul_digs TclBN_fast_s_mp_mul_digs
#define s_mp_mul_digs_fast TclBN_fast_s_mp_mul_digs
#define fast_s_mp_sqr TclBN_fast_s_mp_sqr
#define s_mp_sqr_fast TclBN_fast_s_mp_sqr
#define mp_add TclBN_mp_add







<
<
<
<
<
<
<







40
41
42
43
44
45
46







47
48
49
50
51
52
53
/* unused - no macro */

#define XMALLOC(x) TclBNAlloc(x)
#define XFREE(x) TclBNFree(x)
#define XREALLOC(x,n) TclBNRealloc(x,n)
#define XCALLOC(n,x) TclBNCalloc(n,x)








#define bn_reverse TclBN_reverse
#define s_mp_reverse TclBN_reverse
#define fast_s_mp_mul_digs TclBN_fast_s_mp_mul_digs
#define s_mp_mul_digs_fast TclBN_fast_s_mp_mul_digs
#define fast_s_mp_sqr TclBN_fast_s_mp_sqr
#define s_mp_sqr_fast TclBN_fast_s_mp_sqr
#define mp_add TclBN_mp_add
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#define TclBN_mp_add_d_TCL_DECLARED
/* 3 */
EXTERN int		TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c);
#endif
#ifndef TclBN_mp_and_TCL_DECLARED
#define TclBN_mp_and_TCL_DECLARED
/* 4 */
EXTERN int		TclBN_mp_and(mp_int *a, mp_int *b, mp_int *c);

#endif
#ifndef TclBN_mp_clamp_TCL_DECLARED
#define TclBN_mp_clamp_TCL_DECLARED
/* 5 */
EXTERN void		TclBN_mp_clamp(mp_int *a);
#endif
#ifndef TclBN_mp_clear_TCL_DECLARED
#define TclBN_mp_clear_TCL_DECLARED
/* 6 */
EXTERN void		TclBN_mp_clear(mp_int *a);
#endif
#ifndef TclBN_mp_clear_multi_TCL_DECLARED
#define TclBN_mp_clear_multi_TCL_DECLARED
/* 7 */
EXTERN void		TclBN_mp_clear_multi(mp_int *a, ...);
#endif
#ifndef TclBN_mp_cmp_TCL_DECLARED
#define TclBN_mp_cmp_TCL_DECLARED
/* 8 */
EXTERN int		TclBN_mp_cmp(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_cmp_d_TCL_DECLARED
#define TclBN_mp_cmp_d_TCL_DECLARED
/* 9 */
EXTERN int		TclBN_mp_cmp_d(mp_int *a, mp_digit b);
#endif
#ifndef TclBN_mp_cmp_mag_TCL_DECLARED
#define TclBN_mp_cmp_mag_TCL_DECLARED
/* 10 */
EXTERN int		TclBN_mp_cmp_mag(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_copy_TCL_DECLARED
#define TclBN_mp_copy_TCL_DECLARED
/* 11 */
EXTERN int		TclBN_mp_copy(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_count_bits_TCL_DECLARED







|
>



















|




|




|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#define TclBN_mp_add_d_TCL_DECLARED
/* 3 */
EXTERN int		TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c);
#endif
#ifndef TclBN_mp_and_TCL_DECLARED
#define TclBN_mp_and_TCL_DECLARED
/* 4 */
EXTERN int		TclBN_mp_and(CONST mp_int *a, CONST mp_int *b,
				mp_int *c);
#endif
#ifndef TclBN_mp_clamp_TCL_DECLARED
#define TclBN_mp_clamp_TCL_DECLARED
/* 5 */
EXTERN void		TclBN_mp_clamp(mp_int *a);
#endif
#ifndef TclBN_mp_clear_TCL_DECLARED
#define TclBN_mp_clear_TCL_DECLARED
/* 6 */
EXTERN void		TclBN_mp_clear(mp_int *a);
#endif
#ifndef TclBN_mp_clear_multi_TCL_DECLARED
#define TclBN_mp_clear_multi_TCL_DECLARED
/* 7 */
EXTERN void		TclBN_mp_clear_multi(mp_int *a, ...);
#endif
#ifndef TclBN_mp_cmp_TCL_DECLARED
#define TclBN_mp_cmp_TCL_DECLARED
/* 8 */
EXTERN int		TclBN_mp_cmp(CONST mp_int *a, CONST mp_int *b);
#endif
#ifndef TclBN_mp_cmp_d_TCL_DECLARED
#define TclBN_mp_cmp_d_TCL_DECLARED
/* 9 */
EXTERN int		TclBN_mp_cmp_d(CONST mp_int *a, mp_digit b);
#endif
#ifndef TclBN_mp_cmp_mag_TCL_DECLARED
#define TclBN_mp_cmp_mag_TCL_DECLARED
/* 10 */
EXTERN int		TclBN_mp_cmp_mag(CONST mp_int *a, CONST mp_int *b);
#endif
#ifndef TclBN_mp_copy_TCL_DECLARED
#define TclBN_mp_copy_TCL_DECLARED
/* 11 */
EXTERN int		TclBN_mp_copy(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_count_bits_TCL_DECLARED
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
#define TclBN_mp_neg_TCL_DECLARED
/* 33 */
EXTERN int		TclBN_mp_neg(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_or_TCL_DECLARED
#define TclBN_mp_or_TCL_DECLARED
/* 34 */
EXTERN int		TclBN_mp_or(mp_int *a, mp_int *b, mp_int *c);

#endif
#ifndef TclBN_mp_radix_size_TCL_DECLARED
#define TclBN_mp_radix_size_TCL_DECLARED
/* 35 */
EXTERN int		TclBN_mp_radix_size(mp_int *a, int radix, int *size);
#endif
#ifndef TclBN_mp_read_radix_TCL_DECLARED







|
>







315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#define TclBN_mp_neg_TCL_DECLARED
/* 33 */
EXTERN int		TclBN_mp_neg(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_or_TCL_DECLARED
#define TclBN_mp_or_TCL_DECLARED
/* 34 */
EXTERN int		TclBN_mp_or(CONST mp_int *a, CONST mp_int *b,
				mp_int *c);
#endif
#ifndef TclBN_mp_radix_size_TCL_DECLARED
#define TclBN_mp_radix_size_TCL_DECLARED
/* 35 */
EXTERN int		TclBN_mp_radix_size(mp_int *a, int radix, int *size);
#endif
#ifndef TclBN_mp_read_radix_TCL_DECLARED
394
395
396
397
398
399
400
401

402
403
404
405
406
407
408
#define TclBN_mp_unsigned_bin_size_TCL_DECLARED
/* 47 */
EXTERN int		TclBN_mp_unsigned_bin_size(mp_int *a);
#endif
#ifndef TclBN_mp_xor_TCL_DECLARED
#define TclBN_mp_xor_TCL_DECLARED
/* 48 */
EXTERN int		TclBN_mp_xor(mp_int *a, mp_int *b, mp_int *c);

#endif
#ifndef TclBN_mp_zero_TCL_DECLARED
#define TclBN_mp_zero_TCL_DECLARED
/* 49 */
EXTERN void		TclBN_mp_zero(mp_int *a);
#endif
#ifndef TclBN_reverse_TCL_DECLARED







|
>







389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
#define TclBN_mp_unsigned_bin_size_TCL_DECLARED
/* 47 */
EXTERN int		TclBN_mp_unsigned_bin_size(mp_int *a);
#endif
#ifndef TclBN_mp_xor_TCL_DECLARED
#define TclBN_mp_xor_TCL_DECLARED
/* 48 */
EXTERN int		TclBN_mp_xor(CONST mp_int *a, CONST mp_int *b,
				mp_int *c);
#endif
#ifndef TclBN_mp_zero_TCL_DECLARED
#define TclBN_mp_zero_TCL_DECLARED
/* 49 */
EXTERN void		TclBN_mp_zero(mp_int *a);
#endif
#ifndef TclBN_reverse_TCL_DECLARED
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
    int magic;
    struct TclTomMathStubHooks *hooks;

    int (*tclBN_epoch) (void); /* 0 */
    int (*tclBN_revision) (void); /* 1 */
    int (*tclBN_mp_add) (mp_int *a, mp_int *b, mp_int *c); /* 2 */
    int (*tclBN_mp_add_d) (mp_int *a, mp_digit b, mp_int *c); /* 3 */
    int (*tclBN_mp_and) (mp_int *a, mp_int *b, mp_int *c); /* 4 */
    void (*tclBN_mp_clamp) (mp_int *a); /* 5 */
    void (*tclBN_mp_clear) (mp_int *a); /* 6 */
    void (*tclBN_mp_clear_multi) (mp_int *a, ...); /* 7 */
    int (*tclBN_mp_cmp) (mp_int *a, mp_int *b); /* 8 */
    int (*tclBN_mp_cmp_d) (mp_int *a, mp_digit b); /* 9 */
    int (*tclBN_mp_cmp_mag) (mp_int *a, mp_int *b); /* 10 */
    int (*tclBN_mp_copy) (mp_int *a, mp_int *b); /* 11 */
    int (*tclBN_mp_count_bits) (mp_int *a); /* 12 */
    int (*tclBN_mp_div) (mp_int *a, mp_int *b, mp_int *q, mp_int *r); /* 13 */
    int (*tclBN_mp_div_d) (mp_int *a, mp_digit b, mp_int *q, mp_digit *r); /* 14 */
    int (*tclBN_mp_div_2) (mp_int *a, mp_int *q); /* 15 */
    int (*tclBN_mp_div_2d) (mp_int *a, int b, mp_int *q, mp_int *r); /* 16 */
    int (*tclBN_mp_div_3) (mp_int *a, mp_int *q, mp_digit *r); /* 17 */







|



|
|
|







479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
    int magic;
    struct TclTomMathStubHooks *hooks;

    int (*tclBN_epoch) (void); /* 0 */
    int (*tclBN_revision) (void); /* 1 */
    int (*tclBN_mp_add) (mp_int *a, mp_int *b, mp_int *c); /* 2 */
    int (*tclBN_mp_add_d) (mp_int *a, mp_digit b, mp_int *c); /* 3 */
    int (*tclBN_mp_and) (CONST mp_int *a, CONST mp_int *b, mp_int *c); /* 4 */
    void (*tclBN_mp_clamp) (mp_int *a); /* 5 */
    void (*tclBN_mp_clear) (mp_int *a); /* 6 */
    void (*tclBN_mp_clear_multi) (mp_int *a, ...); /* 7 */
    int (*tclBN_mp_cmp) (CONST mp_int *a, CONST mp_int *b); /* 8 */
    int (*tclBN_mp_cmp_d) (CONST mp_int *a, mp_digit b); /* 9 */
    int (*tclBN_mp_cmp_mag) (CONST mp_int *a, CONST mp_int *b); /* 10 */
    int (*tclBN_mp_copy) (mp_int *a, mp_int *b); /* 11 */
    int (*tclBN_mp_count_bits) (mp_int *a); /* 12 */
    int (*tclBN_mp_div) (mp_int *a, mp_int *b, mp_int *q, mp_int *r); /* 13 */
    int (*tclBN_mp_div_d) (mp_int *a, mp_digit b, mp_int *q, mp_digit *r); /* 14 */
    int (*tclBN_mp_div_2) (mp_int *a, mp_int *q); /* 15 */
    int (*tclBN_mp_div_2d) (mp_int *a, int b, mp_int *q, mp_int *r); /* 16 */
    int (*tclBN_mp_div_3) (mp_int *a, mp_int *q, mp_digit *r); /* 17 */
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
    int (*tclBN_mp_mod) (mp_int *a, mp_int *b, mp_int *r); /* 27 */
    int (*tclBN_mp_mod_2d) (mp_int *a, int b, mp_int *r); /* 28 */
    int (*tclBN_mp_mul) (mp_int *a, mp_int *b, mp_int *p); /* 29 */
    int (*tclBN_mp_mul_d) (mp_int *a, mp_digit b, mp_int *p); /* 30 */
    int (*tclBN_mp_mul_2) (mp_int *a, mp_int *p); /* 31 */
    int (*tclBN_mp_mul_2d) (mp_int *a, int d, mp_int *p); /* 32 */
    int (*tclBN_mp_neg) (mp_int *a, mp_int *b); /* 33 */
    int (*tclBN_mp_or) (mp_int *a, mp_int *b, mp_int *c); /* 34 */
    int (*tclBN_mp_radix_size) (mp_int *a, int radix, int *size); /* 35 */
    int (*tclBN_mp_read_radix) (mp_int *a, CONST char *str, int radix); /* 36 */
    void (*tclBN_mp_rshd) (mp_int *a, int shift); /* 37 */
    int (*tclBN_mp_shrink) (mp_int *a); /* 38 */
    void (*tclBN_mp_set) (mp_int *a, mp_digit b); /* 39 */
    int (*tclBN_mp_sqr) (mp_int *a, mp_int *b); /* 40 */
    int (*tclBN_mp_sqrt) (mp_int *a, mp_int *b); /* 41 */
    int (*tclBN_mp_sub) (mp_int *a, mp_int *b, mp_int *c); /* 42 */
    int (*tclBN_mp_sub_d) (mp_int *a, mp_digit b, mp_int *c); /* 43 */
    int (*tclBN_mp_to_unsigned_bin) (mp_int *a, unsigned char *b); /* 44 */
    int (*tclBN_mp_to_unsigned_bin_n) (mp_int *a, unsigned char *b, unsigned long *outlen); /* 45 */
    int (*tclBN_mp_toradix_n) (mp_int *a, char *str, int radix, int maxlen); /* 46 */
    int (*tclBN_mp_unsigned_bin_size) (mp_int *a); /* 47 */
    int (*tclBN_mp_xor) (mp_int *a, mp_int *b, mp_int *c); /* 48 */
    void (*tclBN_mp_zero) (mp_int *a); /* 49 */
    void (*tclBN_reverse) (unsigned char *s, int len); /* 50 */
    int (*tclBN_fast_s_mp_mul_digs) (mp_int *a, mp_int *b, mp_int *c, int digs); /* 51 */
    int (*tclBN_fast_s_mp_sqr) (mp_int *a, mp_int *b); /* 52 */
    int (*tclBN_mp_karatsuba_mul) (mp_int *a, mp_int *b, mp_int *c); /* 53 */
    int (*tclBN_mp_karatsuba_sqr) (mp_int *a, mp_int *b); /* 54 */
    int (*tclBN_mp_toom_mul) (mp_int *a, mp_int *b, mp_int *c); /* 55 */







|













|







509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
    int (*tclBN_mp_mod) (mp_int *a, mp_int *b, mp_int *r); /* 27 */
    int (*tclBN_mp_mod_2d) (mp_int *a, int b, mp_int *r); /* 28 */
    int (*tclBN_mp_mul) (mp_int *a, mp_int *b, mp_int *p); /* 29 */
    int (*tclBN_mp_mul_d) (mp_int *a, mp_digit b, mp_int *p); /* 30 */
    int (*tclBN_mp_mul_2) (mp_int *a, mp_int *p); /* 31 */
    int (*tclBN_mp_mul_2d) (mp_int *a, int d, mp_int *p); /* 32 */
    int (*tclBN_mp_neg) (mp_int *a, mp_int *b); /* 33 */
    int (*tclBN_mp_or) (CONST mp_int *a, CONST mp_int *b, mp_int *c); /* 34 */
    int (*tclBN_mp_radix_size) (mp_int *a, int radix, int *size); /* 35 */
    int (*tclBN_mp_read_radix) (mp_int *a, CONST char *str, int radix); /* 36 */
    void (*tclBN_mp_rshd) (mp_int *a, int shift); /* 37 */
    int (*tclBN_mp_shrink) (mp_int *a); /* 38 */
    void (*tclBN_mp_set) (mp_int *a, mp_digit b); /* 39 */
    int (*tclBN_mp_sqr) (mp_int *a, mp_int *b); /* 40 */
    int (*tclBN_mp_sqrt) (mp_int *a, mp_int *b); /* 41 */
    int (*tclBN_mp_sub) (mp_int *a, mp_int *b, mp_int *c); /* 42 */
    int (*tclBN_mp_sub_d) (mp_int *a, mp_digit b, mp_int *c); /* 43 */
    int (*tclBN_mp_to_unsigned_bin) (mp_int *a, unsigned char *b); /* 44 */
    int (*tclBN_mp_to_unsigned_bin_n) (mp_int *a, unsigned char *b, unsigned long *outlen); /* 45 */
    int (*tclBN_mp_toradix_n) (mp_int *a, char *str, int radix, int maxlen); /* 46 */
    int (*tclBN_mp_unsigned_bin_size) (mp_int *a); /* 47 */
    int (*tclBN_mp_xor) (CONST mp_int *a, CONST mp_int *b, mp_int *c); /* 48 */
    void (*tclBN_mp_zero) (mp_int *a); /* 49 */
    void (*tclBN_reverse) (unsigned char *s, int len); /* 50 */
    int (*tclBN_fast_s_mp_mul_digs) (mp_int *a, mp_int *b, mp_int *c, int digs); /* 51 */
    int (*tclBN_fast_s_mp_sqr) (mp_int *a, mp_int *b); /* 52 */
    int (*tclBN_mp_karatsuba_mul) (mp_int *a, mp_int *b, mp_int *c); /* 53 */
    int (*tclBN_mp_karatsuba_sqr) (mp_int *a, mp_int *b); /* 54 */
    int (*tclBN_mp_toom_mul) (mp_int *a, mp_int *b, mp_int *c); /* 55 */
Changes to libtommath/bn_mp_and.c.
1
2
3

4
5
6
7
8

9
10
11
12
13

14

15
16

17

18

19
20
21
22
23






24
25
26
27
28


29
30

31
32
33
34
35
36
37

38

39

40

41
42
43
44
45
46
47

48
49
50
51
52
53
#include <tommath.h>
#ifdef BN_MP_AND_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by

 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.

 *

 * Tom St Denis, tomstd[email protected], http://math.libtomcrypt.com
 */



/* AND two ints together */

int
mp_and (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;







  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }


    px = b->used;
    x = b;

  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;
    x = a;
  }



  for (ix = 0; ix < px; ix++) {

    t.dp[ix] &= x->dp[ix];

  }

  /* zero digits above the last from the smallest mp_int */
  for (; ix < t.used; ix++) {
    t.dp[ix] = 0;
  }


  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif


|
>
|
<
|
|
<
>
|
|
<
<
|
>
|
>
|
<
>
|
>
|
>
|
<
|
|
<
>
>
>
>
>
>
|
<
<
<
|
>
>
|
|
>
|
<
|
|
<
<
|
>

>
|
>
|
>
|
|
<
<
<
|
|
>
|
<
<
|


1
2
3
4
5

6
7

8
9
10


11
12
13
14
15

16
17
18
19
20
21

22
23

24
25
26
27
28
29
30



31
32
33
34
35
36
37

38
39


40
41
42
43
44
45
46
47
48
49



50
51
52
53


54
55
56
#include <tommath.h>
#ifdef BN_MP_AND_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */


/* two complement and */
mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c)

{
   int used = MAX(a->used, b->used) + 1, i;
   mp_err err;


   mp_digit ac = 1, bc = 1, cc = 1;
   mp_sign csign = ((a->sign == MP_NEG) && (b->sign == MP_NEG)) ? MP_NEG : MP_ZPOS;

   if (c->alloc < used) {
      if ((err = mp_grow(c, used)) != MP_OKAY) {

         return err;
      }
   }

   for (i = 0; i < used; i++) {
      mp_digit x, y;


      /* convert to two complement if negative */

      if (a->sign == MP_NEG) {
         ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK);
         x = ac & MP_MASK;
         ac >>= MP_DIGIT_BIT;
      } else {
         x = (i >= a->used) ? 0uL : a->dp[i];
      }




      /* convert to two complement if negative */
      if (b->sign == MP_NEG) {
         bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK);
         y = bc & MP_MASK;
         bc >>= MP_DIGIT_BIT;
      } else {

         y = (i >= b->used) ? 0uL : b->dp[i];
      }



      c->dp[i] = x & y;

      /* convert to to sign-magnitude if negative */
      if (csign == MP_NEG) {
         cc += ~c->dp[i] & MP_MASK;
         c->dp[i] = cc & MP_MASK;
         cc >>= MP_DIGIT_BIT;
      }
   }




   c->used = used;
   c->sign = csign;
   mp_clamp(c);


   return MP_OKAY;
}
#endif
Changes to libtommath/bn_mp_cmp.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <tommath.h>
#ifdef BN_MP_CMP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* compare two ints (signed)*/
int
mp_cmp (mp_int * a, mp_int * b)
{
  /* compare based on sign */
  if (a->sign != b->sign) {
     if (a->sign == MP_NEG) {
        return MP_LT;
     } else {
        return MP_GT;
     }
  }
  
  /* compare digits */
  if (a->sign == MP_NEG) {
     /* if negative compare opposite direction */
     return mp_cmp_mag(b, a);
  } else {
     return mp_cmp_mag(a, b);
  }
}
#endif


|
|
<
<
|
<
<
<
<
<
<
<
<
<
<

<
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


1
2
3
4


5










6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <tommath.h>
#ifdef BN_MP_CMP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */













/* compare two ints (signed)*/

mp_ord mp_cmp(const mp_int *a, const mp_int *b)
{
   /* compare based on sign */
   if (a->sign != b->sign) {
      if (a->sign == MP_NEG) {
         return MP_LT;
      } else {
         return MP_GT;
      }
   }

   /* compare digits */
   if (a->sign == MP_NEG) {
      /* if negative compare opposite direction */
      return mp_cmp_mag(b, a);
   } else {
      return mp_cmp_mag(a, b);
   }
}
#endif
Changes to libtommath/bn_mp_cmp_d.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <tommath.h>
#ifdef BN_MP_CMP_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* compare a digit */
int mp_cmp_d(mp_int * a, mp_digit b)
{
  /* compare based on sign */
  if (a->sign == MP_NEG) {
    return MP_LT;
  }

  /* compare based on magnitude */
  if (a->used > 1) {
    return MP_GT;
  }

  /* compare the only digit of a to b */
  if (a->dp[0] > b) {
    return MP_GT;
  } else if (a->dp[0] < b) {
    return MP_LT;
  } else {
    return MP_EQ;
  }
}
#endif


|
|
<
<
|
<
<
<
<
<
<
<
<
<
<

|

|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|


1
2
3
4


5










6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <tommath.h>
#ifdef BN_MP_CMP_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */













/* compare a digit */
mp_ord mp_cmp_d(const mp_int *a, mp_digit b)
{
   /* compare based on sign */
   if (a->sign == MP_NEG) {
      return MP_LT;
   }

   /* compare based on magnitude */
   if (a->used > 1) {
      return MP_GT;
   }

   /* compare the only digit of a to b */
   if (a->dp[0] > b) {
      return MP_GT;
   } else if (a->dp[0] < b) {
      return MP_LT;
   } else {
      return MP_EQ;
   }
}
#endif
Changes to libtommath/bn_mp_cmp_mag.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <tommath.h>
#ifdef BN_MP_CMP_MAG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* compare maginitude of two ints (unsigned) */
int mp_cmp_mag (mp_int * a, mp_int * b)
{
  int     n;
  mp_digit *tmpa, *tmpb;

  /* compare based on # of non-zero digits */
  if (a->used > b->used) {
    return MP_GT;
  }
  
  if (a->used < b->used) {
    return MP_LT;
  }

  /* alias for a */
  tmpa = a->dp + (a->used - 1);

  /* alias for b */
  tmpb = b->dp + (a->used - 1);

  /* compare based on digits  */
  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
    if (*tmpa > *tmpb) {
      return MP_GT;
    }

    if (*tmpa < *tmpb) {
      return MP_LT;
    }
  }
  return MP_EQ;
}
#endif


|
|
<
<
<
<
<
<
<
<
<
<
<
<


|

|
|

|
|
|
|
|
|
|
|

|
|

|
|

|
|
|
|
|

|
|
|
|
|


1
2
3
4












5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <tommath.h>
#ifdef BN_MP_CMP_MAG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */













/* compare maginitude of two ints (unsigned) */
mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b)
{
   int     n;
   const mp_digit *tmpa, *tmpb;

   /* compare based on # of non-zero digits */
   if (a->used > b->used) {
      return MP_GT;
   }

   if (a->used < b->used) {
      return MP_LT;
   }

   /* alias for a */
   tmpa = a->dp + (a->used - 1);

   /* alias for b */
   tmpb = b->dp + (a->used - 1);

   /* compare based on digits  */
   for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
      if (*tmpa > *tmpb) {
         return MP_GT;
      }

      if (*tmpa < *tmpb) {
         return MP_LT;
      }
   }
   return MP_EQ;
}
#endif
Changes to libtommath/bn_mp_or.c.
1
2
3

4
5
6
7
8

9
10
11
12
13

14

15
16

17

18
19

20
21
22






23
24
25
26
27


28
29

30
31
32
33
34

35





36
37
38
39
40


41
42
43
44
45
46
#include <tommath.h>
#ifdef BN_MP_OR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by

 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.

 *

 * Tom St Denis, tomstd[email protected], http://math.libtomcrypt.com
 */



/* OR two ints together */
int mp_or (mp_int * a, mp_int * b, mp_int * c)

{
  int     res, ix, px;
  mp_int  t, *x;







  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }


    px = b->used;
    x = b;

  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;

    x = a;





  }

  for (ix = 0; ix < px; ix++) {
    t.dp[ix] |= x->dp[ix];
  }


  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif


|
>
|
<
|
|
<
>
|
|
<
<
|
>
|
>
|
<
>
|
>
|
|
>
|
|
<
>
>
>
>
>
>
|
<
<
<
|
>
>
|
|
>
|
<
|
|
|
>
|
>
>
>
>
>
|
|
<
<
|
>
>
|
<
<
|


1
2
3
4
5

6
7

8
9
10


11
12
13
14
15

16
17
18
19
20
21
22
23

24
25
26
27
28
29
30



31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49


50
51
52
53


54
55
56
#include <tommath.h>
#ifdef BN_MP_OR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */


/* two complement or */
mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c)

{
   int used = MAX(a->used, b->used) + 1, i;
   mp_err err;


   mp_digit ac = 1, bc = 1, cc = 1;
   mp_sign csign = ((a->sign == MP_NEG) || (b->sign == MP_NEG)) ? MP_NEG : MP_ZPOS;

   if (c->alloc < used) {
      if ((err = mp_grow(c, used)) != MP_OKAY) {

         return err;
      }
   }

   for (i = 0; i < used; i++) {
      mp_digit x, y;

      /* convert to two complement if negative */

      if (a->sign == MP_NEG) {
         ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK);
         x = ac & MP_MASK;
         ac >>= MP_DIGIT_BIT;
      } else {
         x = (i >= a->used) ? 0uL : a->dp[i];
      }




      /* convert to two complement if negative */
      if (b->sign == MP_NEG) {
         bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK);
         y = bc & MP_MASK;
         bc >>= MP_DIGIT_BIT;
      } else {

         y = (i >= b->used) ? 0uL : b->dp[i];
      }

      c->dp[i] = x | y;

      /* convert to to sign-magnitude if negative */
      if (csign == MP_NEG) {
         cc += ~c->dp[i] & MP_MASK;
         c->dp[i] = cc & MP_MASK;
         cc >>= MP_DIGIT_BIT;
      }
   }



   c->used = used;
   c->sign = csign;
   mp_clamp(c);


   return MP_OKAY;
}
#endif
Changes to libtommath/bn_mp_xor.c.
1
2
3

4
5
6
7
8

9
10
11
12
13

14

15
16

17

18

19
20
21
22
23






24
25
26
27
28


29
30

31
32
33
34
35

36





37
38
39
40
41


42
43
44
45
46
47
#include <tommath.h>
#ifdef BN_MP_XOR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by

 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.

 *

 * Tom St Denis, tomstd[email protected], http://math.libtomcrypt.com
 */



/* XOR two ints together */

int
mp_xor (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;







  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }


    px = b->used;
    x = b;

  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;

    x = a;





  }

  for (ix = 0; ix < px; ix++) {
     t.dp[ix] ^= x->dp[ix];
  }


  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif


|
>
|
<
|
|
<
>
|
|
<
<
|
>
|
>
|
<
>
|
>
|
>
|
<
|
|
<
>
>
>
>
>
>
|
<
<
<
|
>
>
|
|
>
|
<
|
|
|
>
|
>
>
>
>
>
|
|
<
<
|
>
>
|
<
<
|


1
2
3
4
5

6
7

8
9
10


11
12
13
14
15

16
17
18
19
20
21

22
23

24
25
26
27
28
29
30



31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49


50
51
52
53


54
55
56
#include <tommath.h>
#ifdef BN_MP_XOR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */


/* two complement xor */
mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c)

{
   int used = MAX(a->used, b->used) + 1, i;
   mp_err err;


   mp_digit ac = 1, bc = 1, cc = 1;
   mp_sign csign = (a->sign != b->sign) ? MP_NEG : MP_ZPOS;

   if (c->alloc < used) {
      if ((err = mp_grow(c, used)) != MP_OKAY) {

         return err;
      }
   }

   for (i = 0; i < used; i++) {
      mp_digit x, y;


      /* convert to two complement if negative */

      if (a->sign == MP_NEG) {
         ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK);
         x = ac & MP_MASK;
         ac >>= MP_DIGIT_BIT;
      } else {
         x = (i >= a->used) ? 0uL : a->dp[i];
      }




      /* convert to two complement if negative */
      if (b->sign == MP_NEG) {
         bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK);
         y = bc & MP_MASK;
         bc >>= MP_DIGIT_BIT;
      } else {

         y = (i >= b->used) ? 0uL : b->dp[i];
      }

      c->dp[i] = x ^ y;

      /* convert to to sign-magnitude if negative */
      if (csign == MP_NEG) {
         cc += ~c->dp[i] & MP_MASK;
         c->dp[i] = cc & MP_MASK;
         cc >>= MP_DIGIT_BIT;
      }
   }



   c->used = used;
   c->sign = csign;
   mp_clamp(c);


   return MP_OKAY;
}
#endif
Changes to libtommath/tommath.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32




33
34
35
36
37
38
39
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */
#ifndef BN_H_
#define BN_H_

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>

#include <tommath_class.h>

#ifndef MIN
   #define MIN(x,y) ((x)<(y)?(x):(y))
#endif

#ifndef MAX
   #define MAX(x,y) ((x)>(y)?(x):(y))
#endif





#ifdef __cplusplus
extern "C" {

/* C++ compilers don't like assigning void * to mp_digit * */
#define  OPT_CAST(x)  (x *)

|
|
<
<
|
<
<
<
<
<
<
<
<
<



<





<
<







>
>
>
>







1
2


3









4
5
6

7
8
9
10
11


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */












#ifndef BN_H_
#define BN_H_


#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>



#ifndef MIN
   #define MIN(x,y) ((x)<(y)?(x):(y))
#endif

#ifndef MAX
   #define MAX(x,y) ((x)>(y)?(x):(y))
#endif

#ifndef MP_NO_FILE
#  include <stdio.h>
#endif

#ifdef __cplusplus
extern "C" {

/* C++ compilers don't like assigning void * to mp_digit * */
#define  OPT_CAST(x)  (x *)

127
128
129
130
131
132
133




134


























135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150
151
152
153
154
155
156

157


158
159
160
161

162
163
164
165
166
167
168
169


170
171
172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251






252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
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
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335



336
337
338



339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475










476
477
478
479







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517



518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535

536
537

538
539
540
541
542
543
544
   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
#endif

#define MP_DIGIT_BIT     DIGIT_BIT
#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
#define MP_DIGIT_MAX     MP_MASK





/* equalities */


























#define MP_LT        -1   /* less than */
#define MP_EQ         0   /* equal to */
#define MP_GT         1   /* greater than */

#define MP_ZPOS       0   /* positive integer */
#define MP_NEG        1   /* negative */

#define MP_OKAY       0   /* ok result */

#define MP_MEM        -2  /* out of mem */
#define MP_VAL        -3  /* invalid input */
#define MP_RANGE      MP_VAL

#define MP_YES        1   /* yes response */
#define MP_NO         0   /* no response */

/* Primality generation flags */
#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */

typedef int           mp_err;


/* you'll have to tune these... */


extern int KARATSUBA_MUL_CUTOFF,
           KARATSUBA_SQR_CUTOFF,
           TOOM_MUL_CUTOFF,
           TOOM_SQR_CUTOFF;


/* define this to use lower memory usage routines (exptmods mostly) */
/* #define MP_LOW_MEM */

/* default precision */
#ifndef MP_PREC
   #ifndef MP_LOW_MEM
      #define MP_PREC                 32     /* default digits of precision */


   #else
      #define MP_PREC                 8      /* default digits of precision */
   #endif   
#endif

/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))

/* the infamous mp_int structure */
typedef struct  {
    int used, alloc, sign;

    mp_digit *dp;
} mp_int;

/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);


#define USED(m)    ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m)    ((m)->sign)

/* error code to char* string */
char *mp_error_to_string(int code);

/* ---> init and deinit bignum functions <--- */
/* init a bignum */
int mp_init(mp_int *a);

/* free a bignum */
void mp_clear(mp_int *a);

/* init a null terminated series of arguments */
int mp_init_multi(mp_int *mp, ...);

/* clear a null terminated series of arguments */
void mp_clear_multi(mp_int *mp, ...);

/* exchange two ints */
void mp_exch(mp_int *a, mp_int *b);

/* shrink ram required for a bignum */
int mp_shrink(mp_int *a);

/* grow an int to a given size */
int mp_grow(mp_int *a, int size);

/* init to a given number of digits */
int mp_init_size(mp_int *a, int size);

/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)


/* set to zero */
void mp_zero(mp_int *a);

/* set to a digit */
void mp_set(mp_int *a, mp_digit b);

/* set a 32-bit const */
int mp_set_int(mp_int *a, unsigned long b);

/* get a 32-bit value */
unsigned long mp_get_int(mp_int * a);

/* initialize and set a digit */
int mp_init_set (mp_int * a, mp_digit b);

/* initialize and set 32-bit value */
int mp_init_set_int (mp_int * a, unsigned long b);

/* copy, b = a */
int mp_copy(mp_int *a, mp_int *b);

/* inits and copies, a = b */
int mp_init_copy(mp_int *a, mp_int *b);

/* trim unused digits */
void mp_clamp(mp_int *a);







/* ---> digit manipulation <--- */

/* right shift by "b" digits */
void mp_rshd(mp_int *a, int b);

/* left shift by "b" digits */
int mp_lshd(mp_int *a, int b);

/* c = a / 2**b */
int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);

/* b = a/2 */
int mp_div_2(mp_int *a, mp_int *b);

/* c = a * 2**b */
int mp_mul_2d(mp_int *a, int b, mp_int *c);

/* b = a*2 */
int mp_mul_2(mp_int *a, mp_int *b);

/* c = a mod 2**d */
int mp_mod_2d(mp_int *a, int b, mp_int *c);

/* computes a = 2**b */
int mp_2expt(mp_int *a, int b);

/* Counts the number of lsbs which are zero before the first zero bit */
int mp_cnt_lsb(mp_int *a);

/* I Love Earth! */

/* makes a pseudo-random int of a given size */
int mp_rand(mp_int *a, int digits);

/* ---> binary operations <--- */
/* c = a XOR b  */
int mp_xor(mp_int *a, mp_int *b, mp_int *c);

/* c = a OR b */
int mp_or(mp_int *a, mp_int *b, mp_int *c);

/* c = a AND b */
int mp_and(mp_int *a, mp_int *b, mp_int *c);

/* ---> Basic arithmetic <--- */

/* b = -a */
int mp_neg(mp_int *a, mp_int *b);

/* b = |a| */
int mp_abs(mp_int *a, mp_int *b);

/* compare a to b */
int mp_cmp(mp_int *a, mp_int *b);

/* compare |a| to |b| */
int mp_cmp_mag(mp_int *a, mp_int *b);

/* c = a + b */
int mp_add(mp_int *a, mp_int *b, mp_int *c);

/* c = a - b */
int mp_sub(mp_int *a, mp_int *b, mp_int *c);

/* c = a * b */
int mp_mul(mp_int *a, mp_int *b, mp_int *c);

/* b = a*a  */
int mp_sqr(mp_int *a, mp_int *b);

/* a/b => cb + d == a */
int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* c = a mod b, 0 <= c < b  */
int mp_mod(mp_int *a, mp_int *b, mp_int *c);

/* ---> single digit functions <--- */

/* compare against a single digit */
int mp_cmp_d(mp_int *a, mp_digit b);

/* c = a + b */
int mp_add_d(mp_int *a, mp_digit b, mp_int *c);




/* c = a - b */
int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);




/* c = a * b */
int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);

/* a/b => cb + d == a */
int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);

/* a/3 => 3c + d == a */
int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);

/* c = a**b */
int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);

/* c = a mod b, 0 <= c < b  */
int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);

/* ---> number theory <--- */

/* d = a + b (mod c) */
int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* d = a - b (mod c) */
int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* d = a * b (mod c) */
int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* c = a * a (mod b) */
int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);

/* c = 1/a (mod b) */
int mp_invmod(mp_int *a, mp_int *b, mp_int *c);

/* c = (a, b) */
int mp_gcd(mp_int *a, mp_int *b, mp_int *c);

/* produces value such that U1*a + U2*b = U3 */
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);

/* c = [a, b] or (a*b)/(a, b) */
int mp_lcm(mp_int *a, mp_int *b, mp_int *c);

/* finds one of the b'th root of a, such that |c|**b <= |a|
 *
 * returns error if a < 0 and b is even
 */
int mp_n_root(mp_int *a, mp_digit b, mp_int *c);

/* special sqrt algo */
int mp_sqrt(mp_int *arg, mp_int *ret);

/* is number a square? */
int mp_is_square(mp_int *arg, int *ret);

/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
int mp_jacobi(mp_int *a, mp_int *n, int *c);

/* used to setup the Barrett reduction for a given modulus b */
int mp_reduce_setup(mp_int *a, mp_int *b);

/* Barrett Reduction, computes a (mod b) with a precomputed value c
 *
 * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
 * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
 */
int mp_reduce(mp_int *a, mp_int *b, mp_int *c);

/* setups the montgomery reduction */
int mp_montgomery_setup(mp_int *a, mp_digit *mp);

/* computes a = B**n mod b without division or multiplication useful for
 * normalizing numbers in a Montgomery system.
 */
int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);

/* computes x/R == x (mod N) via Montgomery Reduction */
int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);

/* returns 1 if a is a valid DR modulus */
int mp_dr_is_modulus(mp_int *a);

/* sets the value of "d" required for mp_dr_reduce */
void mp_dr_setup(mp_int *a, mp_digit *d);

/* reduces a modulo b using the Diminished Radix method */
int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);

/* returns true if a can be reduced with mp_reduce_2k */
int mp_reduce_is_2k(mp_int *a);

/* determines k value for 2k reduction */
int mp_reduce_2k_setup(mp_int *a, mp_digit *d);

/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);

/* returns true if a can be reduced with mp_reduce_2k_l */
int mp_reduce_is_2k_l(mp_int *a);

/* determines k value for 2k reduction */
int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);

/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);

/* d = a**b (mod c) */
int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* ---> Primes <--- */

/* number of primes */
#ifdef MP_8BIT
   #define PRIME_SIZE      31
#else
   #define PRIME_SIZE      256
#endif

/* table of first PRIME_SIZE primes */
extern const mp_digit ltm_prime_tab[];

/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
int mp_prime_is_divisible(mp_int *a, int *result);

/* performs one Fermat test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
int mp_prime_fermat(mp_int *a, mp_int *b, int *result);

/* performs one Miller-Rabin test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);

/* This gives [for a given bit size] the number of trials required
 * such that Miller-Rabin gives a prob of failure lower than 2^-96 
 */
int mp_prime_rabin_miller_trials(int size);











/* performs t rounds of Miller-Rabin on "a" using the first
 * t prime bases.  Also performs an initial sieve of trial
 * division.  Determines if "a" is prime with probability
 * of error no more than (1/4)**t.







 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
int mp_prime_is_prime(mp_int *a, int t, int *result);

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
int mp_prime_next_prime(mp_int *a, int t, int bbs_style);

/* makes a truly random prime of a given size (bytes),
 * call with bbs = 1 if you want it to be congruent to 3 mod 4 
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 * The prime generated will be larger than 2^(8*size).
 */
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 * 
 *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
 *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
 *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */
int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);




/* ---> radix conversion <--- */
int mp_count_bits(mp_int *a);

int mp_unsigned_bin_size(mp_int *a);
int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);
int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);

int mp_signed_bin_size(mp_int *a);
int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);
int mp_to_signed_bin(mp_int *a,  unsigned char *b);
int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);

int mp_read_radix(mp_int *a, const char *str, int radix);
int mp_toradix(mp_int *a, char *str, int radix);
int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
int mp_radix_size(mp_int *a, int radix, int *size);


int mp_fread(mp_int *a, int radix, FILE *stream);
int mp_fwrite(mp_int *a, int radix, FILE *stream);


#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
#define mp_raw_size(mp)           mp_signed_bin_size(mp)
#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))







>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
|
|
|

>



|
<
<
|
<
<
<
<
<
<

>
|
>
>
|
|
|
|
>






|
|
>
>
|
|
|







|
>
|











|



|





|








|


|


|





>




















|


|




>
>
>
>
>
>






|

|
|


|

|
|


|

|
|


|


|




|


|
|

|
|

|
|




|


|


|


|


|


|


|


|


|


|




|


|

>
>
>

|

>
>
>

|


|


|


|


|




|


|


|


|


|


|


|


|








|


|





|



|
|

|


|




|


|


|


|

|
|


|


|


|


|


|


|

|
|














|




|




|


|



>
>
>
>
>
>
>
>
>
>
|
|


>
>
>
>
>
>
>



|






|


|












|
|
|
|






|

>
>
>

|

|
|
|
|

|
|
|
|

|
|
|
|

>
|
|
>







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167


168






169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
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
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
#endif

#define MP_DIGIT_BIT     DIGIT_BIT
#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
#define MP_DIGIT_MAX     MP_MASK

/* Primality generation flags */
#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */

#ifdef MP_USE_ENUMS
typedef enum {
   MP_ZPOS = 0,
   MP_NEG = 1
} mp_sign;
typedef enum {
   MP_LT = -1,
   MP_EQ = 0,
   MP_GT = 1
} mp_ord;
typedef enum {
   MP_NO = 0,
   MP_YES = 1
} mp_bool;
typedef enum {
   MP_OKAY  = 0,
   MP_ERR   = -1,
   MP_MEM   = -2,
   MP_VAL   = -3,
   MP_ITER  = -4
} mp_err;
#else
typedef int mp_sign;
#define MP_ZPOS       0   /* positive integer */
#define MP_NEG        1   /* negative */
typedef int mp_ord;
#define MP_LT        -1   /* less than */
#define MP_EQ         0   /* equal to */
#define MP_GT         1   /* greater than */
typedef int mp_bool;
#define MP_YES        1   /* yes response */
#define MP_NO         0   /* no response */
typedef int mp_err;
#define MP_OKAY       0   /* ok result */
#define MP_ERR        -1  /* unknown error */
#define MP_MEM        -2  /* out of mem */
#define MP_VAL        -3  /* invalid input */
#define MP_RANGE      MP_VAL
#define MP_ITER       -4  /* Max. iterations reached */


#endif







/* tunable cutoffs */

#ifndef MP_FIXED_CUTOFFS
extern int
KARATSUBA_MUL_CUTOFF,
KARATSUBA_SQR_CUTOFF,
TOOM_MUL_CUTOFF,
TOOM_SQR_CUTOFF;
#endif

/* define this to use lower memory usage routines (exptmods mostly) */
/* #define MP_LOW_MEM */

/* default precision */
#ifndef MP_PREC
#   ifndef MP_LOW_MEM
#      define MP_PREC 32        /* default digits of precision */
#   elif defined(MP_8BIT)
#      define MP_PREC 16        /* default digits of precision */
#   else
#      define MP_PREC 8         /* default digits of precision */
#   endif
#endif

/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))

/* the infamous mp_int structure */
typedef struct  {
   int used, alloc;
   mp_sign sign;
   mp_digit *dp;
} mp_int;

/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);


#define USED(m)    ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m)    ((m)->sign)

/* error code to char* string */
const char *mp_error_to_string(mp_err code);

/* ---> init and deinit bignum functions <--- */
/* init a bignum */
mp_err mp_init(mp_int *a);

/* free a bignum */
void mp_clear(mp_int *a);

/* init a null terminated series of arguments */
mp_err mp_init_multi(mp_int *mp, ...);

/* clear a null terminated series of arguments */
void mp_clear_multi(mp_int *mp, ...);

/* exchange two ints */
void mp_exch(mp_int *a, mp_int *b);

/* shrink ram required for a bignum */
mp_err mp_shrink(mp_int *a);

/* grow an int to a given size */
mp_err mp_grow(mp_int *a, int size);

/* init to a given number of digits */
mp_err mp_init_size(mp_int *a, int size);

/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
#define mp_isneg(a)  (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO)

/* set to zero */
void mp_zero(mp_int *a);

/* set to a digit */
void mp_set(mp_int *a, mp_digit b);

/* set a 32-bit const */
int mp_set_int(mp_int *a, unsigned long b);

/* get a 32-bit value */
unsigned long mp_get_int(mp_int * a);

/* initialize and set a digit */
int mp_init_set (mp_int * a, mp_digit b);

/* initialize and set 32-bit value */
int mp_init_set_int (mp_int * a, unsigned long b);

/* copy, b = a */
mp_err mp_copy(const mp_int *a, mp_int *b);

/* inits and copies, a = b */
mp_err mp_init_copy(mp_int *a, const mp_int *b);

/* trim unused digits */
void mp_clamp(mp_int *a);

/* import binary data */
mp_err mp_import(mp_int *rop, size_t count, int order, size_t size, int endian, size_t nails, const void *op);

/* export binary data */
mp_err mp_export(void *rop, size_t *countp, int order, size_t size, int endian, size_t nails, const mp_int *op);

/* ---> digit manipulation <--- */

/* right shift by "b" digits */
void mp_rshd(mp_int *a, int b);

/* left shift by "b" digits */
mp_err mp_lshd(mp_int *a, int b);

/* c = a / 2**b, implemented as c = a >> b */
mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d);

/* b = a/2 */
mp_err mp_div_2(const mp_int *a, mp_int *b);

/* c = a * 2**b, implemented as c = a << b */
mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c);

/* b = a*2 */
mp_err mp_mul_2(const mp_int *a, mp_int *b);

/* c = a mod 2**b */
mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c);

/* computes a = 2**b */
mp_err mp_2expt(mp_int *a, int b);

/* Counts the number of lsbs which are zero before the first zero bit */
int mp_cnt_lsb(const mp_int *a);

/* I Love Earth! */

/* makes a pseudo-random int of a given size */
mp_err mp_rand(mp_int *a, int digits);

/* ---> binary operations <--- */
/* c = a XOR b (two complement) */
mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c);

/* c = a OR b (two complement) */
mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c);

/* c = a AND b (two complement) */
mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c);

/* ---> Basic arithmetic <--- */

/* b = -a */
mp_err mp_neg(const mp_int *a, mp_int *b);

/* b = |a| */
mp_err mp_abs(const mp_int *a, mp_int *b);

/* compare a to b */
mp_ord mp_cmp(const mp_int *a, const mp_int *b);

/* compare |a| to |b| */
mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b);

/* c = a + b */
mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c);

/* c = a - b */
mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c);

/* c = a * b */
mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c);

/* b = a*a  */
mp_err mp_sqr(const mp_int *a, mp_int *b);

/* a/b => cb + d == a */
mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d);

/* c = a mod b, 0 <= c < b  */
mp_err mp_mod(const mp_int *a, const mp_int *b, mp_int *c);

/* ---> single digit functions <--- */

/* compare against a single digit */
mp_ord mp_cmp_d(const mp_int *a, mp_digit b);

/* c = a + b */
mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c);

/* Increment "a" by one like "a++". Changes input! */
mp_err mp_incr(mp_int *a);

/* c = a - b */
mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c);

/* Decrement "a" by one like "a--". Changes input! */
mp_err mp_decr(mp_int *a);

/* c = a * b */
mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c);

/* a/b => cb + d == a */
mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d);

/* a/3 => 3c + d == a */
mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d);

/* c = a**b */
mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c);

/* c = a mod b, 0 <= c < b  */
mp_err mp_mod_d(const mp_int *a, mp_digit b, mp_digit *c);

/* ---> number theory <--- */

/* d = a + b (mod c) */
mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d);

/* d = a - b (mod c) */
mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d);

/* d = a * b (mod c) */
mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d);

/* c = a * a (mod b) */
mp_err mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c);

/* c = 1/a (mod b) */
mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c);

/* c = (a, b) */
mp_err mp_gcd(const mp_int *a, const mp_int *b, mp_int *c);

/* produces value such that U1*a + U2*b = U3 */
mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);

/* c = [a, b] or (a*b)/(a, b) */
mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c);

/* finds one of the b'th root of a, such that |c|**b <= |a|
 *
 * returns error if a < 0 and b is even
 */
int mp_n_root(mp_int *a, mp_digit b, mp_int *c);

/* special sqrt algo */
mp_err mp_sqrt(const mp_int *arg, mp_int *ret);

/* is number a square? */
mp_err mp_is_square(const mp_int *arg, mp_bool *ret);

/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
int mp_jacobi(mp_int *a, mp_int *n, int *c);

/* used to setup the Barrett reduction for a given modulus b */
mp_err mp_reduce_setup(mp_int *a, const mp_int *b);

/* Barrett Reduction, computes a (mod b) with a precomputed value c
 *
 * Assumes that 0 < x <= m*m, note if 0 > x > -(m*m) then you can merely
 * compute the reduction as -1 * mp_reduce(mp_abs(x)) [pseudo code].
 */
mp_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu);

/* setups the montgomery reduction */
mp_err mp_montgomery_setup(const mp_int *n, mp_digit *rho);

/* computes a = B**n mod b without division or multiplication useful for
 * normalizing numbers in a Montgomery system.
 */
mp_err mp_montgomery_calc_normalization(mp_int *a, const mp_int *b);

/* computes x/R == x (mod N) via Montgomery Reduction */
mp_err mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho);

/* returns 1 if a is a valid DR modulus */
mp_bool mp_dr_is_modulus(const mp_int *a);

/* sets the value of "d" required for mp_dr_reduce */
void mp_dr_setup(const mp_int *a, mp_digit *d);

/* reduces a modulo n using the Diminished Radix method */
mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k);

/* returns true if a can be reduced with mp_reduce_2k */
mp_bool mp_reduce_is_2k(const mp_int *a);

/* determines k value for 2k reduction */
mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d);

/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
mp_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d);

/* returns true if a can be reduced with mp_reduce_2k_l */
mp_bool mp_reduce_is_2k_l(const mp_int *a);

/* determines k value for 2k reduction */
mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d);

/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
mp_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d);

/* Y = G**X (mod P) */
mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y);

/* ---> Primes <--- */

/* number of primes */
#ifdef MP_8BIT
   #define PRIME_SIZE      31
#else
   #define PRIME_SIZE      256
#endif

/* table of first PRIME_SIZE primes */
extern const mp_digit ltm_prime_tab[];

/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
mp_err mp_prime_is_divisible(mp_int *a, mp_bool *result);

/* performs one Fermat test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, mp_bool *result);

/* performs one Miller-Rabin test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, mp_bool *result);

/* This gives [for a given bit size] the number of trials required
 * such that Miller-Rabin gives a prob of failure lower than 2^-96
 */
int mp_prime_rabin_miller_trials(int size);

/* performs one strong Lucas-Selfridge test of "a".
 * Sets result to 0 if composite or 1 if probable prime
 */
mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, mp_bool *result);

/* performs one Frobenius test of "a" as described by Paul Underwood.
 * Sets result to 0 if composite or 1 if probable prime
 */
mp_err mp_prime_frobenius_underwood(const mp_int *N, mp_bool *result);

/* performs t random rounds of Miller-Rabin on "a" additional to
 * bases 2 and 3.  Also performs an initial sieve of trial
 * division.  Determines if "a" is prime with probability
 * of error no more than (1/4)**t.
 * Both a strong Lucas-Selfridge to complete the BPSW test
 * and a separate Frobenius test are available at compile time.
 * With t<0 a deterministic test is run for primes up to
 * 318665857834031151167461. With t<13 (abs(t)-13) additional
 * tests with sequential small primes are run starting at 43.
 * Is Fips 186.4 compliant if called with t as computed by
 * mp_prime_rabin_miller_trials();
 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
mp_err mp_prime_is_prime(const mp_int *a, int t, mp_bool *result);

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
mp_err mp_prime_next_prime(mp_int *a, int t, int bbs_style);

/* makes a truly random prime of a given size (bytes),
 * call with bbs = 1 if you want it to be congruent to 3 mod 4
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 * The prime generated will be larger than 2^(8*size).
 */
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 *
 *   MP_PRIME_BBS      - make prime congruent to 3 mod 4
 *   MP_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS)
 *   MP_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */
mp_err mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);

/* Integer logarithm to integer base */
mp_err mp_ilogb(const mp_int *a, mp_digit base, mp_int *c);

/* ---> radix conversion <--- */
int mp_count_bits(const mp_int *a);

int mp_unsigned_bin_size(const mp_int *a);
mp_err mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);
mp_err mp_to_unsigned_bin(const mp_int *a, unsigned char *b);
mp_err mp_to_unsigned_bin_n(const mp_int * a, unsigned char *b, unsigned long *outlen);

int mp_signed_bin_size(const mp_int *a);
mp_err mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);
mp_err mp_to_signed_bin(const mp_int *a,  unsigned char *b);
mp_err mp_to_signed_bin_n(const mp_int * a, unsigned char *b, unsigned long *outlen);

mp_err mp_read_radix(mp_int *a, const char *str, int radix);
mp_err mp_toradix(const mp_int *a, char *str, int radix);
mp_err mp_toradix_n(const mp_int * a, char *str, int radix, int maxlen);
mp_err mp_radix_size(const mp_int *a, int radix, int *size);

#ifndef MP_NO_FILE
mp_err mp_fread(mp_int *a, int radix, FILE *stream);
mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream);
#endif

#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
#define mp_raw_size(mp)           mp_signed_bin_size(mp)
#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))