| author | |
| committer | |
| log | 1b5d61bee9a50a6dc0941c3512ffa7e0abbf9c52 |
| tree | c5ea3d45f894c4cdab8e1fea65ea4675eda85590 |
| parent | 2173e1f457f49990313e1ad038187af8a78205ab |
and make bigfloat use __float1286 files changed, 66 insertions(+), 10 deletions(-)
src/bigfloat.cpp+11-4| ... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
| 11 | #include <math.h> | 11 | #include <math.h> |
| 12 | #include <errno.h> | 12 | #include <errno.h> |
| 13 | 13 | ||
| 14 | void bigfloat_init_float(BigFloat *dest, long double x) { | 14 | void bigfloat_init_float(BigFloat *dest, __float128 x) { |
| 15 | dest->value = x; | 15 | dest->value = x; |
| 16 | } | 16 | } |
| 17 | 17 | ||
| ... | @@ -24,13 +24,13 @@ void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) { | ... | @@ -24,13 +24,13 @@ void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) { |
| 24 | if (op->digit_count == 0) | 24 | if (op->digit_count == 0) |
| 25 | return; | 25 | return; |
| 26 | 26 | ||
| 27 | long double base = (long double)UINT64_MAX; | 27 | __float128 base = (__float128)UINT64_MAX; |
| 28 | const uint64_t *digits = bigint_ptr(op); | 28 | const uint64_t *digits = bigint_ptr(op); |
| 29 | 29 | ||
| 30 | for (size_t i = op->digit_count - 1;;) { | 30 | for (size_t i = op->digit_count - 1;;) { |
| 31 | uint64_t digit = digits[i]; | 31 | uint64_t digit = digits[i]; |
| 32 | dest->value *= base; | 32 | dest->value *= base; |
| 33 | dest->value += (long double)digit; | 33 | dest->value += (__float128)digit; |
| 34 | 34 | ||
| 35 | if (i == 0) { | 35 | if (i == 0) { |
| 36 | if (op->is_negative) { | 36 | if (op->is_negative) { |
| ... | @@ -96,7 +96,7 @@ void bigfloat_mod(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { | ... | @@ -96,7 +96,7 @@ void bigfloat_mod(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | void bigfloat_write_buf(Buf *buf, const BigFloat *op) { | 98 | void bigfloat_write_buf(Buf *buf, const BigFloat *op) { |
| 99 | buf_appendf(buf, "%Lf", op->value); | 99 | buf_appendf(buf, "%Lf", (long double)op->value); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2) { | 102 | Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2) { |
| ... | @@ -117,6 +117,9 @@ void bigfloat_write_ieee597(const BigFloat *op, uint8_t *buf, size_t bit_count, | ... | @@ -117,6 +117,9 @@ void bigfloat_write_ieee597(const BigFloat *op, uint8_t *buf, size_t bit_count, |
| 117 | } else if (bit_count == 64) { | 117 | } else if (bit_count == 64) { |
| 118 | double f64 = op->value; | 118 | double f64 = op->value; |
| 119 | memcpy(buf, &f64, 8); | 119 | memcpy(buf, &f64, 8); |
| 120 | } else if (bit_count == 128) { | ||
| 121 | __float128 f128 = op->value; | ||
| 122 | memcpy(buf, &f128, 16); | ||
| 120 | } else { | 123 | } else { |
| 121 | zig_unreachable(); | 124 | zig_unreachable(); |
| 122 | } | 125 | } |
| ... | @@ -132,6 +135,10 @@ void bigfloat_read_ieee597(BigFloat *dest, const uint8_t *buf, size_t bit_count, | ... | @@ -132,6 +135,10 @@ void bigfloat_read_ieee597(BigFloat *dest, const uint8_t *buf, size_t bit_count, |
| 132 | double f64; | 135 | double f64; |
| 133 | memcpy(&f64, buf, 8); | 136 | memcpy(&f64, buf, 8); |
| 134 | dest->value = f64; | 137 | dest->value = f64; |
| 138 | } else if (bit_count == 128) { | ||
| 139 | __float128 f128; | ||
| 140 | memcpy(&f128, buf, 16); | ||
| 141 | dest->value = f128; | ||
| 135 | } else { | 142 | } else { |
| 136 | zig_unreachable(); | 143 | zig_unreachable(); |
| 137 | } | 144 | } |
src/bigfloat.hpp+2-2| ... | @@ -14,12 +14,12 @@ | ... | @@ -14,12 +14,12 @@ |
| 14 | #include <stddef.h> | 14 | #include <stddef.h> |
| 15 | 15 | ||
| 16 | struct BigFloat { | 16 | struct BigFloat { |
| 17 | long double value; | 17 | __float128 value; |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | struct Buf; | 20 | struct Buf; |
| 21 | 21 | ||
| 22 | void bigfloat_init_float(BigFloat *dest, long double x); | 22 | void bigfloat_init_float(BigFloat *dest, __float128 x); |
| 23 | void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x); | 23 | void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x); |
| 24 | void bigfloat_init_bigint(BigFloat *dest, const BigInt *op); | 24 | void bigfloat_init_bigint(BigFloat *dest, const BigInt *op); |
| 25 | int bigfloat_init_buf_base10(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len); | 25 | int bigfloat_init_buf_base10(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len); |
src/bigint.cpp+5-4| ... | @@ -220,6 +220,7 @@ void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bi | ... | @@ -220,6 +220,7 @@ void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bi |
| 220 | const uint64_t *twos_comp_digits = bigint_ptr(&twos_comp); | 220 | const uint64_t *twos_comp_digits = bigint_ptr(&twos_comp); |
| 221 | 221 | ||
| 222 | size_t bits_in_last_digit = bit_count % 64; | 222 | size_t bits_in_last_digit = bit_count % 64; |
| 223 | if (bits_in_last_digit == 0) bits_in_last_digit = 64; | ||
| 223 | size_t bytes_in_last_digit = (bits_in_last_digit + 7) / 8; | 224 | size_t bytes_in_last_digit = (bits_in_last_digit + 7) / 8; |
| 224 | size_t unwritten_byte_count = 8 - bytes_in_last_digit; | 225 | size_t unwritten_byte_count = 8 - bytes_in_last_digit; |
| 225 | 226 | ||
| ... | @@ -258,13 +259,13 @@ void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bi | ... | @@ -258,13 +259,13 @@ void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bi |
| 258 | for (size_t digit_index = 0; digit_index < digit_count; digit_index += 1) { | 259 | for (size_t digit_index = 0; digit_index < digit_count; digit_index += 1) { |
| 259 | uint64_t x = (digit_index < twos_comp.digit_count) ? twos_comp_digits[digit_index] : 0; | 260 | uint64_t x = (digit_index < twos_comp.digit_count) ? twos_comp_digits[digit_index] : 0; |
| 260 | 261 | ||
| 261 | for (size_t byte_index = 0; byte_index < 8; byte_index += 1) { | 262 | for (size_t byte_index = 0; |
| 263 | byte_index < 8 && (digit_index + 1 < digit_count || byte_index < bytes_in_last_digit); | ||
| 264 | byte_index += 1) | ||
| 265 | { | ||
| 262 | uint8_t byte = x & 0xff; | 266 | uint8_t byte = x & 0xff; |
| 263 | buf[buf_index] = byte; | 267 | buf[buf_index] = byte; |
| 264 | buf_index += 1; | 268 | buf_index += 1; |
| 265 | if (buf_index >= unwritten_byte_count) { | ||
| 266 | break; | ||
| 267 | } | ||
| 268 | x >>= 8; | 269 | x >>= 8; |
| 269 | } | 270 | } |
| 270 | } | 271 | } |
std/special/compiler_rt/README.md+9| ... | @@ -13,3 +13,12 @@ Any bugs should be solved by trying to duplicate the bug upstream. | ... | @@ -13,3 +13,12 @@ Any bugs should be solved by trying to duplicate the bug upstream. |
| 13 | * If the bug only exists in Zig, something went wrong porting the code, | 13 | * If the bug only exists in Zig, something went wrong porting the code, |
| 14 | and you can run the C code and Zig code side by side in a debugger | 14 | and you can run the C code and Zig code side by side in a debugger |
| 15 | to figure out what's happening differently. | 15 | to figure out what's happening differently. |
| 16 | |||
| 17 | To test Zig's compiler-rt, run this command from the build directory: | ||
| 18 | |||
| 19 | ``` | ||
| 20 | make install && ./zig test ../std/special/compiler_rt/index.zig --library c | ||
| 21 | ``` | ||
| 22 | |||
| 23 | The `--library c` argument omits compiler-rt from the generated test program, | ||
| 24 | which prevents duplicate symbol linker errors for all the compiler-rt builtins. |
std/special/compiler_rt/fixunstfsi_test.zig created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; | ||
| 2 | const assert = @import("../../debug.zig").assert; | ||
| 3 | |||
| 4 | fn test__fixunstfsi(a: f128, expected: u32) { | ||
| 5 | const x = __fixunstfsi(a); | ||
| 6 | assert(x == expected); | ||
| 7 | } | ||
| 8 | |||
| 9 | const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000)); | ||
| 10 | |||
| 11 | test "fixunstfsi" { | ||
| 12 | test__fixunstfsi(inf128, 0xffffffff); | ||
| 13 | test__fixunstfsi(0, 0x0); | ||
| 14 | test__fixunstfsi(0x1.23456789abcdefp+5, 0x24); | ||
| 15 | test__fixunstfsi(0x1.23456789abcdefp-3, 0x0); | ||
| 16 | test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456); | ||
| 17 | test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff); | ||
| 18 | test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff); | ||
| 19 | test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0); | ||
| 20 | |||
| 21 | test__fixunstfsi(0x1.p+32, 0xFFFFFFFF); | ||
| 22 | } | ||
test/cases/cast.zig+17| ... | @@ -258,3 +258,20 @@ test "explicit cast float number literal to integer if no fraction component" { | ... | @@ -258,3 +258,20 @@ test "explicit cast float number literal to integer if no fraction component" { |
| 258 | const y = i32(f32(1e4)); | 258 | const y = i32(f32(1e4)); |
| 259 | assert(y == 10000); | 259 | assert(y == 10000); |
| 260 | } | 260 | } |
| 261 | |||
| 262 | test "cast u128 to f128 and back" { | ||
| 263 | comptime testCast128(); | ||
| 264 | testCast128(); | ||
| 265 | } | ||
| 266 | |||
| 267 | fn testCast128() { | ||
| 268 | assert(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); | ||
| 269 | } | ||
| 270 | |||
| 271 | fn cast128Int(x: f128) -> u128 { | ||
| 272 | @bitCast(u128, x) | ||
| 273 | } | ||
| 274 | |||
| 275 | fn cast128Float(x: u128) -> f128 { | ||
| 276 | @bitCast(f128, x) | ||
| 277 | } |