From 84e2b52240857231bb35932c810aac308268ea11 Mon Sep 17 00:00:00 2001 From: Jeong Yunwon Date: Fri, 29 Apr 2022 10:47:59 +0900 Subject: [PATCH] Deref for ArgIntoFloat --- stdlib/src/array.rs | 4 +- stdlib/src/cmath.rs | 6 +-- stdlib/src/math.rs | 80 +++++++++++++++++++-------------------- stdlib/src/statistics.rs | 2 +- vm/src/cformat.rs | 26 ++++++------- vm/src/function/number.rs | 17 +++++++-- 6 files changed, 70 insertions(+), 65 deletions(-) diff --git a/stdlib/src/array.rs b/stdlib/src/array.rs index 7c5664459..0df23af7a 100644 --- a/stdlib/src/array.rs +++ b/stdlib/src/array.rs @@ -512,11 +512,11 @@ mod array { } fn f32_try_into_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - ArgIntoFloat::try_from_object(vm, obj).map(|x| x.to_f64() as f32) + ArgIntoFloat::try_from_object(vm, obj).map(|x| *x as f32) } fn f64_try_into_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - ArgIntoFloat::try_from_object(vm, obj).map(|x| x.to_f64()) + ArgIntoFloat::try_from_object(vm, obj).map(Into::into) } fn pyfloat_from_f32(value: f32) -> PyFloat { diff --git a/stdlib/src/cmath.rs b/stdlib/src/cmath.rs index 4c8d07e4c..b23eaf2ec 100644 --- a/stdlib/src/cmath.rs +++ b/stdlib/src/cmath.rs @@ -38,7 +38,7 @@ mod cmath { /// Convert from polar coordinates to rectangular coordinates. #[pyfunction] fn rect(r: ArgIntoFloat, phi: ArgIntoFloat) -> Complex64 { - Complex64::from_polar(r.to_f64(), phi.to_f64()) + Complex64::from_polar(*r, *phi) } /// Checks if the real or imaginary part of z is infinite. @@ -196,8 +196,8 @@ mod cmath { fn isclose(args: IsCloseArgs, vm: &VirtualMachine) -> PyResult { let a = args.a.to_complex(); let b = args.b.to_complex(); - let rel_tol = args.rel_tol.map_or(1e-09, |value| value.to_f64()); - let abs_tol = args.abs_tol.map_or(0.0, |value| value.to_f64()); + let rel_tol = args.rel_tol.map_or(1e-09, Into::into); + let abs_tol = args.abs_tol.map_or(0.0, Into::into); if rel_tol < 0.0 || abs_tol < 0.0 { return Err(vm.new_value_error("tolerances must be non-negative".to_owned())); diff --git a/stdlib/src/math.rs b/stdlib/src/math.rs index 5b3de8f7f..5816f1e25 100644 --- a/stdlib/src/math.rs +++ b/stdlib/src/math.rs @@ -21,7 +21,7 @@ mod math { // Helper macro: macro_rules! call_math_func { ( $fun:ident, $name:ident, $vm:ident ) => {{ - let value = $name.to_f64(); + let value = *$name; let result = value.$fun(); result_or_overflow(value, result, $vm) }}; @@ -46,17 +46,17 @@ mod math { #[pyfunction] fn isfinite(x: ArgIntoFloat) -> bool { - x.to_f64().is_finite() + x.is_finite() } #[pyfunction] fn isinf(x: ArgIntoFloat) -> bool { - x.to_f64().is_infinite() + x.is_infinite() } #[pyfunction] fn isnan(x: ArgIntoFloat) -> bool { - x.to_f64().is_nan() + x.is_nan() } #[derive(FromArgs)] @@ -73,10 +73,10 @@ mod math { #[pyfunction] fn isclose(args: IsCloseArgs, vm: &VirtualMachine) -> PyResult { - let a = args.a.to_f64(); - let b = args.b.to_f64(); - let rel_tol = args.rel_tol.map_or(1e-09, |value| value.to_f64()); - let abs_tol = args.abs_tol.map_or(0.0, |value| value.to_f64()); + let a = *args.a; + let b = *args.b; + let rel_tol = args.rel_tol.map_or(1e-09, |value| value.into()); + let abs_tol = args.abs_tol.map_or(0.0, |value| value.into()); if rel_tol < 0.0 || abs_tol < 0.0 { return Err(vm.new_value_error("tolerances must be non-negative".to_owned())); @@ -107,12 +107,10 @@ mod math { #[pyfunction] fn copysign(x: ArgIntoFloat, y: ArgIntoFloat) -> f64 { - let a = x.to_f64(); - let b = y.to_f64(); - if a.is_nan() || b.is_nan() { - a + if x.is_nan() || y.is_nan() { + x.into() } else { - a.copysign(b) + x.copysign(*y) } } @@ -129,7 +127,7 @@ mod math { #[pyfunction] fn log(x: ArgIntoFloat, base: OptionalArg, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); + let x = *x; base.map_or_else( || { if x.is_nan() || x > 0.0_f64 { @@ -138,13 +136,13 @@ mod math { Err(vm.new_value_error("math domain error".to_owned())) } }, - |base| Ok(x.log(base.to_f64())), + |base| Ok(x.log(*base)), ) } #[pyfunction] fn log1p(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); + let x = *x; if x.is_nan() || x > -1.0_f64 { Ok((x + 1.0_f64).ln()) } else { @@ -154,7 +152,7 @@ mod math { #[pyfunction] fn log2(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); + let x = *x; if x.is_nan() || x > 0.0_f64 { Ok(x.log2()) } else { @@ -164,7 +162,7 @@ mod math { #[pyfunction] fn log10(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); + let x = *x; if x.is_nan() || x > 0.0_f64 { Ok(x.log10()) } else { @@ -174,8 +172,8 @@ mod math { #[pyfunction] fn pow(x: ArgIntoFloat, y: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); - let y = y.to_f64(); + let x = *x; + let y = *y; if x < 0.0 && x.is_finite() && y.fract() != 0.0 && y.is_finite() { return Err(vm.new_value_error("math domain error".to_owned())); @@ -192,7 +190,7 @@ mod math { #[pyfunction] fn sqrt(value: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let value = value.to_f64(); + let value = *value; if value.is_sign_negative() { return Err(vm.new_value_error("math domain error".to_owned())); } @@ -213,7 +211,7 @@ mod math { // Trigonometric functions: #[pyfunction] fn acos(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); + let x = *x; if x.is_nan() || (-1.0_f64..=1.0_f64).contains(&x) { Ok(x.acos()) } else { @@ -223,7 +221,7 @@ mod math { #[pyfunction] fn asin(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); + let x = *x; if x.is_nan() || (-1.0_f64..=1.0_f64).contains(&x) { Ok(x.asin()) } else { @@ -238,7 +236,7 @@ mod math { #[pyfunction] fn atan2(y: ArgIntoFloat, x: ArgIntoFloat) -> f64 { - y.to_f64().atan2(x.to_f64()) + y.atan2(*x) } #[pyfunction] @@ -337,19 +335,19 @@ mod math { #[pyfunction] fn degrees(x: ArgIntoFloat) -> f64 { - x.to_f64() * (180.0 / std::f64::consts::PI) + *x * (180.0 / std::f64::consts::PI) } #[pyfunction] fn radians(x: ArgIntoFloat) -> f64 { - x.to_f64() * (std::f64::consts::PI / 180.0) + *x * (std::f64::consts::PI / 180.0) } // Hyperbolic functions: #[pyfunction] fn acosh(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); + let x = *x; if x.is_sign_negative() || x.is_zero() { Err(vm.new_value_error("math domain error".to_owned())) } else { @@ -364,7 +362,7 @@ mod math { #[pyfunction] fn atanh(x: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); + let x = *x; if x >= 1.0_f64 || x <= -1.0_f64 { Err(vm.new_value_error("math domain error".to_owned())) } else { @@ -390,7 +388,7 @@ mod math { // Special functions: #[pyfunction] fn erf(x: ArgIntoFloat) -> f64 { - let x = x.to_f64(); + let x = *x; if x.is_nan() { x } else { @@ -400,7 +398,7 @@ mod math { #[pyfunction] fn erfc(x: ArgIntoFloat) -> f64 { - let x = x.to_f64(); + let x = *x; if x.is_nan() { x } else { @@ -410,7 +408,7 @@ mod math { #[pyfunction] fn gamma(x: ArgIntoFloat) -> f64 { - let x = x.to_f64(); + let x = *x; if x.is_finite() { puruspe::gamma(x) } else if x.is_nan() || x.is_sign_positive() { @@ -422,7 +420,7 @@ mod math { #[pyfunction] fn lgamma(x: ArgIntoFloat) -> f64 { - let x = x.to_f64(); + let x = *x; if x.is_finite() { puruspe::ln_gamma(x) } else if x.is_nan() { @@ -474,7 +472,7 @@ mod math { #[pyfunction] fn frexp(x: ArgIntoFloat) -> (f64, i32) { - let value = x.to_f64(); + let value = *x; if value.is_finite() { let (m, exp) = float_ops::ufrexp(value); (m * value.signum(), exp) @@ -541,7 +539,7 @@ mod math { let mut inf_sum = 0.0; for obj in seq.iter(vm)? { - let mut x = obj?.to_f64(); + let mut x = *obj?; let xsave = x; let mut j = 0; @@ -726,7 +724,7 @@ mod math { #[pyfunction] fn modf(x: ArgIntoFloat) -> (f64, f64) { - let x = x.to_f64(); + let x = *x; if !x.is_finite() { if x.is_infinite() { return (0.0_f64.copysign(x), x); @@ -740,12 +738,12 @@ mod math { #[pyfunction] fn nextafter(x: ArgIntoFloat, y: ArgIntoFloat) -> f64 { - float_ops::nextafter(x.to_f64(), y.to_f64()) + float_ops::nextafter(*x, *y) } #[pyfunction] fn ulp(x: ArgIntoFloat) -> f64 { - float_ops::ulp(x.to_f64()) + float_ops::ulp(*x) } fn fmod(x: f64, y: f64) -> f64 { @@ -758,8 +756,8 @@ mod math { #[pyfunction(name = "fmod")] fn py_fmod(x: ArgIntoFloat, y: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); - let y = y.to_f64(); + let x = *x; + let y = *y; let r = fmod(x, y); @@ -772,8 +770,8 @@ mod math { #[pyfunction] fn remainder(x: ArgIntoFloat, y: ArgIntoFloat, vm: &VirtualMachine) -> PyResult { - let x = x.to_f64(); - let y = y.to_f64(); + let x = *x; + let y = *y; if x.is_finite() && y.is_finite() { if y == 0.0 { diff --git a/stdlib/src/statistics.rs b/stdlib/src/statistics.rs index e28ae0b92..356bfd66f 100644 --- a/stdlib/src/statistics.rs +++ b/stdlib/src/statistics.rs @@ -126,7 +126,7 @@ mod _statistics { sigma: ArgIntoFloat, vm: &VirtualMachine, ) -> PyResult { - normal_dist_inv_cdf(p.to_f64(), mu.to_f64(), sigma.to_f64()) + normal_dist_inv_cdf(*p, *mu, *sigma) .ok_or_else(|| vm.new_value_error("inv_cdf undefined for these parameters".to_owned())) } } diff --git a/vm/src/cformat.rs b/vm/src/cformat.rs index 736a99cb2..fd2486fed 100644 --- a/vm/src/cformat.rs +++ b/vm/src/cformat.rs @@ -447,18 +447,16 @@ impl CFormatSpec { }, CFormatType::Float(_) => { let type_name = obj.class().name().to_string(); - let value = ArgIntoFloat::try_from_object(vm, obj) - .map_err(|e| { - if e.fast_isinstance(&vm.ctx.exceptions.type_error) { - // formatfloat in bytesobject.c generates its own specific exception - // text in this case, mirror it here. - vm.new_type_error(format!("float argument required, not {}", type_name)) - } else { - e - } - })? - .to_f64(); - Ok(self.format_float(value).into_bytes()) + let value = ArgIntoFloat::try_from_object(vm, obj).map_err(|e| { + if e.fast_isinstance(&vm.ctx.exceptions.type_error) { + // formatfloat in bytesobject.c generates its own specific exception + // text in this case, mirror it here. + vm.new_type_error(format!("float argument required, not {}", type_name)) + } else { + e + } + })?; + Ok(self.format_float(value.into()).into_bytes()) } CFormatType::Character => { if let Some(i) = obj.payload::() { @@ -542,8 +540,8 @@ impl CFormatSpec { } }, CFormatType::Float(_) => { - let value = ArgIntoFloat::try_from_object(vm, obj)?.to_f64(); - Ok(self.format_float(value)) + let value = ArgIntoFloat::try_from_object(vm, obj)?; + Ok(self.format_float(value.into())) } CFormatType::Character => { if let Some(i) = obj.payload::() { diff --git a/vm/src/function/number.rs b/vm/src/function/number.rs index d282d03c3..8e2daf63a 100644 --- a/vm/src/function/number.rs +++ b/vm/src/function/number.rs @@ -57,10 +57,6 @@ pub struct ArgIntoFloat { } impl ArgIntoFloat { - pub fn to_f64(self) -> f64 { - self.value - } - pub fn vec_into_f64(v: Vec) -> Vec { // TODO: Vec::into_raw_parts once stabilized let mut v = std::mem::ManuallyDrop::new(v); @@ -70,6 +66,19 @@ impl ArgIntoFloat { } } +impl From for f64 { + fn from(arg: ArgIntoFloat) -> Self { + arg.value + } +} + +impl Deref for ArgIntoFloat { + type Target = f64; + fn deref(&self) -> &Self::Target { + &self.value + } +} + impl TryFromObject for ArgIntoFloat { // Equivalent to PyFloat_AsDouble. fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult {