From eea2f2327912c798d4fed2bdb4ae8880d8d7efbf Mon Sep 17 00:00:00 2001 From: lyken Date: Tue, 18 Jun 2024 16:57:21 +0800 Subject: [PATCH 1/7] core: reduce code duplication in codegen/builtin_fns --- nac3core/src/codegen/builtin_fns.rs | 1450 ++++----------------------- 1 file changed, 192 insertions(+), 1258 deletions(-) diff --git a/nac3core/src/codegen/builtin_fns.rs b/nac3core/src/codegen/builtin_fns.rs index 0e4b75f4..47a0649d 100644 --- a/nac3core/src/codegen/builtin_fns.rs +++ b/nac3core/src/codegen/builtin_fns.rs @@ -1044,1275 +1044,209 @@ pub fn call_numpy_maximum<'ctx, G: CodeGenerator + ?Sized>( }) } -/// Invokes the `abs` builtin function. +/// Helper function to create a builtin that takes in either an ndarray or a value and returns a value of the structure. +/// +/// * `(arg_ty, arg_val)`: The [`Type`] and llvm value of the input argument. +/// * `fn_name`: The name of the function, only used when throwing an error with [`unsupported_type`] +/// * `get_ret_elem_type`: A function that takes in the input element [`Type`], and returns the correct return [`Type`]. +/// Return a constant [`Type`] here if the return type does not depend on the input type. +/// * `on_elem`: The function to be called when the input argument is not an ndarray. +fn helper_call_numpy<'ctx, OnElemFn, RetElemFn, G: CodeGenerator + ?Sized>( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + (arg_ty, arg_val): (Type, BasicValueEnum<'ctx>), + fn_name: &str, + get_ret_elem_type: &RetElemFn, + on_elem: &OnElemFn, +) -> Result, String> +where + OnElemFn: Fn( + &mut G, + &mut CodeGenContext<'ctx, '_>, + Type, + BasicValueEnum<'ctx>, + ) -> Option>, + RetElemFn: Fn(&mut CodeGenContext<'ctx, '_>, Type) -> Type, +{ + let result = match arg_val { + BasicValueEnum::PointerValue(x) + if arg_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => + { + let llvm_usize = generator.get_size_type(ctx.ctx); + let (arg_elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, arg_ty); + let ret_elem_ty = get_ret_elem_type(ctx, arg_elem_ty); + + let ndarray = ndarray_elementwise_unaryop_impl( + generator, + ctx, + ret_elem_ty, + None, + NDArrayValue::from_ptr_val(x, llvm_usize, None), + |generator, ctx, elem_val| { + helper_call_numpy( + generator, + ctx, + (arg_elem_ty, elem_val), + fn_name, + get_ret_elem_type, + on_elem, + ) + }, + )?; + ndarray.as_base_value().into() + } + + _ => on_elem(generator, ctx, arg_ty, arg_val) + .unwrap_or_else(|| unsupported_type(ctx, fn_name, &[arg_ty])), + }; + + Ok(result) +} + pub fn call_abs<'ctx, G: CodeGenerator + ?Sized>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, - n: (Type, BasicValueEnum<'ctx>), + arg: (Type, BasicValueEnum<'ctx>), ) -> Result, String> { - const FN_NAME: &str = "abs"; - - let llvm_i1 = ctx.ctx.bool_type(); - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (n_ty, n) = n; - - Ok(match n { - BasicValueEnum::IntValue(n) => { - debug_assert!([ - ctx.primitives.bool, - ctx.primitives.int32, - ctx.primitives.uint32, - ctx.primitives.int64, - ctx.primitives.uint64, - ] - .iter() - .any(|ty| ctx.unifier.unioned(n_ty, *ty))); - - if [ctx.primitives.int32, ctx.primitives.int64] + let fn_name: &str = "abs"; + helper_call_numpy( + generator, + ctx, + arg, + fn_name, + &|_ctx, elem_ty| elem_ty, + &|_generator, ctx, val_ty, val| match val { + BasicValueEnum::IntValue(n) => Some({ + debug_assert!([ + ctx.primitives.bool, + ctx.primitives.int32, + ctx.primitives.uint32, + ctx.primitives.int64, + ctx.primitives.uint64, + ] .iter() - .any(|ty| ctx.unifier.unioned(n_ty, *ty)) - { - llvm_intrinsics::call_int_abs(ctx, n, llvm_i1.const_zero(), Some(FN_NAME)).into() - } else { - n.into() + .any(|ty| ctx.unifier.unioned(val_ty, *ty))); + + if [ctx.primitives.int32, ctx.primitives.int64] + .iter() + .any(|ty| ctx.unifier.unioned(val_ty, *ty)) + { + llvm_intrinsics::call_int_abs( + ctx, + n, + ctx.ctx.bool_type().const_zero(), + Some(fn_name), + ) + .into() + } else { + n.into() + } + }), + + BasicValueEnum::FloatValue(n) => Some({ + debug_assert!(ctx.unifier.unioned(val_ty, ctx.primitives.float)); + + llvm_intrinsics::call_float_fabs(ctx, n, Some(fn_name)).into() + }), + + _ => None, + }, + ) +} + +/// Helper macro. Used so we don't have to keep typing out the type signature of the function. +macro_rules! call_numpy { + ($name:ident, $fn_name:literal, $get_ret_elem_type:expr, $on_elem:expr) => { + pub fn $name<'ctx, G: CodeGenerator + ?Sized>( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + arg: (Type, BasicValueEnum<'ctx>), + ) -> Result, String> { + helper_call_numpy(generator, ctx, arg, $fn_name, &$get_ret_elem_type, &$on_elem) + } + }; +} + +/// Helper macro, only used by [`call_numpy_isnan`] and [`call_numpy_isinf`] +macro_rules! call_numpy_ret_bool { + ($name:ident, $fn_name:literal, $elem_call:expr) => { + call_numpy!($name, $fn_name, |ctx, _| ctx.primitives.bool, |generator, ctx, n_ty, val| { + match val { + BasicValueEnum::FloatValue(n) => { + debug_assert!(ctx.unifier.unioned(n_ty, ctx.primitives.float)); + + let ret = $elem_call(generator, ctx, n); + Some(generator.bool_to_i8(ctx, ret).into()) + } + _ => None, } - } - - BasicValueEnum::FloatValue(n) => { - debug_assert!(ctx.unifier.unioned(n_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_fabs(ctx, n, Some(FN_NAME)).into() - } - - BasicValueEnum::PointerValue(n) - if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(n, llvm_usize, None), - |generator, ctx, val| call_abs(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[n_ty]), - }) + }); + }; } -/// Invokes the `np_isnan` builtin function. -pub fn call_numpy_isnan<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_isnan"; +macro_rules! call_numpy_float { + ($name:ident, $fn_name:literal, $elem_call:expr) => { + call_numpy!( + $name, + $fn_name, + |ctx, _| ctx.primitives.float, + |_generator, ctx, val_ty, val| { + match val { + BasicValueEnum::FloatValue(n) => { + debug_assert!(ctx.unifier.unioned(val_ty, ctx.primitives.float)); - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - irrt::call_isnan(generator, ctx, x).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - ctx.primitives.bool, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| { - let val = call_numpy_isnan(generator, ctx, (elem_ty, val))?; - - Ok(generator.bool_to_i8(ctx, val.into_int_value()).into()) - }, - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) + Some($elem_call(ctx, n, Option::<&str>::None).into()) + } + _ => None, + } + } + ); + }; } -/// Invokes the `np_isinf` builtin function. -pub fn call_numpy_isinf<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_isinf"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - irrt::call_isinf(generator, ctx, x).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - ctx.primitives.bool, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| { - let val = call_numpy_isinf(generator, ctx, (elem_ty, val))?; - - Ok(generator.bool_to_i8(ctx, val.into_int_value()).into()) - }, - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_sin` builtin function. -pub fn call_numpy_sin<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_sin"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_sin(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_sin(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_cos` builtin function. -pub fn call_numpy_cos<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_cos"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_cos(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_cos(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_exp` builtin function. -pub fn call_numpy_exp<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_exp"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_exp(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_exp(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_exp2` builtin function. -pub fn call_numpy_exp2<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_exp2"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_exp2(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_exp2(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_log` builtin function. -pub fn call_numpy_log<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_log"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_log(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_log(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_log10` builtin function. -pub fn call_numpy_log10<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_log10"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_log10(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_log10(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_log2` builtin function. -pub fn call_numpy_log2<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_log2"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_log2(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_log2(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_fabs` builtin function. -pub fn call_numpy_fabs<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_fabs"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_fabs(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_fabs(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_sqrt` builtin function. -pub fn call_numpy_sqrt<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_sqrt"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_sqrt(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_sqrt(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_rint` builtin function. -pub fn call_numpy_rint<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_rint"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - llvm_intrinsics::call_float_roundeven(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_rint(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_tan` builtin function. -pub fn call_numpy_tan<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_tan"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_tan(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_tan(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_arcsin` builtin function. -pub fn call_numpy_arcsin<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_arcsin"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_asin(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_arcsin(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_arccos` builtin function. -pub fn call_numpy_arccos<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_arccos"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_acos(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_arccos(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_arctan` builtin function. -pub fn call_numpy_arctan<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_arctan"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_atan(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_arctan(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_sinh` builtin function. -pub fn call_numpy_sinh<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_sinh"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_sinh(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_sinh(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_cosh` builtin function. -pub fn call_numpy_cosh<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_cosh"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_cosh(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_cosh(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_tanh` builtin function. -pub fn call_numpy_tanh<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_tanh"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_tanh(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_tanh(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_arcsinh` builtin function. -pub fn call_numpy_arcsinh<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_arcsinh"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_asinh(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_arcsinh(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_arccosh` builtin function. -pub fn call_numpy_arccosh<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_arccosh"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_acosh(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_arccosh(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_arctanh` builtin function. -pub fn call_numpy_arctanh<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_arctanh"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_atanh(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_arctanh(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_expm1` builtin function. -pub fn call_numpy_expm1<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_expm1"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_expm1(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_expm1(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `np_cbrt` builtin function. -pub fn call_numpy_cbrt<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "np_cbrt"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_cbrt(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_numpy_cbrt(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `sp_spec_erf` builtin function. -pub fn call_scipy_special_erf<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - z: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "sp_spec_erf"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (z_ty, z) = z; - - Ok(match z { - BasicValueEnum::FloatValue(z) => { - debug_assert!(ctx.unifier.unioned(z_ty, ctx.primitives.float)); - - extern_fns::call_erf(ctx, z, None).into() - } - - BasicValueEnum::PointerValue(z) - if z_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, z_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(z, llvm_usize, None), - |generator, ctx, val| call_scipy_special_erf(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[z_ty]), - }) -} - -/// Invokes the `sp_spec_erfc` builtin function. -pub fn call_scipy_special_erfc<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "sp_spec_erfc"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_erfc(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_scipy_special_erfc(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `sp_spec_gamma` builtin function. -pub fn call_scipy_special_gamma<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - z: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "sp_spec_gamma"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (z_ty, z) = z; - - Ok(match z { - BasicValueEnum::FloatValue(z) => { - debug_assert!(ctx.unifier.unioned(z_ty, ctx.primitives.float)); - - irrt::call_gamma(ctx, z).into() - } - - BasicValueEnum::PointerValue(z) - if z_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, z_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(z, llvm_usize, None), - |generator, ctx, val| call_scipy_special_gamma(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[z_ty]), - }) -} - -/// Invokes the `sp_spec_gammaln` builtin function. -pub fn call_scipy_special_gammaln<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "sp_spec_gammaln"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - irrt::call_gammaln(ctx, x).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_scipy_special_gammaln(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `sp_spec_j0` builtin function. -pub fn call_scipy_special_j0<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "sp_spec_j0"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - irrt::call_j0(ctx, x).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_scipy_special_j0(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} - -/// Invokes the `sp_spec_j1` builtin function. -pub fn call_scipy_special_j1<'ctx, G: CodeGenerator + ?Sized>( - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - x: (Type, BasicValueEnum<'ctx>), -) -> Result, String> { - const FN_NAME: &str = "sp_spec_j1"; - - let llvm_usize = generator.get_size_type(ctx.ctx); - - let (x_ty, x) = x; - - Ok(match x { - BasicValueEnum::FloatValue(x) => { - debug_assert!(ctx.unifier.unioned(x_ty, ctx.primitives.float)); - - extern_fns::call_j1(ctx, x, None).into() - } - - BasicValueEnum::PointerValue(x) - if x_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => - { - let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, x_ty); - - let ndarray = ndarray_elementwise_unaryop_impl( - generator, - ctx, - elem_ty, - None, - NDArrayValue::from_ptr_val(x, llvm_usize, None), - |generator, ctx, val| call_scipy_special_j1(generator, ctx, (elem_ty, val)), - )?; - - ndarray.as_base_value().into() - } - - _ => unsupported_type(ctx, FN_NAME, &[x_ty]), - }) -} +call_numpy_ret_bool!(call_numpy_isnan, "np_isnan", irrt::call_isnan); +call_numpy_ret_bool!(call_numpy_isinf, "np_isinf", irrt::call_isinf); + +call_numpy_float!(call_numpy_sin, "np_sin", llvm_intrinsics::call_float_sin); +call_numpy_float!(call_numpy_cos, "np_cos", llvm_intrinsics::call_float_cos); +call_numpy_float!(call_numpy_tan, "np_tan", extern_fns::call_tan); + +call_numpy_float!(call_numpy_arcsin, "np_arcsin", extern_fns::call_asin); +call_numpy_float!(call_numpy_arccos, "np_arccos", extern_fns::call_acos); +call_numpy_float!(call_numpy_arctan, "np_arctan", extern_fns::call_atan); + +call_numpy_float!(call_numpy_sinh, "np_sinh", extern_fns::call_sinh); +call_numpy_float!(call_numpy_cosh, "np_cosh", extern_fns::call_cosh); +call_numpy_float!(call_numpy_tanh, "np_tanh", extern_fns::call_tanh); + +call_numpy_float!(call_numpy_arcsinh, "np_arcsinh", extern_fns::call_asinh); +call_numpy_float!(call_numpy_arccosh, "np_arccosh", extern_fns::call_acosh); +call_numpy_float!(call_numpy_arctanh, "np_arctanh", extern_fns::call_atanh); + +call_numpy_float!(call_numpy_exp, "np_exp", llvm_intrinsics::call_float_exp); +call_numpy_float!(call_numpy_exp2, "np_exp2", llvm_intrinsics::call_float_exp2); +call_numpy_float!(call_numpy_expm1, "np_expm1", extern_fns::call_expm1); + +call_numpy_float!(call_numpy_log, "np_log", llvm_intrinsics::call_float_log); +call_numpy_float!(call_numpy_log2, "np_log2", llvm_intrinsics::call_float_log2); +call_numpy_float!(call_numpy_log10, "np_log10", llvm_intrinsics::call_float_log10); + +call_numpy_float!(call_numpy_sqrt, "np_sqrt", llvm_intrinsics::call_float_sqrt); +call_numpy_float!(call_numpy_cbrt, "np_cbrt", extern_fns::call_cbrt); + +call_numpy_float!(call_numpy_fabs, "np_fabs", llvm_intrinsics::call_float_fabs); +call_numpy_float!(call_numpy_rint, "np_rint", llvm_intrinsics::call_float_roundeven); + +call_numpy_float!(call_scipy_special_erf, "sp_spec_erf", extern_fns::call_erf); +call_numpy_float!(call_scipy_special_erfc, "sp_spec_erfc", extern_fns::call_erfc); +call_numpy_float!(call_scipy_special_gamma, "sp_spec_gamma", |ctx, val, _| irrt::call_gamma( + ctx, val +)); +call_numpy_float!(call_scipy_special_gammaln, "sp_spec_gammaln", |ctx, val, _| irrt::call_gammaln( + ctx, val +)); +call_numpy_float!(call_scipy_special_j0, "sp_spec_j0", |ctx, val, _| irrt::call_j0(ctx, val)); +call_numpy_float!(call_scipy_special_j1, "sp_spec_j1", extern_fns::call_j1); /// Invokes the `np_arctan2` builtin function. pub fn call_numpy_arctan2<'ctx, G: CodeGenerator + ?Sized>( -- 2.47.0 From 86d1325261534be4ed5b1c47c89bd45b7cdf9b86 Mon Sep 17 00:00:00 2001 From: lyken Date: Tue, 18 Jun 2024 17:16:08 +0800 Subject: [PATCH 2/7] core: suppress clippy warnings on call_numpy!() --- nac3core/src/codegen/builtin_fns.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/nac3core/src/codegen/builtin_fns.rs b/nac3core/src/codegen/builtin_fns.rs index 47a0649d..d26e6654 100644 --- a/nac3core/src/codegen/builtin_fns.rs +++ b/nac3core/src/codegen/builtin_fns.rs @@ -1157,6 +1157,7 @@ pub fn call_abs<'ctx, G: CodeGenerator + ?Sized>( /// Helper macro. Used so we don't have to keep typing out the type signature of the function. macro_rules! call_numpy { ($name:ident, $fn_name:literal, $get_ret_elem_type:expr, $on_elem:expr) => { + #[allow(clippy::redundant_closure_call)] pub fn $name<'ctx, G: CodeGenerator + ?Sized>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, -- 2.47.0 From c20c9a2c5a47a79e6a140f55223edbc7bb2a54d5 Mon Sep 17 00:00:00 2001 From: lyken Date: Wed, 19 Jun 2024 09:47:57 +0800 Subject: [PATCH 3/7] core: minor doc refine for helper_call_numpy() --- nac3core/src/codegen/builtin_fns.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nac3core/src/codegen/builtin_fns.rs b/nac3core/src/codegen/builtin_fns.rs index d26e6654..a951dd7a 100644 --- a/nac3core/src/codegen/builtin_fns.rs +++ b/nac3core/src/codegen/builtin_fns.rs @@ -1050,7 +1050,8 @@ pub fn call_numpy_maximum<'ctx, G: CodeGenerator + ?Sized>( /// * `fn_name`: The name of the function, only used when throwing an error with [`unsupported_type`] /// * `get_ret_elem_type`: A function that takes in the input element [`Type`], and returns the correct return [`Type`]. /// Return a constant [`Type`] here if the return type does not depend on the input type. -/// * `on_elem`: The function to be called when the input argument is not an ndarray. +/// * `on_elem`: The function to be called when the input argument is not an ndarray. Returns [`Option::None`] +/// if the element type & value are faulty and should panic with [`unsupported_type`]. fn helper_call_numpy<'ctx, OnElemFn, RetElemFn, G: CodeGenerator + ?Sized>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, -- 2.47.0 From ef2502e7b420f65693fd937fa98b74bf7767b5fd Mon Sep 17 00:00:00 2001 From: lyken Date: Wed, 19 Jun 2024 16:08:09 +0800 Subject: [PATCH 4/7] core: more minor doc refine for helper_call_numpy() --- nac3core/src/codegen/builtin_fns.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nac3core/src/codegen/builtin_fns.rs b/nac3core/src/codegen/builtin_fns.rs index a951dd7a..a56da144 100644 --- a/nac3core/src/codegen/builtin_fns.rs +++ b/nac3core/src/codegen/builtin_fns.rs @@ -1044,7 +1044,8 @@ pub fn call_numpy_maximum<'ctx, G: CodeGenerator + ?Sized>( }) } -/// Helper function to create a builtin that takes in either an ndarray or a value and returns a value of the structure. +/// Helper function to create a builtin that takes in either an ndarray or a value and returns a value of the same structure. +/// (e.g, `float` to `float`, `float` to `int`, `ndarray` to `ndarray`, or even `ndarray` to `ndarray`). /// /// * `(arg_ty, arg_val)`: The [`Type`] and llvm value of the input argument. /// * `fn_name`: The name of the function, only used when throwing an error with [`unsupported_type`] -- 2.47.0 From 777077a72320d44c837971b3c435b4e44830d0b7 Mon Sep 17 00:00:00 2001 From: lyken Date: Thu, 20 Jun 2024 10:26:15 +0800 Subject: [PATCH 5/7] core: revise nac3core/codegen/builtin_fns.rs numpy macros --- nac3core/src/codegen/builtin_fns.rs | 298 +++++++++++++++++++++------- 1 file changed, 231 insertions(+), 67 deletions(-) diff --git a/nac3core/src/codegen/builtin_fns.rs b/nac3core/src/codegen/builtin_fns.rs index a56da144..7ab695c4 100644 --- a/nac3core/src/codegen/builtin_fns.rs +++ b/nac3core/src/codegen/builtin_fns.rs @@ -1044,25 +1044,25 @@ pub fn call_numpy_maximum<'ctx, G: CodeGenerator + ?Sized>( }) } -/// Helper function to create a builtin that takes in either an ndarray or a value and returns a value of the same structure. -/// (e.g, `float` to `float`, `float` to `int`, `ndarray` to `ndarray`, or even `ndarray` to `ndarray`). +/// Helper function to create a built-in elementwise unary numpy function that takes in either an ndarray or a scalar. /// /// * `(arg_ty, arg_val)`: The [`Type`] and llvm value of the input argument. /// * `fn_name`: The name of the function, only used when throwing an error with [`unsupported_type`] -/// * `get_ret_elem_type`: A function that takes in the input element [`Type`], and returns the correct return [`Type`]. +/// * `get_ret_elem_type`: A function that takes in the input scalar [`Type`], and returns the function's return scalar [`Type`]. /// Return a constant [`Type`] here if the return type does not depend on the input type. -/// * `on_elem`: The function to be called when the input argument is not an ndarray. Returns [`Option::None`] -/// if the element type & value are faulty and should panic with [`unsupported_type`]. -fn helper_call_numpy<'ctx, OnElemFn, RetElemFn, G: CodeGenerator + ?Sized>( +/// * `on_scalar`: The function that acts on the scalars of the input. Returns [`Option::None`] +/// if the scalar type & value are faulty and should panic with [`unsupported_type`]. +fn helper_call_numpy_unary_elementwise<'ctx, OnScalarFn, RetElemFn, G>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, (arg_ty, arg_val): (Type, BasicValueEnum<'ctx>), fn_name: &str, get_ret_elem_type: &RetElemFn, - on_elem: &OnElemFn, + on_scalar: &OnScalarFn, ) -> Result, String> where - OnElemFn: Fn( + G: CodeGenerator + ?Sized, + OnScalarFn: Fn( &mut G, &mut CodeGenContext<'ctx, '_>, Type, @@ -1085,20 +1085,20 @@ where None, NDArrayValue::from_ptr_val(x, llvm_usize, None), |generator, ctx, elem_val| { - helper_call_numpy( + helper_call_numpy_unary_elementwise( generator, ctx, (arg_elem_ty, elem_val), fn_name, get_ret_elem_type, - on_elem, + on_scalar, ) }, )?; ndarray.as_base_value().into() } - _ => on_elem(generator, ctx, arg_ty, arg_val) + _ => on_scalar(generator, ctx, arg_ty, arg_val) .unwrap_or_else(|| unsupported_type(ctx, fn_name, &[arg_ty])), }; @@ -1110,12 +1110,12 @@ pub fn call_abs<'ctx, G: CodeGenerator + ?Sized>( ctx: &mut CodeGenContext<'ctx, '_>, arg: (Type, BasicValueEnum<'ctx>), ) -> Result, String> { - let fn_name: &str = "abs"; - helper_call_numpy( + const FN_NAME: &str = "abs"; + helper_call_numpy_unary_elementwise( generator, ctx, arg, - fn_name, + FN_NAME, &|_ctx, elem_ty| elem_ty, &|_generator, ctx, val_ty, val| match val { BasicValueEnum::IntValue(n) => Some({ @@ -1137,7 +1137,7 @@ pub fn call_abs<'ctx, G: CodeGenerator + ?Sized>( ctx, n, ctx.ctx.bool_type().const_zero(), - Some(fn_name), + Some(FN_NAME), ) .into() } else { @@ -1148,7 +1148,7 @@ pub fn call_abs<'ctx, G: CodeGenerator + ?Sized>( BasicValueEnum::FloatValue(n) => Some({ debug_assert!(ctx.unifier.unioned(val_ty, ctx.primitives.float)); - llvm_intrinsics::call_float_fabs(ctx, n, Some(fn_name)).into() + llvm_intrinsics::call_float_fabs(ctx, n, Some(FN_NAME)).into() }), _ => None, @@ -1156,40 +1156,88 @@ pub fn call_abs<'ctx, G: CodeGenerator + ?Sized>( ) } -/// Helper macro. Used so we don't have to keep typing out the type signature of the function. -macro_rules! call_numpy { - ($name:ident, $fn_name:literal, $get_ret_elem_type:expr, $on_elem:expr) => { +/// Macro to conveniently generate numpy functions with [`helper_call_numpy_unary_elementwise`]. +/// +/// Arguments: +/// * `$name:ident`: The identifier of the rust function to be generated. +/// * `$fn_name:literal`: To be passed to the `fn_name` parameter of [`helper_call_numpy_unary_elementwise`] +/// * `$get_ret_elem_type:expr`: To be passed to the `get_ret_elem_type` parameter of [`helper_call_numpy_unary_elementwise`]. +/// But there is no need to make it a reference. +/// * `$on_scalar:expr`: To be passed to the `on_scalar` parameter of [`helper_call_numpy_unary_elementwise`]. +/// But there is no need to make it a reference. +macro_rules! create_helper_call_numpy_unary_elementwise { + ($name:ident, $fn_name:literal, $get_ret_elem_type:expr, $on_scalar:expr) => { #[allow(clippy::redundant_closure_call)] pub fn $name<'ctx, G: CodeGenerator + ?Sized>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, arg: (Type, BasicValueEnum<'ctx>), ) -> Result, String> { - helper_call_numpy(generator, ctx, arg, $fn_name, &$get_ret_elem_type, &$on_elem) + helper_call_numpy_unary_elementwise( + generator, + ctx, + arg, + $fn_name, + &$get_ret_elem_type, + &$on_scalar, + ) } }; } -/// Helper macro, only used by [`call_numpy_isnan`] and [`call_numpy_isinf`] -macro_rules! call_numpy_ret_bool { - ($name:ident, $fn_name:literal, $elem_call:expr) => { - call_numpy!($name, $fn_name, |ctx, _| ctx.primitives.bool, |generator, ctx, n_ty, val| { - match val { - BasicValueEnum::FloatValue(n) => { - debug_assert!(ctx.unifier.unioned(n_ty, ctx.primitives.float)); +/// A specialized version of [`create_helper_call_numpy_unary_elementwise`] to generate functions that takes in float and returns boolean (as an `i8`) elementwise. +/// +/// Arguments: +/// * `$name:ident`: The identifier of the rust function to be generated. +/// * `$fn_name:literal`: To be passed to the `fn_name` parameter of [`helper_call_numpy_unary_elementwise`]. +/// * `$on_scalar:expr`: The closure (see below for its type) that acts on float scalar values and returns +/// the boolean results of LLVM type `i1`. The returned `i1` value will be converted into an `i8`. +/// ```rust +/// // Type of `$on_scalar:expr` +/// fn on_scalar<'ctx, G: CodeGenerator + ?Sized>( +/// generator: &mut G, +/// ctx: &mut CodeGenContext<'ctx, '_>, +/// arg: FloatValue<'ctx> +/// ) -> IntValue<'ctx> // of LLVM type `i1` +/// ``` +macro_rules! create_helper_call_numpy_unary_elementwise_float_to_bool { + ($name:ident, $fn_name:literal, $on_scalar:expr) => { + create_helper_call_numpy_unary_elementwise!( + $name, + $fn_name, + |ctx, _| ctx.primitives.bool, + |generator, ctx, n_ty, val| { + match val { + BasicValueEnum::FloatValue(n) => { + debug_assert!(ctx.unifier.unioned(n_ty, ctx.primitives.float)); - let ret = $elem_call(generator, ctx, n); - Some(generator.bool_to_i8(ctx, ret).into()) + let ret = $on_scalar(generator, ctx, n); + Some(generator.bool_to_i8(ctx, ret).into()) + } + _ => None, } - _ => None, } - }); + ); }; } -macro_rules! call_numpy_float { +/// A specialized version of [`create_helper_call_numpy_unary_elementwise`] to generate functions that takes in float and returns float elementwise. +/// +/// Arguments: +/// * `$name:ident`: The identifier of the rust function to be generated. +/// * `$fn_name:literal`: To be passed to the `fn_name` parameter of [`helper_call_numpy_unary_elementwise`]. +/// * `$on_scalar:expr`: The closure (see below for its type) that acts on float scalar values and returns float results. +/// ```rust +/// // Type of `$on_scalar:expr` +/// fn on_scalar<'ctx, G: CodeGenerator + ?Sized>( +/// generator: &mut G, +/// ctx: &mut CodeGenContext<'ctx, '_>, +/// arg: FloatValue<'ctx> +/// ) -> FloatValue<'ctx> +/// ``` +macro_rules! create_helper_call_numpy_unary_elementwise_float_to_float { ($name:ident, $fn_name:literal, $elem_call:expr) => { - call_numpy!( + create_helper_call_numpy_unary_elementwise!( $name, $fn_name, |ctx, _| ctx.primitives.float, @@ -1207,49 +1255,165 @@ macro_rules! call_numpy_float { }; } -call_numpy_ret_bool!(call_numpy_isnan, "np_isnan", irrt::call_isnan); -call_numpy_ret_bool!(call_numpy_isinf, "np_isinf", irrt::call_isinf); +create_helper_call_numpy_unary_elementwise_float_to_bool!( + call_numpy_isnan, + "np_isnan", + irrt::call_isnan +); +create_helper_call_numpy_unary_elementwise_float_to_bool!( + call_numpy_isinf, + "np_isinf", + irrt::call_isinf +); -call_numpy_float!(call_numpy_sin, "np_sin", llvm_intrinsics::call_float_sin); -call_numpy_float!(call_numpy_cos, "np_cos", llvm_intrinsics::call_float_cos); -call_numpy_float!(call_numpy_tan, "np_tan", extern_fns::call_tan); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_sin, + "np_sin", + llvm_intrinsics::call_float_sin +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_cos, + "np_cos", + llvm_intrinsics::call_float_cos +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_tan, + "np_tan", + extern_fns::call_tan +); -call_numpy_float!(call_numpy_arcsin, "np_arcsin", extern_fns::call_asin); -call_numpy_float!(call_numpy_arccos, "np_arccos", extern_fns::call_acos); -call_numpy_float!(call_numpy_arctan, "np_arctan", extern_fns::call_atan); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_arcsin, + "np_arcsin", + extern_fns::call_asin +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_arccos, + "np_arccos", + extern_fns::call_acos +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_arctan, + "np_arctan", + extern_fns::call_atan +); -call_numpy_float!(call_numpy_sinh, "np_sinh", extern_fns::call_sinh); -call_numpy_float!(call_numpy_cosh, "np_cosh", extern_fns::call_cosh); -call_numpy_float!(call_numpy_tanh, "np_tanh", extern_fns::call_tanh); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_sinh, + "np_sinh", + extern_fns::call_sinh +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_cosh, + "np_cosh", + extern_fns::call_cosh +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_tanh, + "np_tanh", + extern_fns::call_tanh +); -call_numpy_float!(call_numpy_arcsinh, "np_arcsinh", extern_fns::call_asinh); -call_numpy_float!(call_numpy_arccosh, "np_arccosh", extern_fns::call_acosh); -call_numpy_float!(call_numpy_arctanh, "np_arctanh", extern_fns::call_atanh); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_arcsinh, + "np_arcsinh", + extern_fns::call_asinh +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_arccosh, + "np_arccosh", + extern_fns::call_acosh +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_arctanh, + "np_arctanh", + extern_fns::call_atanh +); -call_numpy_float!(call_numpy_exp, "np_exp", llvm_intrinsics::call_float_exp); -call_numpy_float!(call_numpy_exp2, "np_exp2", llvm_intrinsics::call_float_exp2); -call_numpy_float!(call_numpy_expm1, "np_expm1", extern_fns::call_expm1); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_exp, + "np_exp", + llvm_intrinsics::call_float_exp +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_exp2, + "np_exp2", + llvm_intrinsics::call_float_exp2 +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_expm1, + "np_expm1", + extern_fns::call_expm1 +); -call_numpy_float!(call_numpy_log, "np_log", llvm_intrinsics::call_float_log); -call_numpy_float!(call_numpy_log2, "np_log2", llvm_intrinsics::call_float_log2); -call_numpy_float!(call_numpy_log10, "np_log10", llvm_intrinsics::call_float_log10); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_log, + "np_log", + llvm_intrinsics::call_float_log +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_log2, + "np_log2", + llvm_intrinsics::call_float_log2 +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_log10, + "np_log10", + llvm_intrinsics::call_float_log10 +); -call_numpy_float!(call_numpy_sqrt, "np_sqrt", llvm_intrinsics::call_float_sqrt); -call_numpy_float!(call_numpy_cbrt, "np_cbrt", extern_fns::call_cbrt); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_sqrt, + "np_sqrt", + llvm_intrinsics::call_float_sqrt +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_cbrt, + "np_cbrt", + extern_fns::call_cbrt +); -call_numpy_float!(call_numpy_fabs, "np_fabs", llvm_intrinsics::call_float_fabs); -call_numpy_float!(call_numpy_rint, "np_rint", llvm_intrinsics::call_float_roundeven); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_fabs, + "np_fabs", + llvm_intrinsics::call_float_fabs +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_numpy_rint, + "np_rint", + llvm_intrinsics::call_float_roundeven +); -call_numpy_float!(call_scipy_special_erf, "sp_spec_erf", extern_fns::call_erf); -call_numpy_float!(call_scipy_special_erfc, "sp_spec_erfc", extern_fns::call_erfc); -call_numpy_float!(call_scipy_special_gamma, "sp_spec_gamma", |ctx, val, _| irrt::call_gamma( - ctx, val -)); -call_numpy_float!(call_scipy_special_gammaln, "sp_spec_gammaln", |ctx, val, _| irrt::call_gammaln( - ctx, val -)); -call_numpy_float!(call_scipy_special_j0, "sp_spec_j0", |ctx, val, _| irrt::call_j0(ctx, val)); -call_numpy_float!(call_scipy_special_j1, "sp_spec_j1", extern_fns::call_j1); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_scipy_special_erf, + "sp_spec_erf", + extern_fns::call_erf +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_scipy_special_erfc, + "sp_spec_erfc", + extern_fns::call_erfc +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_scipy_special_gamma, + "sp_spec_gamma", + |ctx, val, _| irrt::call_gamma(ctx, val) +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_scipy_special_gammaln, + "sp_spec_gammaln", + |ctx, val, _| irrt::call_gammaln(ctx, val) +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_scipy_special_j0, + "sp_spec_j0", + |ctx, val, _| irrt::call_j0(ctx, val) +); +create_helper_call_numpy_unary_elementwise_float_to_float!( + call_scipy_special_j1, + "sp_spec_j1", + extern_fns::call_j1 +); /// Invokes the `np_arctan2` builtin function. pub fn call_numpy_arctan2<'ctx, G: CodeGenerator + ?Sized>( -- 2.47.0 From 7987dca464ce1595f24d4d9d03b496dfff786535 Mon Sep 17 00:00:00 2001 From: lyken Date: Thu, 20 Jun 2024 11:46:01 +0800 Subject: [PATCH 6/7] core: restore call_abs() parameter name --- nac3core/src/codegen/builtin_fns.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nac3core/src/codegen/builtin_fns.rs b/nac3core/src/codegen/builtin_fns.rs index 7ab695c4..6d8e3488 100644 --- a/nac3core/src/codegen/builtin_fns.rs +++ b/nac3core/src/codegen/builtin_fns.rs @@ -1108,13 +1108,13 @@ where pub fn call_abs<'ctx, G: CodeGenerator + ?Sized>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, - arg: (Type, BasicValueEnum<'ctx>), + n: (Type, BasicValueEnum<'ctx>), ) -> Result, String> { const FN_NAME: &str = "abs"; helper_call_numpy_unary_elementwise( generator, ctx, - arg, + n, FN_NAME, &|_ctx, elem_ty| elem_ty, &|_generator, ctx, val_ty, val| match val { -- 2.47.0 From eceeee1c50867dc6d9a26b3c6e7efa6bba19c7ac Mon Sep 17 00:00:00 2001 From: lyken Date: Thu, 20 Jun 2024 11:47:05 +0800 Subject: [PATCH 7/7] core: add newline in comments --- nac3core/src/codegen/builtin_fns.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nac3core/src/codegen/builtin_fns.rs b/nac3core/src/codegen/builtin_fns.rs index 6d8e3488..77a39737 100644 --- a/nac3core/src/codegen/builtin_fns.rs +++ b/nac3core/src/codegen/builtin_fns.rs @@ -1192,6 +1192,7 @@ macro_rules! create_helper_call_numpy_unary_elementwise { /// * `$fn_name:literal`: To be passed to the `fn_name` parameter of [`helper_call_numpy_unary_elementwise`]. /// * `$on_scalar:expr`: The closure (see below for its type) that acts on float scalar values and returns /// the boolean results of LLVM type `i1`. The returned `i1` value will be converted into an `i8`. +/// /// ```rust /// // Type of `$on_scalar:expr` /// fn on_scalar<'ctx, G: CodeGenerator + ?Sized>( @@ -1227,6 +1228,7 @@ macro_rules! create_helper_call_numpy_unary_elementwise_float_to_bool { /// * `$name:ident`: The identifier of the rust function to be generated. /// * `$fn_name:literal`: To be passed to the `fn_name` parameter of [`helper_call_numpy_unary_elementwise`]. /// * `$on_scalar:expr`: The closure (see below for its type) that acts on float scalar values and returns float results. +/// /// ```rust /// // Type of `$on_scalar:expr` /// fn on_scalar<'ctx, G: CodeGenerator + ?Sized>( -- 2.47.0