[gbx] - fix ccc->gbox reshare
[oscam.git] / cscrypt / bn_lib.c
blob5210643bf0add8fd8c69b0750719d68440462418
1 #include "bn.h"
3 #ifndef WITH_LIBCRYPTO
4 //FIXME Not checked on threadsafety yet; after checking please remove this line
5 /* crypto/bn/bn_lib.c */
6 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
7 * All rights reserved.
9 * This package is an SSL implementation written
10 * by Eric Young (eay@cryptsoft.com).
11 * The implementation was written so as to conform with Netscapes SSL.
13 * This library is free for commercial and non-commercial use as long as
14 * the following conditions are aheared to. The following conditions
15 * apply to all code found in this distribution, be it the RC4, RSA,
16 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
17 * included with this distribution is covered by the same copyright terms
18 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
20 * Copyright remains Eric Young's, and as such any Copyright notices in
21 * the code are not to be removed.
22 * If this package is used in a product, Eric Young should be given attribution
23 * as the author of the parts of the library used.
24 * This can be in the form of a textual message at program startup or
25 * in documentation (online or textual) provided with the package.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * "This product includes cryptographic software written by
38 * Eric Young (eay@cryptsoft.com)"
39 * The word 'cryptographic' can be left out if the rouines from the library
40 * being used are not cryptographic related :-).
41 * 4. If you include any Windows specific code (or a derivative thereof) from
42 * the apps directory (application code) you must include an acknowledgement:
43 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
45 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
57 * The license and distribution terms for any publically available version or
58 * derivative of this code cannot be changed. i.e. this code cannot simply be
59 * copied and put under another distribution license
60 * [including the GNU Public License.]
63 #ifndef BN_DEBUG
64 # undef NDEBUG /* avoid conflicting definitions */
65 # define NDEBUG
66 #endif
68 #include <string.h>
69 #include <assert.h>
70 #include <limits.h>
71 #include <stdio.h>
72 #include "bn_lcl.h"
73 #include "openssl_mods.h"
75 //const char *BN_version="Big Number 42";
77 /* For a 32 bit machine
78 * 2 - 4 == 128
79 * 3 - 8 == 256
80 * 4 - 16 == 512
81 * 5 - 32 == 1024
82 * 6 - 64 == 2048
83 * 7 - 128 == 4096
84 * 8 - 256 == 8192
86 static int bn_limit_bits = 0;
87 static int bn_limit_num = 8; /* (1<<bn_limit_bits) */
88 static int bn_limit_bits_low = 0;
89 static int bn_limit_num_low = 8; /* (1<<bn_limit_bits_low) */
90 static int bn_limit_bits_high = 0;
91 static int bn_limit_num_high = 8; /* (1<<bn_limit_bits_high) */
92 static int bn_limit_bits_mont = 0;
93 static int bn_limit_num_mont = 8; /* (1<<bn_limit_bits_mont) */
95 void BN_set_params(int mult, int high, int low, int mont)
97 if(mult >= 0)
99 if(mult > (int)(sizeof(int) * 8) - 1)
100 { mult = sizeof(int) * 8 - 1; }
101 bn_limit_bits = mult;
102 bn_limit_num = 1 << mult;
104 if(high >= 0)
106 if(high > (int)(sizeof(int) * 8) - 1)
107 { high = sizeof(int) * 8 - 1; }
108 bn_limit_bits_high = high;
109 bn_limit_num_high = 1 << high;
111 if(low >= 0)
113 if(low > (int)(sizeof(int) * 8) - 1)
114 { low = sizeof(int) * 8 - 1; }
115 bn_limit_bits_low = low;
116 bn_limit_num_low = 1 << low;
118 if(mont >= 0)
120 if(mont > (int)(sizeof(int) * 8) - 1)
121 { mont = sizeof(int) * 8 - 1; }
122 bn_limit_bits_mont = mont;
123 bn_limit_num_mont = 1 << mont;
127 int BN_get_params(int which)
129 if(which == 0) { return (bn_limit_bits); }
130 else if(which == 1) { return (bn_limit_bits_high); }
131 else if(which == 2) { return (bn_limit_bits_low); }
132 else if(which == 3) { return (bn_limit_bits_mont); }
133 else { return (0); }
136 const BIGNUM *BN_value_one(void)
138 static const BN_ULONG data_one = 1L;
139 static const BIGNUM const_one = {(BN_ULONG *) &data_one, 1, 1, 0, BN_FLG_STATIC_DATA};
141 return (&const_one);
144 char *BN_options(void)
146 static int init = 0;
147 static char data[16];
149 if(!init)
151 init++;
152 #ifdef BN_LLONG
153 snprintf(data, sizeof(data), "bn(%d,%d)", (int)sizeof(BN_ULLONG) * 8,
154 (int)sizeof(BN_ULONG) * 8);
155 #else
156 snprintf(data, sizeof(data), "bn(%d,%d)", (int)sizeof(BN_ULONG) * 8,
157 (int)sizeof(BN_ULONG) * 8);
158 #endif
160 return (data);
163 int BN_num_bits_word(BN_ULONG l)
165 static const char bits[256] =
167 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
168 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
169 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
170 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
171 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
172 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
173 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
174 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
175 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
176 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
177 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
178 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
179 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
180 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
181 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
182 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
185 #if defined(SIXTY_FOUR_BIT_LONG)
186 if(l & 0xffffffff00000000L)
188 if(l & 0xffff000000000000L)
190 if(l & 0xff00000000000000L)
192 return (bits[(int)(l >> 56)] + 56);
194 else { return (bits[(int)(l >> 48)] + 48); }
196 else
198 if(l & 0x0000ff0000000000L)
200 return (bits[(int)(l >> 40)] + 40);
202 else { return (bits[(int)(l >> 32)] + 32); }
205 else
206 #else
207 #ifdef SIXTY_FOUR_BIT
208 if(l & 0xffffffff00000000LL)
210 if(l & 0xffff000000000000LL)
212 if(l & 0xff00000000000000LL)
214 return (bits[(int)(l >> 56)] + 56);
216 else { return (bits[(int)(l >> 48)] + 48); }
218 else
220 if(l & 0x0000ff0000000000LL)
222 return (bits[(int)(l >> 40)] + 40);
224 else { return (bits[(int)(l >> 32)] + 32); }
227 else
228 #endif
229 #endif
231 #if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
232 if(l & 0xffff0000L)
234 if(l & 0xff000000L)
235 { return (bits[(int)(l >> 24L)] + 24); }
236 else { return (bits[(int)(l >> 16L)] + 16); }
238 else
239 #endif
241 #if defined(SIXTEEN_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
242 if(l & 0xff00L)
243 { return (bits[(int)(l >> 8)] + 8); }
244 else
245 #endif
246 return (bits[(int)(l)]);
251 int BN_num_bits(const BIGNUM *a)
253 BN_ULONG l;
254 int i;
256 bn_check_top(a);
258 if(a->top == 0) { return (0); }
259 l = a->d[a->top - 1];
260 assert(l != 0);
261 i = (a->top - 1) * BN_BITS2;
262 return (i + BN_num_bits_word(l));
265 void BN_clear_free(BIGNUM *a)
267 int i;
269 if(a == NULL) { return; }
270 if(a->d != NULL)
272 memset(a->d, 0, a->dmax * sizeof(a->d[0]));
273 if(!(BN_get_flags(a, BN_FLG_STATIC_DATA)))
274 { OPENSSL_free(a->d); }
276 i = BN_get_flags(a, BN_FLG_MALLOCED);
277 memset(a, 0, sizeof(BIGNUM));
278 if(i)
279 { OPENSSL_free(a); }
282 void BN_free(BIGNUM *a)
284 if(a == NULL) { return; }
285 if((a->d != NULL) && !(BN_get_flags(a, BN_FLG_STATIC_DATA)))
286 { OPENSSL_free(a->d); }
287 a->flags |= BN_FLG_FREE; /* REMOVE? */
288 if(a->flags & BN_FLG_MALLOCED)
289 { OPENSSL_free(a); }
292 void BN_init(BIGNUM *a)
294 memset(a, 0, sizeof(BIGNUM));
297 BIGNUM *BN_new(void)
299 BIGNUM *ret;
301 if((ret = (BIGNUM *)OPENSSL_malloc(sizeof(BIGNUM))) == NULL)
303 return (NULL);
305 ret->flags = BN_FLG_MALLOCED;
306 ret->top = 0;
307 ret->neg = 0;
308 ret->dmax = 0;
309 ret->d = NULL;
310 return (ret);
313 /* This is an internal function that should not be used in applications.
314 * It ensures that 'b' has enough room for a 'words' word number number.
315 * It is mostly used by the various BIGNUM routines. If there is an error,
316 * NULL is returned. If not, 'b' is returned. */
318 BIGNUM *bn_expand2(BIGNUM *b, int words)
320 BN_ULONG *A, *a;
321 const BN_ULONG *B;
322 int i;
324 bn_check_top(b);
326 if(words > b->dmax)
328 if(words > (INT_MAX / (4 * BN_BITS2)))
330 return NULL;
333 bn_check_top(b);
334 if(BN_get_flags(b, BN_FLG_STATIC_DATA))
336 return (NULL);
338 a = A = (BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG) * (words + 1));
339 if(A == NULL)
341 return (NULL);
343 #if 1
344 B = b->d;
345 /* Check if the previous number needs to be copied */
346 if(B != NULL)
348 #if 0
349 /* This lot is an unrolled loop to copy b->top
350 * BN_ULONGs from B to A
353 * I have nothing against unrolling but it's usually done for
354 * several reasons, namely:
355 * - minimize percentage of decision making code, i.e. branches;
356 * - avoid cache trashing;
357 * - make it possible to schedule loads earlier;
358 * Now let's examine the code below. The cornerstone of C is
359 * "programmer is always right" and that's what we love it for:-)
360 * For this very reason C compilers have to be paranoid when it
361 * comes to data aliasing and assume the worst. Yeah, but what
362 * does it mean in real life? This means that loop body below will
363 * be compiled to sequence of loads immediately followed by stores
364 * as compiler assumes the worst, something in A==B+1 style. As a
365 * result CPU pipeline is going to starve for incoming data. Secondly
366 * if A and B happen to share same cache line such code is going to
367 * cause severe cache trashing. Both factors have severe impact on
368 * performance of modern CPUs and this is the reason why this
369 * particular piece of code is #ifdefed away and replaced by more
370 * "friendly" version found in #else section below. This comment
371 * also applies to BN_copy function.
373 * <appro@fy.chalmers.se>
375 for(i = b->top & (~7); i > 0; i -= 8)
377 A[0] = B[0];
378 A[1] = B[1];
379 A[2] = B[2];
380 A[3] = B[3];
381 A[4] = B[4];
382 A[5] = B[5];
383 A[6] = B[6];
384 A[7] = B[7];
385 A += 8;
386 B += 8;
388 switch(b->top & 7)
390 case 7:
391 A[6] = B[6];
392 case 6:
393 A[5] = B[5];
394 case 5:
395 A[4] = B[4];
396 case 4:
397 A[3] = B[3];
398 case 3:
399 A[2] = B[2];
400 case 2:
401 A[1] = B[1];
402 case 1:
403 A[0] = B[0];
404 case 0:
405 /* I need the 'case 0' entry for utrix cc.
406 * If the optimizer is turned on, it does the
407 * switch table by doing
408 * a=top&7
409 * a--;
410 * goto jump_table[a];
411 * If top is 0, this makes us jump to 0xffffffc
412 * which is rather bad :-(.
413 * eric 23-Apr-1998
417 #else
418 for(i = b->top >> 2; i > 0; i--, A += 4, B += 4)
421 * The fact that the loop is unrolled
422 * 4-wise is a tribute to Intel. It's
423 * the one that doesn't have enough
424 * registers to accomodate more data.
425 * I'd unroll it 8-wise otherwise:-)
427 * <appro@fy.chalmers.se>
429 BN_ULONG a0, a1, a2, a3;
430 a0 = B[0];
431 a1 = B[1];
432 a2 = B[2];
433 a3 = B[3];
434 A[0] = a0;
435 A[1] = a1;
436 A[2] = a2;
437 A[3] = a3;
439 switch(b->top & 3)
441 case 3:
442 A[2] = B[2]; /* fallthrough */
443 case 2:
444 A[1] = B[1]; /* fallthrough */
445 case 1:
446 A[0] = B[0]; /* fallthrough */
447 case 0: ; /* ultrix cc workaround, see above */
449 #endif
450 OPENSSL_free(b->d);
453 b->d = a;
454 b->dmax = words;
456 /* Now need to zero any data between b->top and b->max */
458 A = &(b->d[b->top]);
459 for(i = (b->dmax - b->top) >> 3; i > 0; i--, A += 8)
461 A[0] = 0;
462 A[1] = 0;
463 A[2] = 0;
464 A[3] = 0;
465 A[4] = 0;
466 A[5] = 0;
467 A[6] = 0;
468 A[7] = 0;
470 for(i = (b->dmax - b->top) & 7; i > 0; i--, A++)
471 { A[0] = 0; }
472 #else
473 memset(A, 0, sizeof(BN_ULONG) * (words + 1));
474 memcpy(A, b->d, sizeof(b->d[0])*b->top);
475 b->d = a;
476 b->max = words;
477 #endif
479 /* memset(&(p[b->max]),0,((words+1)-b->max)*sizeof(BN_ULONG)); */
480 /* { int i; for (i=b->max; i<words+1; i++) p[i]=i;} */
483 return (b);
486 BIGNUM *BN_dup(const BIGNUM *a)
488 BIGNUM *r;
490 if(a == NULL) { return NULL; }
492 bn_check_top(a);
494 r = BN_new();
495 if(r == NULL) { return (NULL); }
496 return ((BIGNUM *)BN_copy(r, a));
499 BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
501 int i;
502 BN_ULONG *A;
503 const BN_ULONG *B;
505 bn_check_top(b);
507 if(a == b) { return (a); }
508 if(bn_wexpand(a, b->top) == NULL) { return (NULL); }
510 #if 1
511 A = a->d;
512 B = b->d;
513 for(i = b->top >> 2; i > 0; i--, A += 4, B += 4)
515 BN_ULONG a0, a1, a2, a3;
516 a0 = B[0];
517 a1 = B[1];
518 a2 = B[2];
519 a3 = B[3];
520 A[0] = a0;
521 A[1] = a1;
522 A[2] = a2;
523 A[3] = a3;
525 switch(b->top & 3)
527 case 3:
528 A[2] = B[2]; /* fallthrough */
529 case 2:
530 A[1] = B[1]; /* fallthrough */
531 case 1:
532 A[0] = B[0]; /* fallthrough */
533 case 0: ; /* ultrix cc workaround, see comments in bn_expand2 */
535 #else
536 memcpy(a->d, b->d, sizeof(b->d[0])*b->top);
537 #endif
539 /* memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top));*/
540 a->top = b->top;
541 if((a->top == 0) && (a->d != NULL))
542 { a->d[0] = 0; }
543 a->neg = b->neg;
544 return (a);
547 void BN_clear(BIGNUM *a)
549 if(a->d != NULL)
550 { memset(a->d, 0, a->dmax * sizeof(a->d[0])); }
551 a->top = 0;
552 a->neg = 0;
555 BN_ULONG BN_get_word(const BIGNUM *a)
557 if(a->top > 1)
558 { return BN_MASK2; }
559 else if(a->top == 1)
560 { return a->d[0]; }
561 /* a->top == 0 */
562 return 0;
565 int BN_set_word(BIGNUM *a, BN_ULONG w)
567 bn_check_top(a);
568 if(bn_expand(a, (int)sizeof(BN_ULONG) * 8) == NULL) { return (0); }
569 a->neg = 0;
570 a->d[0] = w;
571 a->top = (w ? 1 : 0);
572 bn_check_top(a);
573 return (1);
576 /* ignore negative */
577 BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
579 unsigned int i, m;
580 unsigned int n;
581 BN_ULONG l;
583 if(ret == NULL) { ret = BN_new(); }
584 if(ret == NULL) { return (NULL); }
585 l = 0;
586 n = len;
587 if(n == 0)
589 ret->top = 0;
590 return (ret);
592 if(bn_expand(ret, (int)(n + 2) * 8) == NULL)
593 { return (NULL); }
594 i = ((n - 1) / BN_BYTES) + 1;
595 m = ((n - 1) % (BN_BYTES));
596 ret->top = i;
597 while(n-- > 0)
599 l = (l << 8L) | *(s++);
600 if(m-- == 0)
602 ret->d[--i] = l;
603 l = 0;
604 m = BN_BYTES - 1;
607 /* need to call this due to clear byte at top if avoiding
608 * having the top bit set (-ve number) */
609 bn_fix_top(ret);
610 return (ret);
613 /* ignore negative */
614 int BN_bn2bin(const BIGNUM *a, unsigned char *to)
616 int n, i;
617 BN_ULONG l;
619 n = i = BN_num_bytes(a);
620 while(i-- > 0)
622 l = a->d[i / BN_BYTES];
623 *(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
625 return (n);
628 int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
630 int i;
631 BN_ULONG t1, t2, *ap, *bp;
633 bn_check_top(a);
634 bn_check_top(b);
636 i = a->top - b->top;
637 if(i != 0) { return (i); }
638 ap = a->d;
639 bp = b->d;
640 for(i = a->top - 1; i >= 0; i--)
642 t1 = ap[i];
643 t2 = bp[i];
644 if(t1 != t2)
645 { return (t1 > t2 ? 1 : -1); }
647 return (0);
650 int BN_cmp(const BIGNUM *a, const BIGNUM *b)
652 int i;
653 int gt, lt;
654 BN_ULONG t1, t2;
656 if((a == NULL) || (b == NULL))
658 if(a != NULL)
659 { return (-1); }
660 else if(b != NULL)
661 { return (1); }
662 else
663 { return (0); }
666 bn_check_top(a);
667 bn_check_top(b);
669 if(a->neg != b->neg)
671 if(a->neg)
672 { return (-1); }
673 else { return (1); }
675 if(a->neg == 0)
677 gt = 1;
678 lt = -1;
680 else
682 gt = -1;
683 lt = 1;
686 if(a->top > b->top) { return (gt); }
687 if(a->top < b->top) { return (lt); }
688 for(i = a->top - 1; i >= 0; i--)
690 t1 = a->d[i];
691 t2 = b->d[i];
692 if(t1 > t2) { return (gt); }
693 if(t1 < t2) { return (lt); }
695 return (0);
698 int BN_set_bit(BIGNUM *a, int n)
700 int i, j, k;
702 i = n / BN_BITS2;
703 j = n % BN_BITS2;
704 if(a->top <= i)
706 if(bn_wexpand(a, i + 1) == NULL) { return (0); }
707 for(k = a->top; k < i + 1; k++)
708 { a->d[k] = 0; }
709 a->top = i + 1;
712 a->d[i] |= (((BN_ULONG)1) << j);
713 return (1);
716 int BN_clear_bit(BIGNUM *a, int n)
718 int i, j;
720 i = n / BN_BITS2;
721 j = n % BN_BITS2;
722 if(a->top <= i) { return (0); }
724 a->d[i] &= (~(((BN_ULONG)1) << j));
725 bn_fix_top(a);
726 return (1);
729 int BN_is_bit_set(const BIGNUM *a, int n)
731 int i, j;
733 if(n < 0) { return (0); }
734 i = n / BN_BITS2;
735 j = n % BN_BITS2;
736 if(a->top <= i) { return (0); }
737 return ((a->d[i] & (((BN_ULONG)1) << j)) ? 1 : 0);
740 int BN_mask_bits(BIGNUM *a, int n)
742 int b, w;
744 w = n / BN_BITS2;
745 b = n % BN_BITS2;
746 if(w >= a->top) { return (0); }
747 if(b == 0)
748 { a->top = w; }
749 else
751 a->top = w + 1;
752 a->d[w] &= ~(BN_MASK2 << b);
754 bn_fix_top(a);
755 return (1);
758 int bn_cmp_words(BN_ULONG *a, BN_ULONG *b, int n)
760 int i;
761 BN_ULONG aa, bb;
763 aa = a[n - 1];
764 bb = b[n - 1];
765 if(aa != bb) { return ((aa > bb) ? 1 : -1); }
766 for(i = n - 2; i >= 0; i--)
768 aa = a[i];
769 bb = b[i];
770 if(aa != bb) { return ((aa > bb) ? 1 : -1); }
772 return (0);
775 #endif