[BACK]Return to level0.h CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari / src / kernel / none

Annotation of OpenXM_contrib/pari/src/kernel/none/level0.h, Revision 1.1.1.1

1.1       maekawa     1: /* $Id: level0.h,v 1.1.1.1 1999/09/16 13:47:55 karim Exp $ */
                      2:
                      3: /* This file defines some "level 0" kernel functions                 */
                      4: /* These functions can be inline, with gcc                           */
                      5: /* If not gcc, they are defined externally with "level0.c"           */
                      6: /* NB: Those functions are not defined in mp.s                       */
                      7:
                      8: /* level0.c includes this file and never needs to be changed         */
                      9: /* The following seven lines are necessary for level0.c and level1.c */
                     10: #ifdef  LEVEL0
                     11: #undef  INLINE
                     12: #define INLINE
                     13: #endif
                     14: #ifdef  LEVEL1
                     15: #undef  INLINE
                     16: #endif
                     17:
                     18: #define LOCAL_OVERFLOW
                     19: #define SAVE_OVERFLOW
                     20: #define LOCAL_HIREMAINDER
                     21: #define SAVE_HIREMAINDER
                     22:
                     23: #ifndef INLINE
                     24:     BEGINEXTERN
                     25:     extern  ulong overflow;
                     26:     extern  ulong hiremainder;
                     27:     extern long addll(ulong x, ulong y);
                     28:     extern long addllx(ulong x, ulong y);
                     29:     extern long subll(ulong x, ulong y);
                     30:     extern long subllx(ulong x, ulong y);
                     31:     extern long shiftl(ulong x, ulong y);
                     32:     extern long shiftlr(ulong x, ulong y);
                     33:     extern long mulll(ulong x, ulong y);
                     34:     extern long addmul(ulong x, ulong y);
                     35:     extern long divll(ulong x, ulong y);
                     36:     extern int  bfffo(ulong x);
                     37:     ENDEXTERN
                     38:
                     39: #else
                     40:
                     41: ulong overflow;
                     42: ulong hiremainder;
                     43:
                     44: INLINE long
                     45: addll(ulong x, ulong y)
                     46: {
                     47:   const ulong z = x+y;
                     48:   overflow=(z<x);
                     49:   return (long) z;
                     50: }
                     51:
                     52: INLINE long
                     53: addllx(ulong x, ulong y)
                     54: {
                     55:   const ulong z = x+y+overflow;
                     56:   overflow = (z<x || (z==x && overflow));
                     57:   return (long) z;
                     58: }
                     59:
                     60: INLINE long
                     61: subll(ulong x, ulong y)
                     62: {
                     63:   const ulong z = x-y;
                     64:   overflow = (z>x);
                     65:   return (long) z;
                     66: }
                     67:
                     68: INLINE long
                     69: subllx(ulong x, ulong y)
                     70: {
                     71:   const ulong z = x-y-overflow;
                     72:   overflow = (z>x || (z==x && overflow));
                     73:   return (long) z;
                     74: }
                     75:
                     76: INLINE long
                     77: shiftl(ulong x, ulong y)
                     78: {
                     79:   hiremainder=x>>(BITS_IN_LONG-y);
                     80:   return (x<<y);
                     81: }
                     82:
                     83: INLINE long
                     84: shiftlr(ulong x, ulong y)
                     85: {
                     86:   hiremainder=x<<(BITS_IN_LONG-y);
                     87:   return (x>>y);
                     88: }
                     89:
                     90: #define HIGHWORD(a) ((a) >> BITS_IN_HALFULONG)
                     91: #define LOWWORD(a) ((a) & LOWMASK)
                     92:
                     93: /* Version Peter Montgomery */
                     94: /*
                     95:  *      Assume (for presentation) that BITS_IN_LONG = 32.
                     96:  *      Then 0 <= xhi, xlo, yhi, ylo <= 2^16 - 1.  Hence
                     97:  *
                     98:  * -2^31 + 2^16 <= (xhi-2^15)*(ylo-2^15) + (xlo-2^15)*(yhi-2^15) <= 2^31.
                     99:  *
                    100:  *      If xhi*ylo + xlo*yhi = 2^32*overflow + xymid, then
                    101:  *
                    102:  * -2^32 + 2^16 <= 2^32*overflow + xymid - 2^15*(xhi + ylo + xlo + yhi) <= 0.
                    103:  *
                    104:  * 2^16*overflow <= (xhi+xlo+yhi+ylo)/2 - xymid/2^16 <= 2^16*overflow + 2^16-1
                    105:  *
                    106:  *       This inequality was derived using exact (rational) arithmetic;
                    107:  *       it remains valid when we truncate the two middle terms.
                    108:  */
                    109: INLINE long
                    110: mulll(ulong x, ulong y)
                    111: {
                    112:   const ulong xlo = LOWWORD(x), xhi = HIGHWORD(x);
                    113:   const ulong ylo = LOWWORD(y), yhi = HIGHWORD(y);
                    114:   ulong xylo,xymid,xyhi,xymidhi,xymidlo;
                    115:
                    116:   xylo = xlo*ylo; xyhi = xhi*yhi;
                    117:   xymid = (xhi+xlo)*(yhi+ylo) - (xyhi+xylo);
                    118:
                    119:   xymidhi = HIGHWORD(xymid);
                    120:   xymidlo = xymid << BITS_IN_HALFULONG;
                    121:
                    122:   xylo += xymidlo;
                    123:   hiremainder = xyhi + xymidhi + (xylo < xymidlo)
                    124:      + (((((xhi+xlo) + (yhi+ylo)) >> 1) - xymidhi) & HIGHMASK);
                    125:
                    126:   return xylo;
                    127: }
                    128:
                    129: INLINE long
                    130: addmul(ulong x, ulong y)
                    131: {
                    132:   const ulong xlo = LOWWORD(x), xhi = HIGHWORD(x);
                    133:   const ulong ylo = LOWWORD(y), yhi = HIGHWORD(y);
                    134:   ulong xylo,xymid,xyhi,xymidhi,xymidlo;
                    135:
                    136:   xylo = xlo*ylo; xyhi = xhi*yhi;
                    137:   xymid = (xhi+xlo)*(yhi+ylo) - (xyhi+xylo);
                    138:
                    139:   xylo += hiremainder; xyhi += (xylo < hiremainder);
                    140:
                    141:   xymidhi = HIGHWORD(xymid);
                    142:   xymidlo = xymid << BITS_IN_HALFULONG;
                    143:
                    144:   xylo += xymidlo;
                    145:   hiremainder = xyhi + xymidhi + (xylo < xymidlo)
                    146:      + (((((xhi+xlo) + (yhi+ylo)) >> 1) - xymidhi) & HIGHMASK);
                    147:
                    148:   return xylo;
                    149: }
                    150:
                    151: /* version Peter Montgomery */
                    152:
                    153: INLINE int
                    154: bfffo(ulong x)
                    155: {
                    156:   int sc;
                    157:   static int tabshi[16]={4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0};
                    158:
                    159:   sc = BITS_IN_LONG - 4;
                    160: #ifdef LONG_IS_64BIT
                    161:   if (x & 0xffffffff00000000) {sc -= 32; x >>= 32;}
                    162: #endif
                    163:   if (x > 0xffffUL) {sc -= 16; x >>= 16;}
                    164:   if (x > 0x00ffUL) {sc -= 8; x >>= 8;}
                    165:   if (x > 0x000fUL) {sc -= 4; x >>= 4;}
                    166:   return sc + tabshi[x];
                    167: }
                    168:
                    169: /* Version Peter Montgomery */
                    170:
                    171: INLINE long
                    172: divll(ulong x, ulong y)
                    173: {
                    174: #define GLUE(hi, lo) (((hi) << BITS_IN_HALFULONG) + (lo))
                    175: #define SPLIT(a, b, c) b = HIGHWORD(a); c = LOWWORD(a)
                    176:
                    177:   ulong v1, v2, u3, u4, q1, q2, aux, aux1, aux2;
                    178:   int k;
                    179:   if (hiremainder >= y) err(talker, "Invalid arguments to divll");
                    180:   if (hiremainder == 0)
                    181:   {    /* Only one division needed */
                    182:     hiremainder = x % y;
                    183:     return x/y;
                    184:   }
                    185:   if (y <= LOWMASK)
                    186:   {    /* Use two half-word divisions */
                    187:     hiremainder = GLUE(hiremainder, HIGHWORD(x));
                    188:     q1 = hiremainder / y;
                    189:     hiremainder = GLUE(hiremainder % y, LOWWORD(x));
                    190:     q2 = hiremainder / y;
                    191:     hiremainder = hiremainder % y;
                    192:     return GLUE(q1, q2);
                    193:   }
                    194:   if (y & HIGHBIT) k = 0;
                    195:   else
                    196:   {
                    197:     k = bfffo(y);
                    198:     hiremainder = (hiremainder << k) + (x >> (BITS_IN_LONG - k));
                    199:     x <<= k; y <<= k;
                    200:   }
                    201:   SPLIT(y, v1, v2);
                    202:   SPLIT(x, u3, u4);
                    203:   q1 = hiremainder / v1; if (q1 > LOWMASK) q1 = LOWMASK;
                    204:   hiremainder -= q1 * v1;
                    205:   aux = v2 * q1;
                    206: again:
                    207:   SPLIT(aux, aux1, aux2);
                    208:   if (aux2 > u3) aux1++;
                    209:   if (aux1 > hiremainder) {q1--; hiremainder += v1; aux -= v2; goto again;}
                    210:
                    211:   hiremainder = GLUE(hiremainder - aux1, LOWWORD(u3 - aux2));
                    212:   q2 = hiremainder / v1; if (q2 > LOWMASK) q2 = LOWMASK;
                    213:   hiremainder -= q2 * v1;
                    214:   aux = v2 * q2;
                    215: again2:
                    216:   SPLIT(aux, aux1, aux2);
                    217:   if (aux2 > u4) aux1++;
                    218:   if (aux1 > hiremainder) {q2--; hiremainder += v1; aux -= v2; goto again2;}
                    219:   hiremainder = GLUE(hiremainder - aux1, LOWWORD(u4 - aux2)) >> k;
                    220:   return GLUE(q1, q2);
                    221: }
                    222:
                    223: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>