Skip to content

Commit a518042

Browse files
committed
Add comptime_float support to std.math.frexp
1 parent ce6eac1 commit a518042

File tree

1 file changed

+61
-58
lines changed

1 file changed

+61
-58
lines changed

lib/std/math/frexp.zig

Lines changed: 61 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const std = @import("../std.zig");
22
const math = std.math;
3+
const assert = std.debug.assert;
34
const expect = std.testing.expect;
45
const expectEqual = std.testing.expectEqual;
56
const expectApproxEqAbs = std.testing.expectApproxEqAbs;
@@ -20,8 +21,10 @@ pub fn Frexp(comptime T: type) type {
2021
/// - frexp(nan) = nan, undefined
2122
pub fn frexp(x: anytype) Frexp(@TypeOf(x)) {
2223
const T: type = @TypeOf(x);
24+
const info = @typeInfo(T);
25+
comptime assert(info == .float or info == .comptime_float);
2326

24-
const bits: comptime_int = @typeInfo(T).float.bits;
27+
const bits: comptime_int = if (info == .float) info.float.bits else 128;
2528
const Int: type = std.meta.Int(.unsigned, bits);
2629

2730
const exp_bits: comptime_int = math.floatExponentBits(T);
@@ -43,7 +46,7 @@ pub fn frexp(x: anytype) Frexp(@TypeOf(x)) {
4346
const extra_denorm_shift: comptime_int = 1 - ones_place;
4447

4548
var result: Frexp(T) = undefined;
46-
var v: Int = @bitCast(x);
49+
var v: Int = if (info == .float) @bitCast(x) else @bitCast(@as(f128, x));
4750

4851
const m: MantInt = @truncate(v);
4952
const e: ExpInt = @truncate(v >> mant_bits);
@@ -81,7 +84,7 @@ pub fn frexp(x: anytype) Frexp(@TypeOf(x)) {
8184
},
8285
}
8386

84-
result.significand = @bitCast(v);
87+
result.significand = if (info == .float) @bitCast(v) else @as(f128, @bitCast(v));
8588
return result;
8689
}
8790

@@ -91,23 +94,22 @@ fn FrexpTests(comptime Float: type) type {
9194
const T = Float;
9295
test "normal" {
9396
const epsilon = 1e-6;
94-
var r: Frexp(T) = undefined;
9597

96-
r = frexp(@as(T, 1.3));
97-
try expectApproxEqAbs(0.65, r.significand, epsilon);
98-
try expectEqual(1, r.exponent);
98+
const r1 = frexp(@as(T, 1.3));
99+
try expectApproxEqAbs(0.65, r1.significand, epsilon);
100+
try expectEqual(1, r1.exponent);
99101

100-
r = frexp(@as(T, 78.0234));
101-
try expectApproxEqAbs(0.609558, r.significand, epsilon);
102-
try expectEqual(7, r.exponent);
102+
const r2 = frexp(@as(T, 78.0234));
103+
try expectApproxEqAbs(0.609558, r2.significand, epsilon);
104+
try expectEqual(7, r2.exponent);
103105

104-
r = frexp(@as(T, -1234.5678));
105-
try expectEqual(11, r.exponent);
106-
try expectApproxEqAbs(-0.602816, r.significand, epsilon);
106+
const r3 = frexp(@as(T, -1234.5678));
107+
try expectEqual(11, r3.exponent);
108+
try expectApproxEqAbs(-0.602816, r3.significand, epsilon);
107109
}
108110
test "max" {
109111
const exponent = math.floatExponentMax(T) + 1;
110-
const significand = 1.0 - math.floatEps(T) / 2;
112+
const significand = 1.0 - math.floatEps(T) / 2.0;
111113
const r: Frexp(T) = frexp(math.floatMax(T));
112114
try expectEqual(exponent, r.exponent);
113115
try expectEqual(significand, r.significand);
@@ -126,17 +128,16 @@ fn FrexpTests(comptime Float: type) type {
126128
try expectEqual(0.5, r.significand);
127129
}
128130
test "zero" {
129-
var r: Frexp(T) = undefined;
131+
const r1 = frexp(@as(T, 0.0));
132+
try expectEqual(0, r1.exponent);
133+
try expect(math.isPositiveZero(r1.significand));
130134

131-
r = frexp(@as(T, 0.0));
132-
try expectEqual(0, r.exponent);
133-
try expect(math.isPositiveZero(r.significand));
134-
135-
r = frexp(@as(T, -0.0));
136-
try expectEqual(0, r.exponent);
137-
try expect(math.isNegativeZero(r.significand));
135+
const r2 = frexp(@as(T, -0.0));
136+
try expectEqual(0, r2.exponent);
137+
try expect(math.isNegativeZero(r2.significand));
138138
}
139139
test "inf" {
140+
if (T == comptime_float) return;
140141
var r: Frexp(T) = undefined;
141142

142143
r = frexp(math.inf(T));
@@ -148,6 +149,7 @@ fn FrexpTests(comptime Float: type) type {
148149
try expect(math.isNegativeInf(r.significand));
149150
}
150151
test "nan" {
152+
if (T == comptime_float) return;
151153
const r: Frexp(T) = frexp(math.nan(T));
152154
try expect(math.isNan(r.significand));
153155
}
@@ -156,53 +158,64 @@ fn FrexpTests(comptime Float: type) type {
156158

157159
// Generate tests for each floating point type
158160
comptime {
159-
for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
161+
for ([_]type{ f16, f32, f64, f80, f128, comptime_float }) |T| {
160162
_ = FrexpTests(T);
161163
}
162164
}
163165

164166
test frexp {
165-
inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
167+
@setEvalBranchQuota(1_500);
168+
169+
inline for ([_]type{ f16, f32, f64, f80, f128, comptime_float }) |T| {
166170
const max_exponent = math.floatExponentMax(T) + 1;
167171
const min_exponent = math.floatExponentMin(T) + 1;
168172
const truemin_exponent = min_exponent - math.floatFractionalBits(T);
169173

170-
var result: Frexp(T) = undefined;
171-
comptime var x: T = undefined;
172-
173174
// basic usage
174175
// value -> {significand, exponent},
175176
// value == significand * (2 ^ exponent)
176-
x = 1234.5678;
177-
result = frexp(x);
178-
try expectEqual(11, result.exponent);
179-
try expectApproxEqAbs(0.602816, result.significand, 1e-6);
180-
try expectEqual(x, math.ldexp(result.significand, result.exponent));
177+
const x1 = 1234.5678;
178+
const result1 = frexp(x1);
179+
try expectEqual(11, result1.exponent);
180+
try expectApproxEqAbs(0.602816, result1.significand, 1e-6);
181+
try expectEqual(x1, math.ldexp(result1.significand, result1.exponent));
181182

182183
// float maximum
183-
x = math.floatMax(T);
184-
result = frexp(x);
185-
try expectEqual(max_exponent, result.exponent);
186-
try expectEqual(1.0 - math.floatEps(T) / 2, result.significand);
187-
try expectEqual(x, math.ldexp(result.significand, result.exponent));
184+
const x2 = math.floatMax(T);
185+
const result2 = frexp(x2);
186+
try expectEqual(max_exponent, result2.exponent);
187+
try expectEqual(1.0 - math.floatEps(T) / 2.0, result2.significand);
188+
try expectEqual(x2, math.ldexp(result2.significand, result2.exponent));
188189

189190
// float minimum
190-
x = math.floatMin(T);
191-
result = frexp(x);
192-
try expectEqual(min_exponent, result.exponent);
193-
try expectEqual(0.5, result.significand);
194-
try expectEqual(x, math.ldexp(result.significand, result.exponent));
191+
const x3 = math.floatMin(T);
192+
const result3 = frexp(x3);
193+
try expectEqual(min_exponent, result3.exponent);
194+
try expectEqual(0.5, result3.significand);
195+
try expectEqual(x3, math.ldexp(result3.significand, result3.exponent));
195196

196197
// float true minimum
197198
// subnormal -> {normal, exponent}
198-
x = math.floatTrueMin(T);
199-
result = frexp(x);
200-
try expectEqual(truemin_exponent, result.exponent);
201-
try expectEqual(0.5, result.significand);
202-
try expectEqual(x, math.ldexp(result.significand, result.exponent));
199+
const x4 = math.floatTrueMin(T);
200+
const result4 = frexp(x4);
201+
try expectEqual(truemin_exponent, result4.exponent);
202+
try expectEqual(0.5, result4.significand);
203+
try expectEqual(x4, math.ldexp(result4.significand, result4.exponent));
204+
205+
// zero -> {zero, zero} (+)
206+
const result5 = frexp(@as(T, 0.0));
207+
try expectEqual(0, result5.exponent);
208+
try expect(math.isPositiveZero(result5.significand));
209+
210+
// zero -> {zero, zero} (-)
211+
const result6 = frexp(@as(T, -0.0));
212+
try expectEqual(0, result6.exponent);
213+
try expect(math.isNegativeZero(result6.significand));
214+
215+
if (T == comptime_float) return;
203216

204217
// infinity -> {infinity, zero} (+)
205-
result = frexp(math.inf(T));
218+
var result = frexp(math.inf(T));
206219
try expectEqual(0, result.exponent);
207220
try expect(math.isPositiveInf(result.significand));
208221

@@ -211,16 +224,6 @@ test frexp {
211224
try expectEqual(0, result.exponent);
212225
try expect(math.isNegativeInf(result.significand));
213226

214-
// zero -> {zero, zero} (+)
215-
result = frexp(@as(T, 0.0));
216-
try expectEqual(0, result.exponent);
217-
try expect(math.isPositiveZero(result.significand));
218-
219-
// zero -> {zero, zero} (-)
220-
result = frexp(@as(T, -0.0));
221-
try expectEqual(0, result.exponent);
222-
try expect(math.isNegativeZero(result.significand));
223-
224227
// nan -> {nan, undefined}
225228
result = frexp(math.nan(T));
226229
try expect(math.isNan(result.significand));

0 commit comments

Comments
 (0)