hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

fenv+x86_64.ha (8710B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 // Defines flags characterizing types of floating point exceptions,
      5 // Each of the flags is only defined when the target platform supports handling
      6 // the corresponding exception. Flags NONE and ALL are always
      7 // defined and correspond to a bitwise OR of none and all defined flags
      8 // respectively. Platforms may define additional nonstandard flags.
      9 //
     10 // Examples:
     11 // 	math::raiseexcept(math::fexcept::UNDERFLOW); // raise UNDERFLOW
     12 // 	math::clearexcept(math::fexcept::ALL); // clear all exceptions
     13 //
     14 // 	// e will be math::fexcept::INVALID
     15 // 	math::clearexcept(math::fexcept::ALL);
     16 // 	let a = 0.0/0.0;
     17 // 	let e = math::testexcept(math::fexcept::INVALID | math::fexcept::INEXACT);
     18 export type fexcept = enum uint {
     19 	// No flags set
     20 	NONE = 0,
     21 	// Occurs when there is no well-defined result of an operation, such as
     22 	// with 0/0 or sqrt(-1)
     23 	INVALID = 1 << 0,
     24 	__DENORM = 1 << 1, // arch-specific
     25 	// Occurs when an operation on finite numbers produces infinity
     26 	DIVBYZERO = 1 << 2,
     27 	// Occurs when the result of an operation is much bigger (by
     28 	// absolute value) than the biggest representable finite number
     29 	OVERFLOW = 1 << 3,
     30 	// Occurs when the result of an operation is too small (by
     31 	// absolute value) to be stored as a normalized number
     32 	UNDERFLOW = 1 << 4,
     33 	// Occurs when the result of an operation is rounded to a
     34 	// value that differs from the infinite precision result.
     35 	INEXACT = 1 << 5,
     36 	// Combination of all flags
     37 	ALL = INVALID | __DENORM | DIVBYZERO | OVERFLOW | UNDERFLOW | INEXACT,
     38 };
     39 
     40 // Defines values characterizing different floating point rounding behaviors.
     41 // Each of the values is only definined when the target platform supports the
     42 // corresponding rounding mode.
     43 export type fround = enum uint {
     44 	// Round towards nearest integer, with ties rounding to even
     45 	TONEAREST = 0,
     46 	// Round towards negative infinity
     47 	DOWNWARD = 0x400,
     48 	// Round towards positive infinity
     49 	UPWARD = 0x800,
     50 	// Round towards zero
     51 	TOWARDZERO = 0xC00,
     52 };
     53 
     54 @test fn fexcept() void = {
     55 	assert(testexcept(fexcept::ALL) == fexcept::NONE);
     56 	assert(testexcept(fexcept::NONE) == fexcept::NONE);
     57 
     58 	raiseexcept(fexcept::INEXACT | fexcept::DIVBYZERO);
     59 
     60 	assert(testexcept(fexcept::INEXACT) == fexcept::INEXACT);
     61 	assert(testexcept(fexcept::DIVBYZERO) == fexcept::DIVBYZERO);
     62 	assert(testexcept(fexcept::UNDERFLOW) == fexcept::NONE);
     63 	assert(testexcept(fexcept::DIVBYZERO | fexcept::INEXACT)
     64 				== fexcept::DIVBYZERO | fexcept::INEXACT);
     65 	assert(testexcept(fexcept::DIVBYZERO | fexcept::INEXACT | fexcept::INVALID)
     66 				== fexcept::DIVBYZERO | fexcept::INEXACT);
     67 
     68 	clearexcept(fexcept::INEXACT);
     69 
     70 	assert(testexcept(fexcept::DIVBYZERO | fexcept::INEXACT) == fexcept::DIVBYZERO);
     71 
     72 	raiseexcept(fexcept::ALL);
     73 
     74 	assert(testexcept(fexcept::ALL) == fexcept::ALL);
     75 	assert(testexcept(fexcept::NONE) == fexcept::NONE);
     76 
     77 	clearexcept(fexcept::ALL);
     78 
     79 	assert(testexcept(fexcept::ALL) == fexcept::NONE);
     80 	assert(testexcept(fexcept::NONE) == fexcept::NONE);
     81 };
     82 
     83 @test fn fround() void = {
     84 	// from musl's testsuite
     85 	let f = &f64frombits;
     86 
     87 	assert(getround() == fround::TONEAREST);
     88 	assert(isnan(nearbyintf64(f(0x7ff8000000000000))));
     89 	assert(nearbyintf64(f(0x7ff0000000000000)) == INF);
     90 	assert(nearbyintf64(f(0xfff0000000000000)) == -INF);
     91 	assert(nearbyintf64(f(0x0)) == f(0x0));
     92 	assert(nearbyintf64(f(0x8000000000000000)) == f(0x8000000000000000));
     93 	assert(nearbyintf64(f(0x3ff0000000000000)) == f(0x3ff0000000000000));
     94 	assert(nearbyintf64(f(0xbff0000000000000)) == f(0xbff0000000000000));
     95 	assert(nearbyintf64(f(0x3fe0000000000000)) == f(0x0));
     96 	assert(nearbyintf64(f(0xbfe0000000000000)) == f(0x8000000000000000));
     97 	assert(nearbyintf64(f(0x3ff0001000000000)) == f(0x3ff0000000000000));
     98 	assert(nearbyintf64(f(0xbff0001000000000)) == f(0xbff0000000000000));
     99 	assert(nearbyintf64(f(0x3feffff000000000)) == f(0x3ff0000000000000));
    100 	assert(nearbyintf64(f(0xbfeffff000000000)) == f(0xbff0000000000000));
    101 	assert(nearbyintf64(f(0x39b0000000000000)) == f(0x0));
    102 	assert(nearbyintf64(f(0xb9b0000000000000)) == f(0x8000000000000000));
    103 
    104 	setround(fround::DOWNWARD);
    105 	assert(getround() == fround::DOWNWARD);
    106 	assert(isnan(nearbyintf64(f(0x7ff8000000000000))));
    107 	assert(nearbyintf64(f(0x7ff0000000000000)) == INF);
    108 	assert(nearbyintf64(f(0xfff0000000000000)) == -INF);
    109 	assert(nearbyintf64(f(0x0)) == f(0x0));
    110 	assert(nearbyintf64(f(0x8000000000000000)) == f(0x8000000000000000));
    111 	assert(nearbyintf64(f(0x3ff0000000000000)) == f(0x3ff0000000000000));
    112 	assert(nearbyintf64(f(0xbff0000000000000)) == f(0xbff0000000000000));
    113 	assert(nearbyintf64(f(0x3fe0000000000000)) == f(0x0));
    114 	assert(nearbyintf64(f(0xbfe0000000000000)) == f(0xbff0000000000000));
    115 	assert(nearbyintf64(f(0x3ff0001000000000)) == f(0x3ff0000000000000));
    116 	assert(nearbyintf64(f(0xbff0001000000000)) == f(0xc000000000000000));
    117 	assert(nearbyintf64(f(0x3feffff000000000)) == f(0x0));
    118 	assert(nearbyintf64(f(0xbfeffff000000000)) == f(0xbff0000000000000));
    119 	assert(nearbyintf64(f(0x39b0000000000000)) == f(0x0));
    120 	assert(nearbyintf64(f(0xb9b0000000000000)) == f(0xbff0000000000000));
    121 
    122 	setround(fround::UPWARD);
    123 	assert(getround() == fround::UPWARD);
    124 	assert(isnan(nearbyintf64(f(0x7ff8000000000000))));
    125 	assert(nearbyintf64(f(0x7ff0000000000000)) == INF);
    126 	assert(nearbyintf64(f(0xfff0000000000000)) == -INF);
    127 	assert(nearbyintf64(f(0x0)) == f(0x0));
    128 	assert(nearbyintf64(f(0x8000000000000000)) == f(0x8000000000000000));
    129 	assert(nearbyintf64(f(0x3ff0000000000000)) == f(0x3ff0000000000000));
    130 	assert(nearbyintf64(f(0xbff0000000000000)) == f(0xbff0000000000000));
    131 	assert(nearbyintf64(f(0x3fe0000000000000)) == f(0x3ff0000000000000));
    132 	assert(nearbyintf64(f(0xbfe0000000000000)) == f(0x8000000000000000));
    133 	assert(nearbyintf64(f(0x3ff0001000000000)) == f(0x4000000000000000));
    134 	assert(nearbyintf64(f(0xbff0001000000000)) == f(0xbff0000000000000));
    135 	assert(nearbyintf64(f(0x3feffff000000000)) == f(0x3ff0000000000000));
    136 	assert(nearbyintf64(f(0xbfeffff000000000)) == f(0x8000000000000000));
    137 	assert(nearbyintf64(f(0x39b0000000000000)) == f(0x3ff0000000000000));
    138 	assert(nearbyintf64(f(0xb9b0000000000000)) == f(0x8000000000000000));
    139 
    140 	let f = &f32frombits;
    141 
    142 	setround(fround::TONEAREST);
    143 	assert(getround() == fround::TONEAREST);
    144 	assert(isnan(nearbyintf32(f(0x7fc00000))));
    145 	assert(nearbyintf32(f(0x7f800000)) == INF);
    146 	assert(nearbyintf32(f(0xff800000)) == -INF);
    147 	assert(nearbyintf32(f(0x0)) == f(0x0));
    148 	assert(nearbyintf32(f(0x80000000)) == f(0x80000000));
    149 	assert(nearbyintf32(f(0x3f800000)) == f(0x3f800000));
    150 	assert(nearbyintf32(f(0xbf800000)) == f(0xbf800000));
    151 	assert(nearbyintf32(f(0x3f000000)) == f(0x0));
    152 	assert(nearbyintf32(f(0xbf000000)) == f(0x80000000));
    153 	assert(nearbyintf32(f(0x3f800080)) == f(0x3f800000));
    154 	assert(nearbyintf32(f(0xbf800080)) == f(0xbf800000));
    155 	assert(nearbyintf32(f(0x3f7fff80)) == f(0x3f800000));
    156 	assert(nearbyintf32(f(0xbf7fff80)) == f(0xbf800000));
    157 	assert(nearbyintf32(f(0xd800000)) == f(0x0));
    158 	assert(nearbyintf32(f(0x8d800000)) == f(0x80000000));
    159 
    160 	setround(fround::DOWNWARD);
    161 	assert(getround() == fround::DOWNWARD);
    162 	assert(isnan(nearbyintf32(f(0x7fc00000))));
    163 	assert(nearbyintf32(f(0x7f800000)) == INF);
    164 	assert(nearbyintf32(f(0xff800000)) == -INF);
    165 	assert(nearbyintf32(f(0x0)) == f(0x0));
    166 	assert(nearbyintf32(f(0x80000000)) == f(0x80000000));
    167 	assert(nearbyintf32(f(0x3f800000)) == f(0x3f800000));
    168 	assert(nearbyintf32(f(0xbf800000)) == f(0xbf800000));
    169 	assert(nearbyintf32(f(0x3f000000)) == f(0x0));
    170 	assert(nearbyintf32(f(0xbf000000)) == f(0xbf800000));
    171 	assert(nearbyintf32(f(0x3f800080)) == f(0x3f800000));
    172 	assert(nearbyintf32(f(0xbf800080)) == f(0xc0000000));
    173 	assert(nearbyintf32(f(0x3f7fff80)) == f(0x0));
    174 	assert(nearbyintf32(f(0xbf7fff80)) == f(0xbf800000));
    175 	assert(nearbyintf32(f(0xd800000)) == f(0x0));
    176 	assert(nearbyintf32(f(0x8d800000)) == f(0xbf800000));
    177 
    178 	setround(fround::UPWARD);
    179 	assert(getround() == fround::UPWARD);
    180 	assert(isnan(nearbyintf32(f(0x7fc00000))));
    181 	assert(nearbyintf32(f(0x7f800000)) == INF);
    182 	assert(nearbyintf32(f(0xff800000)) == -INF);
    183 	assert(nearbyintf32(f(0x0)) == f(0x0));
    184 	assert(nearbyintf32(f(0x80000000)) == f(0x80000000));
    185 	assert(nearbyintf32(f(0x3f800000)) == f(0x3f800000));
    186 	assert(nearbyintf32(f(0xbf800000)) == f(0xbf800000));
    187 	assert(nearbyintf32(f(0x3f000000)) == f(0x3f800000));
    188 	assert(nearbyintf32(f(0xbf000000)) == f(0x80000000));
    189 	assert(nearbyintf32(f(0x3f800080)) == f(0x40000000));
    190 	assert(nearbyintf32(f(0xbf800080)) == f(0xbf800000));
    191 	assert(nearbyintf32(f(0x3f7fff80)) == f(0x3f800000));
    192 	assert(nearbyintf32(f(0xbf7fff80)) == f(0x80000000));
    193 	assert(nearbyintf32(f(0xd800000)) == f(0x3f800000));
    194 	assert(nearbyintf32(f(0x8d800000)) == f(0x80000000));
    195 };