]>
git.saurik.com Git - apple/security.git/blob - libsecurity_cryptkit/lib/giantFFT.c
1 /* Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
12 Library for large-integer arithmetic via FFT. Currently unused
15 R. E. Crandall, Scientific Computation Group, NeXT Computer, Inc.
19 19 Jan 1998 Doug Mitchell at Apple
20 Split off from NSGiantIntegers.c.
25 * FIXME - make sure platform-specific math lib has floor(), fmod(),
29 #include "NSGiantIntegers.h"
35 #define TWOPI (double)(2*3.1415926535897932384626433)
36 #define SQRT2 (double)(1.414213562373095048801688724209)
37 #define SQRTHALF (double)(0.707106781186547524400844362104)
38 #define TWO16 (double)(65536.0)
39 #define TWOM16 (double)(0.0000152587890625)
40 #define BREAK_SHORTS 400 // Number of shorts at which FFT breaks over.
42 static int lpt(int n
, int *lambda
);
43 static void mul_hermitian(double *a
, double *b
, int n
) ;
44 static void square_hermitian(double *b
, int n
);
45 static void addsignal(giant x
, double *zs
, int n
);
46 static void scramble_real(double *x
, int n
);
47 static void fft_real_to_hermitian(double *zs
, int n
);
48 static void fftinv_hermitian_to_real(double *zs
, int n
);
49 static void GiantFFTSquare(giant gx
);
50 static void GiantFFTMul(giant
,giant
);
51 static void giant_to_double(giant x
, int sizex
, double *zs
, int L
);
53 static int mulmode
= AUTO_MUL
;
55 void mulg(giant a
, giant b
) { /* b becomes a*b. */
60 (void)bitlen(b
); // XXX
66 static void GiantAuxMul(giant a
, giant b
) {
67 /* Optimized general multiply, b becomes a*b. Modes are:
68 AUTO_MUL: switch according to empirical speed criteria.
69 GRAMMAR_MUL: force grammar-school algorithm.
70 FFT_MUL: force floating point FFT method.
74 if (isZero(b
)) return;
96 grammartime
= sizea
; grammartime
*= sizeb
;
97 if(grammartime
< BREAK_SHORTS
*BREAK_SHORTS
) {
101 if (square
) GiantFFTSquare(b
);
102 else GiantFFTMul(a
,b
);
109 /***************** Commence FFT multiply routines ****************/
111 static int CurrentRun
= 0;
112 double *sincos
= NULL
;
113 static void init_sincos(int n
) {
117 if (n
<= CurrentRun
) return;
119 if (sincos
) free(sincos
);
120 sincos
= (double *)malloc(sizeof(double)*(1+(n
>>2)));
121 for(j
=0;j
<=(n
>>2);j
++) {
122 sincos
[j
] = sin(e
*j
);
126 static double s_sin(int n
) {
127 int seg
= n
/(CurrentRun
>>2);
130 case 0: return(sincos
[n
]);
131 case 1: return(sincos
[(CurrentRun
>>1)-n
]);
132 case 2: return(-sincos
[n
-(CurrentRun
>>1)]);
134 default: return(-sincos
[CurrentRun
-n
]);
138 static double s_cos(int n
) {
139 int quart
= (CurrentRun
>>2);
141 if (n
< quart
) return(s_sin(n
+quart
));
142 return(-s_sin(n
-quart
));
146 static int lpt(int n
, int *lambda
) {
147 /* returns least power of two greater than n */
158 static void addsignal(giant x
, double *zs
, int n
) {
159 register int j
, k
, m
, car
;
160 register double f
, g
;
161 /*double err, maxerr = 0.0;*/
164 f
= floor(zs
[j
]+0.5);
166 /* err = fabs(zs[j]-f);
167 if(err>maxerr) maxerr = err;
174 zs
[j
+k
] += f
-g
*TWO16
;
182 x
->n
[j
] = m
& 0xffff;
185 if(car
) x
->n
[j
] = car
;
187 while(!(x
->n
[j
])) --j
;
189 if (abs(x
->sign
) > x
->capacity
) NSGiantRaise("addsignal overflow");
192 static void GiantFFTSquare(giant gx
) {
193 int j
,size
= abs(gx
->sign
);
196 if(size
<4) { GiantGrammarMul(gx
,gx
); return; }
197 L
= lpt(size
+size
, &j
);
199 //was...double doubles[L];
201 double *doubles
= malloc(sizeof(double) * L
);
203 giant_to_double(gx
, size
, doubles
, L
);
204 fft_real_to_hermitian(doubles
, L
);
205 square_hermitian(doubles
, L
);
206 fftinv_hermitian_to_real(doubles
, L
);
207 addsignal(gx
, doubles
, L
);
211 gx
->sign
= abs(gx
->sign
);
213 if (abs(gx
->sign
) > gx
->capacity
) NSGiantRaise("GiantFFTSquare overflow");
216 static void GiantFFTMul(giant y
, giant x
) { /* x becomes y*x. */
217 int lambda
, size
, sizex
= abs(x
->sign
), sizey
= abs(y
->sign
);
218 int finalsign
= gsign(x
)*gsign(y
);
221 if((sizex
<=4)||(sizey
<=4)) { GiantGrammarMul(y
,x
); return; }
222 size
= sizex
; if(size
<sizey
) size
=sizey
;
223 L
= lpt(size
+size
, &lambda
);
225 //double doubles1[L];
226 //double doubles2[L];
227 double *doubles1
= malloc(sizeof(double) * L
);
228 double *doubles2
= malloc(sizeof(double) * L
);
230 giant_to_double(x
, sizex
, doubles1
, L
);
231 giant_to_double(y
, sizey
, doubles2
, L
);
232 fft_real_to_hermitian(doubles1
, L
);
233 fft_real_to_hermitian(doubles2
, L
);
234 mul_hermitian(doubles2
, doubles1
, L
);
235 fftinv_hermitian_to_real(doubles1
, L
);
236 addsignal(x
, doubles1
, L
);
241 x
->sign
= finalsign
*abs(x
->sign
);
243 if (abs(x
->sign
) > x
->capacity
) NSGiantRaise("GiantFFTMul overflow");
246 static void scramble_real(double *x
, int n
) {
250 for(i
=0,j
=0;i
<n
-1;i
++) {
265 static void fft_real_to_hermitian(double *zs
, int n
) {
266 /* Output is {Re(z^[0]),...,Re(z^[n/2),Im(z^[n/2-1]),...,Im(z^[1]).
267 This is a decimation-in-time, split-radix algorithm.
269 register double cc1
, ss1
, cc3
, ss3
;
270 register int is
, iD
, i0
, i1
, i2
, i3
, i4
, i5
, i6
, i7
, i8
,
271 a
, a3
, b
, b3
, nminus
= n
-1, dil
, expand
;
272 register double *x
, e
;
274 double t1
, t2
, t3
, t4
, t5
, t6
;
275 register int n2
, n4
, n8
, i
, j
;
278 expand
= CurrentRun
/n
;
279 scramble_real(zs
, n
);
280 x
= zs
-1; /* FORTRAN compatibility. */
284 for(i0
=is
;i0
<=n
;i0
+=iD
) {
301 for(i
=is
;i
<n
;i
+=iD
) {
315 t1
= (x
[i3
]+x
[i4
])*SQRTHALF
;
316 t2
= (x
[i3
]-x
[i4
])*SQRTHALF
;
328 a3
= (a
+(a
<<1))&nminus
;
339 for(i
=is
;i
<n
;i
+=iD
) {
348 t1
= x
[i3
]*cc1
+ x
[i7
]*ss1
;
349 t2
= x
[i7
]*cc1
- x
[i3
]*ss1
;
350 t3
= x
[i4
]*cc3
+ x
[i8
]*ss3
;
351 t4
= x
[i8
]*cc3
- x
[i4
]*ss3
;
376 static void fftinv_hermitian_to_real(double *zs
, int n
) {
377 /* Input is {Re(z^[0]),...,Re(z^[n/2),Im(z^[n/2-1]),...,Im(z^[1]).
378 This is a decimation-in-frequency, split-radix algorithm.
380 register double cc1
, ss1
, cc3
, ss3
;
381 register int is
, iD
, i0
, i1
, i2
, i3
, i4
, i5
, i6
, i7
, i8
,
382 a
, a3
, b
, b3
, nminus
= n
-1, dil
, expand
;
383 register double *x
, e
;
385 double t1
, t2
, t3
, t4
, t5
;
386 int n2
, n4
, n8
, i
, j
;
389 expand
= CurrentRun
/n
;
399 for(i
=is
;i
<n
;i
+=iD
) {
407 x
[i3
] = t1
- 2.0*x
[i4
];
408 x
[i4
] = t1
+ 2.0*x
[i4
];
414 t1
= (x
[i2
]-x
[i1
])*SQRTHALF
;
415 t2
= (x
[i4
]+x
[i3
])*SQRTHALF
;
418 x
[i3
] = -2.0*(t2
+t1
);
427 a3
= (a
+(a
<<1))&nminus
;
438 for(i
=is
;i
<n
;i
+=iD
) {
452 x
[i6
] = x
[i8
] - x
[i3
];
454 x
[i2
] = x
[i4
] - x
[i7
];
459 x
[i3
] = t5
*cc1
+ t4
*ss1
;
460 x
[i7
] = -t4
*cc1
+ t5
*ss1
;
461 x
[i4
] = t1
*cc3
- t2
*ss3
;
462 x
[i8
] = t2
*cc3
+ t1
*ss3
;
472 for(i0
=is
;i0
<=n
;i0
+=iD
){
481 scramble_real(zs
, n
);
483 for(i
=0;i
<n
;i
++) zs
[i
] *= e
;
487 static void mul_hermitian(double *a
, double *b
, int n
) {
488 register int k
, half
= n
>>1;
489 register double aa
, bb
, am
, bm
;
493 for(k
=1;k
<half
;k
++) {
494 aa
= a
[k
]; bb
= b
[k
];
495 am
= a
[n
-k
]; bm
= b
[n
-k
];
496 b
[k
] = aa
*bb
- am
*bm
;
497 b
[n
-k
] = aa
*bm
+ am
*bb
;
501 static void square_hermitian(double *b
, int n
) {
502 register int k
, half
= n
>>1;
503 register double c
, d
;
507 for(k
=1;k
<half
;k
++) {
508 c
= b
[k
]; d
= b
[n
-k
];
514 static void giant_to_double(giant x
, int sizex
, double *zs
, int L
) {
516 for(j
=sizex
;j
<L
;j
++) zs
[j
]=0.0;
517 for(j
=0;j
<sizex
;j
++) {