hare

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

fenv+riscv64.ha (8662B)


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