@@ -2,7 +2,11 @@ use crate::f16::consts;
2
2
use crate :: num:: FpCategory as Fp ;
3
3
use crate :: num:: * ;
4
4
5
- const F16_APPROX : f16 = 0.001 ;
5
+ // We run out of precision pretty quickly with f16
6
+ const F16_APPROX_L1 : f16 = 0.001 ;
7
+ const F16_APPROX_L2 : f16 = 0.01 ;
8
+ const F16_APPROX_L3 : f16 = 0.1 ;
9
+ const F16_APPROX_L4 : f16 = 0.5 ;
6
10
7
11
#[ test]
8
12
fn test_num_f16 ( ) {
@@ -160,8 +164,8 @@ fn test_is_normal() {
160
164
assert ! ( !zero. is_normal( ) ) ;
161
165
assert ! ( !neg_zero. is_normal( ) ) ;
162
166
assert ! ( 1 f16. is_normal( ) ) ;
163
- assert ! ( 1e-37f16 . is_normal( ) ) ;
164
- assert ! ( !1e-38f16 . is_normal( ) ) ;
167
+ assert ! ( 1e-4f16 . is_normal( ) ) ;
168
+ assert ! ( !1e-5f16 . is_normal( ) ) ;
165
169
}
166
170
167
171
#[ test]
@@ -177,8 +181,8 @@ fn test_classify() {
177
181
assert_eq ! ( zero. classify( ) , Fp :: Zero ) ;
178
182
assert_eq ! ( neg_zero. classify( ) , Fp :: Zero ) ;
179
183
assert_eq ! ( 1 f16. classify( ) , Fp :: Normal ) ;
180
- assert_eq ! ( 1e-37f16 . classify( ) , Fp :: Normal ) ;
181
- assert_eq ! ( 1e-38f16 . classify( ) , Fp :: Subnormal ) ;
184
+ assert_eq ! ( 1e-4f16 . classify( ) , Fp :: Normal ) ;
185
+ assert_eq ! ( 1e-5f16 . classify( ) , Fp :: Subnormal ) ;
182
186
}
183
187
184
188
#[ test]
@@ -255,16 +259,16 @@ fn test_trunc() {
255
259
256
260
#[ test]
257
261
fn test_fract ( ) {
258
- assert_approx_eq ! ( 1.0f16 . fract( ) , 0.0f16 , F16_APPROX ) ;
259
- assert_approx_eq ! ( 1.3f16 . fract( ) , 0.3f16 , F16_APPROX ) ;
260
- assert_approx_eq ! ( 1.5f16 . fract( ) , 0.5f16 , F16_APPROX ) ;
261
- assert_approx_eq ! ( 1.7f16 . fract( ) , 0.7f16 , F16_APPROX ) ;
262
- assert_approx_eq ! ( 0.0f16 . fract( ) , 0.0f16 , F16_APPROX ) ;
263
- assert_approx_eq ! ( ( -0.0f16 ) . fract( ) , -0.0f16 , F16_APPROX ) ;
264
- assert_approx_eq ! ( ( -1.0f16 ) . fract( ) , -0.0f16 , F16_APPROX ) ;
265
- assert_approx_eq ! ( ( -1.3f16 ) . fract( ) , -0.3f16 , F16_APPROX ) ;
266
- assert_approx_eq ! ( ( -1.5f16 ) . fract( ) , -0.5f16 , F16_APPROX ) ;
267
- assert_approx_eq ! ( ( -1.7f16 ) . fract( ) , -0.7f16 , F16_APPROX ) ;
262
+ assert_approx_eq ! ( 1.0f16 . fract( ) , 0.0f16 , F16_APPROX_L1 ) ;
263
+ assert_approx_eq ! ( 1.3f16 . fract( ) , 0.3f16 , F16_APPROX_L1 ) ;
264
+ assert_approx_eq ! ( 1.5f16 . fract( ) , 0.5f16 , F16_APPROX_L1 ) ;
265
+ assert_approx_eq ! ( 1.7f16 . fract( ) , 0.7f16 , F16_APPROX_L1 ) ;
266
+ assert_approx_eq ! ( 0.0f16 . fract( ) , 0.0f16 , F16_APPROX_L1 ) ;
267
+ assert_approx_eq ! ( ( -0.0f16 ) . fract( ) , -0.0f16 , F16_APPROX_L1 ) ;
268
+ assert_approx_eq ! ( ( -1.0f16 ) . fract( ) , -0.0f16 , F16_APPROX_L1 ) ;
269
+ assert_approx_eq ! ( ( -1.3f16 ) . fract( ) , -0.3f16 , F16_APPROX_L1 ) ;
270
+ assert_approx_eq ! ( ( -1.5f16 ) . fract( ) , -0.5f16 , F16_APPROX_L1 ) ;
271
+ assert_approx_eq ! ( ( -1.7f16 ) . fract( ) , -0.7f16 , F16_APPROX_L1 ) ;
268
272
}
269
273
270
274
#[ test]
@@ -402,10 +406,10 @@ fn test_mul_add() {
402
406
let nan: f16 = f16:: NAN ;
403
407
let inf: f16 = f16:: INFINITY ;
404
408
let neg_inf: f16 = f16:: NEG_INFINITY ;
405
- assert_approx_eq ! ( 12.3f16 . mul_add( 4.5 , 6.7 ) , 62.05 , F16_APPROX ) ;
406
- assert_approx_eq ! ( ( -12.3f16 ) . mul_add( -4.5 , -6.7 ) , 48.65 , F16_APPROX ) ;
407
- assert_approx_eq ! ( 0.0f16 . mul_add( 8.9 , 1.2 ) , 1.2 , F16_APPROX ) ;
408
- assert_approx_eq ! ( 3.4f16 . mul_add( -0.0 , 5.6 ) , 5.6 , F16_APPROX ) ;
409
+ assert_approx_eq ! ( 12.3f16 . mul_add( 4.5 , 6.7 ) , 62.05 , F16_APPROX_L3 ) ;
410
+ assert_approx_eq ! ( ( -12.3f16 ) . mul_add( -4.5 , -6.7 ) , 48.65 , F16_APPROX_L4 ) ;
411
+ assert_approx_eq ! ( 0.0f16 . mul_add( 8.9 , 1.2 ) , 1.2 , F16_APPROX_L2 ) ;
412
+ assert_approx_eq ! ( 3.4f16 . mul_add( -0.0 , 5.6 ) , 5.6 , F16_APPROX_L2 ) ;
409
413
assert ! ( nan. mul_add( 7.8 , 9.0 ) . is_nan( ) ) ;
410
414
assert_eq ! ( inf. mul_add( 7.8 , 9.0 ) , inf) ;
411
415
assert_eq ! ( neg_inf. mul_add( 7.8 , 9.0 ) , neg_inf) ;
@@ -427,48 +431,35 @@ fn test_recip() {
427
431
assert_eq ! ( neg_inf. recip( ) , 0.0 ) ;
428
432
}
429
433
430
- // TODO: powi gives me LLVM errors:
431
- //
432
- // Both operands to a binary operator are not of the same type!
433
- // %10 = fadd float %9, half 0xHC8CE
434
- // Call parameter type does not match function signature!
435
- // %10 = fadd float %9, half 0xHC8CE
436
- // half %11 = tail call half @llvm.fabs.f16(float %10)
437
- // Intrinsic has incorrect argument type!
438
- // ptr @llvm.powi.f16
439
- // in function _ZN3std3f165tests9test_powi17h5053d7d11c8cb05dE
440
- // LLVM ERROR: Broken function found, compilation aborted!
441
- //
442
- // #[test]
443
- // fn test_powi() {
444
- // let nan: f16 = f16::NAN;
445
- // let inf: f16 = f16::INFINITY;
446
- // let neg_inf: f16 = f16::NEG_INFINITY;
447
- // assert_eq!(1.0f16.powi(1), 1.0);
448
- // assert_approx_eq!((-3.1f16).powi(2), 9.61);
449
- // assert_approx_eq!(5.9f16.powi(-2), 0.028727);
450
- // assert_eq!(8.3f16.powi(0), 1.0);
451
- // assert!(nan.powi(2).is_nan());
452
- // assert_eq!(inf.powi(3), inf);
453
- // assert_eq!(neg_inf.powi(2), inf);
454
- // }
434
+ #[ test]
435
+ fn test_powi ( ) {
436
+ let nan: f16 = f16:: NAN ;
437
+ let inf: f16 = f16:: INFINITY ;
438
+ let neg_inf: f16 = f16:: NEG_INFINITY ;
439
+ assert_eq ! ( 1.0f16 . powi( 1 ) , 1.0 ) ;
440
+ assert_approx_eq ! ( ( -3.1f16 ) . powi( 2 ) , 9.61 ) ;
441
+ assert_approx_eq ! ( 5.9f16 . powi( -2 ) , 0.028727 ) ;
442
+ assert_eq ! ( 8.3f16 . powi( 0 ) , 1.0 ) ;
443
+ assert ! ( nan. powi( 2 ) . is_nan( ) ) ;
444
+ assert_eq ! ( inf. powi( 3 ) , inf) ;
445
+ assert_eq ! ( neg_inf. powi( 2 ) , inf) ;
446
+ }
455
447
456
- // TODO: LLVM errors
457
- // #[test]
458
- // fn test_powf() {
459
- // let nan: f16 = f16::NAN;
460
- // let inf: f16 = f16::INFINITY;
461
- // let neg_inf: f16 = f16::NEG_INFINITY;
462
- // assert_eq!(1.0f16.powf(1.0), 1.0);
463
- // assert_approx_eq!(3.4f16.powf(4.5), 246.408218);
464
- // assert_approx_eq!(2.7f16.powf(-3.2), 0.041652);
465
- // assert_approx_eq!((-3.1f16).powf(2.0), 9.61);
466
- // assert_approx_eq!(5.9f16.powf(-2.0), 0.028727);
467
- // assert_eq!(8.3f16.powf(0.0), 1.0);
468
- // assert!(nan.powf(2.0).is_nan());
469
- // assert_eq!(inf.powf(2.0), inf);
470
- // assert_eq!(neg_inf.powf(3.0), neg_inf);
471
- // }
448
+ #[ test]
449
+ fn test_powf ( ) {
450
+ let nan: f16 = f16:: NAN ;
451
+ let inf: f16 = f16:: INFINITY ;
452
+ let neg_inf: f16 = f16:: NEG_INFINITY ;
453
+ assert_eq ! ( 1.0f16 . powf( 1.0 ) , 1.0 ) ;
454
+ assert_approx_eq ! ( 3.4f16 . powf( 4.5 ) , 246.408218 , F16_APPROX_L4 ) ;
455
+ assert_approx_eq ! ( 2.7f16 . powf( -3.2 ) , 0.041652 , F16_APPROX_L1 ) ;
456
+ assert_approx_eq ! ( ( -3.1f16 ) . powf( 2.0 ) , 9.61 , F16_APPROX_L1 ) ;
457
+ assert_approx_eq ! ( 5.9f16 . powf( -2.0 ) , 0.028727 , F16_APPROX_L1 ) ;
458
+ assert_eq ! ( 8.3f16 . powf( 0.0 ) , 1.0 ) ;
459
+ assert ! ( nan. powf( 2.0 ) . is_nan( ) ) ;
460
+ assert_eq ! ( inf. powf( 2.0 ) , inf) ;
461
+ assert_eq ! ( neg_inf. powf( 3.0 ) , neg_inf) ;
462
+ }
472
463
473
464
#[ test]
474
465
fn test_sqrt_domain ( ) {
@@ -546,9 +537,9 @@ fn test_log2() {
546
537
let nan: f16 = f16:: NAN ;
547
538
let inf: f16 = f16:: INFINITY ;
548
539
let neg_inf: f16 = f16:: NEG_INFINITY ;
549
- assert_approx_eq ! ( 10.0f16 . log2( ) , 3.321928 , F16_APPROX ) ;
550
- assert_approx_eq ! ( 2.3f16 . log2( ) , 1.201634 , F16_APPROX ) ;
551
- assert_approx_eq ! ( 1.0f16 . exp( ) . log2( ) , 1.442695 , F16_APPROX ) ;
540
+ assert_approx_eq ! ( 10.0f16 . log2( ) , 3.321928 , F16_APPROX_L1 ) ;
541
+ assert_approx_eq ! ( 2.3f16 . log2( ) , 1.201634 , F16_APPROX_L1 ) ;
542
+ assert_approx_eq ! ( 1.0f16 . exp( ) . log2( ) , 1.442695 , F16_APPROX_L1 ) ;
552
543
assert ! ( nan. log2( ) . is_nan( ) ) ;
553
544
assert_eq ! ( inf. log2( ) , inf) ;
554
545
assert ! ( neg_inf. log2( ) . is_nan( ) ) ;
@@ -581,13 +572,12 @@ fn test_to_degrees() {
581
572
let inf: f16 = f16:: INFINITY ;
582
573
let neg_inf: f16 = f16:: NEG_INFINITY ;
583
574
assert_eq ! ( 0.0f16 . to_degrees( ) , 0.0 ) ;
584
- // Loss of precision here, increase our bounds
585
- assert_approx_eq ! ( ( -5.8f16 ) . to_degrees( ) , -332.315521 , F16_APPROX * 1.1 ) ;
575
+ assert_approx_eq ! ( ( -5.8f16 ) . to_degrees( ) , -332.315521 , F16_APPROX_L4 ) ;
586
576
assert_eq ! ( pi. to_degrees( ) , 180.0 ) ;
587
577
assert ! ( nan. to_degrees( ) . is_nan( ) ) ;
588
578
assert_eq ! ( inf. to_degrees( ) , inf) ;
589
579
assert_eq ! ( neg_inf. to_degrees( ) , neg_inf) ;
590
- assert_eq ! ( 1_ f16. to_degrees( ) , 57.2957795130823208767981548141051703 ) ;
580
+ assert_approx_eq ! ( 1_ f16. to_degrees( ) , 57.29577951 , F16_APPROX_L3 ) ;
591
581
}
592
582
593
583
#[ test]
@@ -597,15 +587,15 @@ fn test_to_radians() {
597
587
let inf: f16 = f16:: INFINITY ;
598
588
let neg_inf: f16 = f16:: NEG_INFINITY ;
599
589
assert_eq ! ( 0.0f16 . to_radians( ) , 0.0 ) ;
600
- // Loss of precision here, increase our bounds
601
- assert_approx_eq ! ( 154.6f16 . to_radians( ) , 2.698279 , F16_APPROX * 1.1 ) ;
602
- assert_approx_eq ! ( ( -332.31f16 ) . to_radians( ) , -5.799903 , F16_APPROX ) ;
603
- assert_eq ! ( 180.0f16 . to_radians( ) , pi) ;
590
+ assert_approx_eq ! ( 154.6f16 . to_radians( ) , 2.698279 , F16_APPROX_L3 ) ;
591
+ assert_approx_eq ! ( ( -332.31f16 ) . to_radians( ) , -5.799903 , F16_APPROX_L3 ) ;
592
+ assert_approx_eq ! ( 180.0f16 . to_radians( ) , pi, F16_APPROX_L3 ) ;
604
593
assert ! ( nan. to_radians( ) . is_nan( ) ) ;
605
594
assert_eq ! ( inf. to_radians( ) , inf) ;
606
595
assert_eq ! ( neg_inf. to_radians( ) , neg_inf) ;
607
596
}
608
597
598
+ // Disabled since this relies on cmath
609
599
// #[test]
610
600
// fn test_asinh() {
611
601
// assert_eq!(0.0f16.asinh(), 0.0f16);
@@ -724,20 +714,20 @@ fn test_real_consts() {
724
714
let ln_2: f16 = consts:: LN_2 ;
725
715
let ln_10: f16 = consts:: LN_10 ;
726
716
727
- assert_approx_eq ! ( frac_pi_2, pi / 2 f16, F16_APPROX ) ;
728
- assert_approx_eq ! ( frac_pi_3, pi / 3 f16, F16_APPROX ) ;
729
- assert_approx_eq ! ( frac_pi_4, pi / 4 f16, F16_APPROX ) ;
730
- assert_approx_eq ! ( frac_pi_6, pi / 6 f16, F16_APPROX ) ;
731
- assert_approx_eq ! ( frac_pi_8, pi / 8 f16, F16_APPROX ) ;
732
- assert_approx_eq ! ( frac_1_pi, 1 f16 / pi, F16_APPROX ) ;
733
- assert_approx_eq ! ( frac_2_pi, 2 f16 / pi, F16_APPROX ) ;
734
- assert_approx_eq ! ( frac_2_sqrtpi, 2 f16 / pi. sqrt( ) , F16_APPROX ) ;
735
- assert_approx_eq ! ( sqrt2, 2 f16. sqrt( ) , F16_APPROX ) ;
736
- assert_approx_eq ! ( frac_1_sqrt2, 1 f16 / 2 f16. sqrt( ) , F16_APPROX ) ;
737
- assert_approx_eq ! ( log2_e, e. log2( ) , F16_APPROX ) ;
738
- assert_approx_eq ! ( log10_e, e. log10( ) , F16_APPROX ) ;
739
- assert_approx_eq ! ( ln_2, 2 f16. ln( ) , F16_APPROX ) ;
740
- assert_approx_eq ! ( ln_10, 10 f16. ln( ) , F16_APPROX ) ;
717
+ assert_approx_eq ! ( frac_pi_2, pi / 2 f16, F16_APPROX_L1 ) ;
718
+ assert_approx_eq ! ( frac_pi_3, pi / 3 f16, F16_APPROX_L1 ) ;
719
+ assert_approx_eq ! ( frac_pi_4, pi / 4 f16, F16_APPROX_L1 ) ;
720
+ assert_approx_eq ! ( frac_pi_6, pi / 6 f16, F16_APPROX_L1 ) ;
721
+ assert_approx_eq ! ( frac_pi_8, pi / 8 f16, F16_APPROX_L1 ) ;
722
+ assert_approx_eq ! ( frac_1_pi, 1 f16 / pi, F16_APPROX_L1 ) ;
723
+ assert_approx_eq ! ( frac_2_pi, 2 f16 / pi, F16_APPROX_L1 ) ;
724
+ assert_approx_eq ! ( frac_2_sqrtpi, 2 f16 / pi. sqrt( ) , F16_APPROX_L1 ) ;
725
+ assert_approx_eq ! ( sqrt2, 2 f16. sqrt( ) , F16_APPROX_L1 ) ;
726
+ assert_approx_eq ! ( frac_1_sqrt2, 1 f16 / 2 f16. sqrt( ) , F16_APPROX_L1 ) ;
727
+ assert_approx_eq ! ( log2_e, e. log2( ) , F16_APPROX_L1 ) ;
728
+ assert_approx_eq ! ( log10_e, e. log10( ) , F16_APPROX_L1 ) ;
729
+ assert_approx_eq ! ( ln_2, 2 f16. ln( ) , F16_APPROX_L1 ) ;
730
+ assert_approx_eq ! ( ln_10, 10 f16. ln( ) , F16_APPROX_L1 ) ;
741
731
}
742
732
743
733
#[ test]
0 commit comments