FS#8961 - Anti-Aliased Fonts.
[kugel-rb.git] / utils / zenutils / libraries / beecrypt-4.1.2 / beecrypt / mp.c
blob82d272c17a95eb1b927f6dfe5d4e9132e7f8f933
1 /*
2 * Copyright (c) 2002, 2003 Bob Deblier
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 /*!\file mp.c
21 * \brief Multi-precision integer routines.
22 * \author Bob Deblier <bob.deblier@pandora.be>
23 * \ingroup MP_m
26 #define BEECRYPT_DLL_EXPORT
28 #if HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include "beecrypt/mp.h"
33 #include "beecrypt/mpopt.h"
35 #ifndef ASM_MPZERO
36 void mpzero(size_t size, mpw* data)
38 while (size--)
39 *(data++) = 0;
41 #endif
43 #ifndef ASM_MPFILL
44 void mpfill(size_t size, mpw* data, mpw fill)
46 while (size--)
47 *(data++) = fill;
49 #endif
51 #ifndef ASM_MPODD
52 int mpodd(size_t size, const mpw* data)
54 return (int)(data[size-1] & 0x1);
56 #endif
58 #ifndef ASM_MPEVEN
59 int mpeven(size_t size, const mpw* data)
61 return !(int)(data[size-1] & 0x1);
63 #endif
65 #ifndef ASM_MPZ
66 int mpz(size_t size, const mpw* data)
68 while (size--)
69 if (*(data++))
70 return 0;
71 return 1;
73 #endif
75 #ifndef ASM_MPNZ
76 int mpnz(size_t size, const mpw* data)
78 while (size--)
79 if (*(data++))
80 return 1;
81 return 0;
83 #endif
85 #ifndef ASM_MPEQ
86 int mpeq(size_t size, const mpw* xdata, const mpw* ydata)
88 while (size--)
90 if (*xdata == *ydata)
92 xdata++;
93 ydata++;
95 else
96 return 0;
98 return 1;
100 #endif
102 #ifndef ASM_MPEQX
103 int mpeqx(size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata)
105 if (xsize > ysize)
107 register size_t diff = xsize - ysize;
108 return mpeq(ysize, xdata+diff, ydata) && mpz(diff, xdata);
110 else if (xsize < ysize)
112 register size_t diff = ysize - xsize;
113 return mpeq(xsize, ydata+diff, xdata) && mpz(diff, ydata);
115 else
116 return mpeq(xsize, xdata, ydata);
118 #endif
120 #ifndef ASM_MPNE
121 int mpne(size_t size, const mpw* xdata, const mpw* ydata)
123 while (size--)
125 if (*xdata == *ydata)
127 xdata++;
128 ydata++;
130 else
131 return 1;
133 return 0;
135 #endif
137 #ifndef ASM_MPNEX
138 int mpnex(size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata)
140 if (xsize > ysize)
142 register size_t diff = xsize - ysize;
143 return mpnz(diff, xdata) || mpne(ysize, xdata+diff, ydata);
145 else if (xsize < ysize)
147 register size_t diff = ysize - xsize;
148 return mpnz(diff, ydata) || mpne(xsize, ydata+diff, xdata);
150 else
151 return mpne(xsize, xdata, ydata);
153 #endif
155 #ifndef ASM_MPGT
156 int mpgt(size_t size, const mpw* xdata, const mpw* ydata)
158 while (size--)
160 if (*xdata < *ydata)
161 return 0;
162 if (*xdata > *ydata)
163 return 1;
164 xdata++; ydata++;
166 return 0;
168 #endif
170 #ifndef ASM_MPGTX
171 int mpgtx(size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata)
173 if (xsize > ysize)
175 register size_t diff = xsize - ysize;
176 return mpnz(diff, xdata) || mpgt(ysize, xdata + diff, ydata);
178 else if (xsize < ysize)
180 register size_t diff = ysize - xsize;
181 return mpz(diff, ydata) && mpgt(xsize, xdata, ydata + diff);
183 else
184 return mpgt(xsize, xdata, ydata);
186 #endif
188 #ifndef ASM_MPLT
189 int mplt(size_t size, const mpw* xdata, const mpw* ydata)
191 while (size--)
193 if (*xdata > *ydata)
194 return 0;
195 if (*xdata < *ydata)
196 return 1;
197 xdata++; ydata++;
199 return 0;
201 #endif
203 #ifndef ASM_MPLTX
204 int mpltx(size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata)
206 if (xsize > ysize)
208 register size_t diff = xsize - ysize;
209 return mpz(diff, xdata) && mplt(ysize, xdata+diff, ydata);
211 else if (xsize < ysize)
213 register size_t diff = ysize - xsize;
214 return mpnz(diff, ydata) || mplt(xsize, xdata, ydata+diff);
216 else
217 return mplt(xsize, xdata, ydata);
219 #endif
221 #ifndef ASM_MPGE
222 int mpge(size_t size, const mpw* xdata, const mpw* ydata)
224 while (size--)
226 if (*xdata < *ydata)
227 return 0;
228 if (*xdata > *ydata)
229 return 1;
230 xdata++; ydata++;
232 return 1;
234 #endif
236 #ifndef ASM_MPGEX
237 int mpgex(size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata)
239 if (xsize > ysize)
241 register size_t diff = xsize - ysize;
242 return mpnz(diff, xdata) || mpge(ysize, xdata+diff, ydata);
244 else if (xsize < ysize)
246 register size_t diff = ysize - xsize;
247 return mpz(diff, ydata) && mpge(xsize, xdata, ydata+diff);
249 else
250 return mpge(xsize, xdata, ydata);
252 #endif
254 #ifndef ASM_MPLE
255 int mple(size_t size, const mpw* xdata, const mpw* ydata)
257 while (size--)
259 if (*xdata < *ydata)
260 return 1;
261 if (*xdata > *ydata)
262 return 0;
263 xdata++; ydata++;
265 return 1;
267 #endif
269 #ifndef ASM_MPLEX
270 int mplex(size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata)
272 if (xsize > ysize)
274 register size_t diff = xsize - ysize;
275 return mpz(diff, xdata) && mple(ysize, xdata+ diff, ydata);
277 else if (xsize < ysize)
279 register size_t diff = ysize - xsize;
280 return mpnz(diff, ydata) || mple(xsize, xdata, ydata+diff);
282 else
283 return mple(xsize, xdata, ydata);
285 #endif
287 #ifndef ASM_MPISONE
288 int mpisone(size_t size, const mpw* data)
290 data += size;
291 if (*(--data) == 1)
293 while (--size)
294 if (*(--data))
295 return 0;
296 return 1;
298 return 0;
300 #endif
302 #ifndef ASM_MPISTWO
303 int mpistwo(size_t size, const mpw* data)
305 data += size;
306 if (*(--data) == 2)
308 while (--size)
309 if (*(--data))
310 return 0;
311 return 1;
313 return 0;
315 #endif
317 #ifndef ASM_MPEQMONE
318 int mpeqmone(size_t size, const mpw* xdata, const mpw* ydata)
320 xdata += size;
321 ydata += size;
323 if (*(--xdata)+1 == *(--ydata))
325 while (--size)
326 if (*(--xdata) != *(--ydata))
327 return 0;
328 return 1;
330 return 0;
332 #endif
334 #ifndef ASM_MPLEONE
335 int mpleone(size_t size, const mpw* data)
337 data += size;
338 if (*(--data) > 1)
339 return 0;
340 else
342 while (--size)
343 if (*(--data))
344 return 0;
345 return 1;
348 #endif
350 #ifndef ASM_MPMSBSET
351 int mpmsbset(size_t size, const mpw* data)
353 return (int)((*data) >> (MP_WBITS-1));
355 #endif
357 #ifndef ASM_MPLSBSET
358 int mplsbset(size_t size, const mpw* data)
360 return (int)(data[size-1] & 0x1);
362 #endif
364 #ifndef ASM_MPSETMSB
365 void mpsetmsb(size_t size, mpw* data)
367 *data |= MP_MSBMASK;
369 #endif
371 #ifndef ASM_MPSETLSB
372 void mpsetlsb(size_t size, mpw* data)
374 data[size-1] |= MP_LSBMASK;
376 #endif
378 #ifndef ASM_MPCLRMSB
379 void mpclrmsb(size_t size, mpw* data)
381 *data &= ~ MP_MSBMASK;
383 #endif
385 #ifndef ASM_MPCLRLSB
386 void mpclrlsb(size_t size, mpw* data)
388 data[size-1] &= ~ MP_LSBMASK;
390 #endif
392 #ifndef ASM_MPAND
393 void mpand(size_t size, mpw* xdata, const mpw* ydata)
395 while (size--)
396 xdata[size] &= ydata[size];
398 #endif
400 #ifndef ASM_MPOR
401 void mpor(size_t size, mpw* xdata, const mpw* ydata)
403 while (size--)
404 xdata[size] |= ydata[size];
406 #endif
408 #ifndef ASM_MPXOR
409 void mpxor(size_t size, mpw* xdata, const mpw* ydata)
411 while (size--)
412 xdata[size] ^= ydata[size];
414 #endif
416 #ifndef ASM_MPNOT
417 void mpnot(size_t size, mpw* data)
419 while (size--)
420 data[size] = ~data[size];
422 #endif
424 #ifndef ASM_MPSETW
425 void mpsetw(size_t size, mpw* xdata, mpw y)
427 while (--size)
428 *(xdata++) = 0;
429 *(xdata++) = y;
431 #endif
433 #ifndef ASM_MPSETX
434 void mpsetx(size_t xsize, mpw* xdata, size_t ysize, const mpw* ydata)
436 while (xsize > ysize)
438 xsize--;
439 *(xdata++) = 0;
441 while (ysize > xsize)
443 ysize--;
444 ydata++;
446 while (xsize--)
447 *(xdata++) = *(ydata++);
449 #endif
451 #ifndef ASM_MPADDW
452 int mpaddw(size_t size, mpw* xdata, mpw y)
454 register mpw load, temp;
455 register int carry = 0;
457 xdata += size-1;
459 load = *xdata;
460 temp = load + y;
461 *(xdata--) = temp;
462 carry = (load > temp);
464 while (--size && carry)
466 load = *xdata;
467 temp = load + 1;
468 *(xdata--) = temp;
469 carry = (load > temp);
471 return carry;
473 #endif
475 #ifndef ASM_MPADD
476 int mpadd(size_t size, mpw* xdata, const mpw* ydata)
478 register mpw load, temp;
479 register int carry = 0;
481 xdata += size-1;
482 ydata += size-1;
484 while (size--)
486 temp = *(ydata--);
487 load = *xdata;
488 temp = carry ? (load + temp + 1) : (load + temp);
489 *(xdata--) = temp;
490 carry = carry ? (load >= temp) : (load > temp);
492 return carry;
494 #endif
496 #ifndef ASM_MPADDX
497 int mpaddx(size_t xsize, mpw* xdata, size_t ysize, const mpw* ydata)
499 if (xsize > ysize)
501 register size_t diff = xsize - ysize;
502 return mpaddw(diff, xdata, (mpw) mpadd(ysize, xdata+diff, ydata));
504 else
506 register size_t diff = ysize - xsize;
507 return mpadd(xsize, xdata, ydata+diff);
510 #endif
512 #ifndef ASM_MPSUBW
513 int mpsubw(size_t size, mpw* xdata, mpw y)
515 register mpw load, temp;
516 register int carry = 0;
518 xdata += size-1;
520 load = *xdata;
521 temp = load - y;
522 *(xdata--) = temp;
523 carry = (load < temp);
525 while (--size && carry)
527 load = *xdata;
528 temp = load - 1;
529 *(xdata--) = temp;
530 carry = (load < temp);
532 return carry;
534 #endif
536 #ifndef ASM_MPSUB
537 int mpsub(size_t size, mpw* xdata, const mpw* ydata)
539 register mpw load, temp;
540 register int carry = 0;
542 xdata += size-1;
543 ydata += size-1;
545 while (size--)
547 temp = *(ydata--);
548 load = *xdata;
549 temp = carry ? (load - temp - 1) : (load - temp);
550 *(xdata--) = temp;
551 carry = carry ? (load <= temp) : (load < temp);
553 return carry;
555 #endif
557 #ifndef ASM_MPSUBX
558 int mpsubx(size_t xsize, mpw* xdata, size_t ysize, const mpw* ydata)
560 if (xsize > ysize)
562 register size_t diff = xsize - ysize;
563 return mpsubw(diff, xdata, (mpw) mpsub(ysize, xdata+diff, ydata));
565 else
567 register size_t diff = ysize - xsize;
568 return mpsub(xsize, xdata, ydata+diff);
571 #endif
573 #ifndef ASM_MPNEG
574 void mpneg(size_t size, mpw* data)
576 mpnot(size, data);
577 mpaddw(size, data, 1);
579 #endif
581 #ifndef ASM_MPSETMUL
582 mpw mpsetmul(size_t size, mpw* result, const mpw* data, mpw y)
584 #if HAVE_MPDW
585 register mpdw temp;
586 register mpw carry = 0;
588 data += size;
589 result += size;
591 while (size--)
593 temp = *(--data);
594 temp *= y;
595 temp += carry;
596 *(--result) = (mpw) temp;
597 carry = (mpw)(temp >> MP_WBITS);
599 #else
600 register mpw temp, load, carry = 0;
601 register mphw ylo, yhi;
603 ylo = (mphw) y;
604 yhi = (mphw) (y >> MP_HWBITS);
606 data += size;
607 result += size;
609 while (size--)
611 register mphw xlo, xhi;
612 register mpw rlo, rhi;
614 xlo = (mphw) (temp = *(--data));
615 xhi = (mphw) (temp >> MP_HWBITS);
617 rlo = (mpw) xlo * ylo;
618 rhi = (mpw) xhi * yhi;
619 load = rlo;
620 temp = (mpw) xhi * ylo;
621 rlo += (temp << MP_HWBITS);
622 rhi += (temp >> MP_HWBITS) + (load > rlo);
623 load = rlo;
624 temp = (mpw) xlo * yhi;
625 rlo += (temp << MP_HWBITS);
626 rhi += (temp >> MP_HWBITS) + (load > rlo);
627 load = rlo;
628 temp = rlo + carry;
629 carry = rhi + (load > temp);
630 *(--result) = temp;
632 #endif
633 return carry;
635 #endif
637 #ifndef ASM_MPADDMUL
638 mpw mpaddmul(size_t size, mpw* result, const mpw* data, mpw y)
640 #if HAVE_MPDW
641 register mpdw temp;
642 register mpw carry = 0;
644 data += size;
645 result += size;
647 while (size--)
649 temp = *(--data);
650 temp *= y;
651 temp += carry;
652 temp += *(--result);
653 *result = (mpw) temp;
654 carry = (mpw)(temp >> MP_WBITS);
656 #else
657 register mpw temp, load, carry = 0;
658 register mphw ylo, yhi;
660 ylo = (mphw) y;
661 yhi = (mphw) (y >> MP_HWBITS);
663 data += size;
664 result += size;
666 while (size--)
668 register mphw xlo, xhi;
669 register mpw rlo, rhi;
671 xlo = (mphw) (temp = *(--data));
672 xhi = (mphw) (temp >> MP_HWBITS);
674 rlo = (mpw) xlo * ylo;
675 rhi = (mpw) xhi * yhi;
676 load = rlo;
677 temp = (mpw) xhi * ylo;
678 rlo += (temp << MP_HWBITS);
679 rhi += (temp >> MP_HWBITS) + (load > rlo);
680 load = rlo;
681 temp = (mpw) xlo * yhi;
682 rlo += (temp << MP_HWBITS);
683 rhi += (temp >> MP_HWBITS) + (load > rlo);
684 load = rlo;
685 rlo += carry;
686 temp = (load > rlo);
687 load = rhi;
688 rhi += temp;
689 carry = (load > rhi);
690 load = rlo;
691 rlo += *(--result);
692 *result = rlo;
693 carry += rhi + (load > rlo);
695 #endif
696 return carry;
698 #endif
700 #ifndef ASM_MPMUL
701 void mpmul(mpw* result, size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata)
703 /* preferred passing of parameters is x the larger of the two numbers */
704 if (xsize >= ysize)
706 register mpw rc;
708 result += ysize;
709 ydata += ysize;
711 rc = mpsetmul(xsize, result, xdata, *(--ydata));
712 *(--result) = rc;
714 while (--ysize)
716 rc = mpaddmul(xsize, result, xdata, *(--ydata));
717 *(--result) = rc;
720 else
722 register mpw rc;
724 result += xsize;
725 xdata += xsize;
727 rc = mpsetmul(ysize, result, ydata, *(--xdata));
728 *(--result) = rc;
730 while (--xsize)
732 rc = mpaddmul(ysize, result, ydata, *(--xdata));
733 *(--result) = rc;
737 #endif
739 #ifndef ASM_MPADDSQRTRC
740 void mpaddsqrtrc(size_t size, mpw* result, const mpw* data)
742 #if HAVE_MPDW
743 register mpdw temp;
744 register mpw load, carry = 0;
746 result += (size << 1);
748 while (size--)
750 temp = load = data[size];
751 temp *= load;
752 temp += carry;
753 temp += *(--result);
754 *result = (mpw) temp;
755 temp >>= MP_WBITS;
756 temp += *(--result);
757 *result = (mpw) temp;
758 carry = (mpw)(temp >> MP_WBITS);
760 #else
761 register mpw temp, load, carry = 0;
763 result += (size << 1);
765 while (size--)
767 register mphw xlo, xhi;
768 register mpw rlo, rhi;
770 xlo = (mphw) (temp = data[size]);
771 xhi = (mphw) (temp >> MP_HWBITS);
773 rlo = (mpw) xlo * xlo;
774 rhi = (mpw) xhi * xhi;
775 temp = (mpw) xhi * xlo;
776 load = rlo;
777 rlo += (temp << MP_HWBITS);
778 rhi += (temp >> MP_HWBITS) + (load > rlo);
779 load = rlo;
780 rlo += (temp << MP_HWBITS);
781 rhi += (temp >> MP_HWBITS) + (load > rlo);
782 load = rlo;
783 rlo += carry;
784 rhi += (load > rlo);
785 load = rlo;
786 rlo += *(--result);
787 *result = rlo;
788 temp = (load > rlo);
789 load = rhi;
790 rhi += temp;
791 carry = (load > rhi);
792 load = rhi;
793 rhi += *(--result);
794 *result = rhi;
795 carry += (load > rhi);
797 #endif
799 #endif
801 #ifndef ASM_MPSQR
802 void mpsqr(mpw* result, size_t size, const mpw* data)
804 register mpw rc;
805 register size_t n = size-1;
807 result += size;
808 result[n] = 0;
810 if (n)
812 rc = mpsetmul(n, result, data, data[n]);
813 *(--result) = rc;
814 while (--n)
816 rc = mpaddmul(n, result, data, data[n]);
817 *(--result) = rc;
821 *(--result) = 0;
823 mpmultwo(size << 1, result);
825 mpaddsqrtrc(size, result, data);
827 #endif
829 #ifndef ASM_MPSIZE
830 size_t mpsize(size_t size, const mpw* data)
832 while (size)
834 if (*data)
835 return size;
836 data++;
837 size--;
839 return 0;
841 #endif
843 #ifndef ASM_MPBITS
844 size_t mpbits(size_t size, const mpw* data)
846 return MP_WORDS_TO_BITS(size) - mpmszcnt(size, data);
848 #endif
850 #ifndef ASM_MPNORM
851 size_t mpnorm(size_t size, mpw* data)
853 register size_t shift = mpmszcnt(size, data);
854 mplshift(size, data, shift);
855 return shift;
857 #endif
859 #ifndef ASM_MPDIVTWO
860 void mpdivtwo(size_t size, mpw* data)
862 register mpw temp, carry = 0;
864 while (size--)
866 temp = *data;
867 *(data++) = (temp >> 1) | carry;
868 carry = (temp << (MP_WBITS-1));
871 #endif
873 #ifndef ASM_MPSDIVTWO
874 void mpsdivtwo(size_t size, mpw* data)
876 int carry = mpmsbset(size, data);
877 mpdivtwo(size, data);
878 if (carry)
879 mpsetmsb(size, data);
881 #endif
883 #ifndef ASM_MPMULTWO
884 int mpmultwo(size_t size, mpw* data)
886 register mpw temp, carry = 0;
888 data += size;
889 while (size--)
891 temp = *(--data);
892 *data = (temp << 1) | carry;
893 carry = (temp >> (MP_WBITS-1));
895 return (int) carry;
897 #endif
899 #ifndef ASM_MPMSZCNT
900 size_t mpmszcnt(size_t size, const mpw* data)
902 register size_t zbits = 0;
903 register size_t i = 0;
905 while (i < size)
907 register mpw temp = data[i++];
908 if (temp)
910 while (!(temp & MP_MSBMASK))
912 zbits++;
913 temp <<= 1;
915 break;
917 else
918 zbits += MP_WBITS;
920 return zbits;
922 #endif
924 #ifndef ASM_MPLSZCNT
925 size_t mplszcnt(size_t size, const mpw* data)
927 register size_t zbits = 0;
929 while (size--)
931 register mpw temp = data[size];
932 if (temp)
934 while (!(temp & MP_LSBMASK))
936 zbits++;
937 temp >>= 1;
939 break;
941 else
942 zbits += MP_WBITS;
944 return zbits;
946 #endif
948 #ifndef ASM_MPLSHIFT
949 void mplshift(size_t size, mpw* data, size_t count)
951 register size_t words = MP_BITS_TO_WORDS(count);
953 if (words < size)
955 register short lbits = (short) (count & (MP_WBITS-1));
957 /* first do the shifting, then do the moving */
958 if (lbits)
960 register mpw temp, carry = 0;
961 register short rbits = MP_WBITS - lbits;
962 register size_t i = size;
964 while (i > words)
966 temp = data[--i];
967 data[i] = (temp << lbits) | carry;
968 carry = (temp >> rbits);
971 if (words)
973 mpmove(size-words, data, data+words);
974 mpzero(words, data+size-words);
977 else
978 mpzero(size, data);
980 #endif
982 #ifndef ASM_MPRSHIFT
983 void mprshift(size_t size, mpw* data, size_t count)
985 register size_t words = MP_BITS_TO_WORDS(count);
987 if (words < size)
989 register short rbits = (short) (count & (MP_WBITS-1));
991 /* first do the shifting, then do the moving */
992 if (rbits)
994 register mpw temp, carry = 0;
995 register short lbits = MP_WBITS - rbits;
996 register size_t i = 0;
998 while (i < size-words)
1000 temp = data[i];
1001 data[i++] = (temp >> rbits) | carry;
1002 carry = (temp << lbits);
1005 if (words)
1007 mpmove(size-words, data+words, data);
1008 mpzero(words, data);
1011 else
1012 mpzero(size, data);
1014 #endif
1016 #ifndef ASM_MPRSHIFTLSZ
1017 size_t mprshiftlsz(size_t size, mpw* data)
1019 register mpw* slide = data+size-1;
1020 register size_t zwords = 0; /* counter for 'all zero bit' words */
1021 register short lbits, rbits = 0; /* counter for 'least significant zero' bits */
1022 register mpw temp, carry = 0;
1024 data = slide;
1026 /* count 'all zero' words and move src pointer */
1027 while (size--)
1029 /* test if we have a non-zero word */
1030 if ((carry = *(slide--)))
1032 /* count 'least signification zero bits and set zbits counter */
1033 while (!(carry & MP_LSBMASK))
1035 carry >>= 1;
1036 rbits++;
1038 break;
1040 zwords++;
1043 if ((rbits == 0) && (zwords == 0))
1044 return 0;
1046 /* prepare right-shifting of data */
1047 lbits = MP_WBITS - rbits;
1049 /* shift data */
1050 while (size--)
1052 temp = *(slide--);
1053 *(data--) = (temp << lbits) | carry;
1054 carry = (temp >> rbits);
1057 /* store the final carry */
1058 *(data--) = carry;
1060 /* store the return value in size */
1061 size = MP_WORDS_TO_BITS(zwords) + rbits;
1063 /* zero the (zwords) most significant words */
1064 while (zwords--)
1065 *(data--) = 0;
1067 return size;
1069 #endif
1071 /* try an alternate version here, with descending sizes */
1072 /* also integrate lszcnt and rshift properly into one function */
1073 #ifndef ASM_MPGCD_W
1075 * mpgcd_w
1076 * need workspace of (size) words
1078 void mpgcd_w(size_t size, const mpw* xdata, const mpw* ydata, mpw* result, mpw* wksp)
1080 register size_t shift, temp;
1082 if (mpge(size, xdata, ydata))
1084 mpcopy(size, wksp, xdata);
1085 mpcopy(size, result, ydata);
1087 else
1089 mpcopy(size, wksp, ydata);
1090 mpcopy(size, result, xdata);
1093 /* get the smallest returned values, and set shift to that */
1095 shift = mprshiftlsz(size, wksp);
1096 temp = mprshiftlsz(size, result);
1098 if (shift > temp)
1099 shift = temp;
1101 while (mpnz(size, wksp))
1103 mprshiftlsz(size, wksp);
1104 mprshiftlsz(size, result);
1106 if (mpge(size, wksp, result))
1107 mpsub(size, wksp, result);
1108 else
1109 mpsub(size, result, wksp);
1111 /* slide past zero words in both operands by increasing pointers and decreasing size */
1112 if ((*wksp == 0) && (*result == 0))
1114 size--;
1115 wksp++;
1116 result++;
1120 /* figure out if we need to slide the result pointer back */
1121 if ((temp = MP_BITS_TO_WORDS(shift)))
1123 size += temp;
1124 result -= temp;
1127 mplshift(size, result, shift);
1129 #endif
1131 #ifndef ASM_MPEXTGCD_W
1132 /* needs workspace of (6*size+6) words */
1133 /* used to compute the modular inverse */
1134 int mpextgcd_w(size_t size, const mpw* xdata, const mpw* ydata, mpw* result, mpw* wksp)
1137 * For computing a modular inverse, pass the modulus as xdata and the number
1138 * to be inverted as ydata.
1140 * Fact: if a element of Zn, then a is invertible if and only if gcd(a,n) = 1
1141 * Hence: if n is even, then a must be odd, otherwise the gcd(a,n) >= 2
1143 * The calling routine must guarantee this condition.
1146 register size_t sizep = size+1;
1147 register int full;
1149 mpw* udata = wksp;
1150 mpw* vdata = udata+sizep;
1151 mpw* adata = vdata+sizep;
1152 mpw* bdata = adata+sizep;
1153 mpw* cdata = bdata+sizep;
1154 mpw* ddata = cdata+sizep;
1156 mpsetx(sizep, udata, size, xdata);
1157 mpsetx(sizep, vdata, size, ydata);
1158 mpzero(sizep, bdata);
1159 mpsetw(sizep, ddata, 1);
1161 if ((full = mpeven(sizep, udata)))
1163 mpsetw(sizep, adata, 1);
1164 mpzero(sizep, cdata);
1167 while (1)
1169 while (mpeven(sizep, udata))
1171 mpdivtwo(sizep, udata);
1173 if (mpodd(sizep, bdata) || (full && mpodd(sizep, adata)))
1175 if (full) mpaddx(sizep, adata, size, ydata);
1176 mpsubx(sizep, bdata, size, xdata);
1179 if (full) mpsdivtwo(sizep, adata);
1180 mpsdivtwo(sizep, bdata);
1182 while (mpeven(sizep, vdata))
1184 mpdivtwo(sizep, vdata);
1186 if (mpodd(sizep, ddata) || (full && mpodd(sizep, cdata)))
1188 if (full) mpaddx(sizep, cdata, size, ydata);
1189 mpsubx(sizep, ddata, size, xdata);
1192 if (full) mpsdivtwo(sizep, cdata);
1193 mpsdivtwo(sizep, ddata);
1195 if (mpge(sizep, udata, vdata))
1197 mpsub(sizep, udata, vdata);
1198 if (full) mpsub(sizep, adata, cdata);
1199 mpsub(sizep, bdata, ddata);
1201 else
1203 mpsub(sizep, vdata, udata);
1204 if (full) mpsub(sizep, cdata, adata);
1205 mpsub(sizep, ddata, bdata);
1207 if (mpz(sizep, udata))
1209 if (mpisone(sizep, vdata))
1211 if (result)
1213 if (*ddata & MP_MSBMASK)
1215 /* keep adding the modulus until we get a carry */
1216 while (!mpaddx(sizep, ddata, size, xdata));
1218 else
1220 /* in some computations, d ends up > x, hence:
1221 * keep subtracting n from d until d < x
1223 while (mpgtx(sizep, ddata, size, xdata))
1224 mpsubx(sizep, ddata, size, xdata);
1226 mpsetx(size, result, sizep, ddata);
1228 return 1;
1230 return 0;
1234 #endif
1236 #ifndef ASM_MPPNDIV
1237 mpw mppndiv(mpw xhi, mpw xlo, mpw y)
1239 register mpw result = 0;
1240 register short count = MP_WBITS;
1241 register int carry = 0;
1243 while (count--)
1245 if (carry | (xhi >= y))
1247 xhi -= y;
1248 result++;
1250 carry = (xhi >> (MP_WBITS-1));
1251 xhi <<= 1;
1252 xhi |= (xlo >> (MP_WBITS-1));
1253 xlo <<= 1;
1254 result <<= 1;
1256 if (carry | (xhi >= y))
1258 xhi -= y;
1259 result++;
1261 return result;
1263 #endif
1265 #ifndef ASM_MPMOD
1266 void mpmod(mpw* result, size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata, mpw* workspace)
1268 /* result size xsize, workspace size 2*ysize+1 */
1269 mpw q, msw;
1270 mpw* rdata = result;
1271 mpw* ynorm = workspace+ysize+1;
1272 size_t shift, qsize = xsize-ysize;
1274 mpcopy(ysize, ynorm, ydata);
1275 shift = mpnorm(ysize, ynorm);
1276 msw = *ynorm;
1277 mpcopy(xsize, rdata, xdata);
1278 if (mpge(ysize, rdata, ynorm))
1279 mpsub(ysize, rdata, ynorm);
1281 while (qsize--)
1283 q = mppndiv(rdata[0], rdata[1], msw);
1285 *workspace = mpsetmul(ysize, workspace+1, ynorm, q);
1287 while (mplt(ysize+1, rdata, workspace))
1289 mpsubx(ysize+1, workspace, ysize, ynorm);
1290 q--;
1292 mpsub(ysize+1, rdata, workspace);
1293 rdata++;
1295 /* de-normalization steps */
1296 while (shift--)
1298 mpdivtwo(ysize, ynorm);
1299 if (mpge(ysize, rdata, ynorm))
1300 mpsub(ysize, rdata, ynorm);
1303 #endif
1305 #ifndef ASM_MPNDIVMOD
1306 void mpndivmod(mpw* result, size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata, register mpw* workspace)
1308 /* result must be xsize+1 in length */
1309 /* workspace must be ysize+1 in length */
1310 /* expect ydata to be normalized */
1311 mpw q;
1312 mpw msw = *ydata;
1313 size_t qsize = xsize-ysize;
1315 *result = (mpge(ysize, xdata, ydata) ? 1 : 0);
1316 mpcopy(xsize, result+1, xdata);
1318 if (*result)
1319 (void) mpsub(ysize, result+1, ydata);
1321 result++;
1323 while (qsize--)
1325 q = mppndiv(result[0], result[1], msw);
1327 *workspace = mpsetmul(ysize, workspace+1, ydata, q);
1329 while (mplt(ysize+1, result, workspace))
1331 mpsubx(ysize+1, workspace, ysize, ydata);
1332 q--;
1334 mpsub(ysize+1, result, workspace);
1335 *(result++) = q;
1338 #endif
1340 void mpprint(size_t size, const mpw* data)
1342 mpfprint(stdout, size, data);
1345 void mpprintln(size_t size, const mpw* data)
1347 mpfprintln(stdout, size, data);
1350 void mpfprint(FILE* f, size_t size, const mpw* data)
1352 if (data == (mpw*) 0)
1353 return;
1355 if (f == (FILE*) 0)
1356 return;
1358 while (size--)
1360 #if (MP_WBITS == 32)
1361 fprintf(f, "%08x", (unsigned) *(data++));
1362 #elif (MP_WBITS == 64)
1363 # if WIN32
1364 fprintf(f, "%016I64x", *(data++));
1365 # elif SIZEOF_UNSIGNED_LONG == 8
1366 fprintf(f, "%016lx", *(data++));
1367 # else
1368 fprintf(f, "%016llx", *(data++));
1369 # endif
1370 #else
1371 # error
1372 #endif
1374 fflush(f);
1377 void mpfprintln(FILE* f, size_t size, const mpw* data)
1379 if (data == (mpw*) 0)
1380 return;
1382 if (f == (FILE*) 0)
1383 return;
1385 while (size--)
1387 #if (MP_WBITS == 32)
1388 fprintf(f, "%08x", *(data++));
1389 #elif (MP_WBITS == 64)
1390 # if WIN32
1391 fprintf(f, "%016I64x", *(data++));
1392 # elif SIZEOF_UNSIGNED_LONG == 8
1393 fprintf(f, "%016lx", *(data++));
1394 # else
1395 fprintf(f, "%016llx", *(data++));
1396 # endif
1397 #else
1398 # error
1399 #endif
1401 fprintf(f, "\n");
1402 fflush(f);
1405 int i2osp(byte *osdata, size_t ossize, const mpw* idata, size_t isize)
1407 #if WORDS_BIGENDIAN
1408 size_t max_bytes = MP_WORDS_TO_BYTES(isize);
1409 #endif
1410 size_t significant_bytes = (mpbits(isize, idata) + 7) >> 3;
1412 /* verify that ossize is large enough to contain the significant bytes */
1413 if (ossize >= significant_bytes)
1415 /* looking good; check if we have more space than significant bytes */
1416 if (ossize > significant_bytes)
1417 { /* fill most significant bytes with zero */
1418 memset(osdata, 0, ossize - significant_bytes);
1419 osdata += ossize - significant_bytes;
1421 if (significant_bytes)
1422 { /* fill remaining bytes with endian-adjusted data */
1423 #if !WORDS_BIGENDIAN
1424 mpw w = idata[--isize];
1425 byte shift = 0;
1427 /* fill right-to-left; much easier than left-to-right */
1430 osdata[--significant_bytes] = (byte)(w >> shift);
1431 shift += 8;
1432 if (shift == MP_WBITS)
1434 shift = 0;
1435 w = idata[--isize];
1437 } while (significant_bytes);
1438 #else
1439 /* just copy data past zero bytes */
1440 memcpy(osdata, ((byte*) idata) + (max_bytes - significant_bytes), significant_bytes);
1441 #endif
1443 return 0;
1445 return -1;
1448 int os2ip(mpw* idata, size_t isize, const byte* osdata, size_t ossize)
1450 size_t required;
1452 /* skip non-significant leading zero bytes */
1453 while (!(*osdata) && ossize)
1455 osdata++;
1456 ossize--;
1459 required = MP_BYTES_TO_WORDS(ossize + MP_WBYTES - 1);
1461 if (isize >= required)
1463 /* yes, we have enough space and can proceed */
1464 mpw w = 0;
1465 /* adjust counter so that the loop will start by skipping the proper
1466 * amount of leading bytes in the first significant word
1468 byte b = (ossize % MP_WBYTES);
1470 if (isize > required)
1471 { /* fill initials words with zero */
1472 mpzero(isize-required, idata);
1473 idata += isize-required;
1476 if (b == 0)
1477 b = MP_WBYTES;
1479 while (ossize--)
1481 w <<= 8;
1482 w |= *(osdata++);
1483 b--;
1485 if (b == 0)
1487 *(idata++) = w;
1488 w = 0;
1489 b = MP_WBYTES;
1493 return 0;
1495 return -1;
1498 int hs2ip(mpw* idata, size_t isize, const char* hsdata, size_t hssize)
1500 size_t required = MP_NIBBLES_TO_WORDS(hssize + MP_WNIBBLES - 1);
1502 if (isize >= required)
1504 register size_t i;
1507 if (isize > required)
1508 { /* fill initial words with zero */
1509 for (i = required; i < isize; i++)
1510 *(idata++) = 0;
1512 while (hssize)
1514 register mpw w = 0;
1515 register size_t chunk = hssize & (MP_WNIBBLES - 1);
1516 register char ch;
1518 if (chunk == 0) chunk = MP_WNIBBLES;
1520 for (i = 0; i < chunk; i++)
1522 ch = *(hsdata++);
1523 w <<= 4;
1524 if (ch >= '0' && ch <= '9')
1525 w += (ch - '0');
1526 else if (ch >= 'A' && ch <= 'F')
1527 w += (ch - 'A') + 10;
1528 else if (ch >= 'a' && ch <= 'f')
1529 w += (ch - 'a') + 10;
1531 *(idata++) = w;
1532 hssize -= chunk;
1534 return 0;
1536 return -1;