@@ -121,6 +121,10 @@ mod tests {
121
121
Subdf3 ,
122
122
Subsf3 ,
123
123
124
+ // float/mul.rs
125
+ Mulsf3 ,
126
+ Muldf3 ,
127
+
124
128
// int/mul.rs
125
129
Muldi3 ,
126
130
Mulodi4 ,
@@ -3221,6 +3225,181 @@ fn subsf3() {
3221
3225
}
3222
3226
}
3223
3227
3228
+ #[ derive( Eq , Hash , PartialEq ) ]
3229
+ pub struct Mulsf3 {
3230
+ a : u32 , // f32
3231
+ b : u32 , // f32
3232
+ c : u32 , // f32
3233
+ }
3234
+
3235
+ impl TestCase for Mulsf3 {
3236
+ fn name ( ) -> & ' static str {
3237
+ "mulsf3"
3238
+ }
3239
+
3240
+ fn generate < R > ( rng : & mut R ) -> Option < Self >
3241
+ where
3242
+ R : Rng ,
3243
+ Self : Sized ,
3244
+ {
3245
+ let a = gen_large_f32 ( rng) ;
3246
+ let b = gen_large_f32 ( rng) ;
3247
+ let c = a * b;
3248
+ // TODO accept NaNs. We don't do that right now because we can't check
3249
+ // for NaN-ness on the thumb targets (due to missing intrinsics)
3250
+ if a. is_nan ( ) || b. is_nan ( ) || c. is_nan ( ) {
3251
+ return None ;
3252
+ }
3253
+
3254
+ Some (
3255
+ Mulsf3 {
3256
+ a : to_u32 ( a) ,
3257
+ b : to_u32 ( b) ,
3258
+ c : to_u32 ( c) ,
3259
+ } ,
3260
+ )
3261
+ }
3262
+
3263
+ fn to_string ( & self , buffer : & mut String ) {
3264
+ writeln ! (
3265
+ buffer,
3266
+ "(({a}, {b}), {c})," ,
3267
+ a = self . a,
3268
+ b = self . b,
3269
+ c = self . c
3270
+ )
3271
+ . unwrap ( ) ;
3272
+ }
3273
+
3274
+ fn prologue ( ) -> & ' static str {
3275
+ r#"
3276
+ #[cfg(all(target_arch = "arm",
3277
+ not(any(target_env = "gnu", target_env = "musl")),
3278
+ target_os = "linux",
3279
+ test))]
3280
+ use core::mem;
3281
+ #[cfg(not(all(target_arch = "arm",
3282
+ not(any(target_env = "gnu", target_env = "musl")),
3283
+ target_os = "linux",
3284
+ test)))]
3285
+ use std::mem;
3286
+ use compiler_builtins::float::mul::__mulsf3;
3287
+
3288
+ fn mk_f32(x: u32) -> f32 {
3289
+ unsafe { mem::transmute(x) }
3290
+ }
3291
+
3292
+ fn to_u32(x: f32) -> u32 {
3293
+ unsafe { mem::transmute(x) }
3294
+ }
3295
+
3296
+ static TEST_CASES: &[((u32, u32), u32)] = &[
3297
+ "#
3298
+ }
3299
+
3300
+ fn epilogue ( ) -> & ' static str {
3301
+ "
3302
+ ];
3303
+
3304
+ #[test]
3305
+ fn mulsf3() {
3306
+ for &((a, b), c) in TEST_CASES {
3307
+ let c_ = __mulsf3(mk_f32(a), mk_f32(b));
3308
+ assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
3309
+ }
3310
+ }
3311
+ "
3312
+ }
3313
+ }
3314
+
3315
+ #[ derive( Eq , Hash , PartialEq ) ]
3316
+ pub struct Muldf3 {
3317
+ a : u64 , // f64
3318
+ b : u64 , // f64
3319
+ c : u64 , // f64
3320
+ }
3321
+
3322
+ impl TestCase for Muldf3 {
3323
+ fn name ( ) -> & ' static str {
3324
+ "muldf3"
3325
+ }
3326
+
3327
+ fn generate < R > ( rng : & mut R ) -> Option < Self >
3328
+ where
3329
+ R : Rng ,
3330
+ Self : Sized ,
3331
+ {
3332
+ let a = gen_large_f64 ( rng) ;
3333
+ let b = gen_large_f64 ( rng) ;
3334
+ let c = a * b;
3335
+ // TODO accept NaNs. We don't do that right now because we can't check
3336
+ // for NaN-ness on the thumb targets (due to missing intrinsics)
3337
+ if a. is_nan ( ) || b. is_nan ( ) || c. is_nan ( ) {
3338
+ return None ;
3339
+ }
3340
+
3341
+ Some (
3342
+ Muldf3 {
3343
+ a : to_u64 ( a) ,
3344
+ b : to_u64 ( b) ,
3345
+ c : to_u64 ( c) ,
3346
+ } ,
3347
+ )
3348
+ }
3349
+
3350
+ fn to_string ( & self , buffer : & mut String ) {
3351
+ writeln ! (
3352
+ buffer,
3353
+ "(({a}, {b}), {c})," ,
3354
+ a = self . a,
3355
+ b = self . b,
3356
+ c = self . c
3357
+ )
3358
+ . unwrap ( ) ;
3359
+ }
3360
+
3361
+ fn prologue ( ) -> & ' static str {
3362
+ r#"
3363
+ #[cfg(all(target_arch = "arm",
3364
+ not(any(target_env = "gnu", target_env = "musl")),
3365
+ target_os = "linux",
3366
+ test))]
3367
+ use core::mem;
3368
+ #[cfg(not(all(target_arch = "arm",
3369
+ not(any(target_env = "gnu", target_env = "musl")),
3370
+ target_os = "linux",
3371
+ test)))]
3372
+ use std::mem;
3373
+ use compiler_builtins::float::mul::__muldf3;
3374
+
3375
+ fn mk_f64(x: u64) -> f64 {
3376
+ unsafe { mem::transmute(x) }
3377
+ }
3378
+
3379
+ fn to_u64(x: f64) -> u64 {
3380
+ unsafe { mem::transmute(x) }
3381
+ }
3382
+
3383
+ static TEST_CASES: &[((u64, u64), u64)] = &[
3384
+ "#
3385
+ }
3386
+
3387
+ fn epilogue ( ) -> & ' static str {
3388
+ "
3389
+ ];
3390
+
3391
+ #[test]
3392
+ fn muldf3() {
3393
+ for &((a, b), c) in TEST_CASES {
3394
+ let c_ = __muldf3(mk_f64(a), mk_f64(b));
3395
+ assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
3396
+ }
3397
+ }
3398
+ "
3399
+ }
3400
+ }
3401
+
3402
+
3224
3403
#[ derive( Eq , Hash , PartialEq ) ]
3225
3404
pub struct Udivdi3 {
3226
3405
a : u64 ,
@@ -3899,6 +4078,57 @@ macro_rules! panic {
3899
4078
gen_float ! ( gen_f32, f32 , u32 , 32 , 23 ) ;
3900
4079
gen_float ! ( gen_f64, f64 , u64 , 64 , 52 ) ;
3901
4080
4081
+ macro_rules! gen_large_float {
4082
+ ( $name: ident,
4083
+ $fty: ident,
4084
+ $uty: ident,
4085
+ $bits: expr,
4086
+ $significand_bits: expr) => {
4087
+ pub fn $name<R >( rng: & mut R ) -> $fty
4088
+ where
4089
+ R : Rng ,
4090
+ {
4091
+ const BITS : u8 = $bits;
4092
+ const SIGNIFICAND_BITS : u8 = $significand_bits;
4093
+
4094
+ const SIGNIFICAND_MASK : $uty = ( 1 << SIGNIFICAND_BITS ) - 1 ;
4095
+ const SIGN_MASK : $uty = ( 1 << ( BITS - 1 ) ) ;
4096
+ const EXPONENT_MASK : $uty = !( SIGN_MASK | SIGNIFICAND_MASK ) ;
4097
+
4098
+ fn mk_f32( sign: bool , exponent: $uty, significand: $uty) -> $fty {
4099
+ unsafe {
4100
+ mem:: transmute( ( ( sign as $uty) << ( BITS - 1 ) ) |
4101
+ ( ( exponent & EXPONENT_MASK ) <<
4102
+ SIGNIFICAND_BITS ) |
4103
+ ( significand & SIGNIFICAND_MASK ) )
4104
+ }
4105
+ }
4106
+
4107
+ if rng. gen_weighted_bool( 10 ) {
4108
+ // Special values
4109
+ * rng. choose( & [ -0.0 ,
4110
+ 0.0 ,
4111
+ :: std:: $fty:: NAN ,
4112
+ :: std:: $fty:: INFINITY ,
4113
+ -:: std:: $fty:: INFINITY ] )
4114
+ . unwrap( )
4115
+ } else if rng. gen_weighted_bool( 10 ) {
4116
+ // NaN patterns
4117
+ mk_f32( rng. gen ( ) , rng. gen ( ) , 0 )
4118
+ } else if rng. gen ( ) {
4119
+ // Denormalized
4120
+ mk_f32( rng. gen ( ) , 0 , rng. gen ( ) )
4121
+ } else {
4122
+ // Random anything
4123
+ rng. gen :: <$fty>( )
4124
+ }
4125
+ }
4126
+ }
4127
+ }
4128
+
4129
+ gen_large_float ! ( gen_large_f32, f32 , u32 , 32 , 23 ) ;
4130
+ gen_large_float ! ( gen_large_f64, f64 , u64 , 64 , 52 ) ;
4131
+
3902
4132
pub fn gen_u128 < R > ( rng : & mut R ) -> u128
3903
4133
where
3904
4134
R : Rng ,
0 commit comments