@@ -2,7 +2,11 @@ use crate::f16::consts;
22use crate :: num:: FpCategory as Fp ;
33use crate :: num:: * ;
44
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 ;
610
711#[ test]
812fn test_num_f16 ( ) {
@@ -160,8 +164,8 @@ fn test_is_normal() {
160164 assert ! ( !zero. is_normal( ) ) ;
161165 assert ! ( !neg_zero. is_normal( ) ) ;
162166 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( ) ) ;
165169}
166170
167171#[ test]
@@ -177,8 +181,8 @@ fn test_classify() {
177181 assert_eq ! ( zero. classify( ) , Fp :: Zero ) ;
178182 assert_eq ! ( neg_zero. classify( ) , Fp :: Zero ) ;
179183 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 ) ;
182186}
183187
184188#[ test]
@@ -255,16 +259,16 @@ fn test_trunc() {
255259
256260#[ test]
257261fn 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 ) ;
268272}
269273
270274#[ test]
@@ -402,10 +406,10 @@ fn test_mul_add() {
402406 let nan: f16 = f16:: NAN ;
403407 let inf: f16 = f16:: INFINITY ;
404408 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 ) ;
409413 assert ! ( nan. mul_add( 7.8 , 9.0 ) . is_nan( ) ) ;
410414 assert_eq ! ( inf. mul_add( 7.8 , 9.0 ) , inf) ;
411415 assert_eq ! ( neg_inf. mul_add( 7.8 , 9.0 ) , neg_inf) ;
@@ -427,48 +431,35 @@ fn test_recip() {
427431 assert_eq ! ( neg_inf. recip( ) , 0.0 ) ;
428432}
429433
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+ }
455447
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+ }
472463
473464#[ test]
474465fn test_sqrt_domain ( ) {
@@ -546,9 +537,9 @@ fn test_log2() {
546537 let nan: f16 = f16:: NAN ;
547538 let inf: f16 = f16:: INFINITY ;
548539 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 ) ;
552543 assert ! ( nan. log2( ) . is_nan( ) ) ;
553544 assert_eq ! ( inf. log2( ) , inf) ;
554545 assert ! ( neg_inf. log2( ) . is_nan( ) ) ;
@@ -581,13 +572,12 @@ fn test_to_degrees() {
581572 let inf: f16 = f16:: INFINITY ;
582573 let neg_inf: f16 = f16:: NEG_INFINITY ;
583574 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 ) ;
586576 assert_eq ! ( pi. to_degrees( ) , 180.0 ) ;
587577 assert ! ( nan. to_degrees( ) . is_nan( ) ) ;
588578 assert_eq ! ( inf. to_degrees( ) , inf) ;
589579 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 ) ;
591581}
592582
593583#[ test]
@@ -597,15 +587,15 @@ fn test_to_radians() {
597587 let inf: f16 = f16:: INFINITY ;
598588 let neg_inf: f16 = f16:: NEG_INFINITY ;
599589 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 ) ;
604593 assert ! ( nan. to_radians( ) . is_nan( ) ) ;
605594 assert_eq ! ( inf. to_radians( ) , inf) ;
606595 assert_eq ! ( neg_inf. to_radians( ) , neg_inf) ;
607596}
608597
598+ // Disabled since this relies on cmath
609599// #[test]
610600// fn test_asinh() {
611601// assert_eq!(0.0f16.asinh(), 0.0f16);
@@ -724,20 +714,20 @@ fn test_real_consts() {
724714 let ln_2: f16 = consts:: LN_2 ;
725715 let ln_10: f16 = consts:: LN_10 ;
726716
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 ) ;
741731}
742732
743733#[ test]
0 commit comments