/* $Id: level1.h,v 1.18 2002/06/08 13:07:03 karim Exp $ Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file defines some "level 1" kernel functions */ /* These functions can be inline, with gcc */ /* If not gcc, they are defined externally with "level1.c" */ /* level1.c includes this file and never needs to be changed */ /* The following seven lines are necessary for level0.c and level1.c */ #ifdef LEVEL1 # undef INLINE # define INLINE #endif #ifdef LEVEL0 # undef INLINE #endif #ifndef INLINE void addsii(long x, GEN y, GEN z); long addssmod(long a, long b, long p); void addssz(long x, long y, GEN z); void affii(GEN x, GEN y); void affsi(long s, GEN x); void affui(long s, GEN x); void affsr(long s, GEN x); GEN cgetg(long x, long y); GEN cgeti(long x); GEN cgetr(long x); int cmpir(GEN x, GEN y); int cmpsr(long x, GEN y); int divise(GEN x, GEN y); long divisii(GEN x, long y, GEN z); void divisz(GEN x, long y, GEN z); void divrrz(GEN x, GEN y, GEN z); void divsiz(long x, GEN y, GEN z); GEN divss(long x, long y); long divssmod(long a, long b, long p); void divssz(long x, long y, GEN z); void dvmdiiz(GEN x, GEN y, GEN z, GEN t); GEN dvmdis(GEN x, long y, GEN *z); void dvmdisz(GEN x, long y, GEN z, GEN t); GEN dvmdsi(long x, GEN y, GEN *z); void dvmdsiz(long x, GEN y, GEN z, GEN t); GEN dvmdss(long x, long y, GEN *z); void dvmdssz(long x, long y, GEN z, GEN t); long evallg(long x); long evallgef(long x); long evalvalp(long x); long evalexpo(long x); long expi(GEN x); double gtodouble(GEN x); GEN icopy(GEN x); GEN icopy_av(GEN x, GEN y); GEN itor(GEN x, long prec); long itos(GEN x); ulong itou(GEN x); GEN modis(GEN x, long y); GEN mpabs(GEN x); GEN mpadd(GEN x, GEN y); void mpaff(GEN x, GEN y); int mpcmp(GEN x, GEN y); GEN mpcopy(GEN x); GEN mpdiv(GEN x, GEN y); int mpdivis(GEN x, GEN y, GEN z); int mpdivisis(GEN x, long y, GEN z); GEN mpmul(GEN x, GEN y); GEN mpneg(GEN x); GEN mpsub(GEN x, GEN y); void mulsii(long x, GEN y, GEN z); long mulssmod(ulong a, ulong b, ulong c); void mulssz(long x, long y, GEN z); GEN new_chunk(long x); GEN realun(long prec); GEN realzero(long prec); GEN realzero_bit(long bitprec); void resiiz(GEN x, GEN y, GEN z); GEN resis(GEN x, long y); GEN ressi(long x, GEN y); GEN shiftr(GEN x, long n); long smodis(GEN x, long y); GEN stor(long x, long prec); GEN stoi(long x); GEN subii(GEN x, GEN y); GEN subir(GEN x, GEN y); GEN subri(GEN x, GEN y); GEN subrr(GEN x, GEN y); GEN subsi(long x, GEN y); GEN subsr(long x, GEN y); long subssmod(long a, long b, long p); GEN utoi(ulong x); long vali(GEN x); #else /* defined(INLINE) */ INLINE long evallg(long x) { if (x & ~LGBITS) err(errlg); return _evallg(x); } INLINE long evallgef(long x) { if (x & ~LGEFBITS) err(errlgef); return _evallgef(x); } INLINE long evalvalp(long x) { const long v = _evalvalp(x); if (v & ~VALPBITS) err(errvalp); return v; } INLINE long evalexpo(long x) { const long v = _evalexpo(x); if (v & ~EXPOBITS) err(errexpo); return v; } INLINE GEN new_chunk(long x) { const GEN z = ((GEN) avma) - x; if ((ulong)x > (ulong)((GEN)avma-(GEN)bot)) err(errpile); #ifdef MEMSTEP checkmemory(z); #endif #ifdef _WIN32 if (win32ctrlc) dowin32ctrlc(); #endif avma = (gpmem_t)z; return z; } /* THE FOLLOWING ONES ARE IN mp.s */ # ifndef __M68K__ INLINE GEN cgetg(long x, long y) { const GEN z = new_chunk(x); z[0] = evaltyp(y) | evallg(x); return z; } INLINE GEN cgeti(long x) { const GEN z = new_chunk(x); z[0] = evaltyp(t_INT) | evallg(x); return z; } INLINE GEN cgetr(long x) { const GEN z = new_chunk(x); z[0] = evaltyp(t_REAL) | evallg(x); return z; } # endif /* __M68K__ */ /* cannot do memcpy because sometimes x and y overlap */ INLINE GEN mpcopy(GEN x) { register long lx = lg(x); const GEN y = new_chunk(lx); while (--lx >= 0) y[lx]=x[lx]; return y; } INLINE GEN icopy(GEN x) { register long lx = lgefint(x); const GEN y = cgeti(lx); while (--lx > 0) y[lx]=x[lx]; return y; } /* copy integer x as if we had avma = av */ INLINE GEN icopy_av(GEN x, GEN y) { register long lx = lgefint(x); y -= lx; while (--lx >= 0) y[lx]=x[lx]; return y; } INLINE GEN mpneg(GEN x) { const GEN y=mpcopy(x); setsigne(y,-signe(x)); return y; } INLINE GEN mpabs(GEN x) { const GEN y=mpcopy(x); if (signe(x)<0) setsigne(y,1); return y; } INLINE long smodis(GEN x, long y) { const gpmem_t av=avma; divis(x,y); avma=av; if (!hiremainder) return 0; return (signe(x)>0) ? hiremainder: labs(y)+hiremainder; } INLINE GEN utoi(ulong x) { GEN y; if (!x) return gzero; y=cgeti(3); y[1] = evalsigne(1) | evallgefint(3); y[2] = x; return y; } INLINE GEN stoi(long); INLINE GEN realzero(long); INLINE GEN stosmall(long x) { if (labs(x) & SMALL_MASK) return stoi(x); return (GEN) (1 | (x<<1)); } # ifndef __M68K__ INLINE GEN stoi(long x) { GEN y; if (!x) return gzero; y=cgeti(3); if (x>0) { y[1] = evalsigne(1) | evallgefint(3); y[2] = x; } else { y[1] = evalsigne(-1) | evallgefint(3); y[2] = -x; } return y; } INLINE long itos(GEN x) { const long s = signe(x); long u; if (!s) return 0; u = (long)x[2]; if (lgefint(x) > 3 || u < 0) err(affer2); return (s>0) ? u : -u; } INLINE void affii(GEN x, GEN y) { long lx; if (x==y) return; lx=lgefint(x); if (lg(y) 0) { x[1] = evalsigne( 1) | evallgefint(3); x[2] = s; } else { x[1] = evalsigne(-1) | evallgefint(3); x[2] = -s; } } } INLINE void affsr(long s, GEN x) { long l; if (!s) { x[1] = evalexpo(-bit_accuracy(lg(x))); return; } if (s<0) { x[1] = evalsigne(-1); s = -s; } else x[1] = evalsigne(1); l=bfffo(s); x[1] |= evalexpo((BITS_IN_LONG-1)-l); x[2] = s< 3) err(affer2); return x[2]; } INLINE void affui(ulong u, GEN x) { if (!u) x[1] = evalsigne(0) | evallgefint(2); else { if (lg(x) < 3) err(affer1); x[1] = evalsigne(1) | evallgefint(3); x[2] = u; } } INLINE int mpdivisis(GEN x, long y, GEN z) { const gpmem_t av = avma; GEN p1 = divis(x,y); if (hiremainder) { avma = av; return 0; } affii(p1,z); avma = av; return 1; } INLINE double gtodouble(GEN x) { static long reel4[4]={ evaltyp(t_REAL) | _evallg(4),0,0,0 }; if (typ(x)==t_REAL) return rtodbl(x); gaffect(x,(GEN)reel4); return rtodbl((GEN)reel4); } INLINE GEN realzero_bit(long bitprec) { GEN x=cgetr(2); x[1]=evalexpo(bitprec); return x; } INLINE GEN realzero(long prec) { return realzero_bit(-bit_accuracy(prec)); } INLINE GEN realun(long prec) { GEN x=cgetr(prec); affsr(1,x); return x; } INLINE GEN stor(long s, long prec) { GEN z = cgetr(prec); affsr(s,z); return z; } INLINE GEN itor(GEN x, long prec) { GEN z = cgetr(prec); affir(x,z); return z; } INLINE long addssmod(long a, long b, long p) { ulong res = a + b; return (res >= (ulong)p) ? res - p : res; } INLINE long subssmod(long a, long b, long p) { long res = a - b; return (res >= 0) ? res : res + p; } INLINE long mulssmod(ulong a, ulong b, ulong c) { LOCAL_HIREMAINDER; { register ulong x = mulll(a,b); /* alter the doubleword by a multiple of c: */ if (hiremainder>=c) hiremainder %= c; (void)divll(x,c); } return hiremainder; } INLINE long divssmod(long a, long b, long p) { long v1 = 0, v2 = 1, v3, r, oldp = p; while (b > 1) { v3 = v1 - (p / b) * v2; v1 = v2; v2 = v3; r = p % b; p = b; b = r; } if (v2 < 0) v2 += oldp; return mulssmod(a, v2, oldp); } INLINE long expi(GEN x) { const long lx=lgefint(x); return lx==2? -HIGHEXPOBIT: bit_accuracy(lx)-bfffo(x[2])-1; } #endif