Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,16 @@ set(ZIG_STD_FILES
"special/compiler_rt/fixunstfdi.zig"
"special/compiler_rt/fixunstfsi.zig"
"special/compiler_rt/fixunstfti.zig"
"special/compiler_rt/fixint.zig"
"special/compiler_rt/fixdfdi.zig"
"special/compiler_rt/fixdfsi.zig"
"special/compiler_rt/fixdfti.zig"
"special/compiler_rt/fixsfdi.zig"
"special/compiler_rt/fixsfsi.zig"
"special/compiler_rt/fixsfti.zig"
"special/compiler_rt/fixtfdi.zig"
"special/compiler_rt/fixtfsi.zig"
"special/compiler_rt/fixtfti.zig"
"special/compiler_rt/floattidf.zig"
"special/compiler_rt/floattisf.zig"
"special/compiler_rt/floattitf.zig"
Expand Down
7 changes: 7 additions & 0 deletions std/math/index.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ const assert = std.debug.assert;
pub const e = 2.71828182845904523536028747135266249775724709369995;
pub const pi = 3.14159265358979323846264338327950288419716939937510;

// From a small c++ [program using boost float128](https://github.com/winksaville/cpp_boost_float128)
pub const f128_true_min = @bitCast(f128, u128(0x00000000000000000000000000000001));
pub const f128_min = @bitCast(f128, u128(0x00010000000000000000000000000000));
pub const f128_max = @bitCast(f128, u128(0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
pub const f128_epsilon = @bitCast(f128, u128(0x3F8F0000000000000000000000000000));
pub const f128_toint = 1.0 / f128_epsilon;

// float.h details
pub const f64_true_min = 4.94065645841246544177e-324;
pub const f64_min = 2.2250738585072014e-308;
Expand Down
11 changes: 11 additions & 0 deletions std/special/compiler_rt/fixdfdi.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const fixint = @import("fixint.zig").fixint;
const builtin = @import("builtin");

pub extern fn __fixdfdi(a: f64) i64 {
@setRuntimeSafety(builtin.is_test);
return fixint(f64, i64, a);
}

test "import fixdfdi" {
_ = @import("fixdfdi_test.zig");
}
66 changes: 66 additions & 0 deletions std/special/compiler_rt/fixdfdi_test.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
const std = @import("std");
const math = std.math;
const assert = std.debug.assert;
const warn = std.debug.warn;

fn test__fixdfdi(a: f64, expected: i64) void {
const x = __fixdfdi(a);
//warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u64, expected));
assert(x == expected);
}

test "fixdfdi" {
//warn("\n");

test__fixdfdi(-math.f64_max, math.minInt(i64));

test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);

test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000);
test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);

test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000);
test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000);
test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);

test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);

test__fixdfdi(-2.01, -2);
test__fixdfdi(-2.0, -2);
test__fixdfdi(-1.99, -1);
test__fixdfdi(-1.0, -1);
test__fixdfdi(-0.99, 0);
test__fixdfdi(-0.5, 0);
test__fixdfdi(-math.f64_min, 0);
test__fixdfdi(0.0, 0);
test__fixdfdi(math.f64_min, 0);
test__fixdfdi(0.5, 0);
test__fixdfdi(0.99, 0);
test__fixdfdi(1.0, 1);
test__fixdfdi(1.5, 1);
test__fixdfdi(1.99, 1);
test__fixdfdi(2.0, 2);
test__fixdfdi(2.01, 2);

test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);

test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);

test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);

test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));

test__fixdfdi(math.f64_max, math.maxInt(i64));
}
11 changes: 11 additions & 0 deletions std/special/compiler_rt/fixdfsi.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const fixint = @import("fixint.zig").fixint;
const builtin = @import("builtin");

pub extern fn __fixdfsi(a: f64) i32 {
@setRuntimeSafety(builtin.is_test);
return fixint(f64, i32, a);
}

test "import fixdfsi" {
_ = @import("fixdfsi_test.zig");
}
74 changes: 74 additions & 0 deletions std/special/compiler_rt/fixdfsi_test.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const __fixdfsi = @import("fixdfsi.zig").__fixdfsi;
const std = @import("std");
const math = std.math;
const assert = std.debug.assert;
const warn = std.debug.warn;

fn test__fixdfsi(a: f64, expected: i32) void {
const x = __fixdfsi(a);
//warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u32, expected));
assert(x == expected);
}

test "fixdfsi" {
//warn("\n");

test__fixdfsi(-math.f64_max, math.minInt(i32));

test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);

test__fixdfsi(-0x1.0000000000000p+127, -0x80000000);
test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);

test__fixdfsi(-0x1.0000000000001p+63, -0x80000000);
test__fixdfsi(-0x1.0000000000000p+63, -0x80000000);
test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);

test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000);
test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000);

test__fixdfsi(-0x1.000000p+31, -0x80000000);
test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);

test__fixdfsi(-2.01, -2);
test__fixdfsi(-2.0, -2);
test__fixdfsi(-1.99, -1);
test__fixdfsi(-1.0, -1);
test__fixdfsi(-0.99, 0);
test__fixdfsi(-0.5, 0);
test__fixdfsi(-math.f64_min, 0);
test__fixdfsi(0.0, 0);
test__fixdfsi(math.f64_min, 0);
test__fixdfsi(0.5, 0);
test__fixdfsi(0.99, 0);
test__fixdfsi(1.0, 1);
test__fixdfsi(1.5, 1);
test__fixdfsi(1.99, 1);
test__fixdfsi(2.0, 2);
test__fixdfsi(2.01, 2);

test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF);

test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);

test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF);

test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF);

test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));

test__fixdfsi(math.f64_max, math.maxInt(i32));
}
11 changes: 11 additions & 0 deletions std/special/compiler_rt/fixdfti.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const fixint = @import("fixint.zig").fixint;
const builtin = @import("builtin");

pub extern fn __fixdfti(a: f64) i128 {
@setRuntimeSafety(builtin.is_test);
return fixint(f64, i128, a);
}

test "import fixdfti" {
_ = @import("fixdfti_test.zig");
}
66 changes: 66 additions & 0 deletions std/special/compiler_rt/fixdfti_test.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const __fixdfti = @import("fixdfti.zig").__fixdfti;
const std = @import("std");
const math = std.math;
const assert = std.debug.assert;
const warn = std.debug.warn;

fn test__fixdfti(a: f64, expected: i128) void {
const x = __fixdfti(a);
//warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u128, expected));
assert(x == expected);
}

test "fixdfti" {
//warn("\n");

test__fixdfti(-math.f64_max, math.minInt(i128));

test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);

test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);

test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800);
test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000);
test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);

test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);

test__fixdfti(-2.01, -2);
test__fixdfti(-2.0, -2);
test__fixdfti(-1.99, -1);
test__fixdfti(-1.0, -1);
test__fixdfti(-0.99, 0);
test__fixdfti(-0.5, 0);
test__fixdfti(-math.f64_min, 0);
test__fixdfti(0.0, 0);
test__fixdfti(math.f64_min, 0);
test__fixdfti(0.5, 0);
test__fixdfti(0.99, 0);
test__fixdfti(1.0, 1);
test__fixdfti(1.5, 1);
test__fixdfti(1.99, 1);
test__fixdfti(2.0, 2);
test__fixdfti(2.01, 2);

test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);

test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000);
test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800);

test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));

test__fixdfti(math.f64_max, math.maxInt(i128));
}
74 changes: 74 additions & 0 deletions std/special/compiler_rt/fixint.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const is_test = @import("builtin").is_test;
const std = @import("std");
const math = std.math;
const Log2Int = std.math.Log2Int;
const maxInt = std.math.maxInt;
const minInt = std.math.minInt;

const DBG = false;

pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t {
@setRuntimeSafety(is_test);

const rep_t = switch (fp_t) {
f32 => u32,
f64 => u64,
f128 => u128,
else => unreachable,
};
const significandBits = switch (fp_t) {
f32 => 23,
f64 => 52,
f128 => 112,
else => unreachable,
};

const typeWidth = rep_t.bit_count;
const exponentBits = (typeWidth - significandBits - 1);
const signBit = (rep_t(1) << (significandBits + exponentBits));
const maxExponent = ((1 << exponentBits) - 1);
const exponentBias = (maxExponent >> 1);

const implicitBit = (rep_t(1) << significandBits);
const significandMask = (implicitBit - 1);

// Break a into sign, exponent, significand
const aRep: rep_t = @bitCast(rep_t, a);
const absMask = signBit - 1;
const aAbs: rep_t = aRep & absMask;

const negative = (aRep & signBit) != 0;
const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias;
const significand: rep_t = (aAbs & significandMask) | implicitBit;

// If exponent is negative, the uint_result is zero.
if (exponent < 0) return 0;

// The unsigned result needs to be large enough to handle an fixint_t or rep_t
const fixuint_t = @IntType(false, fixint_t.bit_count);
const UintResultType = if (fixint_t.bit_count > rep_t.bit_count) fixuint_t else rep_t;
var uint_result: UintResultType = undefined;

// If the value is too large for the integer type, saturate.
if (@intCast(usize, exponent) >= fixint_t.bit_count) {
return if (negative) fixint_t(minInt(fixint_t)) else fixint_t(maxInt(fixint_t));
}

// If 0 <= exponent < significandBits, right shift else left shift
if (exponent < significandBits) {
uint_result = @intCast(UintResultType, significand) >> @intCast(Log2Int(UintResultType), significandBits - exponent);
} else {
uint_result = @intCast(UintResultType, significand) << @intCast(Log2Int(UintResultType), exponent - significandBits);
}

// Cast to final signed result
if (negative) {
return if (uint_result >= -math.minInt(fixint_t)) math.minInt(fixint_t) else -@intCast(fixint_t, uint_result);
} else {
return if (uint_result >= math.maxInt(fixint_t)) math.maxInt(fixint_t) else @intCast(fixint_t, uint_result);
}
}

test "import fixint" {
_ = @import("fixint_test.zig");
}
Loading