mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
all: migrate code to new cast builtin syntax
Most of this migration was performed automatically with `zig fmt`. There were a few exceptions which I had to manually fix: * `@alignCast` and `@addrSpaceCast` cannot be automatically rewritten * `@truncate`'s fixup is incorrect for vectors * Test cases are not formatted, and their error locations change
This commit is contained in:
parent
447ca4e3ff
commit
f26dda2117
@ -24,28 +24,28 @@ pub inline fn addf3(comptime T: type, a: T, b: T) T {
|
|||||||
const significandMask = (@as(Z, 1) << significandBits) - 1;
|
const significandMask = (@as(Z, 1) << significandBits) - 1;
|
||||||
|
|
||||||
const absMask = signBit - 1;
|
const absMask = signBit - 1;
|
||||||
const qnanRep = @bitCast(Z, math.nan(T)) | quietBit;
|
const qnanRep = @as(Z, @bitCast(math.nan(T))) | quietBit;
|
||||||
|
|
||||||
var aRep = @bitCast(Z, a);
|
var aRep = @as(Z, @bitCast(a));
|
||||||
var bRep = @bitCast(Z, b);
|
var bRep = @as(Z, @bitCast(b));
|
||||||
const aAbs = aRep & absMask;
|
const aAbs = aRep & absMask;
|
||||||
const bAbs = bRep & absMask;
|
const bAbs = bRep & absMask;
|
||||||
|
|
||||||
const infRep = @bitCast(Z, math.inf(T));
|
const infRep = @as(Z, @bitCast(math.inf(T)));
|
||||||
|
|
||||||
// Detect if a or b is zero, infinity, or NaN.
|
// Detect if a or b is zero, infinity, or NaN.
|
||||||
if (aAbs -% @as(Z, 1) >= infRep - @as(Z, 1) or
|
if (aAbs -% @as(Z, 1) >= infRep - @as(Z, 1) or
|
||||||
bAbs -% @as(Z, 1) >= infRep - @as(Z, 1))
|
bAbs -% @as(Z, 1) >= infRep - @as(Z, 1))
|
||||||
{
|
{
|
||||||
// NaN + anything = qNaN
|
// NaN + anything = qNaN
|
||||||
if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);
|
if (aAbs > infRep) return @as(T, @bitCast(@as(Z, @bitCast(a)) | quietBit));
|
||||||
// anything + NaN = qNaN
|
// anything + NaN = qNaN
|
||||||
if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit);
|
if (bAbs > infRep) return @as(T, @bitCast(@as(Z, @bitCast(b)) | quietBit));
|
||||||
|
|
||||||
if (aAbs == infRep) {
|
if (aAbs == infRep) {
|
||||||
// +/-infinity + -/+infinity = qNaN
|
// +/-infinity + -/+infinity = qNaN
|
||||||
if ((@bitCast(Z, a) ^ @bitCast(Z, b)) == signBit) {
|
if ((@as(Z, @bitCast(a)) ^ @as(Z, @bitCast(b))) == signBit) {
|
||||||
return @bitCast(T, qnanRep);
|
return @as(T, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
// +/-infinity + anything remaining = +/- infinity
|
// +/-infinity + anything remaining = +/- infinity
|
||||||
else {
|
else {
|
||||||
@ -60,7 +60,7 @@ pub inline fn addf3(comptime T: type, a: T, b: T) T {
|
|||||||
if (aAbs == 0) {
|
if (aAbs == 0) {
|
||||||
// but we need to get the sign right for zero + zero
|
// but we need to get the sign right for zero + zero
|
||||||
if (bAbs == 0) {
|
if (bAbs == 0) {
|
||||||
return @bitCast(T, @bitCast(Z, a) & @bitCast(Z, b));
|
return @as(T, @bitCast(@as(Z, @bitCast(a)) & @as(Z, @bitCast(b))));
|
||||||
} else {
|
} else {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
@ -78,8 +78,8 @@ pub inline fn addf3(comptime T: type, a: T, b: T) T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract the exponent and significand from the (possibly swapped) a and b.
|
// Extract the exponent and significand from the (possibly swapped) a and b.
|
||||||
var aExponent = @intCast(i32, (aRep >> significandBits) & maxExponent);
|
var aExponent = @as(i32, @intCast((aRep >> significandBits) & maxExponent));
|
||||||
var bExponent = @intCast(i32, (bRep >> significandBits) & maxExponent);
|
var bExponent = @as(i32, @intCast((bRep >> significandBits) & maxExponent));
|
||||||
var aSignificand = aRep & significandMask;
|
var aSignificand = aRep & significandMask;
|
||||||
var bSignificand = bRep & significandMask;
|
var bSignificand = bRep & significandMask;
|
||||||
|
|
||||||
@ -101,11 +101,11 @@ pub inline fn addf3(comptime T: type, a: T, b: T) T {
|
|||||||
|
|
||||||
// Shift the significand of b by the difference in exponents, with a sticky
|
// Shift the significand of b by the difference in exponents, with a sticky
|
||||||
// bottom bit to get rounding correct.
|
// bottom bit to get rounding correct.
|
||||||
const @"align" = @intCast(u32, aExponent - bExponent);
|
const @"align" = @as(u32, @intCast(aExponent - bExponent));
|
||||||
if (@"align" != 0) {
|
if (@"align" != 0) {
|
||||||
if (@"align" < typeWidth) {
|
if (@"align" < typeWidth) {
|
||||||
const sticky = if (bSignificand << @intCast(S, typeWidth - @"align") != 0) @as(Z, 1) else 0;
|
const sticky = if (bSignificand << @as(S, @intCast(typeWidth - @"align")) != 0) @as(Z, 1) else 0;
|
||||||
bSignificand = (bSignificand >> @truncate(S, @"align")) | sticky;
|
bSignificand = (bSignificand >> @as(S, @truncate(@"align"))) | sticky;
|
||||||
} else {
|
} else {
|
||||||
bSignificand = 1; // sticky; b is known to be non-zero.
|
bSignificand = 1; // sticky; b is known to be non-zero.
|
||||||
}
|
}
|
||||||
@ -113,13 +113,13 @@ pub inline fn addf3(comptime T: type, a: T, b: T) T {
|
|||||||
if (subtraction) {
|
if (subtraction) {
|
||||||
aSignificand -= bSignificand;
|
aSignificand -= bSignificand;
|
||||||
// If a == -b, return +zero.
|
// If a == -b, return +zero.
|
||||||
if (aSignificand == 0) return @bitCast(T, @as(Z, 0));
|
if (aSignificand == 0) return @as(T, @bitCast(@as(Z, 0)));
|
||||||
|
|
||||||
// If partial cancellation occured, we need to left-shift the result
|
// If partial cancellation occured, we need to left-shift the result
|
||||||
// and adjust the exponent:
|
// and adjust the exponent:
|
||||||
if (aSignificand < integerBit << 3) {
|
if (aSignificand < integerBit << 3) {
|
||||||
const shift = @intCast(i32, @clz(aSignificand)) - @intCast(i32, @clz(integerBit << 3));
|
const shift = @as(i32, @intCast(@clz(aSignificand))) - @as(i32, @intCast(@clz(integerBit << 3)));
|
||||||
aSignificand <<= @intCast(S, shift);
|
aSignificand <<= @as(S, @intCast(shift));
|
||||||
aExponent -= shift;
|
aExponent -= shift;
|
||||||
}
|
}
|
||||||
} else { // addition
|
} else { // addition
|
||||||
@ -135,13 +135,13 @@ pub inline fn addf3(comptime T: type, a: T, b: T) T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we have overflowed the type, return +/- infinity:
|
// If we have overflowed the type, return +/- infinity:
|
||||||
if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign);
|
if (aExponent >= maxExponent) return @as(T, @bitCast(infRep | resultSign));
|
||||||
|
|
||||||
if (aExponent <= 0) {
|
if (aExponent <= 0) {
|
||||||
// Result is denormal; the exponent and round/sticky bits are zero.
|
// Result is denormal; the exponent and round/sticky bits are zero.
|
||||||
// All we need to do is shift the significand and apply the correct sign.
|
// All we need to do is shift the significand and apply the correct sign.
|
||||||
aSignificand >>= @intCast(S, 4 - aExponent);
|
aSignificand >>= @as(S, @intCast(4 - aExponent));
|
||||||
return @bitCast(T, resultSign | aSignificand);
|
return @as(T, @bitCast(resultSign | aSignificand));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Low three bits are round, guard, and sticky.
|
// Low three bits are round, guard, and sticky.
|
||||||
@ -151,7 +151,7 @@ pub inline fn addf3(comptime T: type, a: T, b: T) T {
|
|||||||
var result = (aSignificand >> 3) & significandMask;
|
var result = (aSignificand >> 3) & significandMask;
|
||||||
|
|
||||||
// Insert the exponent and sign.
|
// Insert the exponent and sign.
|
||||||
result |= @intCast(Z, aExponent) << significandBits;
|
result |= @as(Z, @intCast(aExponent)) << significandBits;
|
||||||
result |= resultSign;
|
result |= resultSign;
|
||||||
|
|
||||||
// Final rounding. The result may overflow to infinity, but that is the
|
// Final rounding. The result may overflow to infinity, but that is the
|
||||||
@ -164,7 +164,7 @@ pub inline fn addf3(comptime T: type, a: T, b: T) T {
|
|||||||
if ((result >> significandBits) != 0) result |= integerBit;
|
if ((result >> significandBits) != 0) result |= integerBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return @bitCast(T, result);
|
return @as(T, @bitCast(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64);
|
const qnan128 = @as(f128, @bitCast(@as(u128, 0x7fff800000000000) << 64));
|
||||||
|
|
||||||
const __addtf3 = @import("addtf3.zig").__addtf3;
|
const __addtf3 = @import("addtf3.zig").__addtf3;
|
||||||
const __addxf3 = @import("addxf3.zig").__addxf3;
|
const __addxf3 = @import("addxf3.zig").__addxf3;
|
||||||
@ -14,9 +14,9 @@ const __subtf3 = @import("subtf3.zig").__subtf3;
|
|||||||
fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
|
fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
|
||||||
const x = __addtf3(a, b);
|
const x = __addtf3(a, b);
|
||||||
|
|
||||||
const rep = @bitCast(u128, x);
|
const rep = @as(u128, @bitCast(x));
|
||||||
const hi = @intCast(u64, rep >> 64);
|
const hi = @as(u64, @intCast(rep >> 64));
|
||||||
const lo = @truncate(u64, rep);
|
const lo = @as(u64, @truncate(rep));
|
||||||
|
|
||||||
if (hi == expected_hi and lo == expected_lo) {
|
if (hi == expected_hi and lo == expected_lo) {
|
||||||
return;
|
return;
|
||||||
@ -37,7 +37,7 @@ test "addtf3" {
|
|||||||
try test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
try test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
||||||
|
|
||||||
// NaN + any = NaN
|
// NaN + any = NaN
|
||||||
try test__addtf3(@bitCast(f128, (@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
try test__addtf3(@as(f128, @bitCast((@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000))), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
||||||
|
|
||||||
// inf + inf = inf
|
// inf + inf = inf
|
||||||
try test__addtf3(math.inf(f128), math.inf(f128), 0x7fff000000000000, 0x0);
|
try test__addtf3(math.inf(f128), math.inf(f128), 0x7fff000000000000, 0x0);
|
||||||
@ -53,9 +53,9 @@ test "addtf3" {
|
|||||||
fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
|
fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
|
||||||
const x = __subtf3(a, b);
|
const x = __subtf3(a, b);
|
||||||
|
|
||||||
const rep = @bitCast(u128, x);
|
const rep = @as(u128, @bitCast(x));
|
||||||
const hi = @intCast(u64, rep >> 64);
|
const hi = @as(u64, @intCast(rep >> 64));
|
||||||
const lo = @truncate(u64, rep);
|
const lo = @as(u64, @truncate(rep));
|
||||||
|
|
||||||
if (hi == expected_hi and lo == expected_lo) {
|
if (hi == expected_hi and lo == expected_lo) {
|
||||||
return;
|
return;
|
||||||
@ -77,7 +77,7 @@ test "subtf3" {
|
|||||||
try test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
try test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
||||||
|
|
||||||
// NaN + any = NaN
|
// NaN + any = NaN
|
||||||
try test__subtf3(@bitCast(f128, (@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
try test__subtf3(@as(f128, @bitCast((@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000))), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
||||||
|
|
||||||
// inf - any = inf
|
// inf - any = inf
|
||||||
try test__subtf3(math.inf(f128), 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0);
|
try test__subtf3(math.inf(f128), 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0);
|
||||||
@ -87,16 +87,16 @@ test "subtf3" {
|
|||||||
try test__subtf3(0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x1.234567829a3bcdef5678ade36734p+5, 0xc0041b8af1915166, 0xa44a7bca780a166c);
|
try test__subtf3(0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x1.234567829a3bcdef5678ade36734p+5, 0xc0041b8af1915166, 0xa44a7bca780a166c);
|
||||||
}
|
}
|
||||||
|
|
||||||
const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1)));
|
const qnan80 = @as(f80, @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1))));
|
||||||
|
|
||||||
fn test__addxf3(a: f80, b: f80, expected: u80) !void {
|
fn test__addxf3(a: f80, b: f80, expected: u80) !void {
|
||||||
const x = __addxf3(a, b);
|
const x = __addxf3(a, b);
|
||||||
const rep = @bitCast(u80, x);
|
const rep = @as(u80, @bitCast(x));
|
||||||
|
|
||||||
if (rep == expected)
|
if (rep == expected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (math.isNan(@bitCast(f80, expected)) and math.isNan(x))
|
if (math.isNan(@as(f80, @bitCast(expected))) and math.isNan(x))
|
||||||
return; // We don't currently test NaN payload propagation
|
return; // We don't currently test NaN payload propagation
|
||||||
|
|
||||||
return error.TestFailed;
|
return error.TestFailed;
|
||||||
@ -104,33 +104,33 @@ fn test__addxf3(a: f80, b: f80, expected: u80) !void {
|
|||||||
|
|
||||||
test "addxf3" {
|
test "addxf3" {
|
||||||
// NaN + any = NaN
|
// NaN + any = NaN
|
||||||
try test__addxf3(qnan80, 0x1.23456789abcdefp+5, @bitCast(u80, qnan80));
|
try test__addxf3(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
|
||||||
try test__addxf3(@bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), 0x1.23456789abcdefp+5, @bitCast(u80, qnan80));
|
try test__addxf3(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
|
||||||
|
|
||||||
// any + NaN = NaN
|
// any + NaN = NaN
|
||||||
try test__addxf3(0x1.23456789abcdefp+5, qnan80, @bitCast(u80, qnan80));
|
try test__addxf3(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80)));
|
||||||
try test__addxf3(0x1.23456789abcdefp+5, @bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), @bitCast(u80, qnan80));
|
try test__addxf3(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80)));
|
||||||
|
|
||||||
// NaN + inf = NaN
|
// NaN + inf = NaN
|
||||||
try test__addxf3(qnan80, math.inf(f80), @bitCast(u80, qnan80));
|
try test__addxf3(qnan80, math.inf(f80), @as(u80, @bitCast(qnan80)));
|
||||||
|
|
||||||
// inf + NaN = NaN
|
// inf + NaN = NaN
|
||||||
try test__addxf3(math.inf(f80), qnan80, @bitCast(u80, qnan80));
|
try test__addxf3(math.inf(f80), qnan80, @as(u80, @bitCast(qnan80)));
|
||||||
|
|
||||||
// inf + inf = inf
|
// inf + inf = inf
|
||||||
try test__addxf3(math.inf(f80), math.inf(f80), @bitCast(u80, math.inf(f80)));
|
try test__addxf3(math.inf(f80), math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
|
||||||
|
|
||||||
// inf + -inf = NaN
|
// inf + -inf = NaN
|
||||||
try test__addxf3(math.inf(f80), -math.inf(f80), @bitCast(u80, qnan80));
|
try test__addxf3(math.inf(f80), -math.inf(f80), @as(u80, @bitCast(qnan80)));
|
||||||
|
|
||||||
// -inf + inf = NaN
|
// -inf + inf = NaN
|
||||||
try test__addxf3(-math.inf(f80), math.inf(f80), @bitCast(u80, qnan80));
|
try test__addxf3(-math.inf(f80), math.inf(f80), @as(u80, @bitCast(qnan80)));
|
||||||
|
|
||||||
// inf + any = inf
|
// inf + any = inf
|
||||||
try test__addxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @bitCast(u80, math.inf(f80)));
|
try test__addxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @as(u80, @bitCast(math.inf(f80))));
|
||||||
|
|
||||||
// any + inf = inf
|
// any + inf = inf
|
||||||
try test__addxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @bitCast(u80, math.inf(f80)));
|
try test__addxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
|
||||||
|
|
||||||
// any + any
|
// any + any
|
||||||
try test__addxf3(0x1.23456789abcdp+5, 0x1.dcba987654321p+5, 0x4005_BFFFFFFFFFFFC400);
|
try test__addxf3(0x1.23456789abcdp+5, 0x1.dcba987654321p+5, 0x4005_BFFFFFFFFFFFC400);
|
||||||
|
|||||||
@ -192,6 +192,6 @@ pub fn __aeabi_ldivmod() callconv(.Naked) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __aeabi_drsub(a: f64, b: f64) callconv(.AAPCS) f64 {
|
pub fn __aeabi_drsub(a: f64, b: f64) callconv(.AAPCS) f64 {
|
||||||
const neg_a = @bitCast(f64, @bitCast(u64, a) ^ (@as(u64, 1) << 63));
|
const neg_a = @as(f64, @bitCast(@as(u64, @bitCast(a)) ^ (@as(u64, 1) << 63)));
|
||||||
return b + neg_a;
|
return b + neg_a;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -232,16 +232,16 @@ fn wideUpdate(comptime T: type, ptr: *T, val: T, update: anytype) T {
|
|||||||
|
|
||||||
const addr = @intFromPtr(ptr);
|
const addr = @intFromPtr(ptr);
|
||||||
const wide_addr = addr & ~(@as(T, smallest_atomic_fetch_exch_size) - 1);
|
const wide_addr = addr & ~(@as(T, smallest_atomic_fetch_exch_size) - 1);
|
||||||
const wide_ptr = @alignCast(smallest_atomic_fetch_exch_size, @ptrFromInt(*WideAtomic, wide_addr));
|
const wide_ptr: *align(smallest_atomic_fetch_exch_size) WideAtomic = @alignCast(@as(*WideAtomic, @ptrFromInt(wide_addr)));
|
||||||
|
|
||||||
const inner_offset = addr & (@as(T, smallest_atomic_fetch_exch_size) - 1);
|
const inner_offset = addr & (@as(T, smallest_atomic_fetch_exch_size) - 1);
|
||||||
const inner_shift = @intCast(std.math.Log2Int(T), inner_offset * 8);
|
const inner_shift = @as(std.math.Log2Int(T), @intCast(inner_offset * 8));
|
||||||
|
|
||||||
const mask = @as(WideAtomic, std.math.maxInt(T)) << inner_shift;
|
const mask = @as(WideAtomic, std.math.maxInt(T)) << inner_shift;
|
||||||
|
|
||||||
var wide_old = @atomicLoad(WideAtomic, wide_ptr, .SeqCst);
|
var wide_old = @atomicLoad(WideAtomic, wide_ptr, .SeqCst);
|
||||||
while (true) {
|
while (true) {
|
||||||
const old = @truncate(T, (wide_old & mask) >> inner_shift);
|
const old = @as(T, @truncate((wide_old & mask) >> inner_shift));
|
||||||
const new = update(val, old);
|
const new = update(val, old);
|
||||||
const wide_new = wide_old & ~mask | (@as(WideAtomic, new) << inner_shift);
|
const wide_new = wide_old & ~mask | (@as(WideAtomic, new) << inner_shift);
|
||||||
if (@cmpxchgWeak(WideAtomic, wide_ptr, wide_old, wide_new, .SeqCst, .SeqCst)) |new_wide_old| {
|
if (@cmpxchgWeak(WideAtomic, wide_ptr, wide_old, wide_new, .SeqCst, .SeqCst)) |new_wide_old| {
|
||||||
|
|||||||
@ -21,9 +21,9 @@ pub fn _alldiv(a: i64, b: i64) callconv(.Stdcall) i64 {
|
|||||||
const an = (a ^ s_a) -% s_a;
|
const an = (a ^ s_a) -% s_a;
|
||||||
const bn = (b ^ s_b) -% s_b;
|
const bn = (b ^ s_b) -% s_b;
|
||||||
|
|
||||||
const r = @bitCast(u64, an) / @bitCast(u64, bn);
|
const r = @as(u64, @bitCast(an)) / @as(u64, @bitCast(bn));
|
||||||
const s = s_a ^ s_b;
|
const s = s_a ^ s_b;
|
||||||
return (@bitCast(i64, r) ^ s) -% s;
|
return (@as(i64, @bitCast(r)) ^ s) -% s;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _aulldiv() callconv(.Naked) void {
|
pub fn _aulldiv() callconv(.Naked) void {
|
||||||
|
|||||||
@ -21,9 +21,9 @@ pub fn _allrem(a: i64, b: i64) callconv(.Stdcall) i64 {
|
|||||||
const an = (a ^ s_a) -% s_a;
|
const an = (a ^ s_a) -% s_a;
|
||||||
const bn = (b ^ s_b) -% s_b;
|
const bn = (b ^ s_b) -% s_b;
|
||||||
|
|
||||||
const r = @bitCast(u64, an) % @bitCast(u64, bn);
|
const r = @as(u64, @bitCast(an)) % @as(u64, @bitCast(bn));
|
||||||
const s = s_a ^ s_b;
|
const s = s_a ^ s_b;
|
||||||
return (@bitCast(i64, r) ^ s) -% s;
|
return (@as(i64, @bitCast(r)) ^ s) -% s;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _aullrem() callconv(.Naked) void {
|
pub fn _aullrem() callconv(.Naked) void {
|
||||||
|
|||||||
@ -27,12 +27,12 @@ comptime {
|
|||||||
|
|
||||||
pub fn __ceilh(x: f16) callconv(.C) f16 {
|
pub fn __ceilh(x: f16) callconv(.C) f16 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f16, ceilf(x));
|
return @as(f16, @floatCast(ceilf(x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ceilf(x: f32) callconv(.C) f32 {
|
pub fn ceilf(x: f32) callconv(.C) f32 {
|
||||||
var u = @bitCast(u32, x);
|
var u = @as(u32, @bitCast(x));
|
||||||
var e = @intCast(i32, (u >> 23) & 0xFF) - 0x7F;
|
var e = @as(i32, @intCast((u >> 23) & 0xFF)) - 0x7F;
|
||||||
var m: u32 = undefined;
|
var m: u32 = undefined;
|
||||||
|
|
||||||
// TODO: Shouldn't need this explicit check.
|
// TODO: Shouldn't need this explicit check.
|
||||||
@ -43,7 +43,7 @@ pub fn ceilf(x: f32) callconv(.C) f32 {
|
|||||||
if (e >= 23) {
|
if (e >= 23) {
|
||||||
return x;
|
return x;
|
||||||
} else if (e >= 0) {
|
} else if (e >= 0) {
|
||||||
m = @as(u32, 0x007FFFFF) >> @intCast(u5, e);
|
m = @as(u32, 0x007FFFFF) >> @as(u5, @intCast(e));
|
||||||
if (u & m == 0) {
|
if (u & m == 0) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ pub fn ceilf(x: f32) callconv(.C) f32 {
|
|||||||
u += m;
|
u += m;
|
||||||
}
|
}
|
||||||
u &= ~m;
|
u &= ~m;
|
||||||
return @bitCast(f32, u);
|
return @as(f32, @bitCast(u));
|
||||||
} else {
|
} else {
|
||||||
math.doNotOptimizeAway(x + 0x1.0p120);
|
math.doNotOptimizeAway(x + 0x1.0p120);
|
||||||
if (u >> 31 != 0) {
|
if (u >> 31 != 0) {
|
||||||
@ -66,7 +66,7 @@ pub fn ceilf(x: f32) callconv(.C) f32 {
|
|||||||
pub fn ceil(x: f64) callconv(.C) f64 {
|
pub fn ceil(x: f64) callconv(.C) f64 {
|
||||||
const f64_toint = 1.0 / math.floatEps(f64);
|
const f64_toint = 1.0 / math.floatEps(f64);
|
||||||
|
|
||||||
const u = @bitCast(u64, x);
|
const u = @as(u64, @bitCast(x));
|
||||||
const e = (u >> 52) & 0x7FF;
|
const e = (u >> 52) & 0x7FF;
|
||||||
var y: f64 = undefined;
|
var y: f64 = undefined;
|
||||||
|
|
||||||
@ -96,13 +96,13 @@ pub fn ceil(x: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
pub fn __ceilx(x: f80) callconv(.C) f80 {
|
pub fn __ceilx(x: f80) callconv(.C) f80 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f80, ceilq(x));
|
return @as(f80, @floatCast(ceilq(x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ceilq(x: f128) callconv(.C) f128 {
|
pub fn ceilq(x: f128) callconv(.C) f128 {
|
||||||
const f128_toint = 1.0 / math.floatEps(f128);
|
const f128_toint = 1.0 / math.floatEps(f128);
|
||||||
|
|
||||||
const u = @bitCast(u128, x);
|
const u = @as(u128, @bitCast(x));
|
||||||
const e = (u >> 112) & 0x7FFF;
|
const e = (u >> 112) & 0x7FFF;
|
||||||
var y: f128 = undefined;
|
var y: f128 = undefined;
|
||||||
|
|
||||||
|
|||||||
@ -102,7 +102,7 @@ fn clear_cache(start: usize, end: usize) callconv(.C) void {
|
|||||||
// If CTR_EL0.IDC is set, data cache cleaning to the point of unification
|
// If CTR_EL0.IDC is set, data cache cleaning to the point of unification
|
||||||
// is not required for instruction to data coherence.
|
// is not required for instruction to data coherence.
|
||||||
if (((ctr_el0 >> 28) & 0x1) == 0x0) {
|
if (((ctr_el0 >> 28) & 0x1) == 0x0) {
|
||||||
const dcache_line_size: usize = @as(usize, 4) << @intCast(u6, (ctr_el0 >> 16) & 15);
|
const dcache_line_size: usize = @as(usize, 4) << @as(u6, @intCast((ctr_el0 >> 16) & 15));
|
||||||
addr = start & ~(dcache_line_size - 1);
|
addr = start & ~(dcache_line_size - 1);
|
||||||
while (addr < end) : (addr += dcache_line_size) {
|
while (addr < end) : (addr += dcache_line_size) {
|
||||||
asm volatile ("dc cvau, %[addr]"
|
asm volatile ("dc cvau, %[addr]"
|
||||||
@ -115,7 +115,7 @@ fn clear_cache(start: usize, end: usize) callconv(.C) void {
|
|||||||
// If CTR_EL0.DIC is set, instruction cache invalidation to the point of
|
// If CTR_EL0.DIC is set, instruction cache invalidation to the point of
|
||||||
// unification is not required for instruction to data coherence.
|
// unification is not required for instruction to data coherence.
|
||||||
if (((ctr_el0 >> 29) & 0x1) == 0x0) {
|
if (((ctr_el0 >> 29) & 0x1) == 0x0) {
|
||||||
const icache_line_size: usize = @as(usize, 4) << @intCast(u6, (ctr_el0 >> 0) & 15);
|
const icache_line_size: usize = @as(usize, 4) << @as(u6, @intCast((ctr_el0 >> 0) & 15));
|
||||||
addr = start & ~(icache_line_size - 1);
|
addr = start & ~(icache_line_size - 1);
|
||||||
while (addr < end) : (addr += icache_line_size) {
|
while (addr < end) : (addr += icache_line_size) {
|
||||||
asm volatile ("ic ivau, %[addr]"
|
asm volatile ("ic ivau, %[addr]"
|
||||||
|
|||||||
@ -2,7 +2,7 @@ const clz = @import("count0bits.zig");
|
|||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
fn test__clzdi2(a: u64, expected: i64) !void {
|
fn test__clzdi2(a: u64, expected: i64) !void {
|
||||||
var x = @bitCast(i64, a);
|
var x = @as(i64, @bitCast(a));
|
||||||
var result = clz.__clzdi2(x);
|
var result = clz.__clzdi2(x);
|
||||||
try testing.expectEqual(expected, result);
|
try testing.expectEqual(expected, result);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,8 @@ const testing = @import("std").testing;
|
|||||||
|
|
||||||
fn test__clzsi2(a: u32, expected: i32) !void {
|
fn test__clzsi2(a: u32, expected: i32) !void {
|
||||||
const nakedClzsi2 = clz.__clzsi2;
|
const nakedClzsi2 = clz.__clzsi2;
|
||||||
const actualClzsi2 = @ptrCast(*const fn (a: i32) callconv(.C) i32, &nakedClzsi2);
|
const actualClzsi2 = @as(*const fn (a: i32) callconv(.C) i32, @ptrCast(&nakedClzsi2));
|
||||||
const x = @bitCast(i32, a);
|
const x = @as(i32, @bitCast(a));
|
||||||
const result = actualClzsi2(x);
|
const result = actualClzsi2(x);
|
||||||
try testing.expectEqual(expected, result);
|
try testing.expectEqual(expected, result);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ const clz = @import("count0bits.zig");
|
|||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
fn test__clzti2(a: u128, expected: i64) !void {
|
fn test__clzti2(a: u128, expected: i64) !void {
|
||||||
var x = @bitCast(i128, a);
|
var x = @as(i128, @bitCast(a));
|
||||||
var result = clz.__clzti2(x);
|
var result = clz.__clzti2(x);
|
||||||
try testing.expectEqual(expected, result);
|
try testing.expectEqual(expected, result);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,30 +75,30 @@ fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.C) i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn _Qp_feq(a: *const f128, b: *const f128) callconv(.C) bool {
|
fn _Qp_feq(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||||
return @enumFromInt(SparcFCMP, _Qp_cmp(a, b)) == .Equal;
|
return @as(SparcFCMP, @enumFromInt(_Qp_cmp(a, b))) == .Equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _Qp_fne(a: *const f128, b: *const f128) callconv(.C) bool {
|
fn _Qp_fne(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||||
return @enumFromInt(SparcFCMP, _Qp_cmp(a, b)) != .Equal;
|
return @as(SparcFCMP, @enumFromInt(_Qp_cmp(a, b))) != .Equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _Qp_flt(a: *const f128, b: *const f128) callconv(.C) bool {
|
fn _Qp_flt(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||||
return @enumFromInt(SparcFCMP, _Qp_cmp(a, b)) == .Less;
|
return @as(SparcFCMP, @enumFromInt(_Qp_cmp(a, b))) == .Less;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.C) bool {
|
fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||||
return @enumFromInt(SparcFCMP, _Qp_cmp(a, b)) == .Greater;
|
return @as(SparcFCMP, @enumFromInt(_Qp_cmp(a, b))) == .Greater;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _Qp_fge(a: *const f128, b: *const f128) callconv(.C) bool {
|
fn _Qp_fge(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||||
return switch (@enumFromInt(SparcFCMP, _Qp_cmp(a, b))) {
|
return switch (@as(SparcFCMP, @enumFromInt(_Qp_cmp(a, b)))) {
|
||||||
.Equal, .Greater => true,
|
.Equal, .Greater => true,
|
||||||
.Less, .Unordered => false,
|
.Less, .Unordered => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _Qp_fle(a: *const f128, b: *const f128) callconv(.C) bool {
|
fn _Qp_fle(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||||
return switch (@enumFromInt(SparcFCMP, _Qp_cmp(a, b))) {
|
return switch (@as(SparcFCMP, @enumFromInt(_Qp_cmp(a, b)))) {
|
||||||
.Equal, .Less => true,
|
.Equal, .Less => true,
|
||||||
.Greater, .Unordered => false,
|
.Greater, .Unordered => false,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -102,22 +102,22 @@ pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
|
|||||||
u16 => {
|
u16 => {
|
||||||
// 16x16 --> 32 bit multiply
|
// 16x16 --> 32 bit multiply
|
||||||
const product = @as(u32, a) * @as(u32, b);
|
const product = @as(u32, a) * @as(u32, b);
|
||||||
hi.* = @intCast(u16, product >> 16);
|
hi.* = @as(u16, @intCast(product >> 16));
|
||||||
lo.* = @truncate(u16, product);
|
lo.* = @as(u16, @truncate(product));
|
||||||
},
|
},
|
||||||
u32 => {
|
u32 => {
|
||||||
// 32x32 --> 64 bit multiply
|
// 32x32 --> 64 bit multiply
|
||||||
const product = @as(u64, a) * @as(u64, b);
|
const product = @as(u64, a) * @as(u64, b);
|
||||||
hi.* = @truncate(u32, product >> 32);
|
hi.* = @as(u32, @truncate(product >> 32));
|
||||||
lo.* = @truncate(u32, product);
|
lo.* = @as(u32, @truncate(product));
|
||||||
},
|
},
|
||||||
u64 => {
|
u64 => {
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn loWord(x: u64) u64 {
|
fn loWord(x: u64) u64 {
|
||||||
return @truncate(u32, x);
|
return @as(u32, @truncate(x));
|
||||||
}
|
}
|
||||||
fn hiWord(x: u64) u64 {
|
fn hiWord(x: u64) u64 {
|
||||||
return @truncate(u32, x >> 32);
|
return @as(u32, @truncate(x >> 32));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 64x64 -> 128 wide multiply for platforms that don't have such an operation;
|
// 64x64 -> 128 wide multiply for platforms that don't have such an operation;
|
||||||
@ -141,16 +141,16 @@ pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
|
|||||||
const Word_FullMask = @as(u64, 0xffffffffffffffff);
|
const Word_FullMask = @as(u64, 0xffffffffffffffff);
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn Word_1(x: u128) u64 {
|
fn Word_1(x: u128) u64 {
|
||||||
return @truncate(u32, x >> 96);
|
return @as(u32, @truncate(x >> 96));
|
||||||
}
|
}
|
||||||
fn Word_2(x: u128) u64 {
|
fn Word_2(x: u128) u64 {
|
||||||
return @truncate(u32, x >> 64);
|
return @as(u32, @truncate(x >> 64));
|
||||||
}
|
}
|
||||||
fn Word_3(x: u128) u64 {
|
fn Word_3(x: u128) u64 {
|
||||||
return @truncate(u32, x >> 32);
|
return @as(u32, @truncate(x >> 32));
|
||||||
}
|
}
|
||||||
fn Word_4(x: u128) u64 {
|
fn Word_4(x: u128) u64 {
|
||||||
return @truncate(u32, x);
|
return @as(u32, @truncate(x));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 128x128 -> 256 wide multiply for platforms that don't have such an operation;
|
// 128x128 -> 256 wide multiply for platforms that don't have such an operation;
|
||||||
@ -216,7 +216,7 @@ pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeIn
|
|||||||
const integerBit = @as(Z, 1) << std.math.floatFractionalBits(T);
|
const integerBit = @as(Z, 1) << std.math.floatFractionalBits(T);
|
||||||
|
|
||||||
const shift = @clz(significand.*) - @clz(integerBit);
|
const shift = @clz(significand.*) - @clz(integerBit);
|
||||||
significand.* <<= @intCast(std.math.Log2Int(Z), shift);
|
significand.* <<= @as(std.math.Log2Int(Z), @intCast(shift));
|
||||||
return @as(i32, 1) - shift;
|
return @as(i32, 1) - shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,8 +228,8 @@ pub inline fn fneg(a: anytype) @TypeOf(a) {
|
|||||||
.bits = bits,
|
.bits = bits,
|
||||||
} });
|
} });
|
||||||
const sign_bit_mask = @as(U, 1) << (bits - 1);
|
const sign_bit_mask = @as(U, 1) << (bits - 1);
|
||||||
const negated = @bitCast(U, a) ^ sign_bit_mask;
|
const negated = @as(U, @bitCast(a)) ^ sign_bit_mask;
|
||||||
return @bitCast(F, negated);
|
return @as(F, @bitCast(negated));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allows to access underlying bits as two equally sized lower and higher
|
/// Allows to access underlying bits as two equally sized lower and higher
|
||||||
|
|||||||
@ -26,12 +26,12 @@ pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT {
|
|||||||
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
||||||
const absMask = signBit - 1;
|
const absMask = signBit - 1;
|
||||||
const infT = comptime std.math.inf(T);
|
const infT = comptime std.math.inf(T);
|
||||||
const infRep = @bitCast(rep_t, infT);
|
const infRep = @as(rep_t, @bitCast(infT));
|
||||||
|
|
||||||
const aInt = @bitCast(srep_t, a);
|
const aInt = @as(srep_t, @bitCast(a));
|
||||||
const bInt = @bitCast(srep_t, b);
|
const bInt = @as(srep_t, @bitCast(b));
|
||||||
const aAbs = @bitCast(rep_t, aInt) & absMask;
|
const aAbs = @as(rep_t, @bitCast(aInt)) & absMask;
|
||||||
const bAbs = @bitCast(rep_t, bInt) & absMask;
|
const bAbs = @as(rep_t, @bitCast(bInt)) & absMask;
|
||||||
|
|
||||||
// If either a or b is NaN, they are unordered.
|
// If either a or b is NaN, they are unordered.
|
||||||
if (aAbs > infRep or bAbs > infRep) return RT.Unordered;
|
if (aAbs > infRep or bAbs > infRep) return RT.Unordered;
|
||||||
@ -81,7 +81,7 @@ pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT {
|
|||||||
return .Equal;
|
return .Equal;
|
||||||
} else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) {
|
} else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) {
|
||||||
// signs are different
|
// signs are different
|
||||||
if (@bitCast(i16, a_rep.exp) < @bitCast(i16, b_rep.exp)) {
|
if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) {
|
||||||
return .Less;
|
return .Less;
|
||||||
} else {
|
} else {
|
||||||
return .Greater;
|
return .Greater;
|
||||||
@ -104,10 +104,10 @@ pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 {
|
|||||||
const exponentBits = std.math.floatExponentBits(T);
|
const exponentBits = std.math.floatExponentBits(T);
|
||||||
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
||||||
const absMask = signBit - 1;
|
const absMask = signBit - 1;
|
||||||
const infRep = @bitCast(rep_t, std.math.inf(T));
|
const infRep = @as(rep_t, @bitCast(std.math.inf(T)));
|
||||||
|
|
||||||
const aAbs: rep_t = @bitCast(rep_t, a) & absMask;
|
const aAbs: rep_t = @as(rep_t, @bitCast(a)) & absMask;
|
||||||
const bAbs: rep_t = @bitCast(rep_t, b) & absMask;
|
const bAbs: rep_t = @as(rep_t, @bitCast(b)) & absMask;
|
||||||
|
|
||||||
return @intFromBool(aAbs > infRep or bAbs > infRep);
|
return @intFromBool(aAbs > infRep or bAbs > infRep);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ comptime {
|
|||||||
|
|
||||||
pub fn __cosh(a: f16) callconv(.C) f16 {
|
pub fn __cosh(a: f16) callconv(.C) f16 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f16, cosf(a));
|
return @as(f16, @floatCast(cosf(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cosf(x: f32) callconv(.C) f32 {
|
pub fn cosf(x: f32) callconv(.C) f32 {
|
||||||
@ -35,7 +35,7 @@ pub fn cosf(x: f32) callconv(.C) f32 {
|
|||||||
const c3pio2: f64 = 3.0 * math.pi / 2.0; // 0x4012D97C, 0x7F3321D2
|
const c3pio2: f64 = 3.0 * math.pi / 2.0; // 0x4012D97C, 0x7F3321D2
|
||||||
const c4pio2: f64 = 4.0 * math.pi / 2.0; // 0x401921FB, 0x54442D18
|
const c4pio2: f64 = 4.0 * math.pi / 2.0; // 0x401921FB, 0x54442D18
|
||||||
|
|
||||||
var ix = @bitCast(u32, x);
|
var ix = @as(u32, @bitCast(x));
|
||||||
const sign = ix >> 31 != 0;
|
const sign = ix >> 31 != 0;
|
||||||
ix &= 0x7fffffff;
|
ix &= 0x7fffffff;
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ pub fn cosf(x: f32) callconv(.C) f32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn cos(x: f64) callconv(.C) f64 {
|
pub fn cos(x: f64) callconv(.C) f64 {
|
||||||
var ix = @bitCast(u64, x) >> 32;
|
var ix = @as(u64, @bitCast(x)) >> 32;
|
||||||
ix &= 0x7fffffff;
|
ix &= 0x7fffffff;
|
||||||
|
|
||||||
// |x| ~< pi/4
|
// |x| ~< pi/4
|
||||||
@ -116,12 +116,12 @@ pub fn cos(x: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
pub fn __cosx(a: f80) callconv(.C) f80 {
|
pub fn __cosx(a: f80) callconv(.C) f80 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f80, cosq(a));
|
return @as(f80, @floatCast(cosq(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cosq(a: f128) callconv(.C) f128 {
|
pub fn cosq(a: f128) callconv(.C) f128 {
|
||||||
// TODO: more correct implementation
|
// TODO: more correct implementation
|
||||||
return cos(@floatCast(f64, a));
|
return cos(@as(f64, @floatCast(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cosl(x: c_longdouble) callconv(.C) c_longdouble {
|
pub fn cosl(x: c_longdouble) callconv(.C) c_longdouble {
|
||||||
|
|||||||
@ -32,9 +32,9 @@ comptime {
|
|||||||
|
|
||||||
inline fn clzXi2(comptime T: type, a: T) i32 {
|
inline fn clzXi2(comptime T: type, a: T) i32 {
|
||||||
var x = switch (@bitSizeOf(T)) {
|
var x = switch (@bitSizeOf(T)) {
|
||||||
32 => @bitCast(u32, a),
|
32 => @as(u32, @bitCast(a)),
|
||||||
64 => @bitCast(u64, a),
|
64 => @as(u64, @bitCast(a)),
|
||||||
128 => @bitCast(u128, a),
|
128 => @as(u128, @bitCast(a)),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
var n: T = @bitSizeOf(T);
|
var n: T = @bitSizeOf(T);
|
||||||
@ -49,7 +49,7 @@ inline fn clzXi2(comptime T: type, a: T) i32 {
|
|||||||
x = y;
|
x = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return @intCast(i32, n - @bitCast(T, x));
|
return @as(i32, @intCast(n - @as(T, @bitCast(x))));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __clzsi2_thumb1() callconv(.Naked) void {
|
fn __clzsi2_thumb1() callconv(.Naked) void {
|
||||||
@ -169,9 +169,9 @@ pub fn __clzti2(a: i128) callconv(.C) i32 {
|
|||||||
|
|
||||||
inline fn ctzXi2(comptime T: type, a: T) i32 {
|
inline fn ctzXi2(comptime T: type, a: T) i32 {
|
||||||
var x = switch (@bitSizeOf(T)) {
|
var x = switch (@bitSizeOf(T)) {
|
||||||
32 => @bitCast(u32, a),
|
32 => @as(u32, @bitCast(a)),
|
||||||
64 => @bitCast(u64, a),
|
64 => @as(u64, @bitCast(a)),
|
||||||
128 => @bitCast(u128, a),
|
128 => @as(u128, @bitCast(a)),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
var n: T = 1;
|
var n: T = 1;
|
||||||
@ -187,7 +187,7 @@ inline fn ctzXi2(comptime T: type, a: T) i32 {
|
|||||||
x = x >> shift;
|
x = x >> shift;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return @intCast(i32, n - @bitCast(T, (x & 1)));
|
return @as(i32, @intCast(n - @as(T, @bitCast((x & 1)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn __ctzsi2(a: i32) callconv(.C) i32 {
|
pub fn __ctzsi2(a: i32) callconv(.C) i32 {
|
||||||
@ -204,9 +204,9 @@ pub fn __ctzti2(a: i128) callconv(.C) i32 {
|
|||||||
|
|
||||||
inline fn ffsXi2(comptime T: type, a: T) i32 {
|
inline fn ffsXi2(comptime T: type, a: T) i32 {
|
||||||
var x = switch (@bitSizeOf(T)) {
|
var x = switch (@bitSizeOf(T)) {
|
||||||
32 => @bitCast(u32, a),
|
32 => @as(u32, @bitCast(a)),
|
||||||
64 => @bitCast(u64, a),
|
64 => @as(u64, @bitCast(a)),
|
||||||
128 => @bitCast(u128, a),
|
128 => @as(u128, @bitCast(a)),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
var n: T = 1;
|
var n: T = 1;
|
||||||
@ -224,7 +224,7 @@ inline fn ffsXi2(comptime T: type, a: T) i32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// return ctz + 1
|
// return ctz + 1
|
||||||
return @intCast(i32, n - @bitCast(T, (x & 1))) + @as(i32, 1);
|
return @as(i32, @intCast(n - @as(T, @bitCast((x & 1))))) + @as(i32, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn __ffssi2(a: i32) callconv(.C) i32 {
|
pub fn __ffssi2(a: i32) callconv(.C) i32 {
|
||||||
|
|||||||
@ -2,7 +2,7 @@ const ctz = @import("count0bits.zig");
|
|||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
fn test__ctzdi2(a: u64, expected: i32) !void {
|
fn test__ctzdi2(a: u64, expected: i32) !void {
|
||||||
var x = @bitCast(i64, a);
|
var x = @as(i64, @bitCast(a));
|
||||||
var result = ctz.__ctzdi2(x);
|
var result = ctz.__ctzdi2(x);
|
||||||
try testing.expectEqual(expected, result);
|
try testing.expectEqual(expected, result);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ const ctz = @import("count0bits.zig");
|
|||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
fn test__ctzsi2(a: u32, expected: i32) !void {
|
fn test__ctzsi2(a: u32, expected: i32) !void {
|
||||||
var x = @bitCast(i32, a);
|
var x = @as(i32, @bitCast(a));
|
||||||
var result = ctz.__ctzsi2(x);
|
var result = ctz.__ctzsi2(x);
|
||||||
try testing.expectEqual(expected, result);
|
try testing.expectEqual(expected, result);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ const ctz = @import("count0bits.zig");
|
|||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
fn test__ctzti2(a: u128, expected: i32) !void {
|
fn test__ctzti2(a: u128, expected: i32) !void {
|
||||||
var x = @bitCast(i128, a);
|
var x = @as(i128, @bitCast(a));
|
||||||
var result = ctz.__ctzti2(x);
|
var result = ctz.__ctzti2(x);
|
||||||
try testing.expectEqual(expected, result);
|
try testing.expectEqual(expected, result);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,52 +47,52 @@ inline fn div(a: f64, b: f64) f64 {
|
|||||||
const absMask = signBit - 1;
|
const absMask = signBit - 1;
|
||||||
const exponentMask = absMask ^ significandMask;
|
const exponentMask = absMask ^ significandMask;
|
||||||
const qnanRep = exponentMask | quietBit;
|
const qnanRep = exponentMask | quietBit;
|
||||||
const infRep = @bitCast(Z, std.math.inf(f64));
|
const infRep = @as(Z, @bitCast(std.math.inf(f64)));
|
||||||
|
|
||||||
const aExponent = @truncate(u32, (@bitCast(Z, a) >> significandBits) & maxExponent);
|
const aExponent = @as(u32, @truncate((@as(Z, @bitCast(a)) >> significandBits) & maxExponent));
|
||||||
const bExponent = @truncate(u32, (@bitCast(Z, b) >> significandBits) & maxExponent);
|
const bExponent = @as(u32, @truncate((@as(Z, @bitCast(b)) >> significandBits) & maxExponent));
|
||||||
const quotientSign: Z = (@bitCast(Z, a) ^ @bitCast(Z, b)) & signBit;
|
const quotientSign: Z = (@as(Z, @bitCast(a)) ^ @as(Z, @bitCast(b))) & signBit;
|
||||||
|
|
||||||
var aSignificand: Z = @bitCast(Z, a) & significandMask;
|
var aSignificand: Z = @as(Z, @bitCast(a)) & significandMask;
|
||||||
var bSignificand: Z = @bitCast(Z, b) & significandMask;
|
var bSignificand: Z = @as(Z, @bitCast(b)) & significandMask;
|
||||||
var scale: i32 = 0;
|
var scale: i32 = 0;
|
||||||
|
|
||||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
// Detect if a or b is zero, denormal, infinity, or NaN.
|
||||||
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
||||||
const aAbs: Z = @bitCast(Z, a) & absMask;
|
const aAbs: Z = @as(Z, @bitCast(a)) & absMask;
|
||||||
const bAbs: Z = @bitCast(Z, b) & absMask;
|
const bAbs: Z = @as(Z, @bitCast(b)) & absMask;
|
||||||
|
|
||||||
// NaN / anything = qNaN
|
// NaN / anything = qNaN
|
||||||
if (aAbs > infRep) return @bitCast(f64, @bitCast(Z, a) | quietBit);
|
if (aAbs > infRep) return @as(f64, @bitCast(@as(Z, @bitCast(a)) | quietBit));
|
||||||
// anything / NaN = qNaN
|
// anything / NaN = qNaN
|
||||||
if (bAbs > infRep) return @bitCast(f64, @bitCast(Z, b) | quietBit);
|
if (bAbs > infRep) return @as(f64, @bitCast(@as(Z, @bitCast(b)) | quietBit));
|
||||||
|
|
||||||
if (aAbs == infRep) {
|
if (aAbs == infRep) {
|
||||||
// infinity / infinity = NaN
|
// infinity / infinity = NaN
|
||||||
if (bAbs == infRep) {
|
if (bAbs == infRep) {
|
||||||
return @bitCast(f64, qnanRep);
|
return @as(f64, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
// infinity / anything else = +/- infinity
|
// infinity / anything else = +/- infinity
|
||||||
else {
|
else {
|
||||||
return @bitCast(f64, aAbs | quotientSign);
|
return @as(f64, @bitCast(aAbs | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// anything else / infinity = +/- 0
|
// anything else / infinity = +/- 0
|
||||||
if (bAbs == infRep) return @bitCast(f64, quotientSign);
|
if (bAbs == infRep) return @as(f64, @bitCast(quotientSign));
|
||||||
|
|
||||||
if (aAbs == 0) {
|
if (aAbs == 0) {
|
||||||
// zero / zero = NaN
|
// zero / zero = NaN
|
||||||
if (bAbs == 0) {
|
if (bAbs == 0) {
|
||||||
return @bitCast(f64, qnanRep);
|
return @as(f64, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
// zero / anything else = +/- zero
|
// zero / anything else = +/- zero
|
||||||
else {
|
else {
|
||||||
return @bitCast(f64, quotientSign);
|
return @as(f64, @bitCast(quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// anything else / zero = +/- infinity
|
// anything else / zero = +/- infinity
|
||||||
if (bAbs == 0) return @bitCast(f64, infRep | quotientSign);
|
if (bAbs == 0) return @as(f64, @bitCast(infRep | quotientSign));
|
||||||
|
|
||||||
// one or both of a or b is denormal, the other (if applicable) is a
|
// one or both of a or b is denormal, the other (if applicable) is a
|
||||||
// normal number. Renormalize one or both of a and b, and set scale to
|
// normal number. Renormalize one or both of a and b, and set scale to
|
||||||
@ -106,13 +106,13 @@ inline fn div(a: f64, b: f64) f64 {
|
|||||||
// won't hurt anything.)
|
// won't hurt anything.)
|
||||||
aSignificand |= implicitBit;
|
aSignificand |= implicitBit;
|
||||||
bSignificand |= implicitBit;
|
bSignificand |= implicitBit;
|
||||||
var quotientExponent: i32 = @bitCast(i32, aExponent -% bExponent) +% scale;
|
var quotientExponent: i32 = @as(i32, @bitCast(aExponent -% bExponent)) +% scale;
|
||||||
|
|
||||||
// Align the significand of b as a Q31 fixed-point number in the range
|
// Align the significand of b as a Q31 fixed-point number in the range
|
||||||
// [1, 2.0) and get a Q32 approximate reciprocal using a small minimax
|
// [1, 2.0) and get a Q32 approximate reciprocal using a small minimax
|
||||||
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
||||||
// is accurate to about 3.5 binary digits.
|
// is accurate to about 3.5 binary digits.
|
||||||
const q31b: u32 = @truncate(u32, bSignificand >> 21);
|
const q31b: u32 = @as(u32, @truncate(bSignificand >> 21));
|
||||||
var recip32 = @as(u32, 0x7504f333) -% q31b;
|
var recip32 = @as(u32, 0x7504f333) -% q31b;
|
||||||
|
|
||||||
// Now refine the reciprocal estimate using a Newton-Raphson iteration:
|
// Now refine the reciprocal estimate using a Newton-Raphson iteration:
|
||||||
@ -123,12 +123,12 @@ inline fn div(a: f64, b: f64) f64 {
|
|||||||
// with each iteration, so after three iterations, we have about 28 binary
|
// with each iteration, so after three iterations, we have about 28 binary
|
||||||
// digits of accuracy.
|
// digits of accuracy.
|
||||||
var correction32: u32 = undefined;
|
var correction32: u32 = undefined;
|
||||||
correction32 = @truncate(u32, ~(@as(u64, recip32) *% q31b >> 32) +% 1);
|
correction32 = @as(u32, @truncate(~(@as(u64, recip32) *% q31b >> 32) +% 1));
|
||||||
recip32 = @truncate(u32, @as(u64, recip32) *% correction32 >> 31);
|
recip32 = @as(u32, @truncate(@as(u64, recip32) *% correction32 >> 31));
|
||||||
correction32 = @truncate(u32, ~(@as(u64, recip32) *% q31b >> 32) +% 1);
|
correction32 = @as(u32, @truncate(~(@as(u64, recip32) *% q31b >> 32) +% 1));
|
||||||
recip32 = @truncate(u32, @as(u64, recip32) *% correction32 >> 31);
|
recip32 = @as(u32, @truncate(@as(u64, recip32) *% correction32 >> 31));
|
||||||
correction32 = @truncate(u32, ~(@as(u64, recip32) *% q31b >> 32) +% 1);
|
correction32 = @as(u32, @truncate(~(@as(u64, recip32) *% q31b >> 32) +% 1));
|
||||||
recip32 = @truncate(u32, @as(u64, recip32) *% correction32 >> 31);
|
recip32 = @as(u32, @truncate(@as(u64, recip32) *% correction32 >> 31));
|
||||||
|
|
||||||
// recip32 might have overflowed to exactly zero in the preceding
|
// recip32 might have overflowed to exactly zero in the preceding
|
||||||
// computation if the high word of b is exactly 1.0. This would sabotage
|
// computation if the high word of b is exactly 1.0. This would sabotage
|
||||||
@ -138,12 +138,12 @@ inline fn div(a: f64, b: f64) f64 {
|
|||||||
|
|
||||||
// We need to perform one more iteration to get us to 56 binary digits;
|
// We need to perform one more iteration to get us to 56 binary digits;
|
||||||
// The last iteration needs to happen with extra precision.
|
// The last iteration needs to happen with extra precision.
|
||||||
const q63blo: u32 = @truncate(u32, bSignificand << 11);
|
const q63blo: u32 = @as(u32, @truncate(bSignificand << 11));
|
||||||
var correction: u64 = undefined;
|
var correction: u64 = undefined;
|
||||||
var reciprocal: u64 = undefined;
|
var reciprocal: u64 = undefined;
|
||||||
correction = ~(@as(u64, recip32) *% q31b +% (@as(u64, recip32) *% q63blo >> 32)) +% 1;
|
correction = ~(@as(u64, recip32) *% q31b +% (@as(u64, recip32) *% q63blo >> 32)) +% 1;
|
||||||
const cHi = @truncate(u32, correction >> 32);
|
const cHi = @as(u32, @truncate(correction >> 32));
|
||||||
const cLo = @truncate(u32, correction);
|
const cLo = @as(u32, @truncate(correction));
|
||||||
reciprocal = @as(u64, recip32) *% cHi +% (@as(u64, recip32) *% cLo >> 32);
|
reciprocal = @as(u64, recip32) *% cHi +% (@as(u64, recip32) *% cLo >> 32);
|
||||||
|
|
||||||
// We already adjusted the 32-bit estimate, now we need to adjust the final
|
// We already adjusted the 32-bit estimate, now we need to adjust the final
|
||||||
@ -195,7 +195,7 @@ inline fn div(a: f64, b: f64) f64 {
|
|||||||
|
|
||||||
if (writtenExponent >= maxExponent) {
|
if (writtenExponent >= maxExponent) {
|
||||||
// If we have overflowed the exponent, return infinity.
|
// If we have overflowed the exponent, return infinity.
|
||||||
return @bitCast(f64, infRep | quotientSign);
|
return @as(f64, @bitCast(infRep | quotientSign));
|
||||||
} else if (writtenExponent < 1) {
|
} else if (writtenExponent < 1) {
|
||||||
if (writtenExponent == 0) {
|
if (writtenExponent == 0) {
|
||||||
// Check whether the rounded result is normal.
|
// Check whether the rounded result is normal.
|
||||||
@ -206,22 +206,22 @@ inline fn div(a: f64, b: f64) f64 {
|
|||||||
absResult += round;
|
absResult += round;
|
||||||
if ((absResult & ~significandMask) != 0) {
|
if ((absResult & ~significandMask) != 0) {
|
||||||
// The rounded result is normal; return it.
|
// The rounded result is normal; return it.
|
||||||
return @bitCast(f64, absResult | quotientSign);
|
return @as(f64, @bitCast(absResult | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Flush denormals to zero. In the future, it would be nice to add
|
// Flush denormals to zero. In the future, it would be nice to add
|
||||||
// code to round them correctly.
|
// code to round them correctly.
|
||||||
return @bitCast(f64, quotientSign);
|
return @as(f64, @bitCast(quotientSign));
|
||||||
} else {
|
} else {
|
||||||
const round = @intFromBool((residual << 1) > bSignificand);
|
const round = @intFromBool((residual << 1) > bSignificand);
|
||||||
// Clear the implicit bit
|
// Clear the implicit bit
|
||||||
var absResult = quotient & significandMask;
|
var absResult = quotient & significandMask;
|
||||||
// Insert the exponent
|
// Insert the exponent
|
||||||
absResult |= @bitCast(Z, @as(SignedZ, writtenExponent)) << significandBits;
|
absResult |= @as(Z, @bitCast(@as(SignedZ, writtenExponent))) << significandBits;
|
||||||
// Round
|
// Round
|
||||||
absResult +%= round;
|
absResult +%= round;
|
||||||
// Insert the sign and return
|
// Insert the sign and return
|
||||||
return @bitCast(f64, absResult | quotientSign);
|
return @as(f64, @bitCast(absResult | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ const __divdf3 = @import("divdf3.zig").__divdf3;
|
|||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
fn compareResultD(result: f64, expected: u64) bool {
|
fn compareResultD(result: f64, expected: u64) bool {
|
||||||
const rep = @bitCast(u64, result);
|
const rep = @as(u64, @bitCast(result));
|
||||||
|
|
||||||
if (rep == expected) {
|
if (rep == expected) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -7,5 +7,5 @@ comptime {
|
|||||||
|
|
||||||
pub fn __divhf3(a: f16, b: f16) callconv(.C) f16 {
|
pub fn __divhf3(a: f16, b: f16) callconv(.C) f16 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f16, divsf3.__divsf3(a, b));
|
return @as(f16, @floatCast(divsf3.__divsf3(a, b)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,52 +44,52 @@ inline fn div(a: f32, b: f32) f32 {
|
|||||||
const absMask = signBit - 1;
|
const absMask = signBit - 1;
|
||||||
const exponentMask = absMask ^ significandMask;
|
const exponentMask = absMask ^ significandMask;
|
||||||
const qnanRep = exponentMask | quietBit;
|
const qnanRep = exponentMask | quietBit;
|
||||||
const infRep = @bitCast(Z, std.math.inf(f32));
|
const infRep = @as(Z, @bitCast(std.math.inf(f32)));
|
||||||
|
|
||||||
const aExponent = @truncate(u32, (@bitCast(Z, a) >> significandBits) & maxExponent);
|
const aExponent = @as(u32, @truncate((@as(Z, @bitCast(a)) >> significandBits) & maxExponent));
|
||||||
const bExponent = @truncate(u32, (@bitCast(Z, b) >> significandBits) & maxExponent);
|
const bExponent = @as(u32, @truncate((@as(Z, @bitCast(b)) >> significandBits) & maxExponent));
|
||||||
const quotientSign: Z = (@bitCast(Z, a) ^ @bitCast(Z, b)) & signBit;
|
const quotientSign: Z = (@as(Z, @bitCast(a)) ^ @as(Z, @bitCast(b))) & signBit;
|
||||||
|
|
||||||
var aSignificand: Z = @bitCast(Z, a) & significandMask;
|
var aSignificand: Z = @as(Z, @bitCast(a)) & significandMask;
|
||||||
var bSignificand: Z = @bitCast(Z, b) & significandMask;
|
var bSignificand: Z = @as(Z, @bitCast(b)) & significandMask;
|
||||||
var scale: i32 = 0;
|
var scale: i32 = 0;
|
||||||
|
|
||||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
// Detect if a or b is zero, denormal, infinity, or NaN.
|
||||||
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
||||||
const aAbs: Z = @bitCast(Z, a) & absMask;
|
const aAbs: Z = @as(Z, @bitCast(a)) & absMask;
|
||||||
const bAbs: Z = @bitCast(Z, b) & absMask;
|
const bAbs: Z = @as(Z, @bitCast(b)) & absMask;
|
||||||
|
|
||||||
// NaN / anything = qNaN
|
// NaN / anything = qNaN
|
||||||
if (aAbs > infRep) return @bitCast(f32, @bitCast(Z, a) | quietBit);
|
if (aAbs > infRep) return @as(f32, @bitCast(@as(Z, @bitCast(a)) | quietBit));
|
||||||
// anything / NaN = qNaN
|
// anything / NaN = qNaN
|
||||||
if (bAbs > infRep) return @bitCast(f32, @bitCast(Z, b) | quietBit);
|
if (bAbs > infRep) return @as(f32, @bitCast(@as(Z, @bitCast(b)) | quietBit));
|
||||||
|
|
||||||
if (aAbs == infRep) {
|
if (aAbs == infRep) {
|
||||||
// infinity / infinity = NaN
|
// infinity / infinity = NaN
|
||||||
if (bAbs == infRep) {
|
if (bAbs == infRep) {
|
||||||
return @bitCast(f32, qnanRep);
|
return @as(f32, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
// infinity / anything else = +/- infinity
|
// infinity / anything else = +/- infinity
|
||||||
else {
|
else {
|
||||||
return @bitCast(f32, aAbs | quotientSign);
|
return @as(f32, @bitCast(aAbs | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// anything else / infinity = +/- 0
|
// anything else / infinity = +/- 0
|
||||||
if (bAbs == infRep) return @bitCast(f32, quotientSign);
|
if (bAbs == infRep) return @as(f32, @bitCast(quotientSign));
|
||||||
|
|
||||||
if (aAbs == 0) {
|
if (aAbs == 0) {
|
||||||
// zero / zero = NaN
|
// zero / zero = NaN
|
||||||
if (bAbs == 0) {
|
if (bAbs == 0) {
|
||||||
return @bitCast(f32, qnanRep);
|
return @as(f32, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
// zero / anything else = +/- zero
|
// zero / anything else = +/- zero
|
||||||
else {
|
else {
|
||||||
return @bitCast(f32, quotientSign);
|
return @as(f32, @bitCast(quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// anything else / zero = +/- infinity
|
// anything else / zero = +/- infinity
|
||||||
if (bAbs == 0) return @bitCast(f32, infRep | quotientSign);
|
if (bAbs == 0) return @as(f32, @bitCast(infRep | quotientSign));
|
||||||
|
|
||||||
// one or both of a or b is denormal, the other (if applicable) is a
|
// one or both of a or b is denormal, the other (if applicable) is a
|
||||||
// normal number. Renormalize one or both of a and b, and set scale to
|
// normal number. Renormalize one or both of a and b, and set scale to
|
||||||
@ -103,7 +103,7 @@ inline fn div(a: f32, b: f32) f32 {
|
|||||||
// won't hurt anything.)
|
// won't hurt anything.)
|
||||||
aSignificand |= implicitBit;
|
aSignificand |= implicitBit;
|
||||||
bSignificand |= implicitBit;
|
bSignificand |= implicitBit;
|
||||||
var quotientExponent: i32 = @bitCast(i32, aExponent -% bExponent) +% scale;
|
var quotientExponent: i32 = @as(i32, @bitCast(aExponent -% bExponent)) +% scale;
|
||||||
|
|
||||||
// Align the significand of b as a Q31 fixed-point number in the range
|
// Align the significand of b as a Q31 fixed-point number in the range
|
||||||
// [1, 2.0) and get a Q32 approximate reciprocal using a small minimax
|
// [1, 2.0) and get a Q32 approximate reciprocal using a small minimax
|
||||||
@ -120,12 +120,12 @@ inline fn div(a: f32, b: f32) f32 {
|
|||||||
// with each iteration, so after three iterations, we have about 28 binary
|
// with each iteration, so after three iterations, we have about 28 binary
|
||||||
// digits of accuracy.
|
// digits of accuracy.
|
||||||
var correction: u32 = undefined;
|
var correction: u32 = undefined;
|
||||||
correction = @truncate(u32, ~(@as(u64, reciprocal) *% q31b >> 32) +% 1);
|
correction = @as(u32, @truncate(~(@as(u64, reciprocal) *% q31b >> 32) +% 1));
|
||||||
reciprocal = @truncate(u32, @as(u64, reciprocal) *% correction >> 31);
|
reciprocal = @as(u32, @truncate(@as(u64, reciprocal) *% correction >> 31));
|
||||||
correction = @truncate(u32, ~(@as(u64, reciprocal) *% q31b >> 32) +% 1);
|
correction = @as(u32, @truncate(~(@as(u64, reciprocal) *% q31b >> 32) +% 1));
|
||||||
reciprocal = @truncate(u32, @as(u64, reciprocal) *% correction >> 31);
|
reciprocal = @as(u32, @truncate(@as(u64, reciprocal) *% correction >> 31));
|
||||||
correction = @truncate(u32, ~(@as(u64, reciprocal) *% q31b >> 32) +% 1);
|
correction = @as(u32, @truncate(~(@as(u64, reciprocal) *% q31b >> 32) +% 1));
|
||||||
reciprocal = @truncate(u32, @as(u64, reciprocal) *% correction >> 31);
|
reciprocal = @as(u32, @truncate(@as(u64, reciprocal) *% correction >> 31));
|
||||||
|
|
||||||
// Exhaustive testing shows that the error in reciprocal after three steps
|
// Exhaustive testing shows that the error in reciprocal after three steps
|
||||||
// is in the interval [-0x1.f58108p-31, 0x1.d0e48cp-29], in line with our
|
// is in the interval [-0x1.f58108p-31, 0x1.d0e48cp-29], in line with our
|
||||||
@ -147,7 +147,7 @@ inline fn div(a: f32, b: f32) f32 {
|
|||||||
// is the error in the reciprocal of b scaled by the maximum
|
// is the error in the reciprocal of b scaled by the maximum
|
||||||
// possible value of a. As a consequence of this error bound,
|
// possible value of a. As a consequence of this error bound,
|
||||||
// either q or nextafter(q) is the correctly rounded
|
// either q or nextafter(q) is the correctly rounded
|
||||||
var quotient: Z = @truncate(u32, @as(u64, reciprocal) *% (aSignificand << 1) >> 32);
|
var quotient: Z = @as(u32, @truncate(@as(u64, reciprocal) *% (aSignificand << 1) >> 32));
|
||||||
|
|
||||||
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
|
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
|
||||||
// In either case, we are going to compute a residual of the form
|
// In either case, we are going to compute a residual of the form
|
||||||
@ -175,7 +175,7 @@ inline fn div(a: f32, b: f32) f32 {
|
|||||||
|
|
||||||
if (writtenExponent >= maxExponent) {
|
if (writtenExponent >= maxExponent) {
|
||||||
// If we have overflowed the exponent, return infinity.
|
// If we have overflowed the exponent, return infinity.
|
||||||
return @bitCast(f32, infRep | quotientSign);
|
return @as(f32, @bitCast(infRep | quotientSign));
|
||||||
} else if (writtenExponent < 1) {
|
} else if (writtenExponent < 1) {
|
||||||
if (writtenExponent == 0) {
|
if (writtenExponent == 0) {
|
||||||
// Check whether the rounded result is normal.
|
// Check whether the rounded result is normal.
|
||||||
@ -186,22 +186,22 @@ inline fn div(a: f32, b: f32) f32 {
|
|||||||
absResult += round;
|
absResult += round;
|
||||||
if ((absResult & ~significandMask) > 0) {
|
if ((absResult & ~significandMask) > 0) {
|
||||||
// The rounded result is normal; return it.
|
// The rounded result is normal; return it.
|
||||||
return @bitCast(f32, absResult | quotientSign);
|
return @as(f32, @bitCast(absResult | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Flush denormals to zero. In the future, it would be nice to add
|
// Flush denormals to zero. In the future, it would be nice to add
|
||||||
// code to round them correctly.
|
// code to round them correctly.
|
||||||
return @bitCast(f32, quotientSign);
|
return @as(f32, @bitCast(quotientSign));
|
||||||
} else {
|
} else {
|
||||||
const round = @intFromBool((residual << 1) > bSignificand);
|
const round = @intFromBool((residual << 1) > bSignificand);
|
||||||
// Clear the implicit bit
|
// Clear the implicit bit
|
||||||
var absResult = quotient & significandMask;
|
var absResult = quotient & significandMask;
|
||||||
// Insert the exponent
|
// Insert the exponent
|
||||||
absResult |= @bitCast(Z, writtenExponent) << significandBits;
|
absResult |= @as(Z, @bitCast(writtenExponent)) << significandBits;
|
||||||
// Round
|
// Round
|
||||||
absResult +%= round;
|
absResult +%= round;
|
||||||
// Insert the sign and return
|
// Insert the sign and return
|
||||||
return @bitCast(f32, absResult | quotientSign);
|
return @as(f32, @bitCast(absResult | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ const __divsf3 = @import("divsf3.zig").__divsf3;
|
|||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
fn compareResultF(result: f32, expected: u32) bool {
|
fn compareResultF(result: f32, expected: u32) bool {
|
||||||
const rep = @bitCast(u32, result);
|
const rep = @as(u32, @bitCast(result));
|
||||||
|
|
||||||
if (rep == expected) {
|
if (rep == expected) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -41,52 +41,52 @@ inline fn div(a: f128, b: f128) f128 {
|
|||||||
const absMask = signBit - 1;
|
const absMask = signBit - 1;
|
||||||
const exponentMask = absMask ^ significandMask;
|
const exponentMask = absMask ^ significandMask;
|
||||||
const qnanRep = exponentMask | quietBit;
|
const qnanRep = exponentMask | quietBit;
|
||||||
const infRep = @bitCast(Z, std.math.inf(f128));
|
const infRep = @as(Z, @bitCast(std.math.inf(f128)));
|
||||||
|
|
||||||
const aExponent = @truncate(u32, (@bitCast(Z, a) >> significandBits) & maxExponent);
|
const aExponent = @as(u32, @truncate((@as(Z, @bitCast(a)) >> significandBits) & maxExponent));
|
||||||
const bExponent = @truncate(u32, (@bitCast(Z, b) >> significandBits) & maxExponent);
|
const bExponent = @as(u32, @truncate((@as(Z, @bitCast(b)) >> significandBits) & maxExponent));
|
||||||
const quotientSign: Z = (@bitCast(Z, a) ^ @bitCast(Z, b)) & signBit;
|
const quotientSign: Z = (@as(Z, @bitCast(a)) ^ @as(Z, @bitCast(b))) & signBit;
|
||||||
|
|
||||||
var aSignificand: Z = @bitCast(Z, a) & significandMask;
|
var aSignificand: Z = @as(Z, @bitCast(a)) & significandMask;
|
||||||
var bSignificand: Z = @bitCast(Z, b) & significandMask;
|
var bSignificand: Z = @as(Z, @bitCast(b)) & significandMask;
|
||||||
var scale: i32 = 0;
|
var scale: i32 = 0;
|
||||||
|
|
||||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
// Detect if a or b is zero, denormal, infinity, or NaN.
|
||||||
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
||||||
const aAbs: Z = @bitCast(Z, a) & absMask;
|
const aAbs: Z = @as(Z, @bitCast(a)) & absMask;
|
||||||
const bAbs: Z = @bitCast(Z, b) & absMask;
|
const bAbs: Z = @as(Z, @bitCast(b)) & absMask;
|
||||||
|
|
||||||
// NaN / anything = qNaN
|
// NaN / anything = qNaN
|
||||||
if (aAbs > infRep) return @bitCast(f128, @bitCast(Z, a) | quietBit);
|
if (aAbs > infRep) return @as(f128, @bitCast(@as(Z, @bitCast(a)) | quietBit));
|
||||||
// anything / NaN = qNaN
|
// anything / NaN = qNaN
|
||||||
if (bAbs > infRep) return @bitCast(f128, @bitCast(Z, b) | quietBit);
|
if (bAbs > infRep) return @as(f128, @bitCast(@as(Z, @bitCast(b)) | quietBit));
|
||||||
|
|
||||||
if (aAbs == infRep) {
|
if (aAbs == infRep) {
|
||||||
// infinity / infinity = NaN
|
// infinity / infinity = NaN
|
||||||
if (bAbs == infRep) {
|
if (bAbs == infRep) {
|
||||||
return @bitCast(f128, qnanRep);
|
return @as(f128, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
// infinity / anything else = +/- infinity
|
// infinity / anything else = +/- infinity
|
||||||
else {
|
else {
|
||||||
return @bitCast(f128, aAbs | quotientSign);
|
return @as(f128, @bitCast(aAbs | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// anything else / infinity = +/- 0
|
// anything else / infinity = +/- 0
|
||||||
if (bAbs == infRep) return @bitCast(f128, quotientSign);
|
if (bAbs == infRep) return @as(f128, @bitCast(quotientSign));
|
||||||
|
|
||||||
if (aAbs == 0) {
|
if (aAbs == 0) {
|
||||||
// zero / zero = NaN
|
// zero / zero = NaN
|
||||||
if (bAbs == 0) {
|
if (bAbs == 0) {
|
||||||
return @bitCast(f128, qnanRep);
|
return @as(f128, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
// zero / anything else = +/- zero
|
// zero / anything else = +/- zero
|
||||||
else {
|
else {
|
||||||
return @bitCast(f128, quotientSign);
|
return @as(f128, @bitCast(quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// anything else / zero = +/- infinity
|
// anything else / zero = +/- infinity
|
||||||
if (bAbs == 0) return @bitCast(f128, infRep | quotientSign);
|
if (bAbs == 0) return @as(f128, @bitCast(infRep | quotientSign));
|
||||||
|
|
||||||
// one or both of a or b is denormal, the other (if applicable) is a
|
// one or both of a or b is denormal, the other (if applicable) is a
|
||||||
// normal number. Renormalize one or both of a and b, and set scale to
|
// normal number. Renormalize one or both of a and b, and set scale to
|
||||||
@ -100,13 +100,13 @@ inline fn div(a: f128, b: f128) f128 {
|
|||||||
// won't hurt anything.
|
// won't hurt anything.
|
||||||
aSignificand |= implicitBit;
|
aSignificand |= implicitBit;
|
||||||
bSignificand |= implicitBit;
|
bSignificand |= implicitBit;
|
||||||
var quotientExponent: i32 = @bitCast(i32, aExponent -% bExponent) +% scale;
|
var quotientExponent: i32 = @as(i32, @bitCast(aExponent -% bExponent)) +% scale;
|
||||||
|
|
||||||
// Align the significand of b as a Q63 fixed-point number in the range
|
// Align the significand of b as a Q63 fixed-point number in the range
|
||||||
// [1, 2.0) and get a Q64 approximate reciprocal using a small minimax
|
// [1, 2.0) and get a Q64 approximate reciprocal using a small minimax
|
||||||
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
||||||
// is accurate to about 3.5 binary digits.
|
// is accurate to about 3.5 binary digits.
|
||||||
const q63b = @truncate(u64, bSignificand >> 49);
|
const q63b = @as(u64, @truncate(bSignificand >> 49));
|
||||||
var recip64 = @as(u64, 0x7504f333F9DE6484) -% q63b;
|
var recip64 = @as(u64, 0x7504f333F9DE6484) -% q63b;
|
||||||
// 0x7504f333F9DE6484 / 2^64 + 1 = 3/4 + 1/sqrt(2)
|
// 0x7504f333F9DE6484 / 2^64 + 1 = 3/4 + 1/sqrt(2)
|
||||||
|
|
||||||
@ -117,16 +117,16 @@ inline fn div(a: f128, b: f128) f128 {
|
|||||||
// This doubles the number of correct binary digits in the approximation
|
// This doubles the number of correct binary digits in the approximation
|
||||||
// with each iteration.
|
// with each iteration.
|
||||||
var correction64: u64 = undefined;
|
var correction64: u64 = undefined;
|
||||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
correction64 = @as(u64, @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1));
|
||||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
recip64 = @as(u64, @truncate(@as(u128, recip64) *% correction64 >> 63));
|
||||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
correction64 = @as(u64, @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1));
|
||||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
recip64 = @as(u64, @truncate(@as(u128, recip64) *% correction64 >> 63));
|
||||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
correction64 = @as(u64, @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1));
|
||||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
recip64 = @as(u64, @truncate(@as(u128, recip64) *% correction64 >> 63));
|
||||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
correction64 = @as(u64, @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1));
|
||||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
recip64 = @as(u64, @truncate(@as(u128, recip64) *% correction64 >> 63));
|
||||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
correction64 = @as(u64, @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1));
|
||||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
recip64 = @as(u64, @truncate(@as(u128, recip64) *% correction64 >> 63));
|
||||||
|
|
||||||
// The reciprocal may have overflowed to zero if the upper half of b is
|
// The reciprocal may have overflowed to zero if the upper half of b is
|
||||||
// exactly 1.0. This would sabatoge the full-width final stage of the
|
// exactly 1.0. This would sabatoge the full-width final stage of the
|
||||||
@ -135,7 +135,7 @@ inline fn div(a: f128, b: f128) f128 {
|
|||||||
|
|
||||||
// We need to perform one more iteration to get us to 112 binary digits;
|
// We need to perform one more iteration to get us to 112 binary digits;
|
||||||
// The last iteration needs to happen with extra precision.
|
// The last iteration needs to happen with extra precision.
|
||||||
const q127blo: u64 = @truncate(u64, bSignificand << 15);
|
const q127blo: u64 = @as(u64, @truncate(bSignificand << 15));
|
||||||
var correction: u128 = undefined;
|
var correction: u128 = undefined;
|
||||||
var reciprocal: u128 = undefined;
|
var reciprocal: u128 = undefined;
|
||||||
|
|
||||||
@ -151,8 +151,8 @@ inline fn div(a: f128, b: f128) f128 {
|
|||||||
|
|
||||||
correction = -%(r64q63 + (r64q127 >> 64));
|
correction = -%(r64q63 + (r64q127 >> 64));
|
||||||
|
|
||||||
const cHi = @truncate(u64, correction >> 64);
|
const cHi = @as(u64, @truncate(correction >> 64));
|
||||||
const cLo = @truncate(u64, correction);
|
const cLo = @as(u64, @truncate(correction));
|
||||||
|
|
||||||
wideMultiply(u128, recip64, cHi, &dummy, &r64cH);
|
wideMultiply(u128, recip64, cHi, &dummy, &r64cH);
|
||||||
wideMultiply(u128, recip64, cLo, &dummy, &r64cL);
|
wideMultiply(u128, recip64, cLo, &dummy, &r64cL);
|
||||||
@ -210,7 +210,7 @@ inline fn div(a: f128, b: f128) f128 {
|
|||||||
|
|
||||||
if (writtenExponent >= maxExponent) {
|
if (writtenExponent >= maxExponent) {
|
||||||
// If we have overflowed the exponent, return infinity.
|
// If we have overflowed the exponent, return infinity.
|
||||||
return @bitCast(f128, infRep | quotientSign);
|
return @as(f128, @bitCast(infRep | quotientSign));
|
||||||
} else if (writtenExponent < 1) {
|
} else if (writtenExponent < 1) {
|
||||||
if (writtenExponent == 0) {
|
if (writtenExponent == 0) {
|
||||||
// Check whether the rounded result is normal.
|
// Check whether the rounded result is normal.
|
||||||
@ -221,22 +221,22 @@ inline fn div(a: f128, b: f128) f128 {
|
|||||||
absResult += round;
|
absResult += round;
|
||||||
if ((absResult & ~significandMask) > 0) {
|
if ((absResult & ~significandMask) > 0) {
|
||||||
// The rounded result is normal; return it.
|
// The rounded result is normal; return it.
|
||||||
return @bitCast(f128, absResult | quotientSign);
|
return @as(f128, @bitCast(absResult | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Flush denormals to zero. In the future, it would be nice to add
|
// Flush denormals to zero. In the future, it would be nice to add
|
||||||
// code to round them correctly.
|
// code to round them correctly.
|
||||||
return @bitCast(f128, quotientSign);
|
return @as(f128, @bitCast(quotientSign));
|
||||||
} else {
|
} else {
|
||||||
const round = @intFromBool((residual << 1) >= bSignificand);
|
const round = @intFromBool((residual << 1) >= bSignificand);
|
||||||
// Clear the implicit bit
|
// Clear the implicit bit
|
||||||
var absResult = quotient & significandMask;
|
var absResult = quotient & significandMask;
|
||||||
// Insert the exponent
|
// Insert the exponent
|
||||||
absResult |= @intCast(Z, writtenExponent) << significandBits;
|
absResult |= @as(Z, @intCast(writtenExponent)) << significandBits;
|
||||||
// Round
|
// Round
|
||||||
absResult +%= round;
|
absResult +%= round;
|
||||||
// Insert the sign and return
|
// Insert the sign and return
|
||||||
return @bitCast(f128, absResult | quotientSign);
|
return @as(f128, @bitCast(absResult | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,9 +5,9 @@ const testing = std.testing;
|
|||||||
const __divtf3 = @import("divtf3.zig").__divtf3;
|
const __divtf3 = @import("divtf3.zig").__divtf3;
|
||||||
|
|
||||||
fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
|
fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
|
||||||
const rep = @bitCast(u128, result);
|
const rep = @as(u128, @bitCast(result));
|
||||||
const hi = @truncate(u64, rep >> 64);
|
const hi = @as(u64, @truncate(rep >> 64));
|
||||||
const lo = @truncate(u64, rep);
|
const lo = @as(u64, @truncate(rep));
|
||||||
|
|
||||||
if (hi == expectedHi and lo == expectedLo) {
|
if (hi == expectedHi and lo == expectedLo) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -21,7 +21,7 @@ pub fn __divti3(a: i128, b: i128) callconv(.C) i128 {
|
|||||||
const v128 = @Vector(2, u64);
|
const v128 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __divti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {
|
fn __divti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {
|
||||||
return @bitCast(v128, div(@bitCast(i128, a), @bitCast(i128, b)));
|
return @as(v128, @bitCast(div(@as(i128, @bitCast(a)), @as(i128, @bitCast(b)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn div(a: i128, b: i128) i128 {
|
inline fn div(a: i128, b: i128) i128 {
|
||||||
@ -31,9 +31,9 @@ inline fn div(a: i128, b: i128) i128 {
|
|||||||
const an = (a ^ s_a) -% s_a;
|
const an = (a ^ s_a) -% s_a;
|
||||||
const bn = (b ^ s_b) -% s_b;
|
const bn = (b ^ s_b) -% s_b;
|
||||||
|
|
||||||
const r = udivmod(u128, @bitCast(u128, an), @bitCast(u128, bn), null);
|
const r = udivmod(u128, @as(u128, @bitCast(an)), @as(u128, @bitCast(bn)), null);
|
||||||
const s = s_a ^ s_b;
|
const s = s_a ^ s_b;
|
||||||
return (@bitCast(i128, r) ^ s) -% s;
|
return (@as(i128, @bitCast(r)) ^ s) -% s;
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@ -14,8 +14,8 @@ test "divti3" {
|
|||||||
try test__divti3(-2, 1, -2);
|
try test__divti3(-2, 1, -2);
|
||||||
try test__divti3(-2, -1, 2);
|
try test__divti3(-2, -1, 2);
|
||||||
|
|
||||||
try test__divti3(@bitCast(i128, @as(u128, 0x8 << 124)), 1, @bitCast(i128, @as(u128, 0x8 << 124)));
|
try test__divti3(@as(i128, @bitCast(@as(u128, 0x8 << 124))), 1, @as(i128, @bitCast(@as(u128, 0x8 << 124))));
|
||||||
try test__divti3(@bitCast(i128, @as(u128, 0x8 << 124)), -1, @bitCast(i128, @as(u128, 0x8 << 124)));
|
try test__divti3(@as(i128, @bitCast(@as(u128, 0x8 << 124))), -1, @as(i128, @bitCast(@as(u128, 0x8 << 124))));
|
||||||
try test__divti3(@bitCast(i128, @as(u128, 0x8 << 124)), -2, @bitCast(i128, @as(u128, 0x4 << 124)));
|
try test__divti3(@as(i128, @bitCast(@as(u128, 0x8 << 124))), -2, @as(i128, @bitCast(@as(u128, 0x4 << 124))));
|
||||||
try test__divti3(@bitCast(i128, @as(u128, 0x8 << 124)), 2, @bitCast(i128, @as(u128, 0xc << 124)));
|
try test__divti3(@as(i128, @bitCast(@as(u128, 0x8 << 124))), 2, @as(i128, @bitCast(@as(u128, 0xc << 124))));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,53 +29,53 @@ pub fn __divxf3(a: f80, b: f80) callconv(.C) f80 {
|
|||||||
const significandMask = (@as(Z, 1) << significandBits) - 1;
|
const significandMask = (@as(Z, 1) << significandBits) - 1;
|
||||||
|
|
||||||
const absMask = signBit - 1;
|
const absMask = signBit - 1;
|
||||||
const qnanRep = @bitCast(Z, std.math.nan(T)) | quietBit;
|
const qnanRep = @as(Z, @bitCast(std.math.nan(T))) | quietBit;
|
||||||
const infRep = @bitCast(Z, std.math.inf(T));
|
const infRep = @as(Z, @bitCast(std.math.inf(T)));
|
||||||
|
|
||||||
const aExponent = @truncate(u32, (@bitCast(Z, a) >> significandBits) & maxExponent);
|
const aExponent = @as(u32, @truncate((@as(Z, @bitCast(a)) >> significandBits) & maxExponent));
|
||||||
const bExponent = @truncate(u32, (@bitCast(Z, b) >> significandBits) & maxExponent);
|
const bExponent = @as(u32, @truncate((@as(Z, @bitCast(b)) >> significandBits) & maxExponent));
|
||||||
const quotientSign: Z = (@bitCast(Z, a) ^ @bitCast(Z, b)) & signBit;
|
const quotientSign: Z = (@as(Z, @bitCast(a)) ^ @as(Z, @bitCast(b))) & signBit;
|
||||||
|
|
||||||
var aSignificand: Z = @bitCast(Z, a) & significandMask;
|
var aSignificand: Z = @as(Z, @bitCast(a)) & significandMask;
|
||||||
var bSignificand: Z = @bitCast(Z, b) & significandMask;
|
var bSignificand: Z = @as(Z, @bitCast(b)) & significandMask;
|
||||||
var scale: i32 = 0;
|
var scale: i32 = 0;
|
||||||
|
|
||||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
// Detect if a or b is zero, denormal, infinity, or NaN.
|
||||||
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
||||||
const aAbs: Z = @bitCast(Z, a) & absMask;
|
const aAbs: Z = @as(Z, @bitCast(a)) & absMask;
|
||||||
const bAbs: Z = @bitCast(Z, b) & absMask;
|
const bAbs: Z = @as(Z, @bitCast(b)) & absMask;
|
||||||
|
|
||||||
// NaN / anything = qNaN
|
// NaN / anything = qNaN
|
||||||
if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);
|
if (aAbs > infRep) return @as(T, @bitCast(@as(Z, @bitCast(a)) | quietBit));
|
||||||
// anything / NaN = qNaN
|
// anything / NaN = qNaN
|
||||||
if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit);
|
if (bAbs > infRep) return @as(T, @bitCast(@as(Z, @bitCast(b)) | quietBit));
|
||||||
|
|
||||||
if (aAbs == infRep) {
|
if (aAbs == infRep) {
|
||||||
// infinity / infinity = NaN
|
// infinity / infinity = NaN
|
||||||
if (bAbs == infRep) {
|
if (bAbs == infRep) {
|
||||||
return @bitCast(T, qnanRep);
|
return @as(T, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
// infinity / anything else = +/- infinity
|
// infinity / anything else = +/- infinity
|
||||||
else {
|
else {
|
||||||
return @bitCast(T, aAbs | quotientSign);
|
return @as(T, @bitCast(aAbs | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// anything else / infinity = +/- 0
|
// anything else / infinity = +/- 0
|
||||||
if (bAbs == infRep) return @bitCast(T, quotientSign);
|
if (bAbs == infRep) return @as(T, @bitCast(quotientSign));
|
||||||
|
|
||||||
if (aAbs == 0) {
|
if (aAbs == 0) {
|
||||||
// zero / zero = NaN
|
// zero / zero = NaN
|
||||||
if (bAbs == 0) {
|
if (bAbs == 0) {
|
||||||
return @bitCast(T, qnanRep);
|
return @as(T, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
// zero / anything else = +/- zero
|
// zero / anything else = +/- zero
|
||||||
else {
|
else {
|
||||||
return @bitCast(T, quotientSign);
|
return @as(T, @bitCast(quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// anything else / zero = +/- infinity
|
// anything else / zero = +/- infinity
|
||||||
if (bAbs == 0) return @bitCast(T, infRep | quotientSign);
|
if (bAbs == 0) return @as(T, @bitCast(infRep | quotientSign));
|
||||||
|
|
||||||
// one or both of a or b is denormal, the other (if applicable) is a
|
// one or both of a or b is denormal, the other (if applicable) is a
|
||||||
// normal number. Renormalize one or both of a and b, and set scale to
|
// normal number. Renormalize one or both of a and b, and set scale to
|
||||||
@ -83,13 +83,13 @@ pub fn __divxf3(a: f80, b: f80) callconv(.C) f80 {
|
|||||||
if (aAbs < integerBit) scale +%= normalize(T, &aSignificand);
|
if (aAbs < integerBit) scale +%= normalize(T, &aSignificand);
|
||||||
if (bAbs < integerBit) scale -%= normalize(T, &bSignificand);
|
if (bAbs < integerBit) scale -%= normalize(T, &bSignificand);
|
||||||
}
|
}
|
||||||
var quotientExponent: i32 = @bitCast(i32, aExponent -% bExponent) +% scale;
|
var quotientExponent: i32 = @as(i32, @bitCast(aExponent -% bExponent)) +% scale;
|
||||||
|
|
||||||
// Align the significand of b as a Q63 fixed-point number in the range
|
// Align the significand of b as a Q63 fixed-point number in the range
|
||||||
// [1, 2.0) and get a Q64 approximate reciprocal using a small minimax
|
// [1, 2.0) and get a Q64 approximate reciprocal using a small minimax
|
||||||
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
||||||
// is accurate to about 3.5 binary digits.
|
// is accurate to about 3.5 binary digits.
|
||||||
const q63b = @intCast(u64, bSignificand);
|
const q63b = @as(u64, @intCast(bSignificand));
|
||||||
var recip64 = @as(u64, 0x7504f333F9DE6484) -% q63b;
|
var recip64 = @as(u64, 0x7504f333F9DE6484) -% q63b;
|
||||||
// 0x7504f333F9DE6484 / 2^64 + 1 = 3/4 + 1/sqrt(2)
|
// 0x7504f333F9DE6484 / 2^64 + 1 = 3/4 + 1/sqrt(2)
|
||||||
|
|
||||||
@ -100,16 +100,16 @@ pub fn __divxf3(a: f80, b: f80) callconv(.C) f80 {
|
|||||||
// This doubles the number of correct binary digits in the approximation
|
// This doubles the number of correct binary digits in the approximation
|
||||||
// with each iteration.
|
// with each iteration.
|
||||||
var correction64: u64 = undefined;
|
var correction64: u64 = undefined;
|
||||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
correction64 = @as(u64, @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1));
|
||||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
recip64 = @as(u64, @truncate(@as(u128, recip64) *% correction64 >> 63));
|
||||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
correction64 = @as(u64, @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1));
|
||||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
recip64 = @as(u64, @truncate(@as(u128, recip64) *% correction64 >> 63));
|
||||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
correction64 = @as(u64, @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1));
|
||||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
recip64 = @as(u64, @truncate(@as(u128, recip64) *% correction64 >> 63));
|
||||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
correction64 = @as(u64, @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1));
|
||||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
recip64 = @as(u64, @truncate(@as(u128, recip64) *% correction64 >> 63));
|
||||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
correction64 = @as(u64, @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1));
|
||||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
recip64 = @as(u64, @truncate(@as(u128, recip64) *% correction64 >> 63));
|
||||||
|
|
||||||
// The reciprocal may have overflowed to zero if the upper half of b is
|
// The reciprocal may have overflowed to zero if the upper half of b is
|
||||||
// exactly 1.0. This would sabatoge the full-width final stage of the
|
// exactly 1.0. This would sabatoge the full-width final stage of the
|
||||||
@ -128,8 +128,8 @@ pub fn __divxf3(a: f80, b: f80) callconv(.C) f80 {
|
|||||||
|
|
||||||
correction = -%correction;
|
correction = -%correction;
|
||||||
|
|
||||||
const cHi = @truncate(u64, correction >> 64);
|
const cHi = @as(u64, @truncate(correction >> 64));
|
||||||
const cLo = @truncate(u64, correction);
|
const cLo = @as(u64, @truncate(correction));
|
||||||
|
|
||||||
var r64cH: u128 = undefined;
|
var r64cH: u128 = undefined;
|
||||||
var r64cL: u128 = undefined;
|
var r64cL: u128 = undefined;
|
||||||
@ -164,8 +164,8 @@ pub fn __divxf3(a: f80, b: f80) callconv(.C) f80 {
|
|||||||
// exponent accordingly.
|
// exponent accordingly.
|
||||||
var quotient: u64 = if (quotient128 < (integerBit << 1)) b: {
|
var quotient: u64 = if (quotient128 < (integerBit << 1)) b: {
|
||||||
quotientExponent -= 1;
|
quotientExponent -= 1;
|
||||||
break :b @intCast(u64, quotient128);
|
break :b @as(u64, @intCast(quotient128));
|
||||||
} else @intCast(u64, quotient128 >> 1);
|
} else @as(u64, @intCast(quotient128 >> 1));
|
||||||
|
|
||||||
// We are going to compute a residual of the form
|
// We are going to compute a residual of the form
|
||||||
//
|
//
|
||||||
@ -182,26 +182,26 @@ pub fn __divxf3(a: f80, b: f80) callconv(.C) f80 {
|
|||||||
const writtenExponent = quotientExponent + exponentBias;
|
const writtenExponent = quotientExponent + exponentBias;
|
||||||
if (writtenExponent >= maxExponent) {
|
if (writtenExponent >= maxExponent) {
|
||||||
// If we have overflowed the exponent, return infinity.
|
// If we have overflowed the exponent, return infinity.
|
||||||
return @bitCast(T, infRep | quotientSign);
|
return @as(T, @bitCast(infRep | quotientSign));
|
||||||
} else if (writtenExponent < 1) {
|
} else if (writtenExponent < 1) {
|
||||||
if (writtenExponent == 0) {
|
if (writtenExponent == 0) {
|
||||||
// Check whether the rounded result is normal.
|
// Check whether the rounded result is normal.
|
||||||
if (residual > (bSignificand >> 1)) { // round
|
if (residual > (bSignificand >> 1)) { // round
|
||||||
if (quotient == (integerBit - 1)) // If the rounded result is normal, return it
|
if (quotient == (integerBit - 1)) // If the rounded result is normal, return it
|
||||||
return @bitCast(T, @bitCast(Z, std.math.floatMin(T)) | quotientSign);
|
return @as(T, @bitCast(@as(Z, @bitCast(std.math.floatMin(T))) | quotientSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Flush denormals to zero. In the future, it would be nice to add
|
// Flush denormals to zero. In the future, it would be nice to add
|
||||||
// code to round them correctly.
|
// code to round them correctly.
|
||||||
return @bitCast(T, quotientSign);
|
return @as(T, @bitCast(quotientSign));
|
||||||
} else {
|
} else {
|
||||||
const round = @intFromBool(residual > (bSignificand >> 1));
|
const round = @intFromBool(residual > (bSignificand >> 1));
|
||||||
// Insert the exponent
|
// Insert the exponent
|
||||||
var absResult = quotient | (@intCast(Z, writtenExponent) << significandBits);
|
var absResult = quotient | (@as(Z, @intCast(writtenExponent)) << significandBits);
|
||||||
// Round
|
// Round
|
||||||
absResult +%= round;
|
absResult +%= round;
|
||||||
// Insert the sign and return
|
// Insert the sign and return
|
||||||
return @bitCast(T, absResult | quotientSign | integerBit);
|
return @as(T, @bitCast(absResult | quotientSign | integerBit));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,11 +5,11 @@ const testing = std.testing;
|
|||||||
const __divxf3 = @import("divxf3.zig").__divxf3;
|
const __divxf3 = @import("divxf3.zig").__divxf3;
|
||||||
|
|
||||||
fn compareResult(result: f80, expected: u80) bool {
|
fn compareResult(result: f80, expected: u80) bool {
|
||||||
const rep = @bitCast(u80, result);
|
const rep = @as(u80, @bitCast(result));
|
||||||
|
|
||||||
if (rep == expected) return true;
|
if (rep == expected) return true;
|
||||||
// test other possible NaN representations (signal NaN)
|
// test other possible NaN representations (signal NaN)
|
||||||
if (math.isNan(result) and math.isNan(@bitCast(f80, expected))) return true;
|
if (math.isNan(result) and math.isNan(@as(f80, @bitCast(expected)))) return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -25,9 +25,9 @@ fn test__divxf3(a: f80, b: f80) !void {
|
|||||||
const x = __divxf3(a, b);
|
const x = __divxf3(a, b);
|
||||||
|
|
||||||
// Next float (assuming normal, non-zero result)
|
// Next float (assuming normal, non-zero result)
|
||||||
const x_plus_eps = @bitCast(f80, (@bitCast(u80, x) + 1) | integerBit);
|
const x_plus_eps = @as(f80, @bitCast((@as(u80, @bitCast(x)) + 1) | integerBit));
|
||||||
// Prev float (assuming normal, non-zero result)
|
// Prev float (assuming normal, non-zero result)
|
||||||
const x_minus_eps = @bitCast(f80, (@bitCast(u80, x) - 1) | integerBit);
|
const x_minus_eps = @as(f80, @bitCast((@as(u80, @bitCast(x)) - 1) | integerBit));
|
||||||
|
|
||||||
// Make sure result is more accurate than the adjacent floats
|
// Make sure result is more accurate than the adjacent floats
|
||||||
const err_x = @fabs(@mulAdd(f80, x, b, -a));
|
const err_x = @fabs(@mulAdd(f80, x, b, -a));
|
||||||
|
|||||||
@ -33,18 +33,14 @@ pub fn __emutls_get_address(control: *emutls_control) callconv(.C) *anyopaque {
|
|||||||
const simple_allocator = struct {
|
const simple_allocator = struct {
|
||||||
/// Allocate a memory chunk for requested type. Return a pointer on the data.
|
/// Allocate a memory chunk for requested type. Return a pointer on the data.
|
||||||
pub fn alloc(comptime T: type) *T {
|
pub fn alloc(comptime T: type) *T {
|
||||||
return @ptrCast(*T, @alignCast(
|
return @ptrCast(@alignCast(advancedAlloc(@alignOf(T), @sizeOf(T))));
|
||||||
@alignOf(T),
|
|
||||||
advancedAlloc(@alignOf(T), @sizeOf(T)),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate a slice of T, with len elements.
|
/// Allocate a slice of T, with len elements.
|
||||||
pub fn allocSlice(comptime T: type, len: usize) []T {
|
pub fn allocSlice(comptime T: type, len: usize) []T {
|
||||||
return @ptrCast([*]T, @alignCast(
|
return @as([*]T, @ptrCast(@alignCast(
|
||||||
@alignOf(T),
|
|
||||||
advancedAlloc(@alignOf(T), @sizeOf(T) * len),
|
advancedAlloc(@alignOf(T), @sizeOf(T) * len),
|
||||||
))[0 .. len - 1];
|
)))[0 .. len - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate a memory chunk.
|
/// Allocate a memory chunk.
|
||||||
@ -56,22 +52,19 @@ const simple_allocator = struct {
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return @ptrCast([*]u8, aligned_ptr);
|
return @as([*]u8, @ptrCast(aligned_ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resize a slice.
|
/// Resize a slice.
|
||||||
pub fn reallocSlice(comptime T: type, slice: []T, len: usize) []T {
|
pub fn reallocSlice(comptime T: type, slice: []T, len: usize) []T {
|
||||||
var c_ptr: *anyopaque = @ptrCast(*anyopaque, slice.ptr);
|
var c_ptr: *anyopaque = @as(*anyopaque, @ptrCast(slice.ptr));
|
||||||
var new_array: [*]T = @ptrCast([*]T, @alignCast(
|
var new_array: [*]T = @ptrCast(@alignCast(std.c.realloc(c_ptr, @sizeOf(T) * len) orelse abort()));
|
||||||
@alignOf(T),
|
|
||||||
std.c.realloc(c_ptr, @sizeOf(T) * len) orelse abort(),
|
|
||||||
));
|
|
||||||
return new_array[0..len];
|
return new_array[0..len];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Free a memory chunk allocated with simple_allocator.
|
/// Free a memory chunk allocated with simple_allocator.
|
||||||
pub fn free(ptr: anytype) void {
|
pub fn free(ptr: anytype) void {
|
||||||
std.c.free(@ptrCast(*anyopaque, ptr));
|
std.c.free(@as(*anyopaque, @ptrCast(ptr)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -132,20 +125,20 @@ const ObjectArray = struct {
|
|||||||
if (self.slots[index] == null) {
|
if (self.slots[index] == null) {
|
||||||
// initialize the slot
|
// initialize the slot
|
||||||
const size = control.size;
|
const size = control.size;
|
||||||
const alignment = @truncate(u29, control.alignment);
|
const alignment = @as(u29, @truncate(control.alignment));
|
||||||
|
|
||||||
var data = simple_allocator.advancedAlloc(alignment, size);
|
var data = simple_allocator.advancedAlloc(alignment, size);
|
||||||
errdefer simple_allocator.free(data);
|
errdefer simple_allocator.free(data);
|
||||||
|
|
||||||
if (control.default_value) |value| {
|
if (control.default_value) |value| {
|
||||||
// default value: copy the content to newly allocated object.
|
// default value: copy the content to newly allocated object.
|
||||||
@memcpy(data[0..size], @ptrCast([*]const u8, value));
|
@memcpy(data[0..size], @as([*]const u8, @ptrCast(value)));
|
||||||
} else {
|
} else {
|
||||||
// no default: return zeroed memory.
|
// no default: return zeroed memory.
|
||||||
@memset(data[0..size], 0);
|
@memset(data[0..size], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.slots[index] = @ptrCast(*anyopaque, data);
|
self.slots[index] = @as(*anyopaque, @ptrCast(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.slots[index].?;
|
return self.slots[index].?;
|
||||||
@ -180,18 +173,12 @@ const current_thread_storage = struct {
|
|||||||
|
|
||||||
/// Return casted thread specific value.
|
/// Return casted thread specific value.
|
||||||
fn getspecific() ?*ObjectArray {
|
fn getspecific() ?*ObjectArray {
|
||||||
return @ptrCast(
|
return @ptrCast(@alignCast(std.c.pthread_getspecific(current_thread_storage.key)));
|
||||||
?*ObjectArray,
|
|
||||||
@alignCast(
|
|
||||||
@alignOf(ObjectArray),
|
|
||||||
std.c.pthread_getspecific(current_thread_storage.key),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set casted thread specific value.
|
/// Set casted thread specific value.
|
||||||
fn setspecific(new: ?*ObjectArray) void {
|
fn setspecific(new: ?*ObjectArray) void {
|
||||||
if (std.c.pthread_setspecific(current_thread_storage.key, @ptrCast(*anyopaque, new)) != 0) {
|
if (std.c.pthread_setspecific(current_thread_storage.key, @as(*anyopaque, @ptrCast(new))) != 0) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,10 +192,7 @@ const current_thread_storage = struct {
|
|||||||
|
|
||||||
/// Invoked by pthread specific destructor. the passed argument is the ObjectArray pointer.
|
/// Invoked by pthread specific destructor. the passed argument is the ObjectArray pointer.
|
||||||
fn deinit(arrayPtr: *anyopaque) callconv(.C) void {
|
fn deinit(arrayPtr: *anyopaque) callconv(.C) void {
|
||||||
var array = @ptrCast(
|
var array: *ObjectArray = @ptrCast(@alignCast(arrayPtr));
|
||||||
*ObjectArray,
|
|
||||||
@alignCast(@alignOf(ObjectArray), arrayPtr),
|
|
||||||
);
|
|
||||||
array.deinit();
|
array.deinit();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -294,7 +278,7 @@ const emutls_control = extern struct {
|
|||||||
.size = @sizeOf(T),
|
.size = @sizeOf(T),
|
||||||
.alignment = @alignOf(T),
|
.alignment = @alignOf(T),
|
||||||
.object = .{ .index = 0 },
|
.object = .{ .index = 0 },
|
||||||
.default_value = @ptrCast(?*const anyopaque, default_value),
|
.default_value = @as(?*const anyopaque, @ptrCast(default_value)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,10 +297,7 @@ const emutls_control = extern struct {
|
|||||||
pub fn get_typed_pointer(self: *emutls_control, comptime T: type) *T {
|
pub fn get_typed_pointer(self: *emutls_control, comptime T: type) *T {
|
||||||
assert(self.size == @sizeOf(T));
|
assert(self.size == @sizeOf(T));
|
||||||
assert(self.alignment == @alignOf(T));
|
assert(self.alignment == @alignOf(T));
|
||||||
return @ptrCast(
|
return @ptrCast(@alignCast(self.getPointer()));
|
||||||
*T,
|
|
||||||
@alignCast(@alignOf(T), self.getPointer()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -343,7 +324,7 @@ test "__emutls_get_address zeroed" {
|
|||||||
try expect(ctl.object.index == 0);
|
try expect(ctl.object.index == 0);
|
||||||
|
|
||||||
// retrieve a variable from ctl
|
// retrieve a variable from ctl
|
||||||
var x = @ptrCast(*usize, @alignCast(@alignOf(usize), __emutls_get_address(&ctl)));
|
var x: *usize = @ptrCast(@alignCast(__emutls_get_address(&ctl)));
|
||||||
try expect(ctl.object.index != 0); // index has been allocated for this ctl
|
try expect(ctl.object.index != 0); // index has been allocated for this ctl
|
||||||
try expect(x.* == 0); // storage has been zeroed
|
try expect(x.* == 0); // storage has been zeroed
|
||||||
|
|
||||||
@ -351,7 +332,7 @@ test "__emutls_get_address zeroed" {
|
|||||||
x.* = 1234;
|
x.* = 1234;
|
||||||
|
|
||||||
// retrieve a variable from ctl (same ctl)
|
// retrieve a variable from ctl (same ctl)
|
||||||
var y = @ptrCast(*usize, @alignCast(@alignOf(usize), __emutls_get_address(&ctl)));
|
var y: *usize = @ptrCast(@alignCast(__emutls_get_address(&ctl)));
|
||||||
|
|
||||||
try expect(y.* == 1234); // same content that x.*
|
try expect(y.* == 1234); // same content that x.*
|
||||||
try expect(x == y); // same pointer
|
try expect(x == y); // same pointer
|
||||||
@ -364,7 +345,7 @@ test "__emutls_get_address with default_value" {
|
|||||||
var ctl = emutls_control.init(usize, &value);
|
var ctl = emutls_control.init(usize, &value);
|
||||||
try expect(ctl.object.index == 0);
|
try expect(ctl.object.index == 0);
|
||||||
|
|
||||||
var x: *usize = @ptrCast(*usize, @alignCast(@alignOf(usize), __emutls_get_address(&ctl)));
|
var x: *usize = @ptrCast(@alignCast(__emutls_get_address(&ctl)));
|
||||||
try expect(ctl.object.index != 0);
|
try expect(ctl.object.index != 0);
|
||||||
try expect(x.* == 5678); // storage initialized with default value
|
try expect(x.* == 5678); // storage initialized with default value
|
||||||
|
|
||||||
@ -373,7 +354,7 @@ test "__emutls_get_address with default_value" {
|
|||||||
|
|
||||||
try expect(value == 5678); // the default value didn't change
|
try expect(value == 5678); // the default value didn't change
|
||||||
|
|
||||||
var y = @ptrCast(*usize, @alignCast(@alignOf(usize), __emutls_get_address(&ctl)));
|
var y: *usize = @ptrCast(@alignCast(__emutls_get_address(&ctl)));
|
||||||
try expect(y.* == 9012); // the modified storage persists
|
try expect(y.* == 9012); // the modified storage persists
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ comptime {
|
|||||||
|
|
||||||
pub fn __exph(a: f16) callconv(.C) f16 {
|
pub fn __exph(a: f16) callconv(.C) f16 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f16, expf(a));
|
return @as(f16, @floatCast(expf(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expf(x_: f32) callconv(.C) f32 {
|
pub fn expf(x_: f32) callconv(.C) f32 {
|
||||||
@ -39,8 +39,8 @@ pub fn expf(x_: f32) callconv(.C) f32 {
|
|||||||
const P2 = -2.7667332906e-3;
|
const P2 = -2.7667332906e-3;
|
||||||
|
|
||||||
var x = x_;
|
var x = x_;
|
||||||
var hx = @bitCast(u32, x);
|
var hx = @as(u32, @bitCast(x));
|
||||||
const sign = @intCast(i32, hx >> 31);
|
const sign = @as(i32, @intCast(hx >> 31));
|
||||||
hx &= 0x7FFFFFFF;
|
hx &= 0x7FFFFFFF;
|
||||||
|
|
||||||
if (math.isNan(x)) {
|
if (math.isNan(x)) {
|
||||||
@ -74,12 +74,12 @@ pub fn expf(x_: f32) callconv(.C) f32 {
|
|||||||
if (hx > 0x3EB17218) {
|
if (hx > 0x3EB17218) {
|
||||||
// |x| > 1.5 * ln2
|
// |x| > 1.5 * ln2
|
||||||
if (hx > 0x3F851592) {
|
if (hx > 0x3F851592) {
|
||||||
k = @intFromFloat(i32, invln2 * x + half[@intCast(usize, sign)]);
|
k = @as(i32, @intFromFloat(invln2 * x + half[@as(usize, @intCast(sign))]));
|
||||||
} else {
|
} else {
|
||||||
k = 1 - sign - sign;
|
k = 1 - sign - sign;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fk = @floatFromInt(f32, k);
|
const fk = @as(f32, @floatFromInt(k));
|
||||||
hi = x - fk * ln2hi;
|
hi = x - fk * ln2hi;
|
||||||
lo = fk * ln2lo;
|
lo = fk * ln2lo;
|
||||||
x = hi - lo;
|
x = hi - lo;
|
||||||
@ -117,9 +117,9 @@ pub fn exp(x_: f64) callconv(.C) f64 {
|
|||||||
const P5: f64 = 4.13813679705723846039e-08;
|
const P5: f64 = 4.13813679705723846039e-08;
|
||||||
|
|
||||||
var x = x_;
|
var x = x_;
|
||||||
var ux = @bitCast(u64, x);
|
var ux = @as(u64, @bitCast(x));
|
||||||
var hx = ux >> 32;
|
var hx = ux >> 32;
|
||||||
const sign = @intCast(i32, hx >> 31);
|
const sign = @as(i32, @intCast(hx >> 31));
|
||||||
hx &= 0x7FFFFFFF;
|
hx &= 0x7FFFFFFF;
|
||||||
|
|
||||||
if (math.isNan(x)) {
|
if (math.isNan(x)) {
|
||||||
@ -157,12 +157,12 @@ pub fn exp(x_: f64) callconv(.C) f64 {
|
|||||||
if (hx > 0x3FD62E42) {
|
if (hx > 0x3FD62E42) {
|
||||||
// |x| >= 1.5 * ln2
|
// |x| >= 1.5 * ln2
|
||||||
if (hx > 0x3FF0A2B2) {
|
if (hx > 0x3FF0A2B2) {
|
||||||
k = @intFromFloat(i32, invln2 * x + half[@intCast(usize, sign)]);
|
k = @as(i32, @intFromFloat(invln2 * x + half[@as(usize, @intCast(sign))]));
|
||||||
} else {
|
} else {
|
||||||
k = 1 - sign - sign;
|
k = 1 - sign - sign;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dk = @floatFromInt(f64, k);
|
const dk = @as(f64, @floatFromInt(k));
|
||||||
hi = x - dk * ln2hi;
|
hi = x - dk * ln2hi;
|
||||||
lo = dk * ln2lo;
|
lo = dk * ln2lo;
|
||||||
x = hi - lo;
|
x = hi - lo;
|
||||||
@ -191,12 +191,12 @@ pub fn exp(x_: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
pub fn __expx(a: f80) callconv(.C) f80 {
|
pub fn __expx(a: f80) callconv(.C) f80 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f80, expq(a));
|
return @as(f80, @floatCast(expq(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expq(a: f128) callconv(.C) f128 {
|
pub fn expq(a: f128) callconv(.C) f128 {
|
||||||
// TODO: more correct implementation
|
// TODO: more correct implementation
|
||||||
return exp(@floatCast(f64, a));
|
return exp(@as(f64, @floatCast(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expl(x: c_longdouble) callconv(.C) c_longdouble {
|
pub fn expl(x: c_longdouble) callconv(.C) c_longdouble {
|
||||||
|
|||||||
@ -27,18 +27,18 @@ comptime {
|
|||||||
|
|
||||||
pub fn __exp2h(x: f16) callconv(.C) f16 {
|
pub fn __exp2h(x: f16) callconv(.C) f16 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f16, exp2f(x));
|
return @as(f16, @floatCast(exp2f(x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exp2f(x: f32) callconv(.C) f32 {
|
pub fn exp2f(x: f32) callconv(.C) f32 {
|
||||||
const tblsiz = @intCast(u32, exp2ft.len);
|
const tblsiz = @as(u32, @intCast(exp2ft.len));
|
||||||
const redux: f32 = 0x1.8p23 / @floatFromInt(f32, tblsiz);
|
const redux: f32 = 0x1.8p23 / @as(f32, @floatFromInt(tblsiz));
|
||||||
const P1: f32 = 0x1.62e430p-1;
|
const P1: f32 = 0x1.62e430p-1;
|
||||||
const P2: f32 = 0x1.ebfbe0p-3;
|
const P2: f32 = 0x1.ebfbe0p-3;
|
||||||
const P3: f32 = 0x1.c6b348p-5;
|
const P3: f32 = 0x1.c6b348p-5;
|
||||||
const P4: f32 = 0x1.3b2c9cp-7;
|
const P4: f32 = 0x1.3b2c9cp-7;
|
||||||
|
|
||||||
var u = @bitCast(u32, x);
|
var u = @as(u32, @bitCast(x));
|
||||||
const ix = u & 0x7FFFFFFF;
|
const ix = u & 0x7FFFFFFF;
|
||||||
|
|
||||||
// |x| > 126
|
// |x| > 126
|
||||||
@ -72,32 +72,32 @@ pub fn exp2f(x: f32) callconv(.C) f32 {
|
|||||||
// intended result but should confirm how GCC/Clang handle this to ensure.
|
// intended result but should confirm how GCC/Clang handle this to ensure.
|
||||||
|
|
||||||
var uf = x + redux;
|
var uf = x + redux;
|
||||||
var i_0 = @bitCast(u32, uf);
|
var i_0 = @as(u32, @bitCast(uf));
|
||||||
i_0 +%= tblsiz / 2;
|
i_0 +%= tblsiz / 2;
|
||||||
|
|
||||||
const k = i_0 / tblsiz;
|
const k = i_0 / tblsiz;
|
||||||
const uk = @bitCast(f64, @as(u64, 0x3FF + k) << 52);
|
const uk = @as(f64, @bitCast(@as(u64, 0x3FF + k) << 52));
|
||||||
i_0 &= tblsiz - 1;
|
i_0 &= tblsiz - 1;
|
||||||
uf -= redux;
|
uf -= redux;
|
||||||
|
|
||||||
const z: f64 = x - uf;
|
const z: f64 = x - uf;
|
||||||
var r: f64 = exp2ft[@intCast(usize, i_0)];
|
var r: f64 = exp2ft[@as(usize, @intCast(i_0))];
|
||||||
const t: f64 = r * z;
|
const t: f64 = r * z;
|
||||||
r = r + t * (P1 + z * P2) + t * (z * z) * (P3 + z * P4);
|
r = r + t * (P1 + z * P2) + t * (z * z) * (P3 + z * P4);
|
||||||
return @floatCast(f32, r * uk);
|
return @as(f32, @floatCast(r * uk));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exp2(x: f64) callconv(.C) f64 {
|
pub fn exp2(x: f64) callconv(.C) f64 {
|
||||||
const tblsiz: u32 = @intCast(u32, exp2dt.len / 2);
|
const tblsiz: u32 = @as(u32, @intCast(exp2dt.len / 2));
|
||||||
const redux: f64 = 0x1.8p52 / @floatFromInt(f64, tblsiz);
|
const redux: f64 = 0x1.8p52 / @as(f64, @floatFromInt(tblsiz));
|
||||||
const P1: f64 = 0x1.62e42fefa39efp-1;
|
const P1: f64 = 0x1.62e42fefa39efp-1;
|
||||||
const P2: f64 = 0x1.ebfbdff82c575p-3;
|
const P2: f64 = 0x1.ebfbdff82c575p-3;
|
||||||
const P3: f64 = 0x1.c6b08d704a0a6p-5;
|
const P3: f64 = 0x1.c6b08d704a0a6p-5;
|
||||||
const P4: f64 = 0x1.3b2ab88f70400p-7;
|
const P4: f64 = 0x1.3b2ab88f70400p-7;
|
||||||
const P5: f64 = 0x1.5d88003875c74p-10;
|
const P5: f64 = 0x1.5d88003875c74p-10;
|
||||||
|
|
||||||
const ux = @bitCast(u64, x);
|
const ux = @as(u64, @bitCast(x));
|
||||||
const ix = @intCast(u32, ux >> 32) & 0x7FFFFFFF;
|
const ix = @as(u32, @intCast(ux >> 32)) & 0x7FFFFFFF;
|
||||||
|
|
||||||
// TODO: This should be handled beneath.
|
// TODO: This should be handled beneath.
|
||||||
if (math.isNan(x)) {
|
if (math.isNan(x)) {
|
||||||
@ -119,7 +119,7 @@ pub fn exp2(x: f64) callconv(.C) f64 {
|
|||||||
if (ux >> 63 != 0) {
|
if (ux >> 63 != 0) {
|
||||||
// underflow
|
// underflow
|
||||||
if (x <= -1075 or x - 0x1.0p52 + 0x1.0p52 != x) {
|
if (x <= -1075 or x - 0x1.0p52 + 0x1.0p52 != x) {
|
||||||
math.doNotOptimizeAway(@floatCast(f32, -0x1.0p-149 / x));
|
math.doNotOptimizeAway(@as(f32, @floatCast(-0x1.0p-149 / x)));
|
||||||
}
|
}
|
||||||
if (x <= -1075) {
|
if (x <= -1075) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -139,18 +139,18 @@ pub fn exp2(x: f64) callconv(.C) f64 {
|
|||||||
// reduce x
|
// reduce x
|
||||||
var uf: f64 = x + redux;
|
var uf: f64 = x + redux;
|
||||||
// NOTE: musl performs an implicit 64-bit to 32-bit u32 truncation here
|
// NOTE: musl performs an implicit 64-bit to 32-bit u32 truncation here
|
||||||
var i_0: u32 = @truncate(u32, @bitCast(u64, uf));
|
var i_0: u32 = @as(u32, @truncate(@as(u64, @bitCast(uf))));
|
||||||
i_0 +%= tblsiz / 2;
|
i_0 +%= tblsiz / 2;
|
||||||
|
|
||||||
const k: u32 = i_0 / tblsiz * tblsiz;
|
const k: u32 = i_0 / tblsiz * tblsiz;
|
||||||
const ik: i32 = @divTrunc(@bitCast(i32, k), tblsiz);
|
const ik: i32 = @divTrunc(@as(i32, @bitCast(k)), tblsiz);
|
||||||
i_0 %= tblsiz;
|
i_0 %= tblsiz;
|
||||||
uf -= redux;
|
uf -= redux;
|
||||||
|
|
||||||
// r = exp2(y) = exp2t[i_0] * p(z - eps[i])
|
// r = exp2(y) = exp2t[i_0] * p(z - eps[i])
|
||||||
var z: f64 = x - uf;
|
var z: f64 = x - uf;
|
||||||
const t: f64 = exp2dt[@intCast(usize, 2 * i_0)];
|
const t: f64 = exp2dt[@as(usize, @intCast(2 * i_0))];
|
||||||
z -= exp2dt[@intCast(usize, 2 * i_0 + 1)];
|
z -= exp2dt[@as(usize, @intCast(2 * i_0 + 1))];
|
||||||
const r: f64 = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));
|
const r: f64 = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));
|
||||||
|
|
||||||
return math.scalbn(r, ik);
|
return math.scalbn(r, ik);
|
||||||
@ -158,12 +158,12 @@ pub fn exp2(x: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
pub fn __exp2x(x: f80) callconv(.C) f80 {
|
pub fn __exp2x(x: f80) callconv(.C) f80 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f80, exp2q(x));
|
return @as(f80, @floatCast(exp2q(x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exp2q(x: f128) callconv(.C) f128 {
|
pub fn exp2q(x: f128) callconv(.C) f128 {
|
||||||
// TODO: more correct implementation
|
// TODO: more correct implementation
|
||||||
return exp2(@floatCast(f64, x));
|
return exp2(@as(f64, @floatCast(x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exp2l(x: c_longdouble) callconv(.C) c_longdouble {
|
pub fn exp2l(x: c_longdouble) callconv(.C) c_longdouble {
|
||||||
|
|||||||
@ -13,9 +13,9 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __extenddftf2(a: f64) callconv(.C) f128 {
|
pub fn __extenddftf2(a: f64) callconv(.C) f128 {
|
||||||
return extendf(f128, f64, @bitCast(u64, a));
|
return extendf(f128, f64, @as(u64, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _Qp_dtoq(c: *f128, a: f64) callconv(.C) void {
|
fn _Qp_dtoq(c: *f128, a: f64) callconv(.C) void {
|
||||||
c.* = extendf(f128, f64, @bitCast(u64, a));
|
c.* = extendf(f128, f64, @as(u64, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,5 +8,5 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __extenddfxf2(a: f64) callconv(.C) f80 {
|
pub fn __extenddfxf2(a: f64) callconv(.C) f80 {
|
||||||
return extend_f80(f64, @bitCast(u64, a));
|
return extend_f80(f64, @as(u64, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,7 @@ pub inline fn extendf(
|
|||||||
const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits;
|
const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits;
|
||||||
|
|
||||||
// Break a into a sign and representation of the absolute value
|
// Break a into a sign and representation of the absolute value
|
||||||
const aRep: src_rep_t = @bitCast(src_rep_t, a);
|
const aRep: src_rep_t = @as(src_rep_t, @bitCast(a));
|
||||||
const aAbs: src_rep_t = aRep & srcAbsMask;
|
const aAbs: src_rep_t = aRep & srcAbsMask;
|
||||||
const sign: src_rep_t = aRep & srcSignMask;
|
const sign: src_rep_t = aRep & srcSignMask;
|
||||||
var absResult: dst_rep_t = undefined;
|
var absResult: dst_rep_t = undefined;
|
||||||
@ -58,10 +58,10 @@ pub inline fn extendf(
|
|||||||
// the correct adjusted exponent in the destination type.
|
// the correct adjusted exponent in the destination type.
|
||||||
const scale: u32 = @clz(aAbs) -
|
const scale: u32 = @clz(aAbs) -
|
||||||
@clz(@as(src_rep_t, srcMinNormal));
|
@clz(@as(src_rep_t, srcMinNormal));
|
||||||
absResult = @as(dst_rep_t, aAbs) << @intCast(DstShift, dstSigBits - srcSigBits + scale);
|
absResult = @as(dst_rep_t, aAbs) << @as(DstShift, @intCast(dstSigBits - srcSigBits + scale));
|
||||||
absResult ^= dstMinNormal;
|
absResult ^= dstMinNormal;
|
||||||
const resultExponent: u32 = dstExpBias - srcExpBias - scale + 1;
|
const resultExponent: u32 = dstExpBias - srcExpBias - scale + 1;
|
||||||
absResult |= @intCast(dst_rep_t, resultExponent) << dstSigBits;
|
absResult |= @as(dst_rep_t, @intCast(resultExponent)) << dstSigBits;
|
||||||
} else {
|
} else {
|
||||||
// a is zero.
|
// a is zero.
|
||||||
absResult = 0;
|
absResult = 0;
|
||||||
@ -69,7 +69,7 @@ pub inline fn extendf(
|
|||||||
|
|
||||||
// Apply the signbit to (dst_t)abs(a).
|
// Apply the signbit to (dst_t)abs(a).
|
||||||
const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits);
|
const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits);
|
||||||
return @bitCast(dst_t, result);
|
return @as(dst_t, @bitCast(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn extend_f80(comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) f80 {
|
pub inline fn extend_f80(comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) f80 {
|
||||||
@ -104,7 +104,7 @@ pub inline fn extend_f80(comptime src_t: type, a: std.meta.Int(.unsigned, @typeI
|
|||||||
// a is a normal number.
|
// a is a normal number.
|
||||||
// Extend to the destination type by shifting the significand and
|
// Extend to the destination type by shifting the significand and
|
||||||
// exponent into the proper position and rebiasing the exponent.
|
// exponent into the proper position and rebiasing the exponent.
|
||||||
dst.exp = @intCast(u16, a_abs >> src_sig_bits);
|
dst.exp = @as(u16, @intCast(a_abs >> src_sig_bits));
|
||||||
dst.exp += dst_exp_bias - src_exp_bias;
|
dst.exp += dst_exp_bias - src_exp_bias;
|
||||||
dst.fraction = @as(u64, a_abs) << (dst_sig_bits - src_sig_bits);
|
dst.fraction = @as(u64, a_abs) << (dst_sig_bits - src_sig_bits);
|
||||||
dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers
|
dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers
|
||||||
@ -124,9 +124,9 @@ pub inline fn extend_f80(comptime src_t: type, a: std.meta.Int(.unsigned, @typeI
|
|||||||
const scale: u16 = @clz(a_abs) -
|
const scale: u16 = @clz(a_abs) -
|
||||||
@clz(@as(src_rep_t, src_min_normal));
|
@clz(@as(src_rep_t, src_min_normal));
|
||||||
|
|
||||||
dst.fraction = @as(u64, a_abs) << @intCast(u6, dst_sig_bits - src_sig_bits + scale);
|
dst.fraction = @as(u64, a_abs) << @as(u6, @intCast(dst_sig_bits - src_sig_bits + scale));
|
||||||
dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers
|
dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers
|
||||||
dst.exp = @truncate(u16, a_abs >> @intCast(SrcShift, src_sig_bits - scale));
|
dst.exp = @as(u16, @truncate(a_abs >> @as(SrcShift, @intCast(src_sig_bits - scale))));
|
||||||
dst.exp ^= 1;
|
dst.exp ^= 1;
|
||||||
dst.exp |= dst_exp_bias - src_exp_bias - scale + 1;
|
dst.exp |= dst_exp_bias - src_exp_bias - scale + 1;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -11,12 +11,12 @@ const F16T = @import("./common.zig").F16T;
|
|||||||
fn test__extenddfxf2(a: f64, expected: u80) !void {
|
fn test__extenddfxf2(a: f64, expected: u80) !void {
|
||||||
const x = __extenddfxf2(a);
|
const x = __extenddfxf2(a);
|
||||||
|
|
||||||
const rep = @bitCast(u80, x);
|
const rep = @as(u80, @bitCast(x));
|
||||||
if (rep == expected)
|
if (rep == expected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// test other possible NaN representation(signal NaN)
|
// test other possible NaN representation(signal NaN)
|
||||||
if (math.isNan(@bitCast(f80, expected)) and math.isNan(x))
|
if (math.isNan(@as(f80, @bitCast(expected))) and math.isNan(x))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@panic("__extenddfxf2 test failure");
|
@panic("__extenddfxf2 test failure");
|
||||||
@ -25,9 +25,9 @@ fn test__extenddfxf2(a: f64, expected: u80) !void {
|
|||||||
fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
|
fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
|
||||||
const x = __extenddftf2(a);
|
const x = __extenddftf2(a);
|
||||||
|
|
||||||
const rep = @bitCast(u128, x);
|
const rep = @as(u128, @bitCast(x));
|
||||||
const hi = @intCast(u64, rep >> 64);
|
const hi = @as(u64, @intCast(rep >> 64));
|
||||||
const lo = @truncate(u64, rep);
|
const lo = @as(u64, @truncate(rep));
|
||||||
|
|
||||||
if (hi == expected_hi and lo == expected_lo)
|
if (hi == expected_hi and lo == expected_lo)
|
||||||
return;
|
return;
|
||||||
@ -45,14 +45,14 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test__extendhfsf2(a: u16, expected: u32) !void {
|
fn test__extendhfsf2(a: u16, expected: u32) !void {
|
||||||
const x = __extendhfsf2(@bitCast(F16T(f32), a));
|
const x = __extendhfsf2(@as(F16T(f32), @bitCast(a)));
|
||||||
const rep = @bitCast(u32, x);
|
const rep = @as(u32, @bitCast(x));
|
||||||
|
|
||||||
if (rep == expected) {
|
if (rep == expected) {
|
||||||
if (rep & 0x7fffffff > 0x7f800000) {
|
if (rep & 0x7fffffff > 0x7f800000) {
|
||||||
return; // NaN is always unequal.
|
return; // NaN is always unequal.
|
||||||
}
|
}
|
||||||
if (x == @bitCast(f32, expected)) {
|
if (x == @as(f32, @bitCast(expected))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,9 +63,9 @@ fn test__extendhfsf2(a: u16, expected: u32) !void {
|
|||||||
fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {
|
fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void {
|
||||||
const x = __extendsftf2(a);
|
const x = __extendsftf2(a);
|
||||||
|
|
||||||
const rep = @bitCast(u128, x);
|
const rep = @as(u128, @bitCast(x));
|
||||||
const hi = @intCast(u64, rep >> 64);
|
const hi = @as(u64, @intCast(rep >> 64));
|
||||||
const lo = @truncate(u64, rep);
|
const lo = @as(u64, @truncate(rep));
|
||||||
|
|
||||||
if (hi == expected_hi and lo == expected_lo)
|
if (hi == expected_hi and lo == expected_lo)
|
||||||
return;
|
return;
|
||||||
@ -184,35 +184,35 @@ test "extendsftf2" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn makeQNaN64() f64 {
|
fn makeQNaN64() f64 {
|
||||||
return @bitCast(f64, @as(u64, 0x7ff8000000000000));
|
return @as(f64, @bitCast(@as(u64, 0x7ff8000000000000)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeInf64() f64 {
|
fn makeInf64() f64 {
|
||||||
return @bitCast(f64, @as(u64, 0x7ff0000000000000));
|
return @as(f64, @bitCast(@as(u64, 0x7ff0000000000000)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeNaN64(rand: u64) f64 {
|
fn makeNaN64(rand: u64) f64 {
|
||||||
return @bitCast(f64, 0x7ff0000000000000 | (rand & 0xfffffffffffff));
|
return @as(f64, @bitCast(0x7ff0000000000000 | (rand & 0xfffffffffffff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeQNaN32() f32 {
|
fn makeQNaN32() f32 {
|
||||||
return @bitCast(f32, @as(u32, 0x7fc00000));
|
return @as(f32, @bitCast(@as(u32, 0x7fc00000)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeNaN32(rand: u32) f32 {
|
fn makeNaN32(rand: u32) f32 {
|
||||||
return @bitCast(f32, 0x7f800000 | (rand & 0x7fffff));
|
return @as(f32, @bitCast(0x7f800000 | (rand & 0x7fffff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn makeInf32() f32 {
|
fn makeInf32() f32 {
|
||||||
return @bitCast(f32, @as(u32, 0x7f800000));
|
return @as(f32, @bitCast(@as(u32, 0x7f800000)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void {
|
fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void {
|
||||||
const x = __extendhftf2(@bitCast(F16T(f128), a));
|
const x = __extendhftf2(@as(F16T(f128), @bitCast(a)));
|
||||||
|
|
||||||
const rep = @bitCast(u128, x);
|
const rep = @as(u128, @bitCast(x));
|
||||||
const hi = @intCast(u64, rep >> 64);
|
const hi = @as(u64, @intCast(rep >> 64));
|
||||||
const lo = @truncate(u64, rep);
|
const lo = @as(u64, @truncate(rep));
|
||||||
|
|
||||||
if (hi == expected_hi and lo == expected_lo)
|
if (hi == expected_hi and lo == expected_lo)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -8,5 +8,5 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __extendhfdf2(a: common.F16T(f64)) callconv(.C) f64 {
|
pub fn __extendhfdf2(a: common.F16T(f64)) callconv(.C) f64 {
|
||||||
return extendf(f64, f16, @bitCast(u16, a));
|
return extendf(f64, f16, @as(u16, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,13 +13,13 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __extendhfsf2(a: common.F16T(f32)) callconv(.C) f32 {
|
pub fn __extendhfsf2(a: common.F16T(f32)) callconv(.C) f32 {
|
||||||
return extendf(f32, f16, @bitCast(u16, a));
|
return extendf(f32, f16, @as(u16, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __gnu_h2f_ieee(a: common.F16T(f32)) callconv(.C) f32 {
|
fn __gnu_h2f_ieee(a: common.F16T(f32)) callconv(.C) f32 {
|
||||||
return extendf(f32, f16, @bitCast(u16, a));
|
return extendf(f32, f16, @as(u16, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __aeabi_h2f(a: u16) callconv(.AAPCS) f32 {
|
fn __aeabi_h2f(a: u16) callconv(.AAPCS) f32 {
|
||||||
return extendf(f32, f16, @bitCast(u16, a));
|
return extendf(f32, f16, @as(u16, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,5 +8,5 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __extendhftf2(a: common.F16T(f128)) callconv(.C) f128 {
|
pub fn __extendhftf2(a: common.F16T(f128)) callconv(.C) f128 {
|
||||||
return extendf(f128, f16, @bitCast(u16, a));
|
return extendf(f128, f16, @as(u16, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,5 +8,5 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __extendhfxf2(a: common.F16T(f80)) callconv(.C) f80 {
|
fn __extendhfxf2(a: common.F16T(f80)) callconv(.C) f80 {
|
||||||
return extend_f80(f16, @bitCast(u16, a));
|
return extend_f80(f16, @as(u16, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,9 +12,9 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __extendsfdf2(a: f32) callconv(.C) f64 {
|
fn __extendsfdf2(a: f32) callconv(.C) f64 {
|
||||||
return extendf(f64, f32, @bitCast(u32, a));
|
return extendf(f64, f32, @as(u32, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __aeabi_f2d(a: f32) callconv(.AAPCS) f64 {
|
fn __aeabi_f2d(a: f32) callconv(.AAPCS) f64 {
|
||||||
return extendf(f64, f32, @bitCast(u32, a));
|
return extendf(f64, f32, @as(u32, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,9 +13,9 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __extendsftf2(a: f32) callconv(.C) f128 {
|
pub fn __extendsftf2(a: f32) callconv(.C) f128 {
|
||||||
return extendf(f128, f32, @bitCast(u32, a));
|
return extendf(f128, f32, @as(u32, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _Qp_stoq(c: *f128, a: f32) callconv(.C) void {
|
fn _Qp_stoq(c: *f128, a: f32) callconv(.C) void {
|
||||||
c.* = extendf(f128, f32, @bitCast(u32, a));
|
c.* = extendf(f128, f32, @as(u32, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,5 +8,5 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __extendsfxf2(a: f32) callconv(.C) f80 {
|
fn __extendsfxf2(a: f32) callconv(.C) f80 {
|
||||||
return extend_f80(f32, @bitCast(u32, a));
|
return extend_f80(f32, @as(u32, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,12 +39,12 @@ fn __extendxftf2(a: f80) callconv(.C) f128 {
|
|||||||
// renormalize the significand and clear the leading bit and integer part,
|
// renormalize the significand and clear the leading bit and integer part,
|
||||||
// then insert the correct adjusted exponent in the destination type.
|
// then insert the correct adjusted exponent in the destination type.
|
||||||
const scale: u32 = @clz(a_rep.fraction);
|
const scale: u32 = @clz(a_rep.fraction);
|
||||||
abs_result = @as(u128, a_rep.fraction) << @intCast(u7, dst_sig_bits - src_sig_bits + scale + 1);
|
abs_result = @as(u128, a_rep.fraction) << @as(u7, @intCast(dst_sig_bits - src_sig_bits + scale + 1));
|
||||||
abs_result ^= dst_min_normal;
|
abs_result ^= dst_min_normal;
|
||||||
abs_result |= @as(u128, scale + 1) << dst_sig_bits;
|
abs_result |= @as(u128, scale + 1) << dst_sig_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the signbit to (dst_t)abs(a).
|
// Apply the signbit to (dst_t)abs(a).
|
||||||
const result: u128 align(@alignOf(f128)) = abs_result | @as(u128, sign) << (dst_bits - 16);
|
const result: u128 align(@alignOf(f128)) = abs_result | @as(u128, sign) << (dst_bits - 16);
|
||||||
return @bitCast(f128, result);
|
return @as(f128, @bitCast(result));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,7 +51,7 @@ pub fn fabsl(x: c_longdouble) callconv(.C) c_longdouble {
|
|||||||
inline fn generic_fabs(x: anytype) @TypeOf(x) {
|
inline fn generic_fabs(x: anytype) @TypeOf(x) {
|
||||||
const T = @TypeOf(x);
|
const T = @TypeOf(x);
|
||||||
const TBits = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
|
const TBits = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
|
||||||
const float_bits = @bitCast(TBits, x);
|
const float_bits = @as(TBits, @bitCast(x));
|
||||||
const remove_sign = ~@as(TBits, 0) >> 1;
|
const remove_sign = ~@as(TBits, 0) >> 1;
|
||||||
return @bitCast(T, float_bits & remove_sign);
|
return @as(T, @bitCast(float_bits & remove_sign));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ const ffs = @import("count0bits.zig");
|
|||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
fn test__ffsdi2(a: u64, expected: i32) !void {
|
fn test__ffsdi2(a: u64, expected: i32) !void {
|
||||||
var x = @bitCast(i64, a);
|
var x = @as(i64, @bitCast(a));
|
||||||
var result = ffs.__ffsdi2(x);
|
var result = ffs.__ffsdi2(x);
|
||||||
try testing.expectEqual(expected, result);
|
try testing.expectEqual(expected, result);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ const ffs = @import("count0bits.zig");
|
|||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
fn test__ffssi2(a: u32, expected: i32) !void {
|
fn test__ffssi2(a: u32, expected: i32) !void {
|
||||||
var x = @bitCast(i32, a);
|
var x = @as(i32, @bitCast(a));
|
||||||
var result = ffs.__ffssi2(x);
|
var result = ffs.__ffssi2(x);
|
||||||
try testing.expectEqual(expected, result);
|
try testing.expectEqual(expected, result);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ const ffs = @import("count0bits.zig");
|
|||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
fn test__ffsti2(a: u128, expected: i32) !void {
|
fn test__ffsti2(a: u128, expected: i32) !void {
|
||||||
var x = @bitCast(i128, a);
|
var x = @as(i128, @bitCast(a));
|
||||||
var result = ffs.__ffsti2(x);
|
var result = ffs.__ffsti2(x);
|
||||||
try testing.expectEqual(expected, result);
|
try testing.expectEqual(expected, result);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,5 @@ pub fn __fixdfti(a: f64) callconv(.C) i128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __fixdfti_windows_x86_64(a: f64) callconv(.C) v2u64 {
|
fn __fixdfti_windows_x86_64(a: f64) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, intFromFloat(i128, a));
|
return @as(v2u64, @bitCast(intFromFloat(i128, a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,5 @@ pub fn __fixhfti(a: f16) callconv(.C) i128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __fixhfti_windows_x86_64(a: f16) callconv(.C) v2u64 {
|
fn __fixhfti_windows_x86_64(a: f16) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, intFromFloat(i128, a));
|
return @as(v2u64, @bitCast(intFromFloat(i128, a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,5 @@ pub fn __fixsfti(a: f32) callconv(.C) i128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __fixsfti_windows_x86_64(a: f32) callconv(.C) v2u64 {
|
fn __fixsfti_windows_x86_64(a: f32) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, intFromFloat(i128, a));
|
return @as(v2u64, @bitCast(intFromFloat(i128, a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,5 +21,5 @@ pub fn __fixtfti(a: f128) callconv(.C) i128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __fixtfti_windows_x86_64(a: f128) callconv(.C) v2u64 {
|
fn __fixtfti_windows_x86_64(a: f128) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, intFromFloat(i128, a));
|
return @as(v2u64, @bitCast(intFromFloat(i128, a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,5 @@ pub fn __fixunsdfti(a: f64) callconv(.C) u128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __fixunsdfti_windows_x86_64(a: f64) callconv(.C) v2u64 {
|
fn __fixunsdfti_windows_x86_64(a: f64) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, intFromFloat(u128, a));
|
return @as(v2u64, @bitCast(intFromFloat(u128, a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,5 @@ pub fn __fixunshfti(a: f16) callconv(.C) u128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __fixunshfti_windows_x86_64(a: f16) callconv(.C) v2u64 {
|
fn __fixunshfti_windows_x86_64(a: f16) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, intFromFloat(u128, a));
|
return @as(v2u64, @bitCast(intFromFloat(u128, a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,5 @@ pub fn __fixunssfti(a: f32) callconv(.C) u128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __fixunssfti_windows_x86_64(a: f32) callconv(.C) v2u64 {
|
fn __fixunssfti_windows_x86_64(a: f32) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, intFromFloat(u128, a));
|
return @as(v2u64, @bitCast(intFromFloat(u128, a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,5 +21,5 @@ pub fn __fixunstfti(a: f128) callconv(.C) u128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __fixunstfti_windows_x86_64(a: f128) callconv(.C) v2u64 {
|
fn __fixunstfti_windows_x86_64(a: f128) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, intFromFloat(u128, a));
|
return @as(v2u64, @bitCast(intFromFloat(u128, a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,5 @@ pub fn __fixunsxfti(a: f80) callconv(.C) u128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __fixunsxfti_windows_x86_64(a: f80) callconv(.C) v2u64 {
|
fn __fixunsxfti_windows_x86_64(a: f80) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, intFromFloat(u128, a));
|
return @as(v2u64, @bitCast(intFromFloat(u128, a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,5 @@ pub fn __fixxfti(a: f80) callconv(.C) i128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __fixxfti_windows_x86_64(a: f80) callconv(.C) v2u64 {
|
fn __fixxfti_windows_x86_64(a: f80) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, intFromFloat(i128, a));
|
return @as(v2u64, @bitCast(intFromFloat(i128, a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,17 +25,17 @@ pub fn floatFromInt(comptime T: type, x: anytype) T {
|
|||||||
// Compute significand
|
// Compute significand
|
||||||
var exp = int_bits - @clz(abs_val) - 1;
|
var exp = int_bits - @clz(abs_val) - 1;
|
||||||
if (int_bits <= fractional_bits or exp <= fractional_bits) {
|
if (int_bits <= fractional_bits or exp <= fractional_bits) {
|
||||||
const shift_amt = fractional_bits - @intCast(math.Log2Int(uT), exp);
|
const shift_amt = fractional_bits - @as(math.Log2Int(uT), @intCast(exp));
|
||||||
|
|
||||||
// Shift up result to line up with the significand - no rounding required
|
// Shift up result to line up with the significand - no rounding required
|
||||||
result = (@intCast(uT, abs_val) << shift_amt);
|
result = (@as(uT, @intCast(abs_val)) << shift_amt);
|
||||||
result ^= implicit_bit; // Remove implicit integer bit
|
result ^= implicit_bit; // Remove implicit integer bit
|
||||||
} else {
|
} else {
|
||||||
var shift_amt = @intCast(math.Log2Int(Z), exp - fractional_bits);
|
var shift_amt = @as(math.Log2Int(Z), @intCast(exp - fractional_bits));
|
||||||
const exact_tie: bool = @ctz(abs_val) == shift_amt - 1;
|
const exact_tie: bool = @ctz(abs_val) == shift_amt - 1;
|
||||||
|
|
||||||
// Shift down result and remove implicit integer bit
|
// Shift down result and remove implicit integer bit
|
||||||
result = @intCast(uT, (abs_val >> (shift_amt - 1))) ^ (implicit_bit << 1);
|
result = @as(uT, @intCast((abs_val >> (shift_amt - 1)))) ^ (implicit_bit << 1);
|
||||||
|
|
||||||
// Round result, including round-to-even for exact ties
|
// Round result, including round-to-even for exact ties
|
||||||
result = ((result + 1) >> 1) & ~@as(uT, @intFromBool(exact_tie));
|
result = ((result + 1) >> 1) & ~@as(uT, @intFromBool(exact_tie));
|
||||||
@ -43,14 +43,14 @@ pub fn floatFromInt(comptime T: type, x: anytype) T {
|
|||||||
|
|
||||||
// Compute exponent
|
// Compute exponent
|
||||||
if ((int_bits > max_exp) and (exp > max_exp)) // If exponent too large, overflow to infinity
|
if ((int_bits > max_exp) and (exp > max_exp)) // If exponent too large, overflow to infinity
|
||||||
return @bitCast(T, sign_bit | @bitCast(uT, inf));
|
return @as(T, @bitCast(sign_bit | @as(uT, @bitCast(inf))));
|
||||||
|
|
||||||
result += (@as(uT, exp) + exp_bias) << math.floatMantissaBits(T);
|
result += (@as(uT, exp) + exp_bias) << math.floatMantissaBits(T);
|
||||||
|
|
||||||
// If the result included a carry, we need to restore the explicit integer bit
|
// If the result included a carry, we need to restore the explicit integer bit
|
||||||
if (T == f80) result |= 1 << fractional_bits;
|
if (T == f80) result |= 1 << fractional_bits;
|
||||||
|
|
||||||
return @bitCast(T, sign_bit | result);
|
return @as(T, @bitCast(sign_bit | result));
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@ -30,12 +30,12 @@ const __floatuntitf = @import("floatuntitf.zig").__floatuntitf;
|
|||||||
|
|
||||||
fn test__floatsisf(a: i32, expected: u32) !void {
|
fn test__floatsisf(a: i32, expected: u32) !void {
|
||||||
const r = __floatsisf(a);
|
const r = __floatsisf(a);
|
||||||
try std.testing.expect(@bitCast(u32, r) == expected);
|
try std.testing.expect(@as(u32, @bitCast(r)) == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_one_floatunsisf(a: u32, expected: u32) !void {
|
fn test_one_floatunsisf(a: u32, expected: u32) !void {
|
||||||
const r = __floatunsisf(a);
|
const r = __floatunsisf(a);
|
||||||
try std.testing.expect(@bitCast(u32, r) == expected);
|
try std.testing.expect(@as(u32, @bitCast(r)) == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "floatsisf" {
|
test "floatsisf" {
|
||||||
@ -43,7 +43,7 @@ test "floatsisf" {
|
|||||||
try test__floatsisf(1, 0x3f800000);
|
try test__floatsisf(1, 0x3f800000);
|
||||||
try test__floatsisf(-1, 0xbf800000);
|
try test__floatsisf(-1, 0xbf800000);
|
||||||
try test__floatsisf(0x7FFFFFFF, 0x4f000000);
|
try test__floatsisf(0x7FFFFFFF, 0x4f000000);
|
||||||
try test__floatsisf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xcf000000);
|
try test__floatsisf(@as(i32, @bitCast(@as(u32, @intCast(0x80000000)))), 0xcf000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "floatunsisf" {
|
test "floatunsisf" {
|
||||||
@ -72,10 +72,10 @@ test "floatdisf" {
|
|||||||
try test__floatdisf(-2, -2.0);
|
try test__floatdisf(-2, -2.0);
|
||||||
try test__floatdisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
|
try test__floatdisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
|
||||||
try test__floatdisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
|
try test__floatdisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
|
||||||
try test__floatdisf(@bitCast(i64, @as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62);
|
try test__floatdisf(@as(i64, @bitCast(@as(u64, 0x8000008000000000))), -0x1.FFFFFEp+62);
|
||||||
try test__floatdisf(@bitCast(i64, @as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62);
|
try test__floatdisf(@as(i64, @bitCast(@as(u64, 0x8000010000000000))), -0x1.FFFFFCp+62);
|
||||||
try test__floatdisf(@bitCast(i64, @as(u64, 0x8000000000000000)), -0x1.000000p+63);
|
try test__floatdisf(@as(i64, @bitCast(@as(u64, 0x8000000000000000))), -0x1.000000p+63);
|
||||||
try test__floatdisf(@bitCast(i64, @as(u64, 0x8000000000000001)), -0x1.000000p+63);
|
try test__floatdisf(@as(i64, @bitCast(@as(u64, 0x8000000000000001))), -0x1.000000p+63);
|
||||||
try test__floatdisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
|
try test__floatdisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
|
||||||
try test__floatdisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
|
try test__floatdisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
|
||||||
try test__floatdisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
|
try test__floatdisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
|
||||||
@ -228,17 +228,17 @@ test "floatuntisf" {
|
|||||||
try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76);
|
try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76);
|
||||||
|
|
||||||
// Test overflow to infinity
|
// Test overflow to infinity
|
||||||
try test__floatuntisf(@as(u128, math.maxInt(u128)), @bitCast(f32, math.inf(f32)));
|
try test__floatuntisf(@as(u128, math.maxInt(u128)), @as(f32, @bitCast(math.inf(f32))));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_one_floatsidf(a: i32, expected: u64) !void {
|
fn test_one_floatsidf(a: i32, expected: u64) !void {
|
||||||
const r = __floatsidf(a);
|
const r = __floatsidf(a);
|
||||||
try std.testing.expect(@bitCast(u64, r) == expected);
|
try std.testing.expect(@as(u64, @bitCast(r)) == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_one_floatunsidf(a: u32, expected: u64) !void {
|
fn test_one_floatunsidf(a: u32, expected: u64) !void {
|
||||||
const r = __floatunsidf(a);
|
const r = __floatunsidf(a);
|
||||||
try std.testing.expect(@bitCast(u64, r) == expected);
|
try std.testing.expect(@as(u64, @bitCast(r)) == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "floatsidf" {
|
test "floatsidf" {
|
||||||
@ -246,15 +246,15 @@ test "floatsidf" {
|
|||||||
try test_one_floatsidf(1, 0x3ff0000000000000);
|
try test_one_floatsidf(1, 0x3ff0000000000000);
|
||||||
try test_one_floatsidf(-1, 0xbff0000000000000);
|
try test_one_floatsidf(-1, 0xbff0000000000000);
|
||||||
try test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000);
|
try test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000);
|
||||||
try test_one_floatsidf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc1e0000000000000);
|
try test_one_floatsidf(@as(i32, @bitCast(@as(u32, @intCast(0x80000000)))), 0xc1e0000000000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "floatunsidf" {
|
test "floatunsidf" {
|
||||||
try test_one_floatunsidf(0, 0x0000000000000000);
|
try test_one_floatunsidf(0, 0x0000000000000000);
|
||||||
try test_one_floatunsidf(1, 0x3ff0000000000000);
|
try test_one_floatunsidf(1, 0x3ff0000000000000);
|
||||||
try test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000);
|
try test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000);
|
||||||
try test_one_floatunsidf(@intCast(u32, 0x80000000), 0x41e0000000000000);
|
try test_one_floatunsidf(@as(u32, @intCast(0x80000000)), 0x41e0000000000000);
|
||||||
try test_one_floatunsidf(@intCast(u32, 0xFFFFFFFF), 0x41efffffffe00000);
|
try test_one_floatunsidf(@as(u32, @intCast(0xFFFFFFFF)), 0x41efffffffe00000);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test__floatdidf(a: i64, expected: f64) !void {
|
fn test__floatdidf(a: i64, expected: f64) !void {
|
||||||
@ -279,12 +279,12 @@ test "floatdidf" {
|
|||||||
try test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
|
try test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62);
|
||||||
try test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
|
try test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
|
||||||
try test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
|
try test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62);
|
||||||
try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000008000000000)), -0x1.FFFFFEp+62);
|
try test__floatdidf(@as(i64, @bitCast(@as(u64, @intCast(0x8000008000000000)))), -0x1.FFFFFEp+62);
|
||||||
try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000800)), -0x1.FFFFFFFFFFFFEp+62);
|
try test__floatdidf(@as(i64, @bitCast(@as(u64, @intCast(0x8000000000000800)))), -0x1.FFFFFFFFFFFFEp+62);
|
||||||
try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000010000000000)), -0x1.FFFFFCp+62);
|
try test__floatdidf(@as(i64, @bitCast(@as(u64, @intCast(0x8000010000000000)))), -0x1.FFFFFCp+62);
|
||||||
try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000001000)), -0x1.FFFFFFFFFFFFCp+62);
|
try test__floatdidf(@as(i64, @bitCast(@as(u64, @intCast(0x8000000000001000)))), -0x1.FFFFFFFFFFFFCp+62);
|
||||||
try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000000)), -0x1.000000p+63);
|
try test__floatdidf(@as(i64, @bitCast(@as(u64, @intCast(0x8000000000000000)))), -0x1.000000p+63);
|
||||||
try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000001)), -0x1.000000p+63); // 0x8000000000000001
|
try test__floatdidf(@as(i64, @bitCast(@as(u64, @intCast(0x8000000000000001)))), -0x1.000000p+63); // 0x8000000000000001
|
||||||
try test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
|
try test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
|
||||||
try test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
|
try test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50);
|
||||||
try test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
|
try test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50);
|
||||||
@ -505,7 +505,7 @@ test "floatuntidf" {
|
|||||||
|
|
||||||
fn test__floatsitf(a: i32, expected: u128) !void {
|
fn test__floatsitf(a: i32, expected: u128) !void {
|
||||||
const r = __floatsitf(a);
|
const r = __floatsitf(a);
|
||||||
try std.testing.expect(@bitCast(u128, r) == expected);
|
try std.testing.expect(@as(u128, @bitCast(r)) == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "floatsitf" {
|
test "floatsitf" {
|
||||||
@ -513,16 +513,16 @@ test "floatsitf" {
|
|||||||
try test__floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000);
|
try test__floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000);
|
||||||
try test__floatsitf(0x12345678, 0x401b2345678000000000000000000000);
|
try test__floatsitf(0x12345678, 0x401b2345678000000000000000000000);
|
||||||
try test__floatsitf(-0x12345678, 0xc01b2345678000000000000000000000);
|
try test__floatsitf(-0x12345678, 0xc01b2345678000000000000000000000);
|
||||||
try test__floatsitf(@bitCast(i32, @intCast(u32, 0xffffffff)), 0xbfff0000000000000000000000000000);
|
try test__floatsitf(@as(i32, @bitCast(@as(u32, @intCast(0xffffffff)))), 0xbfff0000000000000000000000000000);
|
||||||
try test__floatsitf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc01e0000000000000000000000000000);
|
try test__floatsitf(@as(i32, @bitCast(@as(u32, @intCast(0x80000000)))), 0xc01e0000000000000000000000000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void {
|
fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void {
|
||||||
const x = __floatunsitf(a);
|
const x = __floatunsitf(a);
|
||||||
|
|
||||||
const x_repr = @bitCast(u128, x);
|
const x_repr = @as(u128, @bitCast(x));
|
||||||
const x_hi = @intCast(u64, x_repr >> 64);
|
const x_hi = @as(u64, @intCast(x_repr >> 64));
|
||||||
const x_lo = @truncate(u64, x_repr);
|
const x_lo = @as(u64, @truncate(x_repr));
|
||||||
|
|
||||||
if (x_hi == expected_hi and x_lo == expected_lo) {
|
if (x_hi == expected_hi and x_lo == expected_lo) {
|
||||||
return;
|
return;
|
||||||
@ -552,9 +552,9 @@ fn test__floatditf(a: i64, expected: f128) !void {
|
|||||||
fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void {
|
fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void {
|
||||||
const x = __floatunditf(a);
|
const x = __floatunditf(a);
|
||||||
|
|
||||||
const x_repr = @bitCast(u128, x);
|
const x_repr = @as(u128, @bitCast(x));
|
||||||
const x_hi = @intCast(u64, x_repr >> 64);
|
const x_hi = @as(u64, @intCast(x_repr >> 64));
|
||||||
const x_lo = @truncate(u64, x_repr);
|
const x_lo = @as(u64, @truncate(x_repr));
|
||||||
|
|
||||||
if (x_hi == expected_hi and x_lo == expected_lo) {
|
if (x_hi == expected_hi and x_lo == expected_lo) {
|
||||||
return;
|
return;
|
||||||
@ -575,10 +575,10 @@ test "floatditf" {
|
|||||||
try test__floatditf(0x2, make_tf(0x4000000000000000, 0x0));
|
try test__floatditf(0x2, make_tf(0x4000000000000000, 0x0));
|
||||||
try test__floatditf(0x1, make_tf(0x3fff000000000000, 0x0));
|
try test__floatditf(0x1, make_tf(0x3fff000000000000, 0x0));
|
||||||
try test__floatditf(0x0, make_tf(0x0, 0x0));
|
try test__floatditf(0x0, make_tf(0x0, 0x0));
|
||||||
try test__floatditf(@bitCast(i64, @as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0));
|
try test__floatditf(@as(i64, @bitCast(@as(u64, 0xffffffffffffffff))), make_tf(0xbfff000000000000, 0x0));
|
||||||
try test__floatditf(@bitCast(i64, @as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0));
|
try test__floatditf(@as(i64, @bitCast(@as(u64, 0xfffffffffffffffe))), make_tf(0xc000000000000000, 0x0));
|
||||||
try test__floatditf(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000));
|
try test__floatditf(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000));
|
||||||
try test__floatditf(@bitCast(i64, @as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0));
|
try test__floatditf(@as(i64, @bitCast(@as(u64, 0x8000000000000000))), make_tf(0xc03e000000000000, 0x0));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "floatunditf" {
|
test "floatunditf" {
|
||||||
@ -773,7 +773,7 @@ fn make_ti(high: u64, low: u64) i128 {
|
|||||||
var result: u128 = high;
|
var result: u128 = high;
|
||||||
result <<= 64;
|
result <<= 64;
|
||||||
result |= low;
|
result |= low;
|
||||||
return @bitCast(i128, result);
|
return @as(i128, @bitCast(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_uti(high: u64, low: u64) u128 {
|
fn make_uti(high: u64, low: u64) u128 {
|
||||||
@ -787,7 +787,7 @@ fn make_tf(high: u64, low: u64) f128 {
|
|||||||
var result: u128 = high;
|
var result: u128 = high;
|
||||||
result <<= 64;
|
result <<= 64;
|
||||||
result |= low;
|
result |= low;
|
||||||
return @bitCast(f128, result);
|
return @as(f128, @bitCast(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "conversion to f16" {
|
test "conversion to f16" {
|
||||||
@ -815,22 +815,22 @@ test "conversion to f80" {
|
|||||||
const floatFromInt = @import("./float_from_int.zig").floatFromInt;
|
const floatFromInt = @import("./float_from_int.zig").floatFromInt;
|
||||||
|
|
||||||
try testing.expect(floatFromInt(f80, @as(i80, -12)) == -12);
|
try testing.expect(floatFromInt(f80, @as(i80, -12)) == -12);
|
||||||
try testing.expect(@intFromFloat(u80, floatFromInt(f80, @as(u64, math.maxInt(u64)) + 0)) == math.maxInt(u64) + 0);
|
try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u64, math.maxInt(u64)) + 0))) == math.maxInt(u64) + 0);
|
||||||
try testing.expect(@intFromFloat(u80, floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1)) == math.maxInt(u64) + 1);
|
try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1);
|
||||||
|
|
||||||
try testing.expect(floatFromInt(f80, @as(u32, 0)) == 0.0);
|
try testing.expect(floatFromInt(f80, @as(u32, 0)) == 0.0);
|
||||||
try testing.expect(floatFromInt(f80, @as(u32, 1)) == 1.0);
|
try testing.expect(floatFromInt(f80, @as(u32, 1)) == 1.0);
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u32, math.maxInt(u24)) + 0)) == math.maxInt(u24));
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u32, math.maxInt(u24)) + 0))) == math.maxInt(u24));
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u64)) + 0)) == math.maxInt(u64));
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 0))) == math.maxInt(u64));
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1)) == math.maxInt(u64) + 1); // Exact
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1); // Exact
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u64)) + 2)) == math.maxInt(u64) + 1); // Rounds down
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 2))) == math.maxInt(u64) + 1); // Rounds down
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u64)) + 3)) == math.maxInt(u64) + 3); // Tie - Exact
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 3))) == math.maxInt(u64) + 3); // Tie - Exact
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u64)) + 4)) == math.maxInt(u64) + 5); // Rounds up
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 4))) == math.maxInt(u64) + 5); // Rounds up
|
||||||
|
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u65)) + 0)) == math.maxInt(u65) + 1); // Rounds up
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 0))) == math.maxInt(u65) + 1); // Rounds up
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u65)) + 1)) == math.maxInt(u65) + 1); // Exact
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 1))) == math.maxInt(u65) + 1); // Exact
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u65)) + 2)) == math.maxInt(u65) + 1); // Rounds down
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 2))) == math.maxInt(u65) + 1); // Rounds down
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u65)) + 3)) == math.maxInt(u65) + 1); // Tie - Rounds down
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 3))) == math.maxInt(u65) + 1); // Tie - Rounds down
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u65)) + 4)) == math.maxInt(u65) + 5); // Rounds up
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 4))) == math.maxInt(u65) + 5); // Rounds up
|
||||||
try testing.expect(@intFromFloat(u128, floatFromInt(f80, @as(u80, math.maxInt(u65)) + 5)) == math.maxInt(u65) + 5); // Exact
|
try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 5))) == math.maxInt(u65) + 5); // Exact
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,5 +17,5 @@ pub fn __floattidf(a: i128) callconv(.C) f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __floattidf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f64 {
|
fn __floattidf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f64 {
|
||||||
return floatFromInt(f64, @bitCast(i128, a));
|
return floatFromInt(f64, @as(i128, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,5 +17,5 @@ pub fn __floattihf(a: i128) callconv(.C) f16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __floattihf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f16 {
|
fn __floattihf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f16 {
|
||||||
return floatFromInt(f16, @bitCast(i128, a));
|
return floatFromInt(f16, @as(i128, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,5 +17,5 @@ pub fn __floattisf(a: i128) callconv(.C) f32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __floattisf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f32 {
|
fn __floattisf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f32 {
|
||||||
return floatFromInt(f32, @bitCast(i128, a));
|
return floatFromInt(f32, @as(i128, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,5 @@ pub fn __floattitf(a: i128) callconv(.C) f128 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __floattitf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f128 {
|
fn __floattitf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f128 {
|
||||||
return floatFromInt(f128, @bitCast(i128, a));
|
return floatFromInt(f128, @as(i128, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,5 +17,5 @@ pub fn __floattixf(a: i128) callconv(.C) f80 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __floattixf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f80 {
|
fn __floattixf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f80 {
|
||||||
return floatFromInt(f80, @bitCast(i128, a));
|
return floatFromInt(f80, @as(i128, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,5 +17,5 @@ pub fn __floatuntidf(a: u128) callconv(.C) f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __floatuntidf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f64 {
|
fn __floatuntidf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f64 {
|
||||||
return floatFromInt(f64, @bitCast(u128, a));
|
return floatFromInt(f64, @as(u128, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,5 +17,5 @@ pub fn __floatuntihf(a: u128) callconv(.C) f16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __floatuntihf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f16 {
|
fn __floatuntihf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f16 {
|
||||||
return floatFromInt(f16, @bitCast(u128, a));
|
return floatFromInt(f16, @as(u128, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,5 +17,5 @@ pub fn __floatuntisf(a: u128) callconv(.C) f32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __floatuntisf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f32 {
|
fn __floatuntisf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f32 {
|
||||||
return floatFromInt(f32, @bitCast(u128, a));
|
return floatFromInt(f32, @as(u128, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,5 @@ pub fn __floatuntitf(a: u128) callconv(.C) f128 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __floatuntitf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f128 {
|
fn __floatuntitf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f128 {
|
||||||
return floatFromInt(f128, @bitCast(u128, a));
|
return floatFromInt(f128, @as(u128, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,5 +17,5 @@ pub fn __floatuntixf(a: u128) callconv(.C) f80 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn __floatuntixf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f80 {
|
fn __floatuntixf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f80 {
|
||||||
return floatFromInt(f80, @bitCast(u128, a));
|
return floatFromInt(f80, @as(u128, @bitCast(a)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,8 +26,8 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __floorh(x: f16) callconv(.C) f16 {
|
pub fn __floorh(x: f16) callconv(.C) f16 {
|
||||||
var u = @bitCast(u16, x);
|
var u = @as(u16, @bitCast(x));
|
||||||
const e = @intCast(i16, (u >> 10) & 31) - 15;
|
const e = @as(i16, @intCast((u >> 10) & 31)) - 15;
|
||||||
var m: u16 = undefined;
|
var m: u16 = undefined;
|
||||||
|
|
||||||
// TODO: Shouldn't need this explicit check.
|
// TODO: Shouldn't need this explicit check.
|
||||||
@ -40,7 +40,7 @@ pub fn __floorh(x: f16) callconv(.C) f16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (e >= 0) {
|
if (e >= 0) {
|
||||||
m = @as(u16, 1023) >> @intCast(u4, e);
|
m = @as(u16, 1023) >> @as(u4, @intCast(e));
|
||||||
if (u & m == 0) {
|
if (u & m == 0) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ pub fn __floorh(x: f16) callconv(.C) f16 {
|
|||||||
if (u >> 15 != 0) {
|
if (u >> 15 != 0) {
|
||||||
u += m;
|
u += m;
|
||||||
}
|
}
|
||||||
return @bitCast(f16, u & ~m);
|
return @as(f16, @bitCast(u & ~m));
|
||||||
} else {
|
} else {
|
||||||
math.doNotOptimizeAway(x + 0x1.0p120);
|
math.doNotOptimizeAway(x + 0x1.0p120);
|
||||||
if (u >> 15 == 0) {
|
if (u >> 15 == 0) {
|
||||||
@ -60,8 +60,8 @@ pub fn __floorh(x: f16) callconv(.C) f16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn floorf(x: f32) callconv(.C) f32 {
|
pub fn floorf(x: f32) callconv(.C) f32 {
|
||||||
var u = @bitCast(u32, x);
|
var u = @as(u32, @bitCast(x));
|
||||||
const e = @intCast(i32, (u >> 23) & 0xFF) - 0x7F;
|
const e = @as(i32, @intCast((u >> 23) & 0xFF)) - 0x7F;
|
||||||
var m: u32 = undefined;
|
var m: u32 = undefined;
|
||||||
|
|
||||||
// TODO: Shouldn't need this explicit check.
|
// TODO: Shouldn't need this explicit check.
|
||||||
@ -74,7 +74,7 @@ pub fn floorf(x: f32) callconv(.C) f32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (e >= 0) {
|
if (e >= 0) {
|
||||||
m = @as(u32, 0x007FFFFF) >> @intCast(u5, e);
|
m = @as(u32, 0x007FFFFF) >> @as(u5, @intCast(e));
|
||||||
if (u & m == 0) {
|
if (u & m == 0) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ pub fn floorf(x: f32) callconv(.C) f32 {
|
|||||||
if (u >> 31 != 0) {
|
if (u >> 31 != 0) {
|
||||||
u += m;
|
u += m;
|
||||||
}
|
}
|
||||||
return @bitCast(f32, u & ~m);
|
return @as(f32, @bitCast(u & ~m));
|
||||||
} else {
|
} else {
|
||||||
math.doNotOptimizeAway(x + 0x1.0p120);
|
math.doNotOptimizeAway(x + 0x1.0p120);
|
||||||
if (u >> 31 == 0) {
|
if (u >> 31 == 0) {
|
||||||
@ -96,7 +96,7 @@ pub fn floorf(x: f32) callconv(.C) f32 {
|
|||||||
pub fn floor(x: f64) callconv(.C) f64 {
|
pub fn floor(x: f64) callconv(.C) f64 {
|
||||||
const f64_toint = 1.0 / math.floatEps(f64);
|
const f64_toint = 1.0 / math.floatEps(f64);
|
||||||
|
|
||||||
const u = @bitCast(u64, x);
|
const u = @as(u64, @bitCast(x));
|
||||||
const e = (u >> 52) & 0x7FF;
|
const e = (u >> 52) & 0x7FF;
|
||||||
var y: f64 = undefined;
|
var y: f64 = undefined;
|
||||||
|
|
||||||
@ -126,13 +126,13 @@ pub fn floor(x: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
pub fn __floorx(x: f80) callconv(.C) f80 {
|
pub fn __floorx(x: f80) callconv(.C) f80 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f80, floorq(x));
|
return @as(f80, @floatCast(floorq(x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn floorq(x: f128) callconv(.C) f128 {
|
pub fn floorq(x: f128) callconv(.C) f128 {
|
||||||
const f128_toint = 1.0 / math.floatEps(f128);
|
const f128_toint = 1.0 / math.floatEps(f128);
|
||||||
|
|
||||||
const u = @bitCast(u128, x);
|
const u = @as(u128, @bitCast(x));
|
||||||
const e = (u >> 112) & 0x7FFF;
|
const e = (u >> 112) & 0x7FFF;
|
||||||
var y: f128 = undefined;
|
var y: f128 = undefined;
|
||||||
|
|
||||||
|
|||||||
@ -28,20 +28,20 @@ comptime {
|
|||||||
|
|
||||||
pub fn __fmah(x: f16, y: f16, z: f16) callconv(.C) f16 {
|
pub fn __fmah(x: f16, y: f16, z: f16) callconv(.C) f16 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f16, fmaf(x, y, z));
|
return @as(f16, @floatCast(fmaf(x, y, z)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmaf(x: f32, y: f32, z: f32) callconv(.C) f32 {
|
pub fn fmaf(x: f32, y: f32, z: f32) callconv(.C) f32 {
|
||||||
const xy = @as(f64, x) * y;
|
const xy = @as(f64, x) * y;
|
||||||
const xy_z = xy + z;
|
const xy_z = xy + z;
|
||||||
const u = @bitCast(u64, xy_z);
|
const u = @as(u64, @bitCast(xy_z));
|
||||||
const e = (u >> 52) & 0x7FF;
|
const e = (u >> 52) & 0x7FF;
|
||||||
|
|
||||||
if ((u & 0x1FFFFFFF) != 0x10000000 or e == 0x7FF or (xy_z - xy == z and xy_z - z == xy)) {
|
if ((u & 0x1FFFFFFF) != 0x10000000 or e == 0x7FF or (xy_z - xy == z and xy_z - z == xy)) {
|
||||||
return @floatCast(f32, xy_z);
|
return @as(f32, @floatCast(xy_z));
|
||||||
} else {
|
} else {
|
||||||
// TODO: Handle inexact case with double-rounding
|
// TODO: Handle inexact case with double-rounding
|
||||||
return @floatCast(f32, xy_z);
|
return @as(f32, @floatCast(xy_z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ pub fn fma(x: f64, y: f64, z: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
pub fn __fmax(a: f80, b: f80, c: f80) callconv(.C) f80 {
|
pub fn __fmax(a: f80, b: f80, c: f80) callconv(.C) f80 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f80, fmaq(a, b, c));
|
return @as(f80, @floatCast(fmaq(a, b, c)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fused multiply-add: Compute x * y + z with a single rounding error.
|
/// Fused multiply-add: Compute x * y + z with a single rounding error.
|
||||||
@ -201,12 +201,12 @@ fn dd_mul(a: f64, b: f64) dd {
|
|||||||
fn add_adjusted(a: f64, b: f64) f64 {
|
fn add_adjusted(a: f64, b: f64) f64 {
|
||||||
var sum = dd_add(a, b);
|
var sum = dd_add(a, b);
|
||||||
if (sum.lo != 0) {
|
if (sum.lo != 0) {
|
||||||
var uhii = @bitCast(u64, sum.hi);
|
var uhii = @as(u64, @bitCast(sum.hi));
|
||||||
if (uhii & 1 == 0) {
|
if (uhii & 1 == 0) {
|
||||||
// hibits += copysign(1.0, sum.hi, sum.lo)
|
// hibits += copysign(1.0, sum.hi, sum.lo)
|
||||||
const uloi = @bitCast(u64, sum.lo);
|
const uloi = @as(u64, @bitCast(sum.lo));
|
||||||
uhii += 1 - ((uhii ^ uloi) >> 62);
|
uhii += 1 - ((uhii ^ uloi) >> 62);
|
||||||
sum.hi = @bitCast(f64, uhii);
|
sum.hi = @as(f64, @bitCast(uhii));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sum.hi;
|
return sum.hi;
|
||||||
@ -215,12 +215,12 @@ fn add_adjusted(a: f64, b: f64) f64 {
|
|||||||
fn add_and_denorm(a: f64, b: f64, scale: i32) f64 {
|
fn add_and_denorm(a: f64, b: f64, scale: i32) f64 {
|
||||||
var sum = dd_add(a, b);
|
var sum = dd_add(a, b);
|
||||||
if (sum.lo != 0) {
|
if (sum.lo != 0) {
|
||||||
var uhii = @bitCast(u64, sum.hi);
|
var uhii = @as(u64, @bitCast(sum.hi));
|
||||||
const bits_lost = -@intCast(i32, (uhii >> 52) & 0x7FF) - scale + 1;
|
const bits_lost = -@as(i32, @intCast((uhii >> 52) & 0x7FF)) - scale + 1;
|
||||||
if ((bits_lost != 1) == (uhii & 1 != 0)) {
|
if ((bits_lost != 1) == (uhii & 1 != 0)) {
|
||||||
const uloi = @bitCast(u64, sum.lo);
|
const uloi = @as(u64, @bitCast(sum.lo));
|
||||||
uhii += 1 - (((uhii ^ uloi) >> 62) & 2);
|
uhii += 1 - (((uhii ^ uloi) >> 62) & 2);
|
||||||
sum.hi = @bitCast(f64, uhii);
|
sum.hi = @as(f64, @bitCast(uhii));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return math.scalbn(sum.hi, scale);
|
return math.scalbn(sum.hi, scale);
|
||||||
@ -257,12 +257,12 @@ fn dd_add128(a: f128, b: f128) dd128 {
|
|||||||
fn add_adjusted128(a: f128, b: f128) f128 {
|
fn add_adjusted128(a: f128, b: f128) f128 {
|
||||||
var sum = dd_add128(a, b);
|
var sum = dd_add128(a, b);
|
||||||
if (sum.lo != 0) {
|
if (sum.lo != 0) {
|
||||||
var uhii = @bitCast(u128, sum.hi);
|
var uhii = @as(u128, @bitCast(sum.hi));
|
||||||
if (uhii & 1 == 0) {
|
if (uhii & 1 == 0) {
|
||||||
// hibits += copysign(1.0, sum.hi, sum.lo)
|
// hibits += copysign(1.0, sum.hi, sum.lo)
|
||||||
const uloi = @bitCast(u128, sum.lo);
|
const uloi = @as(u128, @bitCast(sum.lo));
|
||||||
uhii += 1 - ((uhii ^ uloi) >> 126);
|
uhii += 1 - ((uhii ^ uloi) >> 126);
|
||||||
sum.hi = @bitCast(f128, uhii);
|
sum.hi = @as(f128, @bitCast(uhii));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sum.hi;
|
return sum.hi;
|
||||||
@ -282,12 +282,12 @@ fn add_and_denorm128(a: f128, b: f128, scale: i32) f128 {
|
|||||||
// If we are losing only one bit to denormalization, however, we must
|
// If we are losing only one bit to denormalization, however, we must
|
||||||
// break the ties manually.
|
// break the ties manually.
|
||||||
if (sum.lo != 0) {
|
if (sum.lo != 0) {
|
||||||
var uhii = @bitCast(u128, sum.hi);
|
var uhii = @as(u128, @bitCast(sum.hi));
|
||||||
const bits_lost = -@intCast(i32, (uhii >> 112) & 0x7FFF) - scale + 1;
|
const bits_lost = -@as(i32, @intCast((uhii >> 112) & 0x7FFF)) - scale + 1;
|
||||||
if ((bits_lost != 1) == (uhii & 1 != 0)) {
|
if ((bits_lost != 1) == (uhii & 1 != 0)) {
|
||||||
const uloi = @bitCast(u128, sum.lo);
|
const uloi = @as(u128, @bitCast(sum.lo));
|
||||||
uhii += 1 - (((uhii ^ uloi) >> 126) & 2);
|
uhii += 1 - (((uhii ^ uloi) >> 126) & 2);
|
||||||
sum.hi = @bitCast(f128, uhii);
|
sum.hi = @as(f128, @bitCast(uhii));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return math.scalbn(sum.hi, scale);
|
return math.scalbn(sum.hi, scale);
|
||||||
|
|||||||
@ -22,7 +22,7 @@ comptime {
|
|||||||
|
|
||||||
pub fn __fmodh(x: f16, y: f16) callconv(.C) f16 {
|
pub fn __fmodh(x: f16, y: f16) callconv(.C) f16 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f16, fmodf(x, y));
|
return @as(f16, @floatCast(fmodf(x, y)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmodf(x: f32, y: f32) callconv(.C) f32 {
|
pub fn fmodf(x: f32, y: f32) callconv(.C) f32 {
|
||||||
@ -46,12 +46,12 @@ pub fn __fmodx(a: f80, b: f80) callconv(.C) f80 {
|
|||||||
const signBit = (@as(Z, 1) << (significandBits + exponentBits));
|
const signBit = (@as(Z, 1) << (significandBits + exponentBits));
|
||||||
const maxExponent = ((1 << exponentBits) - 1);
|
const maxExponent = ((1 << exponentBits) - 1);
|
||||||
|
|
||||||
var aRep = @bitCast(Z, a);
|
var aRep = @as(Z, @bitCast(a));
|
||||||
var bRep = @bitCast(Z, b);
|
var bRep = @as(Z, @bitCast(b));
|
||||||
|
|
||||||
const signA = aRep & signBit;
|
const signA = aRep & signBit;
|
||||||
var expA = @intCast(i32, (@bitCast(Z, a) >> significandBits) & maxExponent);
|
var expA = @as(i32, @intCast((@as(Z, @bitCast(a)) >> significandBits) & maxExponent));
|
||||||
var expB = @intCast(i32, (@bitCast(Z, b) >> significandBits) & maxExponent);
|
var expB = @as(i32, @intCast((@as(Z, @bitCast(b)) >> significandBits) & maxExponent));
|
||||||
|
|
||||||
// There are 3 cases where the answer is undefined, check for:
|
// There are 3 cases where the answer is undefined, check for:
|
||||||
// - fmodx(val, 0)
|
// - fmodx(val, 0)
|
||||||
@ -82,8 +82,8 @@ pub fn __fmodx(a: f80, b: f80) callconv(.C) f80 {
|
|||||||
|
|
||||||
var highA: u64 = 0;
|
var highA: u64 = 0;
|
||||||
var highB: u64 = 0;
|
var highB: u64 = 0;
|
||||||
var lowA: u64 = @truncate(u64, aRep);
|
var lowA: u64 = @as(u64, @truncate(aRep));
|
||||||
var lowB: u64 = @truncate(u64, bRep);
|
var lowB: u64 = @as(u64, @truncate(bRep));
|
||||||
|
|
||||||
while (expA > expB) : (expA -= 1) {
|
while (expA > expB) : (expA -= 1) {
|
||||||
var high = highA -% highB;
|
var high = highA -% highB;
|
||||||
@ -123,11 +123,11 @@ pub fn __fmodx(a: f80, b: f80) callconv(.C) f80 {
|
|||||||
|
|
||||||
// Combine the exponent with the sign and significand, normalize if happened to be denormalized
|
// Combine the exponent with the sign and significand, normalize if happened to be denormalized
|
||||||
if (expA < -fractionalBits) {
|
if (expA < -fractionalBits) {
|
||||||
return @bitCast(T, signA);
|
return @as(T, @bitCast(signA));
|
||||||
} else if (expA <= 0) {
|
} else if (expA <= 0) {
|
||||||
return @bitCast(T, (lowA >> @intCast(math.Log2Int(u64), 1 - expA)) | signA);
|
return @as(T, @bitCast((lowA >> @as(math.Log2Int(u64), @intCast(1 - expA))) | signA));
|
||||||
} else {
|
} else {
|
||||||
return @bitCast(T, lowA | (@as(Z, @intCast(u16, expA)) << significandBits) | signA);
|
return @as(T, @bitCast(lowA | (@as(Z, @as(u16, @intCast(expA))) << significandBits) | signA));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,10 +136,10 @@ pub fn __fmodx(a: f80, b: f80) callconv(.C) f80 {
|
|||||||
pub fn fmodq(a: f128, b: f128) callconv(.C) f128 {
|
pub fn fmodq(a: f128, b: f128) callconv(.C) f128 {
|
||||||
var amod = a;
|
var amod = a;
|
||||||
var bmod = b;
|
var bmod = b;
|
||||||
const aPtr_u64 = @ptrCast([*]u64, &amod);
|
const aPtr_u64 = @as([*]u64, @ptrCast(&amod));
|
||||||
const bPtr_u64 = @ptrCast([*]u64, &bmod);
|
const bPtr_u64 = @as([*]u64, @ptrCast(&bmod));
|
||||||
const aPtr_u16 = @ptrCast([*]u16, &amod);
|
const aPtr_u16 = @as([*]u16, @ptrCast(&amod));
|
||||||
const bPtr_u16 = @ptrCast([*]u16, &bmod);
|
const bPtr_u16 = @as([*]u16, @ptrCast(&bmod));
|
||||||
|
|
||||||
const exp_and_sign_index = comptime switch (builtin.target.cpu.arch.endian()) {
|
const exp_and_sign_index = comptime switch (builtin.target.cpu.arch.endian()) {
|
||||||
.Little => 7,
|
.Little => 7,
|
||||||
@ -155,8 +155,8 @@ pub fn fmodq(a: f128, b: f128) callconv(.C) f128 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const signA = aPtr_u16[exp_and_sign_index] & 0x8000;
|
const signA = aPtr_u16[exp_and_sign_index] & 0x8000;
|
||||||
var expA = @intCast(i32, (aPtr_u16[exp_and_sign_index] & 0x7fff));
|
var expA = @as(i32, @intCast((aPtr_u16[exp_and_sign_index] & 0x7fff)));
|
||||||
var expB = @intCast(i32, (bPtr_u16[exp_and_sign_index] & 0x7fff));
|
var expB = @as(i32, @intCast((bPtr_u16[exp_and_sign_index] & 0x7fff)));
|
||||||
|
|
||||||
// There are 3 cases where the answer is undefined, check for:
|
// There are 3 cases where the answer is undefined, check for:
|
||||||
// - fmodq(val, 0)
|
// - fmodq(val, 0)
|
||||||
@ -173,8 +173,8 @@ pub fn fmodq(a: f128, b: f128) callconv(.C) f128 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove the sign from both
|
// Remove the sign from both
|
||||||
aPtr_u16[exp_and_sign_index] = @bitCast(u16, @intCast(i16, expA));
|
aPtr_u16[exp_and_sign_index] = @as(u16, @bitCast(@as(i16, @intCast(expA))));
|
||||||
bPtr_u16[exp_and_sign_index] = @bitCast(u16, @intCast(i16, expB));
|
bPtr_u16[exp_and_sign_index] = @as(u16, @bitCast(@as(i16, @intCast(expB))));
|
||||||
if (amod <= bmod) {
|
if (amod <= bmod) {
|
||||||
if (amod == bmod) {
|
if (amod == bmod) {
|
||||||
return 0 * a;
|
return 0 * a;
|
||||||
@ -241,10 +241,10 @@ pub fn fmodq(a: f128, b: f128) callconv(.C) f128 {
|
|||||||
|
|
||||||
// Combine the exponent with the sign, normalize if happend to be denormalized
|
// Combine the exponent with the sign, normalize if happend to be denormalized
|
||||||
if (expA <= 0) {
|
if (expA <= 0) {
|
||||||
aPtr_u16[exp_and_sign_index] = @truncate(u16, @bitCast(u32, (expA +% 120))) | signA;
|
aPtr_u16[exp_and_sign_index] = @as(u16, @truncate(@as(u32, @bitCast((expA +% 120))))) | signA;
|
||||||
amod *= 0x1p-120;
|
amod *= 0x1p-120;
|
||||||
} else {
|
} else {
|
||||||
aPtr_u16[exp_and_sign_index] = @truncate(u16, @bitCast(u32, expA)) | signA;
|
aPtr_u16[exp_and_sign_index] = @as(u16, @truncate(@as(u32, @bitCast(expA)))) | signA;
|
||||||
}
|
}
|
||||||
|
|
||||||
return amod;
|
return amod;
|
||||||
@ -270,14 +270,14 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T {
|
|||||||
const exp_bits = if (T == f32) 9 else 12;
|
const exp_bits = if (T == f32) 9 else 12;
|
||||||
const bits_minus_1 = bits - 1;
|
const bits_minus_1 = bits - 1;
|
||||||
const mask = if (T == f32) 0xff else 0x7ff;
|
const mask = if (T == f32) 0xff else 0x7ff;
|
||||||
var ux = @bitCast(uint, x);
|
var ux = @as(uint, @bitCast(x));
|
||||||
var uy = @bitCast(uint, y);
|
var uy = @as(uint, @bitCast(y));
|
||||||
var ex = @intCast(i32, (ux >> digits) & mask);
|
var ex = @as(i32, @intCast((ux >> digits) & mask));
|
||||||
var ey = @intCast(i32, (uy >> digits) & mask);
|
var ey = @as(i32, @intCast((uy >> digits) & mask));
|
||||||
const sx = if (T == f32) @intCast(u32, ux & 0x80000000) else @intCast(i32, ux >> bits_minus_1);
|
const sx = if (T == f32) @as(u32, @intCast(ux & 0x80000000)) else @as(i32, @intCast(ux >> bits_minus_1));
|
||||||
var i: uint = undefined;
|
var i: uint = undefined;
|
||||||
|
|
||||||
if (uy << 1 == 0 or math.isNan(@bitCast(T, uy)) or ex == mask)
|
if (uy << 1 == 0 or math.isNan(@as(T, @bitCast(uy))) or ex == mask)
|
||||||
return (x * y) / (x * y);
|
return (x * y) / (x * y);
|
||||||
|
|
||||||
if (ux << 1 <= uy << 1) {
|
if (ux << 1 <= uy << 1) {
|
||||||
@ -293,7 +293,7 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T {
|
|||||||
ex -= 1;
|
ex -= 1;
|
||||||
i <<= 1;
|
i <<= 1;
|
||||||
}) {}
|
}) {}
|
||||||
ux <<= @intCast(log2uint, @bitCast(u32, -ex + 1));
|
ux <<= @as(log2uint, @intCast(@as(u32, @bitCast(-ex + 1))));
|
||||||
} else {
|
} else {
|
||||||
ux &= math.maxInt(uint) >> exp_bits;
|
ux &= math.maxInt(uint) >> exp_bits;
|
||||||
ux |= 1 << digits;
|
ux |= 1 << digits;
|
||||||
@ -304,7 +304,7 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T {
|
|||||||
ey -= 1;
|
ey -= 1;
|
||||||
i <<= 1;
|
i <<= 1;
|
||||||
}) {}
|
}) {}
|
||||||
uy <<= @intCast(log2uint, @bitCast(u32, -ey + 1));
|
uy <<= @as(log2uint, @intCast(@as(u32, @bitCast(-ey + 1))));
|
||||||
} else {
|
} else {
|
||||||
uy &= math.maxInt(uint) >> exp_bits;
|
uy &= math.maxInt(uint) >> exp_bits;
|
||||||
uy |= 1 << digits;
|
uy |= 1 << digits;
|
||||||
@ -334,16 +334,16 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T {
|
|||||||
// scale result up
|
// scale result up
|
||||||
if (ex > 0) {
|
if (ex > 0) {
|
||||||
ux -%= 1 << digits;
|
ux -%= 1 << digits;
|
||||||
ux |= @as(uint, @bitCast(u32, ex)) << digits;
|
ux |= @as(uint, @as(u32, @bitCast(ex))) << digits;
|
||||||
} else {
|
} else {
|
||||||
ux >>= @intCast(log2uint, @bitCast(u32, -ex + 1));
|
ux >>= @as(log2uint, @intCast(@as(u32, @bitCast(-ex + 1))));
|
||||||
}
|
}
|
||||||
if (T == f32) {
|
if (T == f32) {
|
||||||
ux |= sx;
|
ux |= sx;
|
||||||
} else {
|
} else {
|
||||||
ux |= @intCast(uint, sx) << bits_minus_1;
|
ux |= @as(uint, @intCast(sx)) << bits_minus_1;
|
||||||
}
|
}
|
||||||
return @bitCast(T, ux);
|
return @as(T, @bitCast(ux));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "fmodf" {
|
test "fmodf" {
|
||||||
|
|||||||
@ -52,8 +52,8 @@ test "test_divmodti4" {
|
|||||||
[_]i128{ -7, 5, -1, -2 },
|
[_]i128{ -7, 5, -1, -2 },
|
||||||
[_]i128{ 19, 5, 3, 4 },
|
[_]i128{ 19, 5, 3, 4 },
|
||||||
[_]i128{ 19, -5, -3, 4 },
|
[_]i128{ 19, -5, -3, 4 },
|
||||||
[_]i128{ @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 8, @bitCast(i128, @as(u128, 0xf0000000000000000000000000000000)), 0 },
|
[_]i128{ @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 8, @as(i128, @bitCast(@as(u128, 0xf0000000000000000000000000000000))), 0 },
|
||||||
[_]i128{ @bitCast(i128, @as(u128, 0x80000000000000000000000000000007)), 8, @bitCast(i128, @as(u128, 0xf0000000000000000000000000000001)), -1 },
|
[_]i128{ @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000007))), 8, @as(i128, @bitCast(@as(u128, 0xf0000000000000000000000000000001))), -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (cases) |case| {
|
for (cases) |case| {
|
||||||
@ -85,8 +85,8 @@ test "test_divmoddi4" {
|
|||||||
[_]i64{ -7, 5, -1, -2 },
|
[_]i64{ -7, 5, -1, -2 },
|
||||||
[_]i64{ 19, 5, 3, 4 },
|
[_]i64{ 19, 5, 3, 4 },
|
||||||
[_]i64{ 19, -5, -3, 4 },
|
[_]i64{ 19, -5, -3, 4 },
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 8, @bitCast(i64, @as(u64, 0xf000000000000000)), 0 },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 },
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000007)), 8, @bitCast(i64, @as(u64, 0xf000000000000001)), -1 },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (cases) |case| {
|
for (cases) |case| {
|
||||||
@ -110,14 +110,14 @@ test "test_udivmoddi4" {
|
|||||||
|
|
||||||
pub fn __divdi3(a: i64, b: i64) callconv(.C) i64 {
|
pub fn __divdi3(a: i64, b: i64) callconv(.C) i64 {
|
||||||
// Set aside the sign of the quotient.
|
// Set aside the sign of the quotient.
|
||||||
const sign = @bitCast(u64, (a ^ b) >> 63);
|
const sign = @as(u64, @bitCast((a ^ b) >> 63));
|
||||||
// Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
|
// Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
|
||||||
const abs_a = (a ^ (a >> 63)) -% (a >> 63);
|
const abs_a = (a ^ (a >> 63)) -% (a >> 63);
|
||||||
const abs_b = (b ^ (b >> 63)) -% (b >> 63);
|
const abs_b = (b ^ (b >> 63)) -% (b >> 63);
|
||||||
// Unsigned division
|
// Unsigned division
|
||||||
const res = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), null);
|
const res = __udivmoddi4(@as(u64, @bitCast(abs_a)), @as(u64, @bitCast(abs_b)), null);
|
||||||
// Apply sign of quotient to result and return.
|
// Apply sign of quotient to result and return.
|
||||||
return @bitCast(i64, (res ^ sign) -% sign);
|
return @as(i64, @bitCast((res ^ sign) -% sign));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "test_divdi3" {
|
test "test_divdi3" {
|
||||||
@ -129,10 +129,10 @@ test "test_divdi3" {
|
|||||||
[_]i64{ -2, 1, -2 },
|
[_]i64{ -2, 1, -2 },
|
||||||
[_]i64{ -2, -1, 2 },
|
[_]i64{ -2, -1, 2 },
|
||||||
|
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 1, @bitCast(i64, @as(u64, 0x8000000000000000)) },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1, @as(i64, @bitCast(@as(u64, 0x8000000000000000))) },
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -1, @bitCast(i64, @as(u64, 0x8000000000000000)) },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), -1, @as(i64, @bitCast(@as(u64, 0x8000000000000000))) },
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -2, 0x4000000000000000 },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), -2, 0x4000000000000000 },
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 2, @bitCast(i64, @as(u64, 0xC000000000000000)) },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 2, @as(i64, @bitCast(@as(u64, 0xC000000000000000))) },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (cases) |case| {
|
for (cases) |case| {
|
||||||
@ -151,9 +151,9 @@ pub fn __moddi3(a: i64, b: i64) callconv(.C) i64 {
|
|||||||
const abs_b = (b ^ (b >> 63)) -% (b >> 63);
|
const abs_b = (b ^ (b >> 63)) -% (b >> 63);
|
||||||
// Unsigned division
|
// Unsigned division
|
||||||
var r: u64 = undefined;
|
var r: u64 = undefined;
|
||||||
_ = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), &r);
|
_ = __udivmoddi4(@as(u64, @bitCast(abs_a)), @as(u64, @bitCast(abs_b)), &r);
|
||||||
// Apply the sign of the dividend and return.
|
// Apply the sign of the dividend and return.
|
||||||
return (@bitCast(i64, r) ^ (a >> 63)) -% (a >> 63);
|
return (@as(i64, @bitCast(r)) ^ (a >> 63)) -% (a >> 63);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "test_moddi3" {
|
test "test_moddi3" {
|
||||||
@ -165,12 +165,12 @@ test "test_moddi3" {
|
|||||||
[_]i64{ -5, 3, -2 },
|
[_]i64{ -5, 3, -2 },
|
||||||
[_]i64{ -5, -3, -2 },
|
[_]i64{ -5, -3, -2 },
|
||||||
|
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 1, 0 },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1, 0 },
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -1, 0 },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), -1, 0 },
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 2, 0 },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 2, 0 },
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -2, 0 },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), -2, 0 },
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 3, -2 },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 3, -2 },
|
||||||
[_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -3, -2 },
|
[_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), -3, -2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (cases) |case| {
|
for (cases) |case| {
|
||||||
@ -225,8 +225,8 @@ test "test_divmodsi4" {
|
|||||||
[_]i32{ 19, 5, 3, 4 },
|
[_]i32{ 19, 5, 3, 4 },
|
||||||
[_]i32{ 19, -5, -3, 4 },
|
[_]i32{ 19, -5, -3, 4 },
|
||||||
|
|
||||||
[_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 8, @bitCast(i32, @as(u32, 0xf0000000)), 0 },
|
[_]i32{ @as(i32, @bitCast(@as(u32, 0x80000000))), 8, @as(i32, @bitCast(@as(u32, 0xf0000000))), 0 },
|
||||||
[_]i32{ @bitCast(i32, @as(u32, 0x80000007)), 8, @bitCast(i32, @as(u32, 0xf0000001)), -1 },
|
[_]i32{ @as(i32, @bitCast(@as(u32, 0x80000007))), 8, @as(i32, @bitCast(@as(u32, 0xf0000001))), -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (cases) |case| {
|
for (cases) |case| {
|
||||||
@ -242,7 +242,7 @@ fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void {
|
|||||||
|
|
||||||
pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.C) u32 {
|
pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.C) u32 {
|
||||||
const d = __udivsi3(a, b);
|
const d = __udivsi3(a, b);
|
||||||
rem.* = @bitCast(u32, @bitCast(i32, a) -% (@bitCast(i32, d) * @bitCast(i32, b)));
|
rem.* = @as(u32, @bitCast(@as(i32, @bitCast(a)) -% (@as(i32, @bitCast(d)) * @as(i32, @bitCast(b)))));
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,14 +256,14 @@ fn __aeabi_idiv(n: i32, d: i32) callconv(.AAPCS) i32 {
|
|||||||
|
|
||||||
inline fn div_i32(n: i32, d: i32) i32 {
|
inline fn div_i32(n: i32, d: i32) i32 {
|
||||||
// Set aside the sign of the quotient.
|
// Set aside the sign of the quotient.
|
||||||
const sign = @bitCast(u32, (n ^ d) >> 31);
|
const sign = @as(u32, @bitCast((n ^ d) >> 31));
|
||||||
// Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
|
// Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
|
||||||
const abs_n = (n ^ (n >> 31)) -% (n >> 31);
|
const abs_n = (n ^ (n >> 31)) -% (n >> 31);
|
||||||
const abs_d = (d ^ (d >> 31)) -% (d >> 31);
|
const abs_d = (d ^ (d >> 31)) -% (d >> 31);
|
||||||
// abs(a) / abs(b)
|
// abs(a) / abs(b)
|
||||||
const res = @bitCast(u32, abs_n) / @bitCast(u32, abs_d);
|
const res = @as(u32, @bitCast(abs_n)) / @as(u32, @bitCast(abs_d));
|
||||||
// Apply sign of quotient to result and return.
|
// Apply sign of quotient to result and return.
|
||||||
return @bitCast(i32, (res ^ sign) -% sign);
|
return @as(i32, @bitCast((res ^ sign) -% sign));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "test_divsi3" {
|
test "test_divsi3" {
|
||||||
@ -275,10 +275,10 @@ test "test_divsi3" {
|
|||||||
[_]i32{ -2, 1, -2 },
|
[_]i32{ -2, 1, -2 },
|
||||||
[_]i32{ -2, -1, 2 },
|
[_]i32{ -2, -1, 2 },
|
||||||
|
|
||||||
[_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 1, @bitCast(i32, @as(u32, 0x80000000)) },
|
[_]i32{ @as(i32, @bitCast(@as(u32, 0x80000000))), 1, @as(i32, @bitCast(@as(u32, 0x80000000))) },
|
||||||
[_]i32{ @bitCast(i32, @as(u32, 0x80000000)), -1, @bitCast(i32, @as(u32, 0x80000000)) },
|
[_]i32{ @as(i32, @bitCast(@as(u32, 0x80000000))), -1, @as(i32, @bitCast(@as(u32, 0x80000000))) },
|
||||||
[_]i32{ @bitCast(i32, @as(u32, 0x80000000)), -2, 0x40000000 },
|
[_]i32{ @as(i32, @bitCast(@as(u32, 0x80000000))), -2, 0x40000000 },
|
||||||
[_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 2, @bitCast(i32, @as(u32, 0xC0000000)) },
|
[_]i32{ @as(i32, @bitCast(@as(u32, 0x80000000))), 2, @as(i32, @bitCast(@as(u32, 0xC0000000))) },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (cases) |case| {
|
for (cases) |case| {
|
||||||
@ -304,7 +304,7 @@ inline fn div_u32(n: u32, d: u32) u32 {
|
|||||||
// special cases
|
// special cases
|
||||||
if (d == 0) return 0; // ?!
|
if (d == 0) return 0; // ?!
|
||||||
if (n == 0) return 0;
|
if (n == 0) return 0;
|
||||||
var sr = @bitCast(c_uint, @as(c_int, @clz(d)) - @as(c_int, @clz(n)));
|
var sr = @as(c_uint, @bitCast(@as(c_int, @clz(d)) - @as(c_int, @clz(n))));
|
||||||
// 0 <= sr <= n_uword_bits - 1 or sr large
|
// 0 <= sr <= n_uword_bits - 1 or sr large
|
||||||
if (sr > n_uword_bits - 1) {
|
if (sr > n_uword_bits - 1) {
|
||||||
// d > r
|
// d > r
|
||||||
@ -317,12 +317,12 @@ inline fn div_u32(n: u32, d: u32) u32 {
|
|||||||
sr += 1;
|
sr += 1;
|
||||||
// 1 <= sr <= n_uword_bits - 1
|
// 1 <= sr <= n_uword_bits - 1
|
||||||
// Not a special case
|
// Not a special case
|
||||||
var q: u32 = n << @intCast(u5, n_uword_bits - sr);
|
var q: u32 = n << @as(u5, @intCast(n_uword_bits - sr));
|
||||||
var r: u32 = n >> @intCast(u5, sr);
|
var r: u32 = n >> @as(u5, @intCast(sr));
|
||||||
var carry: u32 = 0;
|
var carry: u32 = 0;
|
||||||
while (sr > 0) : (sr -= 1) {
|
while (sr > 0) : (sr -= 1) {
|
||||||
// r:q = ((r:q) << 1) | carry
|
// r:q = ((r:q) << 1) | carry
|
||||||
r = (r << 1) | (q >> @intCast(u5, n_uword_bits - 1));
|
r = (r << 1) | (q >> @as(u5, @intCast(n_uword_bits - 1)));
|
||||||
q = (q << 1) | carry;
|
q = (q << 1) | carry;
|
||||||
// carry = 0;
|
// carry = 0;
|
||||||
// if (r.all >= d.all)
|
// if (r.all >= d.all)
|
||||||
@ -330,9 +330,9 @@ inline fn div_u32(n: u32, d: u32) u32 {
|
|||||||
// r.all -= d.all;
|
// r.all -= d.all;
|
||||||
// carry = 1;
|
// carry = 1;
|
||||||
// }
|
// }
|
||||||
const s = @bitCast(i32, d -% r -% 1) >> @intCast(u5, n_uword_bits - 1);
|
const s = @as(i32, @bitCast(d -% r -% 1)) >> @as(u5, @intCast(n_uword_bits - 1));
|
||||||
carry = @intCast(u32, s & 1);
|
carry = @as(u32, @intCast(s & 1));
|
||||||
r -= d & @bitCast(u32, s);
|
r -= d & @as(u32, @bitCast(s));
|
||||||
}
|
}
|
||||||
q = (q << 1) | carry;
|
q = (q << 1) | carry;
|
||||||
return q;
|
return q;
|
||||||
@ -496,11 +496,11 @@ test "test_modsi3" {
|
|||||||
[_]i32{ 5, -3, 2 },
|
[_]i32{ 5, -3, 2 },
|
||||||
[_]i32{ -5, 3, -2 },
|
[_]i32{ -5, 3, -2 },
|
||||||
[_]i32{ -5, -3, -2 },
|
[_]i32{ -5, -3, -2 },
|
||||||
[_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 1, 0x0 },
|
[_]i32{ @as(i32, @bitCast(@as(u32, @intCast(0x80000000)))), 1, 0x0 },
|
||||||
[_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 2, 0x0 },
|
[_]i32{ @as(i32, @bitCast(@as(u32, @intCast(0x80000000)))), 2, 0x0 },
|
||||||
[_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), -2, 0x0 },
|
[_]i32{ @as(i32, @bitCast(@as(u32, @intCast(0x80000000)))), -2, 0x0 },
|
||||||
[_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 3, -2 },
|
[_]i32{ @as(i32, @bitCast(@as(u32, @intCast(0x80000000)))), 3, -2 },
|
||||||
[_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), -3, -2 },
|
[_]i32{ @as(i32, @bitCast(@as(u32, @intCast(0x80000000)))), -3, -2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (cases) |case| {
|
for (cases) |case| {
|
||||||
|
|||||||
@ -17,9 +17,9 @@ pub inline fn intFromFloat(comptime I: type, a: anytype) I {
|
|||||||
const sig_mask = (@as(rep_t, 1) << sig_bits) - 1;
|
const sig_mask = (@as(rep_t, 1) << sig_bits) - 1;
|
||||||
|
|
||||||
// Break a into sign, exponent, significand
|
// Break a into sign, exponent, significand
|
||||||
const a_rep: rep_t = @bitCast(rep_t, a);
|
const a_rep: rep_t = @as(rep_t, @bitCast(a));
|
||||||
const negative = (a_rep >> (float_bits - 1)) != 0;
|
const negative = (a_rep >> (float_bits - 1)) != 0;
|
||||||
const exponent = @intCast(i32, (a_rep << 1) >> (sig_bits + 1)) - exp_bias;
|
const exponent = @as(i32, @intCast((a_rep << 1) >> (sig_bits + 1))) - exp_bias;
|
||||||
const significand: rep_t = (a_rep & sig_mask) | implicit_bit;
|
const significand: rep_t = (a_rep & sig_mask) | implicit_bit;
|
||||||
|
|
||||||
// If the exponent is negative, the result rounds to zero.
|
// If the exponent is negative, the result rounds to zero.
|
||||||
@ -29,9 +29,9 @@ pub inline fn intFromFloat(comptime I: type, a: anytype) I {
|
|||||||
switch (@typeInfo(I).Int.signedness) {
|
switch (@typeInfo(I).Int.signedness) {
|
||||||
.unsigned => {
|
.unsigned => {
|
||||||
if (negative) return 0;
|
if (negative) return 0;
|
||||||
if (@intCast(c_uint, exponent) >= @min(int_bits, max_exp)) return math.maxInt(I);
|
if (@as(c_uint, @intCast(exponent)) >= @min(int_bits, max_exp)) return math.maxInt(I);
|
||||||
},
|
},
|
||||||
.signed => if (@intCast(c_uint, exponent) >= @min(int_bits - 1, max_exp)) {
|
.signed => if (@as(c_uint, @intCast(exponent)) >= @min(int_bits - 1, max_exp)) {
|
||||||
return if (negative) math.minInt(I) else math.maxInt(I);
|
return if (negative) math.minInt(I) else math.maxInt(I);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -40,9 +40,9 @@ pub inline fn intFromFloat(comptime I: type, a: anytype) I {
|
|||||||
// Otherwise, shift left.
|
// Otherwise, shift left.
|
||||||
var result: I = undefined;
|
var result: I = undefined;
|
||||||
if (exponent < fractional_bits) {
|
if (exponent < fractional_bits) {
|
||||||
result = @intCast(I, significand >> @intCast(Log2Int(rep_t), fractional_bits - exponent));
|
result = @as(I, @intCast(significand >> @as(Log2Int(rep_t), @intCast(fractional_bits - exponent))));
|
||||||
} else {
|
} else {
|
||||||
result = @intCast(I, significand) << @intCast(Log2Int(I), exponent - fractional_bits);
|
result = @as(I, @intCast(significand)) << @as(Log2Int(I), @intCast(exponent - fractional_bits));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((@typeInfo(I).Int.signedness == .signed) and negative)
|
if ((@typeInfo(I).Int.signedness == .signed) and negative)
|
||||||
|
|||||||
@ -27,7 +27,7 @@ comptime {
|
|||||||
|
|
||||||
pub fn __logh(a: f16) callconv(.C) f16 {
|
pub fn __logh(a: f16) callconv(.C) f16 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f16, logf(a));
|
return @as(f16, @floatCast(logf(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logf(x_: f32) callconv(.C) f32 {
|
pub fn logf(x_: f32) callconv(.C) f32 {
|
||||||
@ -39,7 +39,7 @@ pub fn logf(x_: f32) callconv(.C) f32 {
|
|||||||
const Lg4: f32 = 0xf89e26.0p-26;
|
const Lg4: f32 = 0xf89e26.0p-26;
|
||||||
|
|
||||||
var x = x_;
|
var x = x_;
|
||||||
var ix = @bitCast(u32, x);
|
var ix = @as(u32, @bitCast(x));
|
||||||
var k: i32 = 0;
|
var k: i32 = 0;
|
||||||
|
|
||||||
// x < 2^(-126)
|
// x < 2^(-126)
|
||||||
@ -56,7 +56,7 @@ pub fn logf(x_: f32) callconv(.C) f32 {
|
|||||||
// subnormal, scale x
|
// subnormal, scale x
|
||||||
k -= 25;
|
k -= 25;
|
||||||
x *= 0x1.0p25;
|
x *= 0x1.0p25;
|
||||||
ix = @bitCast(u32, x);
|
ix = @as(u32, @bitCast(x));
|
||||||
} else if (ix >= 0x7F800000) {
|
} else if (ix >= 0x7F800000) {
|
||||||
return x;
|
return x;
|
||||||
} else if (ix == 0x3F800000) {
|
} else if (ix == 0x3F800000) {
|
||||||
@ -65,9 +65,9 @@ pub fn logf(x_: f32) callconv(.C) f32 {
|
|||||||
|
|
||||||
// x into [sqrt(2) / 2, sqrt(2)]
|
// x into [sqrt(2) / 2, sqrt(2)]
|
||||||
ix += 0x3F800000 - 0x3F3504F3;
|
ix += 0x3F800000 - 0x3F3504F3;
|
||||||
k += @intCast(i32, ix >> 23) - 0x7F;
|
k += @as(i32, @intCast(ix >> 23)) - 0x7F;
|
||||||
ix = (ix & 0x007FFFFF) + 0x3F3504F3;
|
ix = (ix & 0x007FFFFF) + 0x3F3504F3;
|
||||||
x = @bitCast(f32, ix);
|
x = @as(f32, @bitCast(ix));
|
||||||
|
|
||||||
const f = x - 1.0;
|
const f = x - 1.0;
|
||||||
const s = f / (2.0 + f);
|
const s = f / (2.0 + f);
|
||||||
@ -77,7 +77,7 @@ pub fn logf(x_: f32) callconv(.C) f32 {
|
|||||||
const t2 = z * (Lg1 + w * Lg3);
|
const t2 = z * (Lg1 + w * Lg3);
|
||||||
const R = t2 + t1;
|
const R = t2 + t1;
|
||||||
const hfsq = 0.5 * f * f;
|
const hfsq = 0.5 * f * f;
|
||||||
const dk = @floatFromInt(f32, k);
|
const dk = @as(f32, @floatFromInt(k));
|
||||||
|
|
||||||
return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
|
return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
|
||||||
}
|
}
|
||||||
@ -94,8 +94,8 @@ pub fn log(x_: f64) callconv(.C) f64 {
|
|||||||
const Lg7: f64 = 1.479819860511658591e-01;
|
const Lg7: f64 = 1.479819860511658591e-01;
|
||||||
|
|
||||||
var x = x_;
|
var x = x_;
|
||||||
var ix = @bitCast(u64, x);
|
var ix = @as(u64, @bitCast(x));
|
||||||
var hx = @intCast(u32, ix >> 32);
|
var hx = @as(u32, @intCast(ix >> 32));
|
||||||
var k: i32 = 0;
|
var k: i32 = 0;
|
||||||
|
|
||||||
if (hx < 0x00100000 or hx >> 31 != 0) {
|
if (hx < 0x00100000 or hx >> 31 != 0) {
|
||||||
@ -111,7 +111,7 @@ pub fn log(x_: f64) callconv(.C) f64 {
|
|||||||
// subnormal, scale x
|
// subnormal, scale x
|
||||||
k -= 54;
|
k -= 54;
|
||||||
x *= 0x1.0p54;
|
x *= 0x1.0p54;
|
||||||
hx = @intCast(u32, @bitCast(u64, ix) >> 32);
|
hx = @as(u32, @intCast(@as(u64, @bitCast(ix)) >> 32));
|
||||||
} else if (hx >= 0x7FF00000) {
|
} else if (hx >= 0x7FF00000) {
|
||||||
return x;
|
return x;
|
||||||
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
||||||
@ -120,10 +120,10 @@ pub fn log(x_: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
// x into [sqrt(2) / 2, sqrt(2)]
|
// x into [sqrt(2) / 2, sqrt(2)]
|
||||||
hx += 0x3FF00000 - 0x3FE6A09E;
|
hx += 0x3FF00000 - 0x3FE6A09E;
|
||||||
k += @intCast(i32, hx >> 20) - 0x3FF;
|
k += @as(i32, @intCast(hx >> 20)) - 0x3FF;
|
||||||
hx = (hx & 0x000FFFFF) + 0x3FE6A09E;
|
hx = (hx & 0x000FFFFF) + 0x3FE6A09E;
|
||||||
ix = (@as(u64, hx) << 32) | (ix & 0xFFFFFFFF);
|
ix = (@as(u64, hx) << 32) | (ix & 0xFFFFFFFF);
|
||||||
x = @bitCast(f64, ix);
|
x = @as(f64, @bitCast(ix));
|
||||||
|
|
||||||
const f = x - 1.0;
|
const f = x - 1.0;
|
||||||
const hfsq = 0.5 * f * f;
|
const hfsq = 0.5 * f * f;
|
||||||
@ -133,19 +133,19 @@ pub fn log(x_: f64) callconv(.C) f64 {
|
|||||||
const t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
|
const t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
|
||||||
const t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
|
const t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
|
||||||
const R = t2 + t1;
|
const R = t2 + t1;
|
||||||
const dk = @floatFromInt(f64, k);
|
const dk = @as(f64, @floatFromInt(k));
|
||||||
|
|
||||||
return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
|
return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn __logx(a: f80) callconv(.C) f80 {
|
pub fn __logx(a: f80) callconv(.C) f80 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f80, logq(a));
|
return @as(f80, @floatCast(logq(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logq(a: f128) callconv(.C) f128 {
|
pub fn logq(a: f128) callconv(.C) f128 {
|
||||||
// TODO: more correct implementation
|
// TODO: more correct implementation
|
||||||
return log(@floatCast(f64, a));
|
return log(@as(f64, @floatCast(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logl(x: c_longdouble) callconv(.C) c_longdouble {
|
pub fn logl(x: c_longdouble) callconv(.C) c_longdouble {
|
||||||
|
|||||||
@ -28,7 +28,7 @@ comptime {
|
|||||||
|
|
||||||
pub fn __log10h(a: f16) callconv(.C) f16 {
|
pub fn __log10h(a: f16) callconv(.C) f16 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f16, log10f(a));
|
return @as(f16, @floatCast(log10f(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log10f(x_: f32) callconv(.C) f32 {
|
pub fn log10f(x_: f32) callconv(.C) f32 {
|
||||||
@ -42,7 +42,7 @@ pub fn log10f(x_: f32) callconv(.C) f32 {
|
|||||||
const Lg4: f32 = 0xf89e26.0p-26;
|
const Lg4: f32 = 0xf89e26.0p-26;
|
||||||
|
|
||||||
var x = x_;
|
var x = x_;
|
||||||
var u = @bitCast(u32, x);
|
var u = @as(u32, @bitCast(x));
|
||||||
var ix = u;
|
var ix = u;
|
||||||
var k: i32 = 0;
|
var k: i32 = 0;
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ pub fn log10f(x_: f32) callconv(.C) f32 {
|
|||||||
|
|
||||||
k -= 25;
|
k -= 25;
|
||||||
x *= 0x1.0p25;
|
x *= 0x1.0p25;
|
||||||
ix = @bitCast(u32, x);
|
ix = @as(u32, @bitCast(x));
|
||||||
} else if (ix >= 0x7F800000) {
|
} else if (ix >= 0x7F800000) {
|
||||||
return x;
|
return x;
|
||||||
} else if (ix == 0x3F800000) {
|
} else if (ix == 0x3F800000) {
|
||||||
@ -68,9 +68,9 @@ pub fn log10f(x_: f32) callconv(.C) f32 {
|
|||||||
|
|
||||||
// x into [sqrt(2) / 2, sqrt(2)]
|
// x into [sqrt(2) / 2, sqrt(2)]
|
||||||
ix += 0x3F800000 - 0x3F3504F3;
|
ix += 0x3F800000 - 0x3F3504F3;
|
||||||
k += @intCast(i32, ix >> 23) - 0x7F;
|
k += @as(i32, @intCast(ix >> 23)) - 0x7F;
|
||||||
ix = (ix & 0x007FFFFF) + 0x3F3504F3;
|
ix = (ix & 0x007FFFFF) + 0x3F3504F3;
|
||||||
x = @bitCast(f32, ix);
|
x = @as(f32, @bitCast(ix));
|
||||||
|
|
||||||
const f = x - 1.0;
|
const f = x - 1.0;
|
||||||
const s = f / (2.0 + f);
|
const s = f / (2.0 + f);
|
||||||
@ -82,11 +82,11 @@ pub fn log10f(x_: f32) callconv(.C) f32 {
|
|||||||
const hfsq = 0.5 * f * f;
|
const hfsq = 0.5 * f * f;
|
||||||
|
|
||||||
var hi = f - hfsq;
|
var hi = f - hfsq;
|
||||||
u = @bitCast(u32, hi);
|
u = @as(u32, @bitCast(hi));
|
||||||
u &= 0xFFFFF000;
|
u &= 0xFFFFF000;
|
||||||
hi = @bitCast(f32, u);
|
hi = @as(f32, @bitCast(u));
|
||||||
const lo = f - hi - hfsq + s * (hfsq + R);
|
const lo = f - hi - hfsq + s * (hfsq + R);
|
||||||
const dk = @floatFromInt(f32, k);
|
const dk = @as(f32, @floatFromInt(k));
|
||||||
|
|
||||||
return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;
|
return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;
|
||||||
}
|
}
|
||||||
@ -105,8 +105,8 @@ pub fn log10(x_: f64) callconv(.C) f64 {
|
|||||||
const Lg7: f64 = 1.479819860511658591e-01;
|
const Lg7: f64 = 1.479819860511658591e-01;
|
||||||
|
|
||||||
var x = x_;
|
var x = x_;
|
||||||
var ix = @bitCast(u64, x);
|
var ix = @as(u64, @bitCast(x));
|
||||||
var hx = @intCast(u32, ix >> 32);
|
var hx = @as(u32, @intCast(ix >> 32));
|
||||||
var k: i32 = 0;
|
var k: i32 = 0;
|
||||||
|
|
||||||
if (hx < 0x00100000 or hx >> 31 != 0) {
|
if (hx < 0x00100000 or hx >> 31 != 0) {
|
||||||
@ -122,7 +122,7 @@ pub fn log10(x_: f64) callconv(.C) f64 {
|
|||||||
// subnormal, scale x
|
// subnormal, scale x
|
||||||
k -= 54;
|
k -= 54;
|
||||||
x *= 0x1.0p54;
|
x *= 0x1.0p54;
|
||||||
hx = @intCast(u32, @bitCast(u64, x) >> 32);
|
hx = @as(u32, @intCast(@as(u64, @bitCast(x)) >> 32));
|
||||||
} else if (hx >= 0x7FF00000) {
|
} else if (hx >= 0x7FF00000) {
|
||||||
return x;
|
return x;
|
||||||
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
||||||
@ -131,10 +131,10 @@ pub fn log10(x_: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
// x into [sqrt(2) / 2, sqrt(2)]
|
// x into [sqrt(2) / 2, sqrt(2)]
|
||||||
hx += 0x3FF00000 - 0x3FE6A09E;
|
hx += 0x3FF00000 - 0x3FE6A09E;
|
||||||
k += @intCast(i32, hx >> 20) - 0x3FF;
|
k += @as(i32, @intCast(hx >> 20)) - 0x3FF;
|
||||||
hx = (hx & 0x000FFFFF) + 0x3FE6A09E;
|
hx = (hx & 0x000FFFFF) + 0x3FE6A09E;
|
||||||
ix = (@as(u64, hx) << 32) | (ix & 0xFFFFFFFF);
|
ix = (@as(u64, hx) << 32) | (ix & 0xFFFFFFFF);
|
||||||
x = @bitCast(f64, ix);
|
x = @as(f64, @bitCast(ix));
|
||||||
|
|
||||||
const f = x - 1.0;
|
const f = x - 1.0;
|
||||||
const hfsq = 0.5 * f * f;
|
const hfsq = 0.5 * f * f;
|
||||||
@ -147,14 +147,14 @@ pub fn log10(x_: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
// hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f)
|
// hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f)
|
||||||
var hi = f - hfsq;
|
var hi = f - hfsq;
|
||||||
var hii = @bitCast(u64, hi);
|
var hii = @as(u64, @bitCast(hi));
|
||||||
hii &= @as(u64, maxInt(u64)) << 32;
|
hii &= @as(u64, maxInt(u64)) << 32;
|
||||||
hi = @bitCast(f64, hii);
|
hi = @as(f64, @bitCast(hii));
|
||||||
const lo = f - hi - hfsq + s * (hfsq + R);
|
const lo = f - hi - hfsq + s * (hfsq + R);
|
||||||
|
|
||||||
// val_hi + val_lo ~ log10(1 + f) + k * log10(2)
|
// val_hi + val_lo ~ log10(1 + f) + k * log10(2)
|
||||||
var val_hi = hi * ivln10hi;
|
var val_hi = hi * ivln10hi;
|
||||||
const dk = @floatFromInt(f64, k);
|
const dk = @as(f64, @floatFromInt(k));
|
||||||
const y = dk * log10_2hi;
|
const y = dk * log10_2hi;
|
||||||
var val_lo = dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi;
|
var val_lo = dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi;
|
||||||
|
|
||||||
@ -168,12 +168,12 @@ pub fn log10(x_: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
pub fn __log10x(a: f80) callconv(.C) f80 {
|
pub fn __log10x(a: f80) callconv(.C) f80 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f80, log10q(a));
|
return @as(f80, @floatCast(log10q(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log10q(a: f128) callconv(.C) f128 {
|
pub fn log10q(a: f128) callconv(.C) f128 {
|
||||||
// TODO: more correct implementation
|
// TODO: more correct implementation
|
||||||
return log10(@floatCast(f64, a));
|
return log10(@as(f64, @floatCast(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log10l(x: c_longdouble) callconv(.C) c_longdouble {
|
pub fn log10l(x: c_longdouble) callconv(.C) c_longdouble {
|
||||||
|
|||||||
@ -28,7 +28,7 @@ comptime {
|
|||||||
|
|
||||||
pub fn __log2h(a: f16) callconv(.C) f16 {
|
pub fn __log2h(a: f16) callconv(.C) f16 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f16, log2f(a));
|
return @as(f16, @floatCast(log2f(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log2f(x_: f32) callconv(.C) f32 {
|
pub fn log2f(x_: f32) callconv(.C) f32 {
|
||||||
@ -40,7 +40,7 @@ pub fn log2f(x_: f32) callconv(.C) f32 {
|
|||||||
const Lg4: f32 = 0xf89e26.0p-26;
|
const Lg4: f32 = 0xf89e26.0p-26;
|
||||||
|
|
||||||
var x = x_;
|
var x = x_;
|
||||||
var u = @bitCast(u32, x);
|
var u = @as(u32, @bitCast(x));
|
||||||
var ix = u;
|
var ix = u;
|
||||||
var k: i32 = 0;
|
var k: i32 = 0;
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ pub fn log2f(x_: f32) callconv(.C) f32 {
|
|||||||
|
|
||||||
k -= 25;
|
k -= 25;
|
||||||
x *= 0x1.0p25;
|
x *= 0x1.0p25;
|
||||||
ix = @bitCast(u32, x);
|
ix = @as(u32, @bitCast(x));
|
||||||
} else if (ix >= 0x7F800000) {
|
} else if (ix >= 0x7F800000) {
|
||||||
return x;
|
return x;
|
||||||
} else if (ix == 0x3F800000) {
|
} else if (ix == 0x3F800000) {
|
||||||
@ -66,9 +66,9 @@ pub fn log2f(x_: f32) callconv(.C) f32 {
|
|||||||
|
|
||||||
// x into [sqrt(2) / 2, sqrt(2)]
|
// x into [sqrt(2) / 2, sqrt(2)]
|
||||||
ix += 0x3F800000 - 0x3F3504F3;
|
ix += 0x3F800000 - 0x3F3504F3;
|
||||||
k += @intCast(i32, ix >> 23) - 0x7F;
|
k += @as(i32, @intCast(ix >> 23)) - 0x7F;
|
||||||
ix = (ix & 0x007FFFFF) + 0x3F3504F3;
|
ix = (ix & 0x007FFFFF) + 0x3F3504F3;
|
||||||
x = @bitCast(f32, ix);
|
x = @as(f32, @bitCast(ix));
|
||||||
|
|
||||||
const f = x - 1.0;
|
const f = x - 1.0;
|
||||||
const s = f / (2.0 + f);
|
const s = f / (2.0 + f);
|
||||||
@ -80,11 +80,11 @@ pub fn log2f(x_: f32) callconv(.C) f32 {
|
|||||||
const hfsq = 0.5 * f * f;
|
const hfsq = 0.5 * f * f;
|
||||||
|
|
||||||
var hi = f - hfsq;
|
var hi = f - hfsq;
|
||||||
u = @bitCast(u32, hi);
|
u = @as(u32, @bitCast(hi));
|
||||||
u &= 0xFFFFF000;
|
u &= 0xFFFFF000;
|
||||||
hi = @bitCast(f32, u);
|
hi = @as(f32, @bitCast(u));
|
||||||
const lo = f - hi - hfsq + s * (hfsq + R);
|
const lo = f - hi - hfsq + s * (hfsq + R);
|
||||||
return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + @floatFromInt(f32, k);
|
return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + @as(f32, @floatFromInt(k));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log2(x_: f64) callconv(.C) f64 {
|
pub fn log2(x_: f64) callconv(.C) f64 {
|
||||||
@ -99,8 +99,8 @@ pub fn log2(x_: f64) callconv(.C) f64 {
|
|||||||
const Lg7: f64 = 1.479819860511658591e-01;
|
const Lg7: f64 = 1.479819860511658591e-01;
|
||||||
|
|
||||||
var x = x_;
|
var x = x_;
|
||||||
var ix = @bitCast(u64, x);
|
var ix = @as(u64, @bitCast(x));
|
||||||
var hx = @intCast(u32, ix >> 32);
|
var hx = @as(u32, @intCast(ix >> 32));
|
||||||
var k: i32 = 0;
|
var k: i32 = 0;
|
||||||
|
|
||||||
if (hx < 0x00100000 or hx >> 31 != 0) {
|
if (hx < 0x00100000 or hx >> 31 != 0) {
|
||||||
@ -116,7 +116,7 @@ pub fn log2(x_: f64) callconv(.C) f64 {
|
|||||||
// subnormal, scale x
|
// subnormal, scale x
|
||||||
k -= 54;
|
k -= 54;
|
||||||
x *= 0x1.0p54;
|
x *= 0x1.0p54;
|
||||||
hx = @intCast(u32, @bitCast(u64, x) >> 32);
|
hx = @as(u32, @intCast(@as(u64, @bitCast(x)) >> 32));
|
||||||
} else if (hx >= 0x7FF00000) {
|
} else if (hx >= 0x7FF00000) {
|
||||||
return x;
|
return x;
|
||||||
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
|
||||||
@ -125,10 +125,10 @@ pub fn log2(x_: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
// x into [sqrt(2) / 2, sqrt(2)]
|
// x into [sqrt(2) / 2, sqrt(2)]
|
||||||
hx += 0x3FF00000 - 0x3FE6A09E;
|
hx += 0x3FF00000 - 0x3FE6A09E;
|
||||||
k += @intCast(i32, hx >> 20) - 0x3FF;
|
k += @as(i32, @intCast(hx >> 20)) - 0x3FF;
|
||||||
hx = (hx & 0x000FFFFF) + 0x3FE6A09E;
|
hx = (hx & 0x000FFFFF) + 0x3FE6A09E;
|
||||||
ix = (@as(u64, hx) << 32) | (ix & 0xFFFFFFFF);
|
ix = (@as(u64, hx) << 32) | (ix & 0xFFFFFFFF);
|
||||||
x = @bitCast(f64, ix);
|
x = @as(f64, @bitCast(ix));
|
||||||
|
|
||||||
const f = x - 1.0;
|
const f = x - 1.0;
|
||||||
const hfsq = 0.5 * f * f;
|
const hfsq = 0.5 * f * f;
|
||||||
@ -141,16 +141,16 @@ pub fn log2(x_: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
// hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f)
|
// hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f)
|
||||||
var hi = f - hfsq;
|
var hi = f - hfsq;
|
||||||
var hii = @bitCast(u64, hi);
|
var hii = @as(u64, @bitCast(hi));
|
||||||
hii &= @as(u64, maxInt(u64)) << 32;
|
hii &= @as(u64, maxInt(u64)) << 32;
|
||||||
hi = @bitCast(f64, hii);
|
hi = @as(f64, @bitCast(hii));
|
||||||
const lo = f - hi - hfsq + s * (hfsq + R);
|
const lo = f - hi - hfsq + s * (hfsq + R);
|
||||||
|
|
||||||
var val_hi = hi * ivln2hi;
|
var val_hi = hi * ivln2hi;
|
||||||
var val_lo = (lo + hi) * ivln2lo + lo * ivln2hi;
|
var val_lo = (lo + hi) * ivln2lo + lo * ivln2hi;
|
||||||
|
|
||||||
// spadd(val_hi, val_lo, y)
|
// spadd(val_hi, val_lo, y)
|
||||||
const y = @floatFromInt(f64, k);
|
const y = @as(f64, @floatFromInt(k));
|
||||||
const ww = y + val_hi;
|
const ww = y + val_hi;
|
||||||
val_lo += (y - ww) + val_hi;
|
val_lo += (y - ww) + val_hi;
|
||||||
val_hi = ww;
|
val_hi = ww;
|
||||||
@ -160,12 +160,12 @@ pub fn log2(x_: f64) callconv(.C) f64 {
|
|||||||
|
|
||||||
pub fn __log2x(a: f80) callconv(.C) f80 {
|
pub fn __log2x(a: f80) callconv(.C) f80 {
|
||||||
// TODO: more efficient implementation
|
// TODO: more efficient implementation
|
||||||
return @floatCast(f80, log2q(a));
|
return @as(f80, @floatCast(log2q(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log2q(a: f128) callconv(.C) f128 {
|
pub fn log2q(a: f128) callconv(.C) f128 {
|
||||||
// TODO: more correct implementation
|
// TODO: more correct implementation
|
||||||
return log2(@floatCast(f64, a));
|
return log2(@as(f64, @floatCast(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log2l(x: c_longdouble) callconv(.C) c_longdouble {
|
pub fn log2l(x: c_longdouble) callconv(.C) c_longdouble {
|
||||||
|
|||||||
@ -24,7 +24,7 @@ pub fn __modti3(a: i128, b: i128) callconv(.C) i128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __modti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 {
|
fn __modti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, mod(@bitCast(i128, a), @bitCast(i128, b)));
|
return @as(v2u64, @bitCast(mod(@as(i128, @bitCast(a)), @as(i128, @bitCast(b)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn mod(a: i128, b: i128) i128 {
|
inline fn mod(a: i128, b: i128) i128 {
|
||||||
@ -35,8 +35,8 @@ inline fn mod(a: i128, b: i128) i128 {
|
|||||||
const bn = (b ^ s_b) -% s_b; // negate if s == -1
|
const bn = (b ^ s_b) -% s_b; // negate if s == -1
|
||||||
|
|
||||||
var r: u128 = undefined;
|
var r: u128 = undefined;
|
||||||
_ = udivmod(u128, @bitCast(u128, an), @bitCast(u128, bn), &r);
|
_ = udivmod(u128, @as(u128, @bitCast(an)), @as(u128, @bitCast(bn)), &r);
|
||||||
return (@bitCast(i128, r) ^ s_a) -% s_a; // negate if s == -1
|
return (@as(i128, @bitCast(r)) ^ s_a) -% s_a; // negate if s == -1
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@ -33,5 +33,5 @@ fn make_ti(high: u64, low: u64) i128 {
|
|||||||
var result: u128 = high;
|
var result: u128 = high;
|
||||||
result <<= 64;
|
result <<= 64;
|
||||||
result |= low;
|
result |= low;
|
||||||
return @bitCast(i128, result);
|
return @as(i128, @bitCast(result));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,8 +21,8 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 {
|
pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 {
|
||||||
var ua = @bitCast(u32, a);
|
var ua = @as(u32, @bitCast(a));
|
||||||
var ub = @bitCast(u32, b);
|
var ub = @as(u32, @bitCast(b));
|
||||||
var r: u32 = 0;
|
var r: u32 = 0;
|
||||||
|
|
||||||
while (ua > 0) {
|
while (ua > 0) {
|
||||||
@ -31,7 +31,7 @@ pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 {
|
|||||||
ub <<= 1;
|
ub <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return @bitCast(i32, r);
|
return @as(i32, @bitCast(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn __muldi3(a: i64, b: i64) callconv(.C) i64 {
|
pub fn __muldi3(a: i64, b: i64) callconv(.C) i64 {
|
||||||
@ -93,7 +93,7 @@ pub fn __multi3(a: i128, b: i128) callconv(.C) i128 {
|
|||||||
const v2u64 = @Vector(2, u64);
|
const v2u64 = @Vector(2, u64);
|
||||||
|
|
||||||
fn __multi3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 {
|
fn __multi3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 {
|
||||||
return @bitCast(v2u64, mulX(i128, @bitCast(i128, a), @bitCast(i128, b)));
|
return @as(v2u64, @bitCast(mulX(i128, @as(i128, @bitCast(a)), @as(i128, @bitCast(b)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@ -46,14 +46,14 @@ test "mulsi3" {
|
|||||||
try test_one_mulsi3(-46340, 46340, -2147395600);
|
try test_one_mulsi3(-46340, 46340, -2147395600);
|
||||||
try test_one_mulsi3(46340, -46340, -2147395600);
|
try test_one_mulsi3(46340, -46340, -2147395600);
|
||||||
try test_one_mulsi3(-46340, -46340, 2147395600);
|
try test_one_mulsi3(-46340, -46340, 2147395600);
|
||||||
try test_one_mulsi3(4194303, 8192, @truncate(i32, 34359730176));
|
try test_one_mulsi3(4194303, 8192, @as(i32, @truncate(34359730176)));
|
||||||
try test_one_mulsi3(-4194303, 8192, @truncate(i32, -34359730176));
|
try test_one_mulsi3(-4194303, 8192, @as(i32, @truncate(-34359730176)));
|
||||||
try test_one_mulsi3(4194303, -8192, @truncate(i32, -34359730176));
|
try test_one_mulsi3(4194303, -8192, @as(i32, @truncate(-34359730176)));
|
||||||
try test_one_mulsi3(-4194303, -8192, @truncate(i32, 34359730176));
|
try test_one_mulsi3(-4194303, -8192, @as(i32, @truncate(34359730176)));
|
||||||
try test_one_mulsi3(8192, 4194303, @truncate(i32, 34359730176));
|
try test_one_mulsi3(8192, 4194303, @as(i32, @truncate(34359730176)));
|
||||||
try test_one_mulsi3(-8192, 4194303, @truncate(i32, -34359730176));
|
try test_one_mulsi3(-8192, 4194303, @as(i32, @truncate(-34359730176)));
|
||||||
try test_one_mulsi3(8192, -4194303, @truncate(i32, -34359730176));
|
try test_one_mulsi3(8192, -4194303, @as(i32, @truncate(-34359730176)));
|
||||||
try test_one_mulsi3(-8192, -4194303, @truncate(i32, 34359730176));
|
try test_one_mulsi3(-8192, -4194303, @as(i32, @truncate(34359730176)));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "muldi3" {
|
test "muldi3" {
|
||||||
|
|||||||
@ -28,53 +28,53 @@ pub inline fn mulf3(comptime T: type, a: T, b: T) T {
|
|||||||
const significandMask = (@as(Z, 1) << significandBits) - 1;
|
const significandMask = (@as(Z, 1) << significandBits) - 1;
|
||||||
|
|
||||||
const absMask = signBit - 1;
|
const absMask = signBit - 1;
|
||||||
const qnanRep = @bitCast(Z, math.nan(T)) | quietBit;
|
const qnanRep = @as(Z, @bitCast(math.nan(T))) | quietBit;
|
||||||
const infRep = @bitCast(Z, math.inf(T));
|
const infRep = @as(Z, @bitCast(math.inf(T)));
|
||||||
const minNormalRep = @bitCast(Z, math.floatMin(T));
|
const minNormalRep = @as(Z, @bitCast(math.floatMin(T)));
|
||||||
|
|
||||||
const ZExp = if (typeWidth >= 32) u32 else Z;
|
const ZExp = if (typeWidth >= 32) u32 else Z;
|
||||||
const aExponent = @truncate(ZExp, (@bitCast(Z, a) >> significandBits) & maxExponent);
|
const aExponent = @as(ZExp, @truncate((@as(Z, @bitCast(a)) >> significandBits) & maxExponent));
|
||||||
const bExponent = @truncate(ZExp, (@bitCast(Z, b) >> significandBits) & maxExponent);
|
const bExponent = @as(ZExp, @truncate((@as(Z, @bitCast(b)) >> significandBits) & maxExponent));
|
||||||
const productSign: Z = (@bitCast(Z, a) ^ @bitCast(Z, b)) & signBit;
|
const productSign: Z = (@as(Z, @bitCast(a)) ^ @as(Z, @bitCast(b))) & signBit;
|
||||||
|
|
||||||
var aSignificand: ZSignificand = @intCast(ZSignificand, @bitCast(Z, a) & significandMask);
|
var aSignificand: ZSignificand = @as(ZSignificand, @intCast(@as(Z, @bitCast(a)) & significandMask));
|
||||||
var bSignificand: ZSignificand = @intCast(ZSignificand, @bitCast(Z, b) & significandMask);
|
var bSignificand: ZSignificand = @as(ZSignificand, @intCast(@as(Z, @bitCast(b)) & significandMask));
|
||||||
var scale: i32 = 0;
|
var scale: i32 = 0;
|
||||||
|
|
||||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
// Detect if a or b is zero, denormal, infinity, or NaN.
|
||||||
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
||||||
const aAbs: Z = @bitCast(Z, a) & absMask;
|
const aAbs: Z = @as(Z, @bitCast(a)) & absMask;
|
||||||
const bAbs: Z = @bitCast(Z, b) & absMask;
|
const bAbs: Z = @as(Z, @bitCast(b)) & absMask;
|
||||||
|
|
||||||
// NaN * anything = qNaN
|
// NaN * anything = qNaN
|
||||||
if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);
|
if (aAbs > infRep) return @as(T, @bitCast(@as(Z, @bitCast(a)) | quietBit));
|
||||||
// anything * NaN = qNaN
|
// anything * NaN = qNaN
|
||||||
if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit);
|
if (bAbs > infRep) return @as(T, @bitCast(@as(Z, @bitCast(b)) | quietBit));
|
||||||
|
|
||||||
if (aAbs == infRep) {
|
if (aAbs == infRep) {
|
||||||
// infinity * non-zero = +/- infinity
|
// infinity * non-zero = +/- infinity
|
||||||
if (bAbs != 0) {
|
if (bAbs != 0) {
|
||||||
return @bitCast(T, aAbs | productSign);
|
return @as(T, @bitCast(aAbs | productSign));
|
||||||
} else {
|
} else {
|
||||||
// infinity * zero = NaN
|
// infinity * zero = NaN
|
||||||
return @bitCast(T, qnanRep);
|
return @as(T, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bAbs == infRep) {
|
if (bAbs == infRep) {
|
||||||
//? non-zero * infinity = +/- infinity
|
//? non-zero * infinity = +/- infinity
|
||||||
if (aAbs != 0) {
|
if (aAbs != 0) {
|
||||||
return @bitCast(T, bAbs | productSign);
|
return @as(T, @bitCast(bAbs | productSign));
|
||||||
} else {
|
} else {
|
||||||
// zero * infinity = NaN
|
// zero * infinity = NaN
|
||||||
return @bitCast(T, qnanRep);
|
return @as(T, @bitCast(qnanRep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// zero * anything = +/- zero
|
// zero * anything = +/- zero
|
||||||
if (aAbs == 0) return @bitCast(T, productSign);
|
if (aAbs == 0) return @as(T, @bitCast(productSign));
|
||||||
// anything * zero = +/- zero
|
// anything * zero = +/- zero
|
||||||
if (bAbs == 0) return @bitCast(T, productSign);
|
if (bAbs == 0) return @as(T, @bitCast(productSign));
|
||||||
|
|
||||||
// one or both of a or b is denormal, the other (if applicable) is a
|
// one or both of a or b is denormal, the other (if applicable) is a
|
||||||
// normal number. Renormalize one or both of a and b, and set scale to
|
// normal number. Renormalize one or both of a and b, and set scale to
|
||||||
@ -99,7 +99,7 @@ pub inline fn mulf3(comptime T: type, a: T, b: T) T {
|
|||||||
const left_align_shift = ZSignificandBits - fractionalBits - 1;
|
const left_align_shift = ZSignificandBits - fractionalBits - 1;
|
||||||
common.wideMultiply(ZSignificand, aSignificand, bSignificand << left_align_shift, &productHi, &productLo);
|
common.wideMultiply(ZSignificand, aSignificand, bSignificand << left_align_shift, &productHi, &productLo);
|
||||||
|
|
||||||
var productExponent: i32 = @intCast(i32, aExponent + bExponent) - exponentBias + scale;
|
var productExponent: i32 = @as(i32, @intCast(aExponent + bExponent)) - exponentBias + scale;
|
||||||
|
|
||||||
// Normalize the significand, adjust exponent if needed.
|
// Normalize the significand, adjust exponent if needed.
|
||||||
if ((productHi & integerBit) != 0) {
|
if ((productHi & integerBit) != 0) {
|
||||||
@ -110,7 +110,7 @@ pub inline fn mulf3(comptime T: type, a: T, b: T) T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we have overflowed the type, return +/- infinity.
|
// If we have overflowed the type, return +/- infinity.
|
||||||
if (productExponent >= maxExponent) return @bitCast(T, infRep | productSign);
|
if (productExponent >= maxExponent) return @as(T, @bitCast(infRep | productSign));
|
||||||
|
|
||||||
var result: Z = undefined;
|
var result: Z = undefined;
|
||||||
if (productExponent <= 0) {
|
if (productExponent <= 0) {
|
||||||
@ -120,8 +120,8 @@ pub inline fn mulf3(comptime T: type, a: T, b: T) T {
|
|||||||
// a zero of the appropriate sign. Mathematically there is no need to
|
// a zero of the appropriate sign. Mathematically there is no need to
|
||||||
// handle this case separately, but we make it a special case to
|
// handle this case separately, but we make it a special case to
|
||||||
// simplify the shift logic.
|
// simplify the shift logic.
|
||||||
const shift: u32 = @truncate(u32, @as(Z, 1) -% @bitCast(u32, productExponent));
|
const shift: u32 = @as(u32, @truncate(@as(Z, 1) -% @as(u32, @bitCast(productExponent))));
|
||||||
if (shift >= ZSignificandBits) return @bitCast(T, productSign);
|
if (shift >= ZSignificandBits) return @as(T, @bitCast(productSign));
|
||||||
|
|
||||||
// Otherwise, shift the significand of the result so that the round
|
// Otherwise, shift the significand of the result so that the round
|
||||||
// bit is the high bit of productLo.
|
// bit is the high bit of productLo.
|
||||||
@ -135,7 +135,7 @@ pub inline fn mulf3(comptime T: type, a: T, b: T) T {
|
|||||||
} else {
|
} else {
|
||||||
// Result is normal before rounding; insert the exponent.
|
// Result is normal before rounding; insert the exponent.
|
||||||
result = productHi & significandMask;
|
result = productHi & significandMask;
|
||||||
result |= @intCast(Z, productExponent) << significandBits;
|
result |= @as(Z, @intCast(productExponent)) << significandBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final rounding. The final result may overflow to infinity, or underflow
|
// Final rounding. The final result may overflow to infinity, or underflow
|
||||||
@ -156,7 +156,7 @@ pub inline fn mulf3(comptime T: type, a: T, b: T) T {
|
|||||||
// Insert the sign of the result:
|
// Insert the sign of the result:
|
||||||
result |= productSign;
|
result |= productSign;
|
||||||
|
|
||||||
return @bitCast(T, result);
|
return @as(T, @bitCast(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the right shift is inexact (i.e. any bit shifted out is non-zero)
|
/// Returns `true` if the right shift is inexact (i.e. any bit shifted out is non-zero)
|
||||||
@ -168,12 +168,12 @@ fn wideShrWithTruncation(comptime Z: type, hi: *Z, lo: *Z, count: u32) bool {
|
|||||||
const S = math.Log2Int(Z);
|
const S = math.Log2Int(Z);
|
||||||
var inexact = false;
|
var inexact = false;
|
||||||
if (count < typeWidth) {
|
if (count < typeWidth) {
|
||||||
inexact = (lo.* << @intCast(S, typeWidth -% count)) != 0;
|
inexact = (lo.* << @as(S, @intCast(typeWidth -% count))) != 0;
|
||||||
lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count));
|
lo.* = (hi.* << @as(S, @intCast(typeWidth -% count))) | (lo.* >> @as(S, @intCast(count)));
|
||||||
hi.* = hi.* >> @intCast(S, count);
|
hi.* = hi.* >> @as(S, @intCast(count));
|
||||||
} else if (count < 2 * typeWidth) {
|
} else if (count < 2 * typeWidth) {
|
||||||
inexact = (hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*) != 0;
|
inexact = (hi.* << @as(S, @intCast(2 * typeWidth -% count)) | lo.*) != 0;
|
||||||
lo.* = hi.* >> @intCast(S, count -% typeWidth);
|
lo.* = hi.* >> @as(S, @intCast(count -% typeWidth));
|
||||||
hi.* = 0;
|
hi.* = 0;
|
||||||
} else {
|
} else {
|
||||||
inexact = (hi.* | lo.*) != 0;
|
inexact = (hi.* | lo.*) != 0;
|
||||||
@ -188,7 +188,7 @@ fn normalize(comptime T: type, significand: *PowerOfTwoSignificandZ(T)) i32 {
|
|||||||
const integerBit = @as(Z, 1) << math.floatFractionalBits(T);
|
const integerBit = @as(Z, 1) << math.floatFractionalBits(T);
|
||||||
|
|
||||||
const shift = @clz(significand.*) - @clz(integerBit);
|
const shift = @clz(significand.*) - @clz(integerBit);
|
||||||
significand.* <<= @intCast(math.Log2Int(Z), shift);
|
significand.* <<= @as(math.Log2Int(Z), @intCast(shift));
|
||||||
return @as(i32, 1) - shift;
|
return @as(i32, 1) - shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64);
|
const qnan128 = @as(f128, @bitCast(@as(u128, 0x7fff800000000000) << 64));
|
||||||
const inf128 = @bitCast(f128, @as(u128, 0x7fff000000000000) << 64);
|
const inf128 = @as(f128, @bitCast(@as(u128, 0x7fff000000000000) << 64));
|
||||||
|
|
||||||
const __multf3 = @import("multf3.zig").__multf3;
|
const __multf3 = @import("multf3.zig").__multf3;
|
||||||
const __mulxf3 = @import("mulxf3.zig").__mulxf3;
|
const __mulxf3 = @import("mulxf3.zig").__mulxf3;
|
||||||
@ -16,9 +16,9 @@ const __mulsf3 = @import("mulsf3.zig").__mulsf3;
|
|||||||
// use two 64-bit integers intead of one 128-bit integer
|
// use two 64-bit integers intead of one 128-bit integer
|
||||||
// because 128-bit integer constant can't be assigned directly
|
// because 128-bit integer constant can't be assigned directly
|
||||||
fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
|
fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool {
|
||||||
const rep = @bitCast(u128, result);
|
const rep = @as(u128, @bitCast(result));
|
||||||
const hi = @intCast(u64, rep >> 64);
|
const hi = @as(u64, @intCast(rep >> 64));
|
||||||
const lo = @truncate(u64, rep);
|
const lo = @as(u64, @truncate(rep));
|
||||||
|
|
||||||
if (hi == expectedHi and lo == expectedLo) {
|
if (hi == expectedHi and lo == expectedLo) {
|
||||||
return true;
|
return true;
|
||||||
@ -45,7 +45,7 @@ fn test__multf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
|
|||||||
|
|
||||||
fn makeNaN128(rand: u64) f128 {
|
fn makeNaN128(rand: u64) f128 {
|
||||||
const int_result = @as(u128, 0x7fff000000000000 | (rand & 0xffffffffffff)) << 64;
|
const int_result = @as(u128, 0x7fff000000000000 | (rand & 0xffffffffffff)) << 64;
|
||||||
const float_result = @bitCast(f128, int_result);
|
const float_result = @as(f128, @bitCast(int_result));
|
||||||
return float_result;
|
return float_result;
|
||||||
}
|
}
|
||||||
test "multf3" {
|
test "multf3" {
|
||||||
@ -60,15 +60,15 @@ test "multf3" {
|
|||||||
|
|
||||||
// any * any
|
// any * any
|
||||||
try test__multf3(
|
try test__multf3(
|
||||||
@bitCast(f128, @as(u128, 0x40042eab345678439abcdefea5678234)),
|
@as(f128, @bitCast(@as(u128, 0x40042eab345678439abcdefea5678234))),
|
||||||
@bitCast(f128, @as(u128, 0x3ffeedcb34a235253948765432134675)),
|
@as(f128, @bitCast(@as(u128, 0x3ffeedcb34a235253948765432134675))),
|
||||||
0x400423e7f9e3c9fc,
|
0x400423e7f9e3c9fc,
|
||||||
0xd906c2c2a85777c4,
|
0xd906c2c2a85777c4,
|
||||||
);
|
);
|
||||||
|
|
||||||
try test__multf3(
|
try test__multf3(
|
||||||
@bitCast(f128, @as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50)),
|
@as(f128, @bitCast(@as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50))),
|
||||||
@bitCast(f128, @as(u128, 0x3ff6ed8764648369535adf4be3214568)),
|
@as(f128, @bitCast(@as(u128, 0x3ff6ed8764648369535adf4be3214568))),
|
||||||
0x3fc52a163c6223fc,
|
0x3fc52a163c6223fc,
|
||||||
0xc94c4bf0430768b4,
|
0xc94c4bf0430768b4,
|
||||||
);
|
);
|
||||||
@ -81,8 +81,8 @@ test "multf3" {
|
|||||||
);
|
);
|
||||||
|
|
||||||
try test__multf3(
|
try test__multf3(
|
||||||
@bitCast(f128, @as(u128, 0x3f154356473c82a9fabf2d22ace345df)),
|
@as(f128, @bitCast(@as(u128, 0x3f154356473c82a9fabf2d22ace345df))),
|
||||||
@bitCast(f128, @as(u128, 0x3e38eda98765476743ab21da23d45679)),
|
@as(f128, @bitCast(@as(u128, 0x3e38eda98765476743ab21da23d45679))),
|
||||||
0x3d4f37c1a3137cae,
|
0x3d4f37c1a3137cae,
|
||||||
0xfc6807048bc2836a,
|
0xfc6807048bc2836a,
|
||||||
);
|
);
|
||||||
@ -108,16 +108,16 @@ test "multf3" {
|
|||||||
try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002);
|
try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002);
|
||||||
}
|
}
|
||||||
|
|
||||||
const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1)));
|
const qnan80 = @as(f80, @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1))));
|
||||||
|
|
||||||
fn test__mulxf3(a: f80, b: f80, expected: u80) !void {
|
fn test__mulxf3(a: f80, b: f80, expected: u80) !void {
|
||||||
const x = __mulxf3(a, b);
|
const x = __mulxf3(a, b);
|
||||||
const rep = @bitCast(u80, x);
|
const rep = @as(u80, @bitCast(x));
|
||||||
|
|
||||||
if (rep == expected)
|
if (rep == expected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (math.isNan(@bitCast(f80, expected)) and math.isNan(x))
|
if (math.isNan(@as(f80, @bitCast(expected))) and math.isNan(x))
|
||||||
return; // We don't currently test NaN payload propagation
|
return; // We don't currently test NaN payload propagation
|
||||||
|
|
||||||
return error.TestFailed;
|
return error.TestFailed;
|
||||||
@ -125,33 +125,33 @@ fn test__mulxf3(a: f80, b: f80, expected: u80) !void {
|
|||||||
|
|
||||||
test "mulxf3" {
|
test "mulxf3" {
|
||||||
// NaN * any = NaN
|
// NaN * any = NaN
|
||||||
try test__mulxf3(qnan80, 0x1.23456789abcdefp+5, @bitCast(u80, qnan80));
|
try test__mulxf3(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
|
||||||
try test__mulxf3(@bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), 0x1.23456789abcdefp+5, @bitCast(u80, qnan80));
|
try test__mulxf3(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80)));
|
||||||
|
|
||||||
// any * NaN = NaN
|
// any * NaN = NaN
|
||||||
try test__mulxf3(0x1.23456789abcdefp+5, qnan80, @bitCast(u80, qnan80));
|
try test__mulxf3(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80)));
|
||||||
try test__mulxf3(0x1.23456789abcdefp+5, @bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), @bitCast(u80, qnan80));
|
try test__mulxf3(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80)));
|
||||||
|
|
||||||
// NaN * inf = NaN
|
// NaN * inf = NaN
|
||||||
try test__mulxf3(qnan80, math.inf(f80), @bitCast(u80, qnan80));
|
try test__mulxf3(qnan80, math.inf(f80), @as(u80, @bitCast(qnan80)));
|
||||||
|
|
||||||
// inf * NaN = NaN
|
// inf * NaN = NaN
|
||||||
try test__mulxf3(math.inf(f80), qnan80, @bitCast(u80, qnan80));
|
try test__mulxf3(math.inf(f80), qnan80, @as(u80, @bitCast(qnan80)));
|
||||||
|
|
||||||
// inf * inf = inf
|
// inf * inf = inf
|
||||||
try test__mulxf3(math.inf(f80), math.inf(f80), @bitCast(u80, math.inf(f80)));
|
try test__mulxf3(math.inf(f80), math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
|
||||||
|
|
||||||
// inf * -inf = -inf
|
// inf * -inf = -inf
|
||||||
try test__mulxf3(math.inf(f80), -math.inf(f80), @bitCast(u80, -math.inf(f80)));
|
try test__mulxf3(math.inf(f80), -math.inf(f80), @as(u80, @bitCast(-math.inf(f80))));
|
||||||
|
|
||||||
// -inf + inf = -inf
|
// -inf + inf = -inf
|
||||||
try test__mulxf3(-math.inf(f80), math.inf(f80), @bitCast(u80, -math.inf(f80)));
|
try test__mulxf3(-math.inf(f80), math.inf(f80), @as(u80, @bitCast(-math.inf(f80))));
|
||||||
|
|
||||||
// inf * any = inf
|
// inf * any = inf
|
||||||
try test__mulxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @bitCast(u80, math.inf(f80)));
|
try test__mulxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @as(u80, @bitCast(math.inf(f80))));
|
||||||
|
|
||||||
// any * inf = inf
|
// any * inf = inf
|
||||||
try test__mulxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @bitCast(u80, math.inf(f80)));
|
try test__mulxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @as(u80, @bitCast(math.inf(f80))));
|
||||||
|
|
||||||
// any * any
|
// any * any
|
||||||
try test__mulxf3(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800);
|
try test__mulxf3(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800);
|
||||||
|
|||||||
@ -45,7 +45,7 @@ inline fn muloXi4_genericFast(comptime ST: type, a: ST, b: ST, overflow: *c_int)
|
|||||||
//invariant: -2^{bitwidth(EST)} < res < 2^{bitwidth(EST)-1}
|
//invariant: -2^{bitwidth(EST)} < res < 2^{bitwidth(EST)-1}
|
||||||
if (res < min or max < res)
|
if (res < min or max < res)
|
||||||
overflow.* = 1;
|
overflow.* = 1;
|
||||||
return @truncate(ST, res);
|
return @as(ST, @truncate(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn __mulosi4(a: i32, b: i32, overflow: *c_int) callconv(.C) i32 {
|
pub fn __mulosi4(a: i32, b: i32, overflow: *c_int) callconv(.C) i32 {
|
||||||
|
|||||||
@ -54,34 +54,34 @@ test "mulodi4" {
|
|||||||
|
|
||||||
try test__mulodi4(0x7FFFFFFFFFFFFFFF, -2, 2, 1);
|
try test__mulodi4(0x7FFFFFFFFFFFFFFF, -2, 2, 1);
|
||||||
try test__mulodi4(-2, 0x7FFFFFFFFFFFFFFF, 2, 1);
|
try test__mulodi4(-2, 0x7FFFFFFFFFFFFFFF, 2, 1);
|
||||||
try test__mulodi4(0x7FFFFFFFFFFFFFFF, -1, @bitCast(i64, @as(u64, 0x8000000000000001)), 0);
|
try test__mulodi4(0x7FFFFFFFFFFFFFFF, -1, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), 0);
|
||||||
try test__mulodi4(-1, 0x7FFFFFFFFFFFFFFF, @bitCast(i64, @as(u64, 0x8000000000000001)), 0);
|
try test__mulodi4(-1, 0x7FFFFFFFFFFFFFFF, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), 0);
|
||||||
try test__mulodi4(0x7FFFFFFFFFFFFFFF, 0, 0, 0);
|
try test__mulodi4(0x7FFFFFFFFFFFFFFF, 0, 0, 0);
|
||||||
try test__mulodi4(0, 0x7FFFFFFFFFFFFFFF, 0, 0);
|
try test__mulodi4(0, 0x7FFFFFFFFFFFFFFF, 0, 0);
|
||||||
try test__mulodi4(0x7FFFFFFFFFFFFFFF, 1, 0x7FFFFFFFFFFFFFFF, 0);
|
try test__mulodi4(0x7FFFFFFFFFFFFFFF, 1, 0x7FFFFFFFFFFFFFFF, 0);
|
||||||
try test__mulodi4(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF, 0);
|
try test__mulodi4(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF, 0);
|
||||||
try test__mulodi4(0x7FFFFFFFFFFFFFFF, 2, @bitCast(i64, @as(u64, 0x8000000000000001)), 1);
|
try test__mulodi4(0x7FFFFFFFFFFFFFFF, 2, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), 1);
|
||||||
try test__mulodi4(2, 0x7FFFFFFFFFFFFFFF, @bitCast(i64, @as(u64, 0x8000000000000001)), 1);
|
try test__mulodi4(2, 0x7FFFFFFFFFFFFFFF, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), 1);
|
||||||
|
|
||||||
try test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000000)), -2, @bitCast(i64, @as(u64, 0x8000000000000000)), 1);
|
try test__mulodi4(@as(i64, @bitCast(@as(u64, 0x8000000000000000))), -2, @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1);
|
||||||
try test__mulodi4(-2, @bitCast(i64, @as(u64, 0x8000000000000000)), @bitCast(i64, @as(u64, 0x8000000000000000)), 1);
|
try test__mulodi4(-2, @as(i64, @bitCast(@as(u64, 0x8000000000000000))), @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1);
|
||||||
try test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000000)), -1, @bitCast(i64, @as(u64, 0x8000000000000000)), 1);
|
try test__mulodi4(@as(i64, @bitCast(@as(u64, 0x8000000000000000))), -1, @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1);
|
||||||
try test__mulodi4(-1, @bitCast(i64, @as(u64, 0x8000000000000000)), @bitCast(i64, @as(u64, 0x8000000000000000)), 1);
|
try test__mulodi4(-1, @as(i64, @bitCast(@as(u64, 0x8000000000000000))), @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1);
|
||||||
try test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000000)), 0, 0, 0);
|
try test__mulodi4(@as(i64, @bitCast(@as(u64, 0x8000000000000000))), 0, 0, 0);
|
||||||
try test__mulodi4(0, @bitCast(i64, @as(u64, 0x8000000000000000)), 0, 0);
|
try test__mulodi4(0, @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 0, 0);
|
||||||
try test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000000)), 1, @bitCast(i64, @as(u64, 0x8000000000000000)), 0);
|
try test__mulodi4(@as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1, @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 0);
|
||||||
try test__mulodi4(1, @bitCast(i64, @as(u64, 0x8000000000000000)), @bitCast(i64, @as(u64, 0x8000000000000000)), 0);
|
try test__mulodi4(1, @as(i64, @bitCast(@as(u64, 0x8000000000000000))), @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 0);
|
||||||
try test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000000)), 2, @bitCast(i64, @as(u64, 0x8000000000000000)), 1);
|
try test__mulodi4(@as(i64, @bitCast(@as(u64, 0x8000000000000000))), 2, @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1);
|
||||||
try test__mulodi4(2, @bitCast(i64, @as(u64, 0x8000000000000000)), @bitCast(i64, @as(u64, 0x8000000000000000)), 1);
|
try test__mulodi4(2, @as(i64, @bitCast(@as(u64, 0x8000000000000000))), @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1);
|
||||||
|
|
||||||
try test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000001)), -2, @bitCast(i64, @as(u64, 0x8000000000000001)), 1);
|
try test__mulodi4(@as(i64, @bitCast(@as(u64, 0x8000000000000001))), -2, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), 1);
|
||||||
try test__mulodi4(-2, @bitCast(i64, @as(u64, 0x8000000000000001)), @bitCast(i64, @as(u64, 0x8000000000000001)), 1);
|
try test__mulodi4(-2, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), @as(i64, @bitCast(@as(u64, 0x8000000000000001))), 1);
|
||||||
try test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000001)), -1, 0x7FFFFFFFFFFFFFFF, 0);
|
try test__mulodi4(@as(i64, @bitCast(@as(u64, 0x8000000000000001))), -1, 0x7FFFFFFFFFFFFFFF, 0);
|
||||||
try test__mulodi4(-1, @bitCast(i64, @as(u64, 0x8000000000000001)), 0x7FFFFFFFFFFFFFFF, 0);
|
try test__mulodi4(-1, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), 0x7FFFFFFFFFFFFFFF, 0);
|
||||||
try test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000001)), 0, 0, 0);
|
try test__mulodi4(@as(i64, @bitCast(@as(u64, 0x8000000000000001))), 0, 0, 0);
|
||||||
try test__mulodi4(0, @bitCast(i64, @as(u64, 0x8000000000000001)), 0, 0);
|
try test__mulodi4(0, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), 0, 0);
|
||||||
try test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000001)), 1, @bitCast(i64, @as(u64, 0x8000000000000001)), 0);
|
try test__mulodi4(@as(i64, @bitCast(@as(u64, 0x8000000000000001))), 1, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), 0);
|
||||||
try test__mulodi4(1, @bitCast(i64, @as(u64, 0x8000000000000001)), @bitCast(i64, @as(u64, 0x8000000000000001)), 0);
|
try test__mulodi4(1, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), @as(i64, @bitCast(@as(u64, 0x8000000000000001))), 0);
|
||||||
try test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000001)), 2, @bitCast(i64, @as(u64, 0x8000000000000000)), 1);
|
try test__mulodi4(@as(i64, @bitCast(@as(u64, 0x8000000000000001))), 2, @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1);
|
||||||
try test__mulodi4(2, @bitCast(i64, @as(u64, 0x8000000000000001)), @bitCast(i64, @as(u64, 0x8000000000000000)), 1);
|
try test__mulodi4(2, @as(i64, @bitCast(@as(u64, 0x8000000000000001))), @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,36 +37,36 @@ test "mulosi4" {
|
|||||||
try test__mulosi4(1, -0x1234567, -0x1234567, 0);
|
try test__mulosi4(1, -0x1234567, -0x1234567, 0);
|
||||||
try test__mulosi4(-0x1234567, 1, -0x1234567, 0);
|
try test__mulosi4(-0x1234567, 1, -0x1234567, 0);
|
||||||
|
|
||||||
try test__mulosi4(0x7FFFFFFF, -2, @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__mulosi4(0x7FFFFFFF, -2, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
try test__mulosi4(-2, 0x7FFFFFFF, @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__mulosi4(-2, 0x7FFFFFFF, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
try test__mulosi4(0x7FFFFFFF, -1, @bitCast(i32, @as(u32, 0x80000001)), 0);
|
try test__mulosi4(0x7FFFFFFF, -1, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
|
||||||
try test__mulosi4(-1, 0x7FFFFFFF, @bitCast(i32, @as(u32, 0x80000001)), 0);
|
try test__mulosi4(-1, 0x7FFFFFFF, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
|
||||||
try test__mulosi4(0x7FFFFFFF, 0, 0, 0);
|
try test__mulosi4(0x7FFFFFFF, 0, 0, 0);
|
||||||
try test__mulosi4(0, 0x7FFFFFFF, 0, 0);
|
try test__mulosi4(0, 0x7FFFFFFF, 0, 0);
|
||||||
try test__mulosi4(0x7FFFFFFF, 1, 0x7FFFFFFF, 0);
|
try test__mulosi4(0x7FFFFFFF, 1, 0x7FFFFFFF, 0);
|
||||||
try test__mulosi4(1, 0x7FFFFFFF, 0x7FFFFFFF, 0);
|
try test__mulosi4(1, 0x7FFFFFFF, 0x7FFFFFFF, 0);
|
||||||
try test__mulosi4(0x7FFFFFFF, 2, @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__mulosi4(0x7FFFFFFF, 2, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
try test__mulosi4(2, 0x7FFFFFFF, @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__mulosi4(2, 0x7FFFFFFF, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
|
|
||||||
try test__mulosi4(@bitCast(i32, @as(u32, 0x80000000)), -2, @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__mulosi4(@as(i32, @bitCast(@as(u32, 0x80000000))), -2, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
try test__mulosi4(-2, @bitCast(i32, @as(u32, 0x80000000)), @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__mulosi4(-2, @as(i32, @bitCast(@as(u32, 0x80000000))), @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
try test__mulosi4(@bitCast(i32, @as(u32, 0x80000000)), -1, @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__mulosi4(@as(i32, @bitCast(@as(u32, 0x80000000))), -1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
try test__mulosi4(-1, @bitCast(i32, @as(u32, 0x80000000)), @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__mulosi4(-1, @as(i32, @bitCast(@as(u32, 0x80000000))), @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
try test__mulosi4(@bitCast(i32, @as(u32, 0x80000000)), 0, 0, 0);
|
try test__mulosi4(@as(i32, @bitCast(@as(u32, 0x80000000))), 0, 0, 0);
|
||||||
try test__mulosi4(0, @bitCast(i32, @as(u32, 0x80000000)), 0, 0);
|
try test__mulosi4(0, @as(i32, @bitCast(@as(u32, 0x80000000))), 0, 0);
|
||||||
try test__mulosi4(@bitCast(i32, @as(u32, 0x80000000)), 1, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__mulosi4(@as(i32, @bitCast(@as(u32, 0x80000000))), 1, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
try test__mulosi4(1, @bitCast(i32, @as(u32, 0x80000000)), @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__mulosi4(1, @as(i32, @bitCast(@as(u32, 0x80000000))), @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
try test__mulosi4(@bitCast(i32, @as(u32, 0x80000000)), 2, @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__mulosi4(@as(i32, @bitCast(@as(u32, 0x80000000))), 2, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
try test__mulosi4(2, @bitCast(i32, @as(u32, 0x80000000)), @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__mulosi4(2, @as(i32, @bitCast(@as(u32, 0x80000000))), @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
|
|
||||||
try test__mulosi4(@bitCast(i32, @as(u32, 0x80000001)), -2, @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__mulosi4(@as(i32, @bitCast(@as(u32, 0x80000001))), -2, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
try test__mulosi4(-2, @bitCast(i32, @as(u32, 0x80000001)), @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__mulosi4(-2, @as(i32, @bitCast(@as(u32, 0x80000001))), @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
try test__mulosi4(@bitCast(i32, @as(u32, 0x80000001)), -1, 0x7FFFFFFF, 0);
|
try test__mulosi4(@as(i32, @bitCast(@as(u32, 0x80000001))), -1, 0x7FFFFFFF, 0);
|
||||||
try test__mulosi4(-1, @bitCast(i32, @as(u32, 0x80000001)), 0x7FFFFFFF, 0);
|
try test__mulosi4(-1, @as(i32, @bitCast(@as(u32, 0x80000001))), 0x7FFFFFFF, 0);
|
||||||
try test__mulosi4(@bitCast(i32, @as(u32, 0x80000001)), 0, 0, 0);
|
try test__mulosi4(@as(i32, @bitCast(@as(u32, 0x80000001))), 0, 0, 0);
|
||||||
try test__mulosi4(0, @bitCast(i32, @as(u32, 0x80000001)), 0, 0);
|
try test__mulosi4(0, @as(i32, @bitCast(@as(u32, 0x80000001))), 0, 0);
|
||||||
try test__mulosi4(@bitCast(i32, @as(u32, 0x80000001)), 1, @bitCast(i32, @as(u32, 0x80000001)), 0);
|
try test__mulosi4(@as(i32, @bitCast(@as(u32, 0x80000001))), 1, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
|
||||||
try test__mulosi4(1, @bitCast(i32, @as(u32, 0x80000001)), @bitCast(i32, @as(u32, 0x80000001)), 0);
|
try test__mulosi4(1, @as(i32, @bitCast(@as(u32, 0x80000001))), @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
|
||||||
try test__mulosi4(@bitCast(i32, @as(u32, 0x80000001)), 2, @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__mulosi4(@as(i32, @bitCast(@as(u32, 0x80000001))), 2, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
try test__mulosi4(2, @bitCast(i32, @as(u32, 0x80000001)), @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__mulosi4(2, @as(i32, @bitCast(@as(u32, 0x80000001))), @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,38 +52,38 @@ test "muloti4" {
|
|||||||
try test__muloti4(2097152, -4398046511103, -9223372036852678656, 0);
|
try test__muloti4(2097152, -4398046511103, -9223372036852678656, 0);
|
||||||
try test__muloti4(-2097152, -4398046511103, 9223372036852678656, 0);
|
try test__muloti4(-2097152, -4398046511103, 9223372036852678656, 0);
|
||||||
|
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x00000000000000B504F333F9DE5BE000)), @bitCast(i128, @as(u128, 0x000000000000000000B504F333F9DE5B)), @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFF328DF915DA296E8A000)), 0);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x00000000000000B504F333F9DE5BE000))), @as(i128, @bitCast(@as(u128, 0x000000000000000000B504F333F9DE5B))), @as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFF328DF915DA296E8A000))), 0);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), -2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), -2, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 1);
|
||||||
try test__muloti4(-2, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1);
|
try test__muloti4(-2, @as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 1);
|
||||||
|
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), -1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), -1, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 0);
|
||||||
try test__muloti4(-1, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0);
|
try test__muloti4(-1, @as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 0);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0, 0, 0);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), 0, 0, 0);
|
||||||
try test__muloti4(0, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0, 0);
|
try test__muloti4(0, @as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), 0, 0);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 1, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), 1, @as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), 0);
|
||||||
try test__muloti4(1, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0);
|
try test__muloti4(1, @as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), @as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), 0);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), 2, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 1);
|
||||||
try test__muloti4(2, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1);
|
try test__muloti4(2, @as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 1);
|
||||||
|
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), -2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), -2, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 1);
|
||||||
try test__muloti4(-2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1);
|
try test__muloti4(-2, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 1);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), -1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), -1, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 1);
|
||||||
try test__muloti4(-1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1);
|
try test__muloti4(-1, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 1);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 0, 0, 0);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 0, 0, 0);
|
||||||
try test__muloti4(0, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 0, 0);
|
try test__muloti4(0, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 0, 0);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 0);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 1, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 0);
|
||||||
try test__muloti4(1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 0);
|
try test__muloti4(1, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 0);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 2, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 1);
|
||||||
try test__muloti4(2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1);
|
try test__muloti4(2, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 1);
|
||||||
|
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), -2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), -2, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 1);
|
||||||
try test__muloti4(-2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1);
|
try test__muloti4(-2, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 1);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), -1, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), -1, @as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), 0);
|
||||||
try test__muloti4(-1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0);
|
try test__muloti4(-1, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), @as(i128, @bitCast(@as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), 0);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0, 0, 0);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 0, 0, 0);
|
||||||
try test__muloti4(0, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0, 0);
|
try test__muloti4(0, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 0, 0);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 1, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 0);
|
||||||
try test__muloti4(1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0);
|
try test__muloti4(1, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 0);
|
||||||
try test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1);
|
try test__muloti4(@as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), 2, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 1);
|
||||||
try test__muloti4(2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1);
|
try test__muloti4(2, @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000001))), @as(i128, @bitCast(@as(u128, 0x80000000000000000000000000000000))), 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,7 @@ inline fn negvXi(comptime ST: type, a: ST) ST {
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
const N: UT = @bitSizeOf(ST);
|
const N: UT = @bitSizeOf(ST);
|
||||||
const min: ST = @bitCast(ST, (@as(UT, 1) << (N - 1)));
|
const min: ST = @as(ST, @bitCast((@as(UT, 1) << (N - 1))));
|
||||||
if (a == min)
|
if (a == min)
|
||||||
@panic("compiler_rt negv: overflow");
|
@panic("compiler_rt negv: overflow");
|
||||||
return -a;
|
return -a;
|
||||||
|
|||||||
@ -27,9 +27,9 @@ pub fn __parityti2(a: i128) callconv(.C) i32 {
|
|||||||
|
|
||||||
inline fn parityXi2(comptime T: type, a: T) i32 {
|
inline fn parityXi2(comptime T: type, a: T) i32 {
|
||||||
var x = switch (@bitSizeOf(T)) {
|
var x = switch (@bitSizeOf(T)) {
|
||||||
32 => @bitCast(u32, a),
|
32 => @as(u32, @bitCast(a)),
|
||||||
64 => @bitCast(u64, a),
|
64 => @as(u64, @bitCast(a)),
|
||||||
128 => @bitCast(u128, a),
|
128 => @as(u128, @bitCast(a)),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
// Bit Twiddling Hacks: Compute parity in parallel
|
// Bit Twiddling Hacks: Compute parity in parallel
|
||||||
@ -39,7 +39,7 @@ inline fn parityXi2(comptime T: type, a: T) i32 {
|
|||||||
shift = shift >> 1;
|
shift = shift >> 1;
|
||||||
}
|
}
|
||||||
x &= 0xf;
|
x &= 0xf;
|
||||||
return (@intCast(u16, 0x6996) >> @intCast(u4, x)) & 1; // optimization for >>2 and >>1
|
return (@as(u16, @intCast(0x6996)) >> @as(u4, @intCast(x))) & 1; // optimization for >>2 and >>1
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@ -3,13 +3,13 @@ const parity = @import("parity.zig");
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
|
|
||||||
fn paritydi2Naive(a: i64) i32 {
|
fn paritydi2Naive(a: i64) i32 {
|
||||||
var x = @bitCast(u64, a);
|
var x = @as(u64, @bitCast(a));
|
||||||
var has_parity: bool = false;
|
var has_parity: bool = false;
|
||||||
while (x > 0) {
|
while (x > 0) {
|
||||||
has_parity = !has_parity;
|
has_parity = !has_parity;
|
||||||
x = x & (x - 1);
|
x = x & (x - 1);
|
||||||
}
|
}
|
||||||
return @intCast(i32, @intFromBool(has_parity));
|
return @as(i32, @intCast(@intFromBool(has_parity)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test__paritydi2(a: i64) !void {
|
fn test__paritydi2(a: i64) !void {
|
||||||
@ -22,9 +22,9 @@ test "paritydi2" {
|
|||||||
try test__paritydi2(0);
|
try test__paritydi2(0);
|
||||||
try test__paritydi2(1);
|
try test__paritydi2(1);
|
||||||
try test__paritydi2(2);
|
try test__paritydi2(2);
|
||||||
try test__paritydi2(@bitCast(i64, @as(u64, 0xffffffff_fffffffd)));
|
try test__paritydi2(@as(i64, @bitCast(@as(u64, 0xffffffff_fffffffd))));
|
||||||
try test__paritydi2(@bitCast(i64, @as(u64, 0xffffffff_fffffffe)));
|
try test__paritydi2(@as(i64, @bitCast(@as(u64, 0xffffffff_fffffffe))));
|
||||||
try test__paritydi2(@bitCast(i64, @as(u64, 0xffffffff_ffffffff)));
|
try test__paritydi2(@as(i64, @bitCast(@as(u64, 0xffffffff_ffffffff))));
|
||||||
|
|
||||||
const RndGen = std.rand.DefaultPrng;
|
const RndGen = std.rand.DefaultPrng;
|
||||||
var rnd = RndGen.init(42);
|
var rnd = RndGen.init(42);
|
||||||
|
|||||||
@ -3,13 +3,13 @@ const parity = @import("parity.zig");
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
|
|
||||||
fn paritysi2Naive(a: i32) i32 {
|
fn paritysi2Naive(a: i32) i32 {
|
||||||
var x = @bitCast(u32, a);
|
var x = @as(u32, @bitCast(a));
|
||||||
var has_parity: bool = false;
|
var has_parity: bool = false;
|
||||||
while (x > 0) {
|
while (x > 0) {
|
||||||
has_parity = !has_parity;
|
has_parity = !has_parity;
|
||||||
x = x & (x - 1);
|
x = x & (x - 1);
|
||||||
}
|
}
|
||||||
return @intCast(i32, @intFromBool(has_parity));
|
return @as(i32, @intCast(@intFromBool(has_parity)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test__paritysi2(a: i32) !void {
|
fn test__paritysi2(a: i32) !void {
|
||||||
@ -22,9 +22,9 @@ test "paritysi2" {
|
|||||||
try test__paritysi2(0);
|
try test__paritysi2(0);
|
||||||
try test__paritysi2(1);
|
try test__paritysi2(1);
|
||||||
try test__paritysi2(2);
|
try test__paritysi2(2);
|
||||||
try test__paritysi2(@bitCast(i32, @as(u32, 0xfffffffd)));
|
try test__paritysi2(@as(i32, @bitCast(@as(u32, 0xfffffffd))));
|
||||||
try test__paritysi2(@bitCast(i32, @as(u32, 0xfffffffe)));
|
try test__paritysi2(@as(i32, @bitCast(@as(u32, 0xfffffffe))));
|
||||||
try test__paritysi2(@bitCast(i32, @as(u32, 0xffffffff)));
|
try test__paritysi2(@as(i32, @bitCast(@as(u32, 0xffffffff))));
|
||||||
|
|
||||||
const RndGen = std.rand.DefaultPrng;
|
const RndGen = std.rand.DefaultPrng;
|
||||||
var rnd = RndGen.init(42);
|
var rnd = RndGen.init(42);
|
||||||
|
|||||||
@ -3,13 +3,13 @@ const parity = @import("parity.zig");
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
|
|
||||||
fn parityti2Naive(a: i128) i32 {
|
fn parityti2Naive(a: i128) i32 {
|
||||||
var x = @bitCast(u128, a);
|
var x = @as(u128, @bitCast(a));
|
||||||
var has_parity: bool = false;
|
var has_parity: bool = false;
|
||||||
while (x > 0) {
|
while (x > 0) {
|
||||||
has_parity = !has_parity;
|
has_parity = !has_parity;
|
||||||
x = x & (x - 1);
|
x = x & (x - 1);
|
||||||
}
|
}
|
||||||
return @intCast(i32, @intFromBool(has_parity));
|
return @as(i32, @intCast(@intFromBool(has_parity)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test__parityti2(a: i128) !void {
|
fn test__parityti2(a: i128) !void {
|
||||||
@ -22,9 +22,9 @@ test "parityti2" {
|
|||||||
try test__parityti2(0);
|
try test__parityti2(0);
|
||||||
try test__parityti2(1);
|
try test__parityti2(1);
|
||||||
try test__parityti2(2);
|
try test__parityti2(2);
|
||||||
try test__parityti2(@bitCast(i128, @as(u128, 0xffffffff_ffffffff_ffffffff_fffffffd)));
|
try test__parityti2(@as(i128, @bitCast(@as(u128, 0xffffffff_ffffffff_ffffffff_fffffffd))));
|
||||||
try test__parityti2(@bitCast(i128, @as(u128, 0xffffffff_ffffffff_ffffffff_fffffffe)));
|
try test__parityti2(@as(i128, @bitCast(@as(u128, 0xffffffff_ffffffff_ffffffff_fffffffe))));
|
||||||
try test__parityti2(@bitCast(i128, @as(u128, 0xffffffff_ffffffff_ffffffff_ffffffff)));
|
try test__parityti2(@as(i128, @bitCast(@as(u128, 0xffffffff_ffffffff_ffffffff_ffffffff))));
|
||||||
|
|
||||||
const RndGen = std.rand.DefaultPrng;
|
const RndGen = std.rand.DefaultPrng;
|
||||||
var rnd = RndGen.init(42);
|
var rnd = RndGen.init(42);
|
||||||
|
|||||||
@ -37,7 +37,7 @@ inline fn popcountXi2(comptime ST: type, a: ST) i32 {
|
|||||||
i128 => u128,
|
i128 => u128,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
var x = @bitCast(UT, a);
|
var x = @as(UT, @bitCast(a));
|
||||||
x -= (x >> 1) & (~@as(UT, 0) / 3); // 0x55...55, aggregate duos
|
x -= (x >> 1) & (~@as(UT, 0) / 3); // 0x55...55, aggregate duos
|
||||||
x = ((x >> 2) & (~@as(UT, 0) / 5)) // 0x33...33, aggregate nibbles
|
x = ((x >> 2) & (~@as(UT, 0) / 5)) // 0x33...33, aggregate nibbles
|
||||||
+ (x & (~@as(UT, 0) / 5));
|
+ (x & (~@as(UT, 0) / 5));
|
||||||
@ -46,7 +46,7 @@ inline fn popcountXi2(comptime ST: type, a: ST) i32 {
|
|||||||
// 8 most significant bits of x + (x<<8) + (x<<16) + ..
|
// 8 most significant bits of x + (x<<8) + (x<<16) + ..
|
||||||
x *%= ~@as(UT, 0) / 255; // 0x01...01
|
x *%= ~@as(UT, 0) / 255; // 0x01...01
|
||||||
x >>= (@bitSizeOf(ST) - 8);
|
x >>= (@bitSizeOf(ST) - 8);
|
||||||
return @intCast(i32, x);
|
return @as(i32, @intCast(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@ -5,8 +5,8 @@ const testing = std.testing;
|
|||||||
fn popcountdi2Naive(a: i64) i32 {
|
fn popcountdi2Naive(a: i64) i32 {
|
||||||
var x = a;
|
var x = a;
|
||||||
var r: i32 = 0;
|
var r: i32 = 0;
|
||||||
while (x != 0) : (x = @bitCast(i64, @bitCast(u64, x) >> 1)) {
|
while (x != 0) : (x = @as(i64, @bitCast(@as(u64, @bitCast(x)) >> 1))) {
|
||||||
r += @intCast(i32, x & 1);
|
r += @as(i32, @intCast(x & 1));
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -21,9 +21,9 @@ test "popcountdi2" {
|
|||||||
try test__popcountdi2(0);
|
try test__popcountdi2(0);
|
||||||
try test__popcountdi2(1);
|
try test__popcountdi2(1);
|
||||||
try test__popcountdi2(2);
|
try test__popcountdi2(2);
|
||||||
try test__popcountdi2(@bitCast(i64, @as(u64, 0xffffffff_fffffffd)));
|
try test__popcountdi2(@as(i64, @bitCast(@as(u64, 0xffffffff_fffffffd))));
|
||||||
try test__popcountdi2(@bitCast(i64, @as(u64, 0xffffffff_fffffffe)));
|
try test__popcountdi2(@as(i64, @bitCast(@as(u64, 0xffffffff_fffffffe))));
|
||||||
try test__popcountdi2(@bitCast(i64, @as(u64, 0xffffffff_ffffffff)));
|
try test__popcountdi2(@as(i64, @bitCast(@as(u64, 0xffffffff_ffffffff))));
|
||||||
|
|
||||||
const RndGen = std.rand.DefaultPrng;
|
const RndGen = std.rand.DefaultPrng;
|
||||||
var rnd = RndGen.init(42);
|
var rnd = RndGen.init(42);
|
||||||
|
|||||||
@ -5,8 +5,8 @@ const testing = std.testing;
|
|||||||
fn popcountsi2Naive(a: i32) i32 {
|
fn popcountsi2Naive(a: i32) i32 {
|
||||||
var x = a;
|
var x = a;
|
||||||
var r: i32 = 0;
|
var r: i32 = 0;
|
||||||
while (x != 0) : (x = @bitCast(i32, @bitCast(u32, x) >> 1)) {
|
while (x != 0) : (x = @as(i32, @bitCast(@as(u32, @bitCast(x)) >> 1))) {
|
||||||
r += @intCast(i32, x & 1);
|
r += @as(i32, @intCast(x & 1));
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -21,9 +21,9 @@ test "popcountsi2" {
|
|||||||
try test__popcountsi2(0);
|
try test__popcountsi2(0);
|
||||||
try test__popcountsi2(1);
|
try test__popcountsi2(1);
|
||||||
try test__popcountsi2(2);
|
try test__popcountsi2(2);
|
||||||
try test__popcountsi2(@bitCast(i32, @as(u32, 0xfffffffd)));
|
try test__popcountsi2(@as(i32, @bitCast(@as(u32, 0xfffffffd))));
|
||||||
try test__popcountsi2(@bitCast(i32, @as(u32, 0xfffffffe)));
|
try test__popcountsi2(@as(i32, @bitCast(@as(u32, 0xfffffffe))));
|
||||||
try test__popcountsi2(@bitCast(i32, @as(u32, 0xffffffff)));
|
try test__popcountsi2(@as(i32, @bitCast(@as(u32, 0xffffffff))));
|
||||||
|
|
||||||
const RndGen = std.rand.DefaultPrng;
|
const RndGen = std.rand.DefaultPrng;
|
||||||
var rnd = RndGen.init(42);
|
var rnd = RndGen.init(42);
|
||||||
|
|||||||
@ -5,8 +5,8 @@ const testing = std.testing;
|
|||||||
fn popcountti2Naive(a: i128) i32 {
|
fn popcountti2Naive(a: i128) i32 {
|
||||||
var x = a;
|
var x = a;
|
||||||
var r: i32 = 0;
|
var r: i32 = 0;
|
||||||
while (x != 0) : (x = @bitCast(i128, @bitCast(u128, x) >> 1)) {
|
while (x != 0) : (x = @as(i128, @bitCast(@as(u128, @bitCast(x)) >> 1))) {
|
||||||
r += @intCast(i32, x & 1);
|
r += @as(i32, @intCast(x & 1));
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -21,9 +21,9 @@ test "popcountti2" {
|
|||||||
try test__popcountti2(0);
|
try test__popcountti2(0);
|
||||||
try test__popcountti2(1);
|
try test__popcountti2(1);
|
||||||
try test__popcountti2(2);
|
try test__popcountti2(2);
|
||||||
try test__popcountti2(@bitCast(i128, @as(u128, 0xffffffff_ffffffff_ffffffff_fffffffd)));
|
try test__popcountti2(@as(i128, @bitCast(@as(u128, 0xffffffff_ffffffff_ffffffff_fffffffd))));
|
||||||
try test__popcountti2(@bitCast(i128, @as(u128, 0xffffffff_ffffffff_ffffffff_fffffffe)));
|
try test__popcountti2(@as(i128, @bitCast(@as(u128, 0xffffffff_ffffffff_ffffffff_fffffffe))));
|
||||||
try test__popcountti2(@bitCast(i128, @as(u128, 0xffffffff_ffffffff_ffffffff_ffffffff)));
|
try test__popcountti2(@as(i128, @bitCast(@as(u128, 0xffffffff_ffffffff_ffffffff_ffffffff))));
|
||||||
|
|
||||||
const RndGen = std.rand.DefaultPrng;
|
const RndGen = std.rand.DefaultPrng;
|
||||||
var rnd = RndGen.init(42);
|
var rnd = RndGen.init(42);
|
||||||
|
|||||||
@ -25,7 +25,7 @@ inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT {
|
|||||||
const is_recip: bool = b < 0;
|
const is_recip: bool = b < 0;
|
||||||
var r: FT = 1.0;
|
var r: FT = 1.0;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (@bitCast(u32, x_b) & @as(u32, 1) != 0) {
|
if (@as(u32, @bitCast(x_b)) & @as(u32, 1) != 0) {
|
||||||
r *= x_a;
|
r *= x_a;
|
||||||
}
|
}
|
||||||
x_b = @divTrunc(x_b, @as(i32, 2));
|
x_b = @divTrunc(x_b, @as(i32, 2));
|
||||||
|
|||||||
@ -49,76 +49,76 @@ test "powihf2" {
|
|||||||
try test__powihf2(0, 2, 0);
|
try test__powihf2(0, 2, 0);
|
||||||
try test__powihf2(0, 3, 0);
|
try test__powihf2(0, 3, 0);
|
||||||
try test__powihf2(0, 4, 0);
|
try test__powihf2(0, 4, 0);
|
||||||
try test__powihf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
|
try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
|
||||||
try test__powihf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 0);
|
try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
|
||||||
|
|
||||||
try test__powihf2(-0.0, 1, -0.0);
|
try test__powihf2(-0.0, 1, -0.0);
|
||||||
try test__powihf2(-0.0, 2, 0);
|
try test__powihf2(-0.0, 2, 0);
|
||||||
try test__powihf2(-0.0, 3, -0.0);
|
try test__powihf2(-0.0, 3, -0.0);
|
||||||
try test__powihf2(-0.0, 4, 0);
|
try test__powihf2(-0.0, 4, 0);
|
||||||
try test__powihf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
|
try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
|
||||||
try test__powihf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -0.0);
|
try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
|
||||||
|
|
||||||
try test__powihf2(1, 1, 1);
|
try test__powihf2(1, 1, 1);
|
||||||
try test__powihf2(1, 2, 1);
|
try test__powihf2(1, 2, 1);
|
||||||
try test__powihf2(1, 3, 1);
|
try test__powihf2(1, 3, 1);
|
||||||
try test__powihf2(1, 4, 1);
|
try test__powihf2(1, 4, 1);
|
||||||
try test__powihf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 1);
|
try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
|
||||||
try test__powihf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 1);
|
try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
|
||||||
|
|
||||||
try test__powihf2(inf_f16, 1, inf_f16);
|
try test__powihf2(inf_f16, 1, inf_f16);
|
||||||
try test__powihf2(inf_f16, 2, inf_f16);
|
try test__powihf2(inf_f16, 2, inf_f16);
|
||||||
try test__powihf2(inf_f16, 3, inf_f16);
|
try test__powihf2(inf_f16, 3, inf_f16);
|
||||||
try test__powihf2(inf_f16, 4, inf_f16);
|
try test__powihf2(inf_f16, 4, inf_f16);
|
||||||
try test__powihf2(inf_f16, @bitCast(i32, @as(u32, 0x7FFFFFFE)), inf_f16);
|
try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
|
||||||
try test__powihf2(inf_f16, @bitCast(i32, @as(u32, 0x7FFFFFFF)), inf_f16);
|
try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16);
|
||||||
|
|
||||||
try test__powihf2(-inf_f16, 1, -inf_f16);
|
try test__powihf2(-inf_f16, 1, -inf_f16);
|
||||||
try test__powihf2(-inf_f16, 2, inf_f16);
|
try test__powihf2(-inf_f16, 2, inf_f16);
|
||||||
try test__powihf2(-inf_f16, 3, -inf_f16);
|
try test__powihf2(-inf_f16, 3, -inf_f16);
|
||||||
try test__powihf2(-inf_f16, 4, inf_f16);
|
try test__powihf2(-inf_f16, 4, inf_f16);
|
||||||
try test__powihf2(-inf_f16, @bitCast(i32, @as(u32, 0x7FFFFFFE)), inf_f16);
|
try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16);
|
||||||
try test__powihf2(-inf_f16, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -inf_f16);
|
try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16);
|
||||||
//
|
//
|
||||||
try test__powihf2(0, -1, inf_f16);
|
try test__powihf2(0, -1, inf_f16);
|
||||||
try test__powihf2(0, -2, inf_f16);
|
try test__powihf2(0, -2, inf_f16);
|
||||||
try test__powihf2(0, -3, inf_f16);
|
try test__powihf2(0, -3, inf_f16);
|
||||||
try test__powihf2(0, -4, inf_f16);
|
try test__powihf2(0, -4, inf_f16);
|
||||||
try test__powihf2(0, @bitCast(i32, @as(u32, 0x80000002)), inf_f16); // 0 ^ anything = +inf
|
try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf
|
||||||
try test__powihf2(0, @bitCast(i32, @as(u32, 0x80000001)), inf_f16);
|
try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16);
|
||||||
try test__powihf2(0, @bitCast(i32, @as(u32, 0x80000000)), inf_f16);
|
try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
|
||||||
|
|
||||||
try test__powihf2(-0.0, -1, -inf_f16);
|
try test__powihf2(-0.0, -1, -inf_f16);
|
||||||
try test__powihf2(-0.0, -2, inf_f16);
|
try test__powihf2(-0.0, -2, inf_f16);
|
||||||
try test__powihf2(-0.0, -3, -inf_f16);
|
try test__powihf2(-0.0, -3, -inf_f16);
|
||||||
try test__powihf2(-0.0, -4, inf_f16);
|
try test__powihf2(-0.0, -4, inf_f16);
|
||||||
try test__powihf2(-0.0, @bitCast(i32, @as(u32, 0x80000002)), inf_f16); // -0 ^ anything even = +inf
|
try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf
|
||||||
try test__powihf2(-0.0, @bitCast(i32, @as(u32, 0x80000001)), -inf_f16); // -0 ^ anything odd = -inf
|
try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf
|
||||||
try test__powihf2(-0.0, @bitCast(i32, @as(u32, 0x80000000)), inf_f16);
|
try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16);
|
||||||
|
|
||||||
try test__powihf2(1, -1, 1);
|
try test__powihf2(1, -1, 1);
|
||||||
try test__powihf2(1, -2, 1);
|
try test__powihf2(1, -2, 1);
|
||||||
try test__powihf2(1, -3, 1);
|
try test__powihf2(1, -3, 1);
|
||||||
try test__powihf2(1, -4, 1);
|
try test__powihf2(1, -4, 1);
|
||||||
try test__powihf2(1, @bitCast(i32, @as(u32, 0x80000002)), 1); // 1.0 ^ anything = 1
|
try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1
|
||||||
try test__powihf2(1, @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
try test__powihf2(1, @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
|
|
||||||
try test__powihf2(inf_f16, -1, 0);
|
try test__powihf2(inf_f16, -1, 0);
|
||||||
try test__powihf2(inf_f16, -2, 0);
|
try test__powihf2(inf_f16, -2, 0);
|
||||||
try test__powihf2(inf_f16, -3, 0);
|
try test__powihf2(inf_f16, -3, 0);
|
||||||
try test__powihf2(inf_f16, -4, 0);
|
try test__powihf2(inf_f16, -4, 0);
|
||||||
try test__powihf2(inf_f16, @bitCast(i32, @as(u32, 0x80000002)), 0);
|
try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
|
||||||
try test__powihf2(inf_f16, @bitCast(i32, @as(u32, 0x80000001)), 0);
|
try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
|
||||||
try test__powihf2(inf_f16, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
//
|
//
|
||||||
try test__powihf2(-inf_f16, -1, -0.0);
|
try test__powihf2(-inf_f16, -1, -0.0);
|
||||||
try test__powihf2(-inf_f16, -2, 0);
|
try test__powihf2(-inf_f16, -2, 0);
|
||||||
try test__powihf2(-inf_f16, -3, -0.0);
|
try test__powihf2(-inf_f16, -3, -0.0);
|
||||||
try test__powihf2(-inf_f16, -4, 0);
|
try test__powihf2(-inf_f16, -4, 0);
|
||||||
try test__powihf2(-inf_f16, @bitCast(i32, @as(u32, 0x80000002)), 0);
|
try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
|
||||||
try test__powihf2(-inf_f16, @bitCast(i32, @as(u32, 0x80000001)), -0.0);
|
try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
|
||||||
try test__powihf2(-inf_f16, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
|
|
||||||
try test__powihf2(2, 10, 1024.0);
|
try test__powihf2(2, 10, 1024.0);
|
||||||
try test__powihf2(-2, 10, 1024.0);
|
try test__powihf2(-2, 10, 1024.0);
|
||||||
@ -158,76 +158,76 @@ test "powisf2" {
|
|||||||
try test__powisf2(0, 2, 0);
|
try test__powisf2(0, 2, 0);
|
||||||
try test__powisf2(0, 3, 0);
|
try test__powisf2(0, 3, 0);
|
||||||
try test__powisf2(0, 4, 0);
|
try test__powisf2(0, 4, 0);
|
||||||
try test__powisf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
|
try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
|
||||||
try test__powisf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 0);
|
try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
|
||||||
|
|
||||||
try test__powisf2(-0.0, 1, -0.0);
|
try test__powisf2(-0.0, 1, -0.0);
|
||||||
try test__powisf2(-0.0, 2, 0);
|
try test__powisf2(-0.0, 2, 0);
|
||||||
try test__powisf2(-0.0, 3, -0.0);
|
try test__powisf2(-0.0, 3, -0.0);
|
||||||
try test__powisf2(-0.0, 4, 0);
|
try test__powisf2(-0.0, 4, 0);
|
||||||
try test__powisf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
|
try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
|
||||||
try test__powisf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -0.0);
|
try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
|
||||||
|
|
||||||
try test__powisf2(1, 1, 1);
|
try test__powisf2(1, 1, 1);
|
||||||
try test__powisf2(1, 2, 1);
|
try test__powisf2(1, 2, 1);
|
||||||
try test__powisf2(1, 3, 1);
|
try test__powisf2(1, 3, 1);
|
||||||
try test__powisf2(1, 4, 1);
|
try test__powisf2(1, 4, 1);
|
||||||
try test__powisf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 1);
|
try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
|
||||||
try test__powisf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 1);
|
try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
|
||||||
|
|
||||||
try test__powisf2(inf_f32, 1, inf_f32);
|
try test__powisf2(inf_f32, 1, inf_f32);
|
||||||
try test__powisf2(inf_f32, 2, inf_f32);
|
try test__powisf2(inf_f32, 2, inf_f32);
|
||||||
try test__powisf2(inf_f32, 3, inf_f32);
|
try test__powisf2(inf_f32, 3, inf_f32);
|
||||||
try test__powisf2(inf_f32, 4, inf_f32);
|
try test__powisf2(inf_f32, 4, inf_f32);
|
||||||
try test__powisf2(inf_f32, @bitCast(i32, @as(u32, 0x7FFFFFFE)), inf_f32);
|
try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
|
||||||
try test__powisf2(inf_f32, @bitCast(i32, @as(u32, 0x7FFFFFFF)), inf_f32);
|
try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32);
|
||||||
|
|
||||||
try test__powisf2(-inf_f32, 1, -inf_f32);
|
try test__powisf2(-inf_f32, 1, -inf_f32);
|
||||||
try test__powisf2(-inf_f32, 2, inf_f32);
|
try test__powisf2(-inf_f32, 2, inf_f32);
|
||||||
try test__powisf2(-inf_f32, 3, -inf_f32);
|
try test__powisf2(-inf_f32, 3, -inf_f32);
|
||||||
try test__powisf2(-inf_f32, 4, inf_f32);
|
try test__powisf2(-inf_f32, 4, inf_f32);
|
||||||
try test__powisf2(-inf_f32, @bitCast(i32, @as(u32, 0x7FFFFFFE)), inf_f32);
|
try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32);
|
||||||
try test__powisf2(-inf_f32, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -inf_f32);
|
try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32);
|
||||||
|
|
||||||
try test__powisf2(0, -1, inf_f32);
|
try test__powisf2(0, -1, inf_f32);
|
||||||
try test__powisf2(0, -2, inf_f32);
|
try test__powisf2(0, -2, inf_f32);
|
||||||
try test__powisf2(0, -3, inf_f32);
|
try test__powisf2(0, -3, inf_f32);
|
||||||
try test__powisf2(0, -4, inf_f32);
|
try test__powisf2(0, -4, inf_f32);
|
||||||
try test__powisf2(0, @bitCast(i32, @as(u32, 0x80000002)), inf_f32);
|
try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
|
||||||
try test__powisf2(0, @bitCast(i32, @as(u32, 0x80000001)), inf_f32);
|
try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32);
|
||||||
try test__powisf2(0, @bitCast(i32, @as(u32, 0x80000000)), inf_f32);
|
try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
|
||||||
|
|
||||||
try test__powisf2(-0.0, -1, -inf_f32);
|
try test__powisf2(-0.0, -1, -inf_f32);
|
||||||
try test__powisf2(-0.0, -2, inf_f32);
|
try test__powisf2(-0.0, -2, inf_f32);
|
||||||
try test__powisf2(-0.0, -3, -inf_f32);
|
try test__powisf2(-0.0, -3, -inf_f32);
|
||||||
try test__powisf2(-0.0, -4, inf_f32);
|
try test__powisf2(-0.0, -4, inf_f32);
|
||||||
try test__powisf2(-0.0, @bitCast(i32, @as(u32, 0x80000002)), inf_f32);
|
try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32);
|
||||||
try test__powisf2(-0.0, @bitCast(i32, @as(u32, 0x80000001)), -inf_f32);
|
try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32);
|
||||||
try test__powisf2(-0.0, @bitCast(i32, @as(u32, 0x80000000)), inf_f32);
|
try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32);
|
||||||
|
|
||||||
try test__powisf2(1, -1, 1);
|
try test__powisf2(1, -1, 1);
|
||||||
try test__powisf2(1, -2, 1);
|
try test__powisf2(1, -2, 1);
|
||||||
try test__powisf2(1, -3, 1);
|
try test__powisf2(1, -3, 1);
|
||||||
try test__powisf2(1, -4, 1);
|
try test__powisf2(1, -4, 1);
|
||||||
try test__powisf2(1, @bitCast(i32, @as(u32, 0x80000002)), 1);
|
try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
|
||||||
try test__powisf2(1, @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
try test__powisf2(1, @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
|
|
||||||
try test__powisf2(inf_f32, -1, 0);
|
try test__powisf2(inf_f32, -1, 0);
|
||||||
try test__powisf2(inf_f32, -2, 0);
|
try test__powisf2(inf_f32, -2, 0);
|
||||||
try test__powisf2(inf_f32, -3, 0);
|
try test__powisf2(inf_f32, -3, 0);
|
||||||
try test__powisf2(inf_f32, -4, 0);
|
try test__powisf2(inf_f32, -4, 0);
|
||||||
try test__powisf2(inf_f32, @bitCast(i32, @as(u32, 0x80000002)), 0);
|
try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
|
||||||
try test__powisf2(inf_f32, @bitCast(i32, @as(u32, 0x80000001)), 0);
|
try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
|
||||||
try test__powisf2(inf_f32, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
|
|
||||||
try test__powisf2(-inf_f32, -1, -0.0);
|
try test__powisf2(-inf_f32, -1, -0.0);
|
||||||
try test__powisf2(-inf_f32, -2, 0);
|
try test__powisf2(-inf_f32, -2, 0);
|
||||||
try test__powisf2(-inf_f32, -3, -0.0);
|
try test__powisf2(-inf_f32, -3, -0.0);
|
||||||
try test__powisf2(-inf_f32, -4, 0);
|
try test__powisf2(-inf_f32, -4, 0);
|
||||||
try test__powisf2(-inf_f32, @bitCast(i32, @as(u32, 0x80000002)), 0);
|
try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
|
||||||
try test__powisf2(-inf_f32, @bitCast(i32, @as(u32, 0x80000001)), -0.0);
|
try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
|
||||||
try test__powisf2(-inf_f32, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
|
|
||||||
try test__powisf2(2.0, 10, 1024.0);
|
try test__powisf2(2.0, 10, 1024.0);
|
||||||
try test__powisf2(-2, 10, 1024.0);
|
try test__powisf2(-2, 10, 1024.0);
|
||||||
@ -263,76 +263,76 @@ test "powidf2" {
|
|||||||
try test__powidf2(0, 2, 0);
|
try test__powidf2(0, 2, 0);
|
||||||
try test__powidf2(0, 3, 0);
|
try test__powidf2(0, 3, 0);
|
||||||
try test__powidf2(0, 4, 0);
|
try test__powidf2(0, 4, 0);
|
||||||
try test__powidf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
|
try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
|
||||||
try test__powidf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 0);
|
try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
|
||||||
|
|
||||||
try test__powidf2(-0.0, 1, -0.0);
|
try test__powidf2(-0.0, 1, -0.0);
|
||||||
try test__powidf2(-0.0, 2, 0);
|
try test__powidf2(-0.0, 2, 0);
|
||||||
try test__powidf2(-0.0, 3, -0.0);
|
try test__powidf2(-0.0, 3, -0.0);
|
||||||
try test__powidf2(-0.0, 4, 0);
|
try test__powidf2(-0.0, 4, 0);
|
||||||
try test__powidf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
|
try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
|
||||||
try test__powidf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -0.0);
|
try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
|
||||||
|
|
||||||
try test__powidf2(1, 1, 1);
|
try test__powidf2(1, 1, 1);
|
||||||
try test__powidf2(1, 2, 1);
|
try test__powidf2(1, 2, 1);
|
||||||
try test__powidf2(1, 3, 1);
|
try test__powidf2(1, 3, 1);
|
||||||
try test__powidf2(1, 4, 1);
|
try test__powidf2(1, 4, 1);
|
||||||
try test__powidf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 1);
|
try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
|
||||||
try test__powidf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 1);
|
try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
|
||||||
|
|
||||||
try test__powidf2(inf_f64, 1, inf_f64);
|
try test__powidf2(inf_f64, 1, inf_f64);
|
||||||
try test__powidf2(inf_f64, 2, inf_f64);
|
try test__powidf2(inf_f64, 2, inf_f64);
|
||||||
try test__powidf2(inf_f64, 3, inf_f64);
|
try test__powidf2(inf_f64, 3, inf_f64);
|
||||||
try test__powidf2(inf_f64, 4, inf_f64);
|
try test__powidf2(inf_f64, 4, inf_f64);
|
||||||
try test__powidf2(inf_f64, @bitCast(i32, @as(u32, 0x7FFFFFFE)), inf_f64);
|
try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
|
||||||
try test__powidf2(inf_f64, @bitCast(i32, @as(u32, 0x7FFFFFFF)), inf_f64);
|
try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64);
|
||||||
|
|
||||||
try test__powidf2(-inf_f64, 1, -inf_f64);
|
try test__powidf2(-inf_f64, 1, -inf_f64);
|
||||||
try test__powidf2(-inf_f64, 2, inf_f64);
|
try test__powidf2(-inf_f64, 2, inf_f64);
|
||||||
try test__powidf2(-inf_f64, 3, -inf_f64);
|
try test__powidf2(-inf_f64, 3, -inf_f64);
|
||||||
try test__powidf2(-inf_f64, 4, inf_f64);
|
try test__powidf2(-inf_f64, 4, inf_f64);
|
||||||
try test__powidf2(-inf_f64, @bitCast(i32, @as(u32, 0x7FFFFFFE)), inf_f64);
|
try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64);
|
||||||
try test__powidf2(-inf_f64, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -inf_f64);
|
try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64);
|
||||||
|
|
||||||
try test__powidf2(0, -1, inf_f64);
|
try test__powidf2(0, -1, inf_f64);
|
||||||
try test__powidf2(0, -2, inf_f64);
|
try test__powidf2(0, -2, inf_f64);
|
||||||
try test__powidf2(0, -3, inf_f64);
|
try test__powidf2(0, -3, inf_f64);
|
||||||
try test__powidf2(0, -4, inf_f64);
|
try test__powidf2(0, -4, inf_f64);
|
||||||
try test__powidf2(0, @bitCast(i32, @as(u32, 0x80000002)), inf_f64);
|
try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
|
||||||
try test__powidf2(0, @bitCast(i32, @as(u32, 0x80000001)), inf_f64);
|
try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64);
|
||||||
try test__powidf2(0, @bitCast(i32, @as(u32, 0x80000000)), inf_f64);
|
try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
|
||||||
|
|
||||||
try test__powidf2(-0.0, -1, -inf_f64);
|
try test__powidf2(-0.0, -1, -inf_f64);
|
||||||
try test__powidf2(-0.0, -2, inf_f64);
|
try test__powidf2(-0.0, -2, inf_f64);
|
||||||
try test__powidf2(-0.0, -3, -inf_f64);
|
try test__powidf2(-0.0, -3, -inf_f64);
|
||||||
try test__powidf2(-0.0, -4, inf_f64);
|
try test__powidf2(-0.0, -4, inf_f64);
|
||||||
try test__powidf2(-0.0, @bitCast(i32, @as(u32, 0x80000002)), inf_f64);
|
try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64);
|
||||||
try test__powidf2(-0.0, @bitCast(i32, @as(u32, 0x80000001)), -inf_f64);
|
try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64);
|
||||||
try test__powidf2(-0.0, @bitCast(i32, @as(u32, 0x80000000)), inf_f64);
|
try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64);
|
||||||
|
|
||||||
try test__powidf2(1, -1, 1);
|
try test__powidf2(1, -1, 1);
|
||||||
try test__powidf2(1, -2, 1);
|
try test__powidf2(1, -2, 1);
|
||||||
try test__powidf2(1, -3, 1);
|
try test__powidf2(1, -3, 1);
|
||||||
try test__powidf2(1, -4, 1);
|
try test__powidf2(1, -4, 1);
|
||||||
try test__powidf2(1, @bitCast(i32, @as(u32, 0x80000002)), 1);
|
try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
|
||||||
try test__powidf2(1, @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
try test__powidf2(1, @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
|
|
||||||
try test__powidf2(inf_f64, -1, 0);
|
try test__powidf2(inf_f64, -1, 0);
|
||||||
try test__powidf2(inf_f64, -2, 0);
|
try test__powidf2(inf_f64, -2, 0);
|
||||||
try test__powidf2(inf_f64, -3, 0);
|
try test__powidf2(inf_f64, -3, 0);
|
||||||
try test__powidf2(inf_f64, -4, 0);
|
try test__powidf2(inf_f64, -4, 0);
|
||||||
try test__powidf2(inf_f64, @bitCast(i32, @as(u32, 0x80000002)), 0);
|
try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
|
||||||
try test__powidf2(inf_f64, @bitCast(i32, @as(u32, 0x80000001)), 0);
|
try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
|
||||||
try test__powidf2(inf_f64, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
|
|
||||||
try test__powidf2(-inf_f64, -1, -0.0);
|
try test__powidf2(-inf_f64, -1, -0.0);
|
||||||
try test__powidf2(-inf_f64, -2, 0);
|
try test__powidf2(-inf_f64, -2, 0);
|
||||||
try test__powidf2(-inf_f64, -3, -0.0);
|
try test__powidf2(-inf_f64, -3, -0.0);
|
||||||
try test__powidf2(-inf_f64, -4, 0);
|
try test__powidf2(-inf_f64, -4, 0);
|
||||||
try test__powidf2(-inf_f64, @bitCast(i32, @as(u32, 0x80000002)), 0);
|
try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
|
||||||
try test__powidf2(-inf_f64, @bitCast(i32, @as(u32, 0x80000001)), -0.0);
|
try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
|
||||||
try test__powidf2(-inf_f64, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
|
|
||||||
try test__powidf2(2, 10, 1024.0);
|
try test__powidf2(2, 10, 1024.0);
|
||||||
try test__powidf2(-2, 10, 1024.0);
|
try test__powidf2(-2, 10, 1024.0);
|
||||||
@ -368,76 +368,76 @@ test "powitf2" {
|
|||||||
try test__powitf2(0, 2, 0);
|
try test__powitf2(0, 2, 0);
|
||||||
try test__powitf2(0, 3, 0);
|
try test__powitf2(0, 3, 0);
|
||||||
try test__powitf2(0, 4, 0);
|
try test__powitf2(0, 4, 0);
|
||||||
try test__powitf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
|
try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
|
||||||
try test__powitf2(0, 0x7FFFFFFF, 0);
|
try test__powitf2(0, 0x7FFFFFFF, 0);
|
||||||
|
|
||||||
try test__powitf2(-0.0, 1, -0.0);
|
try test__powitf2(-0.0, 1, -0.0);
|
||||||
try test__powitf2(-0.0, 2, 0);
|
try test__powitf2(-0.0, 2, 0);
|
||||||
try test__powitf2(-0.0, 3, -0.0);
|
try test__powitf2(-0.0, 3, -0.0);
|
||||||
try test__powitf2(-0.0, 4, 0);
|
try test__powitf2(-0.0, 4, 0);
|
||||||
try test__powitf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
|
try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
|
||||||
try test__powitf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -0.0);
|
try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
|
||||||
|
|
||||||
try test__powitf2(1, 1, 1);
|
try test__powitf2(1, 1, 1);
|
||||||
try test__powitf2(1, 2, 1);
|
try test__powitf2(1, 2, 1);
|
||||||
try test__powitf2(1, 3, 1);
|
try test__powitf2(1, 3, 1);
|
||||||
try test__powitf2(1, 4, 1);
|
try test__powitf2(1, 4, 1);
|
||||||
try test__powitf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 1);
|
try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
|
||||||
try test__powitf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 1);
|
try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
|
||||||
|
|
||||||
try test__powitf2(inf_f128, 1, inf_f128);
|
try test__powitf2(inf_f128, 1, inf_f128);
|
||||||
try test__powitf2(inf_f128, 2, inf_f128);
|
try test__powitf2(inf_f128, 2, inf_f128);
|
||||||
try test__powitf2(inf_f128, 3, inf_f128);
|
try test__powitf2(inf_f128, 3, inf_f128);
|
||||||
try test__powitf2(inf_f128, 4, inf_f128);
|
try test__powitf2(inf_f128, 4, inf_f128);
|
||||||
try test__powitf2(inf_f128, @bitCast(i32, @as(u32, 0x7FFFFFFE)), inf_f128);
|
try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
|
||||||
try test__powitf2(inf_f128, @bitCast(i32, @as(u32, 0x7FFFFFFF)), inf_f128);
|
try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128);
|
||||||
|
|
||||||
try test__powitf2(-inf_f128, 1, -inf_f128);
|
try test__powitf2(-inf_f128, 1, -inf_f128);
|
||||||
try test__powitf2(-inf_f128, 2, inf_f128);
|
try test__powitf2(-inf_f128, 2, inf_f128);
|
||||||
try test__powitf2(-inf_f128, 3, -inf_f128);
|
try test__powitf2(-inf_f128, 3, -inf_f128);
|
||||||
try test__powitf2(-inf_f128, 4, inf_f128);
|
try test__powitf2(-inf_f128, 4, inf_f128);
|
||||||
try test__powitf2(-inf_f128, @bitCast(i32, @as(u32, 0x7FFFFFFE)), inf_f128);
|
try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128);
|
||||||
try test__powitf2(-inf_f128, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -inf_f128);
|
try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128);
|
||||||
|
|
||||||
try test__powitf2(0, -1, inf_f128);
|
try test__powitf2(0, -1, inf_f128);
|
||||||
try test__powitf2(0, -2, inf_f128);
|
try test__powitf2(0, -2, inf_f128);
|
||||||
try test__powitf2(0, -3, inf_f128);
|
try test__powitf2(0, -3, inf_f128);
|
||||||
try test__powitf2(0, -4, inf_f128);
|
try test__powitf2(0, -4, inf_f128);
|
||||||
try test__powitf2(0, @bitCast(i32, @as(u32, 0x80000002)), inf_f128);
|
try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
|
||||||
try test__powitf2(0, @bitCast(i32, @as(u32, 0x80000001)), inf_f128);
|
try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128);
|
||||||
try test__powitf2(0, @bitCast(i32, @as(u32, 0x80000000)), inf_f128);
|
try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
|
||||||
|
|
||||||
try test__powitf2(-0.0, -1, -inf_f128);
|
try test__powitf2(-0.0, -1, -inf_f128);
|
||||||
try test__powitf2(-0.0, -2, inf_f128);
|
try test__powitf2(-0.0, -2, inf_f128);
|
||||||
try test__powitf2(-0.0, -3, -inf_f128);
|
try test__powitf2(-0.0, -3, -inf_f128);
|
||||||
try test__powitf2(-0.0, -4, inf_f128);
|
try test__powitf2(-0.0, -4, inf_f128);
|
||||||
try test__powitf2(-0.0, @bitCast(i32, @as(u32, 0x80000002)), inf_f128);
|
try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128);
|
||||||
try test__powitf2(-0.0, @bitCast(i32, @as(u32, 0x80000001)), -inf_f128);
|
try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128);
|
||||||
try test__powitf2(-0.0, @bitCast(i32, @as(u32, 0x80000000)), inf_f128);
|
try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128);
|
||||||
|
|
||||||
try test__powitf2(1, -1, 1);
|
try test__powitf2(1, -1, 1);
|
||||||
try test__powitf2(1, -2, 1);
|
try test__powitf2(1, -2, 1);
|
||||||
try test__powitf2(1, -3, 1);
|
try test__powitf2(1, -3, 1);
|
||||||
try test__powitf2(1, -4, 1);
|
try test__powitf2(1, -4, 1);
|
||||||
try test__powitf2(1, @bitCast(i32, @as(u32, 0x80000002)), 1);
|
try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
|
||||||
try test__powitf2(1, @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
try test__powitf2(1, @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
|
|
||||||
try test__powitf2(inf_f128, -1, 0);
|
try test__powitf2(inf_f128, -1, 0);
|
||||||
try test__powitf2(inf_f128, -2, 0);
|
try test__powitf2(inf_f128, -2, 0);
|
||||||
try test__powitf2(inf_f128, -3, 0);
|
try test__powitf2(inf_f128, -3, 0);
|
||||||
try test__powitf2(inf_f128, -4, 0);
|
try test__powitf2(inf_f128, -4, 0);
|
||||||
try test__powitf2(inf_f128, @bitCast(i32, @as(u32, 0x80000002)), 0);
|
try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
|
||||||
try test__powitf2(inf_f128, @bitCast(i32, @as(u32, 0x80000001)), 0);
|
try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
|
||||||
try test__powitf2(inf_f128, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
|
|
||||||
try test__powitf2(-inf_f128, -1, -0.0);
|
try test__powitf2(-inf_f128, -1, -0.0);
|
||||||
try test__powitf2(-inf_f128, -2, 0);
|
try test__powitf2(-inf_f128, -2, 0);
|
||||||
try test__powitf2(-inf_f128, -3, -0.0);
|
try test__powitf2(-inf_f128, -3, -0.0);
|
||||||
try test__powitf2(-inf_f128, -4, 0);
|
try test__powitf2(-inf_f128, -4, 0);
|
||||||
try test__powitf2(-inf_f128, @bitCast(i32, @as(u32, 0x80000002)), 0);
|
try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
|
||||||
try test__powitf2(-inf_f128, @bitCast(i32, @as(u32, 0x80000001)), -0.0);
|
try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
|
||||||
try test__powitf2(-inf_f128, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
|
|
||||||
try test__powitf2(2, 10, 1024.0);
|
try test__powitf2(2, 10, 1024.0);
|
||||||
try test__powitf2(-2, 10, 1024.0);
|
try test__powitf2(-2, 10, 1024.0);
|
||||||
@ -473,76 +473,76 @@ test "powixf2" {
|
|||||||
try test__powixf2(0, 2, 0);
|
try test__powixf2(0, 2, 0);
|
||||||
try test__powixf2(0, 3, 0);
|
try test__powixf2(0, 3, 0);
|
||||||
try test__powixf2(0, 4, 0);
|
try test__powixf2(0, 4, 0);
|
||||||
try test__powixf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
|
try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
|
||||||
try test__powixf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 0);
|
try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0);
|
||||||
|
|
||||||
try test__powixf2(-0.0, 1, -0.0);
|
try test__powixf2(-0.0, 1, -0.0);
|
||||||
try test__powixf2(-0.0, 2, 0);
|
try test__powixf2(-0.0, 2, 0);
|
||||||
try test__powixf2(-0.0, 3, -0.0);
|
try test__powixf2(-0.0, 3, -0.0);
|
||||||
try test__powixf2(-0.0, 4, 0);
|
try test__powixf2(-0.0, 4, 0);
|
||||||
try test__powixf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
|
try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0);
|
||||||
try test__powixf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -0.0);
|
try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0);
|
||||||
|
|
||||||
try test__powixf2(1, 1, 1);
|
try test__powixf2(1, 1, 1);
|
||||||
try test__powixf2(1, 2, 1);
|
try test__powixf2(1, 2, 1);
|
||||||
try test__powixf2(1, 3, 1);
|
try test__powixf2(1, 3, 1);
|
||||||
try test__powixf2(1, 4, 1);
|
try test__powixf2(1, 4, 1);
|
||||||
try test__powixf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 1);
|
try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1);
|
||||||
try test__powixf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 1);
|
try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1);
|
||||||
|
|
||||||
try test__powixf2(inf_f80, 1, inf_f80);
|
try test__powixf2(inf_f80, 1, inf_f80);
|
||||||
try test__powixf2(inf_f80, 2, inf_f80);
|
try test__powixf2(inf_f80, 2, inf_f80);
|
||||||
try test__powixf2(inf_f80, 3, inf_f80);
|
try test__powixf2(inf_f80, 3, inf_f80);
|
||||||
try test__powixf2(inf_f80, 4, inf_f80);
|
try test__powixf2(inf_f80, 4, inf_f80);
|
||||||
try test__powixf2(inf_f80, @bitCast(i32, @as(u32, 0x7FFFFFFE)), inf_f80);
|
try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
|
||||||
try test__powixf2(inf_f80, @bitCast(i32, @as(u32, 0x7FFFFFFF)), inf_f80);
|
try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80);
|
||||||
|
|
||||||
try test__powixf2(-inf_f80, 1, -inf_f80);
|
try test__powixf2(-inf_f80, 1, -inf_f80);
|
||||||
try test__powixf2(-inf_f80, 2, inf_f80);
|
try test__powixf2(-inf_f80, 2, inf_f80);
|
||||||
try test__powixf2(-inf_f80, 3, -inf_f80);
|
try test__powixf2(-inf_f80, 3, -inf_f80);
|
||||||
try test__powixf2(-inf_f80, 4, inf_f80);
|
try test__powixf2(-inf_f80, 4, inf_f80);
|
||||||
try test__powixf2(-inf_f80, @bitCast(i32, @as(u32, 0x7FFFFFFE)), inf_f80);
|
try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80);
|
||||||
try test__powixf2(-inf_f80, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -inf_f80);
|
try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80);
|
||||||
|
|
||||||
try test__powixf2(0, -1, inf_f80);
|
try test__powixf2(0, -1, inf_f80);
|
||||||
try test__powixf2(0, -2, inf_f80);
|
try test__powixf2(0, -2, inf_f80);
|
||||||
try test__powixf2(0, -3, inf_f80);
|
try test__powixf2(0, -3, inf_f80);
|
||||||
try test__powixf2(0, -4, inf_f80);
|
try test__powixf2(0, -4, inf_f80);
|
||||||
try test__powixf2(0, @bitCast(i32, @as(u32, 0x80000002)), inf_f80);
|
try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
|
||||||
try test__powixf2(0, @bitCast(i32, @as(u32, 0x80000001)), inf_f80);
|
try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80);
|
||||||
try test__powixf2(0, @bitCast(i32, @as(u32, 0x80000000)), inf_f80);
|
try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
|
||||||
|
|
||||||
try test__powixf2(-0.0, -1, -inf_f80);
|
try test__powixf2(-0.0, -1, -inf_f80);
|
||||||
try test__powixf2(-0.0, -2, inf_f80);
|
try test__powixf2(-0.0, -2, inf_f80);
|
||||||
try test__powixf2(-0.0, -3, -inf_f80);
|
try test__powixf2(-0.0, -3, -inf_f80);
|
||||||
try test__powixf2(-0.0, -4, inf_f80);
|
try test__powixf2(-0.0, -4, inf_f80);
|
||||||
try test__powixf2(-0.0, @bitCast(i32, @as(u32, 0x80000002)), inf_f80);
|
try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80);
|
||||||
try test__powixf2(-0.0, @bitCast(i32, @as(u32, 0x80000001)), -inf_f80);
|
try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80);
|
||||||
try test__powixf2(-0.0, @bitCast(i32, @as(u32, 0x80000000)), inf_f80);
|
try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80);
|
||||||
|
|
||||||
try test__powixf2(1, -1, 1);
|
try test__powixf2(1, -1, 1);
|
||||||
try test__powixf2(1, -2, 1);
|
try test__powixf2(1, -2, 1);
|
||||||
try test__powixf2(1, -3, 1);
|
try test__powixf2(1, -3, 1);
|
||||||
try test__powixf2(1, -4, 1);
|
try test__powixf2(1, -4, 1);
|
||||||
try test__powixf2(1, @bitCast(i32, @as(u32, 0x80000002)), 1);
|
try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1);
|
||||||
try test__powixf2(1, @bitCast(i32, @as(u32, 0x80000001)), 1);
|
try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1);
|
||||||
try test__powixf2(1, @bitCast(i32, @as(u32, 0x80000000)), 1);
|
try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1);
|
||||||
|
|
||||||
try test__powixf2(inf_f80, -1, 0);
|
try test__powixf2(inf_f80, -1, 0);
|
||||||
try test__powixf2(inf_f80, -2, 0);
|
try test__powixf2(inf_f80, -2, 0);
|
||||||
try test__powixf2(inf_f80, -3, 0);
|
try test__powixf2(inf_f80, -3, 0);
|
||||||
try test__powixf2(inf_f80, -4, 0);
|
try test__powixf2(inf_f80, -4, 0);
|
||||||
try test__powixf2(inf_f80, @bitCast(i32, @as(u32, 0x80000002)), 0);
|
try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
|
||||||
try test__powixf2(inf_f80, @bitCast(i32, @as(u32, 0x80000001)), 0);
|
try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0);
|
||||||
try test__powixf2(inf_f80, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
|
|
||||||
try test__powixf2(-inf_f80, -1, -0.0);
|
try test__powixf2(-inf_f80, -1, -0.0);
|
||||||
try test__powixf2(-inf_f80, -2, 0);
|
try test__powixf2(-inf_f80, -2, 0);
|
||||||
try test__powixf2(-inf_f80, -3, -0.0);
|
try test__powixf2(-inf_f80, -3, -0.0);
|
||||||
try test__powixf2(-inf_f80, -4, 0);
|
try test__powixf2(-inf_f80, -4, 0);
|
||||||
try test__powixf2(-inf_f80, @bitCast(i32, @as(u32, 0x80000002)), 0);
|
try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0);
|
||||||
try test__powixf2(-inf_f80, @bitCast(i32, @as(u32, 0x80000001)), -0.0);
|
try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0);
|
||||||
try test__powixf2(-inf_f80, @bitCast(i32, @as(u32, 0x80000000)), 0);
|
try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0);
|
||||||
|
|
||||||
try test__powixf2(2, 10, 1024.0);
|
try test__powixf2(2, 10, 1024.0);
|
||||||
try test__powixf2(-2, 10, 1024.0);
|
try test__powixf2(-2, 10, 1024.0);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user