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 };