authorgravatar for mail@linusgroh.deLinus Groh <mail@linusgroh.de> 2023-10-27 14:50:39+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-09 00:55:43-07:00
loge72049bc61eedd2b7381b87b530428a83581cafe
tree304d5c71d9338e8150e516ecd6278e26cdc7e3e7
parentb2ed2c4d4fcc91980118e875b753eb82c7061bb7

std.math: Add isPositiveZero() and isNegativeZero()


11 files changed, 75 insertions(+), 32 deletions(-)

lib/std/json/dynamic_test.zig+1-1
...@@ -347,7 +347,7 @@ test "negative zero" {...@@ -347,7 +347,7 @@ test "negative zero" {
347 var parsed = try parseFromTokenSource(Value, testing.allocator, &reader, .{});347 var parsed = try parseFromTokenSource(Value, testing.allocator, &reader, .{});
348 defer parsed.deinit();348 defer parsed.deinit();
349349
350 try testing.expect(parsed.value.float == 0 and std.math.signbit(parsed.value.float));350 try testing.expect(std.math.isNegativeZero(parsed.value.float));
351}351}
352352
353fn smallBufferJsonReader(allocator: Allocator, io_reader: anytype) JsonReader(16, @TypeOf(io_reader)) {353fn smallBufferJsonReader(allocator: Allocator, io_reader: anytype) JsonReader(16, @TypeOf(io_reader)) {
lib/std/math.zig+2
...@@ -222,6 +222,8 @@ pub const isFinite = @import("math/isfinite.zig").isFinite;...@@ -222,6 +222,8 @@ pub const isFinite = @import("math/isfinite.zig").isFinite;
222pub const isInf = @import("math/isinf.zig").isInf;222pub const isInf = @import("math/isinf.zig").isInf;
223pub const isPositiveInf = @import("math/isinf.zig").isPositiveInf;223pub const isPositiveInf = @import("math/isinf.zig").isPositiveInf;
224pub const isNegativeInf = @import("math/isinf.zig").isNegativeInf;224pub const isNegativeInf = @import("math/isinf.zig").isNegativeInf;
225pub const isPositiveZero = @import("math/iszero.zig").isPositiveZero;
226pub const isNegativeZero = @import("math/iszero.zig").isNegativeZero;
225pub const isNormal = @import("math/isnormal.zig").isNormal;227pub const isNormal = @import("math/isnormal.zig").isNormal;
226pub const nextAfter = @import("math/nextafter.zig").nextAfter;228pub const nextAfter = @import("math/nextafter.zig").nextAfter;
227pub const signbit = @import("math/signbit.zig").signbit;229pub const signbit = @import("math/signbit.zig").signbit;
lib/std/math/asin.zig+4-4
...@@ -169,15 +169,15 @@ test "math.asin64" {...@@ -169,15 +169,15 @@ test "math.asin64" {
169}169}
170170
171test "math.asin32.special" {171test "math.asin32.special" {
172 try expect(asin32(0.0) == 0.0);172 try expect(math.isPositiveZero(asin32(0.0)));
173 try expect(asin32(-0.0) == -0.0);173 try expect(math.isNegativeZero(asin32(-0.0)));
174 try expect(math.isNan(asin32(-2)));174 try expect(math.isNan(asin32(-2)));
175 try expect(math.isNan(asin32(1.5)));175 try expect(math.isNan(asin32(1.5)));
176}176}
177177
178test "math.asin64.special" {178test "math.asin64.special" {
179 try expect(asin64(0.0) == 0.0);179 try expect(math.isPositiveZero(asin64(0.0)));
180 try expect(asin64(-0.0) == -0.0);180 try expect(math.isNegativeZero(asin64(-0.0)));
181 try expect(math.isNan(asin64(-2)));181 try expect(math.isNan(asin64(-2)));
182 try expect(math.isNan(asin64(1.5)));182 try expect(math.isNan(asin64(1.5)));
183}183}
lib/std/math/asinh.zig+4-4
...@@ -111,16 +111,16 @@ test "math.asinh64" {...@@ -111,16 +111,16 @@ test "math.asinh64" {
111}111}
112112
113test "math.asinh32.special" {113test "math.asinh32.special" {
114 try expect(asinh32(0.0) == 0.0);114 try expect(math.isPositiveZero(asinh32(0.0)));
115 try expect(@as(u32, @bitCast(asinh32(-0.0))) == @as(u32, 0x80000000));115 try expect(math.isNegativeZero(asinh32(-0.0)));
116 try expect(math.isPositiveInf(asinh32(math.inf(f32))));116 try expect(math.isPositiveInf(asinh32(math.inf(f32))));
117 try expect(math.isNegativeInf(asinh32(-math.inf(f32))));117 try expect(math.isNegativeInf(asinh32(-math.inf(f32))));
118 try expect(math.isNan(asinh32(math.nan(f32))));118 try expect(math.isNan(asinh32(math.nan(f32))));
119}119}
120120
121test "math.asinh64.special" {121test "math.asinh64.special" {
122 try expect(asinh64(0.0) == 0.0);122 try expect(math.isPositiveZero(asinh64(0.0)));
123 try expect(@as(u64, @bitCast(asinh64(-0.0))) == @as(u64, 0x8000000000000000));123 try expect(math.isNegativeZero(asinh64(-0.0)));
124 try expect(math.isPositiveInf(asinh64(math.inf(f64))));124 try expect(math.isPositiveInf(asinh64(math.inf(f64))));
125 try expect(math.isNegativeInf(asinh64(-math.inf(f64))));125 try expect(math.isNegativeInf(asinh64(-math.inf(f64))));
126 try expect(math.isNan(asinh64(math.nan(f64))));126 try expect(math.isNan(asinh64(math.nan(f64))));
lib/std/math/atan.zig+4-4
...@@ -239,8 +239,8 @@ test "math.atan64" {...@@ -239,8 +239,8 @@ test "math.atan64" {
239test "math.atan32.special" {239test "math.atan32.special" {
240 const epsilon = 0.000001;240 const epsilon = 0.000001;
241241
242 try expect(atan32(0.0) == 0.0);242 try expect(math.isPositiveZero(atan32(0.0)));
243 try expect(atan32(-0.0) == -0.0);243 try expect(math.isNegativeZero(atan32(-0.0)));
244 try expect(math.approxEqAbs(f32, atan32(math.inf(f32)), math.pi / 2.0, epsilon));244 try expect(math.approxEqAbs(f32, atan32(math.inf(f32)), math.pi / 2.0, epsilon));
245 try expect(math.approxEqAbs(f32, atan32(-math.inf(f32)), -math.pi / 2.0, epsilon));245 try expect(math.approxEqAbs(f32, atan32(-math.inf(f32)), -math.pi / 2.0, epsilon));
246}246}
...@@ -248,8 +248,8 @@ test "math.atan32.special" {...@@ -248,8 +248,8 @@ test "math.atan32.special" {
248test "math.atan64.special" {248test "math.atan64.special" {
249 const epsilon = 0.000001;249 const epsilon = 0.000001;
250250
251 try expect(atan64(0.0) == 0.0);251 try expect(math.isPositiveZero(atan64(0.0)));
252 try expect(atan64(-0.0) == -0.0);252 try expect(math.isNegativeZero(atan64(-0.0)));
253 try expect(math.approxEqAbs(f64, atan64(math.inf(f64)), math.pi / 2.0, epsilon));253 try expect(math.approxEqAbs(f64, atan64(math.inf(f64)), math.pi / 2.0, epsilon));
254 try expect(math.approxEqAbs(f64, atan64(-math.inf(f64)), -math.pi / 2.0, epsilon));254 try expect(math.approxEqAbs(f64, atan64(-math.inf(f64)), -math.pi / 2.0, epsilon));
255}255}
lib/std/math/cbrt.zig+5-5
...@@ -127,7 +127,7 @@ test "math.cbrt" {...@@ -127,7 +127,7 @@ test "math.cbrt" {
127test "math.cbrt32" {127test "math.cbrt32" {
128 const epsilon = 0.000001;128 const epsilon = 0.000001;
129129
130 try expect(cbrt32(0.0) == 0.0);130 try expect(math.isPositiveZero(cbrt32(0.0)));
131 try expect(math.approxEqAbs(f32, cbrt32(0.2), 0.584804, epsilon));131 try expect(math.approxEqAbs(f32, cbrt32(0.2), 0.584804, epsilon));
132 try expect(math.approxEqAbs(f32, cbrt32(0.8923), 0.962728, epsilon));132 try expect(math.approxEqAbs(f32, cbrt32(0.8923), 0.962728, epsilon));
133 try expect(math.approxEqAbs(f32, cbrt32(1.5), 1.144714, epsilon));133 try expect(math.approxEqAbs(f32, cbrt32(1.5), 1.144714, epsilon));
...@@ -138,7 +138,7 @@ test "math.cbrt32" {...@@ -138,7 +138,7 @@ test "math.cbrt32" {
138test "math.cbrt64" {138test "math.cbrt64" {
139 const epsilon = 0.000001;139 const epsilon = 0.000001;
140140
141 try expect(cbrt64(0.0) == 0.0);141 try expect(math.isPositiveZero(cbrt64(0.0)));
142 try expect(math.approxEqAbs(f64, cbrt64(0.2), 0.584804, epsilon));142 try expect(math.approxEqAbs(f64, cbrt64(0.2), 0.584804, epsilon));
143 try expect(math.approxEqAbs(f64, cbrt64(0.8923), 0.962728, epsilon));143 try expect(math.approxEqAbs(f64, cbrt64(0.8923), 0.962728, epsilon));
144 try expect(math.approxEqAbs(f64, cbrt64(1.5), 1.144714, epsilon));144 try expect(math.approxEqAbs(f64, cbrt64(1.5), 1.144714, epsilon));
...@@ -147,7 +147,7 @@ test "math.cbrt64" {...@@ -147,7 +147,7 @@ test "math.cbrt64" {
147}147}
148148
149test "math.cbrt.special" {149test "math.cbrt.special" {
150 try expect(cbrt32(0.0) == 0.0);150 try expect(math.isPositiveZero(cbrt32(0.0)));
151 try expect(@as(u32, @bitCast(cbrt32(-0.0))) == @as(u32, 0x80000000));151 try expect(@as(u32, @bitCast(cbrt32(-0.0))) == @as(u32, 0x80000000));
152 try expect(math.isPositiveInf(cbrt32(math.inf(f32))));152 try expect(math.isPositiveInf(cbrt32(math.inf(f32))));
153 try expect(math.isNegativeInf(cbrt32(-math.inf(f32))));153 try expect(math.isNegativeInf(cbrt32(-math.inf(f32))));
...@@ -155,8 +155,8 @@ test "math.cbrt.special" {...@@ -155,8 +155,8 @@ test "math.cbrt.special" {
155}155}
156156
157test "math.cbrt64.special" {157test "math.cbrt64.special" {
158 try expect(cbrt64(0.0) == 0.0);158 try expect(math.isPositiveZero(cbrt64(0.0)));
159 try expect(@as(u64, @bitCast(cbrt64(-0.0))) == @as(u64, 0x8000000000000000));159 try expect(math.isNegativeZero(cbrt64(-0.0)));
160 try expect(math.isPositiveInf(cbrt64(math.inf(f64))));160 try expect(math.isPositiveInf(cbrt64(math.inf(f64))));
161 try expect(math.isNegativeInf(cbrt64(-math.inf(f64))));161 try expect(math.isNegativeInf(cbrt64(-math.inf(f64))));
162 try expect(math.isNan(cbrt64(math.nan(f64))));162 try expect(math.isNan(cbrt64(math.nan(f64))));
lib/std/math/expm1.zig+2-2
...@@ -293,7 +293,7 @@ test "math.exp1m" {...@@ -293,7 +293,7 @@ test "math.exp1m" {
293test "math.expm1_32" {293test "math.expm1_32" {
294 const epsilon = 0.000001;294 const epsilon = 0.000001;
295295
296 try expect(expm1_32(0.0) == 0.0);296 try expect(math.isPositiveZero(expm1_32(0.0)));
297 try expect(math.approxEqAbs(f32, expm1_32(0.0), 0.0, epsilon));297 try expect(math.approxEqAbs(f32, expm1_32(0.0), 0.0, epsilon));
298 try expect(math.approxEqAbs(f32, expm1_32(0.2), 0.221403, epsilon));298 try expect(math.approxEqAbs(f32, expm1_32(0.2), 0.221403, epsilon));
299 try expect(math.approxEqAbs(f32, expm1_32(0.8923), 1.440737, epsilon));299 try expect(math.approxEqAbs(f32, expm1_32(0.8923), 1.440737, epsilon));
...@@ -303,7 +303,7 @@ test "math.expm1_32" {...@@ -303,7 +303,7 @@ test "math.expm1_32" {
303test "math.expm1_64" {303test "math.expm1_64" {
304 const epsilon = 0.000001;304 const epsilon = 0.000001;
305305
306 try expect(expm1_64(0.0) == 0.0);306 try expect(math.isPositiveZero(expm1_64(0.0)));
307 try expect(math.approxEqAbs(f64, expm1_64(0.0), 0.0, epsilon));307 try expect(math.approxEqAbs(f64, expm1_64(0.0), 0.0, epsilon));
308 try expect(math.approxEqAbs(f64, expm1_64(0.2), 0.221403, epsilon));308 try expect(math.approxEqAbs(f64, expm1_64(0.2), 0.221403, epsilon));
309 try expect(math.approxEqAbs(f64, expm1_64(0.8923), 1.440737, epsilon));309 try expect(math.approxEqAbs(f64, expm1_64(0.8923), 1.440737, epsilon));
lib/std/math/iszero.zig created+41
...@@ -0,0 +1,41 @@
1const std = @import("../std.zig");
2const math = std.math;
3const expect = std.testing.expect;
4
5/// Returns whether x is positive zero.
6pub inline fn isPositiveZero(x: anytype) bool {
7 const T = @TypeOf(x);
8 const bit_count = @typeInfo(T).Float.bits;
9 const TBits = std.meta.Int(.unsigned, bit_count);
10 return @as(TBits, @bitCast(x)) == @as(TBits, 0);
11}
12
13/// Returns whether x is negative zero.
14pub inline fn isNegativeZero(x: anytype) bool {
15 const T = @TypeOf(x);
16 const bit_count = @typeInfo(T).Float.bits;
17 const TBits = std.meta.Int(.unsigned, bit_count);
18 return @as(TBits, @bitCast(x)) == @as(TBits, 1) << (bit_count - 1);
19}
20
21test isPositiveZero {
22 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
23 try expect(isPositiveZero(@as(T, 0.0)));
24 try expect(!isPositiveZero(@as(T, -0.0)));
25 try expect(!isPositiveZero(math.floatMin(T)));
26 try expect(!isPositiveZero(math.floatMax(T)));
27 try expect(!isPositiveZero(math.inf(T)));
28 try expect(!isPositiveZero(-math.inf(T)));
29 }
30}
31
32test isNegativeZero {
33 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
34 try expect(isNegativeZero(@as(T, -0.0)));
35 try expect(!isNegativeZero(@as(T, 0.0)));
36 try expect(!isNegativeZero(math.floatMin(T)));
37 try expect(!isNegativeZero(math.floatMax(T)));
38 try expect(!isNegativeZero(math.inf(T)));
39 try expect(!isNegativeZero(-math.inf(T)));
40 }
41}
lib/std/math/log1p.zig+4-4
...@@ -212,8 +212,8 @@ test "math.log1p_64" {...@@ -212,8 +212,8 @@ test "math.log1p_64" {
212212
213test "math.log1p_32.special" {213test "math.log1p_32.special" {
214 try expect(math.isPositiveInf(log1p_32(math.inf(f32))));214 try expect(math.isPositiveInf(log1p_32(math.inf(f32))));
215 try expect(log1p_32(0.0) == 0.0);215 try expect(math.isPositiveZero(log1p_32(0.0)));
216 try expect(log1p_32(-0.0) == -0.0);216 try expect(math.isNegativeZero(log1p_32(-0.0)));
217 try expect(math.isNegativeInf(log1p_32(-1.0)));217 try expect(math.isNegativeInf(log1p_32(-1.0)));
218 try expect(math.isNan(log1p_32(-2.0)));218 try expect(math.isNan(log1p_32(-2.0)));
219 try expect(math.isNan(log1p_32(math.nan(f32))));219 try expect(math.isNan(log1p_32(math.nan(f32))));
...@@ -221,8 +221,8 @@ test "math.log1p_32.special" {...@@ -221,8 +221,8 @@ test "math.log1p_32.special" {
221221
222test "math.log1p_64.special" {222test "math.log1p_64.special" {
223 try expect(math.isPositiveInf(log1p_64(math.inf(f64))));223 try expect(math.isPositiveInf(log1p_64(math.inf(f64))));
224 try expect(log1p_64(0.0) == 0.0);224 try expect(math.isPositiveZero(log1p_64(0.0)));
225 try expect(log1p_64(-0.0) == -0.0);225 try expect(math.isNegativeZero(log1p_64(-0.0)));
226 try expect(math.isNegativeInf(log1p_64(-1.0)));226 try expect(math.isNegativeInf(log1p_64(-1.0)));
227 try expect(math.isNan(log1p_64(-2.0)));227 try expect(math.isNan(log1p_64(-2.0)));
228 try expect(math.isNan(log1p_64(math.nan(f64))));228 try expect(math.isNan(log1p_64(math.nan(f64))));
lib/std/math/sinh.zig+4-4
...@@ -123,16 +123,16 @@ test "math.sinh64" {...@@ -123,16 +123,16 @@ test "math.sinh64" {
123}123}
124124
125test "math.sinh32.special" {125test "math.sinh32.special" {
126 try expect(sinh32(0.0) == 0.0);126 try expect(math.isPositiveZero(sinh32(0.0)));
127 try expect(sinh32(-0.0) == -0.0);127 try expect(math.isNegativeZero(sinh32(-0.0)));
128 try expect(math.isPositiveInf(sinh32(math.inf(f32))));128 try expect(math.isPositiveInf(sinh32(math.inf(f32))));
129 try expect(math.isNegativeInf(sinh32(-math.inf(f32))));129 try expect(math.isNegativeInf(sinh32(-math.inf(f32))));
130 try expect(math.isNan(sinh32(math.nan(f32))));130 try expect(math.isNan(sinh32(math.nan(f32))));
131}131}
132132
133test "math.sinh64.special" {133test "math.sinh64.special" {
134 try expect(sinh64(0.0) == 0.0);134 try expect(math.isPositiveZero(sinh64(0.0)));
135 try expect(sinh64(-0.0) == -0.0);135 try expect(math.isNegativeZero(sinh64(-0.0)));
136 try expect(math.isPositiveInf(sinh64(math.inf(f64))));136 try expect(math.isPositiveInf(sinh64(math.inf(f64))));
137 try expect(math.isNegativeInf(sinh64(-math.inf(f64))));137 try expect(math.isNegativeInf(sinh64(-math.inf(f64))));
138 try expect(math.isNan(sinh64(math.nan(f64))));138 try expect(math.isNan(sinh64(math.nan(f64))));
lib/std/math/tanh.zig+4-4
...@@ -135,16 +135,16 @@ test "math.tanh64" {...@@ -135,16 +135,16 @@ test "math.tanh64" {
135}135}
136136
137test "math.tanh32.special" {137test "math.tanh32.special" {
138 try expect(tanh32(0.0) == 0.0);138 try expect(math.isPositiveZero(tanh32(0.0)));
139 try expect(tanh32(-0.0) == -0.0);139 try expect(math.isNegativeZero(tanh32(-0.0)));
140 try expect(tanh32(math.inf(f32)) == 1.0);140 try expect(tanh32(math.inf(f32)) == 1.0);
141 try expect(tanh32(-math.inf(f32)) == -1.0);141 try expect(tanh32(-math.inf(f32)) == -1.0);
142 try expect(math.isNan(tanh32(math.nan(f32))));142 try expect(math.isNan(tanh32(math.nan(f32))));
143}143}
144144
145test "math.tanh64.special" {145test "math.tanh64.special" {
146 try expect(tanh64(0.0) == 0.0);146 try expect(math.isPositiveZero(tanh64(0.0)));
147 try expect(tanh64(-0.0) == -0.0);147 try expect(math.isNegativeZero(tanh64(-0.0)));
148 try expect(tanh64(math.inf(f64)) == 1.0);148 try expect(tanh64(math.inf(f64)) == 1.0);
149 try expect(tanh64(-math.inf(f64)) == -1.0);149 try expect(tanh64(-math.inf(f64)) == -1.0);
150 try expect(math.isNan(tanh64(math.nan(f64))));150 try expect(math.isNan(tanh64(math.nan(f64))));