Changes in / [badbb9ad:3508000] in mainline


Ignore:
Location:
uspace/lib/posix
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/stdlib/strtold.c

    rbadbb9ad r3508000  
    4646#include "../strings.h"
    4747#include "../errno.h"
    48 #include "../limits.h"
    49 
    50 // FIXME: #include <float.h>
    5148
    5249#ifndef HUGE_VALL
     
    5552
    5653#ifndef abs
    57         #define abs(x) (((x) < 0) ? -(x) : (x))
     54        #define abs(x) ((x < 0) ? -x : x)
    5855#endif
    5956
    60 /* If the constants are not defined, use double precision as default. */
    61 #ifndef LDBL_MANT_DIG
    62         #define LDBL_MANT_DIG 53
    63 #endif
    64 #ifndef LDBL_MAX_EXP
    65         #define LDBL_MAX_EXP 1024
    66 #endif
    67 #ifndef LDBL_MIN_EXP
    68         #define LDBL_MIN_EXP (-1021)
    69 #endif
    70 #ifndef LDBL_DIG
    71         #define LDBL_DIG 15
    72 #endif
    73 #ifndef LDBL_MIN
    74         #define LDBL_MIN 2.2250738585072014E-308
    75 #endif
    76 
    77 /* power functions ************************************************************/
    78 
    79 #if LDBL_MAX_EXP >= 16384
    80 const int MAX_POW5 = 12;
    81 #else
    82 const int MAX_POW5 = 8;
    83 #endif
     57// TODO: clean up
     58
     59// FIXME: ensure it builds and works on all platforms
     60
     61const int max_small_pow5 = 15;
     62
     63/* The value at index i is approximately 5**i. */
     64long double small_pow5[] = {
     65        0x1P0,
     66        0x5P0,
     67        0x19P0,
     68        0x7dP0,
     69        0x271P0,
     70        0xc35P0,
     71        0x3d09P0,
     72        0x1312dP0,
     73        0x5f5e1P0,
     74        0x1dcd65P0,
     75        0x9502f9P0,
     76        0x2e90eddP0,
     77        0xe8d4a51P0,
     78        0x48c27395P0,
     79        0x16bcc41e9P0,
     80        0x71afd498dP0
     81};
    8482
    8583/* The value at index i is approximately 5**(2**i). */
    86 long double pow5[] = {
    87         0x5p0l,
    88         0x19p0l,
    89         0x271p0l,
    90         0x5F5E1p0l,
    91         0x2386F26FC1p0l,
    92         0x4EE2D6D415B85ACEF81p0l,
    93         0x184F03E93FF9F4DAA797ED6E38ED6p36l,
    94         0x127748F9301D319BF8CDE66D86D62p185l,
    95         0x154FDD7F73BF3BD1BBB77203731FDp482l,
    96 #if LDBL_MAX_EXP >= 16384
    97         0x1C633415D4C1D238D98CAB8A978A0p1076l,
    98         0x192ECEB0D02EA182ECA1A7A51E316p2265l,
    99         0x13D1676BB8A7ABBC94E9A519C6535p4643l,
    100         0x188C0A40514412F3592982A7F0094p9398l,
    101 #endif
     84long double large_pow5[] = {
     85        0x5P0l,
     86        0x19P0l,
     87        0x271P0l,
     88        0x5f5e1P0l,
     89        0x2386f26fc1P0l,
     90        0x4ee2d6d415b85acef81P0l,
     91        0x184f03e93ff9f4daa797ed6e38ed64bf6a1f01P0l,
     92        0x24ee91f2603a6337f19bccdb0dac404dc08d3cff5ecP128l,
     93        0x553f75fdcefcef46eeddcP512l,
     94        0x1c633415d4c1d238d98cab8a978a0b1f138cb07303P1024l,
     95        0x325d9d61a05d4305d9434f4a3c62d433949ae6209d492P2200l,
     96        0x9e8b3b5dc53d5de4a74d28ce329ace526a3197bbebe3034f77154ce2bcba1964P4500l,
     97        0x6230290145104bcd64a60a9fc025254932bb0fd922271133eeae7P9300l
    10298};
    103 
    104 #if LDBL_MAX_EXP >= 16384
    105 const int MAX_POW2 = 15;
    106 #else
    107 const int MAX_POW2 = 9;
    108 #endif
    10999
    110100/* Powers of two. */
     
    120110        0x1P256l,
    121111        0x1P512l,
    122 #if LDBL_MAX_EXP >= 16384
    123112        0x1P1024l,
    124113        0x1P2048l,
    125114        0x1P4096l,
    126         0x1P8192l,
    127 #endif
     115        0x1P8192l
    128116};
    129117
    130118/**
     119 * Decides whether the argument is still in range representable by
     120 * long double or not.
     121 *
     122 * @param num Floating point number to be checked.
     123 * @return True if the argument is out of range, false otherwise.
     124 */
     125static inline bool out_of_range(long double num)
     126{
     127        return num == 0.0l || num == HUGE_VALL;
     128}
     129
     130/**
    131131 * Multiplies a number by a power of five.
    132  * The result may be inexact and may not be the best possible approximation.
    133  *
    134  * @param mant Number to be multiplied.
    135  * @param exp Base 5 exponent.
    136  * @return mant multiplied by 5**exp
    137  */
    138 static long double mul_pow5(long double mant, int exp)
    139 {
    140         if (mant == 0.0l || mant == HUGE_VALL) {
    141                 return mant;
    142         }
    143        
    144         if (abs(exp) >> (MAX_POW5 + 1) != 0) {
    145                 /* Too large exponent. */
     132 * The result is not exact and may not be the best possible approximation.
     133 *
     134 * @param base Number to be multiplied.
     135 * @param exponent Base 5 exponent.
     136 * @return base multiplied by 5**exponent.
     137 */
     138static long double mul_pow5(long double base, int exponent)
     139{
     140        if (out_of_range(base)) {
     141                return base;
     142        }
     143       
     144        if (abs(exponent) >> 13 != 0) {
    146145                errno = ERANGE;
    147                 return exp < 0 ? LDBL_MIN : HUGE_VALL;
    148         }
    149        
    150         if (exp < 0) {
    151                 exp = abs(exp);
    152                 for (int bit = 0; bit <= MAX_POW5; ++bit) {
    153                         /* Multiply by powers of five bit-by-bit. */
    154                         if (((exp >> bit) & 1) != 0) {
    155                                 mant /= pow5[bit];
    156                                 if (mant == 0.0l) {
    157                                         /* Underflow. */
    158                                         mant = LDBL_MIN;
     146                return exponent < 0 ? 0.0l : HUGE_VALL;
     147        }
     148       
     149        if (exponent < 0) {
     150                exponent = -exponent;
     151                base /= small_pow5[exponent & 0xF];
     152                for (int i = 4; i < 13; ++i) {
     153                        if (((exponent >> i) & 1) != 0) {
     154                                base /= large_pow5[i];
     155                                if (out_of_range(base)) {
    159156                                        errno = ERANGE;
    160157                                        break;
     
    163160                }
    164161        } else {
    165                 for (int bit = 0; bit <= MAX_POW5; ++bit) {
    166                         /* Multiply by powers of five bit-by-bit. */
    167                         if (((exp >> bit) & 1) != 0) {
    168                                 mant *= pow5[bit];
    169                                 if (mant == HUGE_VALL) {
    170                                         /* Overflow. */
     162                base *= small_pow5[exponent & 0xF];
     163                for (int i = 4; i < 13; ++i) {
     164                        if (((exponent >> i) & 1) != 0) {
     165                                base *= large_pow5[i];
     166                                if (out_of_range(base)) {
    171167                                        errno = ERANGE;
    172168                                        break;
     
    176172        }
    177173       
    178         return mant;
    179 }
    180 
    181 /**
    182  * Multiplies a number by a power of two. This is always exact.
    183  *
    184  * @param mant Number to be multiplied.
    185  * @param exp Base 2 exponent.
    186  * @return mant multiplied by 2**exp.
    187  */
    188 static long double mul_pow2(long double mant, int exp)
    189 {
    190         if (mant == 0.0l || mant == HUGE_VALL) {
    191                 return mant;
    192         }
    193        
    194         if (exp > LDBL_MAX_EXP || exp < LDBL_MIN_EXP) {
     174        return base;
     175}
     176
     177/**
     178 * Multiplies a number by a power of two.
     179 *
     180 * @param base Number to be multiplied.
     181 * @param exponent Base 2 exponent.
     182 * @return base multiplied by 2**exponent.
     183 */
     184static long double mul_pow2(long double base, int exponent)
     185{
     186        if (out_of_range(base)) {
     187                return base;
     188        }
     189       
     190        if (abs(exponent) >> 14 != 0) {
    195191                errno = ERANGE;
    196                 return exp < 0 ? LDBL_MIN : HUGE_VALL;
    197         }
    198        
    199         if (exp < 0) {
    200                 exp = abs(exp);
    201                 for (int i = 0; i <= MAX_POW2; ++i) {
    202                         if (((exp >> i) & 1) != 0) {
    203                                 mant /= pow2[i];
    204                                 if (mant == 0.0l) {
    205                                         mant = LDBL_MIN;
     192                return exponent < 0 ? 0.0l : HUGE_VALL;
     193        }
     194       
     195        if (exponent < 0) {
     196                exponent = -exponent;
     197                for (int i = 0; i < 14; ++i) {
     198                        if (((exponent >> i) & 1) != 0) {
     199                                base /= pow2[i];
     200                                if (out_of_range(base)) {
    206201                                        errno = ERANGE;
    207202                                        break;
     
    210205                }
    211206        } else {
    212                 for (int i = 0; i <= MAX_POW2; ++i) {
    213                         if (((exp >> i) & 1) != 0) {
    214                                 mant *= pow2[i];
    215                                 if (mant == HUGE_VALL) {
     207                for (int i = 0; i < 14; ++i) {
     208                        if (((exponent >> i) & 1) != 0) {
     209                                base *= pow2[i];
     210                                if (out_of_range(base)) {
    216211                                        errno = ERANGE;
    217212                                        break;
     
    221216        }
    222217       
    223         return mant;
    224 }
    225 
    226 /* end power functions ********************************************************/
    227 
    228 
     218        return base;
     219}
    229220
    230221/**
     
    240231static long double parse_decimal(const char **sptr)
    241232{
    242         assert(sptr != NULL);
    243         assert (*sptr != NULL);
     233        // TODO: Use strtol(), at least for exponent.
    244234       
    245235        const int DEC_BASE = 10;
    246236        const char DECIMAL_POINT = '.';
    247237        const char EXPONENT_MARK = 'e';
    248        
    249         const char *str = *sptr;
    250         long double significand = 0;
    251         long exponent = 0;
     238        /* The highest amount of digits that can be safely parsed
     239         * before an overflow occurs.
     240         */
     241        const int PARSE_DECIMAL_DIGS = 19;
     242       
     243        /* significand */
     244        uint64_t significand = 0;
     245       
     246        /* position in the input string */
     247        int i = 0;
    252248       
    253249        /* number of digits parsed so far */
    254250        int parsed_digits = 0;
    255         bool after_decimal = false;
    256        
    257         while (isdigit(*str) || (!after_decimal && *str == DECIMAL_POINT)) {
    258                 if (*str == DECIMAL_POINT) {
    259                         after_decimal = true;
    260                         str++;
    261                         continue;
    262                 }
    263                
    264                 if (parsed_digits == 0 && *str == '0') {
     251       
     252        int exponent = 0;
     253       
     254        const char *str = *sptr;
     255       
     256        /* digits before decimal point */
     257        while (isdigit(str[i])) {
     258                if (parsed_digits == 0 && str[i] == '0') {
    265259                        /* Nothing, just skip leading zeros. */
    266                 } else if (parsed_digits < LDBL_DIG) {
    267                         significand = significand * DEC_BASE + (*str - '0');
     260                } else if (parsed_digits < PARSE_DECIMAL_DIGS) {
     261                        significand *= DEC_BASE;
     262                        significand += str[i] - '0';
    268263                        parsed_digits++;
    269264                } else {
     
    271266                }
    272267               
    273                 if (after_decimal) {
    274                         /* Decrement exponent if we are parsing the fractional part. */
    275                         exponent--;
    276                 }
    277                
    278                 str++;
     268                i++;
     269        }
     270       
     271        if (str[i] == DECIMAL_POINT) {
     272                i++;
     273               
     274                /* digits after decimal point */
     275                while (isdigit(str[i])) {
     276                        if (parsed_digits == 0 && str[i] == '0') {
     277                                /* Skip leading zeros and decrement exponent. */
     278                                exponent--;
     279                        } else if (parsed_digits < PARSE_DECIMAL_DIGS) {
     280                                significand *= DEC_BASE;
     281                                significand += str[i] - '0';
     282                                exponent--;
     283                                parsed_digits++;
     284                        } else {
     285                                /* ignore */
     286                        }
     287                       
     288                        i++;
     289                }
    279290        }
    280291       
    281292        /* exponent */
    282         if (tolower(*str) == EXPONENT_MARK) {
    283                 str++;
    284                
    285                 /* Returns MIN/MAX value on error, which is ok. */
    286                 long exp = strtol(str, (char **) &str, DEC_BASE);
    287                
    288                 if (exponent > 0 && exp > LONG_MAX - exponent) {
    289                         exponent = LONG_MAX;
    290                 } else if (exponent < 0 && exp < LONG_MIN - exponent) {
    291                         exponent = LONG_MIN;
    292                 } else {
    293                         exponent += exp;
    294                 }
    295         }
    296        
    297         *sptr = str;
    298        
    299         /* Return multiplied by a power of ten. */
    300         return mul_pow2(mul_pow5(significand, exponent), exponent);
     293        if (tolower(str[i]) == EXPONENT_MARK) {
     294                i++;
     295               
     296                bool negative = false;
     297                int exp = 0;
     298               
     299                switch (str[i]) {
     300                case '-':
     301                        negative = true;
     302                        /* fallthrough */
     303                case '+':
     304                        i++;
     305                }
     306               
     307                while (isdigit(str[i])) {
     308                        if (exp < 65536) {
     309                                exp *= DEC_BASE;
     310                                exp += str[i] - '0';
     311                        }
     312                       
     313                        i++;
     314                }
     315               
     316                if (negative) {
     317                        exp = -exp;
     318                }
     319               
     320                exponent += exp;
     321        }
     322       
     323        long double result = (long double) significand;
     324        result = mul_pow5(result, exponent);
     325        if (result != HUGE_VALL) {
     326                result = mul_pow2(result, exponent);
     327        }
     328       
     329        *sptr = &str[i];
     330        return result;
    301331}
    302332
     
    317347
    318348/**
     349 * Get the count of leading zero bits up to the maximum of 3 zero bits.
     350 *
     351 * @param val Integer value.
     352 * @return How many leading zero bits there are. (Maximum is 3)
     353 */
     354static inline int leading_zeros(uint64_t val)
     355{
     356        for (int i = 3; i > 0; --i) {
     357                if ((val >> (64 - i)) == 0) {
     358                        return i;
     359                }
     360        }
     361       
     362        return 0;
     363}
     364
     365/**
    319366 * Convert hexadecimal string representation of the floating point number.
    320367 * Function expects the string pointer to be already pointed at the first
     
    329376static long double parse_hexadecimal(const char **sptr)
    330377{
    331         assert(sptr != NULL && *sptr != NULL);
     378        // TODO: Use strtol(), at least for exponent.
     379       
     380        /* this function currently always rounds to zero */
     381        // TODO: honor rounding mode
    332382       
    333383        const int DEC_BASE = 10;
     
    335385        const char DECIMAL_POINT = '.';
    336386        const char EXPONENT_MARK = 'p';
     387        /* The highest amount of digits that can be safely parsed
     388         * before an overflow occurs.
     389         */
     390        const int PARSE_HEX_DIGS = 16;
     391       
     392        /* significand */
     393        uint64_t significand = 0;
     394       
     395        /* position in the input string */
     396        int i = 0;
     397       
     398        /* number of digits parsed so far */
     399        int parsed_digits = 0;
     400       
     401        int exponent = 0;
    337402       
    338403        const char *str = *sptr;
    339         long double significand = 0;
    340         long exponent = 0;
    341        
    342         /* number of bits parsed so far */
    343         int parsed_bits = 0;
    344         bool after_decimal = false;
    345        
    346         while (posix_isxdigit(*str) || (!after_decimal && *str == DECIMAL_POINT)) {
    347                 if (*str == DECIMAL_POINT) {
    348                         after_decimal = true;
    349                         str++;
    350                         continue;
    351                 }
    352                
    353                 if (parsed_bits == 0 && *str == '0') {
     404       
     405        /* digits before decimal point */
     406        while (posix_isxdigit(str[i])) {
     407                if (parsed_digits == 0 && str[i] == '0') {
    354408                        /* Nothing, just skip leading zeros. */
    355                 } else if (parsed_bits <= LDBL_MANT_DIG) {
    356                         significand = significand * HEX_BASE + hex_value(*str);
    357                         parsed_bits += 4;
     409                } else if (parsed_digits < PARSE_HEX_DIGS) {
     410                        significand *= HEX_BASE;
     411                        significand += hex_value(str[i]);
     412                        parsed_digits++;
     413                } else if (parsed_digits == PARSE_HEX_DIGS) {
     414                        /* The first digit may have had leading zeros,
     415                         * so we need to parse one more digit and shift
     416                         * the value accordingly.
     417                         */
     418                       
     419                        int zeros = leading_zeros(significand);
     420                        significand = (significand << zeros) |
     421                            (hex_value(str[i]) >> (4 - zeros));
     422                       
     423                        exponent += (4 - zeros);
     424                        parsed_digits++;
    358425                } else {
    359426                        exponent += 4;
    360427                }
    361428               
    362                 if (after_decimal) {
    363                         exponent -= 4;
    364                 }
    365                
    366                 str++;
     429                i++;
     430        }
     431       
     432        if (str[i] == DECIMAL_POINT) {
     433                i++;
     434               
     435                /* digits after decimal point */
     436                while (posix_isxdigit(str[i])) {
     437                        if (parsed_digits == 0 && str[i] == '0') {
     438                                /* Skip leading zeros and decrement exponent. */
     439                                exponent -= 4;
     440                        } else if (parsed_digits < PARSE_HEX_DIGS) {
     441                                significand *= HEX_BASE;
     442                                significand += hex_value(str[i]);
     443                                exponent -= 4;
     444                                parsed_digits++;
     445                        } else if (parsed_digits == PARSE_HEX_DIGS) {
     446                                /* The first digit may have had leading zeros,
     447                                 * so we need to parse one more digit and shift
     448                                 * the value accordingly.
     449                                 */
     450                               
     451                                int zeros = leading_zeros(significand);
     452                                significand = (significand << zeros) |
     453                                    (hex_value(str[i]) >> (4 - zeros));
     454                               
     455                                exponent -= zeros;
     456                                parsed_digits++;
     457                        } else {
     458                                /* ignore */
     459                        }
     460                       
     461                        i++;
     462                }
    367463        }
    368464       
    369465        /* exponent */
    370         if (tolower(*str) == EXPONENT_MARK) {
    371                 str++;
    372                
    373                 /* Returns MIN/MAX value on error, which is ok. */
    374                 long exp = strtol(str, (char **) &str, DEC_BASE);
    375                
    376                 if (exponent > 0 && exp > LONG_MAX - exponent) {
    377                         exponent = LONG_MAX;
    378                 } else if (exponent < 0 && exp < LONG_MIN - exponent) {
    379                         exponent = LONG_MIN;
    380                 } else {
    381                         exponent += exp;
    382                 }
    383         }
    384        
    385         *sptr = str;
    386        
    387         /* Return multiplied by a power of two. */
    388         return mul_pow2(significand, exponent);
     466        if (tolower(str[i]) == EXPONENT_MARK) {
     467                i++;
     468               
     469                bool negative = false;
     470                int exp = 0;
     471               
     472                switch (str[i]) {
     473                case '-':
     474                        negative = true;
     475                        /* fallthrough */
     476                case '+':
     477                        i++;
     478                }
     479               
     480                while (isdigit(str[i])) {
     481                        if (exp < 65536) {
     482                                exp *= DEC_BASE;
     483                                exp += str[i] - '0';
     484                        }
     485                       
     486                        i++;
     487                }
     488               
     489                if (negative) {
     490                        exp = -exp;
     491                }
     492               
     493                exponent += exp;
     494        }
     495       
     496        long double result = (long double) significand;
     497        result = mul_pow2(result, exponent);
     498       
     499        *sptr = &str[i];
     500        return result;
    389501}
    390502
  • uspace/lib/posix/unistd.c

    rbadbb9ad r3508000  
    8989{
    9090        /* Always returns false, because there is no easy way to find
    91         * out under HelenOS. */
     91    * out under HelenOS. */
    9292        return 0;
    9393}
Note: See TracChangeset for help on using the changeset viewer.