2
* Copyright (c) 2002 by The XFree86 Project, Inc.
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
* Except as contained in this notice, the name of the XFree86 Project shall
23
* not be used in advertising or otherwise to promote the sale, use or other
24
* dealings in this Software without prior written authorization from the
27
* Author: Paulo César Pereira de Andrade
30
/* $XFree86: xc/programs/xedit/lisp/mp/mpi.c,v 1.12 2002/11/20 07:44:43 paulo Exp $ */
35
# define finite(x) isfinite(x)
41
/* do the hard work of mpi_add and mpi_sub */
42
static void mpi_addsub(mpi *rop, mpi *op1, mpi *op2, int sub);
44
/* logical functions implementation */
45
static INLINE BNS mpi_logic(BNS op1, BNS op2, BNS op);
46
static void mpi_log(mpi *rop, mpi *op1, mpi *op2, BNS op);
48
/* internal mpi_seti, whithout memory allocation */
49
static void _mpi_seti(mpi *rop, long si);
54
static BNS onedig[1] = { 1 };
55
static mpi mpone = { 1, 1, 0, (BNS*)&onedig };
64
op->size = op->alloc = 1;
65
op->digs = mp_malloc(sizeof(BNS));
73
op->size = op->alloc = 0;
78
mpi_set(mpi *rop, mpi *op)
81
if (rop->alloc < op->size) {
82
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * op->size);
83
rop->alloc = op->size;
86
memcpy(rop->digs, op->digs, sizeof(BNS) * op->size);
92
mpi_seti(mpi *rop, long si)
113
if (rop->alloc < size) {
114
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * size);
119
/* store data in small mp integer */
120
rop->digs[0] = (BNS)ui;
122
rop->digs[1] = (BNS)(ui >> BNSBITS);
125
/* adjust result sign */
130
_mpi_seti(mpi *rop, long si)
136
if (si == MINSLONG) {
151
rop->digs[0] = (BNS)ui;
153
rop->digs[1] = (BNS)(ui >> BNSBITS);
160
mpi_setd(mpi *rop, double d)
170
d = copysign(1.0, d) * DBL_MAX;
172
/* check if number is larger than 1 */
181
mantissa = frexp(d, &exponent);
183
mantissa = -mantissa;
185
size = (exponent + (BNSBITS - 1)) / BNSBITS;
186
shift = BNSBITS - (exponent & (BNSBITS - 1));
188
/* adjust amount of memory */
189
if (rop->alloc < size) {
190
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * size);
195
/* adjust the exponent */
197
mantissa = ldexp(mantissa, -shift);
200
for (i = size - 1; i >= 0 && mantissa != 0.0; i--) {
201
mantissa = ldexp(mantissa, BNSBITS);
202
rop->digs[i] = (BNS)mantissa;
203
mantissa -= rop->digs[i];
209
if (size > 1 && rop->digs[size - 1] == 0)
215
/* how many BNS in the given base, log(base) / log(CARRY) */
217
static double str_bases[37] = {
218
0.0000000000000000, 0.0000000000000000, 0.0312500000000000,
219
0.0495300781475362, 0.0625000000000000, 0.0725602529652301,
220
0.0807800781475362, 0.0877298413143002, 0.0937500000000000,
221
0.0990601562950723, 0.1038102529652301, 0.1081072380824156,
222
0.1120300781475362, 0.1156387411919092, 0.1189798413143002,
223
0.1220903311127662, 0.1250000000000000, 0.1277332137890731,
224
0.1303101562950723, 0.1327477347951120, 0.1350602529652300,
225
0.1372599194618363, 0.1393572380824156, 0.1413613111267817,
226
0.1432800781475362, 0.1451205059304602, 0.1468887411919092,
227
0.1485902344426084, 0.1502298413143002, 0.1518119060977367,
228
0.1533403311127662, 0.1548186346995899, 0.1562500000000000,
229
0.1576373162299517, 0.1589832137890731, 0.1602900942795302,
233
static double str_bases[37] = {
234
0.0000000000000000, 0.0000000000000000, 0.0625000000000000,
235
0.0990601562950723, 0.1250000000000000, 0.1451205059304602,
236
0.1615601562950723, 0.1754596826286003, 0.1875000000000000,
237
0.1981203125901446, 0.2076205059304602, 0.2162144761648311,
238
0.2240601562950723, 0.2312774823838183, 0.2379596826286003,
239
0.2441806622255325, 0.2500000000000000, 0.2554664275781462,
240
0.2606203125901445, 0.2654954695902241, 0.2701205059304602,
241
0.2745198389236725, 0.2787144761648311, 0.2827226222535633,
242
0.2865601562950723, 0.2902410118609203, 0.2937774823838183,
243
0.2971804688852168, 0.3004596826286003, 0.3036238121954733,
244
0.3066806622255324, 0.3096372693991797, 0.3125000000000000,
245
0.3152746324599034, 0.3179664275781462, 0.3205801885590604,
251
mpi_setstr(mpi *rop, char *str, int base)
253
long i; /* counter */
254
int sign; /* result sign */
255
BNI carry; /* carry value */
256
BNI value; /* temporary value */
257
BNI size; /* size of result */
258
char *ptr; /* end of valid input */
264
/* skip leading spaces */
265
while (isspace(*str))
268
/* check if sign supplied */
273
else if (*str == '+')
276
/* skip leading zeros */
282
if (*ptr >= '0' && *ptr <= '9') {
283
if (*ptr - '0' >= base)
286
else if (*ptr >= 'A' && *ptr <= 'Z') {
287
if (*ptr - 'A' + 10 >= base)
290
else if (*ptr >= 'a' && *ptr <= 'z') {
291
if (*ptr - 'a' + 10 >= base)
300
size = (ptr - str) * str_bases[base] + 1;
302
/* make sure rop has enough storage */
303
if (rop->alloc < size) {
304
rop->digs = mp_realloc(rop->digs, size * sizeof(BNS));
309
/* initialize rop to zero */
310
memset(rop->digs, '\0', size * sizeof(BNS));
312
/* set result sign */
316
for (; str < ptr; str++) {
319
value = toupper(value);
320
value = value > '9' ? value - 'A' + 10 : value - '0';
321
value += rop->digs[0] * base;
322
carry = value >> BNSBITS;
323
rop->digs[0] = (BNS)value;
324
for (i = 1; i < size; i++) {
325
value = (BNI)rop->digs[i] * base + carry;
326
carry = value >> BNSBITS;
327
rop->digs[i] = (BNS)value;
332
if (rop->size > 1 && rop->digs[rop->size - 1] == 0)
337
mpi_add(mpi *rop, mpi *op1, mpi *op2)
339
mpi_addsub(rop, op1, op2, 0);
343
mpi_addi(mpi *rop, mpi *op1, long op2)
348
op.digs = (BNS*)digs;
351
mpi_addsub(rop, op1, &op, 0);
355
mpi_sub(mpi *rop, mpi *op1, mpi *op2)
357
mpi_addsub(rop, op1, op2, 1);
361
mpi_subi(mpi *rop, mpi *op1, long op2)
366
op.digs = (BNS*)digs;
369
mpi_addsub(rop, op1, &op, 1);
373
mpi_addsub(mpi *rop, mpi *op1, mpi *op2, int sub)
375
long xlen; /* maximum result size */
377
if (sub ^ (op1->sign == op2->sign)) {
378
/* plus one for possible carry */
379
xlen = MAX(op1->size, op2->size) + 1;
380
if (rop->alloc < xlen) {
381
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * xlen);
384
rop->size = mp_add(rop->digs, op1->digs, op2->digs,
385
op1->size, op2->size);
386
rop->sign = op1->sign;
389
long cmp; /* check for larger operator */
391
cmp = mpi_cmpabs(op1, op2);
398
xlen = MAX(op1->size, op2->size);
399
if (rop->alloc < xlen) {
400
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * xlen);
404
rop->size = mp_sub(rop->digs, op1->digs, op2->digs,
405
op1->size, op2->size);
406
rop->sign = op1->sign;
409
rop->size = mp_sub(rop->digs, op2->digs, op1->digs,
410
op2->size, op1->size);
411
rop->sign = sub ^ op2->sign;
418
mpi_mul(mpi *rop, mpi *op1, mpi *op2)
420
int sign; /* sign flag */
421
BNS *digs; /* result data */
422
long xsize; /* result size */
424
/* get result sign */
425
sign = op1->sign ^ op2->sign;
427
/* check for special cases */
428
if (op1->size == 1) {
429
if (*op1->digs == 0) {
434
else if (*op1->digs == 1) {
435
/* multiply by +-1 */
436
if (rop->alloc < op2->size) {
437
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * op2->size);
438
rop->alloc = op2->size;
440
rop->size = op2->size;
441
memmove(rop->digs, op2->digs, sizeof(BNS) * op2->size);
442
rop->sign = op2->size > 1 || *op2->digs ? sign : 0;
447
else if (op2->size == 1) {
448
if (*op2->digs == 0) {
453
else if (*op2->digs == 1) {
454
/* multiply by +-1 */
455
if (rop->alloc < op1->size) {
456
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * op1->size);
457
rop->alloc = op1->size;
459
rop->size = op1->size;
460
memmove(rop->digs, op1->digs, sizeof(BNS) * op1->size);
461
rop->sign = op1->size > 1 || *op1->digs ? sign : 0;
467
/* allocate result data and set it to zero */
468
xsize = op1->size + op2->size;
469
if (rop->digs == op1->digs || rop->digs == op2->digs)
470
/* rop is also an operand */
471
digs = mp_calloc(1, sizeof(BNS) * xsize);
473
if (rop->alloc < xsize) {
474
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * xsize);
478
memset(digs, '\0', sizeof(BNS) * xsize);
481
/* multiply operands */
482
xsize = mp_mul(digs, op1->digs, op2->digs, op1->size, op2->size);
484
/* store result in rop */
485
if (digs != rop->digs) {
486
/* if rop was an operand, free old data */
492
/* set result sign */
497
mpi_muli(mpi *rop, mpi *op1, long op2)
502
op.digs = (BNS*)digs;
505
mpi_mul(rop, op1, &op);
509
mpi_div(mpi *rop, mpi *num, mpi *den)
511
mpi_divqr(rop, NULL, num, den);
515
mpi_rem(mpi *rop, mpi *num, mpi *den)
517
mpi_divqr(NULL, rop, num, den);
521
* Could/should be changed to not allocate qdigs if qrop is NULL
522
* Performance wouldn't suffer too much with a test on every loop iteration.
525
mpi_divqr(mpi *qrop, mpi *rrop, mpi *num, mpi *den)
527
long i, j; /* counters */
528
int qsign; /* sign of quotient */
529
int rsign; /* sign of remainder */
530
BNI qsize; /* size of quotient */
531
BNI rsize; /* size of remainder */
532
BNS qest; /* estimative of quotient value */
533
BNS *qdigs, *rdigs; /* work copy or result */
534
BNS *ndigs, *ddigs; /* work copy or divisor and dividend */
535
BNI value; /* temporary result */
536
long svalue; /* signed temporary result (2's complement) */
537
BNS carry, scarry, denorm; /* carry and normalization */
538
BNI dpos, npos; /* offsets in data */
542
qsign = rsign ^ den->sign;
544
/* check for special case */
545
if (num->size < den->size) {
546
/* quotient is zero and remainder is numerator */
547
if (rrop && rrop->digs != num->digs) {
548
if (rrop->alloc < num->size) {
549
rrop->digs = mp_realloc(rrop->digs, sizeof(BNS) * num->size);
550
rrop->alloc = num->size;
552
rrop->size = num->size;
553
memcpy(rrop->digs, num->digs, sizeof(BNS) * num->size);
562
/* estimate result sizes */
564
qsize = num->size - den->size + 1;
567
npos = num->size - 1;
568
dpos = den->size - 1;
570
/* allocate space for quotient and remainder */
571
if (qrop == NULL || qrop->digs == num->digs || qrop->digs == den->digs)
572
qdigs = mp_calloc(1, sizeof(BNS) * qsize);
574
if (qrop->alloc < qsize) {
575
qrop->digs = mp_realloc(qrop->digs, sizeof(BNS) * qsize);
578
memset(qrop->digs, '\0', sizeof(BNS) * qsize);
582
if (rrop->digs == num->digs || rrop->digs == den->digs)
583
rdigs = mp_calloc(1, sizeof(BNS) * rsize);
585
if (rrop->alloc < rsize) {
586
rrop->digs = mp_realloc(rrop->digs, sizeof(BNS) * rsize);
589
memset(rrop->digs, '\0', sizeof(BNS) * rsize);
594
rdigs = NULL; /* fix gcc warning */
596
/* special case, only one word in divisor */
598
for (carry = 0, i = npos; i >= 0; i--) {
599
value = ((BNI)carry << BNSBITS) + num->digs[i];
600
qdigs[i] = (BNS)(value / den->digs[0]);
601
carry = (BNS)(value % den->digs[0]);
609
/* make work copy of numerator */
610
ndigs = mp_malloc(sizeof(BNS) * (num->size + 1));
611
/* allocate one extra word an update offset */
612
memcpy(ndigs, num->digs, sizeof(BNS) * num->size);
613
ndigs[num->size] = 0;
617
denorm = (BNS)((BNI)CARRY / ((BNI)(den->digs[dpos]) + 1));
620
/* i <= num->size because ndigs has an extra word */
621
for (carry = 0, i = 0; i <= num->size; i++) {
622
value = ndigs[i] * (BNI)denorm + carry;
623
ndigs[i] = (BNS)value;
624
carry = (BNS)(value >> BNSBITS);
626
/* make work copy of denominator */
627
ddigs = mp_malloc(sizeof(BNS) * den->size);
628
memcpy(ddigs, den->digs, sizeof(BNS) * den->size);
629
for (carry = 0, i = 0; i < den->size; i++) {
630
value = ddigs[i] * (BNI)denorm + carry;
631
ddigs[i] = (BNS)value;
632
carry = (BNS)(value >> BNSBITS);
636
/* only allocate copy of denominator if going to change it */
639
/* divide mp integers */
640
for (j = qsize - 1; j >= 0; j--, npos--) {
641
/* estimate quotient */
642
if (ndigs[npos] == ddigs[dpos])
645
qest = (BNS)((((BNI)(ndigs[npos]) << 16) + ndigs[npos - 1]) /
648
while ((value = ((BNI)(ndigs[npos]) << 16) + ndigs[npos - 1] -
649
qest * (BNI)(ddigs[dpos])) < CARRY &&
650
ddigs[dpos - 1] * (BNI)qest >
651
(value << BNSBITS) + ndigs[npos - 2])
654
/* multiply and subtract */
656
for (i = 0; i < den->size; i++) {
657
value = qest * (BNI)ddigs[i] + carry;
658
carry = (BNS)(value >> BNSBITS);
659
svalue = (long)ndigs[npos - dpos + i - 1] - (long)(value & SMASK) -
661
ndigs[npos - dpos + i - 1] = (BNS)svalue;
665
svalue = (long)ndigs[npos] - (long)(carry & SMASK) - (long)scarry;
666
ndigs[npos] = (BNS)svalue;
668
if (svalue & LMASK) {
669
/* quotient too big */
672
for (i = 0; i < den->size; i++) {
673
value = ndigs[npos - dpos + i - 1] + (BNI)carry + (BNI)ddigs[i];
674
ndigs[npos - dpos + i - 1] = (BNS)value;
675
carry = (BNS)(value >> BNSBITS);
677
ndigs[npos] += carry;
683
/* calculate remainder */
685
for (carry = 0, j = dpos; j >= 0; j--) {
686
value = ((BNI)carry << BNSBITS) + ndigs[j];
687
rdigs[j] = (BNS)(value / denorm);
688
carry = (BNS)(value % denorm);
693
if (ddigs != den->digs)
698
if (rrop->digs != rdigs)
700
/* normalize remainder */
701
for (i = rsize - 1; i >= 0; i--)
704
if (i != rsize - 1) {
717
/* normalize quotient */
719
if (qrop->digs != qdigs)
721
for (i = qsize - 1; i >= 0; i--)
724
if (i != qsize - 1) {
741
mpi_divqri(mpi *qrop, mpi *num, long den)
747
dop.digs = (BNS*)ddigs;
748
_mpi_seti(&dop, den);
750
memset(&rrop, '\0', sizeof(mpi));
752
mpi_divqr(qrop, &rrop, num, &dop);
753
remainder = rrop.digs[0];
755
remainder |= (BNI)(rrop.digs[1]) << BNSBITS;
757
remainder = -remainder;
764
mpi_divi(mpi *rop, mpi *num, long den)
769
dop.digs = (BNS*)ddigs;
770
_mpi_seti(&dop, den);
772
mpi_divqr(rop, NULL, num, &dop);
776
mpi_remi(mpi *num, long den)
778
return (mpi_divqri(NULL, num, den));
782
mpi_mod(mpi *rop, mpi *num, mpi *den)
784
mpi_rem(rop, num, den);
785
if (num->sign ^ den->sign)
786
mpi_add(rop, rop, den);
790
mpi_modi(mpi *num, long den)
794
remainder = mpi_remi(num, den);
795
if (num->sign ^ (den < 0))
802
mpi_gcd(mpi *rop, mpi *num, mpi *den)
807
/* check if result already given */
808
cmp = mpi_cmpabs(num, den);
810
/* check if num is equal to den or if num is zero */
811
if (cmp == 0 || (num->size == 1 && num->digs[0] == 0)) {
816
/* check if den is not zero */
817
if (den->size == 1 && den->digs[0] == 0) {
823
/* don't call mpi_init, relies on realloc(0, size) == malloc(size) */
824
memset(&rem, '\0', sizeof(mpi));
826
/* if num larger than den */
828
mpi_rem(&rem, num, den);
829
if (rem.size == 1 && rem.digs[0] == 0) {
839
mpi_rem(&rem, den, num);
840
if (rem.size == 1 && rem.digs[0] == 0) {
850
/* loop using positive values */
851
rop->sign = rem.sign = 0;
853
/* cannot optimize this inverting rem/rop assignment earlier
854
* because rop mais be an operand */
857
/* Euclides algorithm */
859
mpi_rem(&rem, &rem, rop);
860
if (rem.size == 1 && rem.digs[0] == 0)
868
mpi_lcm(mpi *rop, mpi *num, mpi *den)
872
/* check for zero operand */
873
if ((num->size == 1 && num->digs[0] == 0) ||
874
(den->size == 1 && den->digs[0] == 0)) {
880
/* don't call mpi_init, relies on realloc(0, size) == malloc(size) */
881
memset(&gcd, '\0', sizeof(mpi));
883
mpi_gcd(&gcd, num, den);
884
mpi_div(&gcd, den, &gcd);
885
mpi_mul(rop, &gcd, num);
892
mpi_pow(mpi *rop, mpi *op, unsigned long exp)
897
mpi_mul(rop, op, op);
900
/* check for op**0 */
911
else if (op->size == 1) {
912
if (op->digs[0] == 0) {
916
else if (op->digs[0] == 1) {
917
mpi_seti(rop, op->sign && (exp & 1) ? -1 : 1);
922
memset(&zop, '\0', sizeof(mpi));
923
memset(&top, '\0', sizeof(mpi));
926
for (--exp; exp; exp >>= 1) {
928
mpi_mul(&zop, &top, &zop);
929
mpi_mul(&top, &top, &top);
933
rop->sign = zop.sign;
935
rop->digs = zop.digs;
936
rop->size = zop.size;
939
/* Find integer root of given number using the iteration
940
* x{n+1} = ((K-1) * x{n} + N / x{n}^(K-1)) / K
943
mpi_root(mpi *rop, mpi *op, unsigned long nth)
948
mpi *r, t, temp, quot, old, rem;
952
/* divide by zero op**1/0 */
954
int one = 1, zero = 0;
957
/* result is complex */
958
if (sign && !(nth & 1)) {
959
int one = 1, zero = 0;
963
/* special case op**1/1 = op */
969
bits = mpi_getsize(op, 2) - 2;
971
if (bits < 0 || bits / nth == 0) {
972
/* integral root is surely less than 2 */
973
exact = op->size == 1 && (op->digs[0] == 1 || op->digs[0] == 0);
974
mpi_seti(rop, sign ? -1 : op->digs[0] == 0 ? 0 : 1);
984
memset(r, '\0', sizeof(mpi));
986
memset(&temp, '\0', sizeof(mpi));
987
memset(", '\0', sizeof(mpi));
988
memset(&old, '\0', sizeof(mpi));
989
memset(&rem, '\0', sizeof(mpi));
994
/* root aproximation */
995
mpi_ash(r, op, -(bits - (bits / nth)));
998
mpi_pow(&temp, r, nth - 1);
999
mpi_divqr(", &rem, op, &temp);
1000
cmp = mpi_cmpabs(r, ");
1002
exact = mpi_cmpi(&rem, 0) == 0;
1006
if (mpi_cmpabs(r, &old) == 0) {
1012
mpi_muli(&temp, r, nth - 1);
1013
mpi_add(", ", &temp);
1014
mpi_divi(r, ", nth);
1031
* Find square root using the iteration:
1032
* x{n+1} = (x{n}+N/x{n})/2
1035
mpi_sqrt(mpi *rop, mpi *op)
1039
mpi *r, t, quot, rem, old;
1041
/* result is complex */
1043
int one = 1, zero = 0;
1047
bits = mpi_getsize(op, 2) - 2;
1050
/* integral root is surely less than 2 */
1051
exact = op->size == 1 && (op->digs[0] == 1 || op->digs[0] == 0);
1052
mpi_seti(rop, op->digs[0] == 0 ? 0 : 1);
1054
return (exact == 1);
1062
memset(r, '\0', sizeof(mpi));
1064
memset(", '\0', sizeof(mpi));
1065
memset(&rem, '\0', sizeof(mpi));
1066
memset(&old, '\0', sizeof(mpi));
1068
/* root aproximation */
1069
mpi_ash(r, op, -(bits - (bits / 2)));
1072
if (mpi_cmpabs(r, &old) == 0) {
1076
mpi_divqr(", &rem, op, r);
1077
cmp = mpi_cmpabs(", r);
1079
exact = mpi_cmpi(&rem, 0) == 0;
1082
else if (cmp > 0 && rem.size == 1 && rem.digs[0] == 0)
1083
mpi_subi(", ", 1);
1085
mpi_add(r, r, ");
1100
mpi_ash(mpi *rop, mpi *op, long shift)
1102
long i; /* counter */
1103
long xsize; /* maximum result size */
1106
/* check for 0 shift, multiply/divide by 1 */
1109
if (rop->alloc < op->size) {
1110
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * op->size);
1111
rop->alloc = op->size;
1113
rop->size = op->size;
1114
memcpy(rop->digs, op->digs, sizeof(BNS) * op->size);
1119
else if (op->size == 1 && op->digs[0] == 0) {
1127
/* check shift and initialize */
1129
xsize = op->size + (shift / BNSBITS) + 1;
1131
xsize = op->size - ((-shift) / BNSBITS);
1134
rop->sign = op->sign;
1135
rop->digs[0] = op->sign ? 1 : 0;
1141
/* allocate/adjust memory for result */
1143
digs = mp_malloc(sizeof(BNS) * xsize);
1145
if (rop->alloc < xsize) {
1146
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * xsize);
1152
/* left shift, multiply by power of two */
1154
rop->size = mp_lshift(digs, op->digs, op->size, shift);
1155
/* right shift, divide by power of two */
1162
words = -shift / BNSBITS;
1163
bits = -shift % BNSBITS;
1164
for (i = 0; i < words; i++)
1165
carry |= op->digs[xsize + i];
1167
for (i = 0; i < bits; i++)
1168
if (op->digs[op->size - xsize] & (1 << i)) {
1174
rop->size = mp_rshift(digs, op->digs, op->size, -shift);
1177
/* emulates two's complement subtracting 1 from the result */
1178
rop->size = mp_add(digs, digs, mpone.digs, rop->size, 1);
1181
if (rop->digs != digs) {
1183
rop->alloc = rop->size;
1186
rop->sign = op->sign;
1190
mpi_logic(BNS op1, BNS op2, BNS op)
1205
mpi_log(mpi *rop, mpi *op1, mpi *op2, BNS op)
1207
long i; /* counter */
1208
long c, c1, c2; /* carry */
1209
BNS *digs, *digs1, *digs2; /* pointers to mp data */
1210
BNI size, size1, size2;
1211
BNS sign, sign1, sign2;
1212
BNS n, n1, n2; /* logical operands */
1219
sign1 = op1->sign ? SMASK : 0;
1220
sign2 = op2->sign ? SMASK : 0;
1222
sign = mpi_logic(sign1, sign2, op);
1224
size = MAX(size1, size2);
1227
if (rop->alloc < size) {
1228
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * size);
1238
/* apply logical operation */
1239
for (i = 0; i < size; i++) {
1243
sum = (BNI)(BNS)(~digs1[i]) + c1;
1244
c1 = (long)(sum >> BNSBITS);
1253
sum = (BNI)(BNS)(~digs2[i]) + c2;
1254
c2 = (long)(sum >> BNSBITS);
1260
n = mpi_logic(n1, n2, op);
1262
sum = (BNI)(BNS)(~n) + c;
1263
c = (long)(sum >> BNSBITS);
1271
for (i = size - 1; i >= 0; i--)
1274
if (i != size - 1) {
1283
rop->sign = sign != 0;
1288
mpi_and(mpi *rop, mpi *op1, mpi *op2)
1290
mpi_log(rop, op1, op2, '&');
1294
mpi_ior(mpi *rop, mpi *op1, mpi *op2)
1296
mpi_log(rop, op1, op2, '|');
1300
mpi_xor(mpi *rop, mpi *op1, mpi *op2)
1302
mpi_log(rop, op1, op2, '^');
1306
mpi_com(mpi *rop, mpi *op)
1308
static BNS digs[1] = { 1 };
1309
static mpi one = { 0, 1, 1, (BNS*)&digs };
1311
mpi_log(rop, rop, &one, '^');
1315
mpi_neg(mpi *rop, mpi *op)
1317
int sign = op->sign ^ 1;
1319
if (rop->digs != op->digs) {
1320
if (rop->alloc < op->size) {
1321
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * rop->size);
1322
rop->alloc = op->size;
1324
rop->size = op->size;
1325
memcpy(rop->digs, op->digs, sizeof(BNS) * rop->size);
1332
mpi_abs(mpi *rop, mpi *op)
1334
if (rop->digs != op->digs) {
1335
if (rop->alloc < op->size) {
1336
rop->digs = mp_realloc(rop->digs, sizeof(BNS) * rop->size);
1337
rop->alloc = op->size;
1339
rop->size = op->size;
1340
memcpy(rop->digs, op->digs, sizeof(BNS) * rop->size);
1347
mpi_cmp(mpi *op1, mpi *op2)
1349
if (op1->sign ^ op2->sign)
1350
return (op1->sign ? -1 : 1);
1352
if (op1->size == op2->size) {
1355
for (i = op1->size - 1; i >= 0; i--)
1356
if ((cmp = (long)op1->digs[i] - (long)op2->digs[i]) != 0)
1359
return (cmp == 0 ? 0 : (cmp < 0) ^ op1->sign ? -1 : 1);
1362
return ((op1->size < op2->size) ^ op1->sign ? -1 : 1);
1366
mpi_cmpi(mpi *op1, long op2)
1371
return (op1->sign ? -1 : 1);
1374
if (op1->size == 2) {
1375
cmp |= (long)op1->digs[1] << BNSBITS;
1376
if (cmp == MINSLONG)
1377
return (op2 == cmp && op1->sign ? 0 : op1->sign ? -1 : 1);
1386
mpi_cmpabs(mpi *op1, mpi *op2)
1388
if (op1->size == op2->size) {
1391
for (i = op1->size - 1; i >= 0; i--)
1392
if ((cmp = (long)op1->digs[i] - (long)op2->digs[i]) != 0)
1398
return ((op1->size < op2->size) ? -1 : 1);
1402
mpi_cmpabsi(mpi *op1, long op2)
1411
cmp |= (unsigned long)op1->digs[1] << BNSBITS;
1413
return (cmp > op2 ? 1 : cmp == op2 ? 0 : -1);
1419
return (op->sign ? -1 : op->size > 1 || op->digs[0] ? 1 : 0);
1423
mpi_swap(mpi *op1, mpi *op2)
1428
memcpy(&swap, op1, sizeof(mpi));
1429
memcpy(op1, op2, sizeof(mpi));
1430
memcpy(op2, &swap, sizeof(mpi));
1439
else if (op->size == 2) {
1440
unsigned long value = ((BNI)(op->digs[1]) << BNSBITS) | op->digs[0];
1442
if (value & MINSLONG)
1443
return (op->sign && value == MINSLONG) ? 1 : 0;
1456
value = op->digs[0];
1458
value |= (BNI)(op->digs[1]) << BNSBITS;
1460
return (op->sign && value != MINSLONG ? -value : value);
1470
#define FLOATDIGS sizeof(double) / sizeof(BNS)
1474
d = (BNI)(op->digs[1]) << BNSBITS;
1477
return (op->sign ? -d : d);
1482
for (i = 0, len = op->size; len > 0 && i < FLOATDIGS; i++)
1483
d = ldexp(d, BNSBITS) + op->digs[--len];
1484
d = frexp(d, &exponent);
1486
exponent += len * BNSBITS;
1491
d = ldexp(d, exponent);
1493
return (op->sign ? -d : d);
1496
/* how many digits in a given base, floor(log(CARRY) / log(base)) */
1498
static char dig_bases[37] = {
1499
0, 0, 32, 20, 16, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8,
1500
8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6,
1504
static char dig_bases[37] = {
1505
0, 0, 16, 10, 8, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4,
1506
4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1511
/* how many digits per bit in a given base, log(2) / log(base) */
1512
static double bit_bases[37] = {
1513
0.0000000000000000, 0.0000000000000000, 1.0000000000000000,
1514
0.6309297535714575, 0.5000000000000000, 0.4306765580733931,
1515
0.3868528072345416, 0.3562071871080222, 0.3333333333333334,
1516
0.3154648767857287, 0.3010299956639811, 0.2890648263178878,
1517
0.2789429456511298, 0.2702381544273197, 0.2626495350371936,
1518
0.2559580248098155, 0.2500000000000000, 0.2446505421182260,
1519
0.2398124665681315, 0.2354089133666382, 0.2313782131597592,
1520
0.2276702486969530, 0.2242438242175754, 0.2210647294575037,
1521
0.2181042919855316, 0.2153382790366965, 0.2127460535533632,
1522
0.2103099178571525, 0.2080145976765095, 0.2058468324604344,
1523
0.2037950470905062, 0.2018490865820999, 0.2000000000000000,
1524
0.1982398631705605, 0.1965616322328226, 0.1949590218937863,
1528
/* normalization base for string conversion, pow(base, dig_bases[base]) & ~CARRY */
1530
static BNS big_bases[37] = {
1531
0x00000001, 0x00000001, 0x00000000, 0xCFD41B91, 0x00000000, 0x48C27395,
1532
0x81BF1000, 0x75DB9C97, 0x40000000, 0xCFD41B91, 0x3B9ACA00, 0x8C8B6D2B,
1533
0x19A10000, 0x309F1021, 0x57F6C100, 0x98C29B81, 0x00000000, 0x18754571,
1534
0x247DBC80, 0x3547667B, 0x4C4B4000, 0x6B5A6E1D, 0x94ACE180, 0xCAF18367,
1535
0x0B640000, 0x0E8D4A51, 0x1269AE40, 0x17179149, 0x1CB91000, 0x23744899,
1536
0x2B73A840, 0x34E63B41, 0x40000000, 0x4CFA3CC1, 0x5C13D840, 0x6D91B519,
1540
static BNS big_bases[37] = {
1541
0x0001, 0x0001, 0x0000, 0xE6A9, 0x0000, 0x3D09, 0xB640, 0x41A7, 0x8000,
1542
0xE6A9, 0x2710, 0x3931, 0x5100, 0x6F91, 0x9610, 0xC5C1, 0x0000, 0x1331,
1543
0x16C8, 0x1ACB, 0x1F40, 0x242D, 0x2998, 0x2F87, 0x3600, 0x3D09, 0x44A8,
1544
0x4CE3, 0x55C0, 0x5F45, 0x6978, 0x745F, 0x8000, 0x8C61, 0x9988, 0xA77B,
1550
mpi_getsize(mpi *op, int base)
1552
unsigned long value, bits;
1554
value = op->digs[op->size - 1];
1556
/* count leading bits */
1558
unsigned long count, carry;
1560
for (count = 0, carry = CARRY >> 1; carry; count++, carry >>= 1)
1564
bits = BNSBITS - count;
1569
return ((bits + (op->size - 1) * BNSBITS) * bit_bases[base] + 1);
1573
mpi_getstr(char *str, mpi *op, int base)
1575
long i; /* counter */
1576
BNS *digs, *xdigs; /* copy of op data */
1577
BNI size; /* size of op */
1578
BNI digits; /* digits per word in given base */
1579
BNI bigbase; /* big base of given base */
1580
BNI strsize; /* size of resulting string */
1581
char *cp; /* pointer in str for conversion */
1585
strsize = mpi_getsize(op, base) + op->sign + 1;
1588
str = mp_malloc(strsize);
1590
/* check for zero */
1591
if (size == 1 && op->digs[0] == 0) {
1598
digits = dig_bases[base];
1599
bigbase = big_bases[base];
1604
/* make copy of op data and adjust digs */
1605
xdigs = mp_malloc(size * sizeof(BNS));
1606
memcpy(xdigs, op->digs, size * sizeof(unsigned short));
1607
digs = xdigs + size - 1;
1609
/* convert to string */
1613
BNS quotient, remainder = 0;
1615
/* if power of two base */
1616
if ((base & (base - 1)) == 0) {
1617
for (i = 0; i < size; i++) {
1618
quotient = remainder;
1619
remainder = digs[-i];
1620
digs[-i] = quotient;
1621
if (count < 0 && quotient)
1626
for (i = 0; i < size; i++) {
1627
value = digs[-i] + ((BNI)remainder << BNSBITS);
1628
quotient = (BNS)(value / bigbase);
1629
remainder = (BNS)(value % bigbase);
1630
digs[-i] = quotient;
1631
if (count < 0 && quotient)
1635
quotient = remainder;
1636
for (i = 0; i < digits; i++) {
1637
if (quotient == 0 && count < 0)
1639
remainder = quotient % base;
1641
*--cp = remainder < 10 ? remainder + '0' : remainder - 10 + 'A';
1653
/* remove any extra characters */