Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346/****************************************************************************1**2*W integer.c GAP source Martin Schönert3** & Alice Niemeyer4** & Werner Nickel5**6**7*Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany8*Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland9*Y Copyright (C) 2002 The GAP Group10**11** This file implements the functions handling arbitrary size integers.12**13** There are three integer types in GAP: 'T_INT', 'T_INTPOS' and 'T_INTNEG'.14** Each integer has a unique representation, e.g., an integer that can be15** represented as 'T_INT' is never represented as 'T_INTPOS' or 'T_INTNEG'.16**17** 'T_INT' is the type of those integers small enough to fit into 29 bits.18** Therefore the value range of this small integers is $-2^{28}...2^{28}-1$.19** This range contains about 99\% of all integers that usually occur in GAP.20** (I just made up this number, obviously it depends on the application :-)21** Only these small integers can be used as index expression into sequences.22**23** Small integers are represented by an immediate integer handle, containing24** the value instead of pointing to it, which has the following form:25**26** +-------+-------+-------+-------+- - - -+-------+-------+-------+27** | guard | sign | bit | bit | | bit | tag | tag |28** | bit | bit | 27 | 26 | | 0 | 0 | 1 |29** +-------+-------+-------+-------+- - - -+-------+-------+-------+30**31** Immediate integers handles carry the tag 'T_INT', i.e. the last bit is 1.32** This distinguishes immediate integers from other handles which point to33** structures aligned on 4 byte boundaries and therefore have last bit zero.34** (The second bit is reserved as tag to allow extensions of this scheme.)35** Using immediates as pointers and dereferencing them gives address errors.36**37** To aid overflow check the most significant two bits must always be equal,38** that is to say that the sign bit of immediate integers has a guard bit.39**40** The macros 'INTOBJ_INT' and 'INT_INTOBJ' should be used to convert between41** a small integer value and its representation as immediate integer handle.42**43** 'T_INTPOS' and 'T_INTNEG' are the types of positive (respectively, negative)44** integer values that can not be represented by immediate integers.45**46** This large integers values are represented in signed base 65536 notation.47** That means that the bag of a large integer has the following form:48**49** +-------+-------+-------+-------+- - - -+-------+-------+-------+50** | digit | digit | digit | digit | | digit | digit | digit |51** | 0 | 1 | 2 | 3 | | <n>-2 | <n>-1 | <n> |52** +-------+-------+-------+-------+- - - -+-------+-------+-------+53**54** The value of this is: $d0 + d1 65536 + d2 65536^2 + ... + d_n 65536^n$,55** respectively the negative of this if the type of this object is 'T_INTNEG'.56**57** Each digit is of course stored as a 16 bit wide unsigned short.58** Note that base 65536 allows us to multiply 2 digits and add a carry digit59** without overflow in 32 bit long arithmetic, available on most processors.60**61** The number of digits in every large integer is a multiple of four.62** Therefore the leading three digits of some values will actually be zero.63** Note that the uniqueness of representation implies that not four or more64** leading digits may be zero, since |d0|d1|d2|d3| and |d0|d1|d2|d3|0|0|0|0|65** have the same value only one, the first, can be a legal representation.66**67** Because of this it is possible to do a little bit of loop unrolling.68** Thus instead of looping <n> times, handling one digit in each iteration,69** we can loop <n>/4 times, handling four digits during each iteration.70** This reduces the overhead of the loop by a factor of approximately four.71**72** Using base 65536 representation has advantages over using other bases.73** Integers in base 65536 representation can be packed dense and therefore74** use roughly 20\% less space than integers in base 10000 representation.75** 'SumInt' is 20\% and 'ProdInt' is 40\% faster for 65536 than for 10000,76** as their runtime is linear respectively quadratic in the number of digits.77** Dividing by 65536 and computing the remainder mod 65536 can be done fast78** by shifting 16 bit to the right and by taking the lower 16 bits.79** Larger bases are difficult because the product of two digits will not fit80** into 32 bit, which is the word size of most modern micro processors.81** Base 10000 would have the advantage that printing is very much easier,82** but 'PrInt' keeps a terminal at 9600 baud busy for almost all integers.83*/8485#include "system.h" /* Ints, UInts */8687#ifndef USE_GMP /* use this file, otherwise ignore what follows */8889#include "gasman.h" /* garbage collector */90#include "objects.h" /* objects */91#include "scanner.h" /* scanner */9293#include "gvars.h" /* global variables */9495#include "calls.h" /* generic call mechanism */96#include "opers.h" /* generic operations */9798#include "ariths.h" /* basic arithmetic */99100#include "bool.h" /* booleans */101102#include "integer.h" /* integers */103104#include "gap.h" /* error handling, initialisation */105106#include "records.h" /* generic records */107#include "precord.h" /* plain records */108109#include "lists.h" /* generic lists */110#include "string.h" /* strings */111112#include "saveload.h" /* saving and loading */113114#include "intfuncs.h"115116#include "code.h" /* coder */117#include "thread.h" /* threads */118#include "tls.h" /* thread-local storage */119120#include <stdio.h>121122/* for fallbacks to library */123Obj String;124125126/****************************************************************************127**128*F TypeInt(<int>) . . . . . . . . . . . . . . . . . . . . . type of integer129**130** 'TypeInt' returns the type of the integer <int>.131**132** 'TypeInt' is the function in 'TypeObjFuncs' for integers.133*/134Obj TYPE_INT_SMALL_ZERO;135Obj TYPE_INT_SMALL_POS;136Obj TYPE_INT_SMALL_NEG;137Obj TYPE_INT_LARGE_POS;138Obj TYPE_INT_LARGE_NEG;139140Obj TypeIntSmall (141Obj val )142{143if ( 0 == INT_INTOBJ(val) ) {144return TYPE_INT_SMALL_ZERO;145}146else if ( 0 < INT_INTOBJ(val) ) {147return TYPE_INT_SMALL_POS;148}149else /* if ( 0 > INT_INTOBJ(val) ) */ {150return TYPE_INT_SMALL_NEG;151}152}153154Obj TypeIntLargePos (155Obj val )156{157return TYPE_INT_LARGE_POS;158}159160Obj TypeIntLargeNeg (161Obj val )162{163return TYPE_INT_LARGE_NEG;164}165166/**************************************************************************167** The following two functions convert a C Int or UInt respectively into168** a GAP integer, either an immediate, small integer if possible or169** otherwise a new GAP bag with TNUM T_INTPOS or T_INTNEG.170**171*F ObjInt_Int(Int i)172*F ObjInt_UInt(UInt i)173**174****************************************************************************/175176Obj ObjInt_Int(Int i)177{178Obj n;179Int bound = 1L << NR_SMALL_INT_BITS;180if (i >= bound) {181/* We have to make a big integer */182n = NewBag(T_INTPOS,4*sizeof(TypDigit));183ADDR_INT(n)[0] = (TypDigit) (i & ((Int) INTBASE - 1L));184ADDR_INT(n)[1] = (TypDigit) (i >> NR_DIGIT_BITS);185ADDR_INT(n)[2] = 0;186ADDR_INT(n)[3] = 0;187return n;188} else if (-i > bound) {189n = NewBag(T_INTNEG,4*sizeof(TypDigit));190ADDR_INT(n)[0] = (TypDigit) ((-i) & ((Int) INTBASE - 1L));191ADDR_INT(n)[1] = (TypDigit) ((-i) >> NR_DIGIT_BITS);192ADDR_INT(n)[2] = 0;193ADDR_INT(n)[3] = 0;194return n;195} else {196return INTOBJ_INT(i);197}198}199200Obj ObjInt_UInt(UInt i)201{202Obj n;203UInt bound = 1UL << NR_SMALL_INT_BITS;204if (i >= bound) {205/* We have to make a big integer */206n = NewBag(T_INTPOS,4*sizeof(TypDigit));207ADDR_INT(n)[0] = (TypDigit) (i & ((UInt) INTBASE - 1L));208ADDR_INT(n)[1] = (TypDigit) (i >> NR_DIGIT_BITS);209ADDR_INT(n)[2] = 0;210ADDR_INT(n)[3] = 0;211return n;212} else {213return INTOBJ_INT(i);214}215}216217218219/****************************************************************************220**221*F PrintInt( <int> ) . . . . . . . . . . . . . . . print an integer constant222**223** 'PrintInt' prints the integer <int> in the usual decimal notation.224** 'PrintInt' handles objects of type 'T_INT', 'T_INTPOS' and 'T_INTNEG'.225**226** Large integers are first converted into base 10000 and then printed.227** The time for a conversion depends quadratically on the number of digits.228** For 2000 decimal digit integers, a screenfull, it is reasonable fast.229**230** The number of digits needed in PrIntD[] is the ceiling of the logarithm231** with respect to base PRINT_BASE of232**233** ( (1<<NR_DIGIT_BITS) )^1000 - 1.234**235** The latter is the largest number that can be represented with 1000 digits236** of type TypDigit.237**238** If NR_DIGIT_BITS is 16, we get 1205.239** If NR_DIGIT_BITS is 32, we get 1071.240**241** The subsidiary function IntToPrintBase converts an integer into base242** PRINT_BASE, leaving the result in base PrIntD. It returns the index of the243** most significant digits. It assumes that the argument is a large244** integer small enough to fit.245*/246247TypDigit PrIntC [1000]; /* copy of integer to be printed */248249#ifdef SYS_IS_64_BIT250251#define PRINT_BASE 1000000000L /* 10^9 */252#define PRINT_FORMAT "%09d" /* print 9 decimals at a time */253#define CHARS_PER_PRINT_BASE 9254TypDigit PrIntD [1071]; /* integer converted to base 10^9 */255#define NR_HEX_DIGITS 8256257#else258259#define PRINT_BASE 10000260#define PRINT_FORMAT "%04d" /* print 4 decimals at a time */261#define CHARS_PER_PRINT_BASE 4262TypDigit PrIntD [1205]; /* integer converted to base 10000 */263#define NR_HEX_DIGITS 4264265#endif266/****************************************************************************267**268*F FuncHexStringInt( <self>, <int> ) . . . . . . . . hex string for integer269*F FuncIntHexString( <self>, <string> ) . . . . . . integer from hex string270**271** The function `FuncHexStringInt' constructs from an integer the272** corresponding string in hexadecimal notation. It has a leading '-'273** for negative numbers and the digits 10..15 are written as A..F.274**275** The function `FuncIntHexString' does the converse, but here the276** letters a..f are also allowed in <string> instead of A..F.277**278*/279Obj FuncHexStringInt( Obj self, Obj integer )280{281Int len, i, j, n;282UInt nf;283TypDigit d, f;284UInt1 *p, a;285Obj res;286287/* immediate integers */288if (IS_INTOBJ(integer)) {289n = INT_INTOBJ(integer);290/* 0 is special */291if (n == 0) {292res = NEW_STRING(1);293CHARS_STRING(res)[0] = '0';294return res;295}296297/* else we create a string big enough for any immediate integer */298res = NEW_STRING(2 * NR_HEX_DIGITS + 1);299p = CHARS_STRING(res);300/* handle sign */301if (n<0) {302p[0] = '-';303n = -n;304p++;305}306else307SET_LEN_STRING(res, GET_LEN_STRING(res)-1);308/* collect digits, skipping leading zeros */309j = 0;310nf = ((UInt)15) << (4*(2*NR_HEX_DIGITS-1));311for (i = 2*NR_HEX_DIGITS; i; i-- ) {312a = ((UInt)n & nf) >> (4*(i-1));313if (j==0 && a==0) SET_LEN_STRING(res, GET_LEN_STRING(res)-1);314else if (a<10) p[j++] = a + '0';315else p[j++] = a - 10 + 'A';316nf = nf >> 4;317}318/* final null character */319p[j] = 0;320return res;321}322else if (TNUM_OBJ(integer) == T_INTNEG || TNUM_OBJ(integer) == T_INTPOS) {323/* nr of digits */324len = SIZE_INT(integer);325for (; ADDR_INT(integer)[len-1] == 0; len--);326327/* result string and sign */328if (TNUM_OBJ(integer) == T_INTNEG) {329res = NEW_STRING(len * NR_HEX_DIGITS + 1);330p = CHARS_STRING(res);331p[0] = '-';332p++;333}334else {335res = NEW_STRING(len * NR_HEX_DIGITS);336p = CHARS_STRING(res);337}338/* collect digits */339j = 0;340for (; len; len--) {341d = ADDR_INT(integer)[len-1];342f = 15L << (4*(NR_HEX_DIGITS-1));343for (i = NR_HEX_DIGITS; i; i-- ) {344a = (d & f) >> (4*(i-1));345if (j==0 && a==0) SET_LEN_STRING(res, GET_LEN_STRING(res)-1);346else if (a<10) p[j++] = a + '0';347else p[j++] = a - 10 + 'A';348f = f >> 4;349}350}351/* final null character */352p[j] = 0;353return res;354}355else356ErrorReturnObj("HexStringInt: argument must be integer, (not a %s)",357(Int)TNAM_OBJ(integer), 0L,358"");359return (Obj) 0L; /* please picky cc */360}361362Obj FuncIntHexString( Obj self, Obj str )363{364Obj res;365Int i, j, s, ii, len, sign, nd;366UInt n;367UInt1 *p, a;368TypDigit d;369370if (! IsStringConv(str))371ErrorReturnObj("IntHexString: argument must be string (not a %s)",372(Int)TNAM_OBJ(str), 0L,373"");374375/* number of hex digits and sign */376len = GET_LEN_STRING(str);377if (len == 0) {378res = INTOBJ_INT(0);379return res;380}381if (*(CHARS_STRING(str)) == '-') {382sign = -1;383i = 1;384}385else {386sign = 1;387i = 0;388}389390/* skip leading zeros */391while ((CHARS_STRING(str))[i] == '0' && i < len)392i++;393394/* small int case */395if ((len-i)*4 <= NR_SMALL_INT_BITS) {396n = 0;397p = CHARS_STRING(str);398for (; i<len; i++) {399a = p[i];400if (a>96)401a -= 87;402else if (a>64)403a -= 55;404else405a -= 48;406if (a > 15)407ErrorReturnObj("IntHexString: non-valid character in hex-string",4080L, 0L, "");409n = (n << 4) + a;410}411res = INTOBJ_INT(sign * n);412return res;413}414else {415/* number of Digits */416nd = (len-i)/NR_HEX_DIGITS;417if (nd * NR_HEX_DIGITS < (len-i)) nd++;418nd += ((3*nd) % 4);419if (sign == 1)420res = NewBag( T_INTPOS, nd*sizeof(TypDigit) );421else422res = NewBag( T_INTNEG, nd*sizeof(TypDigit) );423/* collect digits, easiest to start from the end */424p = CHARS_STRING(str);425for (j=0; j < nd; j++) {426d = 0;427for (s=0, ii=len-j*NR_HEX_DIGITS-1;428ii>=i && ii>len-(j+1)*NR_HEX_DIGITS-1;429s+=4, ii--) {430a = p[ii];431if (a>96)432a -= 87;433else if (a>64)434a -= 55;435else436a -= 48;437if (a > 15)438ErrorReturnObj("IntHexString: non-valid character in hex-string",4390L, 0L, "");440441d += (a<<s);442}443ADDR_INT(res)[j] = d;444}445return res;446}447}448449450451Int IntToPrintBase ( Obj op )452{453UInt i, k; /* loop counter */454TypDigit * p; /* loop pointer */455UInt c; /* carry in division step */456457i = 0;458for ( k = 0; k < SIZE_INT(op); k++ )459PrIntC[k] = ADDR_INT(op)[k];460while ( k > 0 && PrIntC[k-1] == 0 ) k--;461while ( k > 0 ) {462for ( c = 0, p = PrIntC+k-1; p >= PrIntC; p-- ) {463c = (c<<NR_DIGIT_BITS) + *p;464*p = (TypDigit)(c / PRINT_BASE);465c = c - PRINT_BASE * *p;466}467PrIntD[i++] = (TypDigit)c;468while ( k > 0 && PrIntC[k-1] == 0 ) k--;469}470return i-1;471472}473474void PrintInt (475Obj op )476{477Int i; /* loop counter */478Obj str; /* fallback to lib for large ints */479480/* print a small integer */481if ( IS_INTOBJ(op) ) {482Pr( "%>%d%<", INT_INTOBJ(op), 0L );483}484485/* print a large integer */486else if ( SIZE_INT(op) < 1000 ) {487488/* start printing, %> means insert '\' before a linebreak */489Pr("%>",0L,0L);490491if ( TNUM_OBJ(op) == T_INTNEG )492Pr("-",0L,0L);493494/* convert the integer into base PRINT_BASE */495i = IntToPrintBase(op);496497/* print the base PRINT_BASE digits */498Pr( "%d", (Int)PrIntD[i], 0L );499while ( i > 0 )500Pr( PRINT_FORMAT, (Int)PrIntD[--i], 0L );501Pr("%<",0L,0L);502503}504505else {506str = CALL_1ARGS( String, op );507Pr("%>%s%<",(Int)(CHARS_STRING(str)), 0);508/* for a long time Print of large ints did not follow the general idea509* that Print should produce something that can be read back into GAP:510Pr("<<an integer too large to be printed>>",0L,0L); */511}512}513514/****************************************************************************515**516** Implementation of Log2Int for C integers.517*/518519Int CLog2Int(Int a)520{521Int res, mask;522if (a < 0) a = -a;523if (a < 1) return -1;524if (a < 65536) {525for(mask = 2, res = 0; ;mask *= 2, res += 1) {526if(a < mask) return res;527}528}529for(mask = 65536, res = 15; ;mask *= 2, res += 1) {530if(a < mask) return res;531}532}533534/****************************************************************************535**536*F FuncLog2Int( <self>, <int> ) . . . . . . . . . nr of bits of integer - 1537**538** Given to GAP-Level as "Log2Int".539*/540Obj FuncLog2Int( Obj self, Obj integer)541{542Int d;543Int a, len;544TypDigit dmask;545546/* case of small ints */547if (IS_INTOBJ(integer)) {548return INTOBJ_INT(CLog2Int(INT_INTOBJ(integer)));549}550551/* case of long ints */552if (TNUM_OBJ(integer) == T_INTNEG || TNUM_OBJ(integer) == T_INTPOS) {553for (len = SIZE_INT(integer); ADDR_INT(integer)[len-1] == 0; len--);554/* Instead of computing555res = len * NR_DIGIT_BITS - d;556we keep len and d separate, because on 32 bit systems res may557not fit into an Int (and not into an immediate integer). */558d = 1;559a = (TypDigit)(ADDR_INT(integer)[len-1]);560for(dmask = (TypDigit)1 << (NR_DIGIT_BITS - 1);561(dmask & a) == 0 && dmask != (TypDigit)0;562dmask = dmask >> 1, d++);563return DiffInt(ProdInt(INTOBJ_INT(len), INTOBJ_INT(NR_DIGIT_BITS)),564INTOBJ_INT(d));565}566else {567ErrorReturnObj("Log2Int: argument must be integer, (not a %s)",568(Int)TNAM_OBJ(integer), 0L,569"");570return (Obj) 0L; /* please picky cc */571}572}573574/****************************************************************************575**576*F FuncSTRING_INT( <self>, <int> ) . . . . . convert an integer to a string577**578** `FuncSTRING_INT' returns an immutable string representing the integer579** <int>580**581*/582583Obj FuncSTRING_INT( Obj self, Obj integer )584{585Int x;586Obj str;587Int len;588Int i;589Char c;590Int j,top, chunk, neg;591592/* handle a small integer */593if ( IS_INTOBJ(integer) ) {594x = INT_INTOBJ(integer);595str = NEW_STRING( (NR_SMALL_INT_BITS+5)/3 );596RetypeBag(str, T_STRING+IMMUTABLE);597len = 0;598/* Case of zero */599if (x == 0)600{601CHARS_STRING(str)[0] = '0';602CHARS_STRING(str)[1] = '\0';603ResizeBag(str, SIZEBAG_STRINGLEN(1));604SET_LEN_STRING(str, 1);605606return str;607}608/* Negative numbers */609if (x < 0)610{611CHARS_STRING(str)[len++] = '-';612x = -x;613neg = 1;614}615else616neg = 0;617618/* Now the main case */619while (x != 0)620{621CHARS_STRING(str)[len++] = '0'+ x % 10;622x /= 10;623}624CHARS_STRING(str)[len] = '\0';625626/* finally, reverse the digits in place */627for (i = neg; i < (neg+len)/2; i++)628{629c = CHARS_STRING(str)[neg+len-1-i];630CHARS_STRING(str)[neg+len-1-i] = CHARS_STRING(str)[i];631CHARS_STRING(str)[i] = c;632}633634ResizeBag(str, SIZEBAG_STRINGLEN(len));635SET_LEN_STRING(str, len);636return str;637}638639/* handle a large integer */640else if ( SIZE_INT(integer) < 1000 ) {641642/* convert the integer into base PRINT_BASE */643len = IntToPrintBase(integer);644str = NEW_STRING(CHARS_PER_PRINT_BASE*(len+1)+2);645RetypeBag(str, T_STRING+IMMUTABLE);646647/* sort out the length of the top group */648j = 1;649top = (Int)PrIntD[len];650while ( top >= j)651{652j *= 10;653}654655/* Start filling in the string */656i = 0;657if ( TNUM_OBJ(integer) == T_INTNEG ) {658CHARS_STRING(str)[i++] = '-';659}660661while (j > 1)662{663j /= 10;664CHARS_STRING(str)[i++] = '0' + (top / j) % 10;665}666667/* Now the rest of the base PRINT_BASE digits are easy */668while( len > 0)669{670chunk = (Int)PrIntD[--len];671j = PRINT_BASE/10;672while (j > 0)673{674CHARS_STRING(str)[i++] = '0' + (chunk / j) % 10;675j /= 10;676}677}678679CHARS_STRING(str)[i] = '\0';680ResizeBag(str, SIZEBAG_STRINGLEN(i));681SET_LEN_STRING(str, i);682return str;683}684else {685686/* Very large integer, fall back on the GAP function */687return CALL_1ARGS( String, integer);688}689}690691692693/****************************************************************************694**695*F EqInt( <intL>, <intR> ) . . . . . . . . . test if two integers are equal696**697** 'EqInt' returns 1 if the two integer arguments <intL> and <intR> are698** equal and 0 otherwise.699*/700Int EqInt (701Obj opL,702Obj opR )703{704Int k; /* loop counter */705TypDigit * l; /* pointer into the left operand */706TypDigit * r; /* pointer into the right operand */707708/* compare two small integers */709if ( ARE_INTOBJS( opL, opR ) ) {710if ( INT_INTOBJ(opL) == INT_INTOBJ(opR) ) return 1L;711else return 0L;712}713714/* compare a small and a large integer */715else if ( IS_INTOBJ(opL) ) {716return 0L;717}718else if ( IS_INTOBJ(opR) ) {719return 0L;720}721722/* compare two large integers */723else {724725/* compare the sign and size */726if ( TNUM_OBJ(opL) != TNUM_OBJ(opR)727|| SIZE_INT(opL) != SIZE_INT(opR) )728return 0L;729730/* set up the pointers */731l = ADDR_INT(opL);732r = ADDR_INT(opR);733734/* run through the digits, four at a time */735for ( k = SIZE_INT(opL)/4-1; k >= 0; k-- ) {736if ( *l++ != *r++ ) return 0L;737if ( *l++ != *r++ ) return 0L;738if ( *l++ != *r++ ) return 0L;739if ( *l++ != *r++ ) return 0L;740}741742/* no differences found, so they must be equal */743return 1L;744745}746}747748749/****************************************************************************750**751*F LtInt( <intL>, <intR> ) . . . . . test if an integer is less than another752**753** 'LtInt' returns 1 if the integer <intL> is strictly less than the integer754** <intR> and 0 otherwise.755*/756Int LtInt (757Obj opL,758Obj opR )759{760Int k; /* loop counter */761TypDigit * l; /* pointer into the left operand */762TypDigit * r; /* pointer into the right operand */763764/* compare two small integers */765if ( ARE_INTOBJS( opL, opR ) ) {766if ( INT_INTOBJ(opL) < INT_INTOBJ(opR) ) return 1L;767else return 0L;768}769770/* compare a small and a large integer */771else if ( IS_INTOBJ(opL) ) {772if ( TNUM_OBJ(opR) == T_INTPOS ) return 1L;773else return 0L;774}775else if ( IS_INTOBJ(opR) ) {776if ( TNUM_OBJ(opL) == T_INTPOS ) return 0L;777else return 1L;778}779780/* compare two large integers */781else {782783/* compare the sign and size */784if ( TNUM_OBJ(opL) == T_INTNEG785&& TNUM_OBJ(opR) == T_INTPOS )786return 1L;787else if ( TNUM_OBJ(opL) == T_INTPOS788&& TNUM_OBJ(opR) == T_INTNEG )789return 0L;790else if ( (TNUM_OBJ(opL) == T_INTPOS791&& SIZE_INT(opL) < SIZE_INT(opR))792|| (TNUM_OBJ(opL) == T_INTNEG793&& SIZE_INT(opL) > SIZE_INT(opR)) )794return 1L;795else if ( (TNUM_OBJ(opL) == T_INTPOS796&& SIZE_INT(opL) > SIZE_INT(opR))797|| (TNUM_OBJ(opL) == T_INTNEG798&& SIZE_INT(opL) < SIZE_INT(opR)) )799return 0L;800801/* set up the pointers */802l = ADDR_INT(opL);803r = ADDR_INT(opR);804805/* run through the digits, from the end downwards */806for ( k = SIZE_INT(opL)-1; k >= 0; k-- ) {807if ( l[k] != r[k] ) {808if ( (TNUM_OBJ(opL) == T_INTPOS809&& l[k] < r[k])810|| (TNUM_OBJ(opL) == T_INTNEG811&& l[k] > r[k]) )812return 1L;813else814return 0L;815}816}817818/* no differences found, so they must be equal */819return 0L;820821}822}823824825/****************************************************************************826**827*F SumInt( <intL>, <intR> ) . . . . . . . . . . . . . . sum of two integers828**829** 'SumInt' returns the sum of the two integer arguments <intL> and <intR>.830** 'SumInt' handles operands of type 'T_INT', 'T_INTPOS' and 'T_INTNEG'.831**832** It can also be used in the cases that both operands are small integers833** and the result is a small integer too, i.e., that no overflow occurs.834** This case is usually already handled in 'EvalSum' for a better efficiency.835**836** Is called from the 'EvalSum' binop so both operands are already evaluated.837**838** 'SumInt' is a little bit difficult since there are 16 different cases to839** handle, each operand can be positive or negative, small or large integer.840** If the operands have opposite sign 'SumInt' calls 'DiffInt', this helps841** reduce the total amount of code by a factor of two.842*/843Obj SumInt (844Obj opL,845Obj opR )846{847Int i; /* loop variable */848Int k; /* loop variable */849Int cs; /* sum of two smalls */850UInt c; /* sum of two digits */851TypDigit * l; /* pointer into the left operand */852TypDigit * r; /* pointer into the right operand */853TypDigit * s; /* pointer into the sum */854UInt * l2; /* pointer to get 2 digits at once */855UInt * s2; /* pointer to put 2 digits at once */856Obj sum; /* handle of the result bag */857858/* adding two small integers */859if ( ARE_INTOBJS( opL, opR ) ) {860861/* add two small integers with a small sum */862/* add and compare top two bits to check that no overflow occured */863if ( SUM_INTOBJS( sum, opL, opR ) ) {864return sum;865}866867/* add two small integers with a large sum */868cs = INT_INTOBJ(opL) + INT_INTOBJ(opR);869if ( 0 < cs ) {870sum = NewBag( T_INTPOS, 4*sizeof(TypDigit) );871ADDR_INT(sum)[0] = (TypDigit)cs;872ADDR_INT(sum)[1] = (TypDigit)(cs >> NR_DIGIT_BITS);873}874else {875sum = NewBag( T_INTNEG, 4*sizeof(TypDigit) );876ADDR_INT(sum)[0] = (TypDigit)(-cs);877ADDR_INT(sum)[1] = (TypDigit)((-cs) >> NR_DIGIT_BITS);878}879880}881882/* adding one large integer and one small integer */883else if ( IS_INTOBJ(opL) || IS_INTOBJ(opR) ) {884885/* make the right operand the small one */886if ( IS_INTOBJ(opL) ) {887sum = opL; opL = opR; opR = sum;888}889890/* if the integers have different sign, let 'DiffInt' do the work */891if ( (TNUM_OBJ(opL) == T_INTNEG && 0 <= INT_INTOBJ(opR))892|| (TNUM_OBJ(opL) == T_INTPOS && INT_INTOBJ(opR) < 0) ) {893if ( TNUM_OBJ(opL) == T_INTPOS ) RetypeBag( opL, T_INTNEG );894else RetypeBag( opL, T_INTPOS );895sum = DiffInt( opR, opL );896if ( TNUM_OBJ(opL) == T_INTPOS ) RetypeBag( opL, T_INTNEG );897else RetypeBag( opL, T_INTPOS );898return sum;899}900901/* allocate the result bag and set up the pointers */902if ( TNUM_OBJ(opL) == T_INTPOS ) {903i = INT_INTOBJ(opR);904sum = NewBag( T_INTPOS, (SIZE_INT(opL)+4)*sizeof(TypDigit) );905}906else {907i = -INT_INTOBJ(opR);908sum = NewBag( T_INTNEG, (SIZE_INT(opL)+4)*sizeof(TypDigit) );909}910l = ADDR_INT(opL);911s = ADDR_INT(sum);912913/* add the first four digits,the right operand has only two digits */914c = (UInt)*l++ + (TypDigit)i; *s++ = (TypDigit)c;915c = (UInt)*l++ + (i>>NR_DIGIT_BITS) + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;916c = (UInt)*l++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;917c = (UInt)*l++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;918919/* propagate the carry, this loop is almost never executed */920for ( k = SIZE_INT(opL)/4-1; k != 0 && (c>>NR_DIGIT_BITS) != 0; k-- ) {921c = (UInt)*l++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;922c = (UInt)*l++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;923c = (UInt)*l++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;924c = (UInt)*l++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;925}926927/* just copy the remaining digits, do it two digits at once */928for ( l2 = (UInt*)l, s2 = (UInt*)s; k != 0; k-- ) {929*s2++ = *l2++;930*s2++ = *l2++;931}932933/* if there is a carry, enter it, otherwise shrink the sum */934if ( (c>>NR_DIGIT_BITS) != 0 )935*s++ = (TypDigit)(c>>NR_DIGIT_BITS);936else937ResizeBag( sum, (SIZE_INT(sum)-4)*sizeof(TypDigit) );938939}940941/* add two large integers */942else {943944/* if the integers have different sign, let 'DiffInt' do the work */945if ( (TNUM_OBJ(opL) == T_INTPOS && TNUM_OBJ(opR) == T_INTNEG)946|| (TNUM_OBJ(opL) == T_INTNEG && TNUM_OBJ(opR) == T_INTPOS) ) {947if ( TNUM_OBJ(opL) == T_INTPOS ) RetypeBag( opL, T_INTNEG );948else RetypeBag( opL, T_INTPOS );949sum = DiffInt( opR, opL );950if ( TNUM_OBJ(opL) == T_INTPOS ) RetypeBag( opL, T_INTNEG );951else RetypeBag( opL, T_INTPOS );952return sum;953}954955/* make the right operand the smaller one */956if ( SIZE_INT(opL) < SIZE_INT(opR) ) {957sum = opL; opL = opR; opR = sum;958}959960/* allocate the result bag and set up the pointers */961if ( TNUM_OBJ(opL) == T_INTPOS ) {962sum = NewBag( T_INTPOS, (SIZE_INT(opL)+4)*sizeof(TypDigit) );963}964else {965sum = NewBag( T_INTNEG, (SIZE_INT(opL)+4)*sizeof(TypDigit) );966}967l = ADDR_INT(opL);968r = ADDR_INT(opR);969s = ADDR_INT(sum);970971/* add the digits, convert to UInt to get maximum precision */972c = 0;973for ( k = SIZE_INT(opR)/4; k != 0; k-- ) {974c = (UInt)*l++ + (UInt)*r++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;975c = (UInt)*l++ + (UInt)*r++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;976c = (UInt)*l++ + (UInt)*r++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;977c = (UInt)*l++ + (UInt)*r++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;978}979980/* propagate the carry, this loop is almost never executed */981for ( k=(SIZE_INT(opL)-SIZE_INT(opR))/4;982k!=0 && (c>>NR_DIGIT_BITS)!=0; k-- ) {983c = (UInt)*l++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;984c = (UInt)*l++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;985c = (UInt)*l++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;986c = (UInt)*l++ + (c>>NR_DIGIT_BITS); *s++ = (TypDigit)c;987}988989/* just copy the remaining digits, do it two digits at once */990for ( l2 = (UInt*)l, s2 = (UInt*)s; k != 0; k-- ) {991*s2++ = *l2++;992*s2++ = *l2++;993}994995/* if there is a carry, enter it, otherwise shrink the sum */996if ( (c>>NR_DIGIT_BITS) != 0 )997*s++ = (TypDigit)(c>>NR_DIGIT_BITS);998else999ResizeBag( sum, (SIZE_INT(sum)-4)*sizeof(TypDigit) );10001001}10021003/* return the sum */1004return sum;1005}100610071008/****************************************************************************1009**1010*F ZeroInt(<int>) . . . . . . . . . . . . . . . . . . . . zero of integers1011*/1012Obj ZeroInt (1013Obj op )1014{1015return INTOBJ_INT(0);1016}101710181019/****************************************************************************1020**1021*F AInvInt(<int>) . . . . . . . . . . . . . additive inverse of an integer1022*/1023Obj AInvInt (1024Obj op )1025{1026Obj inv;1027UInt i;10281029/* handle small integer */1030if ( IS_INTOBJ( op ) ) {10311032/* special case (ugh) */1033if ( op == INTOBJ_INT( -(1L<<NR_SMALL_INT_BITS) ) ) {1034inv = NewBag( T_INTPOS, 4*sizeof(TypDigit) );1035ADDR_INT(inv)[0] = 0;1036ADDR_INT(inv)[1] = (TypDigit)(1L<<(NR_SMALL_INT_BITS-NR_DIGIT_BITS));1037}10381039/* general case */1040else {1041inv = INTOBJ_INT( - INT_INTOBJ( op ) );1042}10431044}10451046/* invert a large integer */1047else {10481049/* special case (ugh) */1050if ( TNUM_OBJ(op) == T_INTPOS && SIZE_INT(op) == 41051&& ADDR_INT(op)[3] == 01052&& ADDR_INT(op)[2] == 01053&& ADDR_INT(op)[1] == (1L<<(NR_SMALL_INT_BITS-NR_DIGIT_BITS))1054&& ADDR_INT(op)[0] == 0 ) {1055inv = INTOBJ_INT( -(1L<<NR_SMALL_INT_BITS) );1056}10571058/* general case */1059else {1060if ( TNUM_OBJ(op) == T_INTPOS ) {1061inv = NewBag( T_INTNEG, SIZE_OBJ(op) );1062}1063else {1064inv = NewBag( T_INTPOS, SIZE_OBJ(op) );1065}1066for ( i = 0; i < SIZE_INT(op); i++ ) {1067ADDR_INT(inv)[i] = ADDR_INT(op)[i];1068}1069}10701071}10721073/* return the inverse */1074return inv;1075}107610771078/****************************************************************************1079**1080*F DiffInt( <intL>, <intR> ) . . . . . . . . . . difference of two integers1081**1082** 'DiffInt' returns the difference of the two integer arguments <intL> and1083** <intR>. 'DiffInt' handles operands of type 'T_INT', 'T_INTPOS' and1084** 'T_INTNEG'.1085**1086** It can also be used in the cases that both operands are small integers1087** and the result is a small integer too, i.e., that no overflow occurs.1088** This case is usually already handled in 'EvalDiff' for a better efficiency.1089**1090** Is called from the 'EvalDiff' binop so both operands are already evaluated.1091**1092** 'DiffInt' is a little bit difficult since there are 16 different cases to1093** handle, each operand can be positive or negative, small or large integer.1094** If the operands have opposite sign 'DiffInt' calls 'SumInt', this helps1095** reduce the total amount of code by a factor of two.1096*/1097Obj DiffInt (1098Obj opL,1099Obj opR )1100{1101Int i; /* loop variable */1102Int k; /* loop variable */1103Int c; /* difference of two digits */1104TypDigit * l; /* pointer into the left operand */1105TypDigit * r; /* pointer into the right operand */1106TypDigit * d; /* pointer into the difference */1107UInt * l2; /* pointer to get 2 digits at once */1108UInt * d2; /* pointer to put 2 digits at once */1109Obj dif; /* handle of the result bag */11101111/* subtracting two small integers */1112if ( ARE_INTOBJS( opL, opR ) ) {11131114/* subtract two small integers with a small difference */1115/* sub and compare top two bits to check that no overflow occured */1116if ( DIFF_INTOBJS( dif, opL, opR ) ) {1117return dif;1118}11191120/* subtract two small integers with a large difference */1121c = INT_INTOBJ(opL) - INT_INTOBJ(opR);1122if ( 0 < c ) {1123dif = NewBag( T_INTPOS, 4*sizeof(TypDigit) );1124ADDR_INT(dif)[0] = (TypDigit)c;1125ADDR_INT(dif)[1] = (TypDigit)(c >> NR_DIGIT_BITS);1126}1127else {1128dif = NewBag( T_INTNEG, 4*sizeof(TypDigit) );1129ADDR_INT(dif)[0] = (TypDigit)(-c);1130ADDR_INT(dif)[1] = (TypDigit)((-c) >> NR_DIGIT_BITS);1131}11321133}11341135/* subtracting one small integer and one large integer */1136else if ( IS_INTOBJ( opL ) || IS_INTOBJ( opR ) ) {11371138/* make the right operand the small one */1139if ( IS_INTOBJ( opL ) ) {1140dif = opL; opL = opR; opR = dif;1141c = -1;1142}1143else {1144c = 1;1145}11461147/* if the integers have different sign, let 'SumInt' do the work */1148if ( (TNUM_OBJ(opL) == T_INTNEG && 0 <= INT_INTOBJ(opR))1149|| (TNUM_OBJ(opL) == T_INTPOS && INT_INTOBJ(opR) < 0) ) {1150if ( TNUM_OBJ(opL) == T_INTPOS ) RetypeBag( opL, T_INTNEG );1151else RetypeBag( opL, T_INTPOS );1152dif = SumInt( opL, opR );1153if ( TNUM_OBJ(opL) == T_INTPOS ) RetypeBag( opL, T_INTNEG );1154else RetypeBag( opL, T_INTPOS );1155if ( c == 1 ) {1156if ( TNUM_OBJ(dif) == T_INTPOS ) RetypeBag( dif, T_INTNEG );1157else RetypeBag( dif, T_INTPOS );1158}1159return dif;1160}11611162/* allocate the result bag and set up the pointers */1163if ( TNUM_OBJ(opL) == T_INTPOS ) {1164i = INT_INTOBJ(opR);1165if ( c == 1 ) dif = NewBag( T_INTPOS, SIZE_OBJ(opL) );1166else dif = NewBag( T_INTNEG, SIZE_OBJ(opL) );1167}1168else {1169i = - INT_INTOBJ(opR);1170if ( c == 1 ) dif = NewBag( T_INTNEG, SIZE_OBJ(opL) );1171else dif = NewBag( T_INTPOS, SIZE_OBJ(opL) );1172}1173l = ADDR_INT(opL);1174d = ADDR_INT(dif);11751176/* sub the first four digit, note the left operand has only two */1177/*N (c>>16<) need not work, replace by (c<0?-1:0) */1178c = (Int)*l++ - (TypDigit)i; *d++ = (TypDigit)c;1179c = (Int)*l++ - (TypDigit)(i/(1L<<NR_DIGIT_BITS)) + (c<0?-1:0); *d++ = (TypDigit)c;1180c = (Int)*l++ + (c<0?-1:0); *d++ = (TypDigit)c;1181c = (Int)*l++ + (c<0?-1:0); *d++ = (TypDigit)c;11821183/* propagate the carry, this loop is almost never executed */1184for ( k = SIZE_INT(opL)/4-1; k != 0 && c < 0; k-- ) {1185c = (Int)*l++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1186c = (Int)*l++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1187c = (Int)*l++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1188c = (Int)*l++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1189}11901191/* just copy the remaining digits, do it two digits at once */1192for ( l2 = (UInt*)l, d2 = (UInt*)d; k != 0; k-- ) {1193*d2++ = *l2++;1194*d2++ = *l2++;1195}11961197/* no underflow since we subtracted a small int from a large one */1198/* but there may be leading zeroes in the result, get rid of them */1199/* occurs almost never, so it doesn't matter that it is expensive */1200if ( ((UInt*)d == d21201&& d[-4] == 0 && d[-3] == 0 && d[-2] == 0 && d[-1] == 0)1202|| (SIZE_INT(dif) == 4 && d[-2] == 0 && d[-1] == 0) ) {12031204/* find the number of significant digits */1205d = ADDR_INT(dif);1206for ( k = SIZE_INT(dif); k != 0; k-- ) {1207if ( d[k-1] != 0 )1208break;1209}12101211/* reduce to small integer if possible, otherwise shrink bag */1212if ( k <= 2 && TNUM_OBJ(dif) == T_INTPOS1213&& (UInt)(INTBASE*d[1]+d[0])<(1L<<NR_SMALL_INT_BITS) )1214dif = INTOBJ_INT( INTBASE*d[1]+d[0] );1215else if ( k <= 2 && TNUM_OBJ(dif) == T_INTNEG1216&& (UInt)(INTBASE*d[1]+d[0])<=(1L<<NR_SMALL_INT_BITS) )1217dif = INTOBJ_INT( -(Int)(INTBASE*d[1]+d[0]) );1218else1219ResizeBag( dif, (((k + 3) / 4) * 4) * sizeof(TypDigit) );1220}12211222}12231224/* subtracting two large integers */1225else {12261227/* if the integers have different sign, let 'SumInt' do the work */1228if ( (TNUM_OBJ(opL) == T_INTPOS && TNUM_OBJ(opR) == T_INTNEG)1229|| (TNUM_OBJ(opL) == T_INTNEG && TNUM_OBJ(opR) == T_INTPOS) ) {1230if ( TNUM_OBJ(opR) == T_INTPOS ) RetypeBag( opR, T_INTNEG );1231else RetypeBag( opR, T_INTPOS );1232dif = SumInt( opL, opR );1233if ( TNUM_OBJ(opR) == T_INTPOS ) RetypeBag( opR, T_INTNEG );1234else RetypeBag( opR, T_INTPOS );1235return dif;1236}12371238/* make the right operand the smaller one */1239if ( SIZE_INT(opL) < SIZE_INT(opR)1240|| (TNUM_OBJ(opL) == T_INTPOS && LtInt(opL,opR) )1241|| (TNUM_OBJ(opL) == T_INTNEG && LtInt(opR,opL) ) ) {1242dif = opL; opL = opR; opR = dif; c = -1;1243}1244else {1245c = 1;1246}12471248/* allocate the result bag and set up the pointers */1249if ( (TNUM_OBJ(opL) == T_INTPOS && c == 1)1250|| (TNUM_OBJ(opL) == T_INTNEG && c == -1) )1251dif = NewBag( T_INTPOS, SIZE_OBJ(opL) );1252else1253dif = NewBag( T_INTNEG, SIZE_OBJ(opL) );1254l = ADDR_INT(opL);1255r = ADDR_INT(opR);1256d = ADDR_INT(dif);12571258/* subtract the digits */1259c = 0;1260for ( k = SIZE_INT(opR)/4; k != 0; k-- ) {1261c = (Int)*l++ - (Int)*r++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1262c = (Int)*l++ - (Int)*r++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1263c = (Int)*l++ - (Int)*r++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1264c = (Int)*l++ - (Int)*r++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1265}12661267/* propagate the carry, this loop is almost never executed */1268for ( k=(SIZE_INT(opL)-SIZE_INT(opR))/4;1269k!=0 && c < 0; k-- ) {1270c = (Int)*l++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1271c = (Int)*l++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1272c = (Int)*l++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1273c = (Int)*l++ + (c < 0 ? -1 : 0); *d++ = (TypDigit)c;1274}12751276/* just copy the remaining digits, do it two digits at once */1277for ( d2 = (UInt*)d, l2 = (UInt*)l; k != 0; k-- ) {1278*d2++ = *l2++;1279*d2++ = *l2++;1280}12811282/* no underflow since we subtracted a small int from a large one */1283/* but there may be leading zeroes in the result, get rid of them */1284/* occurs almost never, so it doesn't matter that it is expensive */1285if ( ((UInt*)d == d21286&& d[-4] == 0 && d[-3] == 0 && d[-2] == 0 && d[-1] == 0)1287|| (SIZE_INT(dif) == 4 && d[-2] == 0 && d[-1] == 0) ) {12881289/* find the number of significant digits */1290d = ADDR_INT(dif);1291for ( k = SIZE_INT(dif); k != 0; k-- ) {1292if ( d[k-1] != 0 )1293break;1294}12951296/* reduce to small integer if possible, otherwise shrink bag */1297if ( k <= 2 && TNUM_OBJ(dif) == T_INTPOS1298&& (UInt)(INTBASE*d[1]+d[0]) < (1L<<NR_SMALL_INT_BITS) )1299dif = INTOBJ_INT( INTBASE*d[1]+d[0] );1300else if ( k <= 2 && TNUM_OBJ(dif) == T_INTNEG1301&& (UInt)(INTBASE*d[1]+d[0])<=(1L<<NR_SMALL_INT_BITS))1302dif = INTOBJ_INT( -(Int)(INTBASE*d[1]+d[0]) );1303else1304ResizeBag( dif, (((k + 3) / 4) * 4) * sizeof(TypDigit) );13051306}13071308}13091310/* return the difference */1311return dif;1312}131313141315/****************************************************************************1316**1317*F ProdInt( <intL>, <intR> ) . . . . . . . . . . . . product of two integers1318**1319** 'ProdInt' returns the product of the two integer arguments <intL> and1320** <intR>. 'ProdInt' handles operands of type 'T_INT', 'T_INTPOS' and1321** 'T_INTNEG'.1322**1323** It can also be used in the cases that both operands are small integers1324** and the result is a small integer too, i.e., that no overflow occurs.1325** This case is usually already handled in 'EvalProd' for a better efficiency.1326**1327** Is called from the 'EvalProd' binop so both operands are already evaluated.1328**1329** The only difficulty about this function is the fact that is has to handle1330** 3 different situations, depending on how many arguments are small ints.1331*/1332Obj ProdInt (1333Obj opL,1334Obj opR )1335{1336Int i; /* loop count, value for small int */1337Int k; /* loop count, value for small int */1338UInt c; /* product of two digits */1339TypDigit l; /* one digit of the left operand */1340TypDigit * r; /* pointer into the right operand */1341TypDigit * p; /* pointer into the product */1342Obj prd; /* handle of the result bag */13431344/* multiplying two small integers */1345if ( ARE_INTOBJS( opL, opR ) ) {13461347/* multiply two small integers with a small product */1348/* multiply and divide back to check that no overflow occured */1349if ( PROD_INTOBJS( prd, opL, opR ) ) {1350return prd;1351}13521353/* get the integer values */1354i = INT_INTOBJ(opL);1355k = INT_INTOBJ(opR);13561357/* allocate the product bag */1358if ( (0 < i && 0 < k) || (i < 0 && k < 0) )1359prd = NewBag( T_INTPOS, 4*sizeof(TypDigit) );1360else1361prd = NewBag( T_INTNEG, 4*sizeof(TypDigit) );1362p = ADDR_INT(prd);13631364/* make both operands positive */1365if ( i < 0 ) i = -i;1366if ( k < 0 ) k = -k;13671368/* multiply digitwise */1369c = (UInt)(TypDigit)i * (TypDigit)k; p[0] = (TypDigit)c;1370c = (UInt)(TypDigit)i * (((UInt)k)>>NR_DIGIT_BITS)1371+ (c>>NR_DIGIT_BITS); p[1] = (TypDigit)c;1372p[2] = c>>NR_DIGIT_BITS;13731374c = (UInt)(TypDigit)(((UInt)i)>>NR_DIGIT_BITS) * (TypDigit)k1375+ p[1]; p[1] = (TypDigit)c;1376c = (UInt)(TypDigit)(((UInt)i)>>NR_DIGIT_BITS) * (TypDigit)(((UInt)k)>>NR_DIGIT_BITS)1377+ p[2] + (c>>NR_DIGIT_BITS); p[2] = (TypDigit)c;1378p[3] = (TypDigit)(c>>NR_DIGIT_BITS);13791380}13811382/* multiply a small and a large integer */1383else if ( IS_INTOBJ(opL) || IS_INTOBJ(opR) ) {13841385/* make the left operand the small one */1386if ( IS_INTOBJ(opR) ) {1387i = INT_INTOBJ(opR); opR = opL;1388}1389else {1390i = INT_INTOBJ(opL);1391}13921393/* handle trivial cases first */1394if ( i == 0 )1395return INTOBJ_INT(0);1396if ( i == 1 )1397return opR;13981399/* the large integer 1<<28 times -1 is the small integer -(1<<28) */1400if ( i == -11401&& TNUM_OBJ(opR) == T_INTPOS && SIZE_INT(opR) == 41402&& ADDR_INT(opR)[3] == 01403&& ADDR_INT(opR)[2] == 01404&& ADDR_INT(opR)[1] == (1L<<(NR_SMALL_INT_BITS-NR_DIGIT_BITS))1405&& ADDR_INT(opR)[0] == 0 )1406return INTOBJ_INT( -(Int)(1L<<NR_SMALL_INT_BITS) );14071408/* multiplication by -1 is easy, just switch the sign and copy */1409if ( i == -1 ) {1410if ( TNUM_OBJ(opR) == T_INTPOS )1411prd = NewBag( T_INTNEG, SIZE_OBJ(opR) );1412else1413prd = NewBag( T_INTPOS, SIZE_OBJ(opR) );1414r = ADDR_INT(opR);1415p = ADDR_INT(prd);1416for ( k = SIZE_INT(opR)/4; k != 0; k-- ) {1417/*N should be: *p2++=*r2++; *p2++=*r2++; */1418*p++ = *r++; *p++ = *r++; *p++ = *r++; *p++ = *r++;1419}1420return prd;1421}14221423/* allocate a bag for the result */1424if ( (0 < i && TNUM_OBJ(opR) == T_INTPOS)1425|| (i < 0 && TNUM_OBJ(opR) == T_INTNEG) )1426prd = NewBag( T_INTPOS, (SIZE_INT(opR)+4)*sizeof(TypDigit) );1427else1428prd = NewBag( T_INTNEG, (SIZE_INT(opR)+4)*sizeof(TypDigit) );1429if ( i < 0 ) i = -i;14301431/* multiply with the lower digit of the left operand */1432l = (TypDigit)i;1433if ( l != 0 ) {14341435r = ADDR_INT(opR);1436p = ADDR_INT(prd);1437c = 0;14381439/* multiply the right with this digit and store in the product */1440for ( k = SIZE_INT(opR)/4; k != 0; k-- ) {1441c = (UInt)l * (UInt)*r++ + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1442c = (UInt)l * (UInt)*r++ + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1443c = (UInt)l * (UInt)*r++ + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1444c = (UInt)l * (UInt)*r++ + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1445}1446*p = (TypDigit)(c>>NR_DIGIT_BITS);1447}14481449/* multiply with the larger digit of the left operand */1450l = ((UInt)i) >> NR_DIGIT_BITS;1451if ( l != 0 ) {14521453r = ADDR_INT(opR);1454p = ADDR_INT(prd) + 1;1455c = 0;14561457/* multiply the right with this digit and add into the product */1458for ( k = SIZE_INT(opR)/4; k != 0; k-- ) {1459c = (UInt)l * (UInt)*r++ + (UInt)*p + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1460c = (UInt)l * (UInt)*r++ + (UInt)*p + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1461c = (UInt)l * (UInt)*r++ + (UInt)*p + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1462c = (UInt)l * (UInt)*r++ + (UInt)*p + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1463}1464*p = (TypDigit)(c>>NR_DIGIT_BITS);1465}14661467/* remove the leading zeroes, note that there can't be more than 6 */1468p = ADDR_INT(prd) + SIZE_INT(prd);1469if ( p[-4] == 0 && p[-3] == 0 && p[-2] == 0 && p[-1] == 0 ) {1470ResizeBag( prd, (SIZE_INT(prd)-4)*sizeof(TypDigit) );1471}14721473}14741475/* multiply two large integers */1476else {14771478/* make the left operand the smaller one, for performance */1479if ( SIZE_INT(opL) > SIZE_INT(opR) ) {1480prd = opR; opR = opL; opL = prd;1481}14821483/* allocate a bag for the result */1484if ( TNUM_OBJ(opL) == TNUM_OBJ(opR) )1485prd = NewBag( T_INTPOS, SIZE_OBJ(opL)+SIZE_OBJ(opR) );1486else1487prd = NewBag( T_INTNEG, SIZE_OBJ(opL)+SIZE_OBJ(opR) );14881489/* run through the digits of the left operand */1490for ( i = 0; i < (Int)SIZE_INT(opL); i++ ) {14911492/* set up pointer for one loop iteration */1493l = ADDR_INT(opL)[i];1494if ( l == 0 ) continue;1495r = ADDR_INT(opR);1496p = ADDR_INT(prd) + i;1497c = 0;14981499/* multiply the right with this digit and add into the product */1500for ( k = SIZE_INT(opR)/4; k != 0; k-- ) {1501c = (UInt)l * (UInt)*r++ + (UInt)*p + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1502c = (UInt)l * (UInt)*r++ + (UInt)*p + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1503c = (UInt)l * (UInt)*r++ + (UInt)*p + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1504c = (UInt)l * (UInt)*r++ + (UInt)*p + (c>>NR_DIGIT_BITS); *p++ = (TypDigit)c;1505}1506*p = (TypDigit)(c>>NR_DIGIT_BITS);1507}15081509/* remove the leading zeroes, note that there can't be more than 7 */1510p = ADDR_INT(prd) + SIZE_INT(prd);1511if ( p[-4] == 0 && p[-3] == 0 && p[-2] == 0 && p[-1] == 0 ) {1512ResizeBag( prd, (SIZE_INT(prd)-4)*sizeof(TypDigit) );1513}15141515}15161517/* return the product */1518return prd;1519}152015211522/****************************************************************************1523**1524*F ProdIntObj(<n>,<op>) . . . . . . . . product of an integer and an object1525*/1526Obj ProdIntObj (1527Obj n,1528Obj op )1529{1530Obj res = 0; /* result */1531UInt i, k, l; /* loop variables */15321533/* if the integer is zero, return the neutral element of the operand */1534if ( TNUM_OBJ(n) == T_INT && INT_INTOBJ(n) == 0 ) {1535res = ZERO( op );1536}15371538/* if the integer is one, return the object if immutable1539if mutable, add the object to its ZeroSameMutability to1540ensure correct mutability propagation */1541else if ( TNUM_OBJ(n) == T_INT && INT_INTOBJ(n) == 1 ) {1542if (IS_MUTABLE_OBJ(op))1543res = SUM(ZERO(op),op);1544else1545res = op;1546}15471548/* if the integer is minus one, return the inverse of the operand */1549else if ( TNUM_OBJ(n) == T_INT && INT_INTOBJ(n) == -1 ) {1550res = AINV( op );1551}15521553/* if the integer is negative, invert the operand and the integer */1554else if ( TNUM_OBJ(n) == T_INT && INT_INTOBJ(n) < -1 ) {1555res = AINV( op );1556if ( res == Fail ) {1557return ErrorReturnObj(1558"Operations: <obj> must have an additive inverse",15590L, 0L,1560"you can supply an inverse <inv> for <obj> via 'return <inv>;'" );1561}1562res = PROD( AINV( n ), res );1563}15641565/* if the integer is negative, invert the operand and the integer */1566else if ( TNUM_OBJ(n) == T_INTNEG ) {1567res = AINV( op );1568if ( res == Fail ) {1569return ErrorReturnObj(1570"Operations: <obj> must have an additive inverse",15710L, 0L,1572"you can supply an inverse <inv> for <obj> via 'return <inv>;'" );1573}1574res = PROD( AINV( n ), res );1575}15761577/* if the integer is small, compute the product by repeated doubling */1578/* the loop invariant is <result> = <k>*<res> + <l>*<op>, <l> < <k> */1579/* <res> = 0 means that <res> is the neutral element */1580else if ( TNUM_OBJ(n) == T_INT && INT_INTOBJ(n) > 1 ) {1581res = 0;1582k = 1L << (NR_SMALL_INT_BITS+1);1583l = INT_INTOBJ(n);1584while ( 1 < k ) {1585res = (res == 0 ? res : SUM( res, res ));1586k = k / 2;1587if ( k <= l ) {1588res = (res == 0 ? op : SUM( res, op ));1589l = l - k;1590}1591}1592}15931594/* if the integer is large, compute the product by repeated doubling */1595else if ( TNUM_OBJ(n) == T_INTPOS ) {1596res = 0;1597for ( i = SIZE_OBJ(n)/sizeof(TypDigit); 0 < i; i-- ) {1598k = 1L << (8*sizeof(TypDigit));1599l = ((TypDigit*) ADDR_OBJ(n))[i-1];1600while ( 1 < k ) {1601res = (res == 0 ? res : SUM( res, res ));1602k = k / 2;1603if ( k <= l ) {1604res = (res == 0 ? op : SUM( res, op ));1605l = l - k;1606}1607}1608}1609}16101611/* return the result */1612return res;1613}16141615Obj ProdIntObjFunc;16161617Obj FuncPROD_INT_OBJ (1618Obj self,1619Obj opL,1620Obj opR )1621{1622return ProdIntObj( opL, opR );1623}162416251626/****************************************************************************1627**1628*F OneInt(<int>) . . . . . . . . . . . . . . . . . . . . . one of an integer1629*/1630Obj OneInt (1631Obj op )1632{1633return INTOBJ_INT( 1L );1634}163516361637/****************************************************************************1638**1639*F PowInt( <intL>, <intR> ) . . . . . . . . . . . . . . power of an integer1640**1641** 'PowInt' returns the <intR>-th (an integer) power of the integer <intL>.1642** 'PowInt' handles operands of type 'T_INT', 'T_INTPOS' and 'T_INTNEG'.1643**1644** It can also be used in the cases that both operands are small integers1645** and the result is a small integer too, i.e., that no overflow occurs.1646** This case is usually already handled in 'EvalPow' for a better efficiency.1647**1648** Is called from the 'EvalPow' binop so both operands are already evaluated.1649*/1650Obj PowInt (1651Obj opL,1652Obj opR )1653{1654Int i;1655Obj pow;16561657/* power with a large exponent */1658ReadGuard(opL);1659ReadGuard(opR);1660if ( ! IS_INTOBJ(opR) ) {1661if ( opL == INTOBJ_INT(0) )1662pow = INTOBJ_INT(0);1663else if ( opL == INTOBJ_INT(1) )1664pow = INTOBJ_INT(1);1665else if ( opL == INTOBJ_INT(-1) && ADDR_INT(opR)[0] % 2 == 0 )1666pow = INTOBJ_INT(1);1667else if ( opL == INTOBJ_INT(-1) && ADDR_INT(opR)[0] % 2 != 0 )1668pow = INTOBJ_INT(-1);1669else {1670opR = ErrorReturnObj(1671"Integer operands: <exponent> is too large",16720L, 0L,1673"you can replace the integer <exponent> via 'return <exponent>;'" );1674return POW( opL, opR );1675}1676}16771678/* power with a negative exponent */1679else if ( INT_INTOBJ(opR) < 0 ) {1680if ( opL == INTOBJ_INT(0) ) {1681opL = ErrorReturnObj(1682"Integer operands: <base> must not be zero",16830L, 0L,1684"you can replace the integer <base> via 'return <base>;'" );1685return POW( opL, opR );1686}1687else if ( opL == INTOBJ_INT(1) )1688pow = INTOBJ_INT(1);1689else if ( opL == INTOBJ_INT(-1) && INT_INTOBJ(opR) % 2 == 0 )1690pow = INTOBJ_INT(1);1691else if ( opL == INTOBJ_INT(-1) && INT_INTOBJ(opR) % 2 != 0 )1692pow = INTOBJ_INT(-1);1693else1694pow = QUO( INTOBJ_INT(1),1695PowInt( opL, INTOBJ_INT( -INT_INTOBJ(opR)) ) );1696}16971698/* power with a small positive exponent, do it by a repeated squaring */1699else {1700pow = INTOBJ_INT(1);1701i = INT_INTOBJ(opR);1702while ( i != 0 ) {1703if ( i % 2 == 1 ) pow = ProdInt( pow, opL );1704if ( i > 1 ) opL = ProdInt( opL, opL );1705i = i / 2;1706}1707}17081709/* return the power */1710return pow;1711}171217131714/****************************************************************************1715**1716*F PowObjInt(<op>,<n>) . . . . . . . . . . power of an object and an integer1717*/1718static Obj OneAttr;17191720Obj PowObjInt (1721Obj op,1722Obj n )1723{1724Obj res = 0; /* result */1725UInt i, k, l; /* loop variables */17261727/* if the integer is zero, return the neutral element of the operand */1728if ( TNUM_OBJ(n) == T_INT && INT_INTOBJ(n) == 0 ) {1729return ONE_MUT( op );1730}17311732/* if the integer is one, return a copy of the operand */1733else if ( TNUM_OBJ(n) == T_INT && INT_INTOBJ(n) == 1 ) {1734res = CopyObj( op, 1 );1735}17361737/* if the integer is minus one, return the inverse of the operand */1738else if ( TNUM_OBJ(n) == T_INT && INT_INTOBJ(n) == -1 ) {1739res = INV_MUT( op );1740}17411742/* if the integer is negative, invert the operand and the integer */1743else if ( TNUM_OBJ(n) == T_INT && INT_INTOBJ(n) < 0 ) {1744res = INV_MUT( op );1745if ( res == Fail ) {1746return ErrorReturnObj(1747"Operations: <obj> must have an inverse",17480L, 0L,1749"you can supply an inverse <inv> for <obj> via 'return <inv>;'" );1750}1751res = POW( res, AINV( n ) );1752}17531754/* if the integer is negative, invert the operand and the integer */1755else if ( TNUM_OBJ(n) == T_INTNEG ) {1756res = INV_MUT( op );1757if ( res == Fail ) {1758return ErrorReturnObj(1759"Operations: <obj> must have an inverse",17600L, 0L,1761"you can supply an inverse <inv> for <obj> via 'return <inv>;'" );1762}1763res = POW( res, AINV( n ) );1764}17651766/* if the integer is small, compute the power by repeated squaring */1767/* the loop invariant is <result> = <res>^<k> * <op>^<l>, <l> < <k> */1768/* <res> = 0 means that <res> is the neutral element */1769else if ( TNUM_OBJ(n) == T_INT && INT_INTOBJ(n) > 0 ) {1770res = 0;1771k = 1L << (NR_SMALL_INT_BITS+1);1772l = INT_INTOBJ(n);1773while ( 1 < k ) {1774res = (res == 0 ? res : PROD( res, res ));1775k = k / 2;1776if ( k <= l ) {1777res = (res == 0 ? op : PROD( res, op ));1778l = l - k;1779}1780}1781}17821783/* if the integer is large, compute the power by repeated squaring */1784else if ( TNUM_OBJ(n) == T_INTPOS ) {1785res = 0;1786for ( i = SIZE_OBJ(n)/sizeof(TypDigit); 0 < i; i-- ) {1787k = 1L << (8*sizeof(TypDigit));1788l = ((TypDigit*) ADDR_OBJ(n))[i-1];1789while ( 1 < k ) {1790res = (res == 0 ? res : PROD( res, res ));1791k = k / 2;1792if ( k <= l ) {1793res = (res == 0 ? op : PROD( res, op ));1794l = l - k;1795}1796}1797}1798}17991800/* return the result */1801return res;1802}18031804Obj PowObjIntFunc;18051806Obj FuncPOW_OBJ_INT (1807Obj self,1808Obj opL,1809Obj opR )1810{1811return PowObjInt( opL, opR );1812}181318141815/****************************************************************************1816**1817*F ModInt( <intL>, <intR> ) . representative of residue class of an integer1818**1819** 'ModInt' returns the smallest positive representant of the residue class1820** of the integer <intL> modulo the integer <intR>. 'ModInt' handles1821** operands of type 'T_INT', 'T_INTPOS', 'T_INTNEG'.1822**1823** It can also be used in the cases that both operands are small integers1824** and the result is a small integer too, i.e., that no overflow occurs.1825** This case is usually already handled in 'EvalMod' for a better efficiency.1826p**1827** Is called from the 'EvalMod' binop so both operands are already evaluated.1828*/1829Obj ModInt (1830Obj opL,1831Obj opR )1832{1833Int i; /* loop count, value for small int */1834Int k; /* loop count, value for small int */1835UInt c; /* product of two digits */1836TypDigit d; /* carry into the next digit */1837TypDigit * l; /* pointer into the left operand */1838TypDigit * r; /* pointer into the right operand */1839TypDigit r1; /* leading digit of the right oper */1840TypDigit r2; /* next digit of the right operand */1841UInt rs; /* size of the right operand */1842UInt e; /* we mult r by 2^e so r1 >= 32768 */1843Obj mod; /* handle of the remainder bag */1844TypDigit * m; /* pointer into the remainder */1845UInt m01; /* leading two digits of the rem. */1846TypDigit m2; /* next digit of the remainder */1847TypDigit qi; /* guessed digit of the quotient */18481849/* compute the remainder of two small integers */1850if ( ARE_INTOBJS( opL, opR ) ) {18511852/* pathological case first */1853if ( opR == INTOBJ_INT(0) ) {1854opR = ErrorReturnObj(1855"Integer operations: <divisor> must be nonzero",18560L, 0L,1857"you can replace the integer <divisor> via 'return <divisor>;'" );1858return MOD( opL, opR );1859}18601861/* get the integer values */1862i = INT_INTOBJ(opL);1863k = INT_INTOBJ(opR);18641865/* compute the remainder, make sure we divide only positive numbers*/1866if ( 0 <= i && 0 <= k ) i = ( i % k );1867else if ( 0 <= i && k < 0 ) i = ( i % -k );1868else if ( i < 0 && 0 <= k ) i = ( k - ( -i % k )) % k;1869else if ( i < 0 && k < 0 ) i = (-k - ( -i % -k )) % k;1870mod = INTOBJ_INT( i );18711872}18731874/* compute the remainder of a small integer by a large integer */1875else if ( IS_INTOBJ(opL) ) {18761877/* the small int -(1<<28) mod the large int (1<<28) is 0 */1878if ( opL == INTOBJ_INT((UInt)-(Int)(1L<<NR_SMALL_INT_BITS))1879&& TNUM_OBJ(opR) == T_INTPOS && SIZE_INT(opR) == 41880&& ADDR_INT(opR)[3] == 01881&& ADDR_INT(opR)[2] == 01882&& ADDR_INT(opR)[1] == (NR_SMALL_INT_BITS-NR_DIGIT_BITS)1883&& ADDR_INT(opR)[0] == 0 )1884mod = INTOBJ_INT(0);18851886/* in all other cases the remainder is equal the left operand */1887else if ( 0 <= INT_INTOBJ(opL) )1888mod = opL;1889else if ( TNUM_OBJ(opR) == T_INTPOS )1890mod = SumInt( opL, opR );1891else1892mod = DiffInt( opL, opR );18931894}18951896/* compute the remainder of a large integer by a small integer */1897else if ( IS_INTOBJ(opR)1898&& INT_INTOBJ(opR) < INTBASE1899&& -(Int)INTBASE <= INT_INTOBJ(opR) ) {19001901/* pathological case first */1902if ( opR == INTOBJ_INT(0) ) {1903opR = ErrorReturnObj(1904"Integer operations: <divisor> must be nonzero",19050L, 0L,1906"you can replace the integer <divisor> via 'return <divisor>;'" );1907return MOD( opL, opR );1908}19091910/* get the integer value, make positive */1911i = INT_INTOBJ(opR); if ( i < 0 ) i = -i;19121913/* maybe its trivial */1914if ( INTBASE % i == 0 ) {1915c = ADDR_INT(opL)[0] % i;1916}19171918/* otherwise run through the left operand and divide digitwise */1919else {1920l = ADDR_INT(opL) + SIZE_INT(opL) - 1;1921c = 0;1922for ( ; l >= ADDR_INT(opL); l-- ) {1923c = (c<<NR_DIGIT_BITS) + (Int)*l;1924c = c % i;1925}1926}19271928/* now c is the result, it has the same sign as the left operand */1929if ( TNUM_OBJ(opL) == T_INTPOS )1930mod = INTOBJ_INT( c );1931else if ( c == 0 )1932mod = INTOBJ_INT( c );1933else if ( 0 <= INT_INTOBJ(opR) )1934mod = SumInt( INTOBJ_INT( -(Int)c ), opR );1935else1936mod = DiffInt( INTOBJ_INT( -(Int)c ), opR );19371938}19391940/* compute the remainder of a large integer modulo a large integer */1941else {1942/* a small divisor larger than one digit isn't handled above */1943if ( IS_INTOBJ(opR) ) {1944if ( 0 < INT_INTOBJ(opR) ) {1945mod = NewBag( T_INTPOS, 4*sizeof(TypDigit) );1946ADDR_INT(mod)[0] = (TypDigit)(INT_INTOBJ(opR));1947ADDR_INT(mod)[1] = (TypDigit)(INT_INTOBJ(opR)>>NR_DIGIT_BITS);1948opR = mod;1949}1950else {1951mod = NewBag( T_INTNEG, 4*sizeof(TypDigit) );1952ADDR_INT(mod)[0] = (TypDigit)(-INT_INTOBJ(opR));1953ADDR_INT(mod)[1] = (TypDigit)((-INT_INTOBJ(opR))>>NR_DIGIT_BITS);1954opR = mod;1955}1956}19571958/* trivial case first */1959if ( SIZE_INT(opL) < SIZE_INT(opR) ) {1960if ( TNUM_OBJ(opL) == T_INTPOS )1961return opL;1962else if ( TNUM_OBJ(opR) == T_INTPOS )1963return SumInt( opL, opR );1964else1965return DiffInt( opL, opR );1966}19671968/* copy the left operand into a new bag, this holds the remainder */1969mod = NewBag( TNUM_OBJ(opL), (SIZE_INT(opL)+4)*sizeof(TypDigit) );1970l = ADDR_INT(opL);1971m = ADDR_INT(mod);1972for ( k = SIZE_INT(opL)-1; k >= 0; k-- )1973*m++ = *l++;19741975/* get the size of the right operand, and get the leading 2 digits */1976rs = SIZE_INT(opR);1977r = ADDR_INT(opR);1978while ( r[rs-1] == 0 ) rs--;1979for ( e = 0;1980((Int)r[rs-1]<<e) + (e ? r[rs-2]>>(NR_DIGIT_BITS-e) : 0)1981< INTBASE/2; e++ ) ;19821983r1 = ((Int)r[rs-1]<<e) + (e ? r[rs-2]>>(NR_DIGIT_BITS-e) : 0);1984r2 = ((Int)r[rs-2]<<e) + ((rs>=3 && e)? r[rs-3]>>(NR_DIGIT_BITS-e) : 0);19851986/* run through the digits in the quotient */1987for ( i = SIZE_INT(mod)-SIZE_INT(opR)-1; i >= 0; i-- ) {19881989/* guess the factor */1990m = ADDR_INT(mod) + rs + i;1991m01 = ((INTBASE*m[0]+m[-1])<<e)1992+ (e ? m[-2]>>(NR_DIGIT_BITS-e) : 0);1993if ( m01 == 0 ) continue;1994m2 = ((Int)m[-2]<<e) + ((e && rs+i>=3) ? m[-3]>>(NR_DIGIT_BITS-e) : 0);1995if ( ((Int)m[0]<<e)+(e ? m[-1]>>(NR_DIGIT_BITS-e) : 0) < r1 )1996qi = m01 / r1;1997else qi = INTBASE - 1;1998while ( m01-(Int)qi*r1 < (Int)INTBASE1999&& INTBASE*(m01-(Int)qi*r1)+m2 < (Int)qi*r2 )2000qi--;20012002/* m = m - qi * r; */2003d = 0;2004m = ADDR_INT(mod) + i;2005r = ADDR_INT(opR);2006for ( k = 0; k < (Int)rs; ++k, ++m, ++r ) {2007c = (Int)*m - (Int)qi * *r - (Int)d;2008*m = (TypDigit)c;2009d = -(TypDigit)(c>>NR_DIGIT_BITS);2010}2011c = (Int)*m - d; *m = (TypDigit)c; d = -(TypDigit)(c>>NR_DIGIT_BITS);20122013/* if we have a borrow then add back */2014if ( d != 0 ) {2015d = 0;2016m = ADDR_INT(mod) + i;2017r = ADDR_INT(opR);2018for ( k = 0; k < (Int)rs; ++k, ++m, ++r ) {2019c = (Int)*m + (Int)*r + (Int)d;2020*m = (TypDigit)c;2021d = (TypDigit)(c>>NR_DIGIT_BITS);2022}2023c = (Int)*m + d; *m = (TypDigit)c; d = (TypDigit)(c>>NR_DIGIT_BITS);2024qi--;2025}20262027}20282029/* remove the leading zeroes */2030m = ADDR_INT(mod) + SIZE_INT(mod);2031if ( (m[-4] == 0 && m[-3] == 0 && m[-2] == 0 && m[-1] == 0)2032|| (SIZE_INT(mod) == 4 && m[-2] == 0 && m[-1] == 0) ) {20332034/* find the number of significant digits */2035m = ADDR_INT(mod);2036for ( k = SIZE_INT(mod); k != 0; k-- ) {2037if ( m[k-1] != 0 )2038break;2039}20402041/* reduce to small integer if possible, otherwise shrink bag */20422043if ( k <= 2 && TNUM_OBJ(mod) == T_INTPOS2044&& (UInt)(INTBASE*m[1]+m[0])<(1L<<NR_SMALL_INT_BITS) )2045mod = INTOBJ_INT( INTBASE*m[1]+m[0] );2046else if ( k <= 2 && TNUM_OBJ(mod) == T_INTNEG2047&& (UInt)(INTBASE*m[1]+m[0])<=(1L<<NR_SMALL_INT_BITS) )2048mod = INTOBJ_INT( -(Int)(INTBASE*m[1]+m[0]) );2049else2050ResizeBag( mod, (((k + 3) / 4) * 4) * sizeof(TypDigit) );2051}20522053/* make the representative positive */2054if ( (TNUM_OBJ(mod) == T_INT && INT_INTOBJ(mod) < 0)2055|| TNUM_OBJ(mod) == T_INTNEG ) {2056if ( TNUM_OBJ(opR) == T_INTPOS )2057mod = SumInt( mod, opR );2058else2059mod = DiffInt( mod, opR );2060}20612062}20632064/* return the result */2065return mod;2066}206720682069/****************************************************************************2070**2071*F FuncIS_INT( <self>, <val> ) . . . . . . . . . . internal function 'IsInt'2072**2073** 'FuncIS_INT' implements the internal filter 'IsInt'.2074**2075** 'IsInt( <val> )'2076**2077** 'IsInt' returns 'true' if the value <val> is an integer and 'false'2078** otherwise.2079*/2080Obj IsIntFilt;20812082Obj FuncIS_INT (2083Obj self,2084Obj val )2085{2086/* return 'true' if <obj> is an integer and 'false' otherwise */2087if ( TNUM_OBJ(val) == T_INT2088|| TNUM_OBJ(val) == T_INTPOS2089|| TNUM_OBJ(val) == T_INTNEG ) {2090return True;2091}2092else if ( TNUM_OBJ(val) < FIRST_EXTERNAL_TNUM ) {2093return False;2094}2095else {2096return DoFilter( self, val );2097}2098}209921002101/****************************************************************************2102**2103*F QuoInt( <intL>, <intR> ) . . . . . . . . . . . quotient of two integers2104**2105** 'QuoInt' returns the integer part of the two integers <intL> and <intR>.2106** 'QuoInt' handles operands of type 'T_INT', 'T_INTPOS' and 'T_INTNEG'.2107**2108** It can also be used in the cases that both operands are small integers2109** and the result is a small integer too, i.e., that no overflow occurs.2110**2111** Note that this routine is not called from 'EvalQuo', the division of two2112** integers yields a rational and is therefor performed in 'QuoRat'.2113** This operation is however available through the internal function 'Quo'.2114*/2115Obj QuoInt (2116Obj opL,2117Obj opR )2118{2119Int i; /* loop count, value for small int */2120Int k; /* loop count, value for small int */2121UInt c; /* product of two digits */2122TypDigit d; /* carry into the next digit */2123TypDigit * l; /* pointer into the left operand */2124UInt l01; /* leading two digits of the left */2125TypDigit l2; /* next digit of the left operand */2126TypDigit * r; /* pointer into the right operand */2127TypDigit r1; /* leading digit of the right oper */2128TypDigit r2; /* next digit of the right operand */2129UInt rs; /* size of the right operand */2130UInt e; /* we mult r by 2^e so r1 >= 32768 */2131TypDigit * q; /* pointer into the quotient */2132Obj quo; /* handle of the result bag */2133TypDigit qi; /* guessed digit of the quotient */21342135/* divide to small integers */2136if ( ARE_INTOBJS( opL, opR ) ) {21372138/* pathological case first */2139if ( opR == INTOBJ_INT(0) ) {2140opR = ErrorReturnObj(2141"Integer operations: <divisor> must be nonzero",21420L, 0L,2143"you can replace the integer <divisor> via 'return <divisor>;'" );2144return QUO( opL, opR );2145}21462147/* the small int -(1<<28) divided by -1 is the large int (1<<28) */2148if ( opL == INTOBJ_INT(-(Int)(1L<<NR_SMALL_INT_BITS))2149&& opR == INTOBJ_INT(-1) ) {2150quo = NewBag( T_INTPOS, 4*sizeof(TypDigit) );2151ADDR_INT(quo)[1] = 1L<<(NR_SMALL_INT_BITS-NR_DIGIT_BITS);2152ADDR_INT(quo)[0] = 0;2153return quo;2154}21552156/* get the integer values */2157i = INT_INTOBJ(opL);2158k = INT_INTOBJ(opR);21592160/* divide, make sure we divide only positive numbers */2161if ( 0 <= i && 0 <= k ) i = ( i / k );2162else if ( 0 <= i && k < 0 ) i = - ( i / -k );2163else if ( i < 0 && 0 <= k ) i = - ( -i / k );2164else if ( i < 0 && k < 0 ) i = ( -i / -k );2165quo = INTOBJ_INT( i );21662167}21682169/* divide a small integer by a large one */2170else if ( IS_INTOBJ(opL) ) {21712172/* the small int -(1<<28) divided by the large int (1<<28) is -1 */21732174if ( opL == INTOBJ_INT(-(Int)(1L<<NR_SMALL_INT_BITS))2175&& TNUM_OBJ(opR) == T_INTPOS && SIZE_INT(opR) == 42176&& ADDR_INT(opR)[3] == 02177&& ADDR_INT(opR)[2] == 02178&& ADDR_INT(opR)[1] == 1L<<(NR_SMALL_INT_BITS-NR_DIGIT_BITS)2179&& ADDR_INT(opR)[0] == 0 )2180quo = INTOBJ_INT(-1);21812182/* in all other cases the quotient is of course zero */2183else2184quo = INTOBJ_INT(0);21852186}21872188/* divide a large integer by a small integer */2189else if ( IS_INTOBJ(opR)2190&& INT_INTOBJ(opR) < INTBASE2191&& -(Int)INTBASE <= INT_INTOBJ(opR) ) {21922193/* pathological case first */2194if ( opR == INTOBJ_INT(0) ) {2195opR = ErrorReturnObj(2196"Integer operations: <divisor> must be nonzero",21970L, 0L,2198"you can replace the integer <divisor> via 'return <divisor>;'" );2199return QUO( opL, opR );2200}22012202/* get the integer value, make positive */2203i = INT_INTOBJ(opR); if ( i < 0 ) i = -i;22042205/* allocate a bag for the result and set up the pointers */2206if ( (TNUM_OBJ(opL)==T_INTPOS && 0 < INT_INTOBJ(opR))2207|| (TNUM_OBJ(opL)==T_INTNEG && INT_INTOBJ(opR) < 0) )2208quo = NewBag( T_INTPOS, SIZE_OBJ(opL) );2209else2210quo = NewBag( T_INTNEG, SIZE_OBJ(opL) );2211l = ADDR_INT(opL) + SIZE_INT(opL) - 1;2212q = ADDR_INT(quo) + SIZE_INT(quo) - 1;22132214/* run through the left operand and divide digitwise */2215c = 0;2216for ( ; l >= ADDR_INT(opL); l--, q-- ) {2217c = (c<<NR_DIGIT_BITS) + (Int)*l;2218*q = (TypDigit)(c / i);2219c = c - i * *q;2220/*N clever compilers may prefer: c = c % i; */2221}22222223/* remove the leading zeroes, note that there can't be more than 5 */2224q = ADDR_INT(quo) + SIZE_INT(quo);2225if ( q[-4] == 0 && q[-3] == 0 && q[-2] == 0 && q[-1] == 0 ) {2226ResizeBag( quo, (SIZE_INT(quo)-4)*sizeof(TypDigit) );2227}22282229/* reduce to small integer if possible */2230q = ADDR_INT(quo) + SIZE_INT(quo);2231if ( SIZE_INT(quo) == 4 && q[-2] == 0 && q[-1] == 0 ) {2232if ( TNUM_OBJ(quo) == T_INTPOS2233&&(UInt)(INTBASE*q[-3]+q[-4])2234< (1L<<NR_SMALL_INT_BITS))2235quo = INTOBJ_INT( INTBASE*q[-3]+q[-4] );2236else if ( TNUM_OBJ(quo) == T_INTNEG2237&& (UInt)(INTBASE*q[-3]+q[-4])2238<= (1L<<NR_SMALL_INT_BITS) )2239quo = INTOBJ_INT( -(Int)(INTBASE*q[-3]+q[-4]) );2240}22412242}22432244/* divide a large integer by a large integer */2245else {22462247/* a small divisor larger than one digit isn't handled above */2248if ( IS_INTOBJ(opR) ) {2249if ( 0 < INT_INTOBJ(opR) ) {2250quo = NewBag( T_INTPOS, 4*sizeof(TypDigit) );2251ADDR_INT(quo)[0] = (TypDigit)(INT_INTOBJ(opR));2252ADDR_INT(quo)[1] = (TypDigit)(INT_INTOBJ(opR)>>NR_DIGIT_BITS);2253opR = quo;2254}2255else {2256quo = NewBag( T_INTNEG, 4*sizeof(TypDigit) );2257ADDR_INT(quo)[0] = (TypDigit)(-INT_INTOBJ(opR));2258ADDR_INT(quo)[1] = (TypDigit)((-INT_INTOBJ(opR))>>NR_DIGIT_BITS);2259opR = quo;2260}2261}22622263/* trivial case first */2264if ( SIZE_INT(opL) < SIZE_INT(opR) )2265return INTOBJ_INT(0);22662267/* copy the left operand into a new bag, this holds the remainder */2268quo = NewBag( TNUM_OBJ(opL), (SIZE_INT(opL)+4)*sizeof(TypDigit) );2269l = ADDR_INT(opL);2270q = ADDR_INT(quo);2271for ( k = SIZE_INT(opL)-1; k >= 0; k-- )2272*q++ = *l++;2273opL = quo;22742275/* get the size of the right operand, and get the leading 2 digits */2276rs = SIZE_INT(opR);2277r = ADDR_INT(opR);2278while ( r[rs-1] == 0 ) rs--;2279for ( e = 0;2280((Int)r[rs-1]<<e) + (e ? r[rs-2]>>(NR_DIGIT_BITS-e) : 0)2281< INTBASE/2 ; e++ ) ;22822283r1 = ((Int)r[rs-1]<<e) + (e ? r[rs-2]>>(NR_DIGIT_BITS-e) : 0);2284r2 = ((Int)r[rs-2]<<e) + ((e && rs>=3) ? r[rs-3]>>(NR_DIGIT_BITS-e) : 0);22852286/* allocate a bag for the quotient */2287if ( TNUM_OBJ(opL) == TNUM_OBJ(opR) )2288quo = NewBag( T_INTPOS, SIZE_OBJ(opL)-SIZE_OBJ(opR) );2289else2290quo = NewBag( T_INTNEG, SIZE_OBJ(opL)-SIZE_OBJ(opR) );22912292/* run through the digits in the quotient */2293for ( i = SIZE_INT(opL)-SIZE_INT(opR)-1; i >= 0; i-- ) {22942295/* guess the factor */2296l = ADDR_INT(opL) + rs + i;2297l01 = ((INTBASE*l[0]+l[-1])<<e)2298+ (e ? l[-2]>>(NR_DIGIT_BITS-e):0);22992300if ( l01 == 0 ) continue;2301l2 = ((Int)l[-2]<<e) + (( e && rs+i>=3) ? l[-3]>>(NR_DIGIT_BITS-e) : 0);2302if ( ((Int)l[0]<<e)+(e ? l[-1]>>(NR_DIGIT_BITS-e):0) < r1 )2303qi = l01 / r1;2304else qi = INTBASE - 1;2305while ( l01-(Int)qi*r1 < (Int)INTBASE2306&& INTBASE*(l01-(UInt)qi*r1)+l2 < (UInt)qi*r2 )2307qi--;23082309/* l = l - qi * r; */2310d = 0;2311l = ADDR_INT(opL) + i;2312r = ADDR_INT(opR);2313for ( k = 0; k < (Int)rs; ++k, ++l, ++r ) {2314c = *l - (Int)qi * *r - d; *l = c; d = -(TypDigit)(c>>NR_DIGIT_BITS);2315}2316c = (Int)*l - d; d = -(TypDigit)(c>>NR_DIGIT_BITS);23172318/* if we have a borrow then add back */2319if ( d != 0 ) {2320d = 0;2321l = ADDR_INT(opL) + i;2322r = ADDR_INT(opR);2323for ( k = 0; k < (Int)rs; ++k, ++l, ++r ) {2324c = (Int)*l + (Int)*r + (Int)d;2325*l = (TypDigit)c;2326d = (TypDigit)(c>>NR_DIGIT_BITS);2327}2328c = *l + d; d = (TypDigit)(c>>NR_DIGIT_BITS);2329qi--;2330}23312332/* store the digit in the quotient */2333ADDR_INT(quo)[i] = qi;23342335}23362337/* remove the leading zeroes, note that there can't be more than 7 */2338q = ADDR_INT(quo) + SIZE_INT(quo);2339if ( SIZE_INT(quo) > 42340&& q[-4] == 0 && q[-3] == 0 && q[-2] == 0 && q[-1] == 0 ) {2341ResizeBag( quo, (SIZE_INT(quo)-4)*sizeof(TypDigit) );2342}23432344/* reduce to small integer if possible */2345q = ADDR_INT(quo) + SIZE_INT(quo);2346if ( SIZE_INT(quo) == 4 && q[-2] == 0 && q[-1] == 0 ) {2347if ( TNUM_OBJ(quo) == T_INTPOS2348&& (UInt)(INTBASE*q[-3]+q[-4]) < (1L<<NR_SMALL_INT_BITS) )2349quo = INTOBJ_INT( INTBASE*q[-3]+q[-4] );2350else if ( TNUM_OBJ(quo) == T_INTNEG2351&& (UInt)(INTBASE*q[-3]+q[-4]) <= (1L<<NR_SMALL_INT_BITS) )2352quo = INTOBJ_INT( -(Int)(INTBASE*q[-3]+q[-4]) );2353}23542355}23562357/* return the result */2358return quo;2359}236023612362/****************************************************************************2363**2364*F FuncQUO_INT(<self>,<opL>,<opR>) . . . . . . . internal function 'QuoInt'2365**2366** 'FuncQUO_INT' implements the internal function 'QuoInt'.2367**2368** 'QuoInt( <i>, <k> )'2369**2370** 'Quo' returns the integer part of the quotient of its integer operands.2371** If <i> and <k> are positive 'Quo( <i>, <k> )' is the largest positive2372** integer <q> such that '<q> * <k> \<= <i>'. If <i> or <k> or both are2373** negative we define 'Abs( Quo(<i>,<k>) ) = Quo( Abs(<i>), Abs(<k>) )' and2374** 'Sign( Quo(<i>,<k>) ) = Sign(<i>) * Sign(<k>)'. Dividing by 0 causes an2375** error. 'Rem' (see "Rem") can be used to compute the remainder.2376*/2377Obj FuncQUO_INT (2378Obj self,2379Obj opL,2380Obj opR )2381{2382/* check the arguments */2383while ( TNUM_OBJ(opL) != T_INT2384&& TNUM_OBJ(opL) != T_INTPOS2385&& TNUM_OBJ(opL) != T_INTNEG ) {2386opL = ErrorReturnObj(2387"QuoInt: <left> must be an integer (not a %s)",2388(Int)TNAM_OBJ(opL), 0L,2389"you can replace <left> via 'return <left>;'" );2390}2391while ( TNUM_OBJ(opR) != T_INT2392&& TNUM_OBJ(opR) != T_INTPOS2393&& TNUM_OBJ(opR) != T_INTNEG ) {2394opR = ErrorReturnObj(2395"QuoInt: <right> must be an integer (not a %s)",2396(Int)TNAM_OBJ(opR), 0L,2397"you can replace <right> via 'return <right>;'" );2398}23992400/* return the quotient */2401return QuoInt( opL, opR );2402}240324042405/****************************************************************************2406**2407*F RemInt( <intL>, <intR> ) . . . . . . . . . . . remainder of two integers2408**2409** 'RemInt' returns the remainder of the quotient of the integers <intL>2410** and <intR>. 'RemInt' handles operands of type 'T_INT', 'T_INTPOS' and2411** 'T_INTNEG'.2412**2413** Note that the remainder is different from the value returned by the 'mod'2414** operator which is always positive.2415**2416** 'RemInt' is called from 'FunRemInt'.2417*/2418Obj RemInt (2419Obj opL,2420Obj opR )2421{2422Int i; /* loop count, value for small int */2423Int k; /* loop count, value for small int */2424UInt c; /* product of two digits */2425TypDigit d; /* carry into the next digit */2426TypDigit * l; /* pointer into the left operand */2427TypDigit * r; /* pointer into the right operand */2428TypDigit r1; /* leading digit of the right oper */2429TypDigit r2; /* next digit of the right operand */2430UInt rs; /* size of the right operand */2431UInt e; /* we mult r by 2^e so r1 >= 32768 */2432Obj rem; /* handle of the remainder bag */2433TypDigit * m; /* pointer into the remainder */2434UInt m01; /* leading two digits of the rem. */2435TypDigit m2; /* next digit of the remainder */2436TypDigit qi; /* guessed digit of the quotient */24372438/* compute the remainder of two small integers */2439if ( ARE_INTOBJS( opL, opR ) ) {24402441/* pathological case first */2442if ( opR == INTOBJ_INT(0) ) {2443opR = ErrorReturnObj(2444"Integer operations: <divisor> must be nonzero",24450L, 0L,2446"you can replace the integer <divisor> via 'return <divisor>;'" );2447return QUO( opL, opR );2448}24492450/* get the integer values */2451i = INT_INTOBJ(opL);2452k = INT_INTOBJ(opR);24532454/* compute the remainder, make sure we divide only positive numbers*/2455if ( 0 <= i && 0 <= k ) i = ( i % k );2456else if ( 0 <= i && k < 0 ) i = ( i % -k );2457else if ( i < 0 && 0 <= k ) i = - ( -i % k );2458else if ( i < 0 && k < 0 ) i = - ( -i % -k );2459rem = INTOBJ_INT( i );24602461}24622463/* compute the remainder of a small integer by a large integer */2464else if ( IS_INTOBJ(opL) ) {24652466/* the small int -(1<<28) rem the large int (1<<28) is 0 */2467if ( opL == INTOBJ_INT(-(Int)(1L<<NR_SMALL_INT_BITS))2468&& TNUM_OBJ(opR) == T_INTPOS && SIZE_INT(opR) == 42469&& ADDR_INT(opR)[3] == 02470&& ADDR_INT(opR)[2] == 02471&& ADDR_INT(opR)[1] == 1L << (NR_SMALL_INT_BITS-NR_DIGIT_BITS)2472&& ADDR_INT(opR)[0] == 0 )2473rem = INTOBJ_INT(0);24742475/* in all other cases the remainder is equal the left operand */2476else2477rem = opL;24782479}24802481/* compute the remainder of a large integer by a small integer */2482else if ( IS_INTOBJ(opR)2483&& INT_INTOBJ(opR) < INTBASE2484&& -(Int)INTBASE <= INT_INTOBJ(opR) ) {24852486/* pathological case first */2487if ( opR == INTOBJ_INT(0) ) {2488opR = ErrorReturnObj(2489"Integer operations: <divisor> must be nonzero",24900L, 0L,2491"you can replace the integer <divisor> via 'return <divisor>;'" );2492return QUO( opL, opR );2493}24942495/* get the integer value, make positive */2496i = INT_INTOBJ(opR); if ( i < 0 ) i = -i;24972498/* maybe its trivial */2499if ( INTBASE % i == 0 ) {2500c = ADDR_INT(opL)[0] % i;2501}25022503/* otherwise run through the left operand and divide digitwise */2504else {2505l = ADDR_INT(opL) + SIZE_INT(opL) - 1;2506c = 0;2507for ( ; l >= ADDR_INT(opL); l-- ) {2508c = (c<<NR_DIGIT_BITS) + (Int)*l;2509c = c % i;2510}2511}25122513/* now c is the result, it has the same sign as the left operand */2514if ( TNUM_OBJ(opL) == T_INTPOS )2515rem = INTOBJ_INT( c );2516else2517rem = INTOBJ_INT( -(Int)c );25182519}25202521/* compute the remainder of a large integer modulo a large integer */2522else {25232524/* a small divisor larger than one digit isn't handled above */2525if ( IS_INTOBJ(opR) ) {2526if ( 0 < INT_INTOBJ(opR) ) {2527rem = NewBag( T_INTPOS, 4*sizeof(TypDigit) );2528ADDR_INT(rem)[0] = (TypDigit)(INT_INTOBJ(opR));2529ADDR_INT(rem)[1] = (TypDigit)(INT_INTOBJ(opR)>>NR_DIGIT_BITS);2530opR = rem;2531}2532else {2533rem = NewBag( T_INTNEG, 4*sizeof(TypDigit) );2534ADDR_INT(rem)[0] = (TypDigit)(-INT_INTOBJ(opR));2535ADDR_INT(rem)[1] = (TypDigit)((-INT_INTOBJ(opR))>>NR_DIGIT_BITS);2536opR = rem;2537}2538}25392540/* trivial case first */2541if ( SIZE_INT(opL) < SIZE_INT(opR) )2542return opL;25432544/* copy the left operand into a new bag, this holds the remainder */2545rem = NewBag( TNUM_OBJ(opL), (SIZE_INT(opL)+4)*sizeof(TypDigit) );2546l = ADDR_INT(opL);2547m = ADDR_INT(rem);2548for ( k = SIZE_INT(opL)-1; k >= 0; k-- )2549*m++ = *l++;25502551/* get the size of the right operand, and get the leading 2 digits */2552rs = SIZE_INT(opR);2553r = ADDR_INT(opR);2554while ( r[rs-1] == 0 ) rs--;2555for ( e = 0;2556((Int)r[rs-1]<<e) + (e ? r[rs-2]>>(NR_DIGIT_BITS-e): 0)2557< INTBASE/2; e++ ) ;25582559r1 = ((Int)r[rs-1]<<e) + (e ? r[rs-2]>>(NR_DIGIT_BITS-e):0);2560r2 = ((Int)r[rs-2]<<e) + ((e && rs>=3) ? r[rs-3]>>(NR_DIGIT_BITS-e) : 0);25612562/* run through the digits in the quotient */2563for ( i = SIZE_INT(rem)-SIZE_INT(opR)-1; i >= 0; i-- ) {25642565/* guess the factor */2566m = ADDR_INT(rem) + rs + i;2567m01 = ((INTBASE*m[0]+m[-1])<<e) + (e ? m[-2]>>(NR_DIGIT_BITS-e):0);2568if ( m01 == 0 ) continue;2569m2 = ((Int)m[-2]<<e) + ((e && rs+i>=3) ? m[-3]>>(NR_DIGIT_BITS-e) : 0);2570if ( ((Int)m[0]<<e)+(e ? m[-1]>>(NR_DIGIT_BITS-e): 0) < r1 )2571qi = m01 / r1;2572else qi = INTBASE - 1;2573while ( m01-(Int)qi*r1 < (Int)INTBASE2574&& INTBASE*(m01-(Int)qi*r1)+m2 < (Int)qi*r2 )2575qi--;25762577/* m = m - qi * r; */2578d = 0;2579m = ADDR_INT(rem) + i;2580r = ADDR_INT(opR);2581for ( k = 0; k < (Int)rs; ++k, ++m, ++r ) {2582c = (Int)*m - (Int)qi * *r - (Int)d;2583*m = (TypDigit)c;2584d = -(TypDigit)(c>>NR_DIGIT_BITS);2585}2586c = (Int)*m - d; *m = (TypDigit)c; d = -(TypDigit)(c>>NR_DIGIT_BITS);25872588/* if we have a borrow then add back */2589if ( d != 0 ) {2590d = 0;2591m = ADDR_INT(rem) + i;2592r = ADDR_INT(opR);2593for ( k = 0; k < (Int)rs; ++k, ++m, ++r ) {2594c = (Int)*m + (Int)*r + (Int)d;2595*m = (TypDigit)c;2596d = (TypDigit)(c>>NR_DIGIT_BITS);2597}2598c = (Int)*m + d; *m = (TypDigit)c; d = (TypDigit)(c>>NR_DIGIT_BITS);2599qi--;2600}26012602}26032604/* remove the leading zeroes */2605m = ADDR_INT(rem) + SIZE_INT(rem);2606if ( (m[-4] == 0 && m[-3] == 0 && m[-2] == 0 && m[-1] == 0)2607|| (SIZE_INT(rem) == 4 && m[-2] == 0 && m[-1] == 0) ) {26082609/* find the number of significant digits */2610m = ADDR_INT(rem);2611for ( k = SIZE_INT(rem); k != 0; k-- ) {2612if ( m[k-1] != 0 )2613break;2614}26152616/* reduce to small integer if possible, otherwise shrink bag */2617if ( k <= 2 && TNUM_OBJ(rem) == T_INTPOS2618&& (UInt)(INTBASE*m[1]+m[0]) < (1L<<NR_SMALL_INT_BITS) )2619rem = INTOBJ_INT( INTBASE*m[1]+m[0] );2620else if ( k <= 2 && TNUM_OBJ(rem) == T_INTNEG2621&& (UInt)(INTBASE*m[1]+m[0]) <= (1L<<NR_SMALL_INT_BITS) )2622rem = INTOBJ_INT( -(Int)(INTBASE*m[1]+m[0]) );2623else2624ResizeBag( rem, (((k + 3) / 4) * 4) * sizeof(TypDigit) );2625}26262627}26282629/* return the result */2630return rem;2631}263226332634/****************************************************************************2635**2636*F FuncREM_INT(<self>,<opL>,<opR>) . . . . . . . internal function 'RemInt'2637**2638** 'FuncREM_INT' implements the internal function 'RemInt'.2639**2640** 'RemInt( <i>, <k> )'2641**2642** 'Rem' returns the remainder of its two integer operands, i.e., if <k> is2643** not equal to zero 'Rem( <i>, <k> ) = <i> - <k> * Quo( <i>, <k> )'. Note2644** that the rules given for 'Quo' (see "Quo") imply that 'Rem( <i>, <k> )'2645** has the same sign as <i> and its absolute value is strictly less than the2646** absolute value of <k>. Dividing by 0 causes an error.2647*/2648Obj FuncREM_INT (2649Obj self,2650Obj opL,2651Obj opR )2652{2653/* check the arguments */2654while ( TNUM_OBJ(opL) != T_INT2655&& TNUM_OBJ(opL) != T_INTPOS2656&& TNUM_OBJ(opL) != T_INTNEG ) {2657opL = ErrorReturnObj(2658"RemInt: <left> must be an integer (not a %s)",2659(Int)TNAM_OBJ(opL), 0L,2660"you can replace <left> via 'return <left>;'" );2661}2662while ( TNUM_OBJ(opR) != T_INT2663&& TNUM_OBJ(opR) != T_INTPOS2664&& TNUM_OBJ(opR) != T_INTNEG ) {2665opR = ErrorReturnObj(2666"RemInt: <right> must be an integer (not a %s)",2667(Int)TNAM_OBJ(opR), 0L,2668"you can replace <right> via 'return <right>;'" );2669}26702671/* return the remainder */2672return RemInt( opL, opR );2673}267426752676/****************************************************************************2677**2678*F GcdInt( <opL>, <opR> ) . . . . . . . . . . . . . . . gcd of two integers2679**2680** 'GcdInt' returns the gcd of the two integers <opL> and <opR>.2681**2682** It is called from 'FunGcdInt' and the rational package.2683*/2684Obj GcdInt (2685Obj opL,2686Obj opR )2687{2688Int i; /* loop count, value for small int */2689Int k; /* loop count, value for small int */2690UInt c; /* product of two digits */2691TypDigit d; /* carry into the next digit */2692TypDigit * r; /* pointer into the right operand */2693TypDigit r1; /* leading digit of the right oper */2694TypDigit r2; /* next digit of the right operand */2695UInt rs; /* size of the right operand */2696UInt e; /* we mult r by 2^e so r1 >= 32768 */2697TypDigit * l; /* pointer into the left operand */2698UInt l01; /* leading two digits of the rem. */2699TypDigit l2; /* next digit of the remainder */2700UInt ls; /* size of the left operand */2701TypDigit qi; /* guessed digit of the quotient */2702Obj gcd; /* handle of the result */27032704/* compute the gcd of two small integers */2705if ( ARE_INTOBJS( opL, opR ) ) {27062707/* get the integer values, make them positive */2708i = INT_INTOBJ(opL); if ( i < 0 ) i = -i;2709k = INT_INTOBJ(opR); if ( k < 0 ) k = -k;27102711/* compute the gcd using Euclids algorithm */2712while ( k != 0 ) {2713c = k;2714k = i % k;2715i = c;2716}27172718/* now i is the result */2719if ( i == (1L<<NR_SMALL_INT_BITS) ) {2720gcd = NewBag( T_INTPOS, 4*sizeof(TypDigit) );2721ADDR_INT(gcd)[0] = (TypDigit)i;2722ADDR_INT(gcd)[1] = (TypDigit)(i>>NR_DIGIT_BITS);2723}2724else {2725gcd = INTOBJ_INT( i );2726}27272728}27292730/* compute the gcd of a small and a large integer */2731else if ( (IS_INTOBJ(opL)2732&& INT_INTOBJ(opL) < INTBASE && -(Int)INTBASE <= INT_INTOBJ(opL))2733|| (IS_INTOBJ(opR)2734&& INT_INTOBJ(opR) < INTBASE && -(Int)INTBASE <= INT_INTOBJ(opR)) ) {27352736/* make the right operand the small one */2737if ( IS_INTOBJ(opL) ) {2738gcd = opL; opL = opR; opR = gcd;2739}27402741/* maybe it's trivial */2742if ( opR == INTOBJ_INT(0) ) {2743if( TNUM_OBJ( opL ) == T_INTNEG ) {2744/* If opL is negative, change the sign. We do this by */2745/* copying opL into a bag of type T_INTPOS. Note that */2746/* opL is a large negative number, so it cannot be the */2747/* the negative of 1 << NR_SMALL_INT_BITS. */2748gcd = NewBag( T_INTPOS, SIZE_OBJ(opL) );2749l = ADDR_INT(opL); r = ADDR_INT(gcd);2750for ( k = SIZE_INT(opL); k != 0; k-- ) *r++ = *l++;27512752return gcd;2753}2754else return opL;2755}27562757/* get the right operand value, make it positive */2758i = INT_INTOBJ(opR); if ( i < 0 ) i = -i;27592760/* do one remainder operation */2761l = ADDR_INT(opL) + SIZE_INT(opL) - 1;2762c = 0;2763for ( ; l >= ADDR_INT(opL); l-- ) {2764c = (c<<NR_DIGIT_BITS) + (Int)*l;2765c = c % i;2766}2767k = c;27682769/* compute the gcd using Euclids algorithm */2770while ( k != 0 ) {2771c = k;2772k = i % k;2773i = c;2774}27752776/* now i is the result */2777if ( i == (1L<<NR_SMALL_INT_BITS) ) {2778gcd = NewBag( T_INTPOS, 4*sizeof(TypDigit) );2779ADDR_INT(gcd)[0] = 0;2780ADDR_INT(gcd)[1] = 1L<<(NR_SMALL_INT_BITS-NR_DIGIT_BITS);2781}2782else {2783gcd = INTOBJ_INT( i );2784}27852786}27872788/* compute the gcd of two large integers */2789else {27902791/* a small divisor larger than one digit isn't handled above */2792if ( IS_INTOBJ(opL) ) {2793if ( 0 < INT_INTOBJ(opL) ) {2794gcd = NewBag( T_INTPOS, 4*sizeof(TypDigit) );2795ADDR_INT(gcd)[0] = (TypDigit)(INT_INTOBJ(opL));2796ADDR_INT(gcd)[1] = (TypDigit)(INT_INTOBJ(opL)>>NR_DIGIT_BITS);2797opL = gcd;2798}2799else {2800gcd = NewBag( T_INTNEG, 4*sizeof(TypDigit) );2801ADDR_INT(gcd)[0] = (TypDigit)(-INT_INTOBJ(opL));2802ADDR_INT(gcd)[1] = (TypDigit)((-INT_INTOBJ(opL))>>NR_DIGIT_BITS);2803opL = gcd;2804}2805}28062807/* a small dividend larger than one digit isn't handled above */2808if ( IS_INTOBJ(opR) ) {2809if ( 0 < INT_INTOBJ(opR) ) {2810gcd = NewBag( T_INTPOS, 4*sizeof(TypDigit) );2811ADDR_INT(gcd)[0] = (TypDigit)(INT_INTOBJ(opR));2812ADDR_INT(gcd)[1] = (TypDigit)(INT_INTOBJ(opR)>>NR_DIGIT_BITS);2813opR = gcd;2814}2815else {2816gcd = NewBag( T_INTNEG, 4*sizeof(TypDigit) );2817ADDR_INT(gcd)[0] = (TypDigit)(-INT_INTOBJ(opR));2818ADDR_INT(gcd)[1] = (TypDigit)((-INT_INTOBJ(opR))>>NR_DIGIT_BITS);2819opR = gcd;2820}2821}28222823/* copy the left operand into a new bag */2824gcd = NewBag( T_INTPOS, (SIZE_INT(opL)+4)*sizeof(TypDigit) );2825l = ADDR_INT(opL);2826r = ADDR_INT(gcd);2827for ( k = SIZE_INT(opL)-1; k >= 0; k-- )2828*r++ = *l++;2829opL = gcd;28302831/* get the size of the left operand */2832ls = SIZE_INT(opL);2833l = ADDR_INT(opL);2834while ( ls >= 1 && l[ls-1] == 0 ) ls--;28352836/* copy the right operand into a new bag */2837gcd = NewBag( T_INTPOS, (SIZE_INT(opR)+4)*sizeof(TypDigit) );2838r = ADDR_INT(opR);2839l = ADDR_INT(gcd);2840for ( k = SIZE_INT(opR)-1; k >= 0; k-- )2841*l++ = *r++;2842opR = gcd;28432844/* get the size of the right operand */2845rs = SIZE_INT(opR);2846r = ADDR_INT(opR);2847while ( rs >= 1 && r[rs-1] == 0 ) rs--;28482849/* repeat while the right operand is large */2850while ( rs >= 2 ) {28512852/* get the leading two digits */2853for ( e = 0;2854((Int)r[rs-1]<<e) + (e ? r[rs-2]>>(NR_DIGIT_BITS-e) : 0)2855< INTBASE/2; e++ ) ;2856r1 = ((Int)r[rs-1]<<e) + (e ? r[rs-2]>>(NR_DIGIT_BITS-e): 0);2857r2 = ((Int)r[rs-2]<<e) + ((e && rs>=3) ? r[rs-3]>>(NR_DIGIT_BITS-e) : 0);28582859/* run through the digits in the quotient */2860for ( i = ls - rs; i >= 0; i-- ) {28612862/* guess the factor */2863l = ADDR_INT(opL) + rs + i;2864l01 = ((INTBASE*l[0]+l[-1])<<e) + (e ? l[-2]>>(NR_DIGIT_BITS-e):0);2865if ( l01 == 0 ) continue;2866l2 = ((Int)l[-2]<<e) + ((e && rs+i>=3) ? l[-3]>>(NR_DIGIT_BITS-e):0);2867if ( ((Int)l[0]<<e)+(e ? l[-1]>>(NR_DIGIT_BITS-e):0) < r1 )2868qi = l01 / r1;2869else qi = INTBASE - 1;2870while ( l01-(Int)qi*r1 < (Int)INTBASE2871&& (INTBASE*(l01-(Int)qi*r1)+l2) < ((Int)qi*r2) )2872qi--;28732874/* l = l - qi * r; */2875d = 0;2876l = ADDR_INT(opL) + i;2877r = ADDR_INT(opR);2878for ( k = 0; k < (Int)rs; ++k, ++l, ++r ) {2879c = (Int)*l - (Int)qi * *r - (Int)d;2880*l = (TypDigit)c;2881d = -(TypDigit)(c>>NR_DIGIT_BITS);2882}2883c = (Int)*l - d; *l = (TypDigit)c; d = -(TypDigit)(c>>NR_DIGIT_BITS);28842885/* if we have a borrow then add back */2886if ( d != 0 ) {2887d = 0;2888l = ADDR_INT(opL) + i;2889r = ADDR_INT(opR);2890for ( k = 0; k < (Int)rs; ++k, ++l, ++r ) {2891c = (Int)*l + (Int)*r + (Int)d;2892*l = (TypDigit)c;2893d = (TypDigit)(c>>NR_DIGIT_BITS);2894}2895c = *l + d; *l = (TypDigit)c; d = (TypDigit)(c>>NR_DIGIT_BITS);2896qi--;2897}2898}28992900/* exchange the two operands */2901gcd = opL; opL = opR; opR = gcd;2902ls = rs;29032904/* get the size of the right operand */2905rs = SIZE_INT(opR);2906r = ADDR_INT(opR);2907while ( rs >= 1 && r[rs-1] == 0 ) rs--;29082909}29102911/* if the right operand is zero now, the left is the gcd */2912if ( rs == 0 ) {29132914/* remove the leading zeroes */2915l = ADDR_INT(opL) + SIZE_INT(opL);2916if ( (l[-4] == 0 && l[-3] == 0 && l[-2] == 0 && l[-1] == 0)2917|| (SIZE_INT(opL) == 4 && l[-2] == 0 && l[-1] == 0) ) {29182919/* find the number of significant digits */2920l = ADDR_INT(opL);2921for ( k = SIZE_INT(opL); k != 0; k-- ) {2922if ( l[k-1] != 0 )2923break;2924}29252926/* reduce to small integer if possible, otherwise shrink b */2927if ( k <= 2 && TNUM_OBJ(opL) == T_INTPOS2928&& (UInt)(INTBASE*l[1]+l[0]) < (1L<<NR_SMALL_INT_BITS) )2929opL = INTOBJ_INT( INTBASE*l[1]+l[0] );2930else if ( k <= 2 && TNUM_OBJ(opL) == T_INTNEG2931&& (UInt)(INTBASE*l[1]+l[0]) <= (1L<<NR_SMALL_INT_BITS) )2932opL = INTOBJ_INT( -(Int)(INTBASE*l[1]+l[0]) );2933else2934ResizeBag( opL, (((k + 3) / 4) * 4) * sizeof(TypDigit) );2935}29362937gcd = opL;29382939}29402941/* otherwise handle one large and one small integer as above */2942else {29432944/* get the right operand value, make it positive */2945i = r[0];29462947/* do one remainder operation */2948l = ADDR_INT(opL) + SIZE_INT(opL) - 1;2949c = 0;2950for ( ; l >= ADDR_INT(opL); l-- ) {2951c = (c<<NR_DIGIT_BITS) + (Int)*l;2952c = c % i;2953}2954k = c;29552956/* compute the gcd using Euclids algorithm */2957while ( k != 0 ) {2958c = k;2959k = i % k;2960i = c;2961}29622963/* now i is the result */2964if ( i == (1L<<NR_SMALL_INT_BITS) ) {2965gcd = NewBag( T_INTPOS, 4*sizeof(TypDigit) );2966ADDR_INT(gcd)[0] = 0;2967ADDR_INT(gcd)[1] = 1L<<(NR_SMALL_INT_BITS-NR_DIGIT_BITS);2968}2969else {2970gcd = INTOBJ_INT( i );2971}29722973}29742975}29762977/* return the result */2978return gcd;2979}298029812982/****************************************************************************2983**2984*F FuncGCD_INT(<self>,<opL>,<opR>) . . . . . . . internal function 'GcdInt'2985**2986** 'FuncGCD_INT' implements the internal function 'GcdInt'.2987**2988** 'GcdInt( <i>, <k> )'2989**2990** 'Gcd' returns the greatest common divisor of the two integers <m> and2991** <n>, i.e., the greatest integer that divides both <m> and <n>. The2992** greatest common divisor is never negative, even if the arguments are. We2993** define $gcd( m, 0 ) = gcd( 0, m ) = abs( m )$ and $gcd( 0, 0 ) = 0$.2994*/2995Obj FuncGCD_INT (2996Obj self,2997Obj opL,2998Obj opR )2999{3000/* check the arguments */3001while ( TNUM_OBJ(opL) != T_INT3002&& TNUM_OBJ(opL) != T_INTPOS3003&& TNUM_OBJ(opL) != T_INTNEG ) {3004opL = ErrorReturnObj(3005"GcdInt: <left> must be an integer (not a %s)",3006(Int)TNAM_OBJ(opL), 0L,3007"you can replace <left> via 'return <left>;'" );3008}3009while ( TNUM_OBJ(opR) != T_INT3010&& TNUM_OBJ(opR) != T_INTPOS3011&& TNUM_OBJ(opR) != T_INTNEG ) {3012opR = ErrorReturnObj(3013"GcdInt: <right> must be an integer (not a %s)",3014(Int)TNAM_OBJ(opR), 0L,3015"you can replace <right> via 'return <right>;'" );3016}30173018/* return the gcd */3019return GcdInt( opL, opR );3020}3021302230233024302530263027/****************************************************************************3028**3029*F SaveInt( <int> )3030**3031** Since the type is saved, we don't need to worry about sign3032*/30333034void SaveInt( Obj bigint)3035{3036TypDigit *ptr;3037UInt i;3038ptr = (TypDigit *)ADDR_OBJ(bigint);3039for (i = 0; i < SIZE_INT(bigint); i++)3040#ifdef SYS_IS_64_BIT3041SaveUInt4(*ptr++);3042#else3043SaveUInt2(*ptr++);3044#endif3045return;3046}30473048/****************************************************************************3049**3050*F LoadInt( <int> )3051**3052** Since the type is loaded, we don't need to worry about sign3053*/30543055void LoadInt( Obj bigint)3056{3057TypDigit *ptr;3058UInt i;3059ptr = (TypDigit *)ADDR_OBJ(bigint);3060for (i = 0; i < SIZE_INT(bigint); i++)3061#ifdef SYS_IS_64_BIT3062*ptr++ = LoadUInt4();3063#else3064*ptr++ = LoadUInt2();3065#endif3066return;3067}306830693070/****************************************************************************3071**3072** * * * * * * * "Mersenne twister" random numbers * * * * * * * * * * * * *3073**3074** Part of this code for fast generation of 32 bit pseudo random numbers with3075** a period of length 2^19937-1 and a 623-dimensional equidistribution is3076** taken from:3077** http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html3078** (Also look in Wikipedia for "Mersenne twister".)3079** We use the file mt19937ar.c, version 2002/1/26.3080*/3081308230833084/****************************************************************************3085**3086*F RandomIntegerMT( <mtstr>, <nrbits> )3087**3088** Returns an integer with at most <nrbits> bits in uniform distribution.3089** <nrbits> must be a small integer. <mtstr> is a string as returned by3090** InitRandomMT.3091**3092** Implementation details are a bit tricky to obtain the same random3093** integers on 32 bit and 64 bit machines (which have different long3094** integer digit lengths and different ranges of small integers).3095**3096*/3097/* for comparison in case result is small int */3098Obj SMALLEST_INTPOS = NULL;30993100Obj FuncRandomIntegerMT(Obj self, Obj mtstr, Obj nrbits)3101{3102Obj res;3103Int i, n, q, r, qoff, len, nlen;3104UInt4 *mt, rand;3105TypDigit *pt;3106while (! IsStringConv(mtstr)) {3107mtstr = ErrorReturnObj(3108"<mtstr> must be a string, not a %s)",3109(Int)TNAM_OBJ(mtstr), 0L,3110"you can replace <mtstr> via 'return <mtstr>;'" );3111}3112while ((! IsStringConv(mtstr)) || GET_LEN_STRING(mtstr) < 2500) {3113mtstr = ErrorReturnObj(3114"<mtstr> must be a string with at least 2500 characters, ",31150L, 0L,3116"you can replace <mtstr> via 'return <mtstr>;'" );3117}3118while ((! IS_INTOBJ(nrbits)) || INT_INTOBJ(nrbits) < 0) {3119nrbits = ErrorReturnObj(3120"<nrbits> must be a small non-negative integer, not a %s)",3121(Int)TNAM_OBJ(nrbits), 0L,3122"you can replace <mtstr> via 'return <mtstr>;'" );3123}3124n = INT_INTOBJ(nrbits);31253126/* small int case */3127if (n <= NR_SMALL_INT_BITS) {3128mt = (UInt4*) CHARS_STRING(mtstr);3129#ifdef SYS_IS_64_BIT3130if (n <= 32) {3131res = INTOBJ_INT((Int)(nextrandMT_int32(mt) & ((UInt4) -1L >> (32-n))));3132}3133else {3134unsigned long rd;3135rd = nextrandMT_int32(mt);3136rd += (unsigned long) ((UInt4) nextrandMT_int32(mt) &3137((UInt4) -1L >> (64-n))) << 32;3138res = INTOBJ_INT((Int)rd);3139}3140#else3141res = INTOBJ_INT((Int)(nextrandMT_int32(mt) & ((UInt4) -1L >> (32-n))));3142#endif3143}3144else {3145/* number of Digits */3146q = n / NR_DIGIT_BITS;3147r = n - q*NR_DIGIT_BITS;3148qoff = q + (r==0 ? 0:1);3149len = qoff;3150len = 4*((len+3) / 4);3151res = NewBag( T_INTPOS, len*sizeof(TypDigit) );3152pt = ADDR_INT(res);3153mt = (UInt4*) CHARS_STRING(mtstr);3154#ifdef SYS_IS_64_BIT3155for (i = 0; i < qoff; i++, pt++) {3156rand = (TypDigit) nextrandMT_int32(mt);3157*pt = rand;3158}3159#else3160for (i = 0; i < qoff/2; i++, pt++) {3161rand = nextrandMT_int32(mt);3162*pt = (TypDigit) (rand & 0xFFFFL);3163pt++;3164*pt = (TypDigit) ((rand & 0xFFFF0000L) >> 16);3165}3166if (2*i != qoff) {3167rand = nextrandMT_int32(mt);3168*pt = (TypDigit) (rand & 0xFFFFL);3169}3170#endif3171if (r != 0) {3172ADDR_INT(res)[qoff-1] = ADDR_INT(res)[qoff-1] & ((TypDigit)(-1)3173>> (NR_DIGIT_BITS-r));3174}3175/* shrink bag if necessary */3176for (nlen = len, i=0; nlen >0 && ADDR_INT(res)[nlen-1] == 0L;3177nlen--, i++);3178if (i/4 != 0) {3179ResizeBag(res, 4*((nlen+3) / 4)*sizeof(TypDigit));3180}3181/* convert result if small int */3182if (LtInt(res, SMALLEST_INTPOS)) {3183res = INTOBJ_INT((Int)(ADDR_INT(res)[0] +3184((UInt)ADDR_INT(res)[1] << NR_DIGIT_BITS)));3185}3186}31873188return res;3189}3190319131923193/****************************************************************************3194**3195*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *3196*/31973198/****************************************************************************3199**3200*V GVarFilts . . . . . . . . . . . . . . . . . . . list of filters to export3201*/3202static StructGVarFilt GVarFilts [] = {32033204{ "IS_INT", "obj", &IsIntFilt,3205FuncIS_INT, "src/integer.c:IS_INT" },32063207{ 0 }32083209};321032113212/****************************************************************************3213**3214*V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export3215*/3216static StructGVarFunc GVarFuncs [] = {32173218{ "QUO_INT", 2, "int1, int2",3219FuncQUO_INT, "src/integer.c:QUO_INT" },32203221{ "REM_INT", 2, "int1, int2",3222FuncREM_INT, "src/integer.c:REM_INT" },32233224{ "GCD_INT", 2, "int1, int2",3225FuncGCD_INT, "src/integer.c:GCD_INT" },32263227{ "PROD_INT_OBJ", 2, "int, obj",3228FuncPROD_INT_OBJ, "src/integer.c:PROD_INT_OBJ" },32293230{ "POW_OBJ_INT", 2, "obj, int",3231FuncPOW_OBJ_INT, "src/integer.c:POW_OBJ_INT" },32323233{ "HexStringInt", 1, "integer",3234FuncHexStringInt, "src/integer.c:HexStringInt" },32353236{ "IntHexString", 1, "string",3237FuncIntHexString, "src/integer.c:IntHexString" },32383239{ "Log2Int", 1, "int",3240FuncLog2Int, "src/integer.c:Log2Int" },32413242{ "STRING_INT", 1, "int",3243FuncSTRING_INT, "src/integer.c:STRING_INT" },324432453246{ "RandomIntegerMT", 2, "mtstr, nrbits",3247FuncRandomIntegerMT, "src/integer.c:RandomIntegerMT" },324832493250{ 0 }32513252};325332543255/****************************************************************************3256**3257*F InitKernel( <module> ) . . . . . . . . initialise kernel data structures3258*/3259static Int InitKernel (3260StructInitInfo * module )3261{3262UInt t1, t2;32633264/* init filters and functions */3265InitHdlrFiltsFromTable( GVarFilts );3266InitHdlrFuncsFromTable( GVarFuncs );32673268/* install the marking functions */3269InfoBags[ T_INT ].name = "integer";3270#ifdef SYS_IS_64_BIT3271InfoBags[ T_INTPOS ].name = "integer (>= 2^60)";3272InfoBags[ T_INTNEG ].name = "integer (< -2^60)";3273#else3274InfoBags[ T_INTPOS ].name = "integer (>= 2^28)";3275InfoBags[ T_INTNEG ].name = "integer (< -2^28)";3276#endif3277InitMarkFuncBags( T_INTPOS, MarkNoSubBags );3278InitMarkFuncBags( T_INTNEG, MarkNoSubBags );32793280/* Install the saving methods */3281SaveObjFuncs [ T_INTPOS ] = SaveInt;3282SaveObjFuncs [ T_INTNEG ] = SaveInt;3283LoadObjFuncs [ T_INTPOS ] = LoadInt;3284LoadObjFuncs [ T_INTNEG ] = LoadInt;32853286/* install the printing function */3287PrintObjFuncs[ T_INT ] = PrintInt;3288PrintObjFuncs[ T_INTPOS ] = PrintInt;3289PrintObjFuncs[ T_INTNEG ] = PrintInt;32903291/* install the comparison methods */3292for ( t1 = T_INT; t1 <= T_INTNEG; t1++ ) {3293for ( t2 = T_INT; t2 <= T_INTNEG; t2++ ) {3294EqFuncs [ t1 ][ t2 ] = EqInt;3295LtFuncs [ t1 ][ t2 ] = LtInt;3296}3297}32983299/* install the unary arithmetic methods */3300for ( t1 = T_INT; t1 <= T_INTNEG; t1++ ) {3301ZeroFuncs[ t1 ] = ZeroInt;3302ZeroMutFuncs[ t1 ] = ZeroInt;3303AInvFuncs[ t1 ] = AInvInt;3304AInvMutFuncs[ t1 ] = AInvInt;3305OneFuncs [ t1 ] = OneInt;3306OneMutFuncs [ t1 ] = OneInt;3307}33083309/* install the default product and power methods */3310for ( t1 = T_INT; t1 <= T_INTNEG; t1++ ) {3311for ( t2 = FIRST_CONSTANT_TNUM; t2 <= LAST_CONSTANT_TNUM; t2++ ) {3312ProdFuncs[ t1 ][ t2 ] = ProdIntObj;3313PowFuncs [ t2 ][ t1 ] = PowObjInt;3314}3315for ( t2 = FIRST_RECORD_TNUM; t2 <= LAST_RECORD_TNUM; t2++ ) {3316ProdFuncs[ t1 ][ t2 ] = ProdIntObj;3317PowFuncs [ t2 ][ t1 ] = PowObjInt;3318}3319for ( t2 = FIRST_LIST_TNUM; t2 <= LAST_LIST_TNUM; t2++ ) {3320ProdFuncs[ t1 ][ t2 ] = ProdIntObj;3321PowFuncs [ t2 ][ t1 ] = PowObjInt;3322}3323}33243325/* install the binary arithmetic methods */3326for ( t1 = T_INT; t1 <= T_INTNEG; t1++ ) {3327for ( t2 = T_INT; t2 <= T_INTNEG; t2++ ) {3328EqFuncs [ t1 ][ t2 ] = EqInt;3329LtFuncs [ t1 ][ t2 ] = LtInt;3330SumFuncs [ t1 ][ t2 ] = SumInt;3331DiffFuncs[ t1 ][ t2 ] = DiffInt;3332ProdFuncs[ t1 ][ t2 ] = ProdInt;3333PowFuncs [ t1 ][ t2 ] = PowInt;3334ModFuncs [ t1 ][ t2 ] = ModInt;3335}3336}33373338/* gvars to import from the library */3339ImportGVarFromLibrary( "TYPE_INT_SMALL_ZERO", &TYPE_INT_SMALL_ZERO );3340ImportGVarFromLibrary( "TYPE_INT_SMALL_POS", &TYPE_INT_SMALL_POS );3341ImportGVarFromLibrary( "TYPE_INT_SMALL_NEG", &TYPE_INT_SMALL_NEG );3342ImportGVarFromLibrary( "TYPE_INT_LARGE_POS", &TYPE_INT_LARGE_POS );3343ImportGVarFromLibrary( "TYPE_INT_LARGE_NEG", &TYPE_INT_LARGE_NEG );3344ImportGVarFromLibrary( "SMALLEST_INTPOS", &SMALLEST_INTPOS );33453346ImportFuncFromLibrary( "String", &String );3347ImportFuncFromLibrary( "One", &OneAttr);33483349/* install the type functions */3350TypeObjFuncs[ T_INT ] = TypeIntSmall;3351TypeObjFuncs[ T_INTPOS ] = TypeIntLargePos;3352TypeObjFuncs[ T_INTNEG ] = TypeIntLargeNeg;33533354MakeBagTypePublic( T_INTPOS );3355MakeBagTypePublic( T_INTNEG );33563357/* return success */3358return 0;3359}336033613362/****************************************************************************3363**3364*F InitLibrary( <module> ) . . . . . . . initialise library data structures3365*/3366static Int InitLibrary (3367StructInitInfo * module )3368{3369UInt gvar;3370/* init filters and functions */3371InitGVarFiltsFromTable( GVarFilts );3372InitGVarFuncsFromTable( GVarFuncs );33733374/* hold smallest large integer */3375SMALLEST_INTPOS = NewBag( T_INTPOS, 4*sizeof(TypDigit) );3376ADDR_INT(SMALLEST_INTPOS)[1] =3377(TypDigit) (1L << (NR_SMALL_INT_BITS - NR_DIGIT_BITS));3378gvar = GVarName("SMALLEST_INTPOS");3379MakeReadWriteGVar( gvar);3380AssGVar( gvar, SMALLEST_INTPOS );3381MakeReadOnlyGVar(gvar);33823383/* return success */3384return 0;3385}338633873388/****************************************************************************3389**3390*F InitInfoInt() . . . . . . . . . . . . . . . . . . table of init functions3391*/3392static StructInitInfo module = {3393MODULE_BUILTIN, /* type */3394"integer", /* name */33950, /* revision entry of c file */33960, /* revision entry of h file */33970, /* version */33980, /* crc */3399InitKernel, /* initKernel */3400InitLibrary, /* initLibrary */34010, /* checkInit */34020, /* preSave */34030, /* postSave */34040 /* postRestore */3405};34063407StructInitInfo * InitInfoInt ( void )3408{3409return &module;3410}34113412/* matches the USE_GMP test at the top of the file */3413#endif34143415/****************************************************************************3416**3417*E integer.c . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here3418*/341934203421