]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cryptkit/lib/giantFFT.c
1 /* Copyright (c) 1998,2011,2014 Apple 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, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
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
19 Split off from NSGiantIntegers.c.
24 * FIXME - make sure platform-specific math lib has floor(), fmod(),
28 #include "NSGiantIntegers.h"
34 #define TWOPI (double)(2*3.1415926535897932384626433)
35 #define SQRT2 (double)(1.414213562373095048801688724209)
36 #define SQRTHALF (double)(0.707106781186547524400844362104)
37 #define TWO16 (double)(65536.0)
38 #define TWOM16 (double)(0.0000152587890625)
39 #define BREAK_SHORTS 400 // Number of shorts at which FFT breaks over.
41 static int lpt(int n
, int *lambda
);
42 static void mul_hermitian(double *a
, double *b
, int n
) ;
43 static void square_hermitian(double *b
, int n
);
44 static void addsignal(giant x
, double *zs
, int n
);
45 static void scramble_real(double *x
, int n
);
46 static void fft_real_to_hermitian(double *zs
, int n
);
47 static void fftinv_hermitian_to_real(double *zs
, int n
);
48 static void GiantFFTSquare(giant gx
);
49 static void GiantFFTMul(giant
,giant
);
50 static void giant_to_double(giant x
, int sizex
, double *zs
, int L
);
52 static int mulmode
= AUTO_MUL
;
54 void mulg(giant a
, giant b
) { /* b becomes a*b. */
59 (void)bitlen(b
); // XXX
65 static void GiantAuxMul(giant a
, giant b
) {
66 /* Optimized general multiply, b becomes a*b. Modes are:
67 AUTO_MUL: switch according to empirical speed criteria.
68 GRAMMAR_MUL: force grammar-school algorithm.
69 FFT_MUL: force floating point FFT method.
73 if (isZero(b
)) return;
95 grammartime
= sizea
; grammartime
*= sizeb
;
96 if(grammartime
< BREAK_SHORTS
*BREAK_SHORTS
) {
100 if (square
) GiantFFTSquare(b
);
101 else GiantFFTMul(a
,b
);
108 /***************** Commence FFT multiply routines ****************/
110 static int CurrentRun
= 0;
111 double *sincos
= NULL
;
112 static void init_sincos(int n
) {
116 if (n
<= CurrentRun
) return;
118 if (sincos
) free(sincos
);
119 sincos
= (double *)malloc(sizeof(double)*(1+(n
>>2)));
120 for(j
=0;j
<=(n
>>2);j
++) {
121 sincos
[j
] = sin(e
*j
);
125 static double s_sin(int n
) {
126 int seg
= n
/(CurrentRun
>>2);
129 case 0: return(sincos
[n
]);
130 case 1: return(sincos
[(CurrentRun
>>1)-n
]);
131 case 2: return(-sincos
[n
-(CurrentRun
>>1)]);
133 default: return(-sincos
[CurrentRun
-n
]);
137 static double s_cos(int n
) {
138 int quart
= (CurrentRun
>>2);
140 if (n
< quart
) return(s_sin(n
+quart
));
141 return(-s_sin(n
-quart
));
145 static int lpt(int n
, int *lambda
) {
146 /* returns least power of two greater than n */
157 static void addsignal(giant x
, double *zs
, int n
) {
158 register int j
, k
, m
, car
;
159 register double f
, g
;
160 /*double err, maxerr = 0.0;*/
163 f
= floor(zs
[j
]+0.5);
165 /* err = fabs(zs[j]-f);
166 if(err>maxerr) maxerr = err;
173 zs
[j
+k
] += f
-g
*TWO16
;
181 x
->n
[j
] = m
& 0xffff;
184 if(car
) x
->n
[j
] = car
;
186 while(!(x
->n
[j
])) --j
;
188 if (abs(x
->sign
) > x
->capacity
) NSGiantRaise("addsignal overflow");
191 static void GiantFFTSquare(giant gx
) {
192 int j
,size
= abs(gx
->sign
);
195 if(size
<4) { GiantGrammarMul(gx
,gx
); return; }
196 L
= lpt(size
+size
, &j
);
198 //was...double doubles[L];
200 double *doubles
= malloc(sizeof(double) * L
);
202 giant_to_double(gx
, size
, doubles
, L
);
203 fft_real_to_hermitian(doubles
, L
);
204 square_hermitian(doubles
, L
);
205 fftinv_hermitian_to_real(doubles
, L
);
206 addsignal(gx
, doubles
, L
);
210 gx
->sign
= abs(gx
->sign
);
212 if (abs(gx
->sign
) > gx
->capacity
) NSGiantRaise("GiantFFTSquare overflow");
215 static void GiantFFTMul(giant y
, giant x
) { /* x becomes y*x. */
216 int lambda
, size
, sizex
= abs(x
->sign
), sizey
= abs(y
->sign
);
217 int finalsign
= gsign(x
)*gsign(y
);
220 if((sizex
<=4)||(sizey
<=4)) { GiantGrammarMul(y
,x
); return; }
221 size
= sizex
; if(size
<sizey
) size
=sizey
;
222 L
= lpt(size
+size
, &lambda
);
224 //double doubles1[L];
225 //double doubles2[L];
226 double *doubles1
= malloc(sizeof(double) * L
);
227 double *doubles2
= malloc(sizeof(double) * L
);
229 giant_to_double(x
, sizex
, doubles1
, L
);
230 giant_to_double(y
, sizey
, doubles2
, L
);
231 fft_real_to_hermitian(doubles1
, L
);
232 fft_real_to_hermitian(doubles2
, L
);
233 mul_hermitian(doubles2
, doubles1
, L
);
234 fftinv_hermitian_to_real(doubles1
, L
);
235 addsignal(x
, doubles1
, L
);
240 x
->sign
= finalsign
*abs(x
->sign
);
242 if (abs(x
->sign
) > x
->capacity
) NSGiantRaise("GiantFFTMul overflow");
245 static void scramble_real(double *x
, int n
) {
249 for(i
=0,j
=0;i
<n
-1;i
++) {
264 static void fft_real_to_hermitian(double *zs
, int n
) {
265 /* Output is {Re(z^[0]),...,Re(z^[n/2),Im(z^[n/2-1]),...,Im(z^[1]).
266 This is a decimation-in-time, split-radix algorithm.
268 register double cc1
, ss1
, cc3
, ss3
;
269 register int is
, iD
, i0
, i1
, i2
, i3
, i4
, i5
, i6
, i7
, i8
,
270 a
, a3
, b
, b3
, nminus
= n
-1, dil
, expand
;
271 register double *x
, e
;
273 double t1
, t2
, t3
, t4
, t5
, t6
;
274 register int n2
, n4
, n8
, i
, j
;
277 expand
= CurrentRun
/n
;
278 scramble_real(zs
, n
);
279 x
= zs
-1; /* FORTRAN compatibility. */
283 for(i0
=is
;i0
<=n
;i0
+=iD
) {
300 for(i
=is
;i
<n
;i
+=iD
) {
314 t1
= (x
[i3
]+x
[i4
])*SQRTHALF
;
315 t2
= (x
[i3
]-x
[i4
])*SQRTHALF
;
327 a3
= (a
+(a
<<1))&nminus
;
338 for(i
=is
;i
<n
;i
+=iD
) {
347 t1
= x
[i3
]*cc1
+ x
[i7
]*ss1
;
348 t2
= x
[i7
]*cc1
- x
[i3
]*ss1
;
349 t3
= x
[i4
]*cc3
+ x
[i8
]*ss3
;
350 t4
= x
[i8
]*cc3
- x
[i4
]*ss3
;
375 static void fftinv_hermitian_to_real(double *zs
, int n
) {
376 /* Input is {Re(z^[0]),...,Re(z^[n/2),Im(z^[n/2-1]),...,Im(z^[1]).
377 This is a decimation-in-frequency, split-radix algorithm.
379 register double cc1
, ss1
, cc3
, ss3
;
380 register int is
, iD
, i0
, i1
, i2
, i3
, i4
, i5
, i6
, i7
, i8
,
381 a
, a3
, b
, b3
, nminus
= n
-1, dil
, expand
;
382 register double *x
, e
;
384 double t1
, t2
, t3
, t4
, t5
;
385 int n2
, n4
, n8
, i
, j
;
388 expand
= CurrentRun
/n
;
398 for(i
=is
;i
<n
;i
+=iD
) {
406 x
[i3
] = t1
- 2.0*x
[i4
];
407 x
[i4
] = t1
+ 2.0*x
[i4
];
413 t1
= (x
[i2
]-x
[i1
])*SQRTHALF
;
414 t2
= (x
[i4
]+x
[i3
])*SQRTHALF
;
417 x
[i3
] = -2.0*(t2
+t1
);
426 a3
= (a
+(a
<<1))&nminus
;
437 for(i
=is
;i
<n
;i
+=iD
) {
451 x
[i6
] = x
[i8
] - x
[i3
];
453 x
[i2
] = x
[i4
] - x
[i7
];
458 x
[i3
] = t5
*cc1
+ t4
*ss1
;
459 x
[i7
] = -t4
*cc1
+ t5
*ss1
;
460 x
[i4
] = t1
*cc3
- t2
*ss3
;
461 x
[i8
] = t2
*cc3
+ t1
*ss3
;
471 for(i0
=is
;i0
<=n
;i0
+=iD
){
480 scramble_real(zs
, n
);
482 for(i
=0;i
<n
;i
++) zs
[i
] *= e
;
486 static void mul_hermitian(double *a
, double *b
, int n
) {
487 register int k
, half
= n
>>1;
488 register double aa
, bb
, am
, bm
;
492 for(k
=1;k
<half
;k
++) {
493 aa
= a
[k
]; bb
= b
[k
];
494 am
= a
[n
-k
]; bm
= b
[n
-k
];
495 b
[k
] = aa
*bb
- am
*bm
;
496 b
[n
-k
] = aa
*bm
+ am
*bb
;
500 static void square_hermitian(double *b
, int n
) {
501 register int k
, half
= n
>>1;
502 register double c
, d
;
506 for(k
=1;k
<half
;k
++) {
507 c
= b
[k
]; d
= b
[n
-k
];
513 static void giant_to_double(giant x
, int sizex
, double *zs
, int L
) {
515 for(j
=sizex
;j
<L
;j
++) zs
[j
]=0.0;
516 for(j
=0;j
<sizex
;j
++) {