/* widentt.c */ /* ** This file is placed into the public domain by its author, ** Carey Bloodworth (Carey@Bloodworth.org) on July 16, 2001 ** ** This multiplication demo is not designed for high performance. ** It's a tutorial program designed to be used with the information ** on my web site at www.Bloodworth.org */ /* ** This file demonstrates a very NTT multiplication using very ** wide primes. The code is written for simplicity, not ** for performance, so it is *EXTREMELY* slow. ** ** To compile this using GCC: ** gcc main.c widentt.c -o widentt.exe */ /* ** How many bits should be in our ModInt? ** Choice of 64, 253, 254 and 256 */ #define MOD_BITS 64 #include#include #include #include #include "wmodmath.h" size_t ModWords; /* How many UINT16 words are our ModInts? */ typedef short int Short; #define CalcNTTLen(_NumLen) ((((_NumLen)*BASE_DIG)*2)/BASE_DIG) /* NumLen*BaseDig*ZeroPadding/Dig_Per_NTT */ static ModIntPtr NTTNum1=NULL, NTTNum2=NULL; static int BASE; static int BASE_DIG; ModIntPtr Prime,PrimvRoot,MulInv; static void ComputeRoot(ModIntPtr w,size_t Step,int Dir,size_t ModWords) /* ** Compute the trig root for this step size. */ {ModIntPtr Temp; Temp=ModMalloc(1,ModWords); if (Dir > 0) { CB_Copy(Temp,ModWords,Prime,ModWords);CB_Sub1(Temp,ModWords); CB_DivInt(Temp,Step,ModWords);CB_Sub(Temp,Prime,Temp,ModWords); CB_Sub1(Temp,ModWords); ModPow(w, PrimvRoot,Temp,ModWords); } else { CB_Copy(Temp,ModWords,Prime,ModWords);CB_Sub1(Temp,ModWords); CB_DivInt(Temp,Step,ModWords); ModPow(w, PrimvRoot,Temp,ModWords); } /* ModPow(NthRoot, PrimvRoot,Prime-1-(Prime-1)/NTTLen); ModPow(Nthroot1,PrimvRoot,(Prime-1)/NTTLen); */ ModFree(Temp); } static void NTTReOrder(ModIntPtr Data, size_t Len,size_t ModWords) {size_t Index,xednI,k; xednI=0; for (Index=0;Index Index) ModSwap(&Data[Index*ModWords],&Data[xednI*ModWords],ModWords); k=Len/2; while ((k <= xednI) && (k >=1)) {xednI-=k;k/=2;} xednI+=k; } } static void NTT(ModIntPtr Data, size_t Len,int Dir,size_t ModWords) /* ** A Radix 2, decimation in time, iterative NTT. */ {size_t j,Step,HalfStep,z; ModIntPtr u,w,T,End; NTTReOrder(Data,Len,ModWords); Step=1;z=1; u=ModMalloc(1,ModWords); w=ModMalloc(1,ModWords); T=ModMalloc(1,ModWords); End=&Data[Len*ModWords]; while (Step < Len) { HalfStep=Step; Step*=2; ModSet1(u,ModWords); ComputeRoot(w,Step,Dir,ModWords); for (j=0;j 4) { printf("Error: The fft is slightly hardwired for <= 4 digits in the base.\n"); exit(0); } if ((NTTNum1==NULL) || (NTTNum2==NULL)) { printf("Unable to allocate memory for WideNTTNum1, WideNTTNum2.\n"); printf("Len=%d Words=%d\n",(int)Len,(int)ModWords ); exit(0); } Prime=ModMalloc(1,ModWords); PrimvRoot=ModMalloc(1,ModWords); MulInv=ModMalloc(1,ModWords); #if (MOD_BITS==256) /* 256 bits */ HexStr2Mod(Prime,"CF00000000000000000000000000000000000000000000000000000000000001",ModWords); /* 207*2^248+1 */ HexStr2Mod(PrimvRoot,"5",ModWords); /* primitive root=5 */ #elif (MOD_BITS==254) /* 254 bits */ HexStr2Mod(Prime,"4083000000000000000000000000000000000000000000000000000000000001",ModWords); /* 16515*2^240+1 */ HexStr2Mod(PrimvRoot,"d",ModWords); /* primitive root=13 */ #elif (MOD_BITS==253) /* 253 bits */ HexStr2Mod(Prime,"1FE00000000000000000000000000000000000000000000000000000000001",ModWords); /* 255*2^237+1 */ HexStr2Mod(PrimvRoot,"13",ModWords); /* primitive root=19 (0x13) */ #elif (MOD_BITS==64) /* 64 bits */ HexStr2Mod(Prime,"ffffffff00000001",ModWords); /* 18446742974197923841 */ HexStr2Mod(PrimvRoot,"7",ModWords); #else #error Unknown number of MOD_BITS #endif } void DeInitFFT(unsigned long int Len) { ModFree(NTTNum1); ModFree(NTTNum2); ModFree(Prime); ModFree(PrimvRoot); ModFree(MulInv); DeInitModMath(); }