Home | History | Annotate | Download | only in native
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 #include <string.h>
     19 #include "cbigint.h"
     20 
     21 #if defined(LINUX) || defined(FREEBSD) || defined(ZOS) || defined(MACOSX) || defined(AIX)
     22 #define USE_LL
     23 #endif
     24 
     25 #ifdef HY_LITTLE_ENDIAN
     26 #define at(i) (i)
     27 #else
     28 #define at(i) ((i)^1)
     29 /* the sequence for halfAt is -1, 2, 1, 4, 3, 6, 5, 8... */
     30 /* and it should correspond to 0, 1, 2, 3, 4, 5, 6, 7... */
     31 #define halfAt(i) (-((-(i)) ^ 1))
     32 #endif
     33 
     34 #define HIGH_IN_U64(u64) ((u64) >> 32)
     35 #if defined(USE_LL)
     36 #define LOW_IN_U64(u64) ((u64) & 0x00000000FFFFFFFFLL)
     37 #else
     38 #if defined(USE_L)
     39 #define LOW_IN_U64(u64) ((u64) & 0x00000000FFFFFFFFL)
     40 #else
     41 #define LOW_IN_U64(u64) ((u64) & 0x00000000FFFFFFFF)
     42 #endif /* USE_L */
     43 #endif /* USE_LL */
     44 
     45 #if defined(USE_LL)
     46 #define TEN_E1 (0xALL)
     47 #define TEN_E2 (0x64LL)
     48 #define TEN_E3 (0x3E8LL)
     49 #define TEN_E4 (0x2710LL)
     50 #define TEN_E5 (0x186A0LL)
     51 #define TEN_E6 (0xF4240LL)
     52 #define TEN_E7 (0x989680LL)
     53 #define TEN_E8 (0x5F5E100LL)
     54 #define TEN_E9 (0x3B9ACA00LL)
     55 #define TEN_E19 (0x8AC7230489E80000LL)
     56 #else
     57 #if defined(USE_L)
     58 #define TEN_E1 (0xAL)
     59 #define TEN_E2 (0x64L)
     60 #define TEN_E3 (0x3E8L)
     61 #define TEN_E4 (0x2710L)
     62 #define TEN_E5 (0x186A0L)
     63 #define TEN_E6 (0xF4240L)
     64 #define TEN_E7 (0x989680L)
     65 #define TEN_E8 (0x5F5E100L)
     66 #define TEN_E9 (0x3B9ACA00L)
     67 #define TEN_E19 (0x8AC7230489E80000L)
     68 #else
     69 #define TEN_E1 (0xA)
     70 #define TEN_E2 (0x64)
     71 #define TEN_E3 (0x3E8)
     72 #define TEN_E4 (0x2710)
     73 #define TEN_E5 (0x186A0)
     74 #define TEN_E6 (0xF4240)
     75 #define TEN_E7 (0x989680)
     76 #define TEN_E8 (0x5F5E100)
     77 #define TEN_E9 (0x3B9ACA00)
     78 #define TEN_E19 (0x8AC7230489E80000)
     79 #endif /* USE_L */
     80 #endif /* USE_LL */
     81 
     82 #define TIMES_TEN(x) (((x) << 3) + ((x) << 1))
     83 #define bitSection(x, mask, shift) (((x) & (mask)) >> (shift))
     84 #define DOUBLE_TO_LONGBITS(dbl) (*((U_64 *)(&dbl)))
     85 #define FLOAT_TO_INTBITS(flt) (*((U_32 *)(&flt)))
     86 #define CREATE_DOUBLE_BITS(normalizedM, e) (((normalizedM) & MANTISSA_MASK) | (((U_64)((e) + E_OFFSET)) << 52))
     87 
     88 #if defined(USE_LL)
     89 #define MANTISSA_MASK (0x000FFFFFFFFFFFFFLL)
     90 #define EXPONENT_MASK (0x7FF0000000000000LL)
     91 #define NORMAL_MASK (0x0010000000000000LL)
     92 #define SIGN_MASK (0x8000000000000000LL)
     93 #else
     94 #if defined(USE_L)
     95 #define MANTISSA_MASK (0x000FFFFFFFFFFFFFL)
     96 #define EXPONENT_MASK (0x7FF0000000000000L)
     97 #define NORMAL_MASK (0x0010000000000000L)
     98 #define SIGN_MASK (0x8000000000000000L)
     99 #else
    100 #define MANTISSA_MASK (0x000FFFFFFFFFFFFF)
    101 #define EXPONENT_MASK (0x7FF0000000000000)
    102 #define NORMAL_MASK (0x0010000000000000)
    103 #define SIGN_MASK (0x8000000000000000)
    104 #endif /* USE_L */
    105 #endif /* USE_LL */
    106 
    107 #define E_OFFSET (1075)
    108 
    109 #define FLOAT_MANTISSA_MASK (0x007FFFFF)
    110 #define FLOAT_EXPONENT_MASK (0x7F800000)
    111 #define FLOAT_NORMAL_MASK   (0x00800000)
    112 #define FLOAT_E_OFFSET (150)
    113 
    114 IDATA
    115 simpleAddHighPrecision (U_64 * arg1, IDATA length, U_64 arg2)
    116 {
    117   /* assumes length > 0 */
    118   IDATA index = 1;
    119 
    120   *arg1 += arg2;
    121   if (arg2 <= *arg1)
    122     return 0;
    123   else if (length == 1)
    124     return 1;
    125 
    126   while (++arg1[index] == 0 && ++index < length);
    127 
    128   return (IDATA) index == length;
    129 }
    130 
    131 IDATA
    132 addHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2)
    133 {
    134   /* addition is limited by length of arg1 as it this function is
    135    * storing the result in arg1 */
    136   /* fix for cc (GCC) 3.2 20020903 (Red Hat Linux 8.0 3.2-7): code generated does not
    137    * do the temp1 + temp2 + carry addition correct.  carry is 64 bit because gcc has
    138    * subtle issues when you mix 64 / 32 bit maths. */
    139   U_64 temp1, temp2, temp3;     /* temporary variables to help the SH-4, and gcc */
    140   U_64 carry;
    141   IDATA index;
    142 
    143   if (length1 == 0 || length2 == 0)
    144     {
    145       return 0;
    146     }
    147   else if (length1 < length2)
    148     {
    149       length2 = length1;
    150     }
    151 
    152   carry = 0;
    153   index = 0;
    154   do
    155     {
    156       temp1 = arg1[index];
    157       temp2 = arg2[index];
    158       temp3 = temp1 + temp2;
    159       arg1[index] = temp3 + carry;
    160       if (arg2[index] < arg1[index])
    161         carry = 0;
    162       else if (arg2[index] != arg1[index])
    163         carry = 1;
    164     }
    165   while (++index < length2);
    166   if (!carry)
    167     return 0;
    168   else if (index == length1)
    169     return 1;
    170 
    171   while (++arg1[index] == 0 && ++index < length1);
    172 
    173   return (IDATA) index == length1;
    174 }
    175 
    176 void
    177 subtractHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2)
    178 {
    179   /* assumes arg1 > arg2 */
    180   IDATA index;
    181   for (index = 0; index < length1; ++index)
    182     arg1[index] = ~arg1[index];
    183   simpleAddHighPrecision (arg1, length1, 1);
    184 
    185   while (length2 > 0 && arg2[length2 - 1] == 0)
    186     --length2;
    187 
    188   addHighPrecision (arg1, length1, arg2, length2);
    189 
    190   for (index = 0; index < length1; ++index)
    191     arg1[index] = ~arg1[index];
    192   simpleAddHighPrecision (arg1, length1, 1);
    193 }
    194 
    195 U_32
    196 simpleMultiplyHighPrecision (U_64 * arg1, IDATA length, U_64 arg2)
    197 {
    198   /* assumes arg2 only holds 32 bits of information */
    199   U_64 product;
    200   IDATA index;
    201 
    202   index = 0;
    203   product = 0;
    204 
    205   do
    206     {
    207       product =
    208         HIGH_IN_U64 (product) + arg2 * LOW_U32_FROM_PTR (arg1 + index);
    209       LOW_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (product);
    210       product =
    211         HIGH_IN_U64 (product) + arg2 * HIGH_U32_FROM_PTR (arg1 + index);
    212       HIGH_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (product);
    213     }
    214   while (++index < length);
    215 
    216   return HIGH_U32_FROM_VAR (product);
    217 }
    218 
    219 void
    220 simpleMultiplyAddHighPrecision (U_64 * arg1, IDATA length, U_64 arg2,
    221                                 U_32 * result)
    222 {
    223   /* Assumes result can hold the product and arg2 only holds 32 bits
    224      of information */
    225   U_64 product;
    226   IDATA index, resultIndex;
    227 
    228   index = resultIndex = 0;
    229   product = 0;
    230 
    231   do
    232     {
    233       product =
    234         HIGH_IN_U64 (product) + result[at (resultIndex)] +
    235         arg2 * LOW_U32_FROM_PTR (arg1 + index);
    236       result[at (resultIndex)] = LOW_U32_FROM_VAR (product);
    237       ++resultIndex;
    238       product =
    239         HIGH_IN_U64 (product) + result[at (resultIndex)] +
    240         arg2 * HIGH_U32_FROM_PTR (arg1 + index);
    241       result[at (resultIndex)] = LOW_U32_FROM_VAR (product);
    242       ++resultIndex;
    243     }
    244   while (++index < length);
    245 
    246   result[at (resultIndex)] += HIGH_U32_FROM_VAR (product);
    247   if (result[at (resultIndex)] < HIGH_U32_FROM_VAR (product))
    248     {
    249       /* must be careful with ++ operator and macro expansion */
    250       ++resultIndex;
    251       while (++result[at (resultIndex)] == 0)
    252         ++resultIndex;
    253     }
    254 }
    255 
    256 #ifndef HY_LITTLE_ENDIAN
    257 void simpleMultiplyAddHighPrecisionBigEndianFix(U_64 *arg1, IDATA length, U_64 arg2, U_32 *result) {
    258 	/* Assumes result can hold the product and arg2 only holds 32 bits
    259 	   of information */
    260 	U_64 product;
    261 	IDATA index, resultIndex;
    262 
    263 	index = resultIndex = 0;
    264 	product = 0;
    265 
    266 	do {
    267 		product = HIGH_IN_U64(product) + result[halfAt(resultIndex)] + arg2 * LOW_U32_FROM_PTR(arg1 + index);
    268 		result[halfAt(resultIndex)] = LOW_U32_FROM_VAR(product);
    269 		++resultIndex;
    270 		product = HIGH_IN_U64(product) + result[halfAt(resultIndex)] + arg2 * HIGH_U32_FROM_PTR(arg1 + index);
    271 		result[halfAt(resultIndex)] = LOW_U32_FROM_VAR(product);
    272 		++resultIndex;
    273 	} while (++index < length);
    274 
    275 	result[halfAt(resultIndex)] += HIGH_U32_FROM_VAR(product);
    276 	if (result[halfAt(resultIndex)] < HIGH_U32_FROM_VAR(product)) {
    277 		/* must be careful with ++ operator and macro expansion */
    278 		++resultIndex;
    279 		while (++result[halfAt(resultIndex)] == 0) ++resultIndex;
    280 	}
    281 }
    282 #endif
    283 
    284 void
    285 multiplyHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2,
    286                        U_64 * result, IDATA length)
    287 {
    288   /* assumes result is large enough to hold product */
    289   U_64 *temp;
    290   U_32 *resultIn32;
    291   IDATA count, index;
    292 
    293   if (length1 < length2)
    294     {
    295       temp = arg1;
    296       arg1 = arg2;
    297       arg2 = temp;
    298       count = length1;
    299       length1 = length2;
    300       length2 = count;
    301     }
    302 
    303   memset (result, 0, sizeof (U_64) * length);
    304 
    305   /* length1 > length2 */
    306   resultIn32 = (U_32 *) result;
    307   index = -1;
    308   for (count = 0; count < length2; ++count)
    309     {
    310       simpleMultiplyAddHighPrecision (arg1, length1, LOW_IN_U64 (arg2[count]),
    311                                       resultIn32 + (++index));
    312 #ifdef HY_LITTLE_ENDIAN
    313       simpleMultiplyAddHighPrecision(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index));
    314 #else
    315       simpleMultiplyAddHighPrecisionBigEndianFix(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index));
    316 #endif
    317     }
    318 }
    319 
    320 U_32
    321 simpleAppendDecimalDigitHighPrecision (U_64 * arg1, IDATA length, U_64 digit)
    322 {
    323   /* assumes digit is less than 32 bits */
    324   U_64 arg;
    325   IDATA index = 0;
    326 
    327   digit <<= 32;
    328   do
    329     {
    330       arg = LOW_IN_U64 (arg1[index]);
    331       digit = HIGH_IN_U64 (digit) + TIMES_TEN (arg);
    332       LOW_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (digit);
    333 
    334       arg = HIGH_IN_U64 (arg1[index]);
    335       digit = HIGH_IN_U64 (digit) + TIMES_TEN (arg);
    336       HIGH_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (digit);
    337     }
    338   while (++index < length);
    339 
    340   return HIGH_U32_FROM_VAR (digit);
    341 }
    342 
    343 void
    344 simpleShiftLeftHighPrecision (U_64 * arg1, IDATA length, IDATA arg2)
    345 {
    346   /* assumes length > 0 */
    347   IDATA index, offset;
    348   if (arg2 >= 64)
    349     {
    350       offset = arg2 >> 6;
    351       index = length;
    352 
    353       while (--index - offset >= 0)
    354         arg1[index] = arg1[index - offset];
    355       do
    356         {
    357           arg1[index] = 0;
    358         }
    359       while (--index >= 0);
    360 
    361       arg2 &= 0x3F;
    362     }
    363 
    364   if (arg2 == 0)
    365     return;
    366   while (--length > 0)
    367     {
    368       arg1[length] = arg1[length] << arg2 | arg1[length - 1] >> (64 - arg2);
    369     }
    370   *arg1 <<= arg2;
    371 }
    372 
    373 IDATA
    374 highestSetBit (U_64 * y)
    375 {
    376   U_32 x;
    377   IDATA result;
    378 
    379   if (*y == 0)
    380     return 0;
    381 
    382 #if defined(USE_LL)
    383   if (*y & 0xFFFFFFFF00000000LL)
    384     {
    385       x = HIGH_U32_FROM_PTR (y);
    386       result = 32;
    387     }
    388   else
    389     {
    390       x = LOW_U32_FROM_PTR (y);
    391       result = 0;
    392     }
    393 #else
    394 #if defined(USE_L)
    395   if (*y & 0xFFFFFFFF00000000L)
    396     {
    397       x = HIGH_U32_FROM_PTR (y);
    398       result = 32;
    399     }
    400   else
    401     {
    402       x = LOW_U32_FROM_PTR (y);
    403       result = 0;
    404     }
    405 #else
    406   if (*y & 0xFFFFFFFF00000000)
    407     {
    408       x = HIGH_U32_FROM_PTR (y);
    409       result = 32;
    410     }
    411   else
    412     {
    413       x = LOW_U32_FROM_PTR (y);
    414       result = 0;
    415     }
    416 #endif /* USE_L */
    417 #endif /* USE_LL */
    418 
    419   if (x & 0xFFFF0000)
    420     {
    421       x = bitSection (x, 0xFFFF0000, 16);
    422       result += 16;
    423     }
    424   if (x & 0xFF00)
    425     {
    426       x = bitSection (x, 0xFF00, 8);
    427       result += 8;
    428     }
    429   if (x & 0xF0)
    430     {
    431       x = bitSection (x, 0xF0, 4);
    432       result += 4;
    433     }
    434   if (x > 0x7)
    435     return result + 4;
    436   else if (x > 0x3)
    437     return result + 3;
    438   else if (x > 0x1)
    439     return result + 2;
    440   else
    441     return result + 1;
    442 }
    443 
    444 IDATA
    445 lowestSetBit (U_64 * y)
    446 {
    447   U_32 x;
    448   IDATA result;
    449 
    450   if (*y == 0)
    451     return 0;
    452 
    453 #if defined(USE_LL)
    454   if (*y & 0x00000000FFFFFFFFLL)
    455     {
    456       x = LOW_U32_FROM_PTR (y);
    457       result = 0;
    458     }
    459   else
    460     {
    461       x = HIGH_U32_FROM_PTR (y);
    462       result = 32;
    463     }
    464 #else
    465 #if defined(USE_L)
    466   if (*y & 0x00000000FFFFFFFFL)
    467     {
    468       x = LOW_U32_FROM_PTR (y);
    469       result = 0;
    470     }
    471   else
    472     {
    473       x = HIGH_U32_FROM_PTR (y);
    474       result = 32;
    475     }
    476 #else
    477   if (*y & 0x00000000FFFFFFFF)
    478     {
    479       x = LOW_U32_FROM_PTR (y);
    480       result = 0;
    481     }
    482   else
    483     {
    484       x = HIGH_U32_FROM_PTR (y);
    485       result = 32;
    486     }
    487 #endif /* USE_L */
    488 #endif /* USE_LL */
    489 
    490   if (!(x & 0xFFFF))
    491     {
    492       x = bitSection (x, 0xFFFF0000, 16);
    493       result += 16;
    494     }
    495   if (!(x & 0xFF))
    496     {
    497       x = bitSection (x, 0xFF00, 8);
    498       result += 8;
    499     }
    500   if (!(x & 0xF))
    501     {
    502       x = bitSection (x, 0xF0, 4);
    503       result += 4;
    504     }
    505 
    506   if (x & 0x1)
    507     return result + 1;
    508   else if (x & 0x2)
    509     return result + 2;
    510   else if (x & 0x4)
    511     return result + 3;
    512   else
    513     return result + 4;
    514 }
    515 
    516 IDATA
    517 highestSetBitHighPrecision (U_64 * arg, IDATA length)
    518 {
    519   IDATA highBit;
    520 
    521   while (--length >= 0)
    522     {
    523       highBit = highestSetBit (arg + length);
    524       if (highBit)
    525         return highBit + 64 * length;
    526     }
    527 
    528   return 0;
    529 }
    530 
    531 IDATA
    532 lowestSetBitHighPrecision (U_64 * arg, IDATA length)
    533 {
    534   IDATA lowBit, index = -1;
    535 
    536   while (++index < length)
    537     {
    538       lowBit = lowestSetBit (arg + index);
    539       if (lowBit)
    540         return lowBit + 64 * index;
    541     }
    542 
    543   return 0;
    544 }
    545 
    546 IDATA
    547 compareHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2)
    548 {
    549   while (--length1 >= 0 && arg1[length1] == 0);
    550   while (--length2 >= 0 && arg2[length2] == 0);
    551 
    552   if (length1 > length2)
    553     return 1;
    554   else if (length1 < length2)
    555     return -1;
    556   else if (length1 > -1)
    557     {
    558       do
    559         {
    560           if (arg1[length1] > arg2[length1])
    561             return 1;
    562           else if (arg1[length1] < arg2[length1])
    563             return -1;
    564         }
    565       while (--length1 >= 0);
    566     }
    567 
    568   return 0;
    569 }
    570 
    571 jdouble
    572 toDoubleHighPrecision (U_64 * arg, IDATA length)
    573 {
    574   IDATA highBit;
    575   U_64 mantissa, test64;
    576   U_32 test;
    577   jdouble result;
    578 
    579   while (length > 0 && arg[length - 1] == 0)
    580     --length;
    581 
    582   if (length == 0)
    583     result = 0.0;
    584   else if (length > 16)
    585     {
    586       DOUBLE_TO_LONGBITS (result) = EXPONENT_MASK;
    587     }
    588   else if (length == 1)
    589     {
    590       highBit = highestSetBit (arg);
    591       if (highBit <= 53)
    592         {
    593           highBit = 53 - highBit;
    594           mantissa = *arg << highBit;
    595           DOUBLE_TO_LONGBITS (result) =
    596             CREATE_DOUBLE_BITS (mantissa, -highBit);
    597         }
    598       else
    599         {
    600           highBit -= 53;
    601           mantissa = *arg >> highBit;
    602           DOUBLE_TO_LONGBITS (result) =
    603             CREATE_DOUBLE_BITS (mantissa, highBit);
    604 
    605           /* perform rounding, round to even in case of tie */
    606           test = (LOW_U32_FROM_PTR (arg) << (11 - highBit)) & 0x7FF;
    607           if (test > 0x400 || ((test == 0x400) && (mantissa & 1)))
    608             DOUBLE_TO_LONGBITS (result) = DOUBLE_TO_LONGBITS (result) + 1;
    609         }
    610     }
    611   else
    612     {
    613       highBit = highestSetBit (arg + (--length));
    614       if (highBit <= 53)
    615         {
    616           highBit = 53 - highBit;
    617           if (highBit > 0)
    618             {
    619               mantissa =
    620                 (arg[length] << highBit) | (arg[length - 1] >>
    621                                             (64 - highBit));
    622             }
    623           else
    624             {
    625               mantissa = arg[length];
    626             }
    627           DOUBLE_TO_LONGBITS (result) =
    628             CREATE_DOUBLE_BITS (mantissa, length * 64 - highBit);
    629 
    630           /* perform rounding, round to even in case of tie */
    631           test64 = arg[--length] << highBit;
    632           if (test64 > SIGN_MASK || ((test64 == SIGN_MASK) && (mantissa & 1)))
    633             DOUBLE_TO_LONGBITS (result) = DOUBLE_TO_LONGBITS (result) + 1;
    634           else if (test64 == SIGN_MASK)
    635             {
    636               while (--length >= 0)
    637                 {
    638                   if (arg[length] != 0)
    639                     {
    640                       DOUBLE_TO_LONGBITS (result) =
    641                         DOUBLE_TO_LONGBITS (result) + 1;
    642                       break;
    643                     }
    644                 }
    645             }
    646         }
    647       else
    648         {
    649           highBit -= 53;
    650           mantissa = arg[length] >> highBit;
    651           DOUBLE_TO_LONGBITS (result) =
    652             CREATE_DOUBLE_BITS (mantissa, length * 64 + highBit);
    653 
    654           /* perform rounding, round to even in case of tie */
    655           test = (LOW_U32_FROM_PTR (arg + length) << (11 - highBit)) & 0x7FF;
    656           if (test > 0x400 || ((test == 0x400) && (mantissa & 1)))
    657             DOUBLE_TO_LONGBITS (result) = DOUBLE_TO_LONGBITS (result) + 1;
    658           else if (test == 0x400)
    659             {
    660               do
    661                 {
    662                   if (arg[--length] != 0)
    663                     {
    664                       DOUBLE_TO_LONGBITS (result) =
    665                         DOUBLE_TO_LONGBITS (result) + 1;
    666                       break;
    667                     }
    668                 }
    669               while (length > 0);
    670             }
    671         }
    672     }
    673 
    674   return result;
    675 }
    676 
    677 IDATA
    678 tenToTheEHighPrecision (U_64 * result, IDATA length, jint e)
    679 {
    680   /* size test */
    681   if (length < ((e / 19) + 1))
    682     return 0;
    683 
    684   memset (result, 0, length * sizeof (U_64));
    685   *result = 1;
    686 
    687   if (e == 0)
    688     return 1;
    689 
    690   length = 1;
    691   length = timesTenToTheEHighPrecision (result, length, e);
    692   /* bad O(n) way of doing it, but simple */
    693   /*
    694      do {
    695      overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0);
    696      if (overflow)
    697      result[length++] = overflow;
    698      } while (--e);
    699    */
    700   return length;
    701 }
    702 
    703 IDATA
    704 timesTenToTheEHighPrecision (U_64 * result, IDATA length, jint e)
    705 {
    706   /* assumes result can hold value */
    707   U_64 overflow;
    708   int exp10 = e;
    709 
    710   if (e == 0)
    711     return length;
    712 
    713   /* bad O(n) way of doing it, but simple */
    714   /*
    715      do {
    716      overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0);
    717      if (overflow)
    718      result[length++] = overflow;
    719      } while (--e);
    720    */
    721   /* Replace the current implementaion which performs a
    722    * "multiplication" by 10 e number of times with an actual
    723    * multiplication. 10e19 is the largest exponent to the power of ten
    724    * that will fit in a 64-bit integer, and 10e9 is the largest exponent to
    725    * the power of ten that will fit in a 64-bit integer. Not sure where the
    726    * break-even point is between an actual multiplication and a
    727    * simpleAappendDecimalDigit() so just pick 10e3 as that point for
    728    * now.
    729    */
    730   while (exp10 >= 19)
    731     {
    732       overflow = simpleMultiplyHighPrecision64 (result, length, TEN_E19);
    733       if (overflow)
    734         result[length++] = overflow;
    735       exp10 -= 19;
    736     }
    737   while (exp10 >= 9)
    738     {
    739       overflow = simpleMultiplyHighPrecision (result, length, TEN_E9);
    740       if (overflow)
    741         result[length++] = overflow;
    742       exp10 -= 9;
    743     }
    744   if (exp10 == 0)
    745     return length;
    746   else if (exp10 == 1)
    747     {
    748       overflow = simpleAppendDecimalDigitHighPrecision (result, length, 0);
    749       if (overflow)
    750         result[length++] = overflow;
    751     }
    752   else if (exp10 == 2)
    753     {
    754       overflow = simpleAppendDecimalDigitHighPrecision (result, length, 0);
    755       if (overflow)
    756         result[length++] = overflow;
    757       overflow = simpleAppendDecimalDigitHighPrecision (result, length, 0);
    758       if (overflow)
    759         result[length++] = overflow;
    760     }
    761   else if (exp10 == 3)
    762     {
    763       overflow = simpleMultiplyHighPrecision (result, length, TEN_E3);
    764       if (overflow)
    765         result[length++] = overflow;
    766     }
    767   else if (exp10 == 4)
    768     {
    769       overflow = simpleMultiplyHighPrecision (result, length, TEN_E4);
    770       if (overflow)
    771         result[length++] = overflow;
    772     }
    773   else if (exp10 == 5)
    774     {
    775       overflow = simpleMultiplyHighPrecision (result, length, TEN_E5);
    776       if (overflow)
    777         result[length++] = overflow;
    778     }
    779   else if (exp10 == 6)
    780     {
    781       overflow = simpleMultiplyHighPrecision (result, length, TEN_E6);
    782       if (overflow)
    783         result[length++] = overflow;
    784     }
    785   else if (exp10 == 7)
    786     {
    787       overflow = simpleMultiplyHighPrecision (result, length, TEN_E7);
    788       if (overflow)
    789         result[length++] = overflow;
    790     }
    791   else if (exp10 == 8)
    792     {
    793       overflow = simpleMultiplyHighPrecision (result, length, TEN_E8);
    794       if (overflow)
    795         result[length++] = overflow;
    796     }
    797   return length;
    798 }
    799 
    800 U_64
    801 doubleMantissa (jdouble z)
    802 {
    803   U_64 m = DOUBLE_TO_LONGBITS (z);
    804 
    805   if ((m & EXPONENT_MASK) != 0)
    806     m = (m & MANTISSA_MASK) | NORMAL_MASK;
    807   else
    808     m = (m & MANTISSA_MASK);
    809 
    810   return m;
    811 }
    812 
    813 IDATA
    814 doubleExponent (jdouble z)
    815 {
    816   /* assumes positive double */
    817   IDATA k = HIGH_U32_FROM_VAR (z) >> 20;
    818 
    819   if (k)
    820     k -= E_OFFSET;
    821   else
    822     k = 1 - E_OFFSET;
    823 
    824   return k;
    825 }
    826 
    827 UDATA
    828 floatMantissa (jfloat z)
    829 {
    830   UDATA m = (UDATA) FLOAT_TO_INTBITS (z);
    831 
    832   if ((m & FLOAT_EXPONENT_MASK) != 0)
    833     m = (m & FLOAT_MANTISSA_MASK) | FLOAT_NORMAL_MASK;
    834   else
    835     m = (m & FLOAT_MANTISSA_MASK);
    836 
    837   return m;
    838 }
    839 
    840 IDATA
    841 floatExponent (jfloat z)
    842 {
    843   /* assumes positive float */
    844   IDATA k = FLOAT_TO_INTBITS (z) >> 23;
    845   if (k)
    846     k -= FLOAT_E_OFFSET;
    847   else
    848     k = 1 - FLOAT_E_OFFSET;
    849 
    850   return k;
    851 }
    852 
    853 /* Allow a 64-bit value in arg2 */
    854 U_64
    855 simpleMultiplyHighPrecision64 (U_64 * arg1, IDATA length, U_64 arg2)
    856 {
    857   U_64 intermediate, *pArg1, carry1, carry2, prod1, prod2, sum;
    858   IDATA index;
    859   U_32 buf32;
    860 
    861   index = 0;
    862   intermediate = 0;
    863   pArg1 = arg1 + index;
    864   carry1 = carry2 = 0;
    865 
    866   do
    867     {
    868       if ((*pArg1 != 0) || (intermediate != 0))
    869         {
    870           prod1 =
    871             (U_64) LOW_U32_FROM_VAR (arg2) * (U_64) LOW_U32_FROM_PTR (pArg1);
    872           sum = intermediate + prod1;
    873           if ((sum < prod1) || (sum < intermediate))
    874             {
    875               carry1 = 1;
    876             }
    877           else
    878             {
    879               carry1 = 0;
    880             }
    881           prod1 =
    882             (U_64) LOW_U32_FROM_VAR (arg2) * (U_64) HIGH_U32_FROM_PTR (pArg1);
    883           prod2 =
    884             (U_64) HIGH_U32_FROM_VAR (arg2) * (U_64) LOW_U32_FROM_PTR (pArg1);
    885           intermediate = carry2 + HIGH_IN_U64 (sum) + prod1 + prod2;
    886           if ((intermediate < prod1) || (intermediate < prod2))
    887             {
    888               carry2 = 1;
    889             }
    890           else
    891             {
    892               carry2 = 0;
    893             }
    894           LOW_U32_FROM_PTR (pArg1) = LOW_U32_FROM_VAR (sum);
    895           buf32 = HIGH_U32_FROM_PTR (pArg1);
    896           HIGH_U32_FROM_PTR (pArg1) = LOW_U32_FROM_VAR (intermediate);
    897           intermediate = carry1 + HIGH_IN_U64 (intermediate)
    898             + (U_64) HIGH_U32_FROM_VAR (arg2) * (U_64) buf32;
    899         }
    900       pArg1++;
    901     }
    902   while (++index < length);
    903   return intermediate;
    904 }
    905