00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 #include "udanax.h"
00086
00087 Tumbler ZEROTUMBLERvar;
00088
00089 static int abscmp(Tumbler *aptr, Tumbler *bptr);
00090
00091
00092
00100 bool
00101 tumblereq(
00102 Tumbler *a,
00103 Tumbler *b)
00104 {
00105 char *aptr = (char *)a;
00106 char *bptr = (char *)b;
00107 int i;
00108
00109
00110
00111 i = (int)aptr + sizeof(Tumbler);
00112 for (; ((int)aptr) < i;) {
00113 if (*aptr++ != *bptr++)
00114 return false;
00115 }
00116 return true;
00117 }
00118
00126 bool
00127 tumbleraccounteq(
00128 Tumbler *aptr,
00129 Tumbler *bptr)
00130 {
00131 int i, j;
00132
00133 if (aptr->exp != bptr->exp || aptr->sign != bptr->sign)
00134 return false;
00135
00136 for (j = 0, i = 0; i < NPLACES; i++) {
00137 if (aptr->mantissa[i] != bptr->mantissa[i])
00138 return false;
00139
00140 if (aptr->mantissa[i] == 0 && ++j == 2)
00141 return true;
00142 }
00143 return true;
00144 }
00145
00153 int
00154 tumblercmp(
00155 Tumbler *aptr,
00156 Tumbler *bptr)
00157 {
00158 if (iszerotumbler(aptr)) {
00159 if (iszerotumbler(bptr))
00160 return EQUAL;
00161 else
00162 return (bptr->sign ? GREATER : LESS);
00163 }
00164
00165 if (iszerotumbler(bptr))
00166 return (aptr->sign ? LESS : GREATER);
00167
00168 if (aptr->sign == bptr->sign)
00169 return (aptr->sign ? abscmp(bptr, aptr) : abscmp(aptr, bptr));
00170
00171 return (aptr->sign ? LESS : GREATER);
00172 }
00173
00174 #ifndef ExPeriMental
00175
00182 static int
00183 abscmp(
00184 Tumbler *aptr,
00185 Tumbler *bptr)
00186 {
00187 int *a, *b;
00188 int i, cmp;
00189
00190 if (aptr->exp != bptr->exp) {
00191 if (aptr->exp < bptr->exp) {
00192 return LESS;
00193 } else {
00194 return GREATER;
00195 }
00196
00197 } else {
00198 a = (int *) aptr->mantissa;
00199 b = (int *) bptr->mantissa;
00200 for (i = NPLACES; i--;) {
00201 if (!(cmp = *a++ - *b++)) {
00202 } else if (cmp < 0) {
00203 return LESS;
00204 } else {
00205 return GREATER;
00206 }
00207 }
00208 }
00209 return EQUAL;
00210 }
00211 #else
00212
00219 static int
00220 abscmp(
00221 Tumbler *aptr,
00222 Tumbler *bptr)
00223 {
00224 int *a, *b;
00225 int i, cmp;
00226
00227 if (aptr->exp != bptr->exp) {
00228 if (aptr->exp < bptr->exp) {
00229 return LESS;
00230 } else {
00231 return GREATER;
00232 }
00233 } else {
00234 a = (int *) aptr->mantissa;
00235 b = (int *) bptr->mantissa;
00236 for (i = NPLACES; i--;) {
00237 cmp = *a - *b;
00238 if (cmp == 0) {
00239 a++;
00240 b++;
00241 continue;
00242 } else if (cmp < 0) {
00243 return LESS;
00244 } else {
00245 return GREATER;
00246 }
00247 }
00248 }
00249 return EQUAL;
00250 }
00251 #endif
00252
00260 int
00261 intervalcmp(
00262 Tumbler *left,
00263 Tumbler *right,
00264 Tumbler *address)
00265 {
00266 int cmp;
00267
00268 cmp = tumblercmp(address, left);
00269 if (cmp == LESS)
00270 return TOMYLEFT;
00271
00272 else if (cmp == EQUAL)
00273 return ONMYLEFTBORDER;
00274
00275 cmp = tumblercmp(address, right);
00276 if (cmp == LESS)
00277 return THRUME;
00278 else if (cmp == EQUAL)
00279 return ONMYRIGHTBORDER;
00280 else
00281 return TOMYRIGHT;
00282 }
00283
00284
00285
00293 bool
00294 tumblercheckptr(
00295 Tumbler *ptr,
00296 int *crumptr)
00297 {
00298 bool wrong;
00299 int i;
00300
00301 wrong = false;
00302 if (ptr->exp > 0) {
00303 #ifndef DISTRIBUTION
00304 L("bad exp ");
00305 #endif
00306 wrong = true;
00307 }
00308
00309 if (ptr->sign && ptr->mantissa[0] == 0) {
00310 #ifndef DISTRIBUTION
00311 L(" negative zero ");
00312 #endif
00313 wrong = true;
00314 }
00315
00316 if (ptr->exp && ptr->mantissa[0] == 0) {
00317 #ifndef DISTRIBUTION
00318 L("fucked up non-normalized");
00319 #endif
00320 wrong = true;
00321 }
00322
00323 if (ptr->mantissa[0] == 0) {
00324 for (i = 1; i < NPLACES; ++i) {
00325 if (ptr->mantissa[i] != 0) {
00326 #ifndef DISTRIBUTION
00327 L("nonzerozerotumbler");
00328 #endif
00329 wrong = true;
00330 }
00331 }
00332 }
00333
00334 for (i = 0; i < NPLACES; ++i) {
00335 if ((int) (ptr->mantissa[i]) < 0) {
00336 #ifndef DISTRIBUTION
00337 L("negative digit");
00338 #endif
00339 wrong = true;
00340 }
00341 }
00342
00343 if (wrong) {
00344 #ifndef DISTRIBUTION
00345 dumptumbler(ptr);
00346 if (crumptr) {
00347 dump((typecorecrum *) crumptr);
00348 }
00349 L("\n\n invalid tumbler \n\n");
00350 if (crumptr) {
00351 dumpwholetree((typecorecrum *) crumptr);
00352 }
00353 assert(0);
00354 #else
00355 assert(0);
00356 #endif
00357 return false;
00358 }
00359
00360 return true;
00361 }
00362
00370 bool
00371 tumblercheck(
00372 Tumbler *ptr)
00373 {
00374 return tumblercheckptr(ptr, (int *) NULL);
00375 }
00376
00384
00385 bool
00386 is1story(
00387 Tumbler *tumblerptr)
00388 {
00389 int i;
00390
00391
00392
00393 for (i = 1; i < NPLACES; i++)
00394 if (tumblerptr->mantissa[i] != 0)
00395 return false;
00396 return true;
00397 }
00398
00406 int
00407 nstories(
00408 Tumbler *tumblerptr)
00409 {
00410 int i;
00411
00412
00413
00414 for (i = NPLACES; i > 0 && tumblerptr->mantissa[--i] == 0; )
00415 ;
00416
00417 return i + 1;
00418 }
00419
00427 int
00428 tumblerlength(
00429 Tumbler *tumblerptr)
00430 {
00431 return nstories(tumblerptr) - tumblerptr->exp;
00432 }
00433
00434
00435
00436
00444 int
00445 lastdigitintumbler(
00446 Tumbler *tumblerptr)
00447 {
00448 int n, digit;
00449
00450 n = nstories(tumblerptr);
00451 digit = tumblerptr->mantissa[n - 1];
00452 return digit;
00453 }
00454
00455
00456
00464 void
00465 tumblerjustify(
00466 Tumbler *tumblerptr)
00467 {
00468 int i, j;
00469 int shift;
00470 tdigit *mantissaptr;
00471
00472 mantissaptr = tumblerptr->mantissa;
00473 if (mantissaptr[0] != 0)
00474 return;
00475
00476 for (shift = 0; mantissaptr[shift] == 0; ++shift) {
00477 if (shift == NPLACES - 1) {
00478 tumblerptr->exp = 0;
00479 tumblerptr->sign = 0;
00480 return;
00481 }
00482 }
00483
00484 for (i = 0, j = shift; j < NPLACES;)
00485 mantissaptr[i++] = mantissaptr[j++];
00486
00487 while (i < NPLACES)
00488 mantissaptr[i++] = 0;
00489
00490 tumblerptr->exp -= shift;
00491
00492
00493 }
00494
00495 static void
00496 partialtumblerjustify(
00497 Tumbler *tumblerptr)
00498 {
00499 int i, j;
00500 int shift;
00501 tdigit *mantissaptr;
00502
00503 mantissaptr = tumblerptr->mantissa;
00504
00505
00506 for (shift = 0; mantissaptr[shift] == 0; ++shift) {
00507 if (shift == NPLACES - 1) {
00508 tumblerptr->exp = 0;
00509 tumblerptr->sign = 0;
00510 return;
00511 }
00512 }
00513
00514 for (i = 0, j = shift; j < NPLACES;)
00515 mantissaptr[i++] = mantissaptr[j++];
00516
00517 while (i < NPLACES)
00518 mantissaptr[i++] = 0;
00519
00520 tumblerptr->exp -= shift;
00521
00522
00523 }
00524
00532 void
00533 tumblercopy(
00534 Tumbler *fromptr,
00535 Tumbler *toptr)
00536 {
00537
00538 movetumbler(fromptr, toptr);
00539 }
00540
00541
00542
00543
00551 void
00552 tumblermax(
00553 Tumbler *aptr,
00554 Tumbler *bptr,
00555 Tumbler *cptr)
00556 {
00557 if (tumblercmp(aptr, bptr) == GREATER)
00558 movetumbler(aptr, cptr);
00559 else
00560 movetumbler(bptr, cptr);
00561 }
00562
00570 void
00571 functiontumbleradd(
00572 Tumbler *aptr,
00573 Tumbler *bptr,
00574 Tumbler *cptr)
00575
00576
00577 {
00578 if (iszerotumbler(bptr)) {
00579 movetumbler(aptr, cptr);
00580 return;
00581
00582 } else if (iszerotumbler(aptr)) {
00583 movetumbler(bptr, cptr);
00584 return;
00585
00586 } else if (aptr->sign == bptr->sign) {
00587 absadd(aptr, bptr, cptr);
00588 cptr->sign = aptr->sign;
00589
00590
00591
00592
00593 } else if (abscmp(aptr, bptr) == GREATER) {
00594 strongsub(aptr, bptr, cptr);
00595 cptr->sign = aptr->sign;
00596 if (cptr->mantissa[0] == 0) {
00597 partialtumblerjustify(cptr);
00598 }
00599 } else {
00600 weaksub(bptr, aptr, cptr);
00601 cptr->sign = bptr->sign;
00602 if (cptr->mantissa[0] == 0) {
00603 partialtumblerjustify(cptr);
00604 }
00605 }
00606
00607
00608
00609
00610 }
00611
00619 void
00620 tumblersub(
00621 Tumbler *aptr,
00622 Tumbler *bptr,
00623 Tumbler *cptr)
00624 {
00625 Tumbler temp;
00626
00627
00628
00629
00630
00631 if (iszerotumbler(bptr))
00632 movetumbler(aptr, cptr);
00633
00634 else if (tumblereq(aptr, bptr))
00635 tumblerclear(cptr);
00636
00637 else if (iszerotumbler(aptr)) {
00638 movetumbler(bptr, cptr);
00639 cptr->sign = !cptr->sign;
00640
00641 } else {
00642 movetumbler(bptr, &temp);
00643 temp.sign = !temp.sign;
00644 tumbleradd(aptr, &temp, cptr);
00645 }
00646 tumblerjustify(cptr);
00647
00648
00649
00650
00651
00652 }
00653
00654 #ifndef ExPeRiMENATL
00655 #endif
00656
00664 void
00665 absadd(
00666 Tumbler *aptr,
00667 Tumbler *bptr,
00668 Tumbler *cptr)
00669 {
00670 int i, j;
00671
00672 int temp;
00673 tdigit *ansmant;
00674 tdigit *bmant, *amant;
00675 Tumbler answer;
00676
00677 i = j = 0;
00678 amant = aptr->mantissa;
00679 bmant = bptr->mantissa;
00680 answer.xvartumbler = 0;
00681 answer.varandnotfixed = 0;
00682 answer.sign = 0;
00683 ansmant = answer.mantissa;
00684
00685 if (aptr->exp == bptr->exp) {
00686 answer.exp = aptr->exp;
00687 ansmant[0] = amant[0] + bmant[0];
00688 i = j = 1;
00689
00690 } else if (aptr->exp > bptr->exp) {
00691 answer.exp = aptr->exp;
00692 temp = aptr->exp - bptr->exp;
00693 while (i < temp) {
00694 ansmant[j++] = amant[i++];
00695 }
00696 ansmant[j++] = amant[i++] + bmant[0];
00697 i = 1;
00698
00699 } else {
00700 answer.exp = bptr->exp;
00701 temp = bptr->exp - aptr->exp;
00702 while (i <= temp) {
00703 ansmant[j++] = bmant[i++];
00704 }
00705 }
00706
00707 while (j <= NPLACES - 1)
00708 ansmant[j++] = bmant[i++];
00709
00710 movetumbler(&answer, cptr);
00711 }
00712
00713 #ifdef OlDVeRsIon
00714
00721 void
00722 absadd(
00723 Tumbler *aptr,
00724 Tumbler *bptr,
00725 Tumbler *cptr)
00726 {
00727 int i, j;
00728 int place;
00729 int temp;
00730 tdigit *ansmant;
00731 tdigit *bmant, *amant;
00732 Tumbler answer;
00733
00734 i = j = 0;
00735 amant = aptr->mantissa;
00736 bmant = bptr->mantissa;
00737 tumblerclear(&answer);
00738 ansmant = answer.mantissa;
00739
00740 if (aptr->exp == bptr->exp) {
00741 answer.exp = aptr->exp;
00742 ansmant[0] = amant[0] + bmant[0];
00743 i = j = 1;
00744
00745 } else if (aptr->exp > bptr->exp) {
00746 answer.exp = aptr->exp;
00747 temp = aptr->exp - bptr->exp;
00748 while (i < temp)
00749 ansmant[j++] = amant[i++];
00750 ansmant[j++] = amant[i++] + bmant[0];
00751 i = 1;
00752
00753 } else {
00754 answer.exp = bptr->exp;
00755 temp = bptr->exp - aptr->exp;
00756 while (i <= temp)
00757 ansmant[j++] = bmant[i++];
00758 }
00759
00760 while (j <= NPLACES - 1)
00761 ansmant[j++] = bmant[i++];
00762
00763 movetumbler(&answer, cptr);
00764 }
00765
00766 #endif
00767
00775 void
00776 strongsub(
00777 Tumbler *aptr,
00778 Tumbler *bptr,
00779 Tumbler *cptr)
00780 {
00781 Tumbler answer;
00782 int i, j;
00783
00784 tumblerclear(&answer);
00785 if (tumblereq(aptr, bptr)) {
00786 movetumbler(&answer, cptr);
00787 return;
00788 }
00789
00790 if (bptr->exp < aptr->exp) {
00791 movetumbler(aptr, cptr);
00792 return;
00793 }
00794
00795 answer.exp = aptr->exp;
00796 for (i = 0; aptr->mantissa[i] == bptr->mantissa[i]; ++i) {
00797 --answer.exp;
00798 if (i >= NPLACES) {
00799 movetumbler(&answer, cptr);
00800 return;
00801 }
00802 }
00803
00804 answer.mantissa[0] = aptr->mantissa[i] - bptr->mantissa[i];
00805 if (++i >= NPLACES) {
00806 movetumbler(&answer, cptr);
00807 return;
00808 }
00809
00810 for (j = 1; j < NPLACES && i < NPLACES;)
00811 answer.mantissa[j++] = aptr->mantissa[i++];
00812
00813 movetumbler(&answer, cptr);
00814 }
00815
00823 void
00824 weaksub(
00825 Tumbler *aptr,
00826 Tumbler *bptr,
00827 Tumbler *cptr)
00828 {
00829 Tumbler answer;
00830 int i;
00831 int expdiff;
00832
00833 tumblerclear(&answer);
00834 if (tumblereq(aptr, bptr)) {
00835 movetumbler(&answer, cptr);
00836 return;
00837 }
00838
00839 answer.exp = aptr->exp;
00840 expdiff = aptr->exp - bptr->exp;
00841
00842 for (i = 0; i < expdiff; ++i) {
00843 answer.mantissa[i] = aptr->mantissa[i];
00844 if (i >= NPLACES) {
00845 movetumbler(&answer, cptr);
00846 return;
00847 }
00848 }
00849
00850 answer.mantissa[i] = aptr->mantissa[i] - bptr->mantissa[0];
00851 movetumbler(&answer, cptr);
00852 }
00853
00861 int
00862 tumblerintdiff(
00863 Tumbler *aptr,
00864 Tumbler *bptr)
00865 {
00866 Tumbler c;
00867
00868 tumblersub(aptr, bptr, &c);
00869 return c.mantissa[0];
00870 }
00871
00879 void
00880 tumblerincrement(
00881 Tumbler *aptr,
00882 int rightshift,
00883 int bint,
00884 Tumbler *cptr)
00885 {
00886 int idx;
00887
00888 if (iszerotumbler(aptr)) {
00889 tumblerclear(cptr);
00890 cptr->exp = -rightshift;
00891 cptr->mantissa[0] = bint;
00892 return;
00893 }
00894
00895 if (aptr != cptr)
00896 movetumbler(aptr, cptr);
00897
00898 for (idx = NPLACES; aptr->mantissa[--idx] == 0 && idx > 0;)
00899 ;
00900
00901 if (idx + rightshift >= NPLACES) {
00902 #ifndef DISTRIBUTION
00903 dumptumbler(aptr);
00904 L(" idx = %d rightshift = %d\n", idx, rightshift);
00905 assert(0);
00906 #else
00907 assert(0);
00908 #endif
00909 }
00910
00911 cptr->mantissa[idx + rightshift] += bint;
00912 tumblerjustify(cptr);
00913 }
00914
00922 void
00923 tumblertruncate(
00924 Tumbler *aptr,
00925 int bint,
00926 Tumbler *cptr)
00927 {
00928 Tumbler answer;
00929 int i;
00930
00931 movetumbler(aptr, &answer);
00932 for (i = answer.exp; i < 0 && bint > 0; ++i, --bint)
00933 ;
00934
00935 if (bint <= 0)
00936 tumblerclear(&answer);
00937 else
00938 for (; bint < NPLACES; ++bint)
00939 answer.mantissa[bint] = 0;
00940
00941 tumblerjustify(&answer);
00942 movetumbler(&answer, cptr);
00943 }
00944
00952 void
00953 prefixtumbler(
00954 Tumbler *aptr,
00955 int bint,
00956 Tumbler *cptr)
00957 {
00958 Tumbler temp1, temp2;
00959
00960 tumblerclear(&temp1);
00961 temp1.mantissa[0] = bint;
00962 movetumbler(aptr, &temp2);
00963
00964 if (!iszerotumbler(&temp2))
00965 temp2.exp -= 1;
00966
00967 tumbleradd(&temp1, &temp2, cptr);
00968 }
00969
00977
00978
00979
00980
00981
00982
00983
00984
00985 void
00986 beheadtumbler(
00987 Tumbler *aptr,
00988 Tumbler *bptr)
00989 {
00990 Tumbler temp;
00991
00992 movetumbler(aptr, &temp);
00993 ++temp.exp;
00994
00995 if (aptr->exp == 0)
00996 temp.mantissa[0] = 0;
00997
00998 tumblerjustify(&temp);
00999 movetumbler(&temp, bptr);
01000 }
01001
01009 void
01010 docidandvstream2tumbler(
01011 Tumbler *docid,
01012 Tumbler *vstream,
01013 Tumbler *tumbleptr)
01014 {
01015 int i, j;
01016
01017 movetumbler(docid, tumbleptr);
01018 for (i = NPLACES - 1; i >= 0; i--) {
01019 if (tumbleptr->mantissa[i]) {
01020 ++i;
01021 break;
01022 }
01023 }
01024 for (j = 0; i < NPLACES && j < NPLACES;)
01025 tumbleptr->mantissa[++i] = vstream->mantissa[j++];
01026 }