| author | |
| committer | |
| log | 1b4bae6d69937043add14c0dac357c1a1b05f037 |
| tree | 68de983b3b3fc8bcadaf86322428c03906547c04 |
| parent | 4de60dde6ed734acbc428887866ae3d528abbd37 |
| parent | 440c1d52b4053c40c58c05116c8f6d9da8e35eed |
| signature |
add f16 type16 files changed, 529 insertions(+), 100 deletions(-)
CMakeLists.txt+16| ... | @@ -261,12 +261,15 @@ endif() | ... | @@ -261,12 +261,15 @@ endif() |
| 261 | set(EMBEDDED_SOFTFLOAT_SOURCES | 261 | set(EMBEDDED_SOFTFLOAT_SOURCES |
| 262 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c" | 262 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c" |
| 263 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c" | 263 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c" |
| 264 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c" | ||
| 264 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c" | 265 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c" |
| 265 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c" | 266 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c" |
| 266 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c" | 267 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c" |
| 268 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c" | ||
| 267 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c" | 269 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c" |
| 268 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c" | 270 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c" |
| 269 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c" | 271 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c" |
| 272 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c" | ||
| 270 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c" | 273 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c" |
| 271 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_add.c" | 274 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_add.c" |
| 272 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_div.c" | 275 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_div.c" |
| ... | @@ -293,8 +296,20 @@ set(EMBEDDED_SOFTFLOAT_SOURCES | ... | @@ -293,8 +296,20 @@ set(EMBEDDED_SOFTFLOAT_SOURCES |
| 293 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c" | 296 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c" |
| 294 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64.c" | 297 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64.c" |
| 295 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c" | 298 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c" |
| 299 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_add.c" | ||
| 300 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_div.c" | ||
| 301 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_eq.c" | ||
| 302 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_lt.c" | ||
| 303 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_mul.c" | ||
| 304 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_rem.c" | ||
| 305 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_roundToInt.c" | ||
| 306 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sqrt.c" | ||
| 307 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sub.c" | ||
| 308 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f128M.c" | ||
| 309 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f64.c" | ||
| 296 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_f128M.c" | 310 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_f128M.c" |
| 297 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f128M.c" | 311 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f128M.c" |
| 312 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f16.c" | ||
| 298 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_add256M.c" | 313 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_add256M.c" |
| 299 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addCarryM.c" | 314 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addCarryM.c" |
| 300 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addComplCarryM.c" | 315 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addComplCarryM.c" |
| ... | @@ -572,6 +587,7 @@ set(ZIG_STD_FILES | ... | @@ -572,6 +587,7 @@ set(ZIG_STD_FILES |
| 572 | "special/compiler_rt/floatuntidf.zig" | 587 | "special/compiler_rt/floatuntidf.zig" |
| 573 | "special/compiler_rt/muloti4.zig" | 588 | "special/compiler_rt/muloti4.zig" |
| 574 | "special/compiler_rt/index.zig" | 589 | "special/compiler_rt/index.zig" |
| 590 | "special/compiler_rt/truncXfYf2.zig" | ||
| 575 | "special/compiler_rt/udivmod.zig" | 591 | "special/compiler_rt/udivmod.zig" |
| 576 | "special/compiler_rt/udivmoddi4.zig" | 592 | "special/compiler_rt/udivmoddi4.zig" |
| 577 | "special/compiler_rt/udivmodti4.zig" | 593 | "special/compiler_rt/udivmodti4.zig" |
src/all_types.hpp+2| ... | @@ -258,6 +258,7 @@ struct ConstExprValue { | ... | @@ -258,6 +258,7 @@ struct ConstExprValue { |
| 258 | // populated if special == ConstValSpecialStatic | 258 | // populated if special == ConstValSpecialStatic |
| 259 | BigInt x_bigint; | 259 | BigInt x_bigint; |
| 260 | BigFloat x_bigfloat; | 260 | BigFloat x_bigfloat; |
| 261 | float16_t x_f16; | ||
| 261 | float x_f32; | 262 | float x_f32; |
| 262 | double x_f64; | 263 | double x_f64; |
| 263 | float128_t x_f128; | 264 | float128_t x_f128; |
| ... | @@ -1598,6 +1599,7 @@ struct CodeGen { | ... | @@ -1598,6 +1599,7 @@ struct CodeGen { |
| 1598 | TypeTableEntry *entry_i128; | 1599 | TypeTableEntry *entry_i128; |
| 1599 | TypeTableEntry *entry_isize; | 1600 | TypeTableEntry *entry_isize; |
| 1600 | TypeTableEntry *entry_usize; | 1601 | TypeTableEntry *entry_usize; |
| 1602 | TypeTableEntry *entry_f16; | ||
| 1601 | TypeTableEntry *entry_f32; | 1603 | TypeTableEntry *entry_f32; |
| 1602 | TypeTableEntry *entry_f64; | 1604 | TypeTableEntry *entry_f64; |
| 1603 | TypeTableEntry *entry_f128; | 1605 | TypeTableEntry *entry_f128; |
src/analyze.cpp+15| ... | @@ -4668,6 +4668,13 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -4668,6 +4668,13 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4668 | } | 4668 | } |
| 4669 | case TypeTableEntryIdFloat: | 4669 | case TypeTableEntryIdFloat: |
| 4670 | switch (const_val->type->data.floating.bit_count) { | 4670 | switch (const_val->type->data.floating.bit_count) { |
| 4671 | case 16: | ||
| 4672 | { | ||
| 4673 | uint16_t result; | ||
| 4674 | static_assert(sizeof(result) == sizeof(const_val->data.x_f16), ""); | ||
| 4675 | memcpy(&result, &const_val->data.x_f16, sizeof(result)); | ||
| 4676 | return result * 65537u; | ||
| 4677 | } | ||
| 4671 | case 32: | 4678 | case 32: |
| 4672 | { | 4679 | { |
| 4673 | uint32_t result; | 4680 | uint32_t result; |
| ... | @@ -5128,6 +5135,9 @@ void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double va | ... | @@ -5128,6 +5135,9 @@ void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double va |
| 5128 | bigfloat_init_64(&const_val->data.x_bigfloat, value); | 5135 | bigfloat_init_64(&const_val->data.x_bigfloat, value); |
| 5129 | } else if (type->id == TypeTableEntryIdFloat) { | 5136 | } else if (type->id == TypeTableEntryIdFloat) { |
| 5130 | switch (type->data.floating.bit_count) { | 5137 | switch (type->data.floating.bit_count) { |
| 5138 | case 16: | ||
| 5139 | const_val->data.x_f16 = zig_double_to_f16(value); | ||
| 5140 | break; | ||
| 5131 | case 32: | 5141 | case 32: |
| 5132 | const_val->data.x_f32 = value; | 5142 | const_val->data.x_f32 = value; |
| 5133 | break; | 5143 | break; |
| ... | @@ -5441,6 +5451,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -5441,6 +5451,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 5441 | case TypeTableEntryIdFloat: | 5451 | case TypeTableEntryIdFloat: |
| 5442 | assert(a->type->data.floating.bit_count == b->type->data.floating.bit_count); | 5452 | assert(a->type->data.floating.bit_count == b->type->data.floating.bit_count); |
| 5443 | switch (a->type->data.floating.bit_count) { | 5453 | switch (a->type->data.floating.bit_count) { |
| 5454 | case 16: | ||
| 5455 | return f16_eq(a->data.x_f16, b->data.x_f16); | ||
| 5444 | case 32: | 5456 | case 32: |
| 5445 | return a->data.x_f32 == b->data.x_f32; | 5457 | return a->data.x_f32 == b->data.x_f32; |
| 5446 | case 64: | 5458 | case 64: |
| ... | @@ -5614,6 +5626,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -5614,6 +5626,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5614 | return; | 5626 | return; |
| 5615 | case TypeTableEntryIdFloat: | 5627 | case TypeTableEntryIdFloat: |
| 5616 | switch (type_entry->data.floating.bit_count) { | 5628 | switch (type_entry->data.floating.bit_count) { |
| 5629 | case 16: | ||
| 5630 | buf_appendf(buf, "%f", zig_f16_to_double(const_val->data.x_f16)); | ||
| 5631 | return; | ||
| 5617 | case 32: | 5632 | case 32: |
| 5618 | buf_appendf(buf, "%f", const_val->data.x_f32); | 5633 | buf_appendf(buf, "%f", const_val->data.x_f32); |
| 5619 | return; | 5634 | return; |
src/bigfloat.cpp+8| ... | @@ -18,6 +18,10 @@ void bigfloat_init_128(BigFloat *dest, float128_t x) { | ... | @@ -18,6 +18,10 @@ void bigfloat_init_128(BigFloat *dest, float128_t x) { |
| 18 | dest->value = x; | 18 | dest->value = x; |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | void bigfloat_init_16(BigFloat *dest, float16_t x) { | ||
| 22 | f16_to_f128M(x, &dest->value); | ||
| 23 | } | ||
| 24 | |||
| 21 | void bigfloat_init_32(BigFloat *dest, float x) { | 25 | void bigfloat_init_32(BigFloat *dest, float x) { |
| 22 | float32_t f32_val; | 26 | float32_t f32_val; |
| 23 | memcpy(&f32_val, &x, sizeof(float)); | 27 | memcpy(&f32_val, &x, sizeof(float)); |
| ... | @@ -146,6 +150,10 @@ Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2) { | ... | @@ -146,6 +150,10 @@ Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2) { |
| 146 | } | 150 | } |
| 147 | } | 151 | } |
| 148 | 152 | ||
| 153 | float16_t bigfloat_to_f16(const BigFloat *bigfloat) { | ||
| 154 | return f128M_to_f16(&bigfloat->value); | ||
| 155 | } | ||
| 156 | |||
| 149 | float bigfloat_to_f32(const BigFloat *bigfloat) { | 157 | float bigfloat_to_f32(const BigFloat *bigfloat) { |
| 150 | float32_t f32_value = f128M_to_f32(&bigfloat->value); | 158 | float32_t f32_value = f128M_to_f32(&bigfloat->value); |
| 151 | float result; | 159 | float result; |
src/bigfloat.hpp+2| ... | @@ -22,6 +22,7 @@ struct BigFloat { | ... | @@ -22,6 +22,7 @@ struct BigFloat { |
| 22 | 22 | ||
| 23 | struct Buf; | 23 | struct Buf; |
| 24 | 24 | ||
| 25 | void bigfloat_init_16(BigFloat *dest, float16_t x); | ||
| 25 | void bigfloat_init_32(BigFloat *dest, float x); | 26 | void bigfloat_init_32(BigFloat *dest, float x); |
| 26 | void bigfloat_init_64(BigFloat *dest, double x); | 27 | void bigfloat_init_64(BigFloat *dest, double x); |
| 27 | void bigfloat_init_128(BigFloat *dest, float128_t x); | 28 | void bigfloat_init_128(BigFloat *dest, float128_t x); |
| ... | @@ -29,6 +30,7 @@ void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x); | ... | @@ -29,6 +30,7 @@ void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x); |
| 29 | void bigfloat_init_bigint(BigFloat *dest, const BigInt *op); | 30 | void bigfloat_init_bigint(BigFloat *dest, const BigInt *op); |
| 30 | int bigfloat_init_buf_base10(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len); | 31 | int bigfloat_init_buf_base10(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len); |
| 31 | 32 | ||
| 33 | float16_t bigfloat_to_f16(const BigFloat *bigfloat); | ||
| 32 | float bigfloat_to_f32(const BigFloat *bigfloat); | 34 | float bigfloat_to_f32(const BigFloat *bigfloat); |
| 33 | double bigfloat_to_f64(const BigFloat *bigfloat); | 35 | double bigfloat_to_f64(const BigFloat *bigfloat); |
| 34 | float128_t bigfloat_to_f128(const BigFloat *bigfloat); | 36 | float128_t bigfloat_to_f128(const BigFloat *bigfloat); |
src/codegen.cpp+18-43| ... | @@ -17,6 +17,7 @@ | ... | @@ -17,6 +17,7 @@ |
| 17 | #include "os.hpp" | 17 | #include "os.hpp" |
| 18 | #include "translate_c.hpp" | 18 | #include "translate_c.hpp" |
| 19 | #include "target.hpp" | 19 | #include "target.hpp" |
| 20 | #include "util.hpp" | ||
| 20 | #include "zig_llvm.h" | 21 | #include "zig_llvm.h" |
| 21 | 22 | ||
| 22 | #include <stdio.h> | 23 | #include <stdio.h> |
| ... | @@ -5211,6 +5212,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -5211,6 +5212,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5211 | const_val->data.x_err_set->value, false); | 5212 | const_val->data.x_err_set->value, false); |
| 5212 | case TypeTableEntryIdFloat: | 5213 | case TypeTableEntryIdFloat: |
| 5213 | switch (type_entry->data.floating.bit_count) { | 5214 | switch (type_entry->data.floating.bit_count) { |
| 5215 | case 16: | ||
| 5216 | return LLVMConstReal(type_entry->type_ref, zig_f16_to_double(const_val->data.x_f16)); | ||
| 5214 | case 32: | 5217 | case 32: |
| 5215 | return LLVMConstReal(type_entry->type_ref, const_val->data.x_f32); | 5218 | return LLVMConstReal(type_entry->type_ref, const_val->data.x_f32); |
| 5216 | case 64: | 5219 | case 64: |
| ... | @@ -6177,58 +6180,30 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -6177,58 +6180,30 @@ static void define_builtin_types(CodeGen *g) { |
| 6177 | g->builtin_types.entry_usize = entry; | 6180 | g->builtin_types.entry_usize = entry; |
| 6178 | } | 6181 | } |
| 6179 | } | 6182 | } |
| 6180 | { | ||
| 6181 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat); | ||
| 6182 | entry->type_ref = LLVMFloatType(); | ||
| 6183 | buf_init_from_str(&entry->name, "f32"); | ||
| 6184 | entry->data.floating.bit_count = 32; | ||
| 6185 | |||
| 6186 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | ||
| 6187 | entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), | ||
| 6188 | debug_size_in_bits, | ||
| 6189 | ZigLLVMEncoding_DW_ATE_float()); | ||
| 6190 | g->builtin_types.entry_f32 = entry; | ||
| 6191 | g->primitive_type_table.put(&entry->name, entry); | ||
| 6192 | } | ||
| 6193 | { | ||
| 6194 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat); | ||
| 6195 | entry->type_ref = LLVMDoubleType(); | ||
| 6196 | buf_init_from_str(&entry->name, "f64"); | ||
| 6197 | entry->data.floating.bit_count = 64; | ||
| 6198 | 6183 | ||
| 6199 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | 6184 | auto add_fp_entry = [] (CodeGen *g, |
| 6200 | entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), | 6185 | const char *name, |
| 6201 | debug_size_in_bits, | 6186 | uint32_t bit_count, |
| 6202 | ZigLLVMEncoding_DW_ATE_float()); | 6187 | LLVMTypeRef type_ref, |
| 6203 | g->builtin_types.entry_f64 = entry; | 6188 | TypeTableEntry **field) { |
| 6204 | g->primitive_type_table.put(&entry->name, entry); | ||
| 6205 | } | ||
| 6206 | { | ||
| 6207 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat); | 6189 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat); |
| 6208 | entry->type_ref = LLVMFP128Type(); | 6190 | entry->type_ref = type_ref; |
| 6209 | buf_init_from_str(&entry->name, "f128"); | 6191 | buf_init_from_str(&entry->name, name); |
| 6210 | entry->data.floating.bit_count = 128; | 6192 | entry->data.floating.bit_count = bit_count; |
| 6211 | 6193 | ||
| 6212 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | 6194 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); |
| 6213 | entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), | 6195 | entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), |
| 6214 | debug_size_in_bits, | 6196 | debug_size_in_bits, |
| 6215 | ZigLLVMEncoding_DW_ATE_float()); | 6197 | ZigLLVMEncoding_DW_ATE_float()); |
| 6216 | g->builtin_types.entry_f128 = entry; | 6198 | *field = entry; |
| 6217 | g->primitive_type_table.put(&entry->name, entry); | 6199 | g->primitive_type_table.put(&entry->name, entry); |
| 6218 | } | 6200 | }; |
| 6219 | { | 6201 | add_fp_entry(g, "f16", 16, LLVMHalfType(), &g->builtin_types.entry_f16); |
| 6220 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat); | 6202 | add_fp_entry(g, "f32", 32, LLVMFloatType(), &g->builtin_types.entry_f32); |
| 6221 | entry->type_ref = LLVMX86FP80Type(); | 6203 | add_fp_entry(g, "f64", 64, LLVMDoubleType(), &g->builtin_types.entry_f64); |
| 6222 | buf_init_from_str(&entry->name, "c_longdouble"); | 6204 | add_fp_entry(g, "f128", 128, LLVMFP128Type(), &g->builtin_types.entry_f128); |
| 6223 | entry->data.floating.bit_count = 80; | 6205 | add_fp_entry(g, "c_longdouble", 80, LLVMX86FP80Type(), &g->builtin_types.entry_c_longdouble); |
| 6224 | 6206 | ||
| 6225 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | ||
| 6226 | entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), | ||
| 6227 | debug_size_in_bits, | ||
| 6228 | ZigLLVMEncoding_DW_ATE_float()); | ||
| 6229 | g->builtin_types.entry_c_longdouble = entry; | ||
| 6230 | g->primitive_type_table.put(&entry->name, entry); | ||
| 6231 | } | ||
| 6232 | { | 6207 | { |
| 6233 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid); | 6208 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid); |
| 6234 | entry->type_ref = LLVMVoidType(); | 6209 | entry->type_ref = LLVMVoidType(); |
src/ir.cpp+142-14| ... | @@ -11,9 +11,10 @@ | ... | @@ -11,9 +11,10 @@ |
| 11 | #include "ir.hpp" | 11 | #include "ir.hpp" |
| 12 | #include "ir_print.hpp" | 12 | #include "ir_print.hpp" |
| 13 | #include "os.hpp" | 13 | #include "os.hpp" |
| 14 | #include "translate_c.hpp" | ||
| 15 | #include "range_set.hpp" | 14 | #include "range_set.hpp" |
| 16 | #include "softfloat.hpp" | 15 | #include "softfloat.hpp" |
| 16 | #include "translate_c.hpp" | ||
| 17 | #include "util.hpp" | ||
| 17 | 18 | ||
| 18 | struct IrExecContext { | 19 | struct IrExecContext { |
| 19 | ConstExprValue *mem_slot_list; | 20 | ConstExprValue *mem_slot_list; |
| ... | @@ -7238,6 +7239,11 @@ static bool float_has_fraction(ConstExprValue *const_val) { | ... | @@ -7238,6 +7239,11 @@ static bool float_has_fraction(ConstExprValue *const_val) { |
| 7238 | return bigfloat_has_fraction(&const_val->data.x_bigfloat); | 7239 | return bigfloat_has_fraction(&const_val->data.x_bigfloat); |
| 7239 | } else if (const_val->type->id == TypeTableEntryIdFloat) { | 7240 | } else if (const_val->type->id == TypeTableEntryIdFloat) { |
| 7240 | switch (const_val->type->data.floating.bit_count) { | 7241 | switch (const_val->type->data.floating.bit_count) { |
| 7242 | case 16: | ||
| 7243 | { | ||
| 7244 | float16_t floored = f16_roundToInt(const_val->data.x_f16, softfloat_round_minMag, false); | ||
| 7245 | return !f16_eq(floored, const_val->data.x_f16); | ||
| 7246 | } | ||
| 7241 | case 32: | 7247 | case 32: |
| 7242 | return floorf(const_val->data.x_f32) != const_val->data.x_f32; | 7248 | return floorf(const_val->data.x_f32) != const_val->data.x_f32; |
| 7243 | case 64: | 7249 | case 64: |
| ... | @@ -7261,6 +7267,9 @@ static void float_append_buf(Buf *buf, ConstExprValue *const_val) { | ... | @@ -7261,6 +7267,9 @@ static void float_append_buf(Buf *buf, ConstExprValue *const_val) { |
| 7261 | bigfloat_append_buf(buf, &const_val->data.x_bigfloat); | 7267 | bigfloat_append_buf(buf, &const_val->data.x_bigfloat); |
| 7262 | } else if (const_val->type->id == TypeTableEntryIdFloat) { | 7268 | } else if (const_val->type->id == TypeTableEntryIdFloat) { |
| 7263 | switch (const_val->type->data.floating.bit_count) { | 7269 | switch (const_val->type->data.floating.bit_count) { |
| 7270 | case 16: | ||
| 7271 | buf_appendf(buf, "%f", zig_f16_to_double(const_val->data.x_f16)); | ||
| 7272 | break; | ||
| 7264 | case 32: | 7273 | case 32: |
| 7265 | buf_appendf(buf, "%f", const_val->data.x_f32); | 7274 | buf_appendf(buf, "%f", const_val->data.x_f32); |
| 7266 | break; | 7275 | break; |
| ... | @@ -7296,6 +7305,17 @@ static void float_init_bigint(BigInt *bigint, ConstExprValue *const_val) { | ... | @@ -7296,6 +7305,17 @@ static void float_init_bigint(BigInt *bigint, ConstExprValue *const_val) { |
| 7296 | bigint_init_bigfloat(bigint, &const_val->data.x_bigfloat); | 7305 | bigint_init_bigfloat(bigint, &const_val->data.x_bigfloat); |
| 7297 | } else if (const_val->type->id == TypeTableEntryIdFloat) { | 7306 | } else if (const_val->type->id == TypeTableEntryIdFloat) { |
| 7298 | switch (const_val->type->data.floating.bit_count) { | 7307 | switch (const_val->type->data.floating.bit_count) { |
| 7308 | case 16: | ||
| 7309 | { | ||
| 7310 | double x = zig_f16_to_double(const_val->data.x_f16); | ||
| 7311 | if (x >= 0) { | ||
| 7312 | bigint_init_unsigned(bigint, (uint64_t)x); | ||
| 7313 | } else { | ||
| 7314 | bigint_init_unsigned(bigint, (uint64_t)-x); | ||
| 7315 | bigint->is_negative = true; | ||
| 7316 | } | ||
| 7317 | break; | ||
| 7318 | } | ||
| 7299 | case 32: | 7319 | case 32: |
| 7300 | if (const_val->data.x_f32 >= 0) { | 7320 | if (const_val->data.x_f32 >= 0) { |
| 7301 | bigint_init_unsigned(bigint, (uint64_t)(const_val->data.x_f32)); | 7321 | bigint_init_unsigned(bigint, (uint64_t)(const_val->data.x_f32)); |
| ... | @@ -7332,6 +7352,9 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) { | ... | @@ -7332,6 +7352,9 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) { |
| 7332 | bigfloat_init_bigfloat(&dest_val->data.x_bigfloat, bigfloat); | 7352 | bigfloat_init_bigfloat(&dest_val->data.x_bigfloat, bigfloat); |
| 7333 | } else if (dest_val->type->id == TypeTableEntryIdFloat) { | 7353 | } else if (dest_val->type->id == TypeTableEntryIdFloat) { |
| 7334 | switch (dest_val->type->data.floating.bit_count) { | 7354 | switch (dest_val->type->data.floating.bit_count) { |
| 7355 | case 16: | ||
| 7356 | dest_val->data.x_f16 = bigfloat_to_f16(bigfloat); | ||
| 7357 | break; | ||
| 7335 | case 32: | 7358 | case 32: |
| 7336 | dest_val->data.x_f32 = bigfloat_to_f32(bigfloat); | 7359 | dest_val->data.x_f32 = bigfloat_to_f32(bigfloat); |
| 7337 | break; | 7360 | break; |
| ... | @@ -7349,11 +7372,39 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) { | ... | @@ -7349,11 +7372,39 @@ static void float_init_bigfloat(ConstExprValue *dest_val, BigFloat *bigfloat) { |
| 7349 | } | 7372 | } |
| 7350 | } | 7373 | } |
| 7351 | 7374 | ||
| 7375 | static void float_init_f16(ConstExprValue *dest_val, float16_t x) { | ||
| 7376 | if (dest_val->type->id == TypeTableEntryIdComptimeFloat) { | ||
| 7377 | bigfloat_init_16(&dest_val->data.x_bigfloat, x); | ||
| 7378 | } else if (dest_val->type->id == TypeTableEntryIdFloat) { | ||
| 7379 | switch (dest_val->type->data.floating.bit_count) { | ||
| 7380 | case 16: | ||
| 7381 | dest_val->data.x_f16 = x; | ||
| 7382 | break; | ||
| 7383 | case 32: | ||
| 7384 | dest_val->data.x_f32 = zig_f16_to_double(x); | ||
| 7385 | break; | ||
| 7386 | case 64: | ||
| 7387 | dest_val->data.x_f64 = zig_f16_to_double(x); | ||
| 7388 | break; | ||
| 7389 | case 128: | ||
| 7390 | f16_to_f128M(x, &dest_val->data.x_f128); | ||
| 7391 | break; | ||
| 7392 | default: | ||
| 7393 | zig_unreachable(); | ||
| 7394 | } | ||
| 7395 | } else { | ||
| 7396 | zig_unreachable(); | ||
| 7397 | } | ||
| 7398 | } | ||
| 7399 | |||
| 7352 | static void float_init_f32(ConstExprValue *dest_val, float x) { | 7400 | static void float_init_f32(ConstExprValue *dest_val, float x) { |
| 7353 | if (dest_val->type->id == TypeTableEntryIdComptimeFloat) { | 7401 | if (dest_val->type->id == TypeTableEntryIdComptimeFloat) { |
| 7354 | bigfloat_init_32(&dest_val->data.x_bigfloat, x); | 7402 | bigfloat_init_32(&dest_val->data.x_bigfloat, x); |
| 7355 | } else if (dest_val->type->id == TypeTableEntryIdFloat) { | 7403 | } else if (dest_val->type->id == TypeTableEntryIdFloat) { |
| 7356 | switch (dest_val->type->data.floating.bit_count) { | 7404 | switch (dest_val->type->data.floating.bit_count) { |
| 7405 | case 16: | ||
| 7406 | dest_val->data.x_f16 = zig_double_to_f16(x); | ||
| 7407 | break; | ||
| 7357 | case 32: | 7408 | case 32: |
| 7358 | dest_val->data.x_f32 = x; | 7409 | dest_val->data.x_f32 = x; |
| 7359 | break; | 7410 | break; |
| ... | @@ -7380,6 +7431,9 @@ static void float_init_f64(ConstExprValue *dest_val, double x) { | ... | @@ -7380,6 +7431,9 @@ static void float_init_f64(ConstExprValue *dest_val, double x) { |
| 7380 | bigfloat_init_64(&dest_val->data.x_bigfloat, x); | 7431 | bigfloat_init_64(&dest_val->data.x_bigfloat, x); |
| 7381 | } else if (dest_val->type->id == TypeTableEntryIdFloat) { | 7432 | } else if (dest_val->type->id == TypeTableEntryIdFloat) { |
| 7382 | switch (dest_val->type->data.floating.bit_count) { | 7433 | switch (dest_val->type->data.floating.bit_count) { |
| 7434 | case 16: | ||
| 7435 | dest_val->data.x_f16 = zig_double_to_f16(x); | ||
| 7436 | break; | ||
| 7383 | case 32: | 7437 | case 32: |
| 7384 | dest_val->data.x_f32 = x; | 7438 | dest_val->data.x_f32 = x; |
| 7385 | break; | 7439 | break; |
| ... | @@ -7406,6 +7460,9 @@ static void float_init_f128(ConstExprValue *dest_val, float128_t x) { | ... | @@ -7406,6 +7460,9 @@ static void float_init_f128(ConstExprValue *dest_val, float128_t x) { |
| 7406 | bigfloat_init_128(&dest_val->data.x_bigfloat, x); | 7460 | bigfloat_init_128(&dest_val->data.x_bigfloat, x); |
| 7407 | } else if (dest_val->type->id == TypeTableEntryIdFloat) { | 7461 | } else if (dest_val->type->id == TypeTableEntryIdFloat) { |
| 7408 | switch (dest_val->type->data.floating.bit_count) { | 7462 | switch (dest_val->type->data.floating.bit_count) { |
| 7463 | case 16: | ||
| 7464 | dest_val->data.x_f16 = f128M_to_f16(&x); | ||
| 7465 | break; | ||
| 7409 | case 32: | 7466 | case 32: |
| 7410 | { | 7467 | { |
| 7411 | float32_t f32_val = f128M_to_f32(&x); | 7468 | float32_t f32_val = f128M_to_f32(&x); |
| ... | @@ -7436,6 +7493,9 @@ static void float_init_float(ConstExprValue *dest_val, ConstExprValue *src_val) | ... | @@ -7436,6 +7493,9 @@ static void float_init_float(ConstExprValue *dest_val, ConstExprValue *src_val) |
| 7436 | float_init_bigfloat(dest_val, &src_val->data.x_bigfloat); | 7493 | float_init_bigfloat(dest_val, &src_val->data.x_bigfloat); |
| 7437 | } else if (src_val->type->id == TypeTableEntryIdFloat) { | 7494 | } else if (src_val->type->id == TypeTableEntryIdFloat) { |
| 7438 | switch (src_val->type->data.floating.bit_count) { | 7495 | switch (src_val->type->data.floating.bit_count) { |
| 7496 | case 16: | ||
| 7497 | float_init_f16(dest_val, src_val->data.x_f16); | ||
| 7498 | break; | ||
| 7439 | case 32: | 7499 | case 32: |
| 7440 | float_init_f32(dest_val, src_val->data.x_f32); | 7500 | float_init_f32(dest_val, src_val->data.x_f32); |
| 7441 | break; | 7501 | break; |
| ... | @@ -7459,6 +7519,14 @@ static Cmp float_cmp(ConstExprValue *op1, ConstExprValue *op2) { | ... | @@ -7459,6 +7519,14 @@ static Cmp float_cmp(ConstExprValue *op1, ConstExprValue *op2) { |
| 7459 | return bigfloat_cmp(&op1->data.x_bigfloat, &op2->data.x_bigfloat); | 7519 | return bigfloat_cmp(&op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 7460 | } else if (op1->type->id == TypeTableEntryIdFloat) { | 7520 | } else if (op1->type->id == TypeTableEntryIdFloat) { |
| 7461 | switch (op1->type->data.floating.bit_count) { | 7521 | switch (op1->type->data.floating.bit_count) { |
| 7522 | case 16: | ||
| 7523 | if (f16_lt(op1->data.x_f16, op2->data.x_f16)) { | ||
| 7524 | return CmpLT; | ||
| 7525 | } else if (f16_lt(op2->data.x_f16, op1->data.x_f16)) { | ||
| 7526 | return CmpGT; | ||
| 7527 | } else { | ||
| 7528 | return CmpEQ; | ||
| 7529 | } | ||
| 7462 | case 32: | 7530 | case 32: |
| 7463 | if (op1->data.x_f32 > op2->data.x_f32) { | 7531 | if (op1->data.x_f32 > op2->data.x_f32) { |
| 7464 | return CmpGT; | 7532 | return CmpGT; |
| ... | @@ -7496,6 +7564,17 @@ static Cmp float_cmp_zero(ConstExprValue *op) { | ... | @@ -7496,6 +7564,17 @@ static Cmp float_cmp_zero(ConstExprValue *op) { |
| 7496 | return bigfloat_cmp_zero(&op->data.x_bigfloat); | 7564 | return bigfloat_cmp_zero(&op->data.x_bigfloat); |
| 7497 | } else if (op->type->id == TypeTableEntryIdFloat) { | 7565 | } else if (op->type->id == TypeTableEntryIdFloat) { |
| 7498 | switch (op->type->data.floating.bit_count) { | 7566 | switch (op->type->data.floating.bit_count) { |
| 7567 | case 16: | ||
| 7568 | { | ||
| 7569 | const float16_t zero = zig_double_to_f16(0); | ||
| 7570 | if (f16_lt(op->data.x_f16, zero)) { | ||
| 7571 | return CmpLT; | ||
| 7572 | } else if (f16_lt(zero, op->data.x_f16)) { | ||
| 7573 | return CmpGT; | ||
| 7574 | } else { | ||
| 7575 | return CmpEQ; | ||
| 7576 | } | ||
| 7577 | } | ||
| 7499 | case 32: | 7578 | case 32: |
| 7500 | if (op->data.x_f32 < 0.0) { | 7579 | if (op->data.x_f32 < 0.0) { |
| 7501 | return CmpLT; | 7580 | return CmpLT; |
| ... | @@ -7537,6 +7616,9 @@ static void float_add(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal | ... | @@ -7537,6 +7616,9 @@ static void float_add(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal |
| 7537 | bigfloat_add(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); | 7616 | bigfloat_add(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 7538 | } else if (op1->type->id == TypeTableEntryIdFloat) { | 7617 | } else if (op1->type->id == TypeTableEntryIdFloat) { |
| 7539 | switch (op1->type->data.floating.bit_count) { | 7618 | switch (op1->type->data.floating.bit_count) { |
| 7619 | case 16: | ||
| 7620 | out_val->data.x_f16 = f16_add(op1->data.x_f16, op2->data.x_f16); | ||
| 7621 | return; | ||
| 7540 | case 32: | 7622 | case 32: |
| 7541 | out_val->data.x_f32 = op1->data.x_f32 + op2->data.x_f32; | 7623 | out_val->data.x_f32 = op1->data.x_f32 + op2->data.x_f32; |
| 7542 | return; | 7624 | return; |
| ... | @@ -7561,6 +7643,9 @@ static void float_sub(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal | ... | @@ -7561,6 +7643,9 @@ static void float_sub(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal |
| 7561 | bigfloat_sub(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); | 7643 | bigfloat_sub(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 7562 | } else if (op1->type->id == TypeTableEntryIdFloat) { | 7644 | } else if (op1->type->id == TypeTableEntryIdFloat) { |
| 7563 | switch (op1->type->data.floating.bit_count) { | 7645 | switch (op1->type->data.floating.bit_count) { |
| 7646 | case 16: | ||
| 7647 | out_val->data.x_f16 = f16_sub(op1->data.x_f16, op2->data.x_f16); | ||
| 7648 | return; | ||
| 7564 | case 32: | 7649 | case 32: |
| 7565 | out_val->data.x_f32 = op1->data.x_f32 - op2->data.x_f32; | 7650 | out_val->data.x_f32 = op1->data.x_f32 - op2->data.x_f32; |
| 7566 | return; | 7651 | return; |
| ... | @@ -7585,6 +7670,9 @@ static void float_mul(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal | ... | @@ -7585,6 +7670,9 @@ static void float_mul(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal |
| 7585 | bigfloat_mul(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); | 7670 | bigfloat_mul(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 7586 | } else if (op1->type->id == TypeTableEntryIdFloat) { | 7671 | } else if (op1->type->id == TypeTableEntryIdFloat) { |
| 7587 | switch (op1->type->data.floating.bit_count) { | 7672 | switch (op1->type->data.floating.bit_count) { |
| 7673 | case 16: | ||
| 7674 | out_val->data.x_f16 = f16_mul(op1->data.x_f16, op2->data.x_f16); | ||
| 7675 | return; | ||
| 7588 | case 32: | 7676 | case 32: |
| 7589 | out_val->data.x_f32 = op1->data.x_f32 * op2->data.x_f32; | 7677 | out_val->data.x_f32 = op1->data.x_f32 * op2->data.x_f32; |
| 7590 | return; | 7678 | return; |
| ... | @@ -7609,6 +7697,9 @@ static void float_div(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal | ... | @@ -7609,6 +7697,9 @@ static void float_div(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal |
| 7609 | bigfloat_div(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); | 7697 | bigfloat_div(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 7610 | } else if (op1->type->id == TypeTableEntryIdFloat) { | 7698 | } else if (op1->type->id == TypeTableEntryIdFloat) { |
| 7611 | switch (op1->type->data.floating.bit_count) { | 7699 | switch (op1->type->data.floating.bit_count) { |
| 7700 | case 16: | ||
| 7701 | out_val->data.x_f16 = f16_div(op1->data.x_f16, op2->data.x_f16); | ||
| 7702 | return; | ||
| 7612 | case 32: | 7703 | case 32: |
| 7613 | out_val->data.x_f32 = op1->data.x_f32 / op2->data.x_f32; | 7704 | out_val->data.x_f32 = op1->data.x_f32 / op2->data.x_f32; |
| 7614 | return; | 7705 | return; |
| ... | @@ -7633,21 +7724,15 @@ static void float_div_trunc(ConstExprValue *out_val, ConstExprValue *op1, ConstE | ... | @@ -7633,21 +7724,15 @@ static void float_div_trunc(ConstExprValue *out_val, ConstExprValue *op1, ConstE |
| 7633 | bigfloat_div_trunc(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); | 7724 | bigfloat_div_trunc(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 7634 | } else if (op1->type->id == TypeTableEntryIdFloat) { | 7725 | } else if (op1->type->id == TypeTableEntryIdFloat) { |
| 7635 | switch (op1->type->data.floating.bit_count) { | 7726 | switch (op1->type->data.floating.bit_count) { |
| 7727 | case 16: | ||
| 7728 | out_val->data.x_f16 = f16_div(op1->data.x_f16, op2->data.x_f16); | ||
| 7729 | out_val->data.x_f16 = f16_roundToInt(out_val->data.x_f16, softfloat_round_minMag, false); | ||
| 7730 | return; | ||
| 7636 | case 32: | 7731 | case 32: |
| 7637 | out_val->data.x_f32 = op1->data.x_f32 / op2->data.x_f32; | 7732 | out_val->data.x_f32 = truncf(op1->data.x_f32 / op2->data.x_f32); |
| 7638 | if (out_val->data.x_f32 >= 0.0) { | ||
| 7639 | out_val->data.x_f32 = floorf(out_val->data.x_f32); | ||
| 7640 | } else { | ||
| 7641 | out_val->data.x_f32 = ceilf(out_val->data.x_f32); | ||
| 7642 | } | ||
| 7643 | return; | 7733 | return; |
| 7644 | case 64: | 7734 | case 64: |
| 7645 | out_val->data.x_f64 = op1->data.x_f64 / op2->data.x_f64; | 7735 | out_val->data.x_f64 = trunc(op1->data.x_f64 / op2->data.x_f64); |
| 7646 | if (out_val->data.x_f64 >= 0.0) { | ||
| 7647 | out_val->data.x_f64 = floor(out_val->data.x_f64); | ||
| 7648 | } else { | ||
| 7649 | out_val->data.x_f64 = ceil(out_val->data.x_f64); | ||
| 7650 | } | ||
| 7651 | return; | 7736 | return; |
| 7652 | case 128: | 7737 | case 128: |
| 7653 | f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); | 7738 | f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); |
| ... | @@ -7668,6 +7753,10 @@ static void float_div_floor(ConstExprValue *out_val, ConstExprValue *op1, ConstE | ... | @@ -7668,6 +7753,10 @@ static void float_div_floor(ConstExprValue *out_val, ConstExprValue *op1, ConstE |
| 7668 | bigfloat_div_floor(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); | 7753 | bigfloat_div_floor(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 7669 | } else if (op1->type->id == TypeTableEntryIdFloat) { | 7754 | } else if (op1->type->id == TypeTableEntryIdFloat) { |
| 7670 | switch (op1->type->data.floating.bit_count) { | 7755 | switch (op1->type->data.floating.bit_count) { |
| 7756 | case 16: | ||
| 7757 | out_val->data.x_f16 = f16_div(op1->data.x_f16, op2->data.x_f16); | ||
| 7758 | out_val->data.x_f16 = f16_roundToInt(out_val->data.x_f16, softfloat_round_min, false); | ||
| 7759 | return; | ||
| 7671 | case 32: | 7760 | case 32: |
| 7672 | out_val->data.x_f32 = floorf(op1->data.x_f32 / op2->data.x_f32); | 7761 | out_val->data.x_f32 = floorf(op1->data.x_f32 / op2->data.x_f32); |
| 7673 | return; | 7762 | return; |
| ... | @@ -7693,6 +7782,9 @@ static void float_rem(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal | ... | @@ -7693,6 +7782,9 @@ static void float_rem(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal |
| 7693 | bigfloat_rem(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); | 7782 | bigfloat_rem(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 7694 | } else if (op1->type->id == TypeTableEntryIdFloat) { | 7783 | } else if (op1->type->id == TypeTableEntryIdFloat) { |
| 7695 | switch (op1->type->data.floating.bit_count) { | 7784 | switch (op1->type->data.floating.bit_count) { |
| 7785 | case 16: | ||
| 7786 | out_val->data.x_f16 = f16_rem(op1->data.x_f16, op2->data.x_f16); | ||
| 7787 | return; | ||
| 7696 | case 32: | 7788 | case 32: |
| 7697 | out_val->data.x_f32 = fmodf(op1->data.x_f32, op2->data.x_f32); | 7789 | out_val->data.x_f32 = fmodf(op1->data.x_f32, op2->data.x_f32); |
| 7698 | return; | 7790 | return; |
| ... | @@ -7710,6 +7802,16 @@ static void float_rem(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal | ... | @@ -7710,6 +7802,16 @@ static void float_rem(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal |
| 7710 | } | 7802 | } |
| 7711 | } | 7803 | } |
| 7712 | 7804 | ||
| 7805 | // c = a - b * trunc(a / b) | ||
| 7806 | static float16_t zig_f16_mod(float16_t a, float16_t b) { | ||
| 7807 | float16_t c; | ||
| 7808 | c = f16_div(a, b); | ||
| 7809 | c = f16_roundToInt(c, softfloat_round_min, true); | ||
| 7810 | c = f16_mul(b, c); | ||
| 7811 | c = f16_sub(a, c); | ||
| 7812 | return c; | ||
| 7813 | } | ||
| 7814 | |||
| 7713 | // c = a - b * trunc(a / b) | 7815 | // c = a - b * trunc(a / b) |
| 7714 | static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t* c) { | 7816 | static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t* c) { |
| 7715 | f128M_div(a, b, c); | 7817 | f128M_div(a, b, c); |
| ... | @@ -7725,6 +7827,9 @@ static void float_mod(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal | ... | @@ -7725,6 +7827,9 @@ static void float_mod(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal |
| 7725 | bigfloat_mod(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); | 7827 | bigfloat_mod(&out_val->data.x_bigfloat, &op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 7726 | } else if (op1->type->id == TypeTableEntryIdFloat) { | 7828 | } else if (op1->type->id == TypeTableEntryIdFloat) { |
| 7727 | switch (op1->type->data.floating.bit_count) { | 7829 | switch (op1->type->data.floating.bit_count) { |
| 7830 | case 16: | ||
| 7831 | out_val->data.x_f16 = zig_f16_mod(op1->data.x_f16, op2->data.x_f16); | ||
| 7832 | return; | ||
| 7728 | case 32: | 7833 | case 32: |
| 7729 | out_val->data.x_f32 = fmodf(fmodf(op1->data.x_f32, op2->data.x_f32) + op2->data.x_f32, op2->data.x_f32); | 7834 | out_val->data.x_f32 = fmodf(fmodf(op1->data.x_f32, op2->data.x_f32) + op2->data.x_f32, op2->data.x_f32); |
| 7730 | return; | 7835 | return; |
| ... | @@ -7748,6 +7853,12 @@ static void float_negate(ConstExprValue *out_val, ConstExprValue *op) { | ... | @@ -7748,6 +7853,12 @@ static void float_negate(ConstExprValue *out_val, ConstExprValue *op) { |
| 7748 | bigfloat_negate(&out_val->data.x_bigfloat, &op->data.x_bigfloat); | 7853 | bigfloat_negate(&out_val->data.x_bigfloat, &op->data.x_bigfloat); |
| 7749 | } else if (op->type->id == TypeTableEntryIdFloat) { | 7854 | } else if (op->type->id == TypeTableEntryIdFloat) { |
| 7750 | switch (op->type->data.floating.bit_count) { | 7855 | switch (op->type->data.floating.bit_count) { |
| 7856 | case 16: | ||
| 7857 | { | ||
| 7858 | const float16_t zero = zig_double_to_f16(0); | ||
| 7859 | out_val->data.x_f16 = f16_sub(zero, op->data.x_f16); | ||
| 7860 | return; | ||
| 7861 | } | ||
| 7751 | case 32: | 7862 | case 32: |
| 7752 | out_val->data.x_f32 = -op->data.x_f32; | 7863 | out_val->data.x_f32 = -op->data.x_f32; |
| 7753 | return; | 7864 | return; |
| ... | @@ -7770,6 +7881,9 @@ static void float_negate(ConstExprValue *out_val, ConstExprValue *op) { | ... | @@ -7770,6 +7881,9 @@ static void float_negate(ConstExprValue *out_val, ConstExprValue *op) { |
| 7770 | void float_write_ieee597(ConstExprValue *op, uint8_t *buf, bool is_big_endian) { | 7881 | void float_write_ieee597(ConstExprValue *op, uint8_t *buf, bool is_big_endian) { |
| 7771 | if (op->type->id == TypeTableEntryIdFloat) { | 7882 | if (op->type->id == TypeTableEntryIdFloat) { |
| 7772 | switch (op->type->data.floating.bit_count) { | 7883 | switch (op->type->data.floating.bit_count) { |
| 7884 | case 16: | ||
| 7885 | memcpy(buf, &op->data.x_f16, 2); // TODO wrong when compiler is big endian | ||
| 7886 | return; | ||
| 7773 | case 32: | 7887 | case 32: |
| 7774 | memcpy(buf, &op->data.x_f32, 4); // TODO wrong when compiler is big endian | 7888 | memcpy(buf, &op->data.x_f32, 4); // TODO wrong when compiler is big endian |
| 7775 | return; | 7889 | return; |
| ... | @@ -7790,6 +7904,9 @@ void float_write_ieee597(ConstExprValue *op, uint8_t *buf, bool is_big_endian) { | ... | @@ -7790,6 +7904,9 @@ void float_write_ieee597(ConstExprValue *op, uint8_t *buf, bool is_big_endian) { |
| 7790 | void float_read_ieee597(ConstExprValue *val, uint8_t *buf, bool is_big_endian) { | 7904 | void float_read_ieee597(ConstExprValue *val, uint8_t *buf, bool is_big_endian) { |
| 7791 | if (val->type->id == TypeTableEntryIdFloat) { | 7905 | if (val->type->id == TypeTableEntryIdFloat) { |
| 7792 | switch (val->type->data.floating.bit_count) { | 7906 | switch (val->type->data.floating.bit_count) { |
| 7907 | case 16: | ||
| 7908 | memcpy(&val->data.x_f16, buf, 2); // TODO wrong when compiler is big endian | ||
| 7909 | return; | ||
| 7793 | case 32: | 7910 | case 32: |
| 7794 | memcpy(&val->data.x_f32, buf, 4); // TODO wrong when compiler is big endian | 7911 | memcpy(&val->data.x_f32, buf, 4); // TODO wrong when compiler is big endian |
| 7795 | return; | 7912 | return; |
| ... | @@ -8817,6 +8934,9 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -8817,6 +8934,9 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 8817 | if (other_val->type->id == TypeTableEntryIdComptimeFloat) { | 8934 | if (other_val->type->id == TypeTableEntryIdComptimeFloat) { |
| 8818 | assert(new_type->id == TypeTableEntryIdFloat); | 8935 | assert(new_type->id == TypeTableEntryIdFloat); |
| 8819 | switch (new_type->data.floating.bit_count) { | 8936 | switch (new_type->data.floating.bit_count) { |
| 8937 | case 16: | ||
| 8938 | const_val->data.x_f16 = bigfloat_to_f16(&other_val->data.x_bigfloat); | ||
| 8939 | break; | ||
| 8820 | case 32: | 8940 | case 32: |
| 8821 | const_val->data.x_f32 = bigfloat_to_f32(&other_val->data.x_bigfloat); | 8941 | const_val->data.x_f32 = bigfloat_to_f32(&other_val->data.x_bigfloat); |
| 8822 | break; | 8942 | break; |
| ... | @@ -8847,6 +8967,9 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -8847,6 +8967,9 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 8847 | BigFloat bigfloat; | 8967 | BigFloat bigfloat; |
| 8848 | bigfloat_init_bigint(&bigfloat, &other_val->data.x_bigint); | 8968 | bigfloat_init_bigint(&bigfloat, &other_val->data.x_bigint); |
| 8849 | switch (new_type->data.floating.bit_count) { | 8969 | switch (new_type->data.floating.bit_count) { |
| 8970 | case 16: | ||
| 8971 | const_val->data.x_f16 = bigfloat_to_f16(&bigfloat); | ||
| 8972 | break; | ||
| 8850 | case 32: | 8973 | case 32: |
| 8851 | const_val->data.x_f32 = bigfloat_to_f32(&bigfloat); | 8974 | const_val->data.x_f32 = bigfloat_to_f32(&bigfloat); |
| 8852 | break; | 8975 | break; |
| ... | @@ -20104,6 +20227,9 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction | ... | @@ -20104,6 +20227,9 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction |
| 20104 | bigfloat_sqrt(&out_val->data.x_bigfloat, &val->data.x_bigfloat); | 20227 | bigfloat_sqrt(&out_val->data.x_bigfloat, &val->data.x_bigfloat); |
| 20105 | } else if (float_type->id == TypeTableEntryIdFloat) { | 20228 | } else if (float_type->id == TypeTableEntryIdFloat) { |
| 20106 | switch (float_type->data.floating.bit_count) { | 20229 | switch (float_type->data.floating.bit_count) { |
| 20230 | case 16: | ||
| 20231 | out_val->data.x_f16 = f16_sqrt(val->data.x_f16); | ||
| 20232 | break; | ||
| 20107 | case 32: | 20233 | case 32: |
| 20108 | out_val->data.x_f32 = sqrtf(val->data.x_f32); | 20234 | out_val->data.x_f32 = sqrtf(val->data.x_f32); |
| 20109 | break; | 20235 | break; |
| ... | @@ -20124,7 +20250,9 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction | ... | @@ -20124,7 +20250,9 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction |
| 20124 | } | 20250 | } |
| 20125 | 20251 | ||
| 20126 | assert(float_type->id == TypeTableEntryIdFloat); | 20252 | assert(float_type->id == TypeTableEntryIdFloat); |
| 20127 | if (float_type->data.floating.bit_count != 32 && float_type->data.floating.bit_count != 64) { | 20253 | if (float_type->data.floating.bit_count != 16 && |
| 20254 | float_type->data.floating.bit_count != 32 && | ||
| 20255 | float_type->data.floating.bit_count != 64) { | ||
| 20128 | ir_add_error(ira, instruction->type, buf_sprintf("compiler TODO: add implementation of sqrt for '%s'", buf_ptr(&float_type->name))); | 20256 | ir_add_error(ira, instruction->type, buf_sprintf("compiler TODO: add implementation of sqrt for '%s'", buf_ptr(&float_type->name))); |
| 20129 | return ira->codegen->builtin_types.entry_invalid; | 20257 | return ira->codegen->builtin_types.entry_invalid; |
| 20130 | } | 20258 | } |
src/util.hpp+19| ... | @@ -31,6 +31,8 @@ | ... | @@ -31,6 +31,8 @@ |
| 31 | 31 | ||
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | #include "softfloat.hpp" | ||
| 35 | |||
| 34 | #define BREAKPOINT __asm("int $0x03") | 36 | #define BREAKPOINT __asm("int $0x03") |
| 35 | 37 | ||
| 36 | ATTRIBUTE_COLD | 38 | ATTRIBUTE_COLD |
| ... | @@ -165,4 +167,21 @@ static inline uint8_t log2_u64(uint64_t x) { | ... | @@ -165,4 +167,21 @@ static inline uint8_t log2_u64(uint64_t x) { |
| 165 | return (63 - clzll(x)); | 167 | return (63 - clzll(x)); |
| 166 | } | 168 | } |
| 167 | 169 | ||
| 170 | static inline float16_t zig_double_to_f16(double x) { | ||
| 171 | float64_t y; | ||
| 172 | static_assert(sizeof(x) == sizeof(y), ""); | ||
| 173 | memcpy(&y, &x, sizeof(x)); | ||
| 174 | return f64_to_f16(y); | ||
| 175 | } | ||
| 176 | |||
| 177 | |||
| 178 | // Return value is safe to coerce to float even when |x| is NaN or Infinity. | ||
| 179 | static inline double zig_f16_to_double(float16_t x) { | ||
| 180 | float64_t y = f16_to_f64(x); | ||
| 181 | double z; | ||
| 182 | static_assert(sizeof(y) == sizeof(z), ""); | ||
| 183 | memcpy(&z, &y, sizeof(y)); | ||
| 184 | return z; | ||
| 185 | } | ||
| 186 | |||
| 168 | #endif | 187 | #endif |
std/special/compiler_rt/extendXfYf2.zig+29-27| ... | @@ -10,9 +10,13 @@ pub extern fn __extendsftf2(a: f32) f128 { | ... | @@ -10,9 +10,13 @@ pub extern fn __extendsftf2(a: f32) f128 { |
| 10 | return extendXfYf2(f128, f32, a); | 10 | return extendXfYf2(f128, f32, a); |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | pub extern fn __extendhfsf2(a: u16) f32 { | ||
| 14 | return extendXfYf2(f32, f16, @bitCast(f16, a)); | ||
| 15 | } | ||
| 16 | |||
| 13 | const CHAR_BIT = 8; | 17 | const CHAR_BIT = 8; |
| 14 | 18 | ||
| 15 | pub fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { | 19 | inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { |
| 16 | const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits); | 20 | const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits); |
| 17 | const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits); | 21 | const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits); |
| 18 | const srcSigBits = std.math.floatMantissaBits(src_t); | 22 | const srcSigBits = std.math.floatMantissaBits(src_t); |
| ... | @@ -22,22 +26,22 @@ pub fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { | ... | @@ -22,22 +26,22 @@ pub fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { |
| 22 | 26 | ||
| 23 | // Various constants whose values follow from the type parameters. | 27 | // Various constants whose values follow from the type parameters. |
| 24 | // Any reasonable optimizer will fold and propagate all of these. | 28 | // Any reasonable optimizer will fold and propagate all of these. |
| 25 | const srcBits: i32 = @sizeOf(src_t) * CHAR_BIT; | 29 | const srcBits = @sizeOf(src_t) * CHAR_BIT; |
| 26 | const srcExpBits: i32 = srcBits - srcSigBits - 1; | 30 | const srcExpBits = srcBits - srcSigBits - 1; |
| 27 | const srcInfExp: i32 = (1 << srcExpBits) - 1; | 31 | const srcInfExp = (1 << srcExpBits) - 1; |
| 28 | const srcExpBias: i32 = srcInfExp >> 1; | 32 | const srcExpBias = srcInfExp >> 1; |
| 29 | 33 | ||
| 30 | const srcMinNormal: src_rep_t = src_rep_t(1) << srcSigBits; | 34 | const srcMinNormal = 1 << srcSigBits; |
| 31 | const srcInfinity: src_rep_t = src_rep_t(@bitCast(u32, srcInfExp)) << srcSigBits; | 35 | const srcInfinity = srcInfExp << srcSigBits; |
| 32 | const srcSignMask: src_rep_t = src_rep_t(1) << @intCast(SrcShift, srcSigBits +% srcExpBits); | 36 | const srcSignMask = 1 << (srcSigBits + srcExpBits); |
| 33 | const srcAbsMask: src_rep_t = srcSignMask -% 1; | 37 | const srcAbsMask = srcSignMask - 1; |
| 34 | const srcQNaN: src_rep_t = src_rep_t(1) << @intCast(SrcShift, srcSigBits -% 1); | 38 | const srcQNaN = 1 << (srcSigBits - 1); |
| 35 | const srcNaNCode: src_rep_t = srcQNaN -% 1; | 39 | const srcNaNCode = srcQNaN - 1; |
| 36 | 40 | ||
| 37 | const dstBits: i32 = @sizeOf(dst_t) * CHAR_BIT; | 41 | const dstBits = @sizeOf(dst_t) * CHAR_BIT; |
| 38 | const dstExpBits: i32 = dstBits - dstSigBits - 1; | 42 | const dstExpBits = dstBits - dstSigBits - 1; |
| 39 | const dstInfExp: i32 = (1 << dstExpBits) - 1; | 43 | const dstInfExp = (1 << dstExpBits) - 1; |
| 40 | const dstExpBias: i32 = dstInfExp >> 1; | 44 | const dstExpBias = dstInfExp >> 1; |
| 41 | 45 | ||
| 42 | const dstMinNormal: dst_rep_t = dst_rep_t(1) << dstSigBits; | 46 | const dstMinNormal: dst_rep_t = dst_rep_t(1) << dstSigBits; |
| 43 | 47 | ||
| ... | @@ -47,38 +51,36 @@ pub fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { | ... | @@ -47,38 +51,36 @@ pub fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { |
| 47 | const sign: src_rep_t = aRep & srcSignMask; | 51 | const sign: src_rep_t = aRep & srcSignMask; |
| 48 | var absResult: dst_rep_t = undefined; | 52 | var absResult: dst_rep_t = undefined; |
| 49 | 53 | ||
| 50 | // If @sizeOf(src_rep_t) < @sizeOf(int), the subtraction result is promoted | 54 | if (aAbs -% srcMinNormal < srcInfinity - srcMinNormal) { |
| 51 | // to (signed) int. To avoid that, explicitly cast to src_rep_t. | ||
| 52 | if ((src_rep_t)(aAbs -% srcMinNormal) < srcInfinity -% srcMinNormal) { | ||
| 53 | // a is a normal number. | 55 | // a is a normal number. |
| 54 | // Extend to the destination type by shifting the significand and | 56 | // Extend to the destination type by shifting the significand and |
| 55 | // exponent into the proper position and rebiasing the exponent. | 57 | // exponent into the proper position and rebiasing the exponent. |
| 56 | absResult = dst_rep_t(aAbs) << (dstSigBits -% srcSigBits); | 58 | absResult = dst_rep_t(aAbs) << (dstSigBits - srcSigBits); |
| 57 | absResult += dst_rep_t(@bitCast(u32, dstExpBias -% srcExpBias)) << dstSigBits; | 59 | absResult += (dstExpBias - srcExpBias) << dstSigBits; |
| 58 | } else if (aAbs >= srcInfinity) { | 60 | } else if (aAbs >= srcInfinity) { |
| 59 | // a is NaN or infinity. | 61 | // a is NaN or infinity. |
| 60 | // Conjure the result by beginning with infinity, then setting the qNaN | 62 | // Conjure the result by beginning with infinity, then setting the qNaN |
| 61 | // bit (if needed) and right-aligning the rest of the trailing NaN | 63 | // bit (if needed) and right-aligning the rest of the trailing NaN |
| 62 | // payload field. | 64 | // payload field. |
| 63 | absResult = dst_rep_t(@bitCast(u32, dstInfExp)) << dstSigBits; | 65 | absResult = dstInfExp << dstSigBits; |
| 64 | absResult |= (dst_rep_t)(aAbs & srcQNaN) << (dstSigBits - srcSigBits); | 66 | absResult |= dst_rep_t(aAbs & srcQNaN) << (dstSigBits - srcSigBits); |
| 65 | absResult |= (dst_rep_t)(aAbs & srcNaNCode) << (dstSigBits - srcSigBits); | 67 | absResult |= dst_rep_t(aAbs & srcNaNCode) << (dstSigBits - srcSigBits); |
| 66 | } else if (aAbs != 0) { | 68 | } else if (aAbs != 0) { |
| 67 | // a is denormal. | 69 | // a is denormal. |
| 68 | // renormalize the significand and clear the leading bit, then insert | 70 | // renormalize the significand and clear the leading bit, then insert |
| 69 | // the correct adjusted exponent in the destination type. | 71 | // the correct adjusted exponent in the destination type. |
| 70 | const scale: i32 = @clz(aAbs) - @clz(srcMinNormal); | 72 | const scale: u32 = @clz(aAbs) - @clz(src_rep_t(srcMinNormal)); |
| 71 | absResult = dst_rep_t(aAbs) << @intCast(DstShift, dstSigBits - srcSigBits + scale); | 73 | absResult = dst_rep_t(aAbs) << @intCast(DstShift, dstSigBits - srcSigBits + scale); |
| 72 | absResult ^= dstMinNormal; | 74 | absResult ^= dstMinNormal; |
| 73 | const resultExponent: i32 = dstExpBias - srcExpBias - scale + 1; | 75 | const resultExponent: u32 = dstExpBias - srcExpBias - scale + 1; |
| 74 | absResult |= dst_rep_t(@bitCast(u32, resultExponent)) << @intCast(DstShift, dstSigBits); | 76 | absResult |= @intCast(dst_rep_t, resultExponent) << dstSigBits; |
| 75 | } else { | 77 | } else { |
| 76 | // a is zero. | 78 | // a is zero. |
| 77 | absResult = 0; | 79 | absResult = 0; |
| 78 | } | 80 | } |
| 79 | 81 | ||
| 80 | // Apply the signbit to (dst_t)abs(a). | 82 | // Apply the signbit to (dst_t)abs(a). |
| 81 | const result: dst_rep_t align(@alignOf(dst_t)) = absResult | dst_rep_t(sign) << @intCast(DstShift, dstBits - srcBits); | 83 | const result: dst_rep_t align(@alignOf(dst_t)) = absResult | dst_rep_t(sign) << (dstBits - srcBits); |
| 82 | return @bitCast(dst_t, result); | 84 | return @bitCast(dst_t, result); |
| 83 | } | 85 | } |
| 84 | 86 |
std/special/compiler_rt/extendXfYf2_test.zig+46| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2; | 1 | const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2; |
| 2 | const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2; | ||
| 2 | const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2; | 3 | const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2; |
| 3 | const assert = @import("std").debug.assert; | 4 | const assert = @import("std").debug.assert; |
| 4 | 5 | ||
| ... | @@ -24,6 +25,22 @@ fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void { | ... | @@ -24,6 +25,22 @@ fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void { |
| 24 | @panic("__extenddftf2 test failure"); | 25 | @panic("__extenddftf2 test failure"); |
| 25 | } | 26 | } |
| 26 | 27 | ||
| 28 | fn test__extendhfsf2(a: u16, expected: u32) void { | ||
| 29 | const x = __extendhfsf2(a); | ||
| 30 | const rep = @bitCast(u32, x); | ||
| 31 | |||
| 32 | if (rep == expected) { | ||
| 33 | if (rep & 0x7fffffff > 0x7f800000) { | ||
| 34 | return; // NaN is always unequal. | ||
| 35 | } | ||
| 36 | if (x == @bitCast(f32, expected)) { | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | @panic("__extendhfsf2 test failure"); | ||
| 42 | } | ||
| 43 | |||
| 27 | fn test__extendsftf2(a: f32, expectedHi: u64, expectedLo: u64) void { | 44 | fn test__extendsftf2(a: f32, expectedHi: u64, expectedLo: u64) void { |
| 28 | const x = __extendsftf2(a); | 45 | const x = __extendsftf2(a); |
| 29 | 46 | ||
| ... | @@ -68,6 +85,35 @@ test "extenddftf2" { | ... | @@ -68,6 +85,35 @@ test "extenddftf2" { |
| 68 | test__extenddftf2(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); | 85 | test__extenddftf2(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); |
| 69 | } | 86 | } |
| 70 | 87 | ||
| 88 | test "extendhfsf2" { | ||
| 89 | test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN | ||
| 90 | test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN | ||
| 91 | |||
| 92 | test__extendhfsf2(0, 0); // 0 | ||
| 93 | test__extendhfsf2(0x8000, 0x80000000); // -0 | ||
| 94 | |||
| 95 | test__extendhfsf2(0x7c00, 0x7f800000); // inf | ||
| 96 | test__extendhfsf2(0xfc00, 0xff800000); // -inf | ||
| 97 | |||
| 98 | test__extendhfsf2(0x0001, 0x33800000); // denormal (min), 2**-24 | ||
| 99 | test__extendhfsf2(0x8001, 0xb3800000); // denormal (min), -2**-24 | ||
| 100 | |||
| 101 | test__extendhfsf2(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24 | ||
| 102 | test__extendhfsf2(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24 | ||
| 103 | |||
| 104 | test__extendhfsf2(0x0400, 0x38800000); // normal (min), 2**-14 | ||
| 105 | test__extendhfsf2(0x8400, 0xb8800000); // normal (min), -2**-14 | ||
| 106 | |||
| 107 | test__extendhfsf2(0x7bff, 0x477fe000); // normal (max), 65504 | ||
| 108 | test__extendhfsf2(0xfbff, 0xc77fe000); // normal (max), -65504 | ||
| 109 | |||
| 110 | test__extendhfsf2(0x3c01, 0x3f802000); // normal, 1 + 2**-10 | ||
| 111 | test__extendhfsf2(0xbc01, 0xbf802000); // normal, -1 - 2**-10 | ||
| 112 | |||
| 113 | test__extendhfsf2(0x3555, 0x3eaaa000); // normal, approx. 1/3 | ||
| 114 | test__extendhfsf2(0xb555, 0xbeaaa000); // normal, approx. -1/3 | ||
| 115 | } | ||
| 116 | |||
| 71 | test "extendsftf2" { | 117 | test "extendsftf2" { |
| 72 | // qNaN | 118 | // qNaN |
| 73 | test__extendsftf2(makeQNaN32(), 0x7fff800000000000, 0x0); | 119 | test__extendsftf2(makeQNaN32(), 0x7fff800000000000, 0x0); |
std/special/compiler_rt/index.zig+5| ... | @@ -15,6 +15,8 @@ comptime { | ... | @@ -15,6 +15,8 @@ comptime { |
| 15 | @export("__lttf2", @import("comparetf2.zig").__letf2, linkage); | 15 | @export("__lttf2", @import("comparetf2.zig").__letf2, linkage); |
| 16 | @export("__netf2", @import("comparetf2.zig").__letf2, linkage); | 16 | @export("__netf2", @import("comparetf2.zig").__letf2, linkage); |
| 17 | @export("__gttf2", @import("comparetf2.zig").__getf2, linkage); | 17 | @export("__gttf2", @import("comparetf2.zig").__getf2, linkage); |
| 18 | @export("__gnu_h2f_ieee", @import("extendXfYf2.zig").__extendhfsf2, linkage); | ||
| 19 | @export("__gnu_f2h_ieee", @import("truncXfYf2.zig").__truncsfhf2, linkage); | ||
| 18 | } | 20 | } |
| 19 | 21 | ||
| 20 | @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage); | 22 | @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage); |
| ... | @@ -22,6 +24,9 @@ comptime { | ... | @@ -22,6 +24,9 @@ comptime { |
| 22 | @export("__floatuntidf", @import("floatuntidf.zig").__floatuntidf, linkage); | 24 | @export("__floatuntidf", @import("floatuntidf.zig").__floatuntidf, linkage); |
| 23 | @export("__extenddftf2", @import("extendXfYf2.zig").__extenddftf2, linkage); | 25 | @export("__extenddftf2", @import("extendXfYf2.zig").__extenddftf2, linkage); |
| 24 | @export("__extendsftf2", @import("extendXfYf2.zig").__extendsftf2, linkage); | 26 | @export("__extendsftf2", @import("extendXfYf2.zig").__extendsftf2, linkage); |
| 27 | @export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage); | ||
| 28 | |||
| 29 | @export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage); | ||
| 25 | 30 | ||
| 26 | @export("__fixunssfsi", @import("fixunssfsi.zig").__fixunssfsi, linkage); | 31 | @export("__fixunssfsi", @import("fixunssfsi.zig").__fixunssfsi, linkage); |
| 27 | @export("__fixunssfdi", @import("fixunssfdi.zig").__fixunssfdi, linkage); | 32 | @export("__fixunssfdi", @import("fixunssfdi.zig").__fixunssfdi, linkage); |
std/special/compiler_rt/truncXfYf2.zig created+111| ... | @@ -0,0 +1,111 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub extern fn __truncsfhf2(a: f32) u16 { | ||
| 4 | return @bitCast(u16, truncXfYf2(f16, f32, a)); | ||
| 5 | } | ||
| 6 | |||
| 7 | const CHAR_BIT = 8; | ||
| 8 | |||
| 9 | inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { | ||
| 10 | const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits); | ||
| 11 | const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits); | ||
| 12 | const srcSigBits = std.math.floatMantissaBits(src_t); | ||
| 13 | const dstSigBits = std.math.floatMantissaBits(dst_t); | ||
| 14 | const SrcShift = std.math.Log2Int(src_rep_t); | ||
| 15 | const DstShift = std.math.Log2Int(dst_rep_t); | ||
| 16 | |||
| 17 | // Various constants whose values follow from the type parameters. | ||
| 18 | // Any reasonable optimizer will fold and propagate all of these. | ||
| 19 | const srcBits = @sizeOf(src_t) * CHAR_BIT; | ||
| 20 | const srcExpBits = srcBits - srcSigBits - 1; | ||
| 21 | const srcInfExp = (1 << srcExpBits) - 1; | ||
| 22 | const srcExpBias = srcInfExp >> 1; | ||
| 23 | |||
| 24 | const srcMinNormal = 1 << srcSigBits; | ||
| 25 | const srcSignificandMask = srcMinNormal - 1; | ||
| 26 | const srcInfinity = srcInfExp << srcSigBits; | ||
| 27 | const srcSignMask = 1 << (srcSigBits + srcExpBits); | ||
| 28 | const srcAbsMask = srcSignMask - 1; | ||
| 29 | const roundMask = (1 << (srcSigBits - dstSigBits)) - 1; | ||
| 30 | const halfway = 1 << (srcSigBits - dstSigBits - 1); | ||
| 31 | const srcQNaN = 1 << (srcSigBits - 1); | ||
| 32 | const srcNaNCode = srcQNaN - 1; | ||
| 33 | |||
| 34 | const dstBits = @sizeOf(dst_t) * CHAR_BIT; | ||
| 35 | const dstExpBits = dstBits - dstSigBits - 1; | ||
| 36 | const dstInfExp = (1 << dstExpBits) - 1; | ||
| 37 | const dstExpBias = dstInfExp >> 1; | ||
| 38 | |||
| 39 | const underflowExponent = srcExpBias + 1 - dstExpBias; | ||
| 40 | const overflowExponent = srcExpBias + dstInfExp - dstExpBias; | ||
| 41 | const underflow = underflowExponent << srcSigBits; | ||
| 42 | const overflow = overflowExponent << srcSigBits; | ||
| 43 | |||
| 44 | const dstQNaN = 1 << (dstSigBits - 1); | ||
| 45 | const dstNaNCode = dstQNaN - 1; | ||
| 46 | |||
| 47 | // Break a into a sign and representation of the absolute value | ||
| 48 | const aRep: src_rep_t = @bitCast(src_rep_t, a); | ||
| 49 | const aAbs: src_rep_t = aRep & srcAbsMask; | ||
| 50 | const sign: src_rep_t = aRep & srcSignMask; | ||
| 51 | var absResult: dst_rep_t = undefined; | ||
| 52 | |||
| 53 | if (aAbs -% underflow < aAbs -% overflow) { | ||
| 54 | // The exponent of a is within the range of normal numbers in the | ||
| 55 | // destination format. We can convert by simply right-shifting with | ||
| 56 | // rounding and adjusting the exponent. | ||
| 57 | absResult = @truncate(dst_rep_t, aAbs >> (srcSigBits - dstSigBits)); | ||
| 58 | absResult -%= dst_rep_t(srcExpBias - dstExpBias) << dstSigBits; | ||
| 59 | |||
| 60 | const roundBits: src_rep_t = aAbs & roundMask; | ||
| 61 | if (roundBits > halfway) { | ||
| 62 | // Round to nearest | ||
| 63 | absResult += 1; | ||
| 64 | } else if (roundBits == halfway) { | ||
| 65 | // Ties to even | ||
| 66 | absResult += absResult & 1; | ||
| 67 | } | ||
| 68 | } else if (aAbs > srcInfinity) { | ||
| 69 | // a is NaN. | ||
| 70 | // Conjure the result by beginning with infinity, setting the qNaN | ||
| 71 | // bit and inserting the (truncated) trailing NaN field. | ||
| 72 | absResult = @intCast(dst_rep_t, dstInfExp) << dstSigBits; | ||
| 73 | absResult |= dstQNaN; | ||
| 74 | absResult |= @intCast(dst_rep_t, ((aAbs & srcNaNCode) >> (srcSigBits - dstSigBits)) & dstNaNCode); | ||
| 75 | } else if (aAbs >= overflow) { | ||
| 76 | // a overflows to infinity. | ||
| 77 | absResult = @intCast(dst_rep_t, dstInfExp) << dstSigBits; | ||
| 78 | } else { | ||
| 79 | // a underflows on conversion to the destination type or is an exact | ||
| 80 | // zero. The result may be a denormal or zero. Extract the exponent | ||
| 81 | // to get the shift amount for the denormalization. | ||
| 82 | const aExp: u32 = aAbs >> srcSigBits; | ||
| 83 | const shift: u32 = srcExpBias - dstExpBias - aExp + 1; | ||
| 84 | |||
| 85 | const significand: src_rep_t = (aRep & srcSignificandMask) | srcMinNormal; | ||
| 86 | |||
| 87 | // Right shift by the denormalization amount with sticky. | ||
| 88 | if (shift > srcSigBits) { | ||
| 89 | absResult = 0; | ||
| 90 | } else { | ||
| 91 | const sticky: src_rep_t = significand << @intCast(SrcShift, srcBits - shift); | ||
| 92 | const denormalizedSignificand: src_rep_t = significand >> @intCast(SrcShift, shift) | sticky; | ||
| 93 | absResult = @intCast(dst_rep_t, denormalizedSignificand >> (srcSigBits - dstSigBits)); | ||
| 94 | const roundBits: src_rep_t = denormalizedSignificand & roundMask; | ||
| 95 | if (roundBits > halfway) { | ||
| 96 | // Round to nearest | ||
| 97 | absResult += 1; | ||
| 98 | } else if (roundBits == halfway) { | ||
| 99 | // Ties to even | ||
| 100 | absResult += absResult & 1; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @truncate(dst_rep_t, sign >> @intCast(SrcShift, srcBits - dstBits)); | ||
| 106 | return @bitCast(dst_t, result); | ||
| 107 | } | ||
| 108 | |||
| 109 | test "import truncXfYf2" { | ||
| 110 | _ = @import("truncXfYf2_test.zig"); | ||
| 111 | } | ||
std/special/compiler_rt/truncXfYf2_test.zig created+64| ... | @@ -0,0 +1,64 @@ | ||
| 1 | const __truncsfhf2 = @import("truncXfYf2.zig").__truncsfhf2; | ||
| 2 | |||
| 3 | fn test__truncsfhf2(a: u32, expected: u16) void { | ||
| 4 | const actual = __truncsfhf2(@bitCast(f32, a)); | ||
| 5 | |||
| 6 | if (actual == expected) { | ||
| 7 | return; | ||
| 8 | } | ||
| 9 | |||
| 10 | @panic("__truncsfhf2 test failure"); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "truncsfhf2" { | ||
| 14 | test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN | ||
| 15 | test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN | ||
| 16 | |||
| 17 | test__truncsfhf2(0, 0); // 0 | ||
| 18 | test__truncsfhf2(0x80000000, 0x8000); // -0 | ||
| 19 | |||
| 20 | test__truncsfhf2(0x7f800000, 0x7c00); // inf | ||
| 21 | test__truncsfhf2(0xff800000, 0xfc00); // -inf | ||
| 22 | |||
| 23 | test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf | ||
| 24 | test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf | ||
| 25 | |||
| 26 | test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf | ||
| 27 | test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf | ||
| 28 | |||
| 29 | test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-14 | ||
| 30 | test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-14 | ||
| 31 | |||
| 32 | test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 65504 | ||
| 33 | test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -65504 | ||
| 34 | |||
| 35 | test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 65504 | ||
| 36 | test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -65504 | ||
| 37 | |||
| 38 | test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 65504 | ||
| 39 | test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -65504 | ||
| 40 | |||
| 41 | test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-10 | ||
| 42 | test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-10 | ||
| 43 | |||
| 44 | test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/3 | ||
| 45 | test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/3 | ||
| 46 | |||
| 47 | test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.1415926535 | ||
| 48 | test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.1415926535 | ||
| 49 | |||
| 50 | test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12 | ||
| 51 | |||
| 52 | test__truncsfhf2(0x3f800000, 0x3c00); // normal, 1 | ||
| 53 | test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-14 | ||
| 54 | |||
| 55 | test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-24 | ||
| 56 | test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-24 | ||
| 57 | |||
| 58 | test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24 | ||
| 59 | test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24 | ||
| 60 | |||
| 61 | test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-20 | ||
| 62 | test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24 | ||
| 63 | test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero | ||
| 64 | } | ||
test/cases/cast.zig+38-15| ... | @@ -350,13 +350,16 @@ fn testFloatToInts() void { | ... | @@ -350,13 +350,16 @@ fn testFloatToInts() void { |
| 350 | assert(x == 10000); | 350 | assert(x == 10000); |
| 351 | const y = @floatToInt(i32, f32(1e4)); | 351 | const y = @floatToInt(i32, f32(1e4)); |
| 352 | assert(y == 10000); | 352 | assert(y == 10000); |
| 353 | expectFloatToInt(u8, 255.1, 255); | 353 | expectFloatToInt(f16, 255.1, u8, 255); |
| 354 | expectFloatToInt(i8, 127.2, 127); | 354 | expectFloatToInt(f16, 127.2, i8, 127); |
| 355 | expectFloatToInt(i8, -128.2, -128); | 355 | expectFloatToInt(f16, -128.2, i8, -128); |
| 356 | expectFloatToInt(f32, 255.1, u8, 255); | ||
| 357 | expectFloatToInt(f32, 127.2, i8, 127); | ||
| 358 | expectFloatToInt(f32, -128.2, i8, -128); | ||
| 356 | } | 359 | } |
| 357 | 360 | ||
| 358 | fn expectFloatToInt(comptime T: type, f: f32, i: T) void { | 361 | fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void { |
| 359 | assert(@floatToInt(T, f) == i); | 362 | assert(@floatToInt(I, f) == i); |
| 360 | } | 363 | } |
| 361 | 364 | ||
| 362 | test "cast u128 to f128 and back" { | 365 | test "cast u128 to f128 and back" { |
| ... | @@ -418,19 +421,39 @@ test "@intCast comptime_int" { | ... | @@ -418,19 +421,39 @@ test "@intCast comptime_int" { |
| 418 | } | 421 | } |
| 419 | 422 | ||
| 420 | test "@floatCast comptime_int and comptime_float" { | 423 | test "@floatCast comptime_int and comptime_float" { |
| 421 | const result = @floatCast(f32, 1234); | 424 | { |
| 422 | assert(@typeOf(result) == f32); | 425 | const result = @floatCast(f16, 1234); |
| 423 | assert(result == 1234.0); | 426 | assert(@typeOf(result) == f16); |
| 424 | 427 | assert(result == 1234.0); | |
| 425 | const result2 = @floatCast(f32, 1234.0); | 428 | } |
| 426 | assert(@typeOf(result) == f32); | 429 | { |
| 427 | assert(result == 1234.0); | 430 | const result = @floatCast(f16, 1234.0); |
| 431 | assert(@typeOf(result) == f16); | ||
| 432 | assert(result == 1234.0); | ||
| 433 | } | ||
| 434 | { | ||
| 435 | const result = @floatCast(f32, 1234); | ||
| 436 | assert(@typeOf(result) == f32); | ||
| 437 | assert(result == 1234.0); | ||
| 438 | } | ||
| 439 | { | ||
| 440 | const result = @floatCast(f32, 1234.0); | ||
| 441 | assert(@typeOf(result) == f32); | ||
| 442 | assert(result == 1234.0); | ||
| 443 | } | ||
| 428 | } | 444 | } |
| 429 | 445 | ||
| 430 | test "comptime_int @intToFloat" { | 446 | test "comptime_int @intToFloat" { |
| 431 | const result = @intToFloat(f32, 1234); | 447 | { |
| 432 | assert(@typeOf(result) == f32); | 448 | const result = @intToFloat(f16, 1234); |
| 433 | assert(result == 1234.0); | 449 | assert(@typeOf(result) == f16); |
| 450 | assert(result == 1234.0); | ||
| 451 | } | ||
| 452 | { | ||
| 453 | const result = @intToFloat(f32, 1234); | ||
| 454 | assert(@typeOf(result) == f32); | ||
| 455 | assert(result == 1234.0); | ||
| 456 | } | ||
| 434 | } | 457 | } |
| 435 | 458 | ||
| 436 | test "@bytesToSlice keeps pointer alignment" { | 459 | test "@bytesToSlice keeps pointer alignment" { |
test/cases/math.zig+13-1| ... | @@ -6,15 +6,20 @@ test "division" { | ... | @@ -6,15 +6,20 @@ test "division" { |
| 6 | } | 6 | } |
| 7 | fn testDivision() void { | 7 | fn testDivision() void { |
| 8 | assert(div(u32, 13, 3) == 4); | 8 | assert(div(u32, 13, 3) == 4); |
| 9 | assert(div(f16, 1.0, 2.0) == 0.5); | ||
| 9 | assert(div(f32, 1.0, 2.0) == 0.5); | 10 | assert(div(f32, 1.0, 2.0) == 0.5); |
| 10 | 11 | ||
| 11 | assert(divExact(u32, 55, 11) == 5); | 12 | assert(divExact(u32, 55, 11) == 5); |
| 12 | assert(divExact(i32, -55, 11) == -5); | 13 | assert(divExact(i32, -55, 11) == -5); |
| 14 | assert(divExact(f16, 55.0, 11.0) == 5.0); | ||
| 15 | assert(divExact(f16, -55.0, 11.0) == -5.0); | ||
| 13 | assert(divExact(f32, 55.0, 11.0) == 5.0); | 16 | assert(divExact(f32, 55.0, 11.0) == 5.0); |
| 14 | assert(divExact(f32, -55.0, 11.0) == -5.0); | 17 | assert(divExact(f32, -55.0, 11.0) == -5.0); |
| 15 | 18 | ||
| 16 | assert(divFloor(i32, 5, 3) == 1); | 19 | assert(divFloor(i32, 5, 3) == 1); |
| 17 | assert(divFloor(i32, -5, 3) == -2); | 20 | assert(divFloor(i32, -5, 3) == -2); |
| 21 | assert(divFloor(f16, 5.0, 3.0) == 1.0); | ||
| 22 | assert(divFloor(f16, -5.0, 3.0) == -2.0); | ||
| 18 | assert(divFloor(f32, 5.0, 3.0) == 1.0); | 23 | assert(divFloor(f32, 5.0, 3.0) == 1.0); |
| 19 | assert(divFloor(f32, -5.0, 3.0) == -2.0); | 24 | assert(divFloor(f32, -5.0, 3.0) == -2.0); |
| 20 | assert(divFloor(i32, -0x80000000, -2) == 0x40000000); | 25 | assert(divFloor(i32, -0x80000000, -2) == 0x40000000); |
| ... | @@ -24,8 +29,12 @@ fn testDivision() void { | ... | @@ -24,8 +29,12 @@ fn testDivision() void { |
| 24 | 29 | ||
| 25 | assert(divTrunc(i32, 5, 3) == 1); | 30 | assert(divTrunc(i32, 5, 3) == 1); |
| 26 | assert(divTrunc(i32, -5, 3) == -1); | 31 | assert(divTrunc(i32, -5, 3) == -1); |
| 32 | assert(divTrunc(f16, 5.0, 3.0) == 1.0); | ||
| 33 | assert(divTrunc(f16, -5.0, 3.0) == -1.0); | ||
| 27 | assert(divTrunc(f32, 5.0, 3.0) == 1.0); | 34 | assert(divTrunc(f32, 5.0, 3.0) == 1.0); |
| 28 | assert(divTrunc(f32, -5.0, 3.0) == -1.0); | 35 | assert(divTrunc(f32, -5.0, 3.0) == -1.0); |
| 36 | assert(divTrunc(f64, 5.0, 3.0) == 1.0); | ||
| 37 | assert(divTrunc(f64, -5.0, 3.0) == -1.0); | ||
| 29 | 38 | ||
| 30 | comptime { | 39 | comptime { |
| 31 | assert( | 40 | assert( |
| ... | @@ -435,10 +444,11 @@ test "comptime float rem int" { | ... | @@ -435,10 +444,11 @@ test "comptime float rem int" { |
| 435 | } | 444 | } |
| 436 | 445 | ||
| 437 | test "remainder division" { | 446 | test "remainder division" { |
| 447 | comptime remdiv(f16); | ||
| 438 | comptime remdiv(f32); | 448 | comptime remdiv(f32); |
| 439 | comptime remdiv(f64); | 449 | comptime remdiv(f64); |
| 440 | comptime remdiv(f128); | 450 | comptime remdiv(f128); |
| 441 | remdiv(f32); | 451 | remdiv(f16); |
| 442 | remdiv(f64); | 452 | remdiv(f64); |
| 443 | remdiv(f128); | 453 | remdiv(f128); |
| 444 | } | 454 | } |
| ... | @@ -453,6 +463,8 @@ test "@sqrt" { | ... | @@ -453,6 +463,8 @@ test "@sqrt" { |
| 453 | comptime testSqrt(f64, 12.0); | 463 | comptime testSqrt(f64, 12.0); |
| 454 | testSqrt(f32, 13.0); | 464 | testSqrt(f32, 13.0); |
| 455 | comptime testSqrt(f32, 13.0); | 465 | comptime testSqrt(f32, 13.0); |
| 466 | testSqrt(f16, 13.0); | ||
| 467 | comptime testSqrt(f16, 13.0); | ||
| 456 | 468 | ||
| 457 | const x = 14.0; | 469 | const x = 14.0; |
| 458 | const y = x * x; | 470 | const y = x * x; |
test/cases/misc.zig+1| ... | @@ -53,6 +53,7 @@ test "@IntType builtin" { | ... | @@ -53,6 +53,7 @@ test "@IntType builtin" { |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | test "floating point primitive bit counts" { | 55 | test "floating point primitive bit counts" { |
| 56 | assert(f16.bit_count == 16); | ||
| 56 | assert(f32.bit_count == 32); | 57 | assert(f32.bit_count == 32); |
| 57 | assert(f64.bit_count == 64); | 58 | assert(f64.bit_count == 64); |
| 58 | } | 59 | } |