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