Compare commits
5 Commits
7966535677
...
2e1d6ab644
Author | SHA1 | Date |
---|---|---|
|
2e1d6ab644 | |
|
8d85ca3ac1 | |
|
9d3d5be383 | |
|
df4f5fe9f3 | |
|
197ffbbe81 |
|
@ -137,4 +137,12 @@ int32_t __nac3_list_slice_assign_var_size(
|
||||||
return dest_arr_len - (dest_end - dest_ind) - 1;
|
return dest_arr_len - (dest_end - dest_ind) - 1;
|
||||||
}
|
}
|
||||||
return dest_arr_len;
|
return dest_arr_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t __nac3_isinf(double x) {
|
||||||
|
return __builtin_isinf(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t __nac3_isnan(double x) {
|
||||||
|
return __builtin_isnan(x);
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@ use inkwell::{
|
||||||
memory_buffer::MemoryBuffer,
|
memory_buffer::MemoryBuffer,
|
||||||
module::Module,
|
module::Module,
|
||||||
types::BasicTypeEnum,
|
types::BasicTypeEnum,
|
||||||
values::{IntValue, PointerValue},
|
values::{FloatValue, IntValue, PointerValue},
|
||||||
AddressSpace, IntPredicate,
|
AddressSpace, IntPredicate,
|
||||||
};
|
};
|
||||||
use nac3parser::ast::Expr;
|
use nac3parser::ast::Expr;
|
||||||
|
@ -432,3 +432,43 @@ pub fn list_slice_assignment<'ctx, 'a>(
|
||||||
ctx.builder.build_unconditional_branch(cont_bb);
|
ctx.builder.build_unconditional_branch(cont_bb);
|
||||||
ctx.builder.position_at_end(cont_bb);
|
ctx.builder.position_at_end(cont_bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates a call to `isinf` in IR. Returns an `i1` representing the result.
|
||||||
|
pub fn call_isinf<'ctx, 'a>(
|
||||||
|
generator: &mut dyn CodeGenerator,
|
||||||
|
ctx: &CodeGenContext<'ctx, 'a>,
|
||||||
|
v: FloatValue<'ctx>,
|
||||||
|
) -> IntValue<'ctx> {
|
||||||
|
let intrinsic_fn = ctx.module.get_function("__nac3_isinf").unwrap_or_else(|| {
|
||||||
|
let fn_type = ctx.ctx.i32_type().fn_type(&[ctx.ctx.f64_type().into()], false);
|
||||||
|
ctx.module.add_function("__nac3_isinf", fn_type, None)
|
||||||
|
});
|
||||||
|
|
||||||
|
let ret = ctx.builder
|
||||||
|
.build_call(intrinsic_fn, &[v.into()], "isinf")
|
||||||
|
.try_as_basic_value()
|
||||||
|
.unwrap_left()
|
||||||
|
.into_int_value();
|
||||||
|
|
||||||
|
generator.bool_to_i1(ctx, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates a call to `isnan` in IR. Returns an `i1` representing the result.
|
||||||
|
pub fn call_isnan<'ctx, 'a>(
|
||||||
|
generator: &mut dyn CodeGenerator,
|
||||||
|
ctx: &CodeGenContext<'ctx, 'a>,
|
||||||
|
v: FloatValue<'ctx>,
|
||||||
|
) -> IntValue<'ctx> {
|
||||||
|
let intrinsic_fn = ctx.module.get_function("__nac3_isnan").unwrap_or_else(|| {
|
||||||
|
let fn_type = ctx.ctx.i32_type().fn_type(&[ctx.ctx.f64_type().into()], false);
|
||||||
|
ctx.module.add_function("__nac3_isnan", fn_type, None)
|
||||||
|
});
|
||||||
|
|
||||||
|
let ret = ctx.builder
|
||||||
|
.build_call(intrinsic_fn, &[v.into()], "isnan")
|
||||||
|
.try_as_basic_value()
|
||||||
|
.unwrap_left()
|
||||||
|
.into_int_value();
|
||||||
|
|
||||||
|
generator.bool_to_i1(ctx, ret)
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{
|
codegen::{
|
||||||
expr::destructure_range, irrt::calculate_len_for_slice_range, stmt::exn_constructor,
|
expr::destructure_range,
|
||||||
|
irrt::{calculate_len_for_slice_range, call_isinf, call_isnan},
|
||||||
|
stmt::exn_constructor,
|
||||||
},
|
},
|
||||||
symbol_resolver::SymbolValue,
|
symbol_resolver::SymbolValue,
|
||||||
};
|
};
|
||||||
|
@ -917,70 +919,22 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||||
)))),
|
)))),
|
||||||
loc: None,
|
loc: None,
|
||||||
})),
|
})),
|
||||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
create_fn_by_intrinsic(
|
||||||
name: "floor".into(),
|
primitives,
|
||||||
simple_name: "floor".into(),
|
&var_map,
|
||||||
signature: primitives.1.add_ty(TypeEnum::TFunc(FunSignature {
|
"floor",
|
||||||
args: vec![FuncArg { name: "n".into(), ty: float, default_value: None }],
|
float,
|
||||||
ret: int32,
|
&[(float, "x")],
|
||||||
vars: Default::default(),
|
"llvm.floor.f64",
|
||||||
})),
|
),
|
||||||
var_id: Default::default(),
|
create_fn_by_intrinsic(
|
||||||
instance_to_symbol: Default::default(),
|
primitives,
|
||||||
instance_to_stmt: Default::default(),
|
&var_map,
|
||||||
resolver: None,
|
"ceil",
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
float,
|
||||||
|ctx, _, _, args, generator| {
|
&[(float, "x")],
|
||||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
|
"llvm.ceil.f64",
|
||||||
let floor_intrinsic =
|
),
|
||||||
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
|
|
||||||
let float = ctx.ctx.f64_type();
|
|
||||||
let fn_type = float.fn_type(&[float.into()], false);
|
|
||||||
ctx.module.add_function("llvm.floor.f64", fn_type, None)
|
|
||||||
});
|
|
||||||
let val = ctx
|
|
||||||
.builder
|
|
||||||
.build_call(floor_intrinsic, &[arg.into()], "floor")
|
|
||||||
.try_as_basic_value()
|
|
||||||
.left()
|
|
||||||
.unwrap();
|
|
||||||
Ok(val.into())
|
|
||||||
},
|
|
||||||
)))),
|
|
||||||
loc: None,
|
|
||||||
})),
|
|
||||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
|
||||||
name: "ceil".into(),
|
|
||||||
simple_name: "ceil".into(),
|
|
||||||
signature: primitives.1.add_ty(TypeEnum::TFunc(FunSignature {
|
|
||||||
args: vec![FuncArg { name: "n".into(), ty: float, default_value: None }],
|
|
||||||
ret: int32,
|
|
||||||
vars: Default::default(),
|
|
||||||
})),
|
|
||||||
var_id: Default::default(),
|
|
||||||
instance_to_symbol: Default::default(),
|
|
||||||
instance_to_stmt: Default::default(),
|
|
||||||
resolver: None,
|
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
|
||||||
|ctx, _, _, args, generator| {
|
|
||||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
|
|
||||||
let ceil_intrinsic =
|
|
||||||
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
|
|
||||||
let float = ctx.ctx.f64_type();
|
|
||||||
let fn_type = float.fn_type(&[float.into()], false);
|
|
||||||
ctx.module.add_function("llvm.ceil.f64", fn_type, None)
|
|
||||||
});
|
|
||||||
let val = ctx
|
|
||||||
.builder
|
|
||||||
.build_call(ceil_intrinsic, &[arg.into()], "ceil")
|
|
||||||
.try_as_basic_value()
|
|
||||||
.left()
|
|
||||||
.unwrap();
|
|
||||||
Ok(val.into())
|
|
||||||
},
|
|
||||||
)))),
|
|
||||||
loc: None,
|
|
||||||
})),
|
|
||||||
Arc::new(RwLock::new({
|
Arc::new(RwLock::new({
|
||||||
let list_var = primitives.1.get_fresh_var(Some("L".into()), None);
|
let list_var = primitives.1.get_fresh_var(Some("L".into()), None);
|
||||||
let list = primitives.1.add_ty(TypeEnum::TList { ty: list_var.0 });
|
let list = primitives.1.add_ty(TypeEnum::TList { ty: list_var.0 });
|
||||||
|
@ -1226,6 +1180,565 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||||
)))),
|
)))),
|
||||||
loc: None,
|
loc: None,
|
||||||
})),
|
})),
|
||||||
|
create_fn_by_codegen(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"isnan",
|
||||||
|
boolean,
|
||||||
|
&[(float, "x")],
|
||||||
|
Box::new(|ctx, _, fun, args, generator| {
|
||||||
|
let float = ctx.primitives.float;
|
||||||
|
|
||||||
|
let x_ty = fun.0.args[0].ty;
|
||||||
|
let x_val = args[0].1.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, x_ty)?;
|
||||||
|
|
||||||
|
assert!(ctx.unifier.unioned(x_ty, float));
|
||||||
|
|
||||||
|
let val = call_isnan(generator, ctx, x_val.into_float_value());
|
||||||
|
|
||||||
|
Ok(Some(val.into()))
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
create_fn_by_codegen(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"isinf",
|
||||||
|
boolean,
|
||||||
|
&[(float, "x")],
|
||||||
|
Box::new(|ctx, _, fun, args, generator| {
|
||||||
|
let float = ctx.primitives.float;
|
||||||
|
|
||||||
|
let x_ty = fun.0.args[0].ty;
|
||||||
|
let x_val = args[0].1.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, x_ty)?;
|
||||||
|
|
||||||
|
assert!(ctx.unifier.unioned(x_ty, float));
|
||||||
|
|
||||||
|
let val = call_isinf(generator, ctx, x_val.into_float_value());
|
||||||
|
|
||||||
|
Ok(Some(val.into()))
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"sin",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"llvm.sin.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"cos",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"llvm.cos.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"exp",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"llvm.exp.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"exp2",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"llvm.exp2.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"log",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"llvm.log.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"log10",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"llvm.log10.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"log2",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"llvm.log2.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"fabs",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"llvm.fabs.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"trunc",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"llvm.trunc.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"sqrt",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"llvm.sqrt.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_codegen(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"rint",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
Box::new(|ctx, _, fun, args, generator| {
|
||||||
|
let float = ctx.primitives.float;
|
||||||
|
let llvm_f64 = ctx.ctx.f64_type();
|
||||||
|
|
||||||
|
let x_ty = fun.0.args[0].ty;
|
||||||
|
let x_val = args[0].1.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, x_ty)?;
|
||||||
|
|
||||||
|
assert!(ctx.unifier.unioned(x_ty, float));
|
||||||
|
|
||||||
|
let intrinsic_fn = ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
|
||||||
|
let fn_type = llvm_f64.fn_type(&[llvm_f64.into()], false);
|
||||||
|
|
||||||
|
ctx.module.add_function("llvm.round.f64", fn_type, None)
|
||||||
|
});
|
||||||
|
|
||||||
|
// rint(x) == round(x * 0.5) * 2.0
|
||||||
|
|
||||||
|
// %0 = fmul f64 %x, 0.5
|
||||||
|
let x_half = ctx.builder
|
||||||
|
.build_float_mul(x_val.into_float_value(), llvm_f64.const_float(0.5), "");
|
||||||
|
// %1 = call f64 @llvm.round.f64(f64 %0)
|
||||||
|
let round = ctx.builder
|
||||||
|
.build_call(
|
||||||
|
intrinsic_fn,
|
||||||
|
&vec![x_half.into()],
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
.try_as_basic_value()
|
||||||
|
.left()
|
||||||
|
.unwrap();
|
||||||
|
// %2 = fmul f64 %1, 2.0
|
||||||
|
let val = ctx.builder
|
||||||
|
.build_float_mul(round.into_float_value(), llvm_f64.const_float(2.0).into(), "rint");
|
||||||
|
|
||||||
|
Ok(Some(val.into()))
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"tan",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"tan",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"arcsin",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"asin",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"arccos",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"acos",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"arctan",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"atan",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"sinh",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"sinh",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"cosh",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"cosh",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"tanh",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"tanh",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"arcsinh",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"asinh",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"arccosh",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"acosh",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"arctanh",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"atanh",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"expm1",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"expm1",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"cbrt",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"cbrt",
|
||||||
|
&["readnone", "willreturn"],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"erf",
|
||||||
|
float,
|
||||||
|
&[(float, "z")],
|
||||||
|
"erf",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"erfc",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"erfc",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_codegen(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"gamma",
|
||||||
|
float,
|
||||||
|
&[(float, "z")],
|
||||||
|
Box::new(|ctx, _, fun, args, generator| {
|
||||||
|
let float = ctx.primitives.float;
|
||||||
|
let llvm_f64 = ctx.ctx.f64_type();
|
||||||
|
|
||||||
|
let z_ty = fun.0.args[0].ty;
|
||||||
|
let z_val = args[0].1.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, z_ty)?;
|
||||||
|
|
||||||
|
assert!(ctx.unifier.unioned(z_ty, float));
|
||||||
|
|
||||||
|
let tgamma_fn = ctx.module.get_function("tgamma").unwrap_or_else(|| {
|
||||||
|
let fn_type = llvm_f64.fn_type(&[llvm_f64.into()], false);
|
||||||
|
let func = ctx.module.add_function("tgamma", fn_type, None);
|
||||||
|
func.add_attribute(
|
||||||
|
AttributeLoc::Function,
|
||||||
|
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id("nounwind"), 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
func
|
||||||
|
});
|
||||||
|
|
||||||
|
// %0 = call f64 @tgamma(f64 %z)
|
||||||
|
let call = ctx.builder
|
||||||
|
.build_call(tgamma_fn, &[z_val.into()], "gamma")
|
||||||
|
.try_as_basic_value()
|
||||||
|
.left()
|
||||||
|
.unwrap()
|
||||||
|
.into_float_value();
|
||||||
|
|
||||||
|
// Handling for denormals
|
||||||
|
// | x | Python gamma(x) | C tgamma(x) |
|
||||||
|
// --- | ----------------- | --------------- | ----------- |
|
||||||
|
// (1) | nan | nan | nan |
|
||||||
|
// (2) | -inf | -inf | inf |
|
||||||
|
// (3) | inf | inf | inf |
|
||||||
|
// (4) | 0.0 | inf | inf |
|
||||||
|
// (5) | {-1.0, -2.0, ...} | inf | nan |
|
||||||
|
//
|
||||||
|
// Therefore, we remap to Python's denorm handling by:
|
||||||
|
//
|
||||||
|
// let v = tgamma(x);
|
||||||
|
// v = if isinf(v) || isnan(v) { f64::INFINITY } else { v } // Handles (4)-(5)
|
||||||
|
// v = if isinf(x) || isnan(x) { x } else { v } // Handles (1)-(3)
|
||||||
|
|
||||||
|
// %v.isinf = call i32 @__nac3_isinf(f64 %0)
|
||||||
|
// %v.isinf.tobool = icmp ne i32 %v.isinf, 0
|
||||||
|
let v_isinf = call_isinf(generator, ctx, call.into());
|
||||||
|
// %v.isnan = call i32 @__nac3_isnan(f64 %0)
|
||||||
|
// %v.isnan.tobool = icmp ne i32 %v.isnan, 0
|
||||||
|
let v_isnan = call_isnan(generator, ctx, call.into());
|
||||||
|
|
||||||
|
// %or = or i1 %v.isinf.tobool, %v.isnan.tobool
|
||||||
|
// %3 = select i1 %or, f64 inf, f64 %0
|
||||||
|
let v_is_nonnum = ctx.builder.build_or(v_isinf, v_isnan, "");
|
||||||
|
let val = ctx.builder.build_select(
|
||||||
|
v_is_nonnum,
|
||||||
|
llvm_f64.const_float(f64::INFINITY).into(),
|
||||||
|
call,
|
||||||
|
"",
|
||||||
|
).into_float_value();
|
||||||
|
|
||||||
|
// %z.isinf = call i32 @__nac3_isinf(f64 %z)
|
||||||
|
// %z.isinf.tobool = icmp ne i32 %z.isinf, 0
|
||||||
|
let z_isinf = call_isinf(generator, ctx, z_val.into_float_value());
|
||||||
|
// %z.isnan = call i32 @__nac3_isnan(f64 %z)
|
||||||
|
// %z.isnan.tobool = icmp ne i32 %z.isnan, 0
|
||||||
|
let z_isnan = call_isnan(generator, ctx, z_val.into_float_value());
|
||||||
|
|
||||||
|
// %or = or i1 %z.isinf.tobool, %z.isnan.tobool
|
||||||
|
// %val = select i1 %or, f64 %z, f64 %3
|
||||||
|
let z_is_nonnum = ctx.builder.build_or(z_isinf, z_isnan, "");
|
||||||
|
let val = ctx.builder.build_select(
|
||||||
|
z_is_nonnum,
|
||||||
|
z_val.into_float_value(),
|
||||||
|
val,
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(val.into())
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
create_fn_by_codegen(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"gammaln",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
Box::new(|ctx, _, fun, args, generator| {
|
||||||
|
let float = ctx.primitives.float;
|
||||||
|
let llvm_f64 = ctx.ctx.f64_type();
|
||||||
|
|
||||||
|
let x_ty = fun.0.args[0].ty;
|
||||||
|
let x_val = args[0].1.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, x_ty)?;
|
||||||
|
|
||||||
|
assert!(ctx.unifier.unioned(x_ty, float));
|
||||||
|
|
||||||
|
let tgamma_fn = ctx.module.get_function("lgamma").unwrap_or_else(|| {
|
||||||
|
let fn_type = llvm_f64.fn_type(&[llvm_f64.into()], false);
|
||||||
|
let func = ctx.module.add_function("lgamma", fn_type, None);
|
||||||
|
func.add_attribute(
|
||||||
|
AttributeLoc::Function,
|
||||||
|
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id("nounwind"), 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
func
|
||||||
|
});
|
||||||
|
|
||||||
|
// %0 = call f64 @gamma(f64 %x)
|
||||||
|
let call = ctx.builder
|
||||||
|
.build_call(tgamma_fn, &[x_val.into()], "gammaln")
|
||||||
|
.try_as_basic_value()
|
||||||
|
.left()
|
||||||
|
.unwrap()
|
||||||
|
.into_float_value();
|
||||||
|
|
||||||
|
// libm's handling of value overflows differs from scipy:
|
||||||
|
// - scipy: gammaln(-inf) -> -inf
|
||||||
|
// - libm : lgamma(-inf) -> inf
|
||||||
|
//
|
||||||
|
// Therefore we remap it by:
|
||||||
|
//
|
||||||
|
// let v = lgamma(x);
|
||||||
|
// v = if isinf(x) { x } else { v }
|
||||||
|
|
||||||
|
// %isinf = call i32 @__nac3_isinf(f64 %x)
|
||||||
|
// %tobool = icmp ne i32 %isinf, 0
|
||||||
|
// %val = select i1 %tobool, f64 %x, f64 %0
|
||||||
|
let v = ctx.builder.build_select(
|
||||||
|
call_isinf(generator, ctx, x_val.into_float_value()),
|
||||||
|
x_val,
|
||||||
|
call.into(),
|
||||||
|
""
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(v.into())
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
create_fn_by_codegen(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"j0",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
Box::new(|ctx, _, fun, args, generator| {
|
||||||
|
let float = ctx.primitives.float;
|
||||||
|
let llvm_f64 = ctx.ctx.f64_type();
|
||||||
|
|
||||||
|
let x_ty = fun.0.args[0].ty;
|
||||||
|
let x_val = args[0].1.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, x_ty)?;
|
||||||
|
|
||||||
|
assert!(ctx.unifier.unioned(x_ty, float));
|
||||||
|
|
||||||
|
let tgamma_fn = ctx.module.get_function("j0").unwrap_or_else(|| {
|
||||||
|
let fn_type = llvm_f64.fn_type(&[llvm_f64.into()], false);
|
||||||
|
let func = ctx.module.add_function("j0", fn_type, None);
|
||||||
|
func.add_attribute(
|
||||||
|
AttributeLoc::Function,
|
||||||
|
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id("nounwind"), 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
func
|
||||||
|
});
|
||||||
|
|
||||||
|
// %0 = call f64 @j0(f64 %x)
|
||||||
|
let call = ctx.builder
|
||||||
|
.build_call(tgamma_fn, &[x_val.into()], "j0")
|
||||||
|
.try_as_basic_value()
|
||||||
|
.left()
|
||||||
|
.unwrap()
|
||||||
|
.into_float_value();
|
||||||
|
|
||||||
|
// libm's handling of value overflows differs from scipy:
|
||||||
|
// - scipy: j0(inf) -> nan
|
||||||
|
// - libm : j0(inf) -> 0.0
|
||||||
|
//
|
||||||
|
// Therefore we remap it by:
|
||||||
|
//
|
||||||
|
// let v = j0(x);
|
||||||
|
// v = if isinf(x) { f64::NAN } else { v }
|
||||||
|
|
||||||
|
// %1 = call i32 @__nac3_isinf(f64 %x)
|
||||||
|
// %tobool = icmp ne i32 %isinf, 0
|
||||||
|
let arg_isinf = call_isinf(generator, ctx, x_val.into_float_value());
|
||||||
|
|
||||||
|
// %val = select i1 %tobool, f64 nan, f64 %0
|
||||||
|
let val = ctx.builder
|
||||||
|
.build_select(arg_isinf, llvm_f64.const_float(f64::NAN), call, "");
|
||||||
|
|
||||||
|
Ok(val.into())
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"j1",
|
||||||
|
float,
|
||||||
|
&[(float, "x")],
|
||||||
|
"j1",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
// Not mapped: jv/yv, libm only supports integer orders.
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"arctan2",
|
||||||
|
float,
|
||||||
|
&[(float, "x1"), (float, "x2")],
|
||||||
|
"atan2",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"copysign",
|
||||||
|
float,
|
||||||
|
&[(float, "x1"), (float, "x2")],
|
||||||
|
"llvm.copysign.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"fmax",
|
||||||
|
float,
|
||||||
|
&[(float, "x1"), (float, "x2")],
|
||||||
|
"llvm.maxnum.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_intrinsic(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"fmin",
|
||||||
|
float,
|
||||||
|
&[(float, "x1"), (float, "x2")],
|
||||||
|
"llvm.minnum.f64",
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"ldexp",
|
||||||
|
float,
|
||||||
|
&[(float, "x1"), (int32, "x2")],
|
||||||
|
"ldexp",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"hypot",
|
||||||
|
float,
|
||||||
|
&[(float, "x1"), (float, "x2")],
|
||||||
|
"hypot",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
|
create_fn_by_extern(
|
||||||
|
primitives,
|
||||||
|
&var_map,
|
||||||
|
"nextafter",
|
||||||
|
float,
|
||||||
|
&[(float, "x1"), (float, "x2")],
|
||||||
|
"nextafter",
|
||||||
|
&[],
|
||||||
|
),
|
||||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
Arc::new(RwLock::new(TopLevelDef::Function {
|
||||||
name: "Some".into(),
|
name: "Some".into(),
|
||||||
simple_name: "Some".into(),
|
simple_name: "Some".into(),
|
||||||
|
@ -1270,6 +1783,44 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||||
"min",
|
"min",
|
||||||
"max",
|
"max",
|
||||||
"abs",
|
"abs",
|
||||||
|
"isnan",
|
||||||
|
"isinf",
|
||||||
|
"sin",
|
||||||
|
"cos",
|
||||||
|
"exp",
|
||||||
|
"exp2",
|
||||||
|
"log",
|
||||||
|
"log10",
|
||||||
|
"log2",
|
||||||
|
"fabs",
|
||||||
|
"trunc",
|
||||||
|
"sqrt",
|
||||||
|
"rint",
|
||||||
|
"tan",
|
||||||
|
"arcsin",
|
||||||
|
"arccos",
|
||||||
|
"arctan",
|
||||||
|
"sinh",
|
||||||
|
"cosh",
|
||||||
|
"tanh",
|
||||||
|
"arcsinh",
|
||||||
|
"arccosh",
|
||||||
|
"arctanh",
|
||||||
|
"expm1",
|
||||||
|
"cbrt",
|
||||||
|
"erf",
|
||||||
|
"erfc",
|
||||||
|
"gamma",
|
||||||
|
"gammaln",
|
||||||
|
"j0",
|
||||||
|
"j1",
|
||||||
|
"arctan2",
|
||||||
|
"copysign",
|
||||||
|
"fmax",
|
||||||
|
"fmin",
|
||||||
|
"ldexp",
|
||||||
|
"hypot",
|
||||||
|
"nextafter",
|
||||||
"Some",
|
"Some",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -82,51 +82,55 @@ pub struct FunInstance {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TopLevelDef {
|
pub enum TopLevelDef {
|
||||||
Class {
|
Class {
|
||||||
// name for error messages and symbols
|
/// Name for error messages and symbols.
|
||||||
name: StrRef,
|
name: StrRef,
|
||||||
// object ID used for TypeEnum
|
/// Object ID used for [TypeEnum].
|
||||||
object_id: DefinitionId,
|
object_id: DefinitionId,
|
||||||
/// type variables bounded to the class.
|
/// type variables bounded to the class.
|
||||||
type_vars: Vec<Type>,
|
type_vars: Vec<Type>,
|
||||||
// class fields
|
/// Class fields.
|
||||||
// name, type, is mutable
|
///
|
||||||
|
/// Name and type is mutable.
|
||||||
fields: Vec<(StrRef, Type, bool)>,
|
fields: Vec<(StrRef, Type, bool)>,
|
||||||
// class methods, pointing to the corresponding function definition.
|
/// Class methods, pointing to the corresponding function definition.
|
||||||
methods: Vec<(StrRef, Type, DefinitionId)>,
|
methods: Vec<(StrRef, Type, DefinitionId)>,
|
||||||
// ancestor classes, including itself.
|
/// Ancestor classes, including itself.
|
||||||
ancestors: Vec<TypeAnnotation>,
|
ancestors: Vec<TypeAnnotation>,
|
||||||
// symbol resolver of the module defined the class, none if it is built-in type
|
/// Symbol resolver of the module defined the class; [None] if it is built-in type.
|
||||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||||
// constructor type
|
/// Constructor type.
|
||||||
constructor: Option<Type>,
|
constructor: Option<Type>,
|
||||||
// definition location
|
/// Definition location.
|
||||||
loc: Option<Location>,
|
loc: Option<Location>,
|
||||||
},
|
},
|
||||||
Function {
|
Function {
|
||||||
// prefix for symbol, should be unique globally
|
/// Prefix for symbol, should be unique globally.
|
||||||
name: String,
|
name: String,
|
||||||
// simple name, the same as in method/function definition
|
/// Simple name, the same as in method/function definition.
|
||||||
simple_name: StrRef,
|
simple_name: StrRef,
|
||||||
// function signature.
|
/// Function signature.
|
||||||
signature: Type,
|
signature: Type,
|
||||||
// instantiated type variable IDs
|
/// Instantiated type variable IDs.
|
||||||
var_id: Vec<u32>,
|
var_id: Vec<u32>,
|
||||||
/// Function instance to symbol mapping
|
/// Function instance to symbol mapping
|
||||||
/// Key: string representation of type variable values, sorted by variable ID in ascending
|
///
|
||||||
|
/// * Key: String representation of type variable values, sorted by variable ID in ascending
|
||||||
/// order, including type variables associated with the class.
|
/// order, including type variables associated with the class.
|
||||||
/// Value: function symbol name.
|
/// * Value: Function symbol name.
|
||||||
instance_to_symbol: HashMap<String, String>,
|
instance_to_symbol: HashMap<String, String>,
|
||||||
/// Function instances to annotated AST mapping
|
/// Function instances to annotated AST mapping
|
||||||
/// Key: string representation of type variable values, sorted by variable ID in ascending
|
///
|
||||||
|
/// * Key: String representation of type variable values, sorted by variable ID in ascending
|
||||||
/// order, including type variables associated with the class. Excluding rigid type
|
/// order, including type variables associated with the class. Excluding rigid type
|
||||||
/// variables.
|
/// variables.
|
||||||
/// rigid type variables that would be substituted when the function is instantiated.
|
///
|
||||||
|
/// Rigid type variables that would be substituted when the function is instantiated.
|
||||||
instance_to_stmt: HashMap<String, FunInstance>,
|
instance_to_stmt: HashMap<String, FunInstance>,
|
||||||
// symbol resolver of the module defined the class
|
/// Symbol resolver of the module defined the class.
|
||||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||||
// custom codegen callback
|
/// Custom code generation callback.
|
||||||
codegen_callback: Option<Arc<GenCall>>,
|
codegen_callback: Option<Arc<GenCall>>,
|
||||||
// definition location
|
/// Definition location.
|
||||||
loc: Option<Location>,
|
loc: Option<Location>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,14 @@
|
||||||
#error "Unsupported platform - Platform is not 32-bit or 64-bit"
|
#error "Unsupported platform - Platform is not 32-bit or 64-bit"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
double dbl_nan(void) {
|
||||||
|
return NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
double dbl_inf(void) {
|
||||||
|
return INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
void output_bool(bool x) {
|
void output_bool(bool x) {
|
||||||
puts(x ? "True" : "False");
|
puts(x ? "True" : "False");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
import sys
|
import sys
|
||||||
import importlib.util
|
import importlib.util
|
||||||
import importlib.machinery
|
import importlib.machinery
|
||||||
|
import numpy as np
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import scipy
|
||||||
|
|
||||||
from numpy import int32, int64, uint32, uint64
|
from numpy import int32, int64, uint32, uint64
|
||||||
from typing import TypeVar, Generic
|
from typing import TypeVar, Generic
|
||||||
|
@ -42,6 +44,12 @@ def Some(v: T) -> Option[T]:
|
||||||
none = Option(None)
|
none = Option(None)
|
||||||
|
|
||||||
def patch(module):
|
def patch(module):
|
||||||
|
def dbl_nan():
|
||||||
|
return np.nan
|
||||||
|
|
||||||
|
def dbl_inf():
|
||||||
|
return np.inf
|
||||||
|
|
||||||
def output_asciiart(x):
|
def output_asciiart(x):
|
||||||
if x < 0:
|
if x < 0:
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
|
@ -56,7 +64,11 @@ def patch(module):
|
||||||
|
|
||||||
def extern(fun):
|
def extern(fun):
|
||||||
name = fun.__name__
|
name = fun.__name__
|
||||||
if name == "output_asciiart":
|
if name == "dbl_nan":
|
||||||
|
return dbl_nan
|
||||||
|
elif name == "dbl_inf":
|
||||||
|
return dbl_inf
|
||||||
|
elif name == "output_asciiart":
|
||||||
return output_asciiart
|
return output_asciiart
|
||||||
elif name == "output_float64":
|
elif name == "output_float64":
|
||||||
return output_float
|
return output_float
|
||||||
|
@ -86,6 +98,50 @@ def patch(module):
|
||||||
module.Some = Some
|
module.Some = Some
|
||||||
module.none = none
|
module.none = none
|
||||||
|
|
||||||
|
# NumPy Math functions
|
||||||
|
module.isnan = np.isnan
|
||||||
|
module.isinf = np.isinf
|
||||||
|
module.sin = np.sin
|
||||||
|
module.cos = np.cos
|
||||||
|
module.exp = np.exp
|
||||||
|
module.exp2 = np.exp2
|
||||||
|
module.log = np.log
|
||||||
|
module.log10 = np.log10
|
||||||
|
module.log2 = np.log2
|
||||||
|
module.fabs = np.fabs
|
||||||
|
module.floor = np.floor
|
||||||
|
module.ceil = np.ceil
|
||||||
|
module.trunc = np.trunc
|
||||||
|
module.sqrt = np.sqrt
|
||||||
|
module.rint = np.rint
|
||||||
|
module.tan = np.tan
|
||||||
|
module.arcsin = np.arcsin
|
||||||
|
module.arccos = np.arccos
|
||||||
|
module.arctan = np.arctan
|
||||||
|
module.sinh = np.sinh
|
||||||
|
module.cosh = np.cosh
|
||||||
|
module.tanh = np.tanh
|
||||||
|
module.arcsinh = np.arcsinh
|
||||||
|
module.arccosh = np.arccosh
|
||||||
|
module.arctanh = np.arctanh
|
||||||
|
module.expm1 = np.expm1
|
||||||
|
module.cbrt = np.cbrt
|
||||||
|
module.arctan2 = np.arctan2
|
||||||
|
module.copysign = np.copysign
|
||||||
|
module.fmax = np.fmax
|
||||||
|
module.fmin = np.fmin
|
||||||
|
module.ldexp = np.ldexp
|
||||||
|
module.hypot = np.hypot
|
||||||
|
module.nextafter = np.nextafter
|
||||||
|
|
||||||
|
# SciPy Math Functions
|
||||||
|
module.erf = scipy.special.erf
|
||||||
|
module.erfc = scipy.special.erfc
|
||||||
|
module.gamma = scipy.special.gamma
|
||||||
|
module.gammaln = scipy.special.gammaln
|
||||||
|
module.j0 = scipy.special.j0
|
||||||
|
module.j1 = scipy.special.j1
|
||||||
|
|
||||||
|
|
||||||
def file_import(filename, prefix="file_import_"):
|
def file_import(filename, prefix="file_import_"):
|
||||||
filename = pathlib.Path(filename)
|
filename = pathlib.Path(filename)
|
||||||
|
|
|
@ -0,0 +1,236 @@
|
||||||
|
@extern
|
||||||
|
def output_bool(x: bool):
|
||||||
|
...
|
||||||
|
|
||||||
|
@extern
|
||||||
|
def output_float64(x: float):
|
||||||
|
...
|
||||||
|
|
||||||
|
@extern
|
||||||
|
def dbl_nan() -> float:
|
||||||
|
...
|
||||||
|
|
||||||
|
@extern
|
||||||
|
def dbl_inf() -> float:
|
||||||
|
...
|
||||||
|
|
||||||
|
def dbl_pi() -> float:
|
||||||
|
return 3.1415926535897932384626433
|
||||||
|
|
||||||
|
def dbl_e() -> float:
|
||||||
|
return 2.71828182845904523536028747135266249775724709369995
|
||||||
|
|
||||||
|
def test_isnan():
|
||||||
|
for x in [dbl_nan(), 0.0, dbl_inf()]:
|
||||||
|
output_bool(isnan(x))
|
||||||
|
|
||||||
|
def test_isinf():
|
||||||
|
for x in [dbl_inf(), -dbl_inf(), 0.0, dbl_nan()]:
|
||||||
|
output_bool(isinf(x))
|
||||||
|
|
||||||
|
def test_sin():
|
||||||
|
pi = dbl_pi()
|
||||||
|
for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(sin(x))
|
||||||
|
|
||||||
|
def test_cos():
|
||||||
|
pi = dbl_pi()
|
||||||
|
for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(cos(x))
|
||||||
|
|
||||||
|
def test_exp():
|
||||||
|
for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(exp(x))
|
||||||
|
|
||||||
|
def test_exp2():
|
||||||
|
for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(exp2(x))
|
||||||
|
|
||||||
|
def test_log():
|
||||||
|
e = dbl_e()
|
||||||
|
for x in [1.0, e, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(log(x))
|
||||||
|
|
||||||
|
def test_log10():
|
||||||
|
for x in [1.0, 10.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(log10(x))
|
||||||
|
|
||||||
|
def test_log2():
|
||||||
|
for x in [1.0, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(log2(x))
|
||||||
|
|
||||||
|
def test_fabs():
|
||||||
|
for x in [-1.0, 0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(fabs(x))
|
||||||
|
|
||||||
|
def test_floor():
|
||||||
|
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(floor(x))
|
||||||
|
|
||||||
|
def test_ceil():
|
||||||
|
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(ceil(x))
|
||||||
|
|
||||||
|
def test_trunc():
|
||||||
|
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(trunc(x))
|
||||||
|
|
||||||
|
def test_sqrt():
|
||||||
|
for x in [1.0, 2.0, 4.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(sqrt(x))
|
||||||
|
|
||||||
|
def test_rint():
|
||||||
|
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(rint(x))
|
||||||
|
|
||||||
|
def test_tan():
|
||||||
|
pi = dbl_pi()
|
||||||
|
for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(tan(x))
|
||||||
|
|
||||||
|
def test_arcsin():
|
||||||
|
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(arcsin(x))
|
||||||
|
|
||||||
|
def test_arccos():
|
||||||
|
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(arccos(x))
|
||||||
|
|
||||||
|
def test_arctan():
|
||||||
|
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(arctan(x))
|
||||||
|
|
||||||
|
def test_sinh():
|
||||||
|
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(sinh(x))
|
||||||
|
|
||||||
|
def test_cosh():
|
||||||
|
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(cosh(x))
|
||||||
|
|
||||||
|
def test_tanh():
|
||||||
|
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(tanh(x))
|
||||||
|
|
||||||
|
def test_arcsinh():
|
||||||
|
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(arcsinh(x))
|
||||||
|
|
||||||
|
def test_arccosh():
|
||||||
|
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(arccosh(x))
|
||||||
|
|
||||||
|
def test_arctanh():
|
||||||
|
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(arctanh(x))
|
||||||
|
|
||||||
|
def test_expm1():
|
||||||
|
for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(expm1(x))
|
||||||
|
|
||||||
|
def test_cbrt():
|
||||||
|
for x in [1.0, 8.0, 27.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(expm1(x))
|
||||||
|
|
||||||
|
def test_erf():
|
||||||
|
for x in [-3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(erf(x))
|
||||||
|
|
||||||
|
def test_erfc():
|
||||||
|
for x in [-3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(erfc(x))
|
||||||
|
|
||||||
|
def test_gamma():
|
||||||
|
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(gamma(x))
|
||||||
|
|
||||||
|
def test_gammaln():
|
||||||
|
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(gammaln(x))
|
||||||
|
|
||||||
|
def test_j0():
|
||||||
|
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(j0(x))
|
||||||
|
|
||||||
|
def test_j1():
|
||||||
|
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]:
|
||||||
|
output_float64(j1(x))
|
||||||
|
|
||||||
|
def test_arctan2():
|
||||||
|
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(arctan2(x1, x2))
|
||||||
|
|
||||||
|
def test_copysign():
|
||||||
|
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(copysign(x1, x2))
|
||||||
|
|
||||||
|
def test_fmax():
|
||||||
|
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(fmax(x1, x2))
|
||||||
|
|
||||||
|
def test_fmin():
|
||||||
|
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(fmin(x1, x2))
|
||||||
|
|
||||||
|
def test_ldexp():
|
||||||
|
for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
for x2 in [-2, -1, 0, 1, 2]:
|
||||||
|
output_float64(ldexp(x1, x2))
|
||||||
|
|
||||||
|
def test_hypot():
|
||||||
|
for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
for x2 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(hypot(x1, x2))
|
||||||
|
|
||||||
|
def test_nextafter():
|
||||||
|
for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
for x2 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
|
||||||
|
output_float64(nextafter(x1, x2))
|
||||||
|
|
||||||
|
def run() -> int32:
|
||||||
|
test_isnan()
|
||||||
|
test_isinf()
|
||||||
|
test_sin()
|
||||||
|
test_cos()
|
||||||
|
test_exp()
|
||||||
|
test_exp2()
|
||||||
|
test_log()
|
||||||
|
test_log10()
|
||||||
|
test_log2()
|
||||||
|
test_fabs()
|
||||||
|
test_floor()
|
||||||
|
test_ceil()
|
||||||
|
test_trunc()
|
||||||
|
test_sqrt()
|
||||||
|
test_rint()
|
||||||
|
test_tan()
|
||||||
|
test_arcsin()
|
||||||
|
test_arccos()
|
||||||
|
test_arctan()
|
||||||
|
test_sinh()
|
||||||
|
test_cosh()
|
||||||
|
test_tanh()
|
||||||
|
test_arcsinh()
|
||||||
|
test_arccosh()
|
||||||
|
test_arctanh()
|
||||||
|
test_expm1()
|
||||||
|
test_cbrt()
|
||||||
|
test_erf()
|
||||||
|
test_erfc()
|
||||||
|
test_gamma()
|
||||||
|
test_gammaln()
|
||||||
|
test_j0()
|
||||||
|
test_j1()
|
||||||
|
test_arctan2()
|
||||||
|
test_copysign()
|
||||||
|
test_fmax()
|
||||||
|
test_fmin()
|
||||||
|
test_ldexp()
|
||||||
|
test_hypot()
|
||||||
|
test_nextafter()
|
||||||
|
|
||||||
|
return 0
|
Loading…
Reference in New Issue