From 9e358af292d1ca2658eaf1044d77d6fe21182409 Mon Sep 17 00:00:00 2001 From: Eric Ridge Date: Thu, 2 Feb 2023 13:13:09 -0500 Subject: [PATCH] Support all the Rust "math" operations for `Numeric` and `AnyNumeric` against primitives (#1029) --- pgx-examples/numeric/src/lib.rs | 16 +++ pgx/src/datum/numeric_support/ops.rs | 153 ++++++++++++++++++++++++++- 2 files changed, 168 insertions(+), 1 deletion(-) diff --git a/pgx-examples/numeric/src/lib.rs b/pgx-examples/numeric/src/lib.rs index f0c8ac46e..5ac21507f 100644 --- a/pgx-examples/numeric/src/lib.rs +++ b/pgx-examples/numeric/src/lib.rs @@ -28,6 +28,22 @@ fn math() -> Numeric<10, 3> { n %= 19; n += 99.42; + let mut n: AnyNumeric = n * 42; + n = n / 42; + n = n + 42; + n = n - 42; + n = n * 42.0f32; + n = n / 42.0f32; + n = n + 42.0f32; + n = n - 42.0f32; + n = n * 42.0f64; + n = n / 42.0f64; + n = n + 42.0f64; + n = n - 42.0f64; + + n = n / AnyNumeric::from(42); + n = n / Numeric::<1000, 33>::try_from(42).unwrap(); + n.rescale().unwrap() } diff --git a/pgx/src/datum/numeric_support/ops.rs b/pgx/src/datum/numeric_support/ops.rs index 264d6f498..d3838ae36 100644 --- a/pgx/src/datum/numeric_support/ops.rs +++ b/pgx/src/datum/numeric_support/ops.rs @@ -24,6 +24,16 @@ macro_rules! anynumeric_math_op { call_numeric_func(pg_sys::$pg_func, vec![self.as_datum(), rhs.as_datum()]) } } + + /// [`AnyNumeric`] on the left, [`Numeric`] on the right. Results in a new [`AnyNumeric`] + impl $opname for Numeric { + type Output = AnyNumeric; + + #[inline] + fn $trait_fnname(self, rhs: AnyNumeric) -> Self::Output { + call_numeric_func(pg_sys::$pg_func, vec![self.as_datum(), rhs.as_datum()]) + } + } }; } @@ -35,7 +45,7 @@ anynumeric_math_op!(Rem, rem, numeric_mod); macro_rules! numeric_math_op { ($opname:ident, $trait_fnname:ident, $pg_func:ident) => { - /// Doing this operation on two [`Numeric`] instances results in a new [`AnyNumeric`]. + /// Doing this operation on two [`Numeric`] instances results in a new [`AnyNumeric`]. impl $opname> for Numeric { @@ -46,6 +56,16 @@ macro_rules! numeric_math_op { call_numeric_func(pg_sys::$pg_func, vec![self.as_datum(), rhs.as_datum()]) } } + + /// [`Numeric`] on the left, [`AnyNumeric`] on the right. Results in a new [`AnyNumeric`] + impl $opname> for AnyNumeric { + type Output = AnyNumeric; + + #[inline] + fn $trait_fnname(self, rhs: Numeric) -> Self::Output { + call_numeric_func(pg_sys::$pg_func, vec![self.as_datum(), rhs.as_datum()]) + } + } }; } @@ -199,3 +219,134 @@ anynumeric_assign_op_from_float!(SubAssign, sub_assign, f64, -); anynumeric_assign_op_from_float!(MulAssign, mul_assign, f64, *); anynumeric_assign_op_from_float!(DivAssign, div_assign, f64, /); anynumeric_assign_op_from_float!(RemAssign, rem_assign, f64, %); + +macro_rules! primitive_math_op { + ($opname:ident, $primitive:ty, $trait_fnname:ident, $pg_func:ident) => { + /// [`AnyNumeric`] on the left, rust primitive on the right. Results in an [`AnyNumeric`] + impl $opname<$primitive> for AnyNumeric { + type Output = AnyNumeric; + + #[inline] + fn $trait_fnname(self, rhs: $primitive) -> Self::Output { + call_numeric_func( + pg_sys::$pg_func, + vec![self.as_datum(), AnyNumeric::try_from(rhs).unwrap().as_datum()], + ) + } + } + + /// Rust primitive on the left, [`AnyNumeric`] on the right. Results in an [`AnyNumeric`] + impl $opname for $primitive { + type Output = AnyNumeric; + + #[inline] + fn $trait_fnname(self, rhs: AnyNumeric) -> Self::Output { + call_numeric_func( + pg_sys::$pg_func, + vec![AnyNumeric::try_from(self).unwrap().as_datum(), rhs.as_datum()], + ) + } + } + + /// [`Numeric`] on the left, rust primitive on the right. Results in an [`AnyNumeric`] + impl $opname<$primitive> for Numeric { + type Output = AnyNumeric; + + #[inline] + fn $trait_fnname(self, rhs: $primitive) -> Self::Output { + call_numeric_func( + pg_sys::$pg_func, + vec![self.as_datum(), AnyNumeric::try_from(rhs).unwrap().as_datum()], + ) + } + } + + /// Rust primitive on the left, [`Numeric`] on the right. Results in an [`AnyNumeric`] + impl $opname> for $primitive { + type Output = AnyNumeric; + + #[inline] + fn $trait_fnname(self, rhs: Numeric) -> Self::Output { + call_numeric_func( + pg_sys::$pg_func, + vec![rhs.as_datum(), AnyNumeric::try_from(self).unwrap().as_datum()], + ) + } + } + }; +} + +primitive_math_op!(Add, u8, add, numeric_add); +primitive_math_op!(Add, u16, add, numeric_add); +primitive_math_op!(Add, u32, add, numeric_add); +primitive_math_op!(Add, u64, add, numeric_add); +primitive_math_op!(Add, u128, add, numeric_add); +primitive_math_op!(Add, usize, add, numeric_add); +primitive_math_op!(Add, i8, add, numeric_add); +primitive_math_op!(Add, i16, add, numeric_add); +primitive_math_op!(Add, i32, add, numeric_add); +primitive_math_op!(Add, i64, add, numeric_add); +primitive_math_op!(Add, i128, add, numeric_add); +primitive_math_op!(Add, isize, add, numeric_add); +primitive_math_op!(Add, f32, add, numeric_add); +primitive_math_op!(Add, f64, add, numeric_add); + +primitive_math_op!(Sub, u8, sub, numeric_sub); +primitive_math_op!(Sub, u16, sub, numeric_sub); +primitive_math_op!(Sub, u32, sub, numeric_sub); +primitive_math_op!(Sub, u64, sub, numeric_sub); +primitive_math_op!(Sub, u128, sub, numeric_sub); +primitive_math_op!(Sub, usize, sub, numeric_sub); +primitive_math_op!(Sub, i8, sub, numeric_sub); +primitive_math_op!(Sub, i16, sub, numeric_sub); +primitive_math_op!(Sub, i32, sub, numeric_sub); +primitive_math_op!(Sub, i64, sub, numeric_sub); +primitive_math_op!(Sub, i128, sub, numeric_sub); +primitive_math_op!(Sub, isize, sub, numeric_sub); +primitive_math_op!(Sub, f32, sub, numeric_sub); +primitive_math_op!(Sub, f64, sub, numeric_sub); + +primitive_math_op!(Mul, u8, mul, numeric_mul); +primitive_math_op!(Mul, u16, mul, numeric_mul); +primitive_math_op!(Mul, u32, mul, numeric_mul); +primitive_math_op!(Mul, u64, mul, numeric_mul); +primitive_math_op!(Mul, u128, mul, numeric_mul); +primitive_math_op!(Mul, usize, mul, numeric_mul); +primitive_math_op!(Mul, i8, mul, numeric_mul); +primitive_math_op!(Mul, i16, mul, numeric_mul); +primitive_math_op!(Mul, i32, mul, numeric_mul); +primitive_math_op!(Mul, i64, mul, numeric_mul); +primitive_math_op!(Mul, i128, mul, numeric_mul); +primitive_math_op!(Mul, isize, mul, numeric_mul); +primitive_math_op!(Mul, f32, mul, numeric_mul); +primitive_math_op!(Mul, f64, mul, numeric_mul); + +primitive_math_op!(Div, u8, div, numeric_div); +primitive_math_op!(Div, u16, div, numeric_div); +primitive_math_op!(Div, u32, div, numeric_div); +primitive_math_op!(Div, u64, div, numeric_div); +primitive_math_op!(Div, u128, div, numeric_div); +primitive_math_op!(Div, usize, div, numeric_div); +primitive_math_op!(Div, i8, div, numeric_div); +primitive_math_op!(Div, i16, div, numeric_div); +primitive_math_op!(Div, i32, div, numeric_div); +primitive_math_op!(Div, i64, div, numeric_div); +primitive_math_op!(Div, i128, div, numeric_div); +primitive_math_op!(Div, isize, div, numeric_div); +primitive_math_op!(Div, f32, div, numeric_div); +primitive_math_op!(Div, f64, div, numeric_div); + +primitive_math_op!(Rem, u8, rem, numeric_mod); +primitive_math_op!(Rem, u16, rem, numeric_mod); +primitive_math_op!(Rem, u32, rem, numeric_mod); +primitive_math_op!(Rem, u64, rem, numeric_mod); +primitive_math_op!(Rem, u128, rem, numeric_mod); +primitive_math_op!(Rem, usize, rem, numeric_mod); +primitive_math_op!(Rem, i8, rem, numeric_mod); +primitive_math_op!(Rem, i16, rem, numeric_mod); +primitive_math_op!(Rem, i32, rem, numeric_mod); +primitive_math_op!(Rem, i64, rem, numeric_mod); +primitive_math_op!(Rem, i128, rem, numeric_mod); +primitive_math_op!(Rem, isize, rem, numeric_mod); +primitive_math_op!(Rem, f32, rem, numeric_mod); +primitive_math_op!(Rem, f64, rem, numeric_mod);