diff --git a/rust/src/instructions/math/arithmetic/cos_func.rs b/rust/src/instructions/math/arithmetic/cos_func.rs index 8091b2fd..2f3abeb4 100644 --- a/rust/src/instructions/math/arithmetic/cos_func.rs +++ b/rust/src/instructions/math/arithmetic/cos_func.rs @@ -20,10 +20,8 @@ use crate::utils::{expected_type::expected_type, get_type_name::get_type_name}; #[inline(always)] pub fn cos_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result { if !matches!( - (&a, num_type), - (Value::Float16(_), PrimitiveTypes::Hlf) - | (Value::Float32(_), PrimitiveTypes::Flt) - | (Value::Float64(_), PrimitiveTypes::Dbl) + &a, + Value::Float16(_) | Value::Float32(_) | Value::Float64(_) ) { return Err(VMError::TypeMismatch { ip, @@ -68,6 +66,14 @@ mod tests { found: "String" }) )); + assert!(matches!( + cos_values(Value::Int32(1), PrimitiveTypes::Flt, 17), + Err(VMError::TypeMismatch { + ip: 17, + expected: "Float", + found: "Unknown" + }) + )); let mut stack = Stack::from_vec(vec![invalid]); let original = stack.clone(); assert!(matches!( @@ -81,22 +87,18 @@ mod tests { assert_eq!(stack, original); } #[test] - fn rejects_integer_and_mismatched_float_operands_without_mutating_stack() { - for (operand, found) in [ - (Value::Int32(1), "Unknown"), - (Value::Float64(1.0), "Double"), - ] { - assert!(matches!( - cos_values(operand.clone(), PrimitiveTypes::Flt, 19), - Err(VMError::TypeMismatch { ip: 19, expected: "Float", found: actual }) if actual == found - )); - let mut stack = Stack::from_vec(vec![operand]); - let original = stack.clone(); - assert!(matches!( - cos_func(&mut stack, PrimitiveTypes::Flt, 20), - Err(VMError::TypeMismatch { ip: 20, expected: "Float", found: actual }) if actual == found - )); - assert_eq!(stack, original); - } + fn accepts_cross_width_float_operands_and_returns_directive_type() { + assert!(matches!( + cos_values(Value::Float16(half::f16::ZERO), PrimitiveTypes::Flt, 19), + Ok(Value::Float32(1.0)) + )); + assert!(matches!( + cos_values(Value::Float64(0.0), PrimitiveTypes::Hlf, 20), + Ok(Value::Float16(value)) if value == half::f16::ONE + )); + assert!(matches!( + cos_values(Value::Float64(0.0), PrimitiveTypes::Flt, 21), + Ok(Value::Float32(1.0)) + )); } } diff --git a/rust/src/instructions/math/arithmetic/powf_func.rs b/rust/src/instructions/math/arithmetic/powf_func.rs index 1880c206..58475085 100644 --- a/rust/src/instructions/math/arithmetic/powf_func.rs +++ b/rust/src/instructions/math/arithmetic/powf_func.rs @@ -24,22 +24,20 @@ pub fn powf_values( num_type: PrimitiveTypes, ip: usize, ) -> Result { - let matches_directive = |value: &Value| { + let is_float = |value: &Value| { matches!( - (value, num_type), - (Value::Float16(_), PrimitiveTypes::Hlf) - | (Value::Float32(_), PrimitiveTypes::Flt) - | (Value::Float64(_), PrimitiveTypes::Dbl) + value, + Value::Float16(_) | Value::Float32(_) | Value::Float64(_) ) }; - if !matches_directive(&a) { + if !is_float(&a) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), found: get_type_name(a), }); } - if !matches_directive(&b) { + if !is_float(&b) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), @@ -81,6 +79,19 @@ mod tests { #[test] fn invalid_operands_report_type_mismatch_and_preserve_stack() { let invalid = Value::String("invalid".into()); + assert!(matches!( + powf_values( + Value::Int32(1), + Value::Float32(1.0), + PrimitiveTypes::Flt, + 16 + ), + Err(VMError::TypeMismatch { + ip: 16, + expected: "Float", + found: "Unknown" + }) + )); assert!(matches!( powf_values(invalid.clone(), Value::Int32(1), PrimitiveTypes::Flt, 17), Err(VMError::TypeMismatch { @@ -113,24 +124,46 @@ mod tests { }) )); assert_eq!(stack, original); + let mut stack = Stack::from_vec(vec![Value::Float32(1.0), Value::Int32(1)]); + let original = stack.clone(); + assert!(matches!( + powf_func(&mut stack, PrimitiveTypes::Flt, 20), + Err(VMError::TypeMismatch { + ip: 20, + expected: "Float", + found: "Unknown" + }) + )); + assert_eq!(stack, original); } #[test] - fn rejects_integer_and_mismatched_float_operands_without_mutating_stack() { - for (a, b, found) in [ - (Value::Int32(2), Value::Float32(3.0), "Unknown"), - (Value::Float32(2.0), Value::Float64(3.0), "Double"), - ] { - assert!(matches!( - powf_values(a.clone(), b.clone(), PrimitiveTypes::Flt, 20), - Err(VMError::TypeMismatch { ip: 20, expected: "Float", found: actual }) if actual == found - )); - let mut stack = Stack::from_vec(vec![a, b]); - let original = stack.clone(); - assert!(matches!( - powf_func(&mut stack, PrimitiveTypes::Flt, 21), - Err(VMError::TypeMismatch { ip: 21, expected: "Float", found: actual }) if actual == found - )); - assert_eq!(stack, original); - } + fn accepts_cross_width_float_operands_and_returns_directive_type() { + assert!(matches!( + powf_values( + Value::Float16(half::f16::from_f32(2.0)), + Value::Float64(3.0), + PrimitiveTypes::Flt, + 20 + ), + Ok(Value::Float32(8.0)) + )); + assert!(matches!( + powf_values( + Value::Float64(2.0), + Value::Float32(3.0), + PrimitiveTypes::Hlf, + 21 + ), + Ok(Value::Float16(value)) if value == half::f16::from_f32(8.0) + )); + assert!(matches!( + powf_values( + Value::Float16(half::f16::from_f32(2.0)), + Value::Float32(3.0), + PrimitiveTypes::Dbl, + 22 + ), + Ok(Value::Float64(8.0)) + )); } } diff --git a/rust/src/instructions/math/arithmetic/powi_func.rs b/rust/src/instructions/math/arithmetic/powi_func.rs index d812922d..36d7f8df 100644 --- a/rust/src/instructions/math/arithmetic/powi_func.rs +++ b/rust/src/instructions/math/arithmetic/powi_func.rs @@ -32,16 +32,12 @@ pub fn powi_values( ip: usize, ) -> Result { let valid_base = matches!( - (&a, num_type), - (Value::Float16(_), PrimitiveTypes::Hlf) - | (Value::Float32(_), PrimitiveTypes::Flt) - | (Value::Float64(_), PrimitiveTypes::Dbl) + &a, + Value::Float16(_) | Value::Float32(_) | Value::Float64(_) ); let valid_exponent = matches!( - (&b, num_type), - (Value::Int16(_), PrimitiveTypes::Hlf) - | (Value::Int32(_), PrimitiveTypes::Flt) - | (Value::Int64(_), PrimitiveTypes::Dbl) + &b, + Value::Int16(_) | Value::Int32(_) | Value::Int64(_) | Value::Int128(_) ); if !valid_base { return Err(VMError::TypeMismatch { @@ -92,6 +88,14 @@ mod tests { #[test] fn invalid_operands_report_type_mismatch_and_preserve_stack() { let invalid = Value::String("invalid".into()); + assert!(matches!( + powi_values(Value::Int32(1), Value::Int32(1), PrimitiveTypes::Flt, 16), + Err(VMError::TypeMismatch { + ip: 16, + expected: "Float32/Int32", + found: "Unknown" + }) + )); assert!(matches!( powi_values(invalid.clone(), Value::Int32(1), PrimitiveTypes::Flt, 17), Err(VMError::TypeMismatch { @@ -126,25 +130,48 @@ mod tests { assert_eq!(stack, original); } #[test] - fn rejects_mismatched_base_and_float_exponent_without_mutating_stack() { - for (a, b, found) in [ - (Value::Float64(2.0), Value::Int32(3), "Double"), - (Value::Float32(2.0), Value::Float32(3.0), "Float"), - ] { - assert!(matches!( - powi_values(a.clone(), b.clone(), PrimitiveTypes::Flt, 23), - Err(VMError::TypeMismatch { ip: 23, expected: "Float32/Int32", found: actual }) - if actual == found - )); - let mut stack = Stack::from_vec(vec![a, b]); - let original = stack.clone(); - assert!(matches!( - powi_func(&mut stack, PrimitiveTypes::Flt, 24), - Err(VMError::TypeMismatch { ip: 24, expected: "Float32/Int32", found: actual }) - if actual == found - )); - assert_eq!(stack, original); - } + fn accepts_cross_width_base_and_integer_family_exponent() { + assert!(matches!( + powi_values( + Value::Float16(half::f16::from_f32(2.0)), + Value::Int64(3), + PrimitiveTypes::Flt, + 23 + ), + Ok(Value::Float32(8.0)) + )); + assert!(matches!( + powi_values( + Value::Float64(2.0), + Value::Int128(3), + PrimitiveTypes::Hlf, + 24 + ), + Ok(Value::Float16(value)) if value == half::f16::from_f32(8.0) + )); + assert!(matches!( + powi_values( + Value::Float64(2.0), + Value::Int16(3), + PrimitiveTypes::Flt, + 25 + ), + Ok(Value::Float32(8.0)) + )); + } + #[test] + fn rejects_float_exponent_without_mutating_stack() { + let mut stack = Stack::from_vec(vec![Value::Float32(2.0), Value::Float32(3.0)]); + let original = stack.clone(); + assert!(matches!( + powi_func(&mut stack, PrimitiveTypes::Flt, 26), + Err(VMError::TypeMismatch { + ip: 26, + expected: "Float32/Int32", + found: "Float" + }) + )); + assert_eq!(stack, original); } #[test] fn invalid_operands_report_directive_specific_expected_types() { diff --git a/rust/src/instructions/math/arithmetic/sin_func.rs b/rust/src/instructions/math/arithmetic/sin_func.rs index ac760bc1..2bb6dd10 100644 --- a/rust/src/instructions/math/arithmetic/sin_func.rs +++ b/rust/src/instructions/math/arithmetic/sin_func.rs @@ -20,10 +20,8 @@ use crate::utils::{expected_type::expected_type, get_type_name::get_type_name}; #[inline(always)] pub fn sin_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result { if !matches!( - (&a, num_type), - (Value::Float16(_), PrimitiveTypes::Hlf) - | (Value::Float32(_), PrimitiveTypes::Flt) - | (Value::Float64(_), PrimitiveTypes::Dbl) + &a, + Value::Float16(_) | Value::Float32(_) | Value::Float64(_) ) { return Err(VMError::TypeMismatch { ip, @@ -68,6 +66,14 @@ mod tests { found: "String" }) )); + assert!(matches!( + sin_values(Value::Int32(1), PrimitiveTypes::Flt, 17), + Err(VMError::TypeMismatch { + ip: 17, + expected: "Float", + found: "Unknown" + }) + )); let mut stack = Stack::from_vec(vec![invalid]); let original = stack.clone(); assert!(matches!( @@ -81,22 +87,18 @@ mod tests { assert_eq!(stack, original); } #[test] - fn rejects_integer_and_mismatched_float_operands_without_mutating_stack() { - for (operand, found) in [ - (Value::Int32(1), "Unknown"), - (Value::Float64(1.0), "Double"), - ] { - assert!(matches!( - sin_values(operand.clone(), PrimitiveTypes::Flt, 19), - Err(VMError::TypeMismatch { ip: 19, expected: "Float", found: actual }) if actual == found - )); - let mut stack = Stack::from_vec(vec![operand]); - let original = stack.clone(); - assert!(matches!( - sin_func(&mut stack, PrimitiveTypes::Flt, 20), - Err(VMError::TypeMismatch { ip: 20, expected: "Float", found: actual }) if actual == found - )); - assert_eq!(stack, original); - } + fn accepts_cross_width_float_operands_and_returns_directive_type() { + assert!(matches!( + sin_values(Value::Float16(half::f16::ZERO), PrimitiveTypes::Flt, 19), + Ok(Value::Float32(0.0)) + )); + assert!(matches!( + sin_values(Value::Float64(0.0), PrimitiveTypes::Hlf, 20), + Ok(Value::Float16(value)) if value == half::f16::ZERO + )); + assert!(matches!( + sin_values(Value::Float64(0.0), PrimitiveTypes::Flt, 21), + Ok(Value::Float32(0.0)) + )); } } diff --git a/rust/src/instructions/math/arithmetic/tan_func.rs b/rust/src/instructions/math/arithmetic/tan_func.rs index cd711fe8..cadff25f 100644 --- a/rust/src/instructions/math/arithmetic/tan_func.rs +++ b/rust/src/instructions/math/arithmetic/tan_func.rs @@ -20,10 +20,8 @@ use crate::utils::{expected_type::expected_type, get_type_name::get_type_name}; #[inline(always)] pub fn tan_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result { if !matches!( - (&a, num_type), - (Value::Float16(_), PrimitiveTypes::Hlf) - | (Value::Float32(_), PrimitiveTypes::Flt) - | (Value::Float64(_), PrimitiveTypes::Dbl) + &a, + Value::Float16(_) | Value::Float32(_) | Value::Float64(_) ) { return Err(VMError::TypeMismatch { ip, @@ -68,6 +66,14 @@ mod tests { found: "String" }) )); + assert!(matches!( + tan_values(Value::Int32(1), PrimitiveTypes::Flt, 17), + Err(VMError::TypeMismatch { + ip: 17, + expected: "Float", + found: "Unknown" + }) + )); let mut stack = Stack::from_vec(vec![invalid]); let original = stack.clone(); assert!(matches!( @@ -81,22 +87,18 @@ mod tests { assert_eq!(stack, original); } #[test] - fn rejects_integer_and_mismatched_float_operands_without_mutating_stack() { - for (operand, found) in [ - (Value::Int32(1), "Unknown"), - (Value::Float64(1.0), "Double"), - ] { - assert!(matches!( - tan_values(operand.clone(), PrimitiveTypes::Flt, 19), - Err(VMError::TypeMismatch { ip: 19, expected: "Float", found: actual }) if actual == found - )); - let mut stack = Stack::from_vec(vec![operand]); - let original = stack.clone(); - assert!(matches!( - tan_func(&mut stack, PrimitiveTypes::Flt, 20), - Err(VMError::TypeMismatch { ip: 20, expected: "Float", found: actual }) if actual == found - )); - assert_eq!(stack, original); - } + fn accepts_cross_width_float_operands_and_returns_directive_type() { + assert!(matches!( + tan_values(Value::Float16(half::f16::ZERO), PrimitiveTypes::Flt, 19), + Ok(Value::Float32(0.0)) + )); + assert!(matches!( + tan_values(Value::Float64(0.0), PrimitiveTypes::Hlf, 20), + Ok(Value::Float16(value)) if value == half::f16::ZERO + )); + assert!(matches!( + tan_values(Value::Float64(0.0), PrimitiveTypes::Flt, 21), + Ok(Value::Float32(0.0)) + )); } }