momba_explore/model/
values.rs

1//! Data structures for representing values.
2
3use std::cmp;
4
5use std::convert::TryInto;
6
7use serde::{Deserialize, Serialize};
8
9use ordered_float::NotNan;
10
11use super::types::*;
12
13use self::Value::*;
14
15#[derive(Serialize, Deserialize, Eq, PartialEq, Hash, Clone, Debug)]
16#[serde(untagged)]
17#[repr(u8)]
18pub enum Value {
19    Int64(i64),
20    Float64(NotNan<f64>),
21    Bool(bool),
22    Vector(Vec<Value>),
23}
24
25impl From<bool> for Value {
26    fn from(value: bool) -> Self {
27        Value::Bool(value)
28    }
29}
30
31impl TryInto<bool> for Value {
32    type Error = String;
33
34    fn try_into(self) -> Result<bool, Self::Error> {
35        match self {
36            Value::Bool(value) => Ok(value),
37            _ => Err(format!("Unable to convert {:?} to boolean.", self)),
38        }
39    }
40}
41
42impl From<i64> for Value {
43    fn from(value: i64) -> Self {
44        Value::Int64(value)
45    }
46}
47
48impl TryInto<i64> for Value {
49    type Error = String;
50
51    fn try_into(self) -> Result<i64, Self::Error> {
52        match self {
53            Value::Int64(value) => Ok(value),
54            _ => Err(format!("Unable to convert {:?} to integer.", self)),
55        }
56    }
57}
58
59impl TryInto<f64> for Value {
60    type Error = String;
61
62    fn try_into(self) -> Result<f64, Self::Error> {
63        match self {
64            Value::Float64(value) => Ok(value.into_inner()),
65            _ => Err(format!("Unable to convert {:?} to float.", self)),
66        }
67    }
68}
69
70impl Value {
71    pub fn get_type(&self) -> Type {
72        match self {
73            Value::Int64(_) => Type::Int64,
74            Value::Float64(_) => Type::Float64,
75            Value::Bool(_) => Type::Bool,
76            Value::Vector(elements) => Type::Vector {
77                element_type: Box::new(
78                    // All elements are required to have the same type, hence,
79                    // we just take the first element of the vector.
80                    elements
81                        .first()
82                        .map(|element| element.get_type())
83                        .unwrap_or(Type::Unknown),
84                ),
85            },
86        }
87    }
88
89    pub fn is_int(&self) -> bool {
90        matches!(self, Value::Int64(_))
91    }
92
93    pub fn is_float(&self) -> bool {
94        matches!(self, Value::Float64(_))
95    }
96
97    pub fn is_numeric(&self) -> bool {
98        matches!(self, Value::Int64(_) | Value::Float64(_))
99    }
100
101    pub fn is_bool(&self) -> bool {
102        matches!(self, Value::Bool(_))
103    }
104
105    pub fn is_vector(&self) -> bool {
106        matches!(self, Value::Vector(_))
107    }
108
109    pub fn unwrap_bool(&self) -> bool {
110        match self {
111            Value::Bool(value) => *value,
112            _ => panic!("Value {:?} is not a Bool.", self),
113        }
114    }
115
116    pub fn unwrap_int64(&self) -> i64 {
117        match self {
118            Value::Int64(value) => *value,
119            _ => panic!("Value {:?} is not an Int64.", self),
120        }
121    }
122
123    pub fn unwrap_float64(&self) -> NotNan<f64> {
124        match self {
125            Value::Float64(value) => *value,
126            _ => panic!("Value {:?} is not a Float64.", self),
127        }
128    }
129
130    pub fn unwrap_vector(&self) -> &Vec<Value> {
131        match self {
132            Value::Vector(vector) => vector,
133            _ => panic!("Value {:?} is not a Vector.", self),
134        }
135    }
136
137    #[inline(always)]
138    pub fn apply_not(self) -> Value {
139        match self {
140            Bool(operand) => Bool(!operand),
141            operand => panic!("Invalid operand in expression (! {:?}).", operand),
142        }
143    }
144
145    #[inline(always)]
146    pub fn apply_floor(self) -> Value {
147        match self {
148            Float64(operand) => Int64(operand.floor() as i64),
149            Int64(operand) => Int64(operand),
150            operand => panic!("Invalid operand in expression (floor {:?}).", operand),
151        }
152    }
153
154    #[inline(always)]
155    pub fn apply_ceil(self) -> Value {
156        match self {
157            Float64(operand) => Int64(operand.ceil() as i64),
158            operand => panic!("Invalid operand in expression (ceil {:?}).", operand),
159        }
160    }
161
162    #[inline(always)]
163    pub fn apply_abs(self) -> Value {
164        match self {
165            Float64(operand) => Float64(NotNan::new(operand.abs()).unwrap()),
166            Int64(operand) => Int64(operand.abs()),
167            operand => panic!("Invalid operand in expression (abs {:?}).", operand),
168        }
169    }
170
171    #[inline(always)]
172    pub fn apply_sgn(self) -> Value {
173        match self {
174            Float64(operand) => Float64(NotNan::new(operand.signum()).unwrap()),
175            Int64(operand) => Int64(operand.signum()),
176            operand => panic!("Invalid operand in expression (sgn {:?}).", operand),
177        }
178    }
179
180    #[inline(always)]
181    pub fn apply_trc(self) -> Value {
182        match self {
183            Float64(operand) => Int64(operand.trunc() as i64),
184            operand => panic!("Invalid operand in expression (trc {:?}).", operand),
185        }
186    }
187
188    #[inline(always)]
189    pub fn apply_minus(self) -> Value {
190        match self {
191            Int64(operand) => Int64(-operand),
192            Float64(operand) => Float64(-operand),
193            operand => panic!("Invalid operand in expression (- {:?}).", operand),
194        }
195    }
196
197    #[inline(always)]
198    pub fn apply_add(self, other: Value) -> Value {
199        match (self, other) {
200            (Int64(left), Int64(right)) => Int64(left + right),
201            (Float64(left), Float64(right)) => Float64(left + right),
202            (Int64(left), Float64(right)) => Float64(NotNan::new(left as f64).unwrap() + right),
203            (Float64(left), Int64(right)) => Float64(left + NotNan::new(right as f64).unwrap()),
204            (left, right) => panic!("Invalid operands in expression ({:?} + {:?}).", left, right),
205        }
206    }
207
208    #[inline(always)]
209    pub fn apply_sub(self, other: Value) -> Value {
210        match (self, other) {
211            (Int64(left), Int64(right)) => Int64(left - right),
212            (Float64(left), Float64(right)) => Float64(left - right),
213            (Int64(left), Float64(right)) => Float64(NotNan::new(left as f64).unwrap() - right),
214            (Float64(left), Int64(right)) => Float64(left - NotNan::new(right as f64).unwrap()),
215            (left, right) => panic!("Invalid operands in expression ({:?} - {:?}).", left, right),
216        }
217    }
218
219    #[inline(always)]
220    pub fn apply_mul(self, other: Value) -> Value {
221        match (self, other) {
222            (Int64(left), Int64(right)) => Int64(left * right),
223            (Float64(left), Float64(right)) => Float64(left * right),
224            (Int64(left), Float64(right)) => Float64(NotNan::new(left as f64).unwrap() * right),
225            (Float64(left), Int64(right)) => Float64(left * NotNan::new(right as f64).unwrap()),
226            (left, right) => panic!("Invalid operands in expression ({:?} * {:?}).", left, right),
227        }
228    }
229
230    #[inline(always)]
231    pub fn apply_floor_div(self, other: Value) -> Value {
232        match (self, other) {
233            (Int64(left), Int64(right)) => Int64(left.div_euclid(right)),
234            (Float64(left), Float64(right)) => Int64((left / right).floor() as i64),
235            (Int64(left), Float64(right)) => {
236                Int64((NotNan::new(left as f64).unwrap() / right).floor() as i64)
237            }
238            (Float64(left), Int64(right)) => {
239                Int64((left / (NotNan::new(right as f64).unwrap()).floor()).into_inner() as i64)
240            }
241            (left, right) => panic!(
242                "Invalid operands in expression ({:?} // {:?}).",
243                left, right
244            ),
245        }
246    }
247
248    #[inline(always)]
249    pub fn apply_real_div(self, other: Value) -> Value {
250        match (self, other) {
251            (Int64(left), Int64(right)) => {
252                Float64(NotNan::new((left as f64) / (right as f64)).unwrap())
253            }
254            (Float64(left), Float64(right)) => Float64(left / right),
255            (left, right) => panic!("Invalid operands in expression ({:?} / {:?}).", left, right),
256        }
257    }
258
259    #[inline(always)]
260    pub fn apply_mod(self, other: Value) -> Value {
261        match (self, other) {
262            (Int64(left), Int64(right)) => Int64(left.rem_euclid(right)),
263            (Float64(left), Float64(right)) => Float64(left % right),
264            (left, right) => panic!("Invalid operands in expression ({:?} % {:?}).", left, right),
265        }
266    }
267
268    #[inline(always)]
269    pub fn apply_pow(self, other: Value) -> Value {
270        match (self, other) {
271            (Int64(left), Int64(right)) => {
272                Float64(NotNan::new((left as f64).powf(right as f64)).unwrap())
273            }
274            (Float64(left), Float64(right)) => {
275                Float64(NotNan::new(left.powf(right.into())).unwrap())
276            }
277            (left, right) => panic!(
278                "Invalid operands in expression ({:?} ** {:?}).",
279                left, right
280            ),
281        }
282    }
283
284    #[inline(always)]
285    pub fn apply_log(self, other: Value) -> Value {
286        match (self, other) {
287            (Int64(left), Int64(right)) => {
288                Float64(NotNan::new((left as f64).log(right as f64)).unwrap())
289            }
290            (Float64(left), Float64(right)) => {
291                Float64(NotNan::new(left.log(right.into())).unwrap())
292            }
293            (left, right) => panic!(
294                "Invalid operands in expression ({:?} log {:?}).",
295                left, right
296            ),
297        }
298    }
299
300    #[inline(always)]
301    pub fn apply_min(self, other: Value) -> Value {
302        match (self, other) {
303            (Int64(left), Int64(right)) => Int64(cmp::min(left, right)),
304            (Float64(left), Float64(right)) => Float64(cmp::min(left, right)),
305            (left, right) => panic!(
306                "Invalid operands in expression ({:?} min {:?}).",
307                left, right
308            ),
309        }
310    }
311
312    #[inline(always)]
313    pub fn apply_max(self, other: Value) -> Value {
314        match (self, other) {
315            (Int64(left), Int64(right)) => Int64(cmp::max(left, right)),
316            (Float64(left), Float64(right)) => Float64(cmp::max(left, right)),
317            (left, right) => panic!(
318                "Invalid operands in expression ({:?} max {:?}).",
319                left, right
320            ),
321        }
322    }
323
324    #[inline(always)]
325    pub fn apply_cmp_eq(self, other: Value) -> Value {
326        Value::Bool(self == other)
327    }
328
329    #[inline(always)]
330    pub fn apply_cmp_ne(self, other: Value) -> Value {
331        Value::Bool(self != other)
332    }
333
334    #[inline(always)]
335    pub fn apply_cmp_lt(self, other: Value) -> Value {
336        match (self, other) {
337            (Int64(left), Int64(right)) => Bool(left < right),
338            (Float64(left), Float64(right)) => Bool(left < right),
339            (Int64(left), Float64(right)) => Bool((left as f64) < right.into_inner()),
340            (Float64(left), Int64(right)) => Bool(left.into_inner() < (right as f64)),
341            (left, right) => panic!("Invalid operands in expression ({:?} < {:?}).", left, right),
342        }
343    }
344
345    #[inline(always)]
346    pub fn apply_cmp_le(self, other: Value) -> Value {
347        match (self, other) {
348            (Int64(left), Int64(right)) => Bool(left <= right),
349            (Float64(left), Float64(right)) => Bool(left <= right),
350            (Int64(left), Float64(right)) => Bool((left as f64) <= right.into_inner()),
351            (Float64(left), Int64(right)) => Bool(left.into_inner() <= (right as f64)),
352            (left, right) => panic!(
353                "Invalid operands in expression ({:?} <= {:?}).",
354                left, right
355            ),
356        }
357    }
358
359    #[inline(always)]
360    pub fn apply_cmp_ge(self, other: Value) -> Value {
361        match (self, other) {
362            (Int64(left), Int64(right)) => Bool(left >= right),
363            (Float64(left), Float64(right)) => Bool(left >= right),
364            (Int64(left), Float64(right)) => Bool((left as f64) >= right.into_inner()),
365            (Float64(left), Int64(right)) => Bool(left.into_inner() >= (right as f64)),
366            (left, right) => panic!(
367                "Invalid operands in expression ({:?} >= {:?}).",
368                left, right
369            ),
370        }
371    }
372
373    #[inline(always)]
374    pub fn apply_cmp_gt(self, other: Value) -> Value {
375        match (self, other) {
376            (Int64(left), Int64(right)) => Bool(left > right),
377            (Float64(left), Float64(right)) => Bool(left > right),
378            (Int64(left), Float64(right)) => Bool((left as f64) > right.into_inner()),
379            (Float64(left), Int64(right)) => Bool(left.into_inner() > (right as f64)),
380            (left, right) => panic!("Invalid operands in expression ({:?} > {:?}).", left, right),
381        }
382    }
383
384    #[inline(always)]
385    pub fn apply_sin(self) -> Value {
386        match self {
387            Float64(operand) => Float64(operand.sin().try_into().unwrap()),
388            operand => panic!("Invalid operand in expression (sin {:?}).", operand),
389        }
390    }
391
392    #[inline(always)]
393    pub fn apply_cos(self) -> Value {
394        match self {
395            Float64(operand) => Float64(operand.cos().try_into().unwrap()),
396            operand => panic!("Invalid operand in expression (sin {:?}).", operand),
397        }
398    }
399
400    #[inline(always)]
401    pub fn apply_tan(self) -> Value {
402        match self {
403            Float64(operand) => Float64(operand.tan().try_into().unwrap()),
404            operand => panic!("Invalid operand in expression (sin {:?}).", operand),
405        }
406    }
407}