diff --git a/packages/orion-numbers/.tool-versions b/packages/orion-numbers/.tool-versions index 8f7adfd7b..9bf9e4e8d 100644 --- a/packages/orion-numbers/.tool-versions +++ b/packages/orion-numbers/.tool-versions @@ -1 +1 @@ -scarb 2.6.5 \ No newline at end of file +scarb 2.7.0-rc.3 \ No newline at end of file diff --git a/packages/orion-numbers/Scarb.toml b/packages/orion-numbers/Scarb.toml index a0b87ffba..e6760cea0 100644 --- a/packages/orion-numbers/Scarb.toml +++ b/packages/orion-numbers/Scarb.toml @@ -7,8 +7,8 @@ edition = "2023_11" [dependencies] -[scripts] -test = "scarb cairo-test -f test" +[dev-dependencies] +cairo_test = "2.7.0-rc.3" [cairo] enable-gas=false \ No newline at end of file diff --git a/packages/orion-numbers/src/core_trait.cairo b/packages/orion-numbers/src/core_trait.cairo index fde940c8f..5c29a8a17 100644 --- a/packages/orion-numbers/src/core_trait.cairo +++ b/packages/orion-numbers/src/core_trait.cairo @@ -1,118 +1,3 @@ -// Basic Arithmetic Trait on integer 32, 64 and 128, should be included in Cairo core soon. - -pub impl I32Div of Div { - fn div(lhs: i32, rhs: i32) -> i32 { - assert(rhs != 0, 'divisor cannot be 0'); - - let mut lhs_positive = lhs; - let mut rhs_positive = rhs; - - if lhs < 0 { - lhs_positive = lhs * -1; - } - if rhs < 0 { - rhs_positive = rhs * -1; - } - - let lhs_u32: u32 = lhs_positive.try_into().unwrap(); - let rhs_u32: u32 = rhs_positive.try_into().unwrap(); - - let mut result = lhs_u32 / rhs_u32; - let felt_result: felt252 = result.into(); - let signed_int_result: i32 = felt_result.try_into().unwrap(); - - // avoids mul overflow for f16x16 - if sign_i32(lhs) * rhs < 0 { - signed_int_result * -1 - } else { - signed_int_result - } - } -} - -pub impl I32Rem of Rem { - fn rem(lhs: i32, rhs: i32) -> i32 { - let div = Div::div(lhs, rhs); - lhs - rhs * div - } -} - - -pub impl I64Div of Div { - fn div(lhs: i64, rhs: i64) -> i64 { - assert(rhs != 0, 'divisor cannot be 0'); - - let mut lhs_positive = lhs; - let mut rhs_positive = rhs; - - if lhs < 0 { - lhs_positive = lhs * -1; - } - if rhs < 0 { - rhs_positive = rhs * -1; - } - - let lhs_u64: u64 = lhs_positive.try_into().unwrap(); - let rhs_u64: u64 = rhs_positive.try_into().unwrap(); - - let mut result = lhs_u64 / rhs_u64; - let felt_result: felt252 = result.into(); - let signed_int_result: i64 = felt_result.try_into().unwrap(); - - // avoids mul overflow for f16x16 - if sign_i64(lhs) * rhs < 0 { - signed_int_result * -1 - } else { - signed_int_result - } - } -} - -pub impl I64Rem of Rem { - fn rem(lhs: i64, rhs: i64) -> i64 { - let div = Div::div(lhs, rhs); - lhs - rhs * div - } -} - -pub impl I128Div of Div { - fn div(lhs: i128, rhs: i128) -> i128 { - assert(rhs != 0, 'divisor cannot be 0'); - - let mut lhs_positive = lhs; - let mut rhs_positive = rhs; - - if lhs < 0 { - lhs_positive = lhs * -1; - } - if rhs < 0 { - rhs_positive = rhs * -1; - } - - let lhs_u128: u128 = lhs_positive.try_into().unwrap(); - let rhs_u128: u128 = rhs_positive.try_into().unwrap(); - - let mut result = lhs_u128 / rhs_u128; - let felt_result: felt252 = result.into(); - let signed_int_result: i128 = felt_result.try_into().unwrap(); - - // avoids mul overflow for f16x16 - if sign_i128(lhs) * rhs < 0 { - signed_int_result * -1 - } else { - signed_int_result - } - } -} - -pub impl I128Rem of Rem { - fn rem(lhs: i128, rhs: i128) -> i128 { - let div = Div::div(lhs, rhs); - lhs - rhs * div - } -} - - pub fn sign_i128(a: i128) -> i128 { if a == 0 { 0 diff --git a/packages/orion-numbers/src/f16x16/erf.cairo b/packages/orion-numbers/src/f16x16/erf.cairo index 07c43d32e..b7a3081e6 100644 --- a/packages/orion-numbers/src/f16x16/erf.cairo +++ b/packages/orion-numbers/src/f16x16/erf.cairo @@ -35,7 +35,6 @@ mod tests { use super::{erf, f16x16}; #[test] - #[available_gas(1000000000)] fn test_erf() { // 1.0 let f1 = 65536; diff --git a/packages/orion-numbers/src/f16x16/helpers.cairo b/packages/orion-numbers/src/f16x16/helpers.cairo index ada4e617b..1fd6c02f8 100644 --- a/packages/orion-numbers/src/f16x16/helpers.cairo +++ b/packages/orion-numbers/src/f16x16/helpers.cairo @@ -1,5 +1,4 @@ use orion_numbers::f16x16::core::{F16x16Impl, f16x16, ONE, HALF}; -use orion_numbers::core_trait::I32Div; const DEFAULT_PRECISION: i32 = 7; // 1e-4 diff --git a/packages/orion-numbers/src/f16x16/lut.cairo b/packages/orion-numbers/src/f16x16/lut.cairo index 696ca91a7..73cbe732d 100644 --- a/packages/orion-numbers/src/f16x16/lut.cairo +++ b/packages/orion-numbers/src/f16x16/lut.cairo @@ -1,7 +1,5 @@ use orion_numbers::f16x16::core::ONE; -use orion_numbers::core_trait::I32Div; - // Calculates the most significant bit pub fn msb(whole: i32) -> (i32, i32) { if whole < 256 { diff --git a/packages/orion-numbers/src/f16x16/math.cairo b/packages/orion-numbers/src/f16x16/math.cairo index 2d2273b2c..31e152ec2 100644 --- a/packages/orion-numbers/src/f16x16/math.cairo +++ b/packages/orion-numbers/src/f16x16/math.cairo @@ -1,9 +1,9 @@ +use core::option::OptionTrait; +use core::traits::TryInto; use core::integer; +use core::num::traits::{WideMul, Sqrt}; use orion_numbers::f16x16::{core::{F16x16Impl, f16x16, ONE, HALF}, lut}; -use orion_numbers::core_trait::{I32Rem, I32Div, I64Div}; //I32TryIntoNonZero, I32DivRem - - pub fn abs(a: f16x16) -> f16x16 { if a >= 0 { a @@ -33,7 +33,7 @@ pub fn ceil(a: f16x16) -> f16x16 { } pub fn div(a: f16x16, b: f16x16) -> f16x16 { - let a_i64 = integer::i32_wide_mul(a, ONE); + let a_i64 = WideMul::wide_mul(a, ONE); let res_i64 = a_i64 / b.into(); // Re-apply sign @@ -141,7 +141,7 @@ pub fn log10(a: f16x16) -> f16x16 { } pub fn mul(a: f16x16, b: f16x16) -> f16x16 { - let prod_i64 = integer::i32_wide_mul(a, b); + let prod_i64 = WideMul::wide_mul(a, b); // Re-apply sign F16x16Impl::new((prod_i64 / ONE.into()).try_into().unwrap()) @@ -220,9 +220,11 @@ pub fn sign(a: f16x16) -> f16x16 { // x must be positive pub fn sqrt(a: f16x16) -> f16x16 { assert(a >= 0, 'must be positive'); - //let a: usize = a.try_into().unwrap(); - let root = integer::u64_sqrt(a.try_into().unwrap() * ONE.try_into().unwrap()); + let a: u64 = a.try_into().unwrap(); + let one: u64 = ONE.try_into().unwrap(); + + let root: u32 = Sqrt::sqrt(a * one); F16x16Impl::new(root.try_into().unwrap()) } @@ -230,7 +232,7 @@ pub fn sqrt(a: f16x16) -> f16x16 { // Tests // -// +// // -------------------------------------------------------------------------------------------------------------- #[cfg(test)] @@ -242,8 +244,6 @@ mod tests { ln, log2, log10, pow, round, sign }; - use orion_numbers::core_trait::{I32Rem, I32Div}; - #[test] fn test_into() { let a = F16x16Impl::new_unscaled(5); @@ -257,21 +257,18 @@ mod tests { } #[test] - #[available_gas(10000000)] fn test_exp() { let a = F16x16Impl::new_unscaled(2); assert_relative(exp(a), 484249, 'invalid exp of 2', Option::None(())); // 7.389056098793725 } #[test] - #[available_gas(400000)] fn test_exp2() { let a = F16x16Impl::new_unscaled(5); assert(exp2(a) == 2097152, 'invalid exp2 of 2'); } #[test] - #[available_gas(20000)] fn test_exp2_int() { assert(exp2_int(5).into() == 2097152, 'invalid exp2 of 2'); } @@ -283,7 +280,6 @@ mod tests { } #[test] - #[available_gas(1000000)] fn test_ln() { let mut a = F16x16Impl::new_unscaled(1); assert(ln(a) == 0, 'invalid ln of 1'); @@ -293,7 +289,6 @@ mod tests { } #[test] - #[available_gas(1000000)] fn test_log2() { let mut a = F16x16Impl::new_unscaled(32); assert(log2(a) == F16x16Impl::new_unscaled(5), 'invalid log2 32'); @@ -303,7 +298,6 @@ mod tests { } #[test] - #[available_gas(1000000)] fn test_log10() { let a = F16x16Impl::new_unscaled(100); assert_relative(log10(a), 2 * ONE.into(), 'invalid log10', Option::None(())); @@ -311,7 +305,6 @@ mod tests { #[test] - #[available_gas(600000)] fn test_pow() { let a = F16x16Impl::new_unscaled(3); let b = F16x16Impl::new_unscaled(4); @@ -319,7 +312,6 @@ mod tests { } #[test] - #[available_gas(900000)] fn test_pow_frac() { let a = F16x16Impl::new_unscaled(3); let b = F16x16Impl::new(32768); // 0.5 @@ -352,7 +344,6 @@ mod tests { } #[test] - #[available_gas(2000000)] fn test_sign() { let a = F16x16Impl::new(0); assert(a.sign() == 0, 'invalid sign (0)'); @@ -371,7 +362,6 @@ mod tests { } #[test] - #[available_gas(100000)] fn test_msb() { let a = F16x16Impl::new_unscaled(100); let (msb, div) = lut::msb(a / ONE); @@ -427,7 +417,6 @@ mod tests { } #[test] - #[available_gas(100000)] fn test_mul_pos() { let a = 190054; let b = 190054; diff --git a/packages/orion-numbers/src/f16x16/trig.cairo b/packages/orion-numbers/src/f16x16/trig.cairo index 97f551e6d..60606d59c 100644 --- a/packages/orion-numbers/src/f16x16/trig.cairo +++ b/packages/orion-numbers/src/f16x16/trig.cairo @@ -2,8 +2,6 @@ use core::integer; use orion_numbers::f16x16::{core::{f16x16, ONE, HALF, TWO}, lut}; use orion_numbers::FixedTrait; -use orion_numbers::core_trait::{I32Div, I32Rem}; - // CONSTANTS const TWO_PI: i32 = 411775; const PI: i32 = 205887; @@ -178,10 +176,7 @@ mod tests { sin_fast, tan_fast, acosh, asinh, atanh, cosh, sinh, tanh }; - use orion_numbers::core_trait::I32Div; - #[test] - #[available_gas(8000000)] fn test_acos_fast() { let error = Option::Some(84); // 1e-5 @@ -203,14 +198,12 @@ mod tests { #[test] #[should_panic] - #[available_gas(8000000)] fn test_acos_fail() { let a = FixedTrait::new(2 * ONE); acos_fast(a); } #[test] - #[available_gas(8000000)] fn test_atan_fast() { let error = Option::Some(84); // 1e-5 @@ -237,7 +230,6 @@ mod tests { } #[test] - #[available_gas(8000000)] fn test_asin() { let error = Option::Some(84); // 1e-5 @@ -261,14 +253,12 @@ mod tests { #[test] #[should_panic] - #[available_gas(8000000)] fn test_asin_fail() { let a = FixedTrait::new(2 * ONE); asin_fast(a); } #[test] - #[available_gas(8000000)] fn test_cos_fast() { let error = Option::Some(84); // 1e-5 @@ -289,7 +279,6 @@ mod tests { } #[test] - #[available_gas(8000000)] fn test_sin_fast() { let error = Option::Some(84); // 1e-5 @@ -313,7 +302,6 @@ mod tests { } #[test] - #[available_gas(8000000)] fn test_tan_fast() { let a = FixedTrait::new(HALF_PI / 2); assert_precise(tan_fast(a), ONE.into(), 'invalid quarter pi', Option::None(())); @@ -330,7 +318,6 @@ mod tests { } #[test] - #[available_gas(10000000)] fn test_acosh() { let a = FixedTrait::new(246559); // 3.5954653836066 assert_precise(acosh(a), 131072, 'invalid two', Option::None(())); @@ -343,7 +330,6 @@ mod tests { } #[test] - #[available_gas(10000000)] fn test_asinh() { let a = FixedTrait::new(237690); // 3.48973469357602 assert_precise(asinh(a), 131072, 'invalid two', Option::None(())); @@ -362,7 +348,6 @@ mod tests { } #[test] - #[available_gas(10000000)] fn test_atanh() { let a = FixedTrait::new(58982); // 0.9 assert_precise(atanh(a), 96483, 'invalid 0.9', Option::None(())); // 1.36892147623689 @@ -381,7 +366,6 @@ mod tests { } #[test] - #[available_gas(10000000)] fn test_cosh() { let a = FixedTrait::new(TWO); assert_precise(cosh(a), 246550, 'invalid two', Option::None(())); // 3.5954653836066 @@ -400,7 +384,6 @@ mod tests { } #[test] - #[available_gas(10000000)] fn test_sinh() { let a = FixedTrait::new(TWO); assert_precise(sinh(a), 237681, 'invalid two', Option::None(())); // 3.48973469357602 @@ -419,7 +402,6 @@ mod tests { } #[test] - #[available_gas(10000000)] fn test_tanh() { let a = FixedTrait::new(TWO); assert_precise(tanh(a), 63179, 'invalid two', Option::None(())); // 0.75314654693321 diff --git a/packages/orion-numbers/src/f32x32/helpers.cairo b/packages/orion-numbers/src/f32x32/helpers.cairo index 606af6efe..4ba229ef4 100644 --- a/packages/orion-numbers/src/f32x32/helpers.cairo +++ b/packages/orion-numbers/src/f32x32/helpers.cairo @@ -1,5 +1,4 @@ use orion_numbers::f32x32::core::{F32x32Impl, f32x32, ONE, HALF}; -use orion_numbers::core_trait::I64Div; const DEFAULT_PRECISION: i64 = 429497; // 1e-4 diff --git a/packages/orion-numbers/src/f32x32/math.cairo b/packages/orion-numbers/src/f32x32/math.cairo index 208736f60..2afb1d4df 100644 --- a/packages/orion-numbers/src/f32x32/math.cairo +++ b/packages/orion-numbers/src/f32x32/math.cairo @@ -1,7 +1,7 @@ use core::integer; +use core::num::traits::{WideMul, Sqrt}; use orion_numbers::f32x32::core::{F32x32Impl, f32x32, ONE, HALF}; -use orion_numbers::core_trait::{I64Div, I64Rem, I128Div}; pub fn abs(a: f32x32) -> f32x32 { @@ -13,7 +13,7 @@ pub fn abs(a: f32x32) -> f32x32 { } pub fn div(a: f32x32, b: f32x32) -> f32x32 { - let a_i128 = integer::i64_wide_mul(a, ONE); + let a_i128 = WideMul::wide_mul(a, ONE); let res_i128 = a_i128 / b.into(); // Re-apply sign @@ -21,7 +21,7 @@ pub fn div(a: f32x32, b: f32x32) -> f32x32 { } pub fn mul(a: f32x32, b: f32x32) -> f32x32 { - let prod_i128 = integer::i64_wide_mul(a, b); + let prod_i128 = WideMul::wide_mul(a, b); // Re-apply sign F32x32Impl::new((prod_i128 / ONE.into()).try_into().unwrap()) @@ -62,7 +62,6 @@ mod tests { #[test] - #[available_gas(2000000)] fn test_sign() { let a = F32x32Impl::new(0); assert(a.sign() == 0, 'invalid sign (0)');