/usr/include/eclib/xmod.h is in libec-dev 20160101-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | // xmod.h: declarations of basic modular arithmetic functions
//////////////////////////////////////////////////////////////////////////
//
// Copyright 1990-2012 John Cremona
//
// This file is part of the eclib package.
//
// eclib 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; either version 2 of the License, or (at your
// option) any later version.
//
// eclib is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with eclib; if not, write to the Free Software Foundation,
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
//
//////////////////////////////////////////////////////////////////////////
// All are inline functions, there's no .cc file
#ifndef _XMOD_H
#define _XMOD_H 1
// undefine this to use int/long/longlong arithmetic only
//#define USE_DMOD
// We'll define BIGPRIME to be one of the following, the largest prime
// possible for the given strategy without overlow.
// We allow all residues a with |a|<p, for speed
// This condition is ASSUMED ON INPUT to the xmodmul functions
// In fact we only use PRIME27 and PRIME30 which are ints.
#define PRIME27 134217689 // = largest p such that p < 2^27
#define PRIME63 6074000981 // = largest p such that (p/2)^2 < 2^63.
#define PRIME30 1073741789 // = largest p such that p < 2^30.
#define PRIME31a 2147483647 // = largest p such that p < 2^31.
#define PRIME31b 92681 // = largest p such that (p/2)^2 < 2^31.
//////////////////////////////////////////////////////////////////////
#ifdef USE_DMOD
// Strategy: whether base type is 32- or 64-bit, modular operations
// are done via doubles which have 52 bits for the mantissa, so any
// modulus < 2^27 is ok, and the default modulus PRIME27 is the
// largest such prime.
#include "math.h" // for floor()
#define XMOD_METHOD "doubles"
const int BIGPRIME = PRIME27;
const double BIGPRIME_D = PRIME27;
const double BIGPRIME_D_INV = 1/BIGPRIME_D;
const int BIGPRIME_I = PRIME27;
inline long xmod(long a, double m) {return (long)(a-(m*floor((a/m)+0.5)));}
inline int xmod(int a, double m) {return (int)(a-(m*floor((a/m)+0.5)));}
inline long xmod(long a, long m) {return (long)(a-(m*floor((a/m)+0.5)));}
inline int xmod(int a, int m) {return (int)(a-(m*floor((a/m)+0.5)));}
inline int xmod(long a, int m) {return (int)(a-(m*floor((a/m)+0.5)));}
inline long xmod0(long a) {return (long)(a-(BIGPRIME_D*floor((a*BIGPRIME_D_INV))));}
inline int xmod0(int a) {return (int)(a-(BIGPRIME_D*floor((a*BIGPRIME_D_INV))));}
inline long mod0(long a) {return (long)(a-(BIGPRIME_D*floor((a*BIGPRIME_D_INV)+0.5)));}
inline int mod0(int a) {return (int)(a-(BIGPRIME_D*floor((a*BIGPRIME_D_INV)+0.5)));}
inline long xmodmul(long a, long b, double m)
{ double c = (double)a * (double)b;
return (long)(c-m*floor((c/m)+0.5));
}
inline int xmodmul(int a, int b, double m)
{ double c = (double)a * (double)b;
return (int)(c-m*floor((c/m)+0.5));
}
inline long xmodmul0(long a, long b)
{ double c = (double)a * (double)b;
return (long)(c-BIGPRIME_D*floor((c*BIGPRIME_D_INV)+0.5));
}
inline int xmodmul0(int a, int b)
{ double c = (double)a * (double)b;
return (int)(c-BIGPRIME_D*floor((c*BIGPRIME_D_INV)+0.5));
}
inline long xmodmul(long a, long b, long m)
{ double c = (double)a * (double)b;
return (long)(c-m*floor((c/m)+0.5));
}
inline int xmodmul(int a, int b, int m)
{ double c = (double)a * (double)b;
return (int)(c-m*floor((c/m)+0.5));
}
//////////////////////////////////////////////////////////////////////
#else // use some int/long/longlong combination
// Strategy: modular multiplication for ints and longs is done via
// int64_ts which have 63 bits
// modular addition is simply xmod(a+b,m) since 2*m<2^31
#define XMOD_METHOD "ints and longs"
const int BIGPRIME = PRIME30;
const int HALF_BIGPRIME = BIGPRIME>>1; // = 536870894;
const int TWO_BIGPRIME = 2147483578; // 2*BIGPRIME
const int64_t INV_BIGPRIME = 4294967436LL; // = 2^32+140 = [2^62/p]
inline int xmod(int a, int m) {return a%m;}
inline long xmod(long a, long m) {return a%m;}
inline int xmod(long a, int m) { return (int)(a%(long)m);}
inline long xmod(int a, long m) { return (long)((long)(a)%m);}
inline int xmod0(int a) {return a%BIGPRIME;}
inline int mod0(int a)
{a%=BIGPRIME;
if(a>0)
while(a>HALF_BIGPRIME) a-=BIGPRIME;
else
while(-a>HALF_BIGPRIME) a+=BIGPRIME;
return a;
}
inline long xmod0(long a) {return (a%(long)BIGPRIME);}
inline long mod0(long a) {return mod0((int)(a%BIGPRIME));}
inline int xmodmul0(int a, int b)
{
return ((int)( ( (int64_t)(a)*(int64_t)(b) ) % (int64_t)(BIGPRIME) ))%BIGPRIME;
}
inline long xmodmul0(long a, long b)
{
return (long)(((int)( ( (int64_t)(a)*(int64_t)(b) ) % (int64_t)(BIGPRIME) ))%BIGPRIME);
}
// This special version only works modulo BIGPRIME, not a general modulus:
// It should work faster (no divisions)! Thanks to David Harvey.
inline int xmm0(int a, int b)
{
if (a==1) return b;
if (a==-1) return -b;
if (b==1) return a;
if (b==-1) return -a;
// check:
// int r2 = (a*(int64_t)b) % BIGPRIME;
if(a<0) a+=BIGPRIME;
if(b<0) b+=BIGPRIME;
int64_t ab = a*(int64_t)b;
int64_t r = ab-((INV_BIGPRIME*(ab>>30))>>32)*BIGPRIME;
r -= ( ((r>=TWO_BIGPRIME)?BIGPRIME:0) + ((r>=BIGPRIME)?BIGPRIME:0) );
if (r>HALF_BIGPRIME) r-=BIGPRIME;
// check:
// if (r!=r2)
// {
// cout << "Problem with "<<a<<"*"<<b<<" (mod "<<BIGPRIME
// <<"): computed "<<r<<", not "<<r2<<endl;
// return r2;
// }
return (int)r;
}
inline long xmm0(long a, long b)
{
return (a*(int64_t)b) % BIGPRIME;
}
inline int xmodmul(int a, int b, int m)
{
if (m==BIGPRIME) return xmm0(a,b);
return ((int)( ( (int64_t)(a)*(int64_t)(b) ) % (int64_t)(m) ))%m;
}
inline int xmodmul(int a, int b, long m)
{
return (int)(((long)( ( (int64_t)(a)*(int64_t)(b) ) % (int64_t)(m) ))%m);
}
inline int xmodmul(long a, long b, int m)
{
return ((int)( ( (int64_t)(a)*(int64_t)(b) ) % (int64_t)(m) ))%m;
}
inline long xmodmul(long a, long b, long m)
{
return ((long)( ( (int64_t)(a)*(int64_t)(b) ) % (int64_t)(m) ))%m;
}
#endif // ifdef USE_DMOD
#if(1)
const int DEFAULT_MODULUS = BIGPRIME;
// table of inversers of residues<20 modulo BIGPRIME:
static int table_invs[20] = {0,1, 536870895, 357913930, 805306342, 214748358, 178956965, 920350105, 402653171, 477218573, 107374179, 97612890, 626349377, 330382089, 997045947, 71582786, 738197480, 442128972, 775480181, 226050903};
#else
const int DEFAULT_MODULUS = 1073741783; //BIGPRIME-6;
// table of inversers of residues<20 modulo 1073741783:
static int table_invs[20] = {0, 1, 536870892, 357913928, 268435446,
644245070, 178956964, 460175050, 134217723, 835132498, 322122535,
780903115, 89478482, 743359696, 230087525, 930576212, 603979753,
884257939, 417566249, 395589078};
#endif
inline long invmod0(long aa)
{
long a=aa;
// if |a| is small, use look-up table:
if ((a>0)&&(a<20)) return table_invs[a];
long ma=-a;
if ((ma>0)&&(ma<20)) return -table_invs[ma];
// if a = BIGPRIME-ma with ma small, use look-up table:
ma+=BIGPRIME; // = BIGPRIME-a
if ((ma>0)&&(ma<20)) return -table_invs[ma];
// if a = -BIGPRIME+ma with ma small, use look-up table:
ma=a-BIGPRIME;
if ((ma>0)&&(ma<20)) return table_invs[ma];
// General code, use Euclidean Algorithm:
long x=0,oldx=1,newx,b=BIGPRIME,c,q;
while (b!=0)
{ q = a/b;
c = a - q*b; a = b; b = c;
newx = oldx - q*x; oldx = x; x = newx;
}
if (a==1) {return oldx;}
if (a==-1) {return -oldx;}
cout << "invmod0 called with " << a << " -- not invertible!\n";
return 0;
}
inline int invmod0(int aa)
{
int a=aa;
// if |a| is small, use look-up table:
if ((a>0)&&(a<20)) return table_invs[a];
int ma=-a;
if ((ma>0)&&(ma<20)) return -table_invs[ma];
// if a = BIGPRIME-ma with ma small, use look-up table:
ma+=BIGPRIME; // = BIGPRIME-a
if ((ma>0)&&(ma<20)) return -table_invs[ma];
// if a = -BIGPRIME+ma with ma small, use look-up table:
ma=a-BIGPRIME;
if ((ma>0)&&(ma<20)) return table_invs[ma];
// General code, use Euclidean Algorithm:
int x=0,oldx=1,newx,b=BIGPRIME,c,q;
while (b!=0)
{ q = a/b;
c = a - q*b; a = b; b = c;
newx = oldx - q*x; oldx = x; x = newx;
}
if (a==1) {return oldx;}
if (a==-1) {return -oldx;}
cout << "invmod0 called with " << a << " -- not invertible!\n";
return 0;
}
#endif // ifndef _XMOD_H
|