mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 05:34:11 +03:00
commit
4ce520fed6
@ -430,6 +430,20 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||
),
|
||||
);
|
||||
|
||||
// log : Float a -> Float a
|
||||
let log_needs_positive = SolvedType::TagUnion(
|
||||
vec![(TagName::Global("LogNeedsPositive".into()), vec![])],
|
||||
Box::new(SolvedType::Wildcard),
|
||||
);
|
||||
|
||||
add_type(
|
||||
Symbol::NUM_LOG,
|
||||
top_level_function(
|
||||
vec![float_type(flex(TVAR1))],
|
||||
Box::new(result_type(float_type(flex(TVAR1)), log_needs_positive)),
|
||||
),
|
||||
);
|
||||
|
||||
// round : Float a -> Int b
|
||||
add_type(
|
||||
Symbol::NUM_ROUND,
|
||||
|
@ -139,6 +139,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
|
||||
NUM_REM => num_rem,
|
||||
NUM_IS_MULTIPLE_OF => num_is_multiple_of,
|
||||
NUM_SQRT => num_sqrt,
|
||||
NUM_LOG => num_log,
|
||||
NUM_ROUND => num_round,
|
||||
NUM_IS_ODD => num_is_odd,
|
||||
NUM_IS_EVEN => num_is_even,
|
||||
@ -276,6 +277,7 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
|
||||
Symbol::NUM_REM => num_rem,
|
||||
Symbol::NUM_IS_MULTIPLE_OF => num_is_multiple_of,
|
||||
Symbol::NUM_SQRT => num_sqrt,
|
||||
Symbol::NUM_LOG => num_log,
|
||||
Symbol::NUM_ROUND => num_round,
|
||||
Symbol::NUM_IS_ODD => num_is_odd,
|
||||
Symbol::NUM_IS_EVEN => num_is_even,
|
||||
@ -1174,6 +1176,52 @@ fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
)
|
||||
}
|
||||
|
||||
/// Num.log : Float -> Result Float [ LogNeedsPositive ]*
|
||||
fn num_log(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let bool_var = var_store.fresh();
|
||||
let float_var = var_store.fresh();
|
||||
let unbound_zero_var = var_store.fresh();
|
||||
let precision_var = var_store.fresh();
|
||||
let ret_var = var_store.fresh();
|
||||
|
||||
let body = If {
|
||||
branch_var: ret_var,
|
||||
cond_var: bool_var,
|
||||
branches: vec![(
|
||||
no_region(RunLowLevel {
|
||||
op: LowLevel::NumGt,
|
||||
args: vec![
|
||||
(float_var, Var(Symbol::ARG_1)),
|
||||
(float_var, Float(unbound_zero_var, precision_var, 0.0)),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
}),
|
||||
no_region(tag(
|
||||
"Ok",
|
||||
vec![RunLowLevel {
|
||||
op: LowLevel::NumLogUnchecked,
|
||||
args: vec![(float_var, Var(Symbol::ARG_1))],
|
||||
ret_var: float_var,
|
||||
}],
|
||||
var_store,
|
||||
)),
|
||||
)],
|
||||
final_else: Box::new(no_region(tag(
|
||||
"Err",
|
||||
vec![tag("LogNeedsPositive", Vec::new(), var_store)],
|
||||
var_store,
|
||||
))),
|
||||
};
|
||||
|
||||
defn(
|
||||
symbol,
|
||||
vec![(float_var, Symbol::ARG_1)],
|
||||
var_store,
|
||||
body,
|
||||
ret_var,
|
||||
)
|
||||
}
|
||||
|
||||
/// Num.round : Float -> Int
|
||||
fn num_round(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let float_var = var_store.fresh();
|
||||
|
@ -337,6 +337,12 @@ fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) {
|
||||
f64_type.fn_type(&[f64_type.into()], false),
|
||||
);
|
||||
|
||||
add_intrinsic(
|
||||
module,
|
||||
LLVM_LOG_F64,
|
||||
f64_type.fn_type(&[f64_type.into()], false),
|
||||
);
|
||||
|
||||
add_intrinsic(
|
||||
module,
|
||||
LLVM_LROUND_I64_F64,
|
||||
@ -455,6 +461,7 @@ fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) {
|
||||
static LLVM_MEMSET_I64: &str = "llvm.memset.p0i8.i64";
|
||||
static LLVM_MEMSET_I32: &str = "llvm.memset.p0i8.i32";
|
||||
static LLVM_SQRT_F64: &str = "llvm.sqrt.f64";
|
||||
static LLVM_LOG_F64: &str = "llvm.log.f64";
|
||||
static LLVM_LROUND_I64_F64: &str = "llvm.lround.i64.f64";
|
||||
static LLVM_FABS_F64: &str = "llvm.fabs.f64";
|
||||
static LLVM_SIN_F64: &str = "llvm.sin.f64";
|
||||
@ -3969,8 +3976,8 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||
|
||||
list_join(env, inplace, parent, list, outer_list_layout)
|
||||
}
|
||||
NumAbs | NumNeg | NumRound | NumSqrtUnchecked | NumSin | NumCos | NumCeiling | NumFloor
|
||||
| NumToFloat | NumIsFinite | NumAtan | NumAcos | NumAsin => {
|
||||
NumAbs | NumNeg | NumRound | NumSqrtUnchecked | NumLogUnchecked | NumSin | NumCos
|
||||
| NumCeiling | NumFloor | NumToFloat | NumIsFinite | NumAtan | NumAcos | NumAsin => {
|
||||
debug_assert_eq!(args.len(), 1);
|
||||
|
||||
let (arg, arg_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
@ -5279,6 +5286,7 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
|
||||
NumNeg => bd.build_float_neg(arg, "negate_float").into(),
|
||||
NumAbs => env.call_intrinsic(LLVM_FABS_F64, &[arg.into()]),
|
||||
NumSqrtUnchecked => env.call_intrinsic(LLVM_SQRT_F64, &[arg.into()]),
|
||||
NumLogUnchecked => env.call_intrinsic(LLVM_LOG_F64, &[arg.into()]),
|
||||
NumRound => env.call_intrinsic(LLVM_LROUND_I64_F64, &[arg.into()]),
|
||||
NumSin => env.call_intrinsic(LLVM_SIN_F64, &[arg.into()]),
|
||||
NumCos => env.call_intrinsic(LLVM_COS_F64, &[arg.into()]),
|
||||
|
@ -72,6 +72,7 @@ pub enum LowLevel {
|
||||
NumSin,
|
||||
NumCos,
|
||||
NumSqrtUnchecked,
|
||||
NumLogUnchecked,
|
||||
NumRound,
|
||||
NumToFloat,
|
||||
NumPow,
|
||||
|
@ -804,59 +804,60 @@ define_builtins! {
|
||||
43 NUM_MOD_INT: "modInt"
|
||||
44 NUM_MOD_FLOAT: "modFloat"
|
||||
45 NUM_SQRT: "sqrt"
|
||||
46 NUM_ROUND: "round"
|
||||
47 NUM_COMPARE: "compare"
|
||||
48 NUM_POW: "pow"
|
||||
49 NUM_CEILING: "ceiling"
|
||||
50 NUM_POW_INT: "powInt"
|
||||
51 NUM_FLOOR: "floor"
|
||||
52 NUM_ADD_WRAP: "addWrap"
|
||||
53 NUM_ADD_CHECKED: "addChecked"
|
||||
54 NUM_ATAN: "atan"
|
||||
55 NUM_ACOS: "acos"
|
||||
56 NUM_ASIN: "asin"
|
||||
57 NUM_AT_SIGNED128: "@Signed128"
|
||||
58 NUM_SIGNED128: "Signed128" imported
|
||||
59 NUM_AT_SIGNED64: "@Signed64"
|
||||
60 NUM_SIGNED64: "Signed64" imported
|
||||
61 NUM_AT_SIGNED32: "@Signed32"
|
||||
62 NUM_SIGNED32: "Signed32" imported
|
||||
63 NUM_AT_SIGNED16: "@Signed16"
|
||||
64 NUM_SIGNED16: "Signed16" imported
|
||||
65 NUM_AT_SIGNED8: "@Signed8"
|
||||
66 NUM_SIGNED8: "Signed8" imported
|
||||
67 NUM_AT_UNSIGNED128: "@Unsigned128"
|
||||
68 NUM_UNSIGNED128: "Unsigned128" imported
|
||||
69 NUM_AT_UNSIGNED64: "@Unsigned64"
|
||||
70 NUM_UNSIGNED64: "Unsigned64" imported
|
||||
71 NUM_AT_UNSIGNED32: "@Unsigned32"
|
||||
72 NUM_UNSIGNED32: "Unsigned32" imported
|
||||
73 NUM_AT_UNSIGNED16: "@Unsigned16"
|
||||
74 NUM_UNSIGNED16: "Unsigned16" imported
|
||||
75 NUM_AT_UNSIGNED8: "@Unsigned8"
|
||||
76 NUM_UNSIGNED8: "Unsigned8" imported
|
||||
77 NUM_AT_BINARY64: "@Binary64"
|
||||
78 NUM_BINARY64: "Binary64" imported
|
||||
79 NUM_AT_BINARY32: "@Binary32"
|
||||
80 NUM_BINARY32: "Binary32" imported
|
||||
81 NUM_BITWISE_AND: "bitwiseAnd"
|
||||
82 NUM_BITWISE_XOR: "bitwiseXor"
|
||||
83 NUM_BITWISE_OR: "bitwiseOr"
|
||||
84 NUM_SHIFT_LEFT: "shiftLeftBy"
|
||||
85 NUM_SHIFT_RIGHT: "shiftRightBy"
|
||||
86 NUM_SHIFT_RIGHT_ZERO_FILL: "shiftRightZfBy"
|
||||
87 NUM_SUB_WRAP: "subWrap"
|
||||
88 NUM_SUB_CHECKED: "subChecked"
|
||||
89 NUM_MUL_WRAP: "mulWrap"
|
||||
90 NUM_MUL_CHECKED: "mulChecked"
|
||||
91 NUM_INT: "Int" imported
|
||||
92 NUM_FLOAT: "Float" imported
|
||||
93 NUM_AT_NATURAL: "@Natural"
|
||||
94 NUM_NATURAL: "Natural" imported
|
||||
95 NUM_NAT: "Nat" imported
|
||||
96 NUM_INT_CAST: "intCast"
|
||||
97 NUM_MAX_I128: "maxI128"
|
||||
98 NUM_IS_MULTIPLE_OF: "isMultipleOf"
|
||||
46 NUM_LOG: "log"
|
||||
47 NUM_ROUND: "round"
|
||||
48 NUM_COMPARE: "compare"
|
||||
49 NUM_POW: "pow"
|
||||
50 NUM_CEILING: "ceiling"
|
||||
51 NUM_POW_INT: "powInt"
|
||||
52 NUM_FLOOR: "floor"
|
||||
53 NUM_ADD_WRAP: "addWrap"
|
||||
54 NUM_ADD_CHECKED: "addChecked"
|
||||
55 NUM_ATAN: "atan"
|
||||
56 NUM_ACOS: "acos"
|
||||
57 NUM_ASIN: "asin"
|
||||
58 NUM_AT_SIGNED128: "@Signed128"
|
||||
59 NUM_SIGNED128: "Signed128" imported
|
||||
60 NUM_AT_SIGNED64: "@Signed64"
|
||||
61 NUM_SIGNED64: "Signed64" imported
|
||||
62 NUM_AT_SIGNED32: "@Signed32"
|
||||
63 NUM_SIGNED32: "Signed32" imported
|
||||
64 NUM_AT_SIGNED16: "@Signed16"
|
||||
65 NUM_SIGNED16: "Signed16" imported
|
||||
66 NUM_AT_SIGNED8: "@Signed8"
|
||||
67 NUM_SIGNED8: "Signed8" imported
|
||||
68 NUM_AT_UNSIGNED128: "@Unsigned128"
|
||||
69 NUM_UNSIGNED128: "Unsigned128" imported
|
||||
70 NUM_AT_UNSIGNED64: "@Unsigned64"
|
||||
71 NUM_UNSIGNED64: "Unsigned64" imported
|
||||
72 NUM_AT_UNSIGNED32: "@Unsigned32"
|
||||
73 NUM_UNSIGNED32: "Unsigned32" imported
|
||||
74 NUM_AT_UNSIGNED16: "@Unsigned16"
|
||||
75 NUM_UNSIGNED16: "Unsigned16" imported
|
||||
76 NUM_AT_UNSIGNED8: "@Unsigned8"
|
||||
77 NUM_UNSIGNED8: "Unsigned8" imported
|
||||
78 NUM_AT_BINARY64: "@Binary64"
|
||||
79 NUM_BINARY64: "Binary64" imported
|
||||
80 NUM_AT_BINARY32: "@Binary32"
|
||||
81 NUM_BINARY32: "Binary32" imported
|
||||
82 NUM_BITWISE_AND: "bitwiseAnd"
|
||||
83 NUM_BITWISE_XOR: "bitwiseXor"
|
||||
84 NUM_BITWISE_OR: "bitwiseOr"
|
||||
85 NUM_SHIFT_LEFT: "shiftLeftBy"
|
||||
86 NUM_SHIFT_RIGHT: "shiftRightBy"
|
||||
87 NUM_SHIFT_RIGHT_ZERO_FILL: "shiftRightZfBy"
|
||||
88 NUM_SUB_WRAP: "subWrap"
|
||||
89 NUM_SUB_CHECKED: "subChecked"
|
||||
90 NUM_MUL_WRAP: "mulWrap"
|
||||
91 NUM_MUL_CHECKED: "mulChecked"
|
||||
92 NUM_INT: "Int" imported
|
||||
93 NUM_FLOAT: "Float" imported
|
||||
94 NUM_AT_NATURAL: "@Natural"
|
||||
95 NUM_NATURAL: "Natural" imported
|
||||
96 NUM_NAT: "Nat" imported
|
||||
97 NUM_INT_CAST: "intCast"
|
||||
98 NUM_MAX_I128: "maxI128"
|
||||
99 NUM_IS_MULTIPLE_OF: "isMultipleOf"
|
||||
|
||||
}
|
||||
2 BOOL: "Bool" => {
|
||||
|
@ -671,10 +671,9 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
|
||||
| NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy
|
||||
| NumShiftRightZfBy => arena.alloc_slice_copy(&[irrelevant, irrelevant]),
|
||||
|
||||
NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumRound | NumCeiling | NumFloor
|
||||
| NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin | NumIntCast => {
|
||||
arena.alloc_slice_copy(&[irrelevant])
|
||||
}
|
||||
NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumLogUnchecked | NumRound
|
||||
| NumCeiling | NumFloor | NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin
|
||||
| NumIntCast => arena.alloc_slice_copy(&[irrelevant]),
|
||||
StrStartsWith | StrEndsWith => arena.alloc_slice_copy(&[owned, borrowed]),
|
||||
StrFromUtf8 => arena.alloc_slice_copy(&[owned]),
|
||||
StrToBytes => arena.alloc_slice_copy(&[owned]),
|
||||
|
@ -361,7 +361,6 @@ mod gen_num {
|
||||
|
||||
#[test]
|
||||
fn f64_sqrt() {
|
||||
// FIXME this works with normal types, but fails when checking uniqueness types
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
@ -376,6 +375,35 @@ mod gen_num {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_log() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Num.log 7.38905609893 is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
"#
|
||||
),
|
||||
1.999999999999912,
|
||||
f64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_log_one() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Num.log 1 is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
"#
|
||||
),
|
||||
0.0,
|
||||
f64
|
||||
);
|
||||
}
|
||||
|
||||
fn f64_sqrt_zero() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
@ -405,6 +433,36 @@ mod gen_num {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_log_zero() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Num.log 0 is
|
||||
Err _ -> 42
|
||||
Ok val -> val
|
||||
"#
|
||||
),
|
||||
42.0,
|
||||
f64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_log_negative() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Num.log -1 is
|
||||
Err _ -> 42
|
||||
Ok val -> val
|
||||
"#
|
||||
),
|
||||
42.0,
|
||||
f64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_round_old() {
|
||||
assert_evals_to!("Num.round 3.6", 4, i64);
|
||||
|
Loading…
Reference in New Issue
Block a user