authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-27 12:29:05-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-06-27 12:29:05-04:00
log1b4bae6d69937043add14c0dac357c1a1b05f037
tree68de983b3b3fc8bcadaf86322428c03906547c04
parent4de60dde6ed734acbc428887866ae3d528abbd37
parent440c1d52b4053c40c58c05116c8f6d9da8e35eed
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #1159 from bnoordhuis/f16

add f16 type

16 files changed, 529 insertions(+), 100 deletions(-)

CMakeLists.txt+16
...@@ -261,12 +261,15 @@ endif()...@@ -261,12 +261,15 @@ endif()
261set(EMBEDDED_SOFTFLOAT_SOURCES261set(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 == ConstValSpecialStatic258 // 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}
2020
21void bigfloat_init_16(BigFloat *dest, float16_t x) {
22 f16_to_f128M(x, &dest->value);
23}
24
21void bigfloat_init_32(BigFloat *dest, float x) {25void 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}
148152
153float16_t bigfloat_to_f16(const BigFloat *bigfloat) {
154 return f128M_to_f16(&bigfloat->value);
155}
156
149float bigfloat_to_f32(const BigFloat *bigfloat) {157float 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 {
2222
23struct Buf;23struct Buf;
2424
25void bigfloat_init_16(BigFloat *dest, float16_t x);
25void bigfloat_init_32(BigFloat *dest, float x);26void bigfloat_init_32(BigFloat *dest, float x);
26void bigfloat_init_64(BigFloat *dest, double x);27void bigfloat_init_64(BigFloat *dest, double x);
27void bigfloat_init_128(BigFloat *dest, float128_t x);28void 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);
29void bigfloat_init_bigint(BigFloat *dest, const BigInt *op);30void bigfloat_init_bigint(BigFloat *dest, const BigInt *op);
30int bigfloat_init_buf_base10(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len);31int bigfloat_init_buf_base10(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len);
3132
33float16_t bigfloat_to_f16(const BigFloat *bigfloat);
32float bigfloat_to_f32(const BigFloat *bigfloat);34float bigfloat_to_f32(const BigFloat *bigfloat);
33double bigfloat_to_f64(const BigFloat *bigfloat);35double bigfloat_to_f64(const BigFloat *bigfloat);
34float128_t bigfloat_to_f128(const BigFloat *bigfloat);36float128_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"
2122
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;
61986183
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;
62116193
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);
62246206
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"
1718
18struct IrExecContext {19struct 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}
73517374
7375static 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
7352static void float_init_f32(ConstExprValue *dest_val, float x) {7400static 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}
77127804
7805// c = a - b * trunc(a / b)
7806static 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)
7714static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t* c) {7816static 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) {
7770void float_write_ieee597(ConstExprValue *op, uint8_t *buf, bool is_big_endian) {7881void 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 endian7888 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) {
7790void float_read_ieee597(ConstExprValue *val, uint8_t *buf, bool is_big_endian) {7904void 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 endian7911 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 }
2012520251
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 @@
3131
32#endif32#endif
3333
34#include "softfloat.hpp"
35
34#define BREAKPOINT __asm("int $0x03")36#define BREAKPOINT __asm("int $0x03")
3537
36ATTRIBUTE_COLD38ATTRIBUTE_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}
167169
170static 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.
179static 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#endif187#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}
1212
13pub extern fn __extendhfsf2(a: u16) f32 {
14 return extendXfYf2(f32, f16, @bitCast(f16, a));
15}
16
13const CHAR_BIT = 8;17const CHAR_BIT = 8;
1418
15pub fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {19inline 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 {
2226
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;
2933
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;
3640
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;
4145
42 const dstMinNormal: dst_rep_t = dst_rep_t(1) << dstSigBits;46 const dstMinNormal: dst_rep_t = dst_rep_t(1) << dstSigBits;
4347
...@@ -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;
4953
50 // If @sizeOf(src_rep_t) < @sizeOf(int), the subtraction result is promoted54 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 and56 // 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 qNaN62 // Conjure the result by beginning with infinity, then setting the qNaN
61 // bit (if needed) and right-aligning the rest of the trailing NaN63 // 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 insert70 // 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 }
7981
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}
8486
std/special/compiler_rt/extendXfYf2_test.zig+46
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;1const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
2const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;
2const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;3const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;
3const assert = @import("std").debug.assert;4const assert = @import("std").debug.assert;
45
...@@ -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}
2627
28fn 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
27fn test__extendsftf2(a: f32, expectedHi: u64, expectedLo: u64) void {44fn test__extendsftf2(a: f32, expectedHi: u64, expectedLo: u64) void {
28 const x = __extendsftf2(a);45 const x = __extendsftf2(a);
2946
...@@ -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}
7087
88test "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
71test "extendsftf2" {117test "extendsftf2" {
72 // qNaN118 // 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 }
1921
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);
2530
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 @@
1const std = @import("std");
2
3pub extern fn __truncsfhf2(a: f32) u16 {
4 return @bitCast(u16, truncXfYf2(f16, f32, a));
5}
6
7const CHAR_BIT = 8;
8
9inline 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
109test "import truncXfYf2" {
110 _ = @import("truncXfYf2_test.zig");
111}
std/special/compiler_rt/truncXfYf2_test.zig created+64
...@@ -0,0 +1,64 @@
1const __truncsfhf2 = @import("truncXfYf2.zig").__truncsfhf2;
2
3fn 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
13test "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}
357360
358fn expectFloatToInt(comptime T: type, f: f32, i: T) void {361fn 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}
361364
362test "cast u128 to f128 and back" {365test "cast u128 to f128 and back" {
...@@ -418,19 +421,39 @@ test "@intCast comptime_int" {...@@ -418,19 +421,39 @@ test "@intCast comptime_int" {
418}421}
419422
420test "@floatCast comptime_int and comptime_float" {423test "@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);
424427 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}
429445
430test "comptime_int @intToFloat" {446test "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}
435458
436test "@bytesToSlice keeps pointer alignment" {459test "@bytesToSlice keeps pointer alignment" {
test/cases/math.zig+13-1
...@@ -6,15 +6,20 @@ test "division" {...@@ -6,15 +6,20 @@ test "division" {
6}6}
7fn testDivision() void {7fn 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);
1011
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);
1518
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 {
2429
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);
2938
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}
436445
437test "remainder division" {446test "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);
456468
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}
5454
55test "floating point primitive bit counts" {55test "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}