@@ -35,8 +35,8 @@ pub fn pow(comptime T: type, x: T, y: T) T {
35
35
return math .powi (T , x , y ) catch unreachable ;
36
36
}
37
37
38
- if (T != f32 and T != f64 ) {
39
- @compileError ("pow not implemented for " ++ @typeName ( T ) );
38
+ if (@typeInfo ( T ) == .comptime_float ) {
39
+ @compileError ("pow not implemented for comptime_float" );
40
40
}
41
41
42
42
// pow(x, +-0) = 1 for all x
@@ -60,15 +60,15 @@ pub fn pow(comptime T: type, x: T, y: T) T {
60
60
if (x == 0 ) {
61
61
if (y < 0 ) {
62
62
// pow(+-0, y) = +-inf for y an odd integer
63
- if (isOddInteger (y )) {
63
+ if (isOddInteger (T , y )) {
64
64
return math .copysign (math .inf (T ), x );
65
65
}
66
66
// pow(+-0, y) = +inf for y an even integer
67
67
else {
68
68
return math .inf (T );
69
69
}
70
70
} else {
71
- if (isOddInteger (y )) {
71
+ if (isOddInteger (T , y )) {
72
72
return x ;
73
73
} else {
74
74
return 0 ;
@@ -178,29 +178,37 @@ pub fn pow(comptime T: type, x: T, y: T) T {
178
178
return math .scalbn (a1 , ae );
179
179
}
180
180
181
- fn isOddInteger (x : f64 ) bool {
182
- if (@abs (x ) >= 1 << 53 ) {
183
- // From https://golang.org/src/math/pow.go
184
- // 1 << 53 is the largest exact integer in the float64 format.
181
+ fn isOddInteger (comptime T : type , x : T ) bool {
182
+ if (@abs (x ) >= 1 << ( math . floatFractionalBits ( T ) + 1 ) ) {
183
+ // From https://golang.org/src/math/pow.go (adapted for generic type T)
184
+ // 1 << (floatFractionalBits(T) + 1) is the largest exact integer in the floating point format.
185
185
// Any number outside this range will be truncated before the decimal point and therefore will always be
186
186
// an even integer.
187
- // Without this check and if x overflows i64 the @intFromFloat(r.ipart) conversion below will panic
187
+ // Without this check and if x overflows i128 the @intFromFloat(r.ipart) conversion below will panic
188
188
return false ;
189
189
}
190
190
const r = math .modf (x );
191
- return r .fpart == 0.0 and @as (i64 , @intFromFloat (r .ipart )) & 1 == 1 ;
191
+ return r .fpart == 0.0 and @as (i128 , @intFromFloat (r .ipart )) & 1 == 1 ;
192
192
}
193
193
194
194
test isOddInteger {
195
- try expect (isOddInteger (math .maxInt (i64 ) * 2 ) == false );
196
- try expect (isOddInteger (math .maxInt (i64 ) * 2 + 1 ) == false );
197
- try expect (isOddInteger (1 << 53 ) == false );
198
- try expect (isOddInteger (12.0 ) == false );
199
- try expect (isOddInteger (15.0 ) == true );
195
+ try expect (isOddInteger (f64 , math .maxInt (i64 ) * 2 ) == false );
196
+ try expect (isOddInteger (f64 , math .maxInt (i64 ) * 2 + 1 ) == false );
197
+ try expect (isOddInteger (f64 , 1 << 53 ) == false );
198
+ try expect (isOddInteger (f64 , 12.0 ) == false );
199
+ try expect (isOddInteger (f64 , 15.0 ) == true );
200
200
}
201
201
202
202
test pow {
203
203
const epsilon = 0.000001 ;
204
+ const epsilon16 = 0.01 ;
205
+
206
+ try expect (math .approxEqAbs (f16 , pow (f16 , 0.0 , 3.3 ), 0.0 , epsilon16 ));
207
+ try expect (math .approxEqAbs (f16 , pow (f16 , 0.8923 , 3.3 ), 0.686572 , epsilon16 ));
208
+ try expect (math .approxEqAbs (f16 , pow (f16 , 0.2 , 3.3 ), 0.004936 , epsilon16 ));
209
+ try expect (math .approxEqAbs (f16 , pow (f16 , 1.5 , 3.3 ), 3.811546 , epsilon16 ));
210
+ try expect (math .approxEqAbs (f16 , pow (f16 , 37.45 , 3.3 ), 155736.7160616 , epsilon16 ));
211
+ try expect (math .approxEqAbs (f16 , pow (f16 , 89.123 , 3.3 ), 2722490.231436 , epsilon16 ));
204
212
205
213
try expect (math .approxEqAbs (f32 , pow (f32 , 0.0 , 3.3 ), 0.0 , epsilon ));
206
214
try expect (math .approxEqAbs (f32 , pow (f32 , 0.8923 , 3.3 ), 0.686572 , epsilon ));
@@ -215,6 +223,20 @@ test pow {
215
223
try expect (math .approxEqAbs (f64 , pow (f64 , 1.5 , 3.3 ), 3.811546 , epsilon ));
216
224
try expect (math .approxEqAbs (f64 , pow (f64 , 37.45 , 3.3 ), 155736.7160616 , epsilon ));
217
225
try expect (math .approxEqAbs (f64 , pow (f64 , 89.123 , 3.3 ), 2722490.231436 , epsilon ));
226
+
227
+ try expect (math .approxEqAbs (f80 , pow (f80 , 0.0 , 3.3 ), 0.0 , epsilon ));
228
+ try expect (math .approxEqAbs (f80 , pow (f80 , 0.8923 , 3.3 ), 0.686572 , epsilon ));
229
+ try expect (math .approxEqAbs (f80 , pow (f80 , 0.2 , 3.3 ), 0.004936 , epsilon ));
230
+ try expect (math .approxEqAbs (f80 , pow (f80 , 1.5 , 3.3 ), 3.811546 , epsilon ));
231
+ try expect (math .approxEqAbs (f80 , pow (f80 , 37.45 , 3.3 ), 155736.7160616 , epsilon ));
232
+ try expect (math .approxEqAbs (f80 , pow (f80 , 89.123 , 3.3 ), 2722490.231436 , epsilon ));
233
+
234
+ try expect (math .approxEqAbs (f128 , pow (f128 , 0.0 , 3.3 ), 0.0 , epsilon ));
235
+ try expect (math .approxEqAbs (f128 , pow (f128 , 0.8923 , 3.3 ), 0.686572 , epsilon ));
236
+ try expect (math .approxEqAbs (f128 , pow (f128 , 0.2 , 3.3 ), 0.004936 , epsilon ));
237
+ try expect (math .approxEqAbs (f128 , pow (f128 , 1.5 , 3.3 ), 3.811546 , epsilon ));
238
+ try expect (math .approxEqAbs (f128 , pow (f128 , 37.45 , 3.3 ), 155736.7160616 , epsilon ));
239
+ try expect (math .approxEqAbs (f128 , pow (f128 , 89.123 , 3.3 ), 2722490.231436 , epsilon ));
218
240
}
219
241
220
242
test "special" {
0 commit comments