Auto merge of #3601 - RalfJung:intrinsics, r=RalfJung
a bit of intrinsics organization
This commit is contained in:
commit
14ced80892
6 changed files with 230 additions and 236 deletions
|
|
@ -167,6 +167,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// This is a "bitwise" operation, so there's no NaN non-determinism.
|
||||
this.write_scalar(Scalar::from_f64(f.abs()), dest)?;
|
||||
}
|
||||
|
||||
"floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => {
|
||||
let [f] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f32()?;
|
||||
|
|
@ -182,6 +183,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"floorf64" | "ceilf64" | "truncf64" | "roundf64" | "rintf64" => {
|
||||
let [f] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f64()?;
|
||||
let mode = match intrinsic_name {
|
||||
"floorf64" => Round::TowardNegative,
|
||||
"ceilf64" => Round::TowardPositive,
|
||||
"truncf64" => Round::TowardZero,
|
||||
"roundf64" => Round::NearestTiesToAway,
|
||||
"rintf64" => Round::NearestTiesToEven,
|
||||
_ => bug!(),
|
||||
};
|
||||
let res = f.round_to_integral(mode).value;
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
| "sinf32"
|
||||
| "cosf32"
|
||||
|
|
@ -211,22 +228,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"floorf64" | "ceilf64" | "truncf64" | "roundf64" | "rintf64" => {
|
||||
let [f] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f64()?;
|
||||
let mode = match intrinsic_name {
|
||||
"floorf64" => Round::TowardNegative,
|
||||
"ceilf64" => Round::TowardPositive,
|
||||
"truncf64" => Round::TowardZero,
|
||||
"roundf64" => Round::NearestTiesToAway,
|
||||
"rintf64" => Round::NearestTiesToEven,
|
||||
_ => bug!(),
|
||||
};
|
||||
let res = f.round_to_integral(mode).value;
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
#[rustfmt::skip]
|
||||
| "sinf64"
|
||||
| "cosf64"
|
||||
|
|
@ -256,6 +257,91 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"minnumf32" | "maxnumf32" | "copysignf32" => {
|
||||
let [a, b] = check_arg_count(args)?;
|
||||
let a = this.read_scalar(a)?.to_f32()?;
|
||||
let b = this.read_scalar(b)?.to_f32()?;
|
||||
let res = match intrinsic_name {
|
||||
"minnumf32" => this.adjust_nan(a.min(b), &[a, b]),
|
||||
"maxnumf32" => this.adjust_nan(a.max(b), &[a, b]),
|
||||
"copysignf32" => a.copy_sign(b), // bitwise, no NaN adjustments
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_f32(res), dest)?;
|
||||
}
|
||||
"minnumf64" | "maxnumf64" | "copysignf64" => {
|
||||
let [a, b] = check_arg_count(args)?;
|
||||
let a = this.read_scalar(a)?.to_f64()?;
|
||||
let b = this.read_scalar(b)?.to_f64()?;
|
||||
let res = match intrinsic_name {
|
||||
"minnumf64" => this.adjust_nan(a.min(b), &[a, b]),
|
||||
"maxnumf64" => this.adjust_nan(a.max(b), &[a, b]),
|
||||
"copysignf64" => a.copy_sign(b), // bitwise, no NaN adjustments
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_f64(res), dest)?;
|
||||
}
|
||||
|
||||
"fmaf32" => {
|
||||
let [a, b, c] = check_arg_count(args)?;
|
||||
let a = this.read_scalar(a)?.to_f32()?;
|
||||
let b = this.read_scalar(b)?.to_f32()?;
|
||||
let c = this.read_scalar(c)?.to_f32()?;
|
||||
// FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
|
||||
let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[a, b, c]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"fmaf64" => {
|
||||
let [a, b, c] = check_arg_count(args)?;
|
||||
let a = this.read_scalar(a)?.to_f64()?;
|
||||
let b = this.read_scalar(b)?.to_f64()?;
|
||||
let c = this.read_scalar(c)?.to_f64()?;
|
||||
// FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
|
||||
let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[a, b, c]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"powf32" => {
|
||||
let [f1, f2] = check_arg_count(args)?;
|
||||
let f1 = this.read_scalar(f1)?.to_f32()?;
|
||||
let f2 = this.read_scalar(f2)?.to_f32()?;
|
||||
// Using host floats (but it's fine, this operation does not have guaranteed precision).
|
||||
let res = f1.to_host().powf(f2.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[f1, f2]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"powf64" => {
|
||||
let [f1, f2] = check_arg_count(args)?;
|
||||
let f1 = this.read_scalar(f1)?.to_f64()?;
|
||||
let f2 = this.read_scalar(f2)?.to_f64()?;
|
||||
// Using host floats (but it's fine, this operation does not have guaranteed precision).
|
||||
let res = f1.to_host().powf(f2.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[f1, f2]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"powif32" => {
|
||||
let [f, i] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f32()?;
|
||||
let i = this.read_scalar(i)?.to_i32()?;
|
||||
// Using host floats (but it's fine, this operation does not have guaranteed precision).
|
||||
let res = f.to_host().powi(i).to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"powif64" => {
|
||||
let [f, i] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f64()?;
|
||||
let i = this.read_scalar(i)?.to_i32()?;
|
||||
// Using host floats (but it's fine, this operation does not have guaranteed precision).
|
||||
let res = f.to_host().powi(i).to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
| "fadd_algebraic"
|
||||
| "fsub_algebraic"
|
||||
|
|
@ -329,102 +415,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
this.write_immediate(*res, dest)?;
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
| "minnumf32"
|
||||
| "maxnumf32"
|
||||
| "copysignf32"
|
||||
=> {
|
||||
let [a, b] = check_arg_count(args)?;
|
||||
let a = this.read_scalar(a)?.to_f32()?;
|
||||
let b = this.read_scalar(b)?.to_f32()?;
|
||||
let res = match intrinsic_name {
|
||||
"minnumf32" => this.adjust_nan(a.min(b), &[a, b]),
|
||||
"maxnumf32" => this.adjust_nan(a.max(b), &[a, b]),
|
||||
"copysignf32" => a.copy_sign(b), // bitwise, no NaN adjustments
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_f32(res), dest)?;
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
| "minnumf64"
|
||||
| "maxnumf64"
|
||||
| "copysignf64"
|
||||
=> {
|
||||
let [a, b] = check_arg_count(args)?;
|
||||
let a = this.read_scalar(a)?.to_f64()?;
|
||||
let b = this.read_scalar(b)?.to_f64()?;
|
||||
let res = match intrinsic_name {
|
||||
"minnumf64" => this.adjust_nan(a.min(b), &[a, b]),
|
||||
"maxnumf64" => this.adjust_nan(a.max(b), &[a, b]),
|
||||
"copysignf64" => a.copy_sign(b), // bitwise, no NaN adjustments
|
||||
_ => bug!(),
|
||||
};
|
||||
this.write_scalar(Scalar::from_f64(res), dest)?;
|
||||
}
|
||||
|
||||
"fmaf32" => {
|
||||
let [a, b, c] = check_arg_count(args)?;
|
||||
let a = this.read_scalar(a)?.to_f32()?;
|
||||
let b = this.read_scalar(b)?.to_f32()?;
|
||||
let c = this.read_scalar(c)?.to_f32()?;
|
||||
// FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
|
||||
let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[a, b, c]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"fmaf64" => {
|
||||
let [a, b, c] = check_arg_count(args)?;
|
||||
let a = this.read_scalar(a)?.to_f64()?;
|
||||
let b = this.read_scalar(b)?.to_f64()?;
|
||||
let c = this.read_scalar(c)?.to_f64()?;
|
||||
// FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
|
||||
let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[a, b, c]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"powf32" => {
|
||||
let [f1, f2] = check_arg_count(args)?;
|
||||
let f1 = this.read_scalar(f1)?.to_f32()?;
|
||||
let f2 = this.read_scalar(f2)?.to_f32()?;
|
||||
// Using host floats (but it's fine, this operation does not have guaranteed precision).
|
||||
let res = f1.to_host().powf(f2.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[f1, f2]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"powf64" => {
|
||||
let [f1, f2] = check_arg_count(args)?;
|
||||
let f1 = this.read_scalar(f1)?.to_f64()?;
|
||||
let f2 = this.read_scalar(f2)?.to_f64()?;
|
||||
// Using host floats (but it's fine, this operation does not have guaranteed precision).
|
||||
let res = f1.to_host().powf(f2.to_host()).to_soft();
|
||||
let res = this.adjust_nan(res, &[f1, f2]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"powif32" => {
|
||||
let [f, i] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f32()?;
|
||||
let i = this.read_scalar(i)?.to_i32()?;
|
||||
// Using host floats (but it's fine, this operation does not have guaranteed precision).
|
||||
let res = f.to_host().powi(i).to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"powif64" => {
|
||||
let [f, i] = check_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f64()?;
|
||||
let i = this.read_scalar(i)?.to_i32()?;
|
||||
// Using host floats (but it's fine, this operation does not have guaranteed precision).
|
||||
let res = f.to_host().powi(i).to_soft();
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
|
||||
"float_to_int_unchecked" => {
|
||||
let [val] = check_arg_count(args)?;
|
||||
let val = this.read_immediate(val)?;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(float_gamma)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![allow(arithmetic_overflow)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
|
@ -22,6 +23,8 @@ fn main() {
|
|||
rounding();
|
||||
mul_add();
|
||||
libm();
|
||||
test_fast();
|
||||
test_algebraic();
|
||||
}
|
||||
|
||||
// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE.
|
||||
|
|
@ -751,3 +754,67 @@ pub fn libm() {
|
|||
assert_approx_eq!(val, (2.0 * f64::consts::PI.sqrt()).ln());
|
||||
assert_eq!(sign, -1);
|
||||
}
|
||||
|
||||
fn test_fast() {
|
||||
use std::intrinsics::{fadd_fast, fdiv_fast, fmul_fast, frem_fast, fsub_fast};
|
||||
|
||||
#[inline(never)]
|
||||
pub fn test_operations_f64(a: f64, b: f64) {
|
||||
// make sure they all map to the correct operation
|
||||
unsafe {
|
||||
assert_eq!(fadd_fast(a, b), a + b);
|
||||
assert_eq!(fsub_fast(a, b), a - b);
|
||||
assert_eq!(fmul_fast(a, b), a * b);
|
||||
assert_eq!(fdiv_fast(a, b), a / b);
|
||||
assert_eq!(frem_fast(a, b), a % b);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn test_operations_f32(a: f32, b: f32) {
|
||||
// make sure they all map to the correct operation
|
||||
unsafe {
|
||||
assert_eq!(fadd_fast(a, b), a + b);
|
||||
assert_eq!(fsub_fast(a, b), a - b);
|
||||
assert_eq!(fmul_fast(a, b), a * b);
|
||||
assert_eq!(fdiv_fast(a, b), a / b);
|
||||
assert_eq!(frem_fast(a, b), a % b);
|
||||
}
|
||||
}
|
||||
|
||||
test_operations_f64(1., 2.);
|
||||
test_operations_f64(10., 5.);
|
||||
test_operations_f32(11., 2.);
|
||||
test_operations_f32(10., 15.);
|
||||
}
|
||||
|
||||
fn test_algebraic() {
|
||||
use std::intrinsics::{
|
||||
fadd_algebraic, fdiv_algebraic, fmul_algebraic, frem_algebraic, fsub_algebraic,
|
||||
};
|
||||
|
||||
#[inline(never)]
|
||||
pub fn test_operations_f64(a: f64, b: f64) {
|
||||
// make sure they all map to the correct operation
|
||||
assert_eq!(fadd_algebraic(a, b), a + b);
|
||||
assert_eq!(fsub_algebraic(a, b), a - b);
|
||||
assert_eq!(fmul_algebraic(a, b), a * b);
|
||||
assert_eq!(fdiv_algebraic(a, b), a / b);
|
||||
assert_eq!(frem_algebraic(a, b), a % b);
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn test_operations_f32(a: f32, b: f32) {
|
||||
// make sure they all map to the correct operation
|
||||
assert_eq!(fadd_algebraic(a, b), a + b);
|
||||
assert_eq!(fsub_algebraic(a, b), a - b);
|
||||
assert_eq!(fmul_algebraic(a, b), a * b);
|
||||
assert_eq!(fdiv_algebraic(a, b), a / b);
|
||||
assert_eq!(frem_algebraic(a, b), a % b);
|
||||
}
|
||||
|
||||
test_operations_f64(1., 2.);
|
||||
test_operations_f64(10., 5.);
|
||||
test_operations_f32(11., 2.);
|
||||
test_operations_f32(10., 15.);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
#![feature(core_intrinsics)]
|
||||
|
||||
use std::intrinsics::{fadd_fast, fdiv_fast, fmul_fast, frem_fast, fsub_fast};
|
||||
|
||||
#[inline(never)]
|
||||
pub fn test_operations_f64(a: f64, b: f64) {
|
||||
// make sure they all map to the correct operation
|
||||
unsafe {
|
||||
assert_eq!(fadd_fast(a, b), a + b);
|
||||
assert_eq!(fsub_fast(a, b), a - b);
|
||||
assert_eq!(fmul_fast(a, b), a * b);
|
||||
assert_eq!(fdiv_fast(a, b), a / b);
|
||||
assert_eq!(frem_fast(a, b), a % b);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn test_operations_f32(a: f32, b: f32) {
|
||||
// make sure they all map to the correct operation
|
||||
unsafe {
|
||||
assert_eq!(fadd_fast(a, b), a + b);
|
||||
assert_eq!(fsub_fast(a, b), a - b);
|
||||
assert_eq!(fmul_fast(a, b), a * b);
|
||||
assert_eq!(fdiv_fast(a, b), a / b);
|
||||
assert_eq!(frem_fast(a, b), a % b);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_operations_f64(1., 2.);
|
||||
test_operations_f64(10., 5.);
|
||||
test_operations_f32(11., 2.);
|
||||
test_operations_f32(10., 15.);
|
||||
}
|
||||
|
|
@ -1,7 +1,64 @@
|
|||
//@compile-flags: -Coverflow-checks=off
|
||||
#![allow(arithmetic_overflow)]
|
||||
|
||||
fn basic() {
|
||||
fn ret() -> i64 {
|
||||
1
|
||||
}
|
||||
|
||||
fn neg() -> i64 {
|
||||
-1
|
||||
}
|
||||
|
||||
fn add() -> i64 {
|
||||
1 + 2
|
||||
}
|
||||
|
||||
fn indirect_add() -> i64 {
|
||||
let x = 1;
|
||||
let y = 2;
|
||||
x + y
|
||||
}
|
||||
|
||||
fn arith() -> i32 {
|
||||
3 * 3 + 4 * 4
|
||||
}
|
||||
|
||||
fn match_int() -> i16 {
|
||||
let n = 2;
|
||||
match n {
|
||||
0 => 0,
|
||||
1 => 10,
|
||||
2 => 20,
|
||||
3 => 30,
|
||||
_ => 100,
|
||||
}
|
||||
}
|
||||
|
||||
fn match_int_range() -> i64 {
|
||||
let n = 42;
|
||||
match n {
|
||||
0..=9 => 0,
|
||||
10..=19 => 1,
|
||||
20..=29 => 2,
|
||||
30..=39 => 3,
|
||||
40..=42 => 4,
|
||||
_ => 5,
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(ret(), 1);
|
||||
assert_eq!(neg(), -1);
|
||||
assert_eq!(add(), 3);
|
||||
assert_eq!(indirect_add(), 3);
|
||||
assert_eq!(arith(), 5 * 5);
|
||||
assert_eq!(match_int(), 20);
|
||||
assert_eq!(match_int_range(), 4);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
basic();
|
||||
|
||||
// This tests that we do (not) do sign extension properly when loading integers
|
||||
assert_eq!(u32::MAX as i64, 4294967295);
|
||||
assert_eq!(i32::MIN as i64, -2147483648);
|
||||
|
|
@ -152,6 +209,10 @@ pub fn main() {
|
|||
|
||||
assert_eq!(5i32.overflowing_mul(2), (10, false));
|
||||
assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));
|
||||
assert_eq!(i64::MIN.overflowing_mul(-1), (i64::MIN, true));
|
||||
assert_eq!(i32::MIN.overflowing_mul(-1), (i32::MIN, true));
|
||||
assert_eq!(i16::MIN.overflowing_mul(-1), (i16::MIN, true));
|
||||
assert_eq!(i8::MIN.overflowing_mul(-1), (i8::MIN, true));
|
||||
|
||||
assert_eq!(5i32.overflowing_div(2), (2, false));
|
||||
assert_eq!(i32::MIN.overflowing_div(-1), (i32::MIN, true));
|
||||
|
|
|
|||
|
|
@ -1,58 +0,0 @@
|
|||
fn ret() -> i64 {
|
||||
1
|
||||
}
|
||||
|
||||
fn neg() -> i64 {
|
||||
-1
|
||||
}
|
||||
|
||||
fn add() -> i64 {
|
||||
1 + 2
|
||||
}
|
||||
|
||||
fn indirect_add() -> i64 {
|
||||
let x = 1;
|
||||
let y = 2;
|
||||
x + y
|
||||
}
|
||||
|
||||
fn arith() -> i32 {
|
||||
3 * 3 + 4 * 4
|
||||
}
|
||||
|
||||
fn match_int() -> i16 {
|
||||
let n = 2;
|
||||
match n {
|
||||
0 => 0,
|
||||
1 => 10,
|
||||
2 => 20,
|
||||
3 => 30,
|
||||
_ => 100,
|
||||
}
|
||||
}
|
||||
|
||||
fn match_int_range() -> i64 {
|
||||
let n = 42;
|
||||
match n {
|
||||
0..=9 => 0,
|
||||
10..=19 => 1,
|
||||
20..=29 => 2,
|
||||
30..=39 => 3,
|
||||
40..=42 => 4,
|
||||
_ => 5,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(ret(), 1);
|
||||
assert_eq!(neg(), -1);
|
||||
assert_eq!(add(), 3);
|
||||
assert_eq!(indirect_add(), 3);
|
||||
assert_eq!(arith(), 5 * 5);
|
||||
assert_eq!(match_int(), 20);
|
||||
assert_eq!(match_int_range(), 4);
|
||||
assert_eq!(i64::MIN.overflowing_mul(-1), (i64::MIN, true));
|
||||
assert_eq!(i32::MIN.overflowing_mul(-1), (i32::MIN, true));
|
||||
assert_eq!(i16::MIN.overflowing_mul(-1), (i16::MIN, true));
|
||||
assert_eq!(i8::MIN.overflowing_mul(-1), (i8::MIN, true));
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#![feature(core_intrinsics)]
|
||||
|
||||
use std::intrinsics::{
|
||||
fadd_algebraic, fdiv_algebraic, fmul_algebraic, frem_algebraic, fsub_algebraic,
|
||||
};
|
||||
|
||||
#[inline(never)]
|
||||
pub fn test_operations_f64(a: f64, b: f64) {
|
||||
// make sure they all map to the correct operation
|
||||
assert_eq!(fadd_algebraic(a, b), a + b);
|
||||
assert_eq!(fsub_algebraic(a, b), a - b);
|
||||
assert_eq!(fmul_algebraic(a, b), a * b);
|
||||
assert_eq!(fdiv_algebraic(a, b), a / b);
|
||||
assert_eq!(frem_algebraic(a, b), a % b);
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn test_operations_f32(a: f32, b: f32) {
|
||||
// make sure they all map to the correct operation
|
||||
assert_eq!(fadd_algebraic(a, b), a + b);
|
||||
assert_eq!(fsub_algebraic(a, b), a - b);
|
||||
assert_eq!(fmul_algebraic(a, b), a * b);
|
||||
assert_eq!(fdiv_algebraic(a, b), a / b);
|
||||
assert_eq!(frem_algebraic(a, b), a % b);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_operations_f64(1., 2.);
|
||||
test_operations_f64(10., 5.);
|
||||
test_operations_f32(11., 2.);
|
||||
test_operations_f32(10., 15.);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue