calcit/builtins/
math.rs

1use crate::primes::{Calcit, CalcitErr, CalcitItems};
2
3use crate::util::number::{f64_to_i32, is_integer};
4
5pub fn binary_add(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
6  match (xs.get(0), xs.get(1)) {
7    (Some(Calcit::Number(a)), Some(Calcit::Number(b))) => Ok(Calcit::Number(a + b)),
8    (Some(a), Some(b)) => CalcitErr::err_str(format!("invalid types for &+: {} {}", a, b)),
9    (_, _) if xs.len() != 2 => CalcitErr::err_str("&+ expected 2 arguments"),
10    _ => CalcitErr::err_str("invalid arguments"),
11  }
12}
13
14pub fn binary_minus(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
15  match (xs.get(0), xs.get(1)) {
16    (Some(Calcit::Number(a)), Some(Calcit::Number(b))) => Ok(Calcit::Number(a - b)),
17    (Some(a), Some(b)) => CalcitErr::err_str(format!("invalid types for &-: {} {}", a, b)),
18    (_, _) if xs.len() != 2 => CalcitErr::err_str("&- expected 2 arguments"),
19    _ => CalcitErr::err_str("invalid arguments"),
20  }
21}
22
23pub fn binary_multiply(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
24  match (xs.get(0), xs.get(1)) {
25    (Some(Calcit::Number(a)), Some(Calcit::Number(b))) => Ok(Calcit::Number(a * b)),
26    (Some(a), Some(b)) => CalcitErr::err_str(format!("invalid types for &*: {} {}", a, b)),
27    (_, _) if xs.len() != 2 => CalcitErr::err_str("&* expected 2 arguments"),
28    _ => CalcitErr::err_str("invalid arguments"),
29  }
30}
31
32pub fn binary_divide(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
33  match (xs.get(0), xs.get(1)) {
34    (Some(Calcit::Number(a)), Some(Calcit::Number(b))) => Ok(Calcit::Number(a / b)),
35    (Some(a), Some(b)) => CalcitErr::err_str(format!("invalid types for &/: {} {}", a, b)),
36    (_, _) if xs.len() != 2 => CalcitErr::err_str("&/ expected 2 arguments"),
37    _ => CalcitErr::err_str("invalid arguments"),
38  }
39}
40
41pub fn round_ques(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
42  match xs.get(0) {
43    Some(Calcit::Number(n)) => Ok(Calcit::Bool(is_integer(*n))),
44    Some(a) => CalcitErr::err_str(format!("round? expected a number: {}", a)),
45    a => CalcitErr::err_str(format!("round? expected 1 number: {:?}", a)),
46  }
47}
48
49pub fn floor(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
50  match xs.get(0) {
51    Some(Calcit::Number(n)) => Ok(Calcit::Number(n.floor())),
52    Some(a) => CalcitErr::err_str(format!("rand expected a number: {}", a)),
53    a => CalcitErr::err_str(format!("rand expected 1 number: {:?}", a)),
54  }
55}
56
57// TODO semantics of Rust and JavaScript are different
58pub fn fractional(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
59  match xs.get(0) {
60    Some(Calcit::Number(n)) => Ok(Calcit::Number(n - n.floor())),
61    Some(a) => CalcitErr::err_str(format!("fractional expected a number: {}", a)),
62    a => CalcitErr::err_str(format!("fractional expected 1 number: {:?}", a)),
63  }
64}
65
66pub fn rem(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
67  match (xs.get(0), xs.get(1)) {
68    (Some(Calcit::Number(base)), Some(Calcit::Number(step))) => match (f64_to_i32(*base), f64_to_i32(*step)) {
69      (Ok(a), Ok(b)) => Ok(Calcit::Number((a % b) as f64)),
70      (Err(a), _) => CalcitErr::err_str(a),
71      (_, Err(a)) => CalcitErr::err_str(a),
72    },
73    (Some(a), Some(b)) => CalcitErr::err_str(format!("mod expected 2 numbers, got: {:?} {:?}", a, b)),
74    (a, b) => CalcitErr::err_str(format!("mod expected 2 numbers, got: {:?} {:?}", a, b)),
75  }
76}
77
78pub fn round(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
79  match xs.get(0) {
80    Some(Calcit::Number(n)) => Ok(Calcit::Number(n.round())),
81    Some(a) => CalcitErr::err_str(format!("round expected a number: {}", a)),
82    a => CalcitErr::err_str(format!("round expected 1 number: {:?}", a)),
83  }
84}
85pub fn sin(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
86  match xs.get(0) {
87    Some(Calcit::Number(n)) => Ok(Calcit::Number(n.sin())),
88    Some(a) => CalcitErr::err_str(format!("sin expected a number: {}", a)),
89    a => CalcitErr::err_str(format!("sin expected 1 number: {:?}", a)),
90  }
91}
92pub fn cos(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
93  match xs.get(0) {
94    Some(Calcit::Number(n)) => Ok(Calcit::Number(n.cos())),
95    Some(a) => CalcitErr::err_str(format!("cos expected a number: {}", a)),
96    a => CalcitErr::err_str(format!("cos expected 1 number: {:?}", a)),
97  }
98}
99pub fn pow(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
100  match (xs.get(0), xs.get(1)) {
101    (Some(Calcit::Number(base)), Some(Calcit::Number(step))) => Ok(Calcit::Number(base.powf(*step))),
102    (Some(a), Some(b)) => CalcitErr::err_str(format!("pow expected 2 numbers, got: {:?} {:?}", a, b)),
103    (a, b) => CalcitErr::err_str(format!("pow expected 2 numbers, got: {:?} {:?}", a, b)),
104  }
105}
106pub fn ceil(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
107  match xs.get(0) {
108    Some(Calcit::Number(n)) => Ok(Calcit::Number(n.ceil())),
109    Some(a) => CalcitErr::err_str(format!("ceil expected a number: {}", a)),
110    a => CalcitErr::err_str(format!("ceil expected 1 number: {:?}", a)),
111  }
112}
113pub fn sqrt(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
114  match xs.get(0) {
115    Some(Calcit::Number(n)) => Ok(Calcit::Number(n.sqrt())),
116    Some(a) => CalcitErr::err_str(format!("sqrt expected a number: {}", a)),
117    a => CalcitErr::err_str(format!("sqrt expected 1 number: {:?}", a)),
118  }
119}
120
121pub fn bit_shr(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
122  match (xs.get(0), xs.get(1)) {
123    (Some(Calcit::Number(n)), Some(Calcit::Number(m))) => match (f64_to_i32(*n), f64_to_i32(*m)) {
124      (Ok(value), Ok(step)) => Ok(Calcit::Number((value >> step) as f64)),
125      (Err(e), _) => CalcitErr::err_str(format!("bit-shr expect int as initial value: {}", e)),
126      (_, Err(e)) => CalcitErr::err_str(format!("bit-shr expect int as step: {}", e)),
127    },
128    (Some(a), Some(b)) => CalcitErr::err_str(format!("bit-shr expected 2 numbers, got: {} {}", a, b)),
129    (a, b) => CalcitErr::err_str(format!("bit-shr expected 2 number: {:?} {:?}", a, b)),
130  }
131}
132
133pub fn bit_shl(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
134  match (xs.get(0), xs.get(1)) {
135    (Some(Calcit::Number(n)), Some(Calcit::Number(m))) => match (f64_to_i32(*n), f64_to_i32(*m)) {
136      (Ok(value), Ok(step)) => Ok(Calcit::Number((value << step) as f64)),
137      (Err(e), _) => CalcitErr::err_str(format!("bit-shl expect int as initial value: {}", e)),
138      (_, Err(e)) => CalcitErr::err_str(format!("bit-shl expect int as step: {}", e)),
139    },
140    (Some(a), Some(b)) => CalcitErr::err_str(format!("bit-shl expected 2 numbers, got: {} {}", a, b)),
141    (a, b) => CalcitErr::err_str(format!("bit-shl expected 2 number: {:?} {:?}", a, b)),
142  }
143}