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 <stdlib.h>
     19 #include <string.h>
     20 #include <math.h>
     21 #include "JNIHelp.h"
     22 #include "commonDblParce.h"
     23 #include "cbigint.h"
     24 
     25 #if defined(LINUX) || defined(FREEBSD) || defined(ZOS)
     26 #define USE_LL
     27 #endif
     28 
     29 #define LOW_I32_FROM_VAR(u64)     LOW_I32_FROM_LONG64(u64)
     30 #ifdef HY_LITTLE_ENDIAN
     31 #define LOW_I32_FROM_PTR(ptr64) (*(I_32 *) (ptr64))
     32 #else
     33 #define LOW_I32_FROM_PTR(ptr64) (*(((I_32 *) (ptr64)) + 1))
     34 #endif
     35 #define HIGH_I32_FROM_VAR(u64)    HIGH_I32_FROM_LONG64(u64)
     36 #define HIGH_I32_FROM_PTR(u64ptr) HIGH_I32_FROM_LONG64_PTR(u64ptr)
     37 
     38 #define MAX_ACCURACY_WIDTH 8
     39 
     40 #define DEFAULT_WIDTH MAX_ACCURACY_WIDTH
     41 
     42 JNIEXPORT jfloat JNICALL
     43 Java_org_apache_harmony_luni_util_FloatingPointParser_parseFltImpl (JNIEnv * env,
     44                                                         jclass clazz,
     45                                                         jstring s, jint e);
     46 JNIEXPORT jdouble JNICALL
     47 Java_org_apache_harmony_luni_util_FloatingPointParser_parseDblImpl (JNIEnv * env,
     48                                                         jclass clazz,
     49                                                         jstring s, jint e);
     50 
     51 jfloat createFloat1 (JNIEnv * env, U_64 * f, IDATA length, jint e);
     52 jfloat floatAlgorithm (JNIEnv * env, U_64 * f, IDATA length, jint e,
     53                        jfloat z);
     54 jfloat createFloat (JNIEnv * env, const char *s, jint e);
     55 
     56 static const U_32 tens[] = {
     57   0x3f800000,
     58   0x41200000,
     59   0x42c80000,
     60   0x447a0000,
     61   0x461c4000,
     62   0x47c35000,
     63   0x49742400,
     64   0x4b189680,
     65   0x4cbebc20,
     66   0x4e6e6b28,
     67   0x501502f9                    /* 10 ^ 10 in float */
     68 };
     69 
     70 #define tenToTheE(e) (*((jfloat *) (tens + (e))))
     71 #define LOG5_OF_TWO_TO_THE_N 11
     72 
     73 #define sizeOfTenToTheE(e) (((e) / 19) + 1)
     74 
     75 #define INFINITE_INTBITS (0x7F800000)
     76 #define MINIMUM_INTBITS (1)
     77 
     78 #define MANTISSA_MASK (0x007FFFFF)
     79 #define EXPONENT_MASK (0x7F800000)
     80 #define NORMAL_MASK   (0x00800000)
     81 #define FLOAT_TO_INTBITS(flt) (*((U_32 *)(&flt)))
     82 
     83 /* Keep a count of the number of times we decrement and increment to
     84  * approximate the double, and attempt to detect the case where we
     85  * could potentially toggle back and forth between decrementing and
     86  * incrementing. It is possible for us to be stuck in the loop when
     87  * incrementing by one or decrementing by one may exceed or stay below
     88  * the value that we are looking for. In this case, just break out of
     89  * the loop if we toggle between incrementing and decrementing for more
     90  * than twice.
     91  */
     92 #define INCREMENT_FLOAT(_x, _decCount, _incCount) \
     93     { \
     94         ++FLOAT_TO_INTBITS(_x); \
     95         _incCount++; \
     96         if( (_incCount > 2) && (_decCount > 2) ) { \
     97             if( _decCount > _incCount ) { \
     98                 FLOAT_TO_INTBITS(_x) += _decCount - _incCount; \
     99             } else if( _incCount > _decCount ) { \
    100                 FLOAT_TO_INTBITS(_x) -= _incCount - _decCount; \
    101             } \
    102             break; \
    103         } \
    104     }
    105 #define DECREMENT_FLOAT(_x, _decCount, _incCount) \
    106     { \
    107         --FLOAT_TO_INTBITS(_x); \
    108         _decCount++; \
    109         if( (_incCount > 2) && (_decCount > 2) ) { \
    110             if( _decCount > _incCount ) { \
    111                 FLOAT_TO_INTBITS(_x) += _decCount - _incCount; \
    112             } else if( _incCount > _decCount ) { \
    113                 FLOAT_TO_INTBITS(_x) -= _incCount - _decCount; \
    114             } \
    115             break; \
    116         } \
    117     }
    118 #define ERROR_OCCURED(x) (HIGH_I32_FROM_VAR(x) < 0)
    119 
    120 #define allocateU64(x, n) if (!((x) = (U_64*) malloc((n) * sizeof(U_64)))) goto OutOfMemory;
    121 #define release(r) if ((r)) free((r));
    122 
    123 jfloat
    124 createFloat (JNIEnv * env, const char *s, jint e)
    125 {
    126   /* assumes s is a null terminated string with at least one
    127    * character in it */
    128   U_64 def[DEFAULT_WIDTH];
    129   U_64 defBackup[DEFAULT_WIDTH];
    130   U_64 *f, *fNoOverflow, *g, *tempBackup;
    131   U_32 overflow;
    132   jfloat result;
    133   IDATA index = 1;
    134   int unprocessedDigits = 0;
    135 
    136   f = def;
    137   fNoOverflow = defBackup;
    138   *f = 0;
    139   tempBackup = g = 0;
    140   do
    141     {
    142       if (*s >= '0' && *s <= '9')
    143         {
    144           /* Make a back up of f before appending, so that we can
    145            * back out of it if there is no more room, i.e. index >
    146            * MAX_ACCURACY_WIDTH.
    147            */
    148           memcpy (fNoOverflow, f, sizeof (U_64) * index);
    149           overflow =
    150             simpleAppendDecimalDigitHighPrecision (f, index, *s - '0');
    151           if (overflow)
    152             {
    153 
    154               f[index++] = overflow;
    155               /* There is an overflow, but there is no more room
    156                * to store the result. We really only need the top 52
    157                * bits anyway, so we must back out of the overflow,
    158                * and ignore the rest of the string.
    159                */
    160               if (index >= MAX_ACCURACY_WIDTH)
    161                 {
    162                   index--;
    163                   memcpy (f, fNoOverflow, sizeof (U_64) * index);
    164                   break;
    165                 }
    166               if (tempBackup)
    167                 {
    168                   fNoOverflow = tempBackup;
    169                 }
    170             }
    171         }
    172       else
    173         index = -1;
    174     }
    175   while (index > 0 && *(++s) != '\0');
    176 
    177   /* We've broken out of the parse loop either because we've reached
    178    * the end of the string or we've overflowed the maximum accuracy
    179    * limit of a double. If we still have unprocessed digits in the
    180    * given string, then there are three possible results:
    181    *   1. (unprocessed digits + e) == 0, in which case we simply
    182    *      convert the existing bits that are already parsed
    183    *   2. (unprocessed digits + e) < 0, in which case we simply
    184    *      convert the existing bits that are already parsed along
    185    *      with the given e
    186    *   3. (unprocessed digits + e) > 0 indicates that the value is
    187    *      simply too big to be stored as a double, so return Infinity
    188    */
    189   if ((unprocessedDigits = strlen (s)) > 0)
    190     {
    191       e += unprocessedDigits;
    192       if (index > -1)
    193         {
    194           if (e <= 0)
    195             {
    196               result = createFloat1 (env, f, index, e);
    197             }
    198           else
    199             {
    200               FLOAT_TO_INTBITS (result) = INFINITE_INTBITS;
    201             }
    202         }
    203       else
    204         {
    205           result = *(jfloat *) & index;
    206         }
    207     }
    208   else
    209     {
    210       if (index > -1)
    211         {
    212           result = createFloat1 (env, f, index, e);
    213         }
    214       else
    215         {
    216         result = *(jfloat *) & index;
    217         }
    218     }
    219 
    220   return result;
    221 
    222 }
    223 
    224 jfloat
    225 createFloat1 (JNIEnv * env, U_64 * f, IDATA length, jint e)
    226 {
    227   IDATA numBits;
    228   jdouble dresult;
    229   jfloat result;
    230 
    231   numBits = highestSetBitHighPrecision (f, length) + 1;
    232   if (numBits < 25 && e >= 0 && e < LOG5_OF_TWO_TO_THE_N)
    233     {
    234       return ((jfloat) LOW_I32_FROM_PTR (f)) * tenToTheE (e);
    235     }
    236   else if (numBits < 25 && e < 0 && (-e) < LOG5_OF_TWO_TO_THE_N)
    237     {
    238       return ((jfloat) LOW_I32_FROM_PTR (f)) / tenToTheE (-e);
    239     }
    240   else if (e >= 0 && e < 39)
    241     {
    242       result = (jfloat) (toDoubleHighPrecision (f, length) * pow (10.0, (double) e));
    243     }
    244   else if (e >= 39)
    245     {
    246       /* Convert the partial result to make sure that the
    247        * non-exponential part is not zero. This check fixes the case
    248        * where the user enters 0.0e309! */
    249       result = (jfloat) toDoubleHighPrecision (f, length);
    250 
    251       if (result == 0.0)
    252 
    253         FLOAT_TO_INTBITS (result) = MINIMUM_INTBITS;
    254       else
    255         FLOAT_TO_INTBITS (result) = INFINITE_INTBITS;
    256     }
    257   else if (e > -309)
    258     {
    259       int dexp;
    260       U_32 fmant, fovfl;
    261       U_64 dmant;
    262       dresult = toDoubleHighPrecision (f, length) / pow (10.0, (double) -e);
    263       if (IS_DENORMAL_DBL (dresult))
    264         {
    265           FLOAT_TO_INTBITS (result) = 0;
    266           return result;
    267         }
    268       dexp = doubleExponent (dresult) + 51;
    269       dmant = doubleMantissa (dresult);
    270       /* Is it too small to be represented by a single-precision
    271        * float? */
    272       if (dexp <= -155)
    273         {
    274           FLOAT_TO_INTBITS (result) = 0;
    275           return result;
    276         }
    277       /* Is it a denormalized single-precision float? */
    278       if ((dexp <= -127) && (dexp > -155))
    279         {
    280           /* Only interested in 24 msb bits of the 53-bit double mantissa */
    281           fmant = (U_32) (dmant >> 29);
    282           fovfl = ((U_32) (dmant & 0x1FFFFFFF)) << 3;
    283           while ((dexp < -127) && ((fmant | fovfl) != 0))
    284             {
    285               if ((fmant & 1) != 0)
    286                 {
    287                   fovfl |= 0x80000000;
    288                 }
    289               fovfl >>= 1;
    290               fmant >>= 1;
    291               dexp++;
    292             }
    293           if ((fovfl & 0x80000000) != 0)
    294             {
    295               if ((fovfl & 0x7FFFFFFC) != 0)
    296                 {
    297                   fmant++;
    298                 }
    299               else if ((fmant & 1) != 0)
    300                 {
    301                   fmant++;
    302                 }
    303             }
    304           else if ((fovfl & 0x40000000) != 0)
    305             {
    306               if ((fovfl & 0x3FFFFFFC) != 0)
    307                 {
    308                   fmant++;
    309                 }
    310             }
    311           FLOAT_TO_INTBITS (result) = fmant;
    312         }
    313       else
    314         {
    315           result = (jfloat) dresult;
    316         }
    317     }
    318 
    319   /* Don't go straight to zero as the fact that x*0 = 0 independent
    320    * of x might cause the algorithm to produce an incorrect result.
    321    * Instead try the min  value first and let it fall to zero if need
    322    * be.
    323    */
    324   if (e <= -309 || FLOAT_TO_INTBITS (result) == 0)
    325     FLOAT_TO_INTBITS (result) = MINIMUM_INTBITS;
    326 
    327   return floatAlgorithm (env, f, length, e, (jfloat) result);
    328 }
    329 
    330 #if defined(WIN32)
    331 /* disable global optimizations on the microsoft compiler for the
    332  * floatAlgorithm function otherwise it won't properly compile */
    333 #pragma optimize("g",off)
    334 #endif
    335 
    336 /* The algorithm for the function floatAlgorithm() below can be found
    337  * in:
    338  *
    339  *      "How to Read Floating-Point Numbers Accurately", William D.
    340  *      Clinger, Proceedings of the ACM SIGPLAN '90 Conference on
    341  *      Programming Language Design and Implementation, June 20-22,
    342  *      1990, pp. 92-101.
    343  *
    344  * There is a possibility that the function will end up in an endless
    345  * loop if the given approximating floating-point number (a very small
    346  * floating-point whose value is very close to zero) straddles between
    347  * two approximating integer values. We modified the algorithm slightly
    348  * to detect the case where it oscillates back and forth between
    349  * incrementing and decrementing the floating-point approximation. It
    350  * is currently set such that if the oscillation occurs more than twice
    351  * then return the original approximation.
    352  */
    353 jfloat
    354 floatAlgorithm (JNIEnv * env, U_64 * f, IDATA length, jint e, jfloat z)
    355 {
    356   U_64 m;
    357   IDATA k, comparison, comparison2;
    358   U_64 *x, *y, *D, *D2;
    359   IDATA xLength, yLength, DLength, D2Length;
    360   IDATA decApproxCount, incApproxCount;
    361 
    362   x = y = D = D2 = 0;
    363   xLength = yLength = DLength = D2Length = 0;
    364   decApproxCount = incApproxCount = 0;
    365 
    366   do
    367     {
    368       m = floatMantissa (z);
    369       k = floatExponent (z);
    370 
    371       if (x && x != f)
    372           free(x);
    373 
    374       release (y);
    375       release (D);
    376       release (D2);
    377 
    378       if (e >= 0 && k >= 0)
    379         {
    380           xLength = sizeOfTenToTheE (e) + length;
    381           allocateU64 (x, xLength);
    382           memset (x + length, 0, sizeof (U_64) * (xLength - length));
    383           memcpy (x, f, sizeof (U_64) * length);
    384           timesTenToTheEHighPrecision (x, xLength, e);
    385 
    386           yLength = (k >> 6) + 2;
    387           allocateU64 (y, yLength);
    388           memset (y + 1, 0, sizeof (U_64) * (yLength - 1));
    389           *y = m;
    390           simpleShiftLeftHighPrecision (y, yLength, k);
    391         }
    392       else if (e >= 0)
    393         {
    394           xLength = sizeOfTenToTheE (e) + length + ((-k) >> 6) + 1;
    395           allocateU64 (x, xLength);
    396           memset (x + length, 0, sizeof (U_64) * (xLength - length));
    397           memcpy (x, f, sizeof (U_64) * length);
    398           timesTenToTheEHighPrecision (x, xLength, e);
    399           simpleShiftLeftHighPrecision (x, xLength, -k);
    400 
    401           yLength = 1;
    402           allocateU64 (y, 1);
    403           *y = m;
    404         }
    405       else if (k >= 0)
    406         {
    407           xLength = length;
    408           x = f;
    409 
    410           yLength = sizeOfTenToTheE (-e) + 2 + (k >> 6);
    411           allocateU64 (y, yLength);
    412           memset (y + 1, 0, sizeof (U_64) * (yLength - 1));
    413           *y = m;
    414           timesTenToTheEHighPrecision (y, yLength, -e);
    415           simpleShiftLeftHighPrecision (y, yLength, k);
    416         }
    417       else
    418         {
    419           xLength = length + ((-k) >> 6) + 1;
    420           allocateU64 (x, xLength);
    421           memset (x + length, 0, sizeof (U_64) * (xLength - length));
    422           memcpy (x, f, sizeof (U_64) * length);
    423           simpleShiftLeftHighPrecision (x, xLength, -k);
    424 
    425           yLength = sizeOfTenToTheE (-e) + 1;
    426           allocateU64 (y, yLength);
    427           memset (y + 1, 0, sizeof (U_64) * (yLength - 1));
    428           *y = m;
    429           timesTenToTheEHighPrecision (y, yLength, -e);
    430         }
    431 
    432       comparison = compareHighPrecision (x, xLength, y, yLength);
    433       if (comparison > 0)
    434         {                       /* x > y */
    435           DLength = xLength;
    436           allocateU64 (D, DLength);
    437           memcpy (D, x, DLength * sizeof (U_64));
    438           subtractHighPrecision (D, DLength, y, yLength);
    439         }
    440       else if (comparison)
    441         {                       /* y > x */
    442           DLength = yLength;
    443           allocateU64 (D, DLength);
    444           memcpy (D, y, DLength * sizeof (U_64));
    445           subtractHighPrecision (D, DLength, x, xLength);
    446         }
    447       else
    448         {                       /* y == x */
    449           DLength = 1;
    450           allocateU64 (D, 1);
    451           *D = 0;
    452         }
    453 
    454       D2Length = DLength + 1;
    455       allocateU64 (D2, D2Length);
    456       m <<= 1;
    457       multiplyHighPrecision (D, DLength, &m, 1, D2, D2Length);
    458       m >>= 1;
    459 
    460       comparison2 = compareHighPrecision (D2, D2Length, y, yLength);
    461       if (comparison2 < 0)
    462         {
    463           if (comparison < 0 && m == NORMAL_MASK)
    464             {
    465               simpleShiftLeftHighPrecision (D2, D2Length, 1);
    466               if (compareHighPrecision (D2, D2Length, y, yLength) > 0)
    467                 {
    468                   DECREMENT_FLOAT (z, decApproxCount, incApproxCount);
    469                 }
    470               else
    471                 {
    472                   break;
    473                 }
    474             }
    475           else
    476             {
    477               break;
    478             }
    479         }
    480       else if (comparison2 == 0)
    481         {
    482           if ((m & 1) == 0)
    483             {
    484               if (comparison < 0 && m == NORMAL_MASK)
    485                 {
    486                   DECREMENT_FLOAT (z, decApproxCount, incApproxCount);
    487                 }
    488               else
    489                 {
    490                   break;
    491                 }
    492             }
    493           else if (comparison < 0)
    494             {
    495               DECREMENT_FLOAT (z, decApproxCount, incApproxCount);
    496               break;
    497             }
    498           else
    499             {
    500               INCREMENT_FLOAT (z, decApproxCount, incApproxCount);
    501               break;
    502             }
    503         }
    504       else if (comparison < 0)
    505         {
    506           DECREMENT_FLOAT (z, decApproxCount, incApproxCount);
    507         }
    508       else
    509         {
    510           if (FLOAT_TO_INTBITS (z) == EXPONENT_MASK)
    511             break;
    512           INCREMENT_FLOAT (z, decApproxCount, incApproxCount);
    513         }
    514     }
    515   while (1);
    516 
    517   if (x && x != f)
    518       free(x);
    519   release (y);
    520   release (D);
    521   release (D2);
    522   return z;
    523 
    524 OutOfMemory:
    525   if (x && x != f)
    526       free(x);
    527   release (y);
    528   release (D);
    529   release (D2);
    530 
    531   FLOAT_TO_INTBITS (z) = -2;
    532 
    533   return z;
    534 }
    535 
    536 #if defined(WIN32)
    537 #pragma optimize("",on)         /*restore optimizations */
    538 #endif
    539 
    540 JNIEXPORT jfloat JNICALL
    541 Java_org_apache_harmony_luni_util_FloatingPointParser_parseFltImpl (JNIEnv * env,
    542                                                         jclass clazz,
    543                                                         jstring s, jint e)
    544 {
    545   jfloat flt;
    546   const char *str = (*env)->GetStringUTFChars (env, s, 0);
    547   flt = createFloat (env, str, e);
    548   (*env)->ReleaseStringUTFChars (env, s, str);
    549 
    550   if (((I_32) FLOAT_TO_INTBITS (flt)) >= 0)
    551     {
    552       return flt;
    553     }
    554   else if (((I_32) FLOAT_TO_INTBITS (flt)) == (I_32) - 1)
    555     {                           /* NumberFormatException */
    556       jniThrowException(env, "java/lang/NumberFormatException", "");
    557     }
    558   else
    559     {                           /* OutOfMemoryError */
    560       jniThrowException(env, "java/lang/OutOfMemoryError", "");
    561     }
    562 
    563   return 0.0;
    564 }
    565 
    566 JNIEXPORT jdouble JNICALL
    567 Java_org_apache_harmony_luni_util_FloatingPointParser_parseDblImpl (JNIEnv * env,
    568                                                         jclass clazz,
    569                                                         jstring s, jint e)
    570 {
    571   jdouble dbl;
    572   const char *str = (*env)->GetStringUTFChars (env, s, 0);
    573   dbl = createDouble (env, str, e);
    574   (*env)->ReleaseStringUTFChars (env, s, str);
    575 
    576   if (!ERROR_OCCURED (dbl))
    577     {
    578       return dbl;
    579     }
    580   else if (LOW_I32_FROM_VAR (dbl) == (I_32) - 1)
    581     {                           /* NumberFormatException */
    582       jniThrowException(env, "java/lang/NumberFormatException", "");
    583     }
    584   else
    585     {                           /* OutOfMemoryError */
    586       jniThrowException(env, "java/lang/OutOfMemoryError", "");
    587     }
    588 
    589   return 0.0;
    590 }
    591 
    592 /*
    593  * JNI registration
    594  */
    595 static JNINativeMethod gMethods[] = {
    596     /* NAME,          SIGNATURE,                FUNCPTR */
    597     { "parseFltImpl", "(Ljava/lang/String;I)F",
    598         Java_org_apache_harmony_luni_util_FloatingPointParser_parseFltImpl },
    599     { "parseDblImpl", "(Ljava/lang/String;I)D",
    600         Java_org_apache_harmony_luni_util_FloatingPointParser_parseDblImpl },
    601 };
    602 int register_org_apache_harmony_luni_util_fltparse(JNIEnv *env)
    603 {
    604     return jniRegisterNativeMethods(env,
    605                "org/apache/harmony/luni/util/FloatingPointParser",
    606                 gMethods, NELEM(gMethods));
    607 }
    608