YoushouldhavereceivedcopiesoftheGNUGeneralPublicLicenseandthe GNULesserGeneralPublicLicensealongwiththeGNUMPLibrary.Ifnot,
see https://www.gnu.org/licenses/. */
/* __GMP_DECLSPEC must be given on any global data that will be accessed fromoutsidelibgmp,meaningfromthetestordevelopmentprograms,or fromlibgmpxx.Failingtodothiswillresultinanincorrectaddress beingusedfortheaccesses.Onfunctions__GMP_DECLSPECmakescalls fromoutsidelibgmpmoreefficient,butthey'llstillworkfinewithout
it. */
#ifndef __GMP_IMPL_H__ #define __GMP_IMPL_H__
#ifdefined _CRAY #include <intrinsics.h> /* for _popcnt */ #endif
/* For INT_MAX, etc. We used to avoid it because of a bug (on solaris, gcc2.95under-mcpu=ultrasparcinABI=32endsupgettingwrong values(theABI=64values)),butitshouldbesafenow.
OnCrayvectorsystems,however,weneedthesystemlimits.hsincesizes ofsignedandunsignedtypescandifferthere,dependingoncompiler options(eg.-hnofastmd),makingourSHRT_MAXetcexpressionsfail.For reference,intcanbe46or64bits,whereasuintisalways64bits;and
short can be 24, 32, 46 or 64 bits, and different for ushort. */
#if HAVE_INTTYPES_H /* for uint_least32_t */ # include <inttypes.h> #endif /* On some platforms inttypes.h exists but is incomplete
and we still need stdint.h. */ #if HAVE_STDINT_H # include <stdint.h> #endif
#ifdef __cplusplus #include <cstring> /* for strlen */ #include <string> /* for std::string */ #endif
#ifndef WANT_TMP_DEBUG /* for TMP_ALLOC_LIMBS_2 and others */ #define WANT_TMP_DEBUG 0 #endif
/* The following tries to get a good version of alloca. The tests are adaptedfromautoconfAC_FUNC_ALLOCA,withacoupleofadditions. WhetherthissucceedsistestedbyGMP_FUNC_ALLOCAandHAVE_ALLOCAwill besetupappropriately.
/* if not provided by gmp-mparam.h */ #ifndef GMP_LIMB_BYTES #define GMP_LIMB_BYTES SIZEOF_MP_LIMB_T #endif #ifndef GMP_LIMB_BITS #define GMP_LIMB_BITS (8 * SIZEOF_MP_LIMB_T) #endif
#define BITS_PER_ULONG (8 * SIZEOF_UNSIGNED_LONG)
/* gmp_uint_least32_t is an unsigned integer type with at least 32 bits. */ #if HAVE_UINT_LEAST32_T typedef uint_least32_t gmp_uint_least32_t; #else #if SIZEOF_UNSIGNED_SHORT >= 4 typedefunsignedshort gmp_uint_least32_t; #else #if SIZEOF_UNSIGNED >= 4 typedefunsigned gmp_uint_least32_t; #else typedefunsignedlong gmp_uint_least32_t; #endif #endif #endif
/* gmp_intptr_t, for pointer to integer casts */ #if HAVE_INTPTR_T typedef intptr_t gmp_intptr_t; #else/* fallback */ typedef size_t gmp_intptr_t; #endif
/* pre-inverse types for truncating division and modulo */ typedefstruct {mp_limb_t inv32;} gmp_pi1_t; typedefstruct {mp_limb_t inv21, inv32, inv53;} gmp_pi2_t;
/* "const" basically means a function does nothing but examine its arguments andgiveareturnvalue,itdoesn'treadorwriteanymemory(neither globalnorpointedtobyarguments),andhasnootherside-effects.This ismorerestrictivethan"pure".Seeinfonode"(gcc)Function Attributes".__GMP_NO_ATTRIBUTE_CONST_PUREletstune/common.cetcturn
this off when trying to write timing loops. */ #if HAVE_ATTRIBUTE_CONST && ! defined (__GMP_NO_ATTRIBUTE_CONST_PURE) #define ATTRIBUTE_CONST __attribute__ ((const)) #else #define ATTRIBUTE_CONST #endif
/* "malloc" means a function behaves like malloc in that the pointer it
returns doesn't alias anything. */ #if HAVE_ATTRIBUTE_MALLOC #define ATTRIBUTE_MALLOC __attribute__ ((malloc)) #else #define ATTRIBUTE_MALLOC #endif
/* va_copy is standard in C99, and gcc provides __va_copy when in strict C89 mode.Fallingbacktoamemcpywillgivemaximumportability,sinceit
works no matter whether va_list is a pointer, struct or array. */ #if ! defined (va_copy) && defined (__va_copy) #define va_copy(dst,src) __va_copy(dst,src) #endif #if ! defined (va_copy) #define va_copy(dst,src) \ do { memcpy (&(dst), &(src), sizeof (va_list)); } while (0) #endif
/* HAVE_HOST_CPU_alpha_CIX is 1 on an alpha with the CIX instructions
(ie. ctlz, ctpop, cttz). */ #if HAVE_HOST_CPU_alphaev67 || HAVE_HOST_CPU_alphaev68 \
|| HAVE_HOST_CPU_alphaev7 #define HAVE_HOST_CPU_alpha_CIX 1 #endif
TMP_DECLjustdeclaresavariable,butmightbeemptyandsomustbelast inalistofvariables.TMP_MARKmustbedonebeforeanyTMP_ALLOC. TMP_ALLOC(0)isnotallowed.TMP_FREEdoesn'tneedtobedoneifa
TMP_MARK was made, but then no TMP_ALLOCs. */
/* The alignment in bytes, used for TMP_ALLOCed blocks, when alloca or
__gmp_allocate_func doesn't already determine it. */ union tmp_align_t {
mp_limb_t l; double d; char *p;
}; #define __TMP_ALIGN sizeof (union tmp_align_t)
/* Return "a" rounded upwards to a multiple of "m", if it isn't already. "a"mustbeanunsignedtype. Thisisdesignedforusewithacompile-timeconstant"m". ThePOW2caseisexpectedtobeusual,andgcc3.0anduprecognises "(-(8*n))%8"orthelikeisalwayszero,whichmeanstheroundingupin
the WANT_TMP_NOTREENTRANT version of TMP_ALLOC below will be a noop. */ #define ROUND_UP_MULTIPLE(a,m) \
(POW2_P(m) ? (a) + (-(a))%(m) \
: (a)+(m)-1 - (((a)+(m)-1) % (m)))
/* n-1 inverts any low zeros and the lowest one bit. If n&(n-1) leaves zero thenthatlowestonebitmusthavebeentheonlybitset.n==0will
return true though, so avoid that. */ #define POW2_P(n) (((n) & ((n) - 1)) == 0)
/* Dummy for non-gcc, code involving it will go dead. */ #if ! defined (__GNUC__) || __GNUC__ < 2 #define __builtin_constant_p(x) 0 #endif
/* In gcc 2.96 and up on i386, tail calls are optimized to jumps if the stackusageiscompatible.__attribute__((regparm(N)))helpsby puttingleadingparametersinregisters,avoidingextrastack.
Onathlon-unknown-freebsd4.9withgcc3.3.3,regparmcannotbeusedwith -por-pgprofiling,sincethatversionofgccdoesn'trealizethe .mcountcallswillclobbertheparameterregisters.Othersystemsare ok,likedebianwithglibc2.3.2(mcountdoesn'tclobber),butwedon't bothertotrytodetectthis.regparmisonlyanoptimizationsowejust
disable it when profiling (profiling being a slowdown anyway). */
/* Macros for altering parameter order according to regparm usage. */ #if USE_LEADING_REGPARM #define REGPARM_2_1(a,b,x) x,a,b #define REGPARM_3_1(a,b,c,x) x,a,b,c #define REGPARM_ATTR(n) __attribute__ ((regparm (n))) #else #define REGPARM_2_1(a,b,x) a,b,x #define REGPARM_3_1(a,b,c,x) a,b,c,x #define REGPARM_ATTR(n) #endif
/* ASM_L gives a local label for a gcc asm block, for use when temporary locallabelslike"1:"mightnotbeavailable,whichisthecasefor instanceonthex86s(theSCOassemblerdoesn'tsupportthem).
#ifndef mpn_addmul_2 /* if not done with cpuvec in a fat binary */ #define mpn_addmul_2 __MPN(addmul_2)
__GMP_DECLSPEC mp_limb_t mpn_addmul_2 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); #endif
/* Alternative entry point in mpn_addmul_2 for the benefit of mpn_sqr_basecase. */ #define mpn_addmul_2s __MPN(addmul_2s)
__GMP_DECLSPEC mp_limb_t mpn_addmul_2s (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr);
/* Override mpn_addlsh1_n, mpn_addlsh2_n, mpn_sublsh1_n, etc with mpn_addlsh_n, etcwhen!HAVE_NATIVEtheformerbutHAVE_NATIVE_thelatter.Similarly, overridefoo_ip1functionswithfoo.Wethenlieandsaythesemacros representnativefunctions,butleaveatracebyusingthevalue2rather
than 1. */
#ifndef mpn_lshiftc /* if not done with cpuvec in a fat binary */ #define mpn_lshiftc __MPN(lshiftc)
__GMP_DECLSPEC mp_limb_t mpn_lshiftc (mp_ptr, mp_srcptr, mp_size_t, unsignedint); #endif
#ifndef mpn_mul_basecase /* if not done with cpuvec in a fat binary */ #define mpn_mul_basecase __MPN(mul_basecase)
__GMP_DECLSPEC void mpn_mul_basecase (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); #endif
#ifndef mpn_mullo_basecase /* if not done with cpuvec in a fat binary */ #define mpn_mullo_basecase __MPN(mullo_basecase)
__GMP_DECLSPEC void mpn_mullo_basecase (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); #endif
#ifndef mpn_sqr_basecase /* if not done with cpuvec in a fat binary */ #define mpn_sqr_basecase __MPN(sqr_basecase)
__GMP_DECLSPEC void mpn_sqr_basecase (mp_ptr, mp_srcptr, mp_size_t); #endif
#ifndef mpn_redc_1 /* if not done with cpuvec in a fat binary */ #define mpn_redc_1 __MPN(redc_1)
__GMP_DECLSPEC mp_limb_t mpn_redc_1 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); #endif
#ifndef mpn_redc_2 /* if not done with cpuvec in a fat binary */ #define mpn_redc_2 __MPN(redc_2)
__GMP_DECLSPEC mp_limb_t mpn_redc_2 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); #endif
#ifndef mpn_mod_1_1p_cps /* if not done with cpuvec in a fat binary */ #define mpn_mod_1_1p_cps __MPN(mod_1_1p_cps)
__GMP_DECLSPEC void mpn_mod_1_1p_cps (mp_limb_t [4], mp_limb_t); #endif #ifndef mpn_mod_1_1p /* if not done with cpuvec in a fat binary */ #define mpn_mod_1_1p __MPN(mod_1_1p)
__GMP_DECLSPEC mp_limb_t mpn_mod_1_1p (mp_srcptr, mp_size_t, mp_limb_t, const mp_limb_t [4]) __GMP_ATTRIBUTE_PURE; #endif
#ifndef mpn_mod_1s_2p_cps /* if not done with cpuvec in a fat binary */ #define mpn_mod_1s_2p_cps __MPN(mod_1s_2p_cps)
__GMP_DECLSPEC void mpn_mod_1s_2p_cps (mp_limb_t [5], mp_limb_t); #endif #ifndef mpn_mod_1s_2p /* if not done with cpuvec in a fat binary */ #define mpn_mod_1s_2p __MPN(mod_1s_2p)
__GMP_DECLSPEC mp_limb_t mpn_mod_1s_2p (mp_srcptr, mp_size_t, mp_limb_t, const mp_limb_t [5]) __GMP_ATTRIBUTE_PURE; #endif
#ifndef mpn_mod_1s_3p_cps /* if not done with cpuvec in a fat binary */ #define mpn_mod_1s_3p_cps __MPN(mod_1s_3p_cps)
__GMP_DECLSPEC void mpn_mod_1s_3p_cps (mp_limb_t [6], mp_limb_t); #endif #ifndef mpn_mod_1s_3p /* if not done with cpuvec in a fat binary */ #define mpn_mod_1s_3p __MPN(mod_1s_3p)
__GMP_DECLSPEC mp_limb_t mpn_mod_1s_3p (mp_srcptr, mp_size_t, mp_limb_t, const mp_limb_t [6]) __GMP_ATTRIBUTE_PURE; #endif
#ifndef mpn_mod_1s_4p_cps /* if not done with cpuvec in a fat binary */ #define mpn_mod_1s_4p_cps __MPN(mod_1s_4p_cps)
__GMP_DECLSPEC void mpn_mod_1s_4p_cps (mp_limb_t [7], mp_limb_t); #endif #ifndef mpn_mod_1s_4p /* if not done with cpuvec in a fat binary */ #define mpn_mod_1s_4p __MPN(mod_1s_4p)
__GMP_DECLSPEC mp_limb_t mpn_mod_1s_4p (mp_srcptr, mp_size_t, mp_limb_t, const mp_limb_t [7]) __GMP_ATTRIBUTE_PURE; #endif
/* Macro to obtain a void pointer to the function pointers structure. */ #define RNG_FNPTR(rstate) ((rstate)->_mp_algdata._mp_lc)
/* Macro to obtain a pointer to the generator's state.
When used as a lvalue the rvalue needs to be cast to mp_ptr. */ #define RNG_STATE(rstate) ((rstate)->_mp_seed->_mp_d)
/* Write a given number of random bits to rp. */ #define _gmp_rand(rp, state, bits) \ do { \
gmp_randstate_ptr __rstate = (state); \
(*((gmp_randfnptr_t *) RNG_FNPTR (__rstate))->randget_fn) \
(__rstate, rp, bits); \
} while (0)
/* __gmp_rands is the global state for the old-style random functions, and isalsousedinthetestprograms(hencethe__GMP_DECLSPEC).
There'snoseedinghere,sompz_randometcwillgeneratethesame sequenceeverytime.ThisisnotunliketheClibraryrandomfunctions ifyoudon'tseedthem,soperhapsit'sacceptable.Diggingupaseed from/dev/randomorthelikewouldworkonmanysystems,butmight encourageafalseconfidence,sinceit'dbeprettymuchimpossibletodo somethingthatwouldworkreliablyeverywhere.Inanycasethenewstyle functionsarerecommendedtoapplicationswhichcareaboutrandomness,so
the old functions aren't too important. */
/* this is used by the test programs, to free memory */ #define RANDS_CLEAR() \ do { \ if (__gmp_rands_initialized) \
{ \
__gmp_rands_initialized = 0; \
gmp_randclear (__gmp_rands); \
} \
} while (0)
/* For a threshold between algorithms A and B, size>=thresh is where B shouldbeused.SpecialvalueMP_SIZE_T_MAXmeansonlyeveruseA,or value0meansonlyeveruseB.Thetestsforthesespecialvalueswill becompile-timeconstants,sothecompilershouldbeabletoeliminate
the code for the unwanted algorithm. */
/* The minimal supported value for Toom22 depends also on Toom32 and
Toom42 implementations. */ #define MPN_TOOM22_MUL_MINSIZE 6 #define MPN_TOOM2_SQR_MINSIZE 4
#ifndef mpn_bdiv_dbm1c /* if not done with cpuvec in a fat binary */ #define mpn_bdiv_dbm1c __MPN(bdiv_dbm1c)
__GMP_DECLSPEC mp_limb_t mpn_bdiv_dbm1c (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t); #endif
#define mpn_bsqrtinv __MPN(bsqrtinv)
__GMP_DECLSPEC int mpn_bsqrtinv (mp_ptr, mp_srcptr, mp_bitcnt_t, mp_ptr);
#ifdefined (_CRAY) #define MPN_COPY_INCR(dst, src, n) \ do { \ int __i; /* Faster on some Crays with plain int */ \
_Pragma ("_CRI ivdep"); \ for (__i = 0; __i < (n); __i++) \
(dst)[__i] = (src)[__i]; \
} while (0) #endif
/* used by test programs, hence __GMP_DECLSPEC */ #ifndef mpn_copyi /* if not done with cpuvec in a fat binary */ #define mpn_copyi __MPN(copyi)
__GMP_DECLSPEC void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t); #endif
#ifdefined (_CRAY) #define MPN_COPY_DECR(dst, src, n) \ do { \ int __i; /* Faster on some Crays with plain int */ \
_Pragma ("_CRI ivdep"); \ for (__i = (n) - 1; __i >= 0; __i--) \
(dst)[__i] = (src)[__i]; \
} while (0) #endif
/* used by test programs, hence __GMP_DECLSPEC */ #ifndef mpn_copyd /* if not done with cpuvec in a fat binary */ #define mpn_copyd __MPN(copyd)
__GMP_DECLSPEC void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t); #endif
Enhancement:GLIBCdoessometrickerywithdcbztozerowholecachelines atatime.MPN_ZEROisn'tallthatimportantinGMP,soitmightbemore troublethanit'sworthtodothesame,thoughperhapsacalltomemset
would be good when on a GNU system. */
#if HAVE_HOST_CPU_FAMILY_power || HAVE_HOST_CPU_FAMILY_powerpc #define MPN_FILL(dst, n, f) \ do { \
mp_ptr __dst = (dst) - 1; \
mp_size_t __n = (n); \
ASSERT (__n > 0); \ do \
*++__dst = (f); \ while (--__n); \
} while (0) #endif
#ifndef MPN_FILL #define MPN_FILL(dst, n, f) \ do { \
mp_ptr __dst = (dst); \
mp_size_t __n = (n); \
ASSERT (__n > 0); \ do \
*__dst++ = (f); \ while (--__n); \
} while (0) #endif
#define MPN_ZERO(dst, n) \ do { \
ASSERT ((n) >= 0); \ if ((n) != 0) \
MPN_FILL (dst, n, CNST_LIMB (0)); \
} while (0)
/* On the x86s repe/scasl doesn't seem useful, since it takes many cycles to startupandwouldneedtostripalotofzerosbeforeit'dbefaster thanasimplecmplloop.Herearesometimesincyclesfor std/repe/scasl/cldandcld/repe/scasl(thelatterwouldbeforstripping lowzeros).
stdcld P51816 P64638 K63613 K72120
*/ #ifndef MPN_NORMALIZE #define MPN_NORMALIZE(DST, NLIMBS) \ do { \ while ((NLIMBS) > 0) \
{ \ if ((DST)[(NLIMBS) - 1] != 0) \ break; \
(NLIMBS)--; \
} \
} while (0) #endif #ifndef MPN_NORMALIZE_NOT_ZERO #define MPN_NORMALIZE_NOT_ZERO(DST, NLIMBS) \ do { \ while (1) \
{ \
ASSERT ((NLIMBS) >= 1); \ if ((DST)[(NLIMBS) - 1] != 0) \ break; \
(NLIMBS)--; \
} \
} while (0) #endif
/* Strip least significant zero limbs from {ptr,size} by incrementing ptr anddecrementingsize.lowshouldbeptr[0],andwillbethenewptr[0] onreturning.Thenumberin{ptr,size}mustbenon-zero,ie.size!=0and
somewhere a non-zero limb. */ #define MPN_STRIP_LOW_ZEROS_NOT_ZERO(ptr, size, low) \ do { \
ASSERT ((size) >= 1); \
ASSERT ((low) == (ptr)[0]); \
\ while ((low) == 0) \
{ \
(size)--; \
ASSERT ((size) >= 1); \
(ptr)++; \
(low) = *(ptr); \
} \
} while (0)
/* Initialize X of type mpz_t with space for NLIMBS limbs. X should be a temporaryvariable;itwillbeautomaticallyclearedoutatfunction return.Weuse__xheretomakeitpossibletoacceptbothmpz_ptrand
mpz_t arguments. */ #define MPZ_TMP_INIT(X, NLIMBS) \ do { \
mpz_ptr __x = (X); \
ASSERT ((NLIMBS) >= 1); \
__x->_mp_alloc = (NLIMBS); \
__x->_mp_d = TMP_ALLOC_LIMBS (NLIMBS); \
} while (0)
#if WANT_ASSERT staticinlinevoid *
_mpz_newalloc (mpz_ptr z, mp_size_t n)
{ void * res = _mpz_realloc(z,n); /* If we are checking the code, force a random change to limbs. */
((mp_ptr) res)[0] = ~ ((mp_ptr) res)[ALLOC (z) - 1]; return res;
} #else #define _mpz_newalloc _mpz_realloc #endif /* Realloc for an mpz_t WHAT if it has less than NEEDED limbs. */ #define MPZ_REALLOC(z,n) (UNLIKELY ((n) > ALLOC(z)) \
? (mp_ptr) _mpz_realloc(z,n) \
: PTR(z)) #define MPZ_NEWALLOC(z,n) (UNLIKELY ((n) > ALLOC(z)) \
? (mp_ptr) _mpz_newalloc(z,n) \
: PTR(z))
/* n^log <= GMP_NUMB_MAX, a limb can store log factors less than n */ staticinlineunsigned
log_n_max (mp_limb_t n)
{ unsigned log; for (log = 8; n > __gmp_limbroots_table[log - 1]; log--); return log;
}
#define SIEVESIZE 512/* FIXME: Allow gmp_init_primesieve to choose */ typedefstruct
{ unsignedlong d; /* current index in s[] */ unsignedlong s0; /* number corresponding to s[0] */ unsignedlong sqrt_s0; /* misnomer for sqrt(s[SIEVESIZE-1]) */ unsignedchar s[SIEVESIZE + 1]; /* sieve table */
} gmp_primesieve_t;
/* MUL_TOOM22_THRESHOLD_LIMIT is the maximum for MUL_TOOM22_THRESHOLD. In a normalbuildMUL_TOOM22_THRESHOLDisaconstantandweusethat.Inafat binaryortuneprogrambuildMUL_TOOM22_THRESHOLDisavariableanda
separate hard limit will have been defined. Similarly for TOOM3. */ #ifndef MUL_TOOM22_THRESHOLD_LIMIT #define MUL_TOOM22_THRESHOLD_LIMIT MUL_TOOM22_THRESHOLD #endif #ifndef MUL_TOOM33_THRESHOLD_LIMIT #define MUL_TOOM33_THRESHOLD_LIMIT MUL_TOOM33_THRESHOLD #endif #ifndef MULLO_BASECASE_THRESHOLD_LIMIT #define MULLO_BASECASE_THRESHOLD_LIMIT MULLO_BASECASE_THRESHOLD #endif #ifndef SQRLO_BASECASE_THRESHOLD_LIMIT #define SQRLO_BASECASE_THRESHOLD_LIMIT SQRLO_BASECASE_THRESHOLD #endif #ifndef SQRLO_DC_THRESHOLD_LIMIT #define SQRLO_DC_THRESHOLD_LIMIT SQRLO_DC_THRESHOLD #endif
/* SQR_BASECASE_THRESHOLD is where mpn_sqr_basecase should take over from mpn_mul_basecase.Defaultistousempn_sqr_basecasefrom0.(Notethatwe certainlyalwayswantitifthere'sanativeassemblermpn_sqr_basecase.)
Ifitturnsoutthatmpn_toom2_sqrbecomesfasterthanmpn_mul_basecase beforempn_sqr_basecasedoes,thenSQR_BASECASE_THRESHOLDisthetoom2 thresholdandSQR_TOOM2_THRESHOLDis0.Thisoddityarisesmoreorless becauseSQR_TOOM2_THRESHOLDrepresentsthesizeuptowhichmpn_sqr_basecase
should be used, and that may be never. */
#ifndef SQR_BASECASE_THRESHOLD #define SQR_BASECASE_THRESHOLD 0/* never use mpn_mul_basecase */ #endif
/* First k to use for an FFT modF multiply. A modF FFT is an order log(2^k)/log(2^(k-1))algorithm,sok=3ismerely1.5likekaratsuba,
whereas k=4 is 1.33 which is faster than toom3 at 1.485. */ #define FFT_FIRST_K 4
/* Threshold at which FFT should be used to do a modF NxN -> N multiply. */ #ifndef MUL_FFT_MODF_THRESHOLD #define MUL_FFT_MODF_THRESHOLD (MUL_TOOM33_THRESHOLD * 3) #endif #ifndef SQR_FFT_MODF_THRESHOLD #define SQR_FFT_MODF_THRESHOLD (SQR_TOOM3_THRESHOLD * 3) #endif
/* Threshold at which FFT should be used to do an NxN -> 2N multiply. This willbeasizewhereFFTisusingk=7ork=8,sinceanFFT-kusedforan NxN->2Nmultiplyandnotrecursingintoitselfisanorder log(2^k)/log(2^(k-2))algorithm,soit'llbeatleastk=7at1.39which
is the first better than toom3. */ #ifndef MUL_FFT_THRESHOLD #define MUL_FFT_THRESHOLD (MUL_FFT_MODF_THRESHOLD * 10) #endif #ifndef SQR_FFT_THRESHOLD #define SQR_FFT_THRESHOLD (SQR_FFT_MODF_THRESHOLD * 10) #endif
/* Return non-zero if xp,xsize and yp,ysize overlap. Ifxp+xsize<=ypthere'snooverlap,orifyp+ysize<=xpthere'sno
overlap. If both these are false, there's an overlap. */ #define MPN_OVERLAP_P(xp, xsize, yp, ysize) \
((xp) + (xsize) > (yp) && (yp) + (ysize) > (xp)) #define MEM_OVERLAP_P(xp, xsize, yp, ysize) \
( (char *) (xp) + (xsize) > (char *) (yp) \
&& (char *) (yp) + (ysize) > (char *) (xp))
/* Return non-zero if xp,xsize and yp,ysize are either identical or not
overlapping. Return zero if they're partially overlapping. */ #define MPN_SAME_OR_SEPARATE_P(xp, yp, size) \
MPN_SAME_OR_SEPARATE2_P(xp, size, yp, size) #define MPN_SAME_OR_SEPARATE2_P(xp, xsize, yp, ysize) \
((xp) == (yp) || ! MPN_OVERLAP_P (xp, xsize, yp, ysize))
/* Return non-zero if dst,dsize and src,ssize are either identical or overlappinginawaysuitableforanincrementing/decrementingalgorithm.
Return zero if they're partially overlapping in an unsuitable fashion. */ #define MPN_SAME_OR_INCR2_P(dst, dsize, src, ssize) \
((dst) <= (src) || ! MPN_OVERLAP_P (dst, dsize, src, ssize)) #define MPN_SAME_OR_INCR_P(dst, src, size) \
MPN_SAME_OR_INCR2_P(dst, size, src, size) #define MPN_SAME_OR_DECR2_P(dst, dsize, src, ssize) \
((dst) >= (src) || ! MPN_OVERLAP_P (dst, dsize, src, ssize)) #define MPN_SAME_OR_DECR_P(dst, src, size) \
MPN_SAME_OR_DECR2_P(dst, size, src, size)
/* ASSERT() is a private assertion checking scheme, similar to <assert.h>. ASSERT()doesthecheckonlyifWANT_ASSERTisselected,ASSERT_ALWAYS() doesitalways.Generallyassertionsaremeantfordevelopment,but
might help when looking for a problem later too. */
/* ASSERT_CODE includes code when assertion checking is wanted. This is the
same as writing "#if WANT_ASSERT", but more compact. */ #if WANT_ASSERT #define ASSERT_CODE(expr) expr #else #define ASSERT_CODE(expr) #endif
/* Test that an mpq_t is in fully canonical form. This can be used as protectiononroutineslikempq_equalwhichgivewrongresultson
non-canonical inputs. */ #if WANT_ASSERT #define ASSERT_MPQ_CANONICAL(q) \ do { \
ASSERT (q->_mp_den._mp_size > 0); \ if (q->_mp_num._mp_size == 0) \
{ \ /* zero should be 0/1 */ \
ASSERT (mpz_cmp_ui (mpq_denref(q), 1L) == 0); \
} \ else \
{ \ /* no common factors */ \
mpz_t __g; \
mpz_init (__g); \
mpz_gcd (__g, mpq_numref(q), mpq_denref(q)); \
ASSERT (mpz_cmp_ui (__g, 1) == 0); \
mpz_clear (__g); \
} \
} while (0) #else #define ASSERT_MPQ_CANONICAL(q) do {} while (0) #endif
/* Check that the nail parts are zero. */ #define ASSERT_ALWAYS_LIMB(limb) \ do { \
mp_limb_t __nail = (limb) & GMP_NAIL_MASK; \
ASSERT_ALWAYS (__nail == 0); \
} while (0) #define ASSERT_ALWAYS_MPN(ptr, size) \ do { \ /* let whole loop go dead when no nails */ \ if (GMP_NAIL_BITS != 0) \
{ \
mp_size_t __i; \ for (__i = 0; __i < (size); __i++) \
ASSERT_ALWAYS_LIMB ((ptr)[__i]); \
} \
} while (0) #if WANT_ASSERT #define ASSERT_LIMB(limb) ASSERT_ALWAYS_LIMB (limb) #define ASSERT_MPN(ptr, size) ASSERT_ALWAYS_MPN (ptr, size) #else #define ASSERT_LIMB(limb) do {} while (0) #define ASSERT_MPN(ptr, size) do {} while (0) #endif
/* Assert that an mpn region {ptr,size} is zero, or non-zero.
size==0 is allowed, and in that case {ptr,size} considered to be zero. */ #if WANT_ASSERT #define ASSERT_MPN_ZERO_P(ptr,size) \ do { \
mp_size_t __i; \
ASSERT ((size) >= 0); \ for (__i = 0; __i < (size); __i++) \
ASSERT ((ptr)[__i] == 0); \
} while (0) #define ASSERT_MPN_NONZERO_P(ptr,size) \ do { \
mp_size_t __i; \ int __nonzero = 0; \
ASSERT ((size) >= 0); \ for (__i = 0; __i < (size); __i++) \ if ((ptr)[__i] != 0) \
{ \
__nonzero = 1; \ break; \
} \
ASSERT (__nonzero); \
} while (0) #else #define ASSERT_MPN_ZERO_P(ptr,size) do {} while (0) #define ASSERT_MPN_NONZERO_P(ptr,size) do {} while (0) #endif
FIXME:Switchallcodefrommpn_{incr,decr}_utoMPN_{INCR,DECR}_U, declaringtheiroperandsizes,thenremovetheformer.Thisispurely
for the benefit of assertion checking. */
#ifdefined (__GNUC__) && GMP_NAIL_BITS == 0 && ! defined (NO_ASM) \
&& (defined(HAVE_HOST_CPU_FAMILY_x86) || defined(HAVE_HOST_CPU_FAMILY_x86_64)) \
&& ! WANT_ASSERT /* Better flags handling than the generic C gives on i386, saving a few
bytes of code and maybe a cycle or two. */
/* Structure for conversion between internal binary format and strings. */ struct bases
{ /* Number of digits in the conversion base that always fits in an mp_limb_t. Forexample,forbase10onamachinewhereanmp_limb_thas32bitsthis
is 9, since 10**9 is the largest number that fits into an mp_limb_t. */ int chars_per_limb;
/* base**chars_per_limb, i.e. the biggest number that fits a word, built by factorsofbase.Exception:For2,4,8,etc,big_baseislog2(base),
i.e. the number of bits used to represent each digit in the base. */
mp_limb_t big_base;
/* A GMP_LIMB_BITS bit approximation to 1/big_base, represented as a fixed-pointnumber.Insteadofdividingbybig_baseanapplicationcan
choose to multiply by big_base_inverted. */
mp_limb_t big_base_inverted;
};
/* Compute the number of digits in base for nbits bits, making sure the result isnevertoosmall.Thetwovariantsofthemacroimplementthesame
function; the GT2 variant below works just for bases > 2. */ #define DIGITS_IN_BASE_FROM_BITS(res, nbits, b) \ do { \
mp_limb_t _ph, _dummy; \
size_t _nbits = (nbits); \
umul_ppmm (_ph, _dummy, mp_bases[b].logb2, _nbits); \
_ph += (_dummy + _nbits < _dummy); \
res = _ph + 1; \
} while (0) #define DIGITS_IN_BASEGT2_FROM_BITS(res, nbits, b) \ do { \
mp_limb_t _ph, _dummy; \
size_t _nbits = (nbits); \
umul_ppmm (_ph, _dummy, mp_bases[b].logb2 + 1, _nbits); \
res = _ph + 1; \
} while (0)
/* For power of 2 bases this is exact. For other bases the result is either exactoronetoobig.
/* bit count to limb count, rounding up */ #define BITS_TO_LIMBS(n) (((n) + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS)
/* MPN_SET_UI sets an mpn (ptr, cnt) to given ui. MPZ_FAKE_UI creates fake mpz_tfromui.ThezpargumentmusthaveroomforLIMBS_PER_ULONGlimbs
in both cases (LIMBS_PER_ULONG is also defined here.) */ #if BITS_PER_ULONG <= GMP_NUMB_BITS /* need one limb per ulong */
Recentversionsofgcc(eg.3.3)willinfactoptimizea"?:"likethis toanarithmeticrightshiftanyway,butit'sgoodtogetthedesired shiftonpastversionstoo(inparticularsinceanimportantuseof
LIMB_HIGHBIT_TO_MASK is in udiv_qrnnd_preinv). */
/* Use a library function for invert_limb, if available. */ #define mpn_invert_limb __MPN(invert_limb)
__GMP_DECLSPEC mp_limb_t mpn_invert_limb (mp_limb_t) ATTRIBUTE_CONST; #if ! defined (invert_limb) && HAVE_NATIVE_mpn_invert_limb #define invert_limb(invxl,xl) \ do { \
(invxl) = mpn_invert_limb (xl); \
} while (0) #endif
#ifndef mpn_preinv_divrem_1 /* if not done with cpuvec in a fat binary */ #define mpn_preinv_divrem_1 __MPN(preinv_divrem_1)
__GMP_DECLSPEC mp_limb_t mpn_preinv_divrem_1 (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t, int); #endif
/* USE_PREINV_DIVREM_1 is whether to use mpn_preinv_divrem_1, as opposed to the plainmpn_divrem_1.Thedefaultisyes,sincethefewCISCchipswhere
preinv is not good have defines saying so. */ #ifndef USE_PREINV_DIVREM_1 #define USE_PREINV_DIVREM_1 1 #endif
/* This selection may seem backwards. The reason mpn_mod_1 typically takes
over for larger sizes is that it uses the mod_1_1 function. */ #define MPN_MOD_OR_PREINV_MOD_1(src,size,divisor,inverse) \
(BELOW_THRESHOLD (size, PREINV_MOD_1_TO_MOD_1_THRESHOLD) \
? mpn_preinv_mod_1 (src, size, divisor, inverse) \
: mpn_mod_1 (src, size, divisor))
#ifndef mpn_mod_34lsub1 /* if not done with cpuvec in a fat binary */ #define mpn_mod_34lsub1 __MPN(mod_34lsub1)
__GMP_DECLSPEC mp_limb_t mpn_mod_34lsub1 (mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; #endif
/* DIVEXACT_1_THRESHOLD is at what size to use mpn_divexact_1, as opposed to plainmpn_divrem_1.LikewiseBMOD_1_TO_MOD_1_THRESHOLDfor mpn_modexact_1_oddagainstplainmpn_mod_1.OnmostCPUsdivexactand modexactarefasteratallsizes,sothedefaultsare0.ThoseCPUs
where this is not right have a tuned threshold. */ #ifndef DIVEXACT_1_THRESHOLD #define DIVEXACT_1_THRESHOLD 0 #endif #ifndef BMOD_1_TO_MOD_1_THRESHOLD #define BMOD_1_TO_MOD_1_THRESHOLD 10 #endif
#define MPN_DIVREM_OR_DIVEXACT_1(rp, up, n, d) \ do { \ if (BELOW_THRESHOLD (n, DIVEXACT_1_THRESHOLD)) \
ASSERT_NOCARRY (mpn_divrem_1 (rp, (mp_size_t) 0, up, n, d)); \ else \
{ \
ASSERT (mpn_mod_1 (up, n, d) == 0); \
mpn_divexact_1 (rp, up, n, d); \
} \
} while (0)
#ifndef mpn_modexact_1c_odd /* if not done with cpuvec in a fat binary */ #define mpn_modexact_1c_odd __MPN(modexact_1c_odd)
__GMP_DECLSPEC mp_limb_t mpn_modexact_1c_odd (mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; #endif
/* binvert_limb() sets inv to the multiplicative inverse of n modulo 2^GMP_NUMB_BITS,ie.satisfyinginv*n==1mod2^GMP_NUMB_BITS. nmustbeodd(otherwisesuchaninversedoesn'texist).
Alternative:AsnotedinGranlundandMontgomery"DivisionbyInvariant IntegersusingMultiplication"(referenceingmp.texi),nitselfgivesa 3-bitinverseimmediately,andcouldbeusedinsteadofatablelookup. A4-bitinversecanbeobtainedeffectivelyfromxoringbits1and2into
bit 3, for instance with (((n + 2) & 4) << 1) ^ n. */
#ifdefined (__GNUC__) && ! defined (__INTEL_COMPILER) \
&& ! defined (NO_ASM) && defined (__ia64) /* unsigned long is either 32 or 64 bits depending on the ABI, zero extend
to a 64 bit unsigned long long for popcnt */ #define ULONG_PARITY(p, n) \ do { \ unsignedlonglong __n = (unsignedlong) (n); \ int __p; \
__asm__ ("popcnt %0 = %1" : "=r" (__p) : "r" (__n)); \
(p) = __p & 1; \
} while (0) #endif
Withinthefieldswerelyontheintegerendiannessbeingthesameasthe floatendianness,thisistrueeverywhereweknowofandit'dbeafairly
strange system that did anything else. */
/* Use (4.0 * ...) instead of (2.0 * ...) to work around buggy compilers
that don't convert ulong->double correctly (eg. SunOS 4 native cc). */ #define MP_BASE_AS_DOUBLE (4.0 * ((mp_limb_t) 1 << (GMP_NUMB_BITS - 2))) /* Maximum number of limbs it will take to store any `double'.
We assume doubles have 53 mantissa bits. */ #define LIMBS_PER_DOUBLE ((53 + GMP_NUMB_BITS - 2) / GMP_NUMB_BITS + 1)
__GMP_DECLSPEC int __gmp_extract_double (mp_ptr, double);
#if HAVE_DOUBLE_VAX_D || HAVE_DOUBLE_VAX_G || HAVE_DOUBLE_CRAY_CFP /* no nans or infs in these formats */ #define DOUBLE_NAN_INF_ACTION(x, a_nan, a_inf) \ do { } while (0) #endif
#ifndef DOUBLE_NAN_INF_ACTION /* Unknown format, try something generic. NaNshouldbe"unordered",sox!=x.
Inf should be bigger than DBL_MAX. */ #define DOUBLE_NAN_INF_ACTION(x, a_nan, a_inf) \ do { \
{ \ if (UNLIKELY ((x) != (x))) \
{ a_nan; } \ elseif (UNLIKELY ((x) > DBL_MAX || (x) < -DBL_MAX)) \
{ a_inf; } \
} \
} while (0) #endif
/* On m68k, x86 and amd64, gcc (and maybe other compilers) can hold doubles inthecoprocessor,whichmeansabiggerexponentrangethannormal,and dependingontheroundingmode,abiggermantissathannormal.(See "Disappointments"inthegccmanual.)FORCE_DOUBLEstoresandfetches "d"throughmemorytoforceanyroundingandoverflowstooccur.
Notquitesurethatan"automaticvolatile"willusememory,butitdoes ingcc.Anasm("":"=m"(d):"0"(d))can'tbeusedtotrickgcc,since apparentlymatchingoperandslike"0"areonlyallowedonaregister output.gcc3.4warnsaboutthis,thoughinfactitandpastversions
seem to put the operand through memory as hoped. */
#if (HAVE_HOST_CPU_FAMILY_m68k || HAVE_HOST_CPU_FAMILY_x86 \
|| defined (__amd64__)) #define FORCE_DOUBLE(d) \ do { volatiledouble __gmp_force = (d); (d) = __gmp_force; } while (0) #else #define FORCE_DOUBLE(d) do { } while (0) #endif
/* BIT1 means a result value in bit 1 (second least significant bit), with a zerobitrepresenting+1andaonebitrepresenting-1.Bitsotherthan bit1aregarbage.Thesearemeanttobekeptin"int"s,andcastsare usedtoensuretheexpressionsare"int"sevenifaand/orbmightbe othertypes.
JACOBI_TWOS_U_BIT1andJACOBI_RECIP_UU_BIT1areusedinmpn_jacobi_base andtheirspeedisimportant.Expressionsareusedratherthan conditionalstoaccumulatesignchanges,whicheffectivelymeansXORs
instead of conditional JUMPs. */
/* (a/0), with a signed; is 1 if a=+/-1, 0 otherwise */ #define JACOBI_S0(a) (((a) == 1) | ((a) == -1))
/* (a/0), with a unsigned; is 1 if a=+/-1, 0 otherwise */ #define JACOBI_U0(a) ((a) == 1)
/* FIXME: JACOBI_LS0 and JACOBI_0LS are the same, so delete one and
come up with a better name. */
/* (a/0), with a given by low and size;
is 1 if a=+/-1, 0 otherwise */ #define JACOBI_LS0(alow,asize) \
(((asize) == 1 || (asize) == -1) && (alow) == 1)
/* (a/0), with a an mpz_t;
fetch of low limb always valid, even if size is zero */ #define JACOBI_Z0(a) JACOBI_LS0 (PTR(a)[0], SIZ(a))
/* (0/b), with b unsigned; is 1 if b=1, 0 otherwise */ #define JACOBI_0U(b) ((b) == 1)
/* (0/b), with b unsigned; is 1 if b=+/-1, 0 otherwise */ #define JACOBI_0S(b) ((b) == 1 || (b) == -1)
/* (0/b), with b given by low and size; is 1 if b=+/-1, 0 otherwise */ #define JACOBI_0LS(blow,bsize) \
(((bsize) == 1 || (bsize) == -1) && (blow) == 1)
/* Convert a bit1 to +1 or -1. */ #define JACOBI_BIT1_TO_PN(result_bit1) \
(1 - ((int) (result_bit1) & 2))
/* (2/b), with b unsigned and odd; is(-1)^((b^2-1)/8)whichis1ifb==1,7mod8or-1ifb==3,5mod8and
hence obtained from (b>>1)^b */ #define JACOBI_TWO_U_BIT1(b) \
((int) (((b) >> 1) ^ (b)))
/* (2/b)^twos, with b unsigned and odd */ #define JACOBI_TWOS_U_BIT1(twos, b) \
((int) ((twos) << 1) & JACOBI_TWO_U_BIT1 (b))
/* (2/b)^twos, with b unsigned and odd */ #define JACOBI_TWOS_U(twos, b) \
(JACOBI_BIT1_TO_PN (JACOBI_TWOS_U_BIT1 (twos, b)))
/* (-1/b), with b odd (signed or unsigned);
is (-1)^((b-1)/2) */ #define JACOBI_N1B_BIT1(b) \
((int) (b))
/* (a/b) effect due to sign of a: signed/unsigned, b odd;
is (-1/b) if a<0, or +1 if a>=0 */ #define JACOBI_ASGN_SU_BIT1(a, b) \
((((a) < 0) << 1) & JACOBI_N1B_BIT1(b))
/* (a/b) effect due to sign of b: signed/signed;
is -1 if a and b both negative, +1 otherwise */ #define JACOBI_BSGN_SS_BIT1(a, b) \
((((a)<0) & ((b)<0)) << 1)
/* (a/b) effect due to sign of b: signed/mpz;
is -1 if a and b both negative, +1 otherwise */ #define JACOBI_BSGN_SZ_BIT1(a, b) \
JACOBI_BSGN_SS_BIT1 (a, SIZ(b))
/* (a/b) effect due to sign of b: mpz/signed;
is -1 if a and b both negative, +1 otherwise */ #define JACOBI_BSGN_ZS_BIT1(a, b) \
JACOBI_BSGN_SZ_BIT1 (b, a)
/* (a/b) reciprocity to switch to (b/a), a,b both unsigned and odd; is(-1)^((a-1)*(b-1)/4),whichmeans+1ifeithera,b==1mod4,or-1if botha,b==3mod4,achievedinbit1bya&b.NoASSERT()sabouta,bodd becausethisisusedinacoupleofplaceswithonlybit1ofaorb
valid. */ #define JACOBI_RECIP_UU_BIT1(a, b) \
((int) ((a) & (b)))
/* Strip low zero limbs from {b_ptr,b_size} by incrementing b_ptr and decrementingb_size.b_lowshouldbeb_ptr[0]onentry,andwillbe updatedforthenewb_ptr.result_bit1isupdatedaccordingtothe
factors of 2 stripped, as per (a/2). */ #define JACOBI_STRIP_LOW_ZEROS(result_bit1, a, b_ptr, b_size, b_low) \ do { \
ASSERT ((b_size) >= 1); \
ASSERT ((b_low) == (b_ptr)[0]); \
\ while (UNLIKELY ((b_low) == 0)) \
{ \
(b_size)--; \
ASSERT ((b_size) >= 1); \
(b_ptr)++; \
(b_low) = *(b_ptr); \
\
ASSERT (((a) & 1) != 0); \ if ((GMP_NUMB_BITS % 2) == 1) \
(result_bit1) ^= JACOBI_TWO_U_BIT1(a); \
} \
} while (0)
/* Set a_rem to {a_ptr,a_size} reduced modulo b, either using mod_1 or modexact_1_odd,butineithercaseleavinga_rem<b.bmustbeoddand unsigned.modexact_1_oddeffectivelycalculates-amodb,and result_bit1isadjustedforthefactorof-1.
FIXME:mpn_modexact_1_oddismoreefficient,sosomewaytogetitused foroddGMP_NUMB_BITSwouldbegood.Perhapsitcouldmungitsresult,
or not skip a divide step, or something. */
staticinlineint
mpn_jacobi_finish (unsigned bits)
{ /* (a, b) = (1,0) or (0,1) */
ASSERT ( (bits & 14) == 0);
return1-2*(bits & 1);
}
staticinlineunsigned
mpn_jacobi_update (unsigned bits, unsigned denominator, unsigned q)
{ /* FIXME: Could halve table size by not including the e bit in the *index,andinsteadxorwhenupdating.Thenthelookupwouldbe *like * *bits^=table[((bits&30)<<2)+(denominator<<2)+q];
*/
/* For almost all calls, denominator is constant and quite often q isconstanttoo.Souseadditionratherthanor,sothecompiler canputtheconstantpartcanintotheoffsetofanindexed addressinginstruction.
/* Definitions for mpn_set_str and mpn_get_str */ struct powers
{
mp_ptr p; /* actual power value */
mp_size_t n; /* # of limbs at p */
mp_size_t shift; /* weight of lowest limb, in limb base B */
size_t digits_in_base; /* number of corresponding digits */ int base;
}; typedefstruct powers powers_t; #define mpn_str_powtab_alloc(n) ((n) + 2 * GMP_LIMB_BITS) /* FIXME: This can perhaps be trimmed */ #define mpn_dc_set_str_itch(n) ((n) + GMP_LIMB_BITS) #define mpn_dc_get_str_itch(n) ((n) + GMP_LIMB_BITS)
/* Compute the number of base-b digits corresponding to nlimbs limbs, rounding
down. */ #define DIGITS_IN_BASE_PER_LIMB(res, nlimbs, b) \ do { \
mp_limb_t _ph, _dummy; \
umul_ppmm (_ph, _dummy, \
mp_bases[b].logb2, GMP_NUMB_BITS * (mp_limb_t) (nlimbs));\
res = _ph; \
} while (0)
/* Compute the number of limbs corresponding to ndigits base-b digits, rounding
up. */ #define LIMBS_PER_DIGIT_IN_BASE(res, ndigits, b) \ do { \
mp_limb_t _ph, _dummy; \
umul_ppmm (_ph, _dummy, mp_bases[b].log2b, (mp_limb_t) (ndigits)); \
res = 8 * _ph / GMP_NUMB_BITS + 2; \
} while (0)
/* Set n to the number of significant digits an mpf of the given _mp_prec field,inthegivenbase.Thisisaroundedupvalue,designedtoensure there'senoughdigitstoreproducealltheguaranteedpartofthevalue.
FIXME:Ifbaseisapowerof2andthebitsperdigitdivides GMP_LIMB_BITSthenthe+2isunnecessary.Thishappensalwaysfor
base==2, and in base==16 with the current 32 or 64 bit limb sizes. */
#define MPF_SIGNIFICANT_DIGITS(n, base, prec) \ do { \
size_t rawn; \
ASSERT (base >= 2 && base < numberof (mp_bases)); \
DIGITS_IN_BASE_PER_LIMB (rawn, (prec) - 1, base); \
n = rawn + 2; \
} while (0)
/* Decimal point string, from the current C locale. Needs <langinfo.h> for nl_langinfoandconstants,preferablywith_GNU_SOURCEdefinedtoget DECIMAL_POINTfromglibc,andneeds<locale.h>forlocaleconv,eachunder theirrespective#ifHAVE_FOO_H.
/* DECIMAL_POINT seems to need _GNU_SOURCE defined to get it from glibc. */ #if HAVE_NL_LANGINFO && defined (DECIMAL_POINT) #define GMP_DECIMAL_POINT (nl_langinfo (DECIMAL_POINT)) #endif /* RADIXCHAR is deprecated, still in unix98 or some such. */ #if HAVE_NL_LANGINFO && defined (RADIXCHAR) && ! defined (GMP_DECIMAL_POINT) #define GMP_DECIMAL_POINT (nl_langinfo (RADIXCHAR)) #endif /* localeconv is slower since it returns all locale stuff */ #if HAVE_LOCALECONV && ! defined (GMP_DECIMAL_POINT) #define GMP_DECIMAL_POINT (localeconv()->decimal_point) #endif #if ! defined (GMP_DECIMAL_POINT) #define GMP_DECIMAL_POINT (".") #endif
struct doprnt_params_t { int base; /* negative for upper case */ int conv; /* choices above */ constchar *expfmt; /* exponent format */ int exptimes4; /* exponent multiply by 4 */ char fill; /* character */ int justify; /* choices above */ int prec; /* prec field, or -1 for all digits */ int showbase; /* choices above */ int showpoint; /* if radix point always shown */ int showtrailing; /* if trailing zeros wanted */ char sign; /* '+', ' ', or '\0' */ int width; /* width field */
};
/* "buf" is a __gmp_allocate_func block of "alloc" many bytes. The first "size"ofthesehavebeenwritten."alloc>size"ismaintained,so there'sroomtostorea'\0'attheend."result"iswherethe
application wants the final block pointer. */ struct gmp_asprintf_t { char **result; char *buf;
size_t size;
size_t alloc;
};
/* If a realloc is necessary, use twice the size actually required, so as to
avoid repeated small reallocs. */ #define GMP_ASPRINTF_T_NEED(d, n) \ do { \
size_t alloc, newsize, newalloc; \
ASSERT ((d)->alloc >= (d)->size + 1); \
\
alloc = (d)->alloc; \
newsize = (d)->size + (n); \ if (alloc <= newsize) \
{ \
newalloc = 2*newsize; \
(d)->alloc = newalloc; \
(d)->buf = __GMP_REALLOCATE_FUNC_TYPE ((d)->buf, \
alloc, newalloc, char); \
} \
} while (0)
__GMP_DECLSPEC int __gmp_asprintf_memory (struct gmp_asprintf_t *, constchar *, size_t);
__GMP_DECLSPEC int __gmp_asprintf_reps (struct gmp_asprintf_t *, int, int);
__GMP_DECLSPEC int __gmp_asprintf_final (struct gmp_asprintf_t *);
/* buf is where to write the next output, and size is how much space is left there.Iftheapplicationpassedsize==0thenthat'swhatwe'llhave
here, and nothing at all should be written. */ struct gmp_snprintf_t { char *buf;
size_t size;
};
/* Add the bytes printed by the call to the total retval, or bail out on an
error. */ #define DOPRNT_ACCUMULATE(call) \ do { \ int __ret; \
__ret = call; \ if (__ret == -1) \ goto error; \
retval += __ret; \
} while (0) #define DOPRNT_ACCUMULATE_FUN(fun, params) \ do { \
ASSERT ((fun) != NULL); \
DOPRNT_ACCUMULATE ((*(fun)) params); \
} while (0)
/* Enhancement: The "mod" and "gcd_1" functions below could have __GMP_ATTRIBUTE_PURE,butcurrently(gcc3.3)that'snotsupportedon functionpointers,onlyactualfunctions.Itprobablydoesn'tmakemuch differencetothegmpcode,sincehopefullywearrangecallssothere's
no great need for the compiler to move things around. */
/* Get a threshold "field" from __gmpn_cpuvec, running __gmpn_cpuvec_init()
if that hasn't yet been done (to establish the right values). */ #define CPUVEC_THRESHOLD(field) \
((LIKELY (__gmpn_cpuvec_initialized) ? 0 : (__gmpn_cpuvec_init (), 0)), \
__gmpn_cpuvec.field)
#if TUNE_PROGRAM_BUILD /* Some extras wanted when recompiling some .c files for use by the tune program.Notpartofanormalbuild.
It'snecessarytokeepthesethresholdsas#defines(justtoan identicallynamedvariable),sincevariousdefaultsareestablishedbased on#ifdefinthe.cfiles.Forsomethisisnotso(thedefaultsare
instead established above), but all are done this way for consistency. */
/* A native mpn_sqr_basecase is not tuned and SQR_BASECASE_THRESHOLD should
remain as zero (always use it). */ #if ! HAVE_NATIVE_mpn_sqr_basecase #undef SQR_BASECASE_THRESHOLD #define SQR_BASECASE_THRESHOLD sqr_basecase_threshold extern mp_size_t sqr_basecase_threshold; #endif
#undef FFT_TABLE_ATTRS #define FFT_TABLE_ATTRS extern mp_size_t mpn_fft_table[2][MPN_FFT_TABLE_SIZE]; #define FFT_TABLE3_SIZE 2000/* generous space for tuning */ externstruct fft_table_nk mpn_fft_table3[2][FFT_TABLE3_SIZE];
/* Sizes the tune program tests up to, used in a couple of recompilations. */ #undef MUL_TOOM22_THRESHOLD_LIMIT #undef MUL_TOOM33_THRESHOLD_LIMIT #undef MULLO_BASECASE_THRESHOLD_LIMIT #undef SQRLO_BASECASE_THRESHOLD_LIMIT #undef SQRLO_DC_THRESHOLD_LIMIT #undef SQR_TOOM3_THRESHOLD_LIMIT #define SQR_TOOM2_MAX_GENERIC 200 #define MUL_TOOM22_THRESHOLD_LIMIT 700 #define MUL_TOOM33_THRESHOLD_LIMIT 700 #define SQR_TOOM3_THRESHOLD_LIMIT 400 #define MUL_TOOM44_THRESHOLD_LIMIT 1000 #define SQR_TOOM4_THRESHOLD_LIMIT 1000 #define MUL_TOOM6H_THRESHOLD_LIMIT 1100 #define SQR_TOOM6_THRESHOLD_LIMIT 1100 #define MUL_TOOM8H_THRESHOLD_LIMIT 1200 #define SQR_TOOM8_THRESHOLD_LIMIT 1200 #define MULLO_BASECASE_THRESHOLD_LIMIT 200 #define SQRLO_BASECASE_THRESHOLD_LIMIT 200 #define SQRLO_DC_THRESHOLD_LIMIT 400 #define GET_STR_THRESHOLD_LIMIT 150 #define FAC_DSC_THRESHOLD_LIMIT 2048
#endif/* TUNE_PROGRAM_BUILD */
#ifdefined (__cplusplus)
} #endif
/* FIXME: Make these itch functions less conservative. Also consider making themdependentonjust'an',andcomputetheallocationdirectlyfrom'an'
instead of via n. */
/* toom22/toom2: Scratch need is 2*(an + k), k is the recursion depth. kisthssmallestksuchthat ceil(an/2^k)<MUL_TOOM22_THRESHOLD. whichimpliesthat k=bitsizeoffloor((an-1)/(MUL_TOOM22_THRESHOLD-1)) =1+floor(log_2(floor((an-1)/(MUL_TOOM22_THRESHOLD-1))))
*/ #define mpn_toom22_mul_itch(an, bn) \
(2 * ((an) + GMP_NUMB_BITS)) #define mpn_toom2_sqr_itch(an) \
(2 * ((an) + GMP_NUMB_BITS))
/* toom33/toom3: Scratch need is 5an/2 + 10k, k is the recursion depth. Weuse3an+C,sothatwecanuseasmallerconstant.
*/ #define mpn_toom33_mul_itch(an, bn) \
(3 * (an) + GMP_NUMB_BITS) #define mpn_toom3_sqr_itch(an) \
(3 * (an) + GMP_NUMB_BITS)
/* toom33/toom3: Scratch need is 8an/3 + 13k, k is the recursion depth. Weuse3an+C,sothatwecanuseasmallerconstant.
*/ #define mpn_toom44_mul_itch(an, bn) \
(3 * (an) + GMP_NUMB_BITS) #define mpn_toom4_sqr_itch(an) \
(3 * (an) + GMP_NUMB_BITS)
/* A little helper for a null-terminated __gmp_allocate_func string. Thedestructorensuresit'sfreedevenifanexceptionisthrown. Thelenfieldisneededbythedestructor,andcanbeusedbyanyoneelse toavoidasecondstrlenpassoverthedata.
SinceourinputisaCstring,usingstrleniscorrect.Perhapsit'dbe moreC++-ishstyletousestd::char_traits<char>::length,butchar_traits
isn't available in gcc 2.95.4. */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.