Home | History | Annotate | Line # | Download | only in mp
      1 /*
      2  * Copyright (c) 2002 by The XFree86 Project, Inc.
      3  *
      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:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     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
     20  * SOFTWARE.
     21  *
     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
     25  * XFree86 Project.
     26  *
     27  * Author: Paulo Csar Pereira de Andrade
     28  */
     29 
     30 /* $XFree86: xc/programs/xedit/lisp/mp/mpi.c,v 1.12 2002/11/20 07:44:43 paulo Exp $ */
     31 
     32 #include "mp.h"
     33 
     34 #ifdef __APPLE__
     35 # define finite(x) isfinite(x)
     36 #endif
     37 
     38 /*
     39  * Prototypes
     40  */
     41 	/* do the hard work of mpi_add and mpi_sub */
     42 static void mpi_addsub(mpi *rop, mpi *op1, mpi *op2, int sub);
     43 
     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);
     47 
     48 	/* internal mpi_seti, whithout memory allocation */
     49 static void _mpi_seti(mpi *rop, long si);
     50 
     51 /*
     52  * Initialization
     53  */
     54 static BNS onedig[1] = { 1 };
     55 static mpi mpone = { 1, 1, 0, (BNS*)&onedig };
     56 
     57 /*
     58  * Implementation
     59  */
     60 void
     61 mpi_init(mpi *op)
     62 {
     63     op->sign = 0;
     64     op->size = op->alloc = 1;
     65     op->digs = mp_malloc(sizeof(BNS));
     66     op->digs[0] = 0;
     67 }
     68 
     69 void
     70 mpi_clear(mpi *op)
     71 {
     72     op->sign = 0;
     73     op->size = op->alloc = 0;
     74     mp_free(op->digs);
     75 }
     76 
     77 void
     78 mpi_set(mpi *rop, mpi *op)
     79 {
     80     if (rop != op) {
     81 	if (rop->alloc < op->size) {
     82 	    rop->digs = mp_realloc(rop->digs, sizeof(BNS) * op->size);
     83 	    rop->alloc = op->size;
     84 	}
     85 	rop->size = op->size;
     86 	memcpy(rop->digs, op->digs, sizeof(BNS) * op->size);
     87 	rop->sign = op->sign;
     88     }
     89 }
     90 
     91 void
     92 mpi_seti(mpi *rop, long si)
     93 {
     94     unsigned long ui;
     95     int sign = si < 0;
     96     int size;
     97 
     98     if (si == MINSLONG) {
     99 	ui = MINSLONG;
    100 	size = 2;
    101     }
    102     else {
    103 	if (sign)
    104 	    ui = -si;
    105 	else
    106 	    ui = si;
    107 	if (ui < CARRY)
    108 	    size = 1;
    109 	else
    110 	    size = 2;
    111     }
    112 
    113     if (rop->alloc < size) {
    114 	rop->digs = mp_realloc(rop->digs, sizeof(BNS) * size);
    115 	rop->alloc = size;
    116     }
    117     rop->size = size;
    118 
    119     /* store data in small mp integer */
    120     rop->digs[0] = (BNS)ui;
    121     if (size > 1)
    122 	rop->digs[1] = (BNS)(ui >> BNSBITS);
    123     rop->size = size;
    124 
    125     /* adjust result sign */
    126     rop->sign = sign;
    127 }
    128 
    129 static void
    130 _mpi_seti(mpi *rop, long si)
    131 {
    132     unsigned long ui;
    133     int sign = si < 0;
    134     int size;
    135 
    136     if (si == MINSLONG) {
    137 	ui = MINSLONG;
    138 	size = 2;
    139     }
    140     else {
    141 	if (sign)
    142 	    ui = -si;
    143 	else
    144 	    ui = si;
    145 	if (ui < CARRY)
    146 	    size = 1;
    147 	else
    148 	    size = 2;
    149     }
    150 
    151     rop->digs[0] = (BNS)ui;
    152     if (size > 1)
    153 	rop->digs[1] = (BNS)(ui >> BNSBITS);
    154     rop->size = size;
    155 
    156     rop->sign = sign;
    157 }
    158 
    159 void
    160 mpi_setd(mpi *rop, double d)
    161 {
    162     long i;
    163     double mantissa;
    164     int shift, exponent;
    165     BNI size;
    166 
    167     if (isnan(d))
    168 	d = 0.0;
    169     else if (!finite(d))
    170 	d = copysign(1.0, d) * DBL_MAX;
    171 
    172     /* check if number is larger than 1 */
    173     if (fabs(d) < 1.0) {
    174 	rop->digs[0] = 0;
    175 	rop->size = 1;
    176 	rop->sign = d < 0.0;
    177 
    178 	return;
    179     }
    180 
    181     mantissa = frexp(d, &exponent);
    182     if (mantissa < 0)
    183 	mantissa = -mantissa;
    184 
    185     size = (exponent + (BNSBITS - 1)) / BNSBITS;
    186     shift = BNSBITS - (exponent & (BNSBITS - 1));
    187 
    188     /* adjust amount of memory */
    189     if (rop->alloc < size) {
    190 	rop->digs = mp_realloc(rop->digs, sizeof(BNS) * size);
    191 	rop->alloc = size;
    192     }
    193     rop->size = size;
    194 
    195     /* adjust the exponent */
    196     if (shift < BNSBITS)
    197 	mantissa = ldexp(mantissa, -shift);
    198 
    199     /* convert double */
    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];
    204     }
    205     for (; i >= 0; i--)
    206 	rop->digs[i] = 0;
    207 
    208     /* normalize */
    209     if (size > 1 && rop->digs[size - 1] == 0)
    210 	--rop->size;
    211 
    212     rop->sign = d < 0.0;
    213 }
    214 
    215 /* how many BNS in the given base, log(base) / log(CARRY) */
    216 #ifdef LONG64
    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,
    230     0.1615601562950723,
    231 };
    232 #else
    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,
    246     0.3231203125901446,
    247 };
    248 #endif
    249 
    250 void
    251 mpi_setstr(mpi *rop, char *str, int base)
    252 {
    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 */
    259 
    260     /* initialization */
    261     sign = 0;
    262     carry = 0;
    263 
    264     /* skip leading spaces */
    265     while (isspace(*str))
    266 	++str;
    267 
    268     /* check if sign supplied */
    269     if (*str == '-') {
    270 	sign = 1;
    271 	++str;
    272     }
    273     else if (*str == '+')
    274 	++str;
    275 
    276     /* skip leading zeros */
    277     while (*str == '0')
    278 	++str;
    279 
    280     ptr = str;
    281     while (*ptr) {
    282 	if (*ptr >= '0' && *ptr <= '9') {
    283 	    if (*ptr - '0' >= base)
    284 		break;
    285 	}
    286 	else if (*ptr >= 'A' && *ptr <= 'Z') {
    287 	    if (*ptr - 'A' + 10 >= base)
    288 		break;
    289 	}
    290 	else if (*ptr >= 'a' && *ptr <= 'z') {
    291 	    if (*ptr - 'a' + 10 >= base)
    292 		break;
    293 	}
    294 	else
    295 	    break;
    296 	++ptr;
    297     }
    298 
    299     /* resulting size */
    300     size = (ptr - str) * str_bases[base] + 1;
    301 
    302     /* make sure rop has enough storage */
    303     if (rop->alloc < size) {
    304 	rop->digs = mp_realloc(rop->digs, size * sizeof(BNS));
    305 	rop->alloc = size;
    306     }
    307     rop->size = size;
    308 
    309     /* initialize rop to zero */
    310     memset(rop->digs, '\0', size * sizeof(BNS));
    311 
    312     /* set result sign */
    313     rop->sign = sign;
    314 
    315     /* convert string */
    316     for (; str < ptr; str++) {
    317 	value = *str;
    318 	if (islower(value))
    319 	    value = toupper(value);
    320 	value = value > '9' ? value - 'A' + 10 : value - '0';
    321 	value += (BNI)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;
    328 	}
    329     }
    330 
    331     /* normalize */
    332     if (rop->size > 1 && rop->digs[rop->size - 1] == 0)
    333 	--rop->size;
    334 }
    335 
    336 void
    337 mpi_add(mpi *rop, mpi *op1, mpi *op2)
    338 {
    339     mpi_addsub(rop, op1, op2, 0);
    340 }
    341 
    342 void
    343 mpi_addi(mpi *rop, mpi *op1, long op2)
    344 {
    345     BNS digs[2];
    346     mpi op;
    347 
    348     op.digs = (BNS*)digs;
    349     _mpi_seti(&op, op2);
    350 
    351     mpi_addsub(rop, op1, &op, 0);
    352 }
    353 
    354 void
    355 mpi_sub(mpi *rop, mpi *op1, mpi *op2)
    356 {
    357     mpi_addsub(rop, op1, op2, 1);
    358 }
    359 
    360 void
    361 mpi_subi(mpi *rop, mpi *op1, long op2)
    362 {
    363     BNS digs[2];
    364     mpi op;
    365 
    366     op.digs = (BNS*)digs;
    367     _mpi_seti(&op, op2);
    368 
    369     mpi_addsub(rop, op1, &op, 1);
    370 }
    371 
    372 static void
    373 mpi_addsub(mpi *rop, mpi *op1, mpi *op2, int sub)
    374 {
    375     long xlen;				/* maximum result size */
    376 
    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);
    382 	    rop->alloc = xlen;
    383 	}
    384 	rop->size = mp_add(rop->digs, op1->digs, op2->digs,
    385 			   op1->size, op2->size);
    386 	rop->sign = op1->sign;
    387     }
    388     else {
    389 	long cmp;			/* check for larger operator */
    390 
    391 	cmp = mpi_cmpabs(op1, op2);
    392 	if (cmp == 0) {
    393 	    rop->digs[0] = 0;
    394 	    rop->size = 1;
    395 	    rop->sign = 0;
    396 	}
    397 	else {
    398 	    xlen = MAX(op1->size, op2->size);
    399 	    if (rop->alloc < xlen) {
    400 		rop->digs = mp_realloc(rop->digs, sizeof(BNS) * xlen);
    401 		rop->alloc = xlen;
    402 	    }
    403 	    if (cmp > 0) {
    404 		rop->size = mp_sub(rop->digs, op1->digs, op2->digs,
    405 				   op1->size, op2->size);
    406 		rop->sign = op1->sign;
    407 	    }
    408 	    else {
    409 		rop->size = mp_sub(rop->digs, op2->digs, op1->digs,
    410 				   op2->size, op1->size);
    411 		rop->sign = sub ^ op2->sign;
    412 	    }
    413 	}
    414     }
    415 }
    416 
    417 void
    418 mpi_mul(mpi *rop, mpi *op1, mpi *op2)
    419 {
    420     int sign;				/* sign flag */
    421     BNS *digs;				/* result data */
    422     long xsize;				/* result size */
    423 
    424     /* get result sign */
    425     sign = op1->sign ^ op2->sign;
    426 
    427     /* check for special cases */
    428     if (op1->size == 1) {
    429 	if (*op1->digs == 0) {
    430 	    /* multiply by 0 */
    431 	    mpi_seti(rop, 0);
    432 	    return;
    433 	}
    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;
    439 	    }
    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;
    443 
    444 	    return;
    445 	}
    446     }
    447     else if (op2->size == 1) {
    448 	if (*op2->digs == 0) {
    449 	    /* multiply by 0 */
    450 	    mpi_seti(rop, 0);
    451 	    return;
    452 	}
    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;
    458 	    }
    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;
    462 
    463 	    return;
    464 	}
    465     }
    466 
    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);
    472     else {
    473 	if (rop->alloc < xsize) {
    474 	    rop->digs = mp_realloc(rop->digs, sizeof(BNS) * xsize);
    475 	    rop->alloc = xsize;
    476 	}
    477 	digs = rop->digs;
    478 	memset(digs, '\0', sizeof(BNS) * xsize);
    479     }
    480 
    481     /* multiply operands */
    482     xsize = mp_mul(digs, op1->digs, op2->digs, op1->size, op2->size);
    483 
    484     /* store result in rop */
    485     if (digs != rop->digs) {
    486 	/* if rop was an operand, free old data */
    487 	mp_free(rop->digs);
    488 	rop->digs = digs;
    489     }
    490     rop->size = xsize;
    491 
    492     /* set result sign */
    493     rop->sign = sign;
    494 }
    495 
    496 void
    497 mpi_muli(mpi *rop, mpi *op1, long op2)
    498 {
    499     BNS digs[2];
    500     mpi op;
    501 
    502     op.digs = (BNS*)digs;
    503     _mpi_seti(&op, op2);
    504 
    505     mpi_mul(rop, op1, &op);
    506 }
    507 
    508 void
    509 mpi_div(mpi *rop, mpi *num, mpi *den)
    510 {
    511     mpi_divqr(rop, NULL, num, den);
    512 }
    513 
    514 void
    515 mpi_rem(mpi *rop, mpi *num, mpi *den)
    516 {
    517     mpi_divqr(NULL, rop, num, den);
    518 }
    519 
    520 /*
    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.
    523  */
    524 void
    525 mpi_divqr(mpi *qrop, mpi *rrop, mpi *num, mpi *den)
    526 {
    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 */
    539 
    540     /* get signs */
    541     rsign = num->sign;
    542     qsign = rsign ^ den->sign;
    543 
    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;
    551 	    }
    552 	    rrop->size = num->size;
    553 	    memcpy(rrop->digs, num->digs, sizeof(BNS) * num->size);
    554 	    rrop->sign = rsign;
    555 	}
    556 	if (qrop)
    557 	    mpi_seti(qrop, 0);
    558 
    559 	return;
    560     }
    561 
    562     /* estimate result sizes */
    563     rsize = den->size;
    564     qsize = num->size - den->size + 1;
    565 
    566     /* offsets */
    567     npos = num->size - 1;
    568     dpos = den->size - 1;
    569 
    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);
    573     else {
    574 	if (qrop->alloc < qsize) {
    575 	    qrop->digs = mp_realloc(qrop->digs, sizeof(BNS) * qsize);
    576 	    qrop->alloc = qsize;
    577 	}
    578 	memset(qrop->digs, '\0', sizeof(BNS) * qsize);
    579 	qdigs = qrop->digs;
    580     }
    581     if (rrop) {
    582 	if (rrop->digs == num->digs || rrop->digs == den->digs)
    583 	    rdigs = mp_calloc(1, sizeof(BNS) * rsize);
    584 	else {
    585 	    if (rrop->alloc < rsize) {
    586 		rrop->digs = mp_realloc(rrop->digs, sizeof(BNS) * rsize);
    587 		rrop->alloc = rsize;
    588 	    }
    589 	    memset(rrop->digs, '\0', sizeof(BNS) * rsize);
    590 	    rdigs = rrop->digs;
    591 	}
    592     }
    593     else
    594 	rdigs = NULL;	/* fix gcc warning */
    595 
    596     /* special case, only one word in divisor */
    597     if (dpos == 0) {
    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]);
    602 	}
    603 	if (rrop)
    604 	    rdigs[0] = carry;
    605 
    606 	goto mpi_divqr_done;
    607     }
    608 
    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;
    614     ++npos;
    615 
    616     /* normalize */
    617     denorm = (BNS)((BNI)CARRY / ((BNI)(den->digs[dpos]) + 1));
    618 
    619     if (denorm > 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);
    625 	}
    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);
    633 	}
    634     }
    635     else
    636 	/* only allocate copy of denominator if going to change it */
    637 	ddigs = den->digs;
    638 
    639     /* divide mp integers */
    640     for (j = qsize - 1; j >= 0; j--, npos--) {
    641 	/* estimate quotient */
    642 	if (ndigs[npos] == ddigs[dpos])
    643 	    qest = (BNS)SMASK;
    644 	else
    645 	    qest = (BNS)((((BNI)(ndigs[npos]) << BNSBITS) + ndigs[npos - 1]) /
    646 			 ddigs[dpos]);
    647 
    648 	while ((value = ((BNI)(ndigs[npos]) << BNSBITS) + ndigs[npos - 1] -
    649 	        qest * (BNI)(ddigs[dpos])) < CARRY &&
    650 		ddigs[dpos - 1] * (BNI)qest >
    651 		(value << BNSBITS) + ndigs[npos - 2])
    652 	       --qest;
    653 
    654 	/* multiply and subtract */
    655 	carry = scarry = 0;
    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) -
    660 		     (long)scarry;
    661 	    ndigs[npos - dpos + i - 1] = (BNS)svalue;
    662 	    scarry = svalue < 0;
    663 	}
    664 
    665 	svalue = (long)ndigs[npos] - (long)(carry & SMASK) - (long)scarry;
    666 	ndigs[npos] = (BNS)svalue;
    667 
    668 	if (svalue & LMASK) {
    669 	    /* quotient too big */
    670 	    --qest;
    671 	    carry = 0;
    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);
    676 	    }
    677 	    ndigs[npos] += carry;
    678 	}
    679 
    680 	qdigs[j] = qest;
    681     }
    682 
    683     /* calculate remainder */
    684     if (rrop) {
    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);
    689 	}
    690     }
    691 
    692     mp_free(ndigs);
    693     if (ddigs != den->digs)
    694 	mp_free(ddigs);
    695 
    696 mpi_divqr_done:
    697     if (rrop) {
    698 	if (rrop->digs != rdigs)
    699 	    mp_free(rrop->digs);
    700 	/* normalize remainder */
    701 	for (i = rsize - 1; i >= 0; i--)
    702 	    if (rdigs[i] != 0)
    703 		break;
    704 	if (i != rsize - 1) {
    705 	    if (i < 0) {
    706 		rsign = 0;
    707 		rsize = 1;
    708 	    }
    709 	    else
    710 		rsize = i + 1;
    711 	}
    712 	rrop->digs = rdigs;
    713 	rrop->sign = rsign;
    714 	rrop->size = rsize;
    715     }
    716 
    717     /* normalize quotient */
    718     if (qrop) {
    719 	if (qrop->digs != qdigs)
    720 	    mp_free(qrop->digs);
    721 	for (i = qsize - 1; i >= 0; i--)
    722 	    if (qdigs[i] != 0)
    723 		break;
    724 	if (i != qsize - 1) {
    725 	    if (i < 0) {
    726 		qsign = 0;
    727 		qsize = 1;
    728 	    }
    729 	    else
    730 		qsize = i + 1;
    731 	}
    732 	qrop->digs = qdigs;
    733 	qrop->sign = qsign;
    734 	qrop->size = qsize;
    735     }
    736     else
    737 	mp_free(qdigs);
    738 }
    739 
    740 long
    741 mpi_divqri(mpi *qrop, mpi *num, long den)
    742 {
    743     BNS ddigs[2];
    744     mpi dop, rrop;
    745     long remainder;
    746 
    747     dop.digs = (BNS*)ddigs;
    748     _mpi_seti(&dop, den);
    749 
    750     memset(&rrop, '\0', sizeof(mpi));
    751     mpi_init(&rrop);
    752     mpi_divqr(qrop, &rrop, num, &dop);
    753     remainder = rrop.digs[0];
    754     if (rrop.size > 1)
    755 	remainder |= (BNI)(rrop.digs[1]) << BNSBITS;
    756     if (rrop.sign)
    757 	remainder = -remainder;
    758     mpi_clear(&rrop);
    759 
    760     return (remainder);
    761 }
    762 
    763 void
    764 mpi_divi(mpi *rop, mpi *num, long den)
    765 {
    766     BNS ddigs[2];
    767     mpi dop;
    768 
    769     dop.digs = (BNS*)ddigs;
    770     _mpi_seti(&dop, den);
    771 
    772     mpi_divqr(rop, NULL, num, &dop);
    773 }
    774 
    775 long
    776 mpi_remi(mpi *num, long den)
    777 {
    778     return (mpi_divqri(NULL, num, den));
    779 }
    780 
    781 void
    782 mpi_mod(mpi *rop, mpi *num, mpi *den)
    783 {
    784     mpi_rem(rop, num, den);
    785     if (num->sign ^ den->sign)
    786 	mpi_add(rop, rop, den);
    787 }
    788 
    789 long
    790 mpi_modi(mpi *num, long den)
    791 {
    792     long remainder;
    793 
    794     remainder = mpi_remi(num, den);
    795     if (num->sign ^ (den < 0))
    796 	remainder += den;
    797 
    798     return (remainder);
    799 }
    800 
    801 void
    802 mpi_gcd(mpi *rop, mpi *num, mpi *den)
    803 {
    804     long cmp;
    805     mpi rem;
    806 
    807     /* check if result already given */
    808     cmp = mpi_cmpabs(num, den);
    809 
    810     /* check if num is equal to den or if num is zero */
    811     if (cmp == 0 || (num->size == 1 && num->digs[0] == 0)) {
    812 	mpi_set(rop, den);
    813 	rop->sign = 0;
    814 	return;
    815     }
    816     /* check if den is not zero */
    817     if (den->size == 1 && den->digs[0] == 0) {
    818 	mpi_set(rop, num);
    819 	rop->sign = 0;
    820 	return;
    821     }
    822 
    823     /* don't call mpi_init, relies on realloc(0, size) == malloc(size) */
    824     memset(&rem, '\0', sizeof(mpi));
    825 
    826     /* if num larger than den */
    827     if (cmp > 0) {
    828 	mpi_rem(&rem, num, den);
    829 	if (rem.size == 1 && rem.digs[0] == 0) {
    830 	    /* exact division */
    831 	    mpi_set(rop, den);
    832 	    rop->sign = 0;
    833 	    mpi_clear(&rem);
    834 	    return;
    835 	}
    836 	mpi_set(rop, den);
    837     }
    838     else {
    839 	mpi_rem(&rem, den, num);
    840 	if (rem.size == 1 && rem.digs[0] == 0) {
    841 	    /* exact division */
    842 	    mpi_set(rop, num);
    843 	    rop->sign = 0;
    844 	    mpi_clear(&rem);
    845 	    return;
    846 	}
    847 	mpi_set(rop, num);
    848     }
    849 
    850     /* loop using positive values */
    851     rop->sign = rem.sign = 0;
    852 
    853     /* cannot optimize this inverting rem/rop assignment earlier
    854      * because rop mais be an operand */
    855     mpi_swap(rop, &rem);
    856 
    857     /* Euclides algorithm */
    858     for (;;) {
    859 	mpi_rem(&rem, &rem, rop);
    860 	if (rem.size == 1 && rem.digs[0] == 0)
    861 	    break;
    862 	mpi_swap(rop, &rem);
    863     }
    864     mpi_clear(&rem);
    865 }
    866 
    867 void
    868 mpi_lcm(mpi *rop, mpi *num, mpi *den)
    869 {
    870     mpi gcd;
    871 
    872     /* check for zero operand */
    873     if ((num->size == 1 && num->digs[0] == 0) ||
    874 	(den->size == 1 && den->digs[0] == 0)) {
    875 	rop->digs[0] = 0;
    876 	rop->sign = 0;
    877 	return;
    878     }
    879 
    880     /* don't call mpi_init, relies on realloc(0, size) == malloc(size) */
    881     memset(&gcd, '\0', sizeof(mpi));
    882 
    883     mpi_gcd(&gcd, num, den);
    884     mpi_div(&gcd, den, &gcd);
    885     mpi_mul(rop, &gcd, num);
    886     rop->sign = 0;
    887 
    888     mpi_clear(&gcd);
    889 }
    890 
    891 void
    892 mpi_pow(mpi *rop, mpi *op, unsigned long exp)
    893 {
    894     mpi zop, top;
    895 
    896     if (exp == 2) {
    897 	mpi_mul(rop, op, op);
    898 	return;
    899     }
    900     /* check for op**0 */
    901     else if (exp == 0) {
    902 	rop->digs[0] = 1;
    903 	rop->size = 1;
    904 	rop->sign = 0;
    905 	return;
    906     }
    907     else if (exp == 1) {
    908 	mpi_set(rop, op);
    909 	return;
    910     }
    911     else if (op->size == 1) {
    912 	if (op->digs[0] == 0) {
    913 	    mpi_seti(rop, 0);
    914 	    return;
    915 	}
    916 	else if (op->digs[0] == 1) {
    917 	    mpi_seti(rop, op->sign && (exp & 1) ? -1 : 1);
    918 	    return;
    919 	}
    920     }
    921 
    922     memset(&zop, '\0', sizeof(mpi));
    923     memset(&top, '\0', sizeof(mpi));
    924     mpi_set(&zop, op);
    925     mpi_set(&top, op);
    926     for (--exp; exp; exp >>= 1) {
    927 	if (exp & 1)
    928 	    mpi_mul(&zop, &top, &zop);
    929 	mpi_mul(&top, &top, &top);
    930     }
    931 
    932     mpi_clear(&top);
    933     rop->sign = zop.sign;
    934     mp_free(rop->digs);
    935     rop->digs = zop.digs;
    936     rop->size = zop.size;
    937 }
    938 
    939 /* Find integer root of given number using the iteration
    940  *	x{n+1} = ((K-1) * x{n} + N / x{n}^(K-1)) / K
    941  */
    942 int
    943 mpi_root(mpi *rop, mpi *op, unsigned long nth)
    944 {
    945     long bits, cmp;
    946     int exact;
    947     int sign;
    948     mpi *r, t, temp, quot, old, rem;
    949 
    950     sign = op->sign;
    951 
    952     /* divide by zero op**1/0 */
    953     if (nth == 0) {
    954 	int one = 1, zero = 0;
    955 	one = one / zero;
    956     }
    957     /* result is complex */
    958     if (sign && !(nth & 1)) {
    959 	int one = 1, zero = 0;
    960 	one = one / zero;
    961     }
    962 
    963     /* special case op**1/1 = op */
    964     if (nth == 1) {
    965 	mpi_set(rop, op);
    966 	return (1);
    967     }
    968 
    969     bits = mpi_getsize(op, 2) - 2;
    970 
    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);
    975 
    976 	return (exact == 1);
    977     }
    978 
    979     /* initialize */
    980     if (rop != op)
    981 	r = rop;
    982     else {
    983 	r = &t;
    984 	memset(r, '\0', sizeof(mpi));
    985     }
    986     memset(&temp, '\0', sizeof(mpi));
    987     memset(&quot, '\0', sizeof(mpi));
    988     memset(&old, '\0', sizeof(mpi));
    989     memset(&rem, '\0', sizeof(mpi));
    990 
    991     if (sign)
    992 	r->sign = 0;
    993 
    994     /* root aproximation */
    995     mpi_ash(r, op, -(bits - (bits / nth)));
    996 
    997     for (;;) {
    998 	mpi_pow(&temp, r, nth - 1);
    999 	mpi_divqr(&quot, &rem, op, &temp);
   1000 	cmp = mpi_cmpabs(r, &quot);
   1001 	if (cmp == 0) {
   1002 	    exact = mpi_cmpi(&rem, 0) == 0;
   1003 	    break;
   1004 	}
   1005 	else if (cmp < 0) {
   1006 	    if (mpi_cmpabs(r, &old) == 0) {
   1007 		exact = 0;
   1008 		break;
   1009 	    }
   1010 	    mpi_set(&old, r);
   1011 	}
   1012 	mpi_muli(&temp, r, nth - 1);
   1013 	mpi_add(&quot, &quot, &temp);
   1014 	mpi_divi(r, &quot, nth);
   1015     }
   1016 
   1017     mpi_clear(&temp);
   1018     mpi_clear(&quot);
   1019     mpi_clear(&old);
   1020     mpi_clear(&rem);
   1021     if (r != rop) {
   1022 	mpi_set(rop, r);
   1023 	mpi_clear(r);
   1024     }
   1025     rop->sign = sign;
   1026 
   1027     return (exact);
   1028 }
   1029 
   1030 /*
   1031  * Find square root using the iteration:
   1032  *	x{n+1} = (x{n}+N/x{n})/2
   1033  */
   1034 int
   1035 mpi_sqrt(mpi *rop, mpi *op)
   1036 {
   1037     long bits, cmp;
   1038     int exact;
   1039     mpi *r, t, quot, rem, old;
   1040 
   1041     /* result is complex */
   1042     if (op->sign) {
   1043 	int one = 1, zero = 0;
   1044 	one = one / zero;
   1045     }
   1046 
   1047     bits = mpi_getsize(op, 2) - 2;
   1048 
   1049     if (bits < 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);
   1053 
   1054 	return (exact == 1);
   1055     }
   1056 
   1057     /* initialize */
   1058     if (rop != op)
   1059 	r = rop;
   1060     else {
   1061 	r = &t;
   1062 	memset(r, '\0', sizeof(mpi));
   1063     }
   1064     memset(&quot, '\0', sizeof(mpi));
   1065     memset(&rem, '\0', sizeof(mpi));
   1066     memset(&old, '\0', sizeof(mpi));
   1067 
   1068     /* root aproximation */
   1069     mpi_ash(r, op, -(bits - (bits / 2)));
   1070 
   1071     for (;;) {
   1072 	if (mpi_cmpabs(r, &old) == 0) {
   1073 	    exact = 0;
   1074 	    break;
   1075 	}
   1076 	mpi_divqr(&quot, &rem, op, r);
   1077 	cmp = mpi_cmpabs(&quot, r);
   1078 	if (cmp == 0) {
   1079 	    exact = mpi_cmpi(&rem, 0) == 0;
   1080 	    break;
   1081 	}
   1082 	else if (cmp > 0 && rem.size == 1 && rem.digs[0] == 0)
   1083 	    mpi_subi(&quot, &quot, 1);
   1084 	mpi_set(&old, r);
   1085 	mpi_add(r, r, &quot);
   1086 	mpi_ash(r, r, -1);
   1087     }
   1088     mpi_clear(&quot);
   1089     mpi_clear(&rem);
   1090     mpi_clear(&old);
   1091     if (r != rop) {
   1092 	mpi_set(rop, r);
   1093 	mpi_clear(r);
   1094     }
   1095 
   1096     return (exact);
   1097 }
   1098 
   1099 void
   1100 mpi_ash(mpi *rop, mpi *op, long shift)
   1101 {
   1102     long i;			/* counter */
   1103     long xsize;			/* maximum result size */
   1104     BNS *digs;
   1105 
   1106     /* check for 0 shift, multiply/divide by 1 */
   1107     if (shift == 0) {
   1108 	if (rop != op) {
   1109 	    if (rop->alloc < op->size) {
   1110 		rop->digs = mp_realloc(rop->digs, sizeof(BNS) * op->size);
   1111 		rop->alloc = op->size;
   1112 	    }
   1113 	    rop->size = op->size;
   1114 	    memcpy(rop->digs, op->digs, sizeof(BNS) * op->size);
   1115 	}
   1116 
   1117 	return;
   1118     }
   1119     else if (op->size == 1 && op->digs[0] == 0) {
   1120 	rop->sign = 0;
   1121 	rop->size = 1;
   1122 	rop->digs[0] = 0;
   1123 
   1124 	return;
   1125     }
   1126 
   1127     /* check shift and initialize */
   1128     if (shift > 0)
   1129 	xsize = op->size + (shift / BNSBITS) + 1;
   1130     else {
   1131 	xsize = op->size - ((-shift) / BNSBITS);
   1132 	if (xsize <= 0) {
   1133 	    rop->size = 1;
   1134 	    rop->sign = op->sign;
   1135 	    rop->digs[0] = op->sign ? 1 : 0;
   1136 
   1137 	    return;
   1138 	}
   1139     }
   1140 
   1141     /* allocate/adjust memory for result */
   1142     if (rop == op)
   1143 	digs = mp_malloc(sizeof(BNS) * xsize);
   1144     else {
   1145 	if (rop->alloc < xsize) {
   1146 	    rop->digs = mp_realloc(rop->digs, sizeof(BNS) * xsize);
   1147 	    rop->alloc = xsize;
   1148 	}
   1149 	digs = rop->digs;
   1150     }
   1151 
   1152     /* left shift, multiply by power of two */
   1153     if (shift > 0)
   1154 	rop->size = mp_lshift(digs, op->digs, op->size, shift);
   1155     /* right shift, divide by power of two */
   1156     else {
   1157 	long carry = 0;
   1158 
   1159 	if (op->sign) {
   1160 	    BNI words, bits;
   1161 
   1162 	    words = -shift / BNSBITS;
   1163 	    bits = -shift % BNSBITS;
   1164 	    for (i = 0; i < words; i++)
   1165 		carry |= op->digs[xsize + i];
   1166 	    if (!carry) {
   1167 		for (i = 0; i < bits; i++)
   1168 		    if (op->digs[op->size - xsize] & (1 << i)) {
   1169 			carry = 1;
   1170 			break;
   1171 		    }
   1172 	    }
   1173 	}
   1174 	rop->size = mp_rshift(digs, op->digs, op->size, -shift);
   1175 
   1176 	if (carry)
   1177 	    /* emulates two's complement subtracting 1 from the result */
   1178 	    rop->size = mp_add(digs, digs, mpone.digs, rop->size, 1);
   1179     }
   1180 
   1181     if (rop->digs != digs) {
   1182 	mp_free(rop->digs);
   1183 	rop->alloc = rop->size;
   1184 	rop->digs = digs;
   1185     }
   1186     rop->sign = op->sign;
   1187 }
   1188 
   1189 static INLINE BNS
   1190 mpi_logic(BNS op1, BNS op2, BNS op)
   1191 {
   1192     switch (op) {
   1193 	case '&':
   1194 	    return (op1 & op2);
   1195 	case '|':
   1196 	    return (op1 | op2);
   1197 	case '^':
   1198 	    return (op1 ^ op2);
   1199     }
   1200 
   1201     return (SMASK);
   1202 }
   1203 
   1204 static void
   1205 mpi_log(mpi *rop, mpi *op1, mpi *op2, BNS op)
   1206 {
   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 */
   1213     BNI sum;
   1214 
   1215     /* initialize */
   1216     size1 = op1->size;
   1217     size2 = op2->size;
   1218 
   1219     sign1 = op1->sign ? SMASK : 0;
   1220     sign2 = op2->sign ? SMASK : 0;
   1221 
   1222     sign = mpi_logic(sign1, sign2, op);
   1223 
   1224     size = MAX(size1, size2);
   1225     if (sign)
   1226 	++size;
   1227     if (rop->alloc < size) {
   1228 	rop->digs = mp_realloc(rop->digs, sizeof(BNS) * size);
   1229 	rop->alloc = size;
   1230     }
   1231 
   1232     digs = rop->digs;
   1233     digs1 = op1->digs;
   1234     digs2 = op2->digs;
   1235 
   1236     c = c1 = c2 = 1;
   1237 
   1238     /* apply logical operation */
   1239     for (i = 0; i < size; i++) {
   1240 	if (i >= size1)
   1241 	    n1 = sign1;
   1242 	else if (sign1) {
   1243 	    sum = (BNI)(BNS)(~digs1[i]) + c1;
   1244 	    c1 = (long)(sum >> BNSBITS);
   1245 	    n1 = (BNS)sum;
   1246 	}
   1247 	else
   1248 	    n1 = digs1[i];
   1249 
   1250 	if (i >= size2)
   1251 	    n2 = sign2;
   1252 	else if (sign2) {
   1253 	    sum = (BNI)(BNS)(~digs2[i]) + c2;
   1254 	    c2 = (long)(sum >> BNSBITS);
   1255 	    n2 = (BNS)sum;
   1256 	}
   1257 	else
   1258 	    n2 = digs2[i];
   1259 
   1260 	n = mpi_logic(n1, n2, op);
   1261 	if (sign) {
   1262 	    sum = (BNI)(BNS)(~n) + c;
   1263 	    c = (long)(sum >> BNSBITS);
   1264 	    digs[i] = (BNS)sum;
   1265 	}
   1266 	else
   1267 	    digs[i] = n;
   1268     }
   1269 
   1270     /* normalize */
   1271     for (i = size - 1; i >= 0; i--)
   1272 	if (digs[i] != 0)
   1273 	    break;
   1274     if (i != size - 1) {
   1275 	if (i < 0) {
   1276 	    sign = 0;
   1277 	    size = 1;
   1278 	}
   1279 	else
   1280 	    size = i + 1;
   1281     }
   1282 
   1283     rop->sign = sign != 0;
   1284     rop->size = size;
   1285 }
   1286 
   1287 void
   1288 mpi_and(mpi *rop, mpi *op1, mpi *op2)
   1289 {
   1290     mpi_log(rop, op1, op2, '&');
   1291 }
   1292 
   1293 void
   1294 mpi_ior(mpi *rop, mpi *op1, mpi *op2)
   1295 {
   1296     mpi_log(rop, op1, op2, '|');
   1297 }
   1298 
   1299 void
   1300 mpi_xor(mpi *rop, mpi *op1, mpi *op2)
   1301 {
   1302     mpi_log(rop, op1, op2, '^');
   1303 }
   1304 
   1305 void
   1306 mpi_com(mpi *rop, mpi *op)
   1307 {
   1308     static BNS digs[1] = { 1 };
   1309     static mpi one = { 0, 1, 1, (BNS*)&digs };
   1310 
   1311     mpi_log(rop, rop, &one, '^');
   1312 }
   1313 
   1314 void
   1315 mpi_neg(mpi *rop, mpi *op)
   1316 {
   1317     int sign = op->sign ^ 1;
   1318 
   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;
   1323 	}
   1324 	rop->size = op->size;
   1325 	memcpy(rop->digs, op->digs, sizeof(BNS) * rop->size);
   1326     }
   1327 
   1328     rop->sign = sign;
   1329 }
   1330 
   1331 void
   1332 mpi_abs(mpi *rop, mpi *op)
   1333 {
   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;
   1338 	}
   1339 	rop->size = op->size;
   1340 	memcpy(rop->digs, op->digs, sizeof(BNS) * rop->size);
   1341     }
   1342 
   1343     rop->sign = 0;
   1344 }
   1345 
   1346 int
   1347 mpi_cmp(mpi *op1, mpi *op2)
   1348 {
   1349     if (op1->sign ^ op2->sign)
   1350 	return (op1->sign ? -1 : 1);
   1351 
   1352     if (op1->size == op2->size) {
   1353 	long i, cmp = 0;
   1354 
   1355 	for (i = op1->size - 1; i >= 0; i--)
   1356 	    if ((cmp = (long)op1->digs[i] - (long)op2->digs[i]) != 0)
   1357 		break;
   1358 
   1359 	return (cmp == 0 ? 0 : (cmp < 0) ^ op1->sign ? -1 : 1);
   1360     }
   1361 
   1362     return ((op1->size < op2->size) ^ op1->sign ? -1 : 1);
   1363 }
   1364 
   1365 int
   1366 mpi_cmpi(mpi *op1, long op2)
   1367 {
   1368     long cmp;
   1369 
   1370     if (op1->size > 2)
   1371 	return (op1->sign ? -1 : 1);
   1372 
   1373     cmp = op1->digs[0];
   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);
   1378     }
   1379     if (op1->sign)
   1380 	cmp = -cmp;
   1381 
   1382     return (cmp - op2);
   1383 }
   1384 
   1385 int
   1386 mpi_cmpabs(mpi *op1, mpi *op2)
   1387 {
   1388     if (op1->size == op2->size) {
   1389 	long i, cmp = 0;
   1390 
   1391 	for (i = op1->size - 1; i >= 0; i--)
   1392 	    if ((cmp = (long)op1->digs[i] - (long)op2->digs[i]) != 0)
   1393 		break;
   1394 
   1395 	return (cmp);
   1396     }
   1397 
   1398     return ((op1->size < op2->size) ? -1 : 1);
   1399 }
   1400 
   1401 int
   1402 mpi_cmpabsi(mpi *op1, long op2)
   1403 {
   1404     unsigned long cmp;
   1405 
   1406     if (op1->size > 2)
   1407 	return (1);
   1408 
   1409     cmp = op1->digs[0];
   1410     if (op1->size == 2)
   1411 	cmp |= (unsigned long)op1->digs[1] << BNSBITS;
   1412 
   1413     return (cmp > op2 ? 1 : cmp == op2 ? 0 : -1);
   1414 }
   1415 
   1416 int
   1417 mpi_sgn(mpi *op)
   1418 {
   1419     return (op->sign ? -1 : op->size > 1 || op->digs[0] ? 1 : 0);
   1420 }
   1421 
   1422 void
   1423 mpi_swap(mpi *op1, mpi *op2)
   1424 {
   1425     if (op1 != op2) {
   1426 	mpi swap;
   1427 
   1428 	memcpy(&swap, op1, sizeof(mpi));
   1429 	memcpy(op1, op2, sizeof(mpi));
   1430 	memcpy(op2, &swap, sizeof(mpi));
   1431     }
   1432 }
   1433 
   1434 int
   1435 mpi_fiti(mpi *op)
   1436 {
   1437     if (op->size == 1)
   1438 	return (1);
   1439     else if (op->size == 2) {
   1440 	unsigned long value = ((BNI)(op->digs[1]) << BNSBITS) | op->digs[0];
   1441 
   1442 	if (value & MINSLONG)
   1443 	    return (op->sign && value == MINSLONG) ? 1 : 0;
   1444 
   1445 	return (1);
   1446     }
   1447 
   1448     return (0);
   1449 }
   1450 
   1451 long
   1452 mpi_geti(mpi *op)
   1453 {
   1454     long value;
   1455 
   1456     value = op->digs[0];
   1457     if (op->size > 1)
   1458 	value |= (BNI)(op->digs[1]) << BNSBITS;
   1459 
   1460     return (op->sign && value != MINSLONG ? -value : value);
   1461 }
   1462 
   1463 double
   1464 mpi_getd(mpi *op)
   1465 {
   1466     long i, len;
   1467     double d = 0.0;
   1468     int exponent;
   1469 
   1470 #define FLOATDIGS	sizeof(double) / sizeof(BNS)
   1471 
   1472     switch (op->size) {
   1473 	case 2:
   1474 	    d = (BNI)(op->digs[1]) << BNSBITS;
   1475 	case 1:
   1476 	    d += op->digs[0];
   1477 	    return (op->sign ? -d : d);
   1478 	default:
   1479 	    break;
   1480     }
   1481 
   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);
   1485     if (len > 0)
   1486 	exponent += len * BNSBITS;
   1487 
   1488     if (d == 0.0)
   1489 	return (d);
   1490 
   1491     d = ldexp(d, exponent);
   1492 
   1493     return (op->sign ? -d : d);
   1494 }
   1495 
   1496 /* how many digits in a given base, floor(log(CARRY) / log(base)) */
   1497 #ifdef LONG64
   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,
   1501      6,  6,  6,  6,  6,
   1502 };
   1503 #else
   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,
   1507      3,  3,  3,  3,  3,
   1508 };
   1509 #endif
   1510 
   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,
   1525     0.1934264036172708,
   1526 };
   1527 
   1528 /* normalization base for string conversion, pow(base, dig_bases[base]) & ~CARRY */
   1529 #ifdef LONG64
   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,
   1537     0x81BF1000,
   1538 };
   1539 #else
   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,
   1545     0xb640,
   1546 };
   1547 #endif
   1548 
   1549 unsigned long
   1550 mpi_getsize(mpi *op, int base)
   1551 {
   1552     unsigned long value, bits;
   1553 
   1554     value = op->digs[op->size - 1];
   1555 
   1556     /* count leading bits */
   1557     if (value) {
   1558 	unsigned long count, carry;
   1559 
   1560 	for (count = 0, carry = CARRY >> 1; carry; count++, carry >>= 1)
   1561 	    if (value & carry)
   1562 		break;
   1563 
   1564 	bits = BNSBITS - count;
   1565     }
   1566     else
   1567 	bits = 0;
   1568 
   1569     return ((bits + (op->size - 1) * BNSBITS) * bit_bases[base] + 1);
   1570 }
   1571 
   1572 char *
   1573 mpi_getstr(char *str, mpi *op, int base)
   1574 {
   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 */
   1582 
   1583     /* initialize */
   1584     size = op->size;
   1585     strsize = mpi_getsize(op, base) + op->sign + 1;
   1586 
   1587     if (str == NULL)
   1588 	str = mp_malloc(strsize);
   1589 
   1590     /* check for zero */
   1591     if (size == 1 && op->digs[0] == 0) {
   1592 	str[0] = '0';
   1593 	str[1] = '\0';
   1594 
   1595 	return (str);
   1596     }
   1597 
   1598     digits = dig_bases[base];
   1599     bigbase = big_bases[base];
   1600 
   1601     cp = str + strsize;
   1602     *--cp = '\0';
   1603 
   1604     /* make copy of op data and adjust digs */
   1605     xdigs = mp_malloc(size * sizeof(BNS));
   1606     memcpy(xdigs, op->digs, size * sizeof(BNS));
   1607     digs = xdigs + size - 1;
   1608 
   1609     /* convert to string */
   1610     for (;;) {
   1611 	long count = -1;
   1612 	BNI value;
   1613 	BNS quotient, remainder = 0;
   1614 
   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)
   1622 		    count = i;
   1623 	    }
   1624 	}
   1625 	else {
   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)
   1632 		    count = i;
   1633 	    }
   1634 	}
   1635 	quotient = remainder;
   1636 	for (i = 0; i < digits; i++) {
   1637 	    if (quotient == 0 && count < 0)
   1638 		break;
   1639 	    remainder = quotient % base;
   1640 	    quotient /= base;
   1641 	    *--cp = remainder < 10 ? remainder + '0' : remainder - 10 + 'A';
   1642 	}
   1643 	if (count < 0)
   1644 	    break;
   1645 	digs -= count;
   1646 	size -= count;
   1647     }
   1648 
   1649     /* adjust sign */
   1650     if (op->sign)
   1651 	*--cp = '-';
   1652 
   1653     /* remove any extra characters */
   1654     if (cp > str)
   1655 	strcpy(str, cp);
   1656 
   1657     mp_free(xdigs);
   1658 
   1659     return (str);
   1660 }
   1661