More CVS ignore stuff...
[openssl.git] / crypto / bn / bn_mulw.c
1 /* crypto/bn/bn_mulw.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include "bn_lcl.h"
62
63 #ifdef BN_LLONG 
64
65 BN_ULONG bn_mul_add_words(rp,ap,num,w)
66 BN_ULONG *rp,*ap;
67 int num;
68 BN_ULONG w;
69         {
70         BN_ULONG c1=0;
71
72         for (;;)
73                 {
74                 mul_add(rp[0],ap[0],w,c1);
75                 if (--num == 0) break;
76                 mul_add(rp[1],ap[1],w,c1);
77                 if (--num == 0) break;
78                 mul_add(rp[2],ap[2],w,c1);
79                 if (--num == 0) break;
80                 mul_add(rp[3],ap[3],w,c1);
81                 if (--num == 0) break;
82                 ap+=4;
83                 rp+=4;
84                 }
85         
86         return(c1);
87         } 
88
89 BN_ULONG bn_mul_words(rp,ap,num,w)
90 BN_ULONG *rp,*ap;
91 int num;
92 BN_ULONG w;
93         {
94         BN_ULONG c1=0;
95
96         for (;;)
97                 {
98                 mul(rp[0],ap[0],w,c1);
99                 if (--num == 0) break;
100                 mul(rp[1],ap[1],w,c1);
101                 if (--num == 0) break;
102                 mul(rp[2],ap[2],w,c1);
103                 if (--num == 0) break;
104                 mul(rp[3],ap[3],w,c1);
105                 if (--num == 0) break;
106                 ap+=4;
107                 rp+=4;
108                 }
109         return(c1);
110         } 
111
112 void bn_sqr_words(r,a,n)
113 BN_ULONG *r,*a;
114 int n;
115         {
116         for (;;)
117                 {
118                 BN_ULLONG t;
119
120                 t=(BN_ULLONG)(a[0])*(a[0]);
121                 r[0]=Lw(t); r[1]=Hw(t);
122                 if (--n == 0) break;
123
124                 t=(BN_ULLONG)(a[1])*(a[1]);
125                 r[2]=Lw(t); r[3]=Hw(t);
126                 if (--n == 0) break;
127
128                 t=(BN_ULLONG)(a[2])*(a[2]);
129                 r[4]=Lw(t); r[5]=Hw(t);
130                 if (--n == 0) break;
131
132                 t=(BN_ULLONG)(a[3])*(a[3]);
133                 r[6]=Lw(t); r[7]=Hw(t);
134                 if (--n == 0) break;
135
136                 a+=4;
137                 r+=8;
138                 }
139         }
140
141 BN_ULONG bn_add_words(r,a,b,n)
142 BN_ULONG *r,*a,*b;
143 int n;
144         {
145         BN_ULLONG ll;
146
147         ll=0;
148         for (;;)
149                 {
150                 ll+= (BN_ULLONG)a[0]+b[0];
151                 r[0]=(BN_ULONG)ll&BN_MASK2;
152                 ll>>=BN_BITS2;
153                 if (--n <= 0) break;
154
155                 ll+= (BN_ULLONG)a[1]+b[1];
156                 r[1]=(BN_ULONG)ll&BN_MASK2;
157                 ll>>=BN_BITS2;
158                 if (--n <= 0) break;
159
160                 ll+= (BN_ULLONG)a[2]+b[2];
161                 r[2]=(BN_ULONG)ll&BN_MASK2;
162                 ll>>=BN_BITS2;
163                 if (--n <= 0) break;
164
165                 ll+= (BN_ULLONG)a[3]+b[3];
166                 r[3]=(BN_ULONG)ll&BN_MASK2;
167                 ll>>=BN_BITS2;
168                 if (--n <= 0) break;
169
170                 a+=4;
171                 b+=4;
172                 r+=4;
173                 }
174         return(ll&BN_MASK2);
175         }
176
177 #else
178
179 BN_ULONG bn_mul_add_words(rp,ap,num,w)
180 BN_ULONG *rp,*ap;
181 int num;
182 BN_ULONG w;
183         {
184         BN_ULONG c=0;
185         BN_ULONG bl,bh;
186
187         bl=LBITS(w);
188         bh=HBITS(w);
189
190         for (;;)
191                 {
192                 mul_add(rp[0],ap[0],bl,bh,c);
193                 if (--num == 0) break;
194                 mul_add(rp[1],ap[1],bl,bh,c);
195                 if (--num == 0) break;
196                 mul_add(rp[2],ap[2],bl,bh,c);
197                 if (--num == 0) break;
198                 mul_add(rp[3],ap[3],bl,bh,c);
199                 if (--num == 0) break;
200                 ap+=4;
201                 rp+=4;
202                 }
203         return(c);
204         } 
205
206 BN_ULONG bn_mul_words(rp,ap,num,w)
207 BN_ULONG *rp,*ap;
208 int num;
209 BN_ULONG w;
210         {
211         BN_ULONG carry=0;
212         BN_ULONG bl,bh;
213
214         bl=LBITS(w);
215         bh=HBITS(w);
216
217         for (;;)
218                 {
219                 mul(rp[0],ap[0],bl,bh,carry);
220                 if (--num == 0) break;
221                 mul(rp[1],ap[1],bl,bh,carry);
222                 if (--num == 0) break;
223                 mul(rp[2],ap[2],bl,bh,carry);
224                 if (--num == 0) break;
225                 mul(rp[3],ap[3],bl,bh,carry);
226                 if (--num == 0) break;
227                 ap+=4;
228                 rp+=4;
229                 }
230         return(carry);
231         } 
232
233 void bn_sqr_words(r,a,n)
234 BN_ULONG *r,*a;
235 int n;
236         {
237         for (;;)
238                 {
239                 sqr64(r[0],r[1],a[0]);
240                 if (--n == 0) break;
241
242                 sqr64(r[2],r[3],a[1]);
243                 if (--n == 0) break;
244
245                 sqr64(r[4],r[5],a[2]);
246                 if (--n == 0) break;
247
248                 sqr64(r[6],r[7],a[3]);
249                 if (--n == 0) break;
250
251                 a+=4;
252                 r+=8;
253                 }
254         }
255
256 BN_ULONG bn_add_words(r,a,b,n)
257 BN_ULONG *r,*a,*b;
258 int n;
259         {
260         BN_ULONG t1,t2;
261         int carry,i;
262
263         carry=0;
264         for (i=0; i<n; i++)
265                 {
266                 t1= *(a++);
267                 t2= *(b++);
268                 if (carry)
269                         {
270                         carry=(t2 >= ((~t1)&BN_MASK2));
271                         t2=(t1+t2+1)&BN_MASK2;
272                         }
273                 else
274                         {
275                         t2=(t1+t2)&BN_MASK2;
276                         carry=(t2<t1);
277                         }
278                 *(r++)=t2;
279                 }
280         return(carry);
281         }
282
283 #endif
284
285 #if defined(BN_LLONG) && defined(BN_DIV2W)
286
287 BN_ULONG bn_div64(h,l,d)
288 BN_ULONG h,l,d;
289         {
290         return((BN_ULONG)(((((BN_ULLONG)h)<<BN_BITS2)|l)/(BN_ULLONG)d));
291         }
292
293 #else
294
295 /* Divide h-l by d and return the result. */
296 /* I need to test this some more :-( */
297 BN_ULONG bn_div64(h,l,d)
298 BN_ULONG h,l,d;
299         {
300         BN_ULONG dh,dl,q,ret=0,th,tl,t;
301         int i,count=2;
302
303         if (d == 0) return(BN_MASK2);
304
305         i=BN_num_bits_word(d);
306         if ((i != BN_BITS2) && (h > (BN_ULONG)1<<i))
307                 {
308 #if !defined(NO_STDIO) && !defined(WIN16)
309                 fprintf(stderr,"Division would overflow (%d)\n",i);
310 #endif
311                 abort();
312                 }
313         i=BN_BITS2-i;
314         if (h >= d) h-=d;
315
316         if (i)
317                 {
318                 d<<=i;
319                 h=(h<<i)|(l>>(BN_BITS2-i));
320                 l<<=i;
321                 }
322         dh=(d&BN_MASK2h)>>BN_BITS4;
323         dl=(d&BN_MASK2l);
324         for (;;)
325                 {
326                 if ((h>>BN_BITS4) == dh)
327                         q=BN_MASK2l;
328                 else
329                         q=h/dh;
330
331                 for (;;)
332                         {
333                         t=(h-q*dh);
334                         if ((t&BN_MASK2h) ||
335                                 ((dl*q) <= (
336                                         (t<<BN_BITS4)+
337                                         ((l&BN_MASK2h)>>BN_BITS4))))
338                                 break;
339                         q--;
340                         }
341                 th=q*dh;
342                 tl=q*dl;
343                 t=(tl>>BN_BITS4);
344                 tl=(tl<<BN_BITS4)&BN_MASK2h;
345                 th+=t;
346
347                 if (l < tl) th++;
348                 l-=tl;
349                 if (h < th)
350                         {
351                         h+=d;
352                         q--;
353                         }
354                 h-=th;
355
356                 if (--count == 0) break;
357
358                 ret=q<<BN_BITS4;
359                 h=((h<<BN_BITS4)|(l>>BN_BITS4))&BN_MASK2;
360                 l=(l&BN_MASK2l)<<BN_BITS4;
361                 }
362         ret|=q;
363         return(ret);
364         }
365 #endif
366