Ignore:
Timestamp:
2011-08-06T07:04:50Z (13 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d3e241a, e0e922d
Parents:
9a6034a
Message:

Quadruple-precision softfloat, coding style improvements. Details below…

Highlights:

  • completed double-precision support
  • added quadruple-precision support
  • added SPARC quadruple-precision wrappers
  • added doxygen comments
  • corrected and unified coding style

Current state of the softfloat library:

Support for single, double and quadruple precision is currently almost complete (apart from power, square root, complex multiplication and complex division) and provides the same set of features (i.e. the support for all three precisions is now aligned). In order to extend softfloat library consistently, addition of quadruple precision was done in the same spirit as already existing single and double precision written by Josef Cejka in 2006 - that is relaxed standard-compliance for corner cases while mission-critical code sections heavily inspired by the widely used softfloat library written by John R. Hauser (although I personally think it would be more appropriate for HelenOS to use something less optimized, shorter and more readable).

Most of the quadruple-precision code is just an adapted double-precision code to work on 128-bit variables. That means if there is TODO, FIXME or some defect in single or double-precision code, it is most likely also in the quadruple-precision code. Please note that quadruple-precision functions are currently not tested - it is challenging task for itself, especially when the ports that use them are either not finished (mips64) or badly supported by simulators (sparc64). To test whole softfloat library, one would probably have to either write very non-trivial native tester, or use some existing one (e.g. TestFloat from J. R. Hauser) and port it to HelenOS (or rip the softfloat library out of HelenOS and test it on a host system). At the time of writing this, the code dependent on quadruple-precision functions (on mips64 and sparc64) is just a libposix strtold() function (and its callers, most notably scanf backend).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/softfloat/generic/comparison.c

    r9a6034a rc67aff2  
    11/*
    22 * Copyright (c) 2005 Josef Cejka
     3 * Copyright (c) 2011 Petr Koupy
    34 * All rights reserved.
    45 *
     
    3031 * @{
    3132 */
    32 /** @file
     33/** @file Comparison functions.
    3334 */
    3435
    3536#include <sftypes.h>
    3637#include <comparison.h>
    37 
    38 /* NaN : exp = 0xff and nonzero fraction */
     38#include <common.h>
     39
     40/**
     41 * Determines whether the given float represents NaN (either signalling NaN or
     42 * quiet NaN).
     43 *
     44 * @param f Single-precision float.
     45 * @return 1 if float is NaN, 0 otherwise.
     46 */
    3947int isFloat32NaN(float32 f)
    4048{
     49        /* NaN : exp = 0xff and nonzero fraction */
    4150        return ((f.parts.exp == 0xFF) && (f.parts.fraction));
    4251}
    4352
    44 /* NaN : exp = 0x7ff and nonzero fraction */
     53/**
     54 * Determines whether the given float represents NaN (either signalling NaN or
     55 * quiet NaN).
     56 *
     57 * @param d Double-precision float.
     58 * @return 1 if float is NaN, 0 otherwise.
     59 */
    4560int isFloat64NaN(float64 d)
    4661{
     62        /* NaN : exp = 0x7ff and nonzero fraction */
    4763        return ((d.parts.exp == 0x7FF) && (d.parts.fraction));
    4864}
    4965
    50 /* SigNaN : exp = 0xff fraction = 0xxxxx..x (binary), where at least one x is nonzero */
     66/**
     67 * Determines whether the given float represents NaN (either signalling NaN or
     68 * quiet NaN).
     69 *
     70 * @param ld Quadruple-precision float.
     71 * @return 1 if float is NaN, 0 otherwise.
     72 */
     73int isFloat128NaN(float128 ld)
     74{
     75        /* NaN : exp = 0x7fff and nonzero fraction */
     76        return ((ld.parts.exp == 0x7FF) &&
     77            !eq128(ld.parts.frac_hi, ld.parts.frac_lo, 0x0ll, 0x0ll));
     78}
     79
     80/**
     81 * Determines whether the given float represents signalling NaN.
     82 *
     83 * @param f Single-precision float.
     84 * @return 1 if float is signalling NaN, 0 otherwise.
     85 */
    5186int isFloat32SigNaN(float32 f)
    5287{
    53         return ((f.parts.exp == 0xFF) && (f.parts.fraction < 0x400000) && (f.parts.fraction));
    54 }
    55 
    56 /* SigNaN : exp = 0x7ff fraction = 0xxxxx..x (binary), where at least one x is nonzero */
     88        /* SigNaN : exp = 0xff and fraction = 0xxxxx..x (binary),
     89         * where at least one x is nonzero */
     90        return ((f.parts.exp == 0xFF) &&
     91            (f.parts.fraction < 0x400000) && (f.parts.fraction));
     92}
     93
     94/**
     95 * Determines whether the given float represents signalling NaN.
     96 *
     97 * @param d Double-precision float.
     98 * @return 1 if float is signalling NaN, 0 otherwise.
     99 */
    57100int isFloat64SigNaN(float64 d)
    58101{
    59         return ((d.parts.exp == 0x7FF) && (d.parts.fraction) && (d.parts.fraction < 0x8000000000000ll));
    60 }
    61 
     102        /* SigNaN : exp = 0x7ff and fraction = 0xxxxx..x (binary),
     103         * where at least one x is nonzero */
     104        return ((d.parts.exp == 0x7FF) &&
     105            (d.parts.fraction) && (d.parts.fraction < 0x8000000000000ll));
     106}
     107
     108/**
     109 * Determines whether the given float represents signalling NaN.
     110 *
     111 * @param ld Quadruple-precision float.
     112 * @return 1 if float is signalling NaN, 0 otherwise.
     113 */
     114int isFloat128SigNaN(float128 ld)
     115{
     116        /* SigNaN : exp = 0x7fff and fraction = 0xxxxx..x (binary),
     117         * where at least one x is nonzero */
     118        return ((ld.parts.exp == 0x7FFF) &&
     119            (ld.parts.frac_hi || ld.parts.frac_lo) &&
     120            lt128(ld.parts.frac_hi, ld.parts.frac_lo, 0x800000000000ll, 0x0ll));
     121
     122}
     123
     124/**
     125 * Determines whether the given float represents positive or negative infinity.
     126 *
     127 * @param f Single-precision float.
     128 * @return 1 if float is infinite, 0 otherwise.
     129 */
    62130int isFloat32Infinity(float32 f)
    63131{
     132        /* NaN : exp = 0x7ff and zero fraction */
    64133        return ((f.parts.exp == 0xFF) && (f.parts.fraction == 0x0));
    65134}
    66135
     136/**
     137 * Determines whether the given float represents positive or negative infinity.
     138 *
     139 * @param d Double-precision float.
     140 * @return 1 if float is infinite, 0 otherwise.
     141 */
    67142int isFloat64Infinity(float64 d)
    68143{
     144        /* NaN : exp = 0x7ff and zero fraction */
    69145        return ((d.parts.exp == 0x7FF) && (d.parts.fraction == 0x0));
    70146}
    71147
     148/**
     149 * Determines whether the given float represents positive or negative infinity.
     150 *
     151 * @param ld Quadruple-precision float.
     152 * @return 1 if float is infinite, 0 otherwise.
     153 */
     154int isFloat128Infinity(float128 ld)
     155{
     156        /* NaN : exp = 0x7fff and zero fraction */
     157        return ((ld.parts.exp == 0x7FFF) &&
     158            eq128(ld.parts.frac_hi, ld.parts.frac_lo, 0x0ll, 0x0ll));
     159}
     160
     161/**
     162 * Determines whether the given float represents positive or negative zero.
     163 *
     164 * @param f Single-precision float.
     165 * @return 1 if float is zero, 0 otherwise.
     166 */
    72167int isFloat32Zero(float32 f)
    73168{
     
    75170}
    76171
     172/**
     173 * Determines whether the given float represents positive or negative zero.
     174 *
     175 * @param d Double-precision float.
     176 * @return 1 if float is zero, 0 otherwise.
     177 */
    77178int isFloat64Zero(float64 d)
    78179{
     
    81182
    82183/**
    83  * @return 1 if both floats are equal - but NaNs are not recognized
     184 * Determines whether the given float represents positive or negative zero.
     185 *
     186 * @param ld Quadruple-precision float.
     187 * @return 1 if float is zero, 0 otherwise.
     188 */
     189int isFloat128Zero(float128 ld)
     190{
     191        uint64_t tmp_hi;
     192        uint64_t tmp_lo;
     193
     194        and128(ld.binary.hi, ld.binary.lo,
     195            0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
     196
     197        return eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll);
     198}
     199
     200/**
     201 * Determine whether two floats are equal. NaNs are not recognized.
     202 *
     203 * @a First single-precision operand.
     204 * @b Second single-precision operand.
     205 * @return 1 if both floats are equal, 0 otherwise.
    84206 */
    85207int isFloat32eq(float32 a, float32 b)
    86208{
    87209        /* a equals to b or both are zeros (with any sign) */
    88         return ((a.binary==b.binary) || (((a.binary | b.binary) & 0x7FFFFFFF) == 0));
    89 }
    90 
    91 /**
    92  * @return 1 if a < b - but NaNs are not recognized
     210        return ((a.binary == b.binary) ||
     211            (((a.binary | b.binary) & 0x7FFFFFFF) == 0));
     212}
     213
     214/**
     215 * Determine whether two floats are equal. NaNs are not recognized.
     216 *
     217 * @a First double-precision operand.
     218 * @b Second double-precision operand.
     219 * @return 1 if both floats are equal, 0 otherwise.
     220 */
     221int isFloat64eq(float64 a, float64 b)
     222{
     223        /* a equals to b or both are zeros (with any sign) */
     224        return ((a.binary == b.binary) ||
     225            (((a.binary | b.binary) & 0x7FFFFFFFFFFFFFFFll) == 0));
     226}
     227
     228/**
     229 * Determine whether two floats are equal. NaNs are not recognized.
     230 *
     231 * @a First quadruple-precision operand.
     232 * @b Second quadruple-precision operand.
     233 * @return 1 if both floats are equal, 0 otherwise.
     234 */
     235int isFloat128eq(float128 a, float128 b)
     236{
     237        uint64_t tmp_hi;
     238        uint64_t tmp_lo;
     239
     240        /* both are zeros (with any sign) */
     241        or128(a.binary.hi, a.binary.lo,
     242            b.binary.hi, b.binary.lo, &tmp_hi, &tmp_lo);
     243        and128(tmp_hi, tmp_lo,
     244            0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
     245        int both_zero = eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll);
     246       
     247        /* a equals to b */
     248        int are_equal = eq128(a.binary.hi, a.binary.lo, b.binary.hi, b.binary.lo);
     249
     250        return are_equal || both_zero;
     251}
     252
     253/**
     254 * Lower-than comparison between two floats. NaNs are not recognized.
     255 *
     256 * @a First single-precision operand.
     257 * @b Second single-precision operand.
     258 * @return 1 if a is lower than b, 0 otherwise.
    93259 */
    94260int isFloat32lt(float32 a, float32 b)
    95261{
    96         if (((a.binary | b.binary) & 0x7FFFFFFF) == 0)
     262        if (((a.binary | b.binary) & 0x7FFFFFFF) == 0) {
    97263                return 0; /* +- zeroes */
     264        }
    98265       
    99         if ((a.parts.sign) && (b.parts.sign))
     266        if ((a.parts.sign) && (b.parts.sign)) {
    100267                /* if both are negative, smaller is that with greater binary value */
    101268                return (a.binary > b.binary);
     269        }
    102270       
    103         /* lets negate signs - now will be positive numbers allways bigger than negative (first bit will be set for unsigned integer comparison) */
     271        /* lets negate signs - now will be positive numbers allways bigger than
     272         * negative (first bit will be set for unsigned integer comparison) */
    104273        a.parts.sign = !a.parts.sign;
    105274        b.parts.sign = !b.parts.sign;
     
    108277
    109278/**
    110  * @return 1 if a > b - but NaNs are not recognized
     279 * Lower-than comparison between two floats. NaNs are not recognized.
     280 *
     281 * @a First double-precision operand.
     282 * @b Second double-precision operand.
     283 * @return 1 if a is lower than b, 0 otherwise.
     284 */
     285int isFloat64lt(float64 a, float64 b)
     286{
     287        if (((a.binary | b.binary) & 0x7FFFFFFFFFFFFFFFll) == 0) {
     288                return 0; /* +- zeroes */
     289        }
     290
     291        if ((a.parts.sign) && (b.parts.sign)) {
     292                /* if both are negative, smaller is that with greater binary value */
     293                return (a.binary > b.binary);
     294        }
     295
     296        /* lets negate signs - now will be positive numbers allways bigger than
     297         * negative (first bit will be set for unsigned integer comparison) */
     298        a.parts.sign = !a.parts.sign;
     299        b.parts.sign = !b.parts.sign;
     300        return (a.binary < b.binary);
     301}
     302
     303/**
     304 * Lower-than comparison between two floats. NaNs are not recognized.
     305 *
     306 * @a First quadruple-precision operand.
     307 * @b Second quadruple-precision operand.
     308 * @return 1 if a is lower than b, 0 otherwise.
     309 */
     310int isFloat128lt(float128 a, float128 b)
     311{
     312        uint64_t tmp_hi;
     313        uint64_t tmp_lo;
     314
     315        or128(a.binary.hi, a.binary.lo,
     316            b.binary.hi, b.binary.lo, &tmp_hi, &tmp_lo);
     317        and128(tmp_hi, tmp_lo,
     318            0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
     319        if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
     320                return 0; /* +- zeroes */
     321        }
     322
     323        if ((a.parts.sign) && (b.parts.sign)) {
     324                /* if both are negative, smaller is that with greater binary value */
     325                return lt128(b.binary.hi, b.binary.lo, a.binary.hi, a.binary.lo);
     326        }
     327
     328        /* lets negate signs - now will be positive numbers allways bigger than
     329         * negative (first bit will be set for unsigned integer comparison) */
     330        a.parts.sign = !a.parts.sign;
     331        b.parts.sign = !b.parts.sign;
     332        return lt128(a.binary.hi, a.binary.lo, b.binary.hi, b.binary.lo);
     333}
     334
     335/**
     336 * Greater-than comparison between two floats. NaNs are not recognized.
     337 *
     338 * @a First single-precision operand.
     339 * @b Second single-precision operand.
     340 * @return 1 if a is greater than b, 0 otherwise.
    111341 */
    112342int isFloat32gt(float32 a, float32 b)
    113343{
    114         if (((a.binary | b.binary) & 0x7FFFFFFF) == 0)
     344        if (((a.binary | b.binary) & 0x7FFFFFFF) == 0) {
    115345                return 0; /* zeroes are equal with any sign */
     346        }
    116347       
    117         if ((a.parts.sign) && (b.parts.sign))
     348        if ((a.parts.sign) && (b.parts.sign)) {
    118349                /* if both are negative, greater is that with smaller binary value */
    119350                return (a.binary < b.binary);
     351        }
    120352       
    121         /* lets negate signs - now will be positive numbers allways bigger than negative (first bit will be set for unsigned integer comparison) */
     353        /* lets negate signs - now will be positive numbers allways bigger than
     354         *  negative (first bit will be set for unsigned integer comparison) */
    122355        a.parts.sign = !a.parts.sign;
    123356        b.parts.sign = !b.parts.sign;
     
    125358}
    126359
     360/**
     361 * Greater-than comparison between two floats. NaNs are not recognized.
     362 *
     363 * @a First double-precision operand.
     364 * @b Second double-precision operand.
     365 * @return 1 if a is greater than b, 0 otherwise.
     366 */
     367int isFloat64gt(float64 a, float64 b)
     368{
     369        if (((a.binary | b.binary) & 0x7FFFFFFFFFFFFFFFll) == 0) {
     370                return 0; /* zeroes are equal with any sign */
     371        }
     372
     373        if ((a.parts.sign) && (b.parts.sign)) {
     374                /* if both are negative, greater is that with smaller binary value */
     375                return (a.binary < b.binary);
     376        }
     377
     378        /* lets negate signs - now will be positive numbers allways bigger than
     379         *  negative (first bit will be set for unsigned integer comparison) */
     380        a.parts.sign = !a.parts.sign;
     381        b.parts.sign = !b.parts.sign;
     382        return (a.binary > b.binary);
     383}
     384
     385/**
     386 * Greater-than comparison between two floats. NaNs are not recognized.
     387 *
     388 * @a First quadruple-precision operand.
     389 * @b Second quadruple-precision operand.
     390 * @return 1 if a is greater than b, 0 otherwise.
     391 */
     392int isFloat128gt(float128 a, float128 b)
     393{
     394        uint64_t tmp_hi;
     395        uint64_t tmp_lo;
     396
     397        or128(a.binary.hi, a.binary.lo,
     398            b.binary.hi, b.binary.lo, &tmp_hi, &tmp_lo);
     399        and128(tmp_hi, tmp_lo,
     400            0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
     401        if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
     402                return 0; /* zeroes are equal with any sign */
     403        }
     404
     405        if ((a.parts.sign) && (b.parts.sign)) {
     406                /* if both are negative, greater is that with smaller binary value */
     407                return lt128(a.binary.hi, a.binary.lo, b.binary.hi, b.binary.lo);
     408        }
     409
     410        /* lets negate signs - now will be positive numbers allways bigger than
     411         *  negative (first bit will be set for unsigned integer comparison) */
     412        a.parts.sign = !a.parts.sign;
     413        b.parts.sign = !b.parts.sign;
     414        return lt128(b.binary.hi, b.binary.lo, a.binary.hi, a.binary.lo);
     415}
     416
    127417/** @}
    128418 */
Note: See TracChangeset for help on using the changeset viewer.