1use crate::calc::context::{Context, Format};
2use crate::calc::meaning::Meaning;
3use crate::error::MyResult;
4use crate::regex;
5use crate::util::text::{create_padding, remove_char};
6use big_rational_str::BigRationalExt;
7use chrono::{DateTime, Duration, NaiveDateTime};
8use num::traits::Inv;
9use num::*;
10use regex::{Captures, Match};
11use std::cell::RefCell;
12use std::fmt::{Debug, Formatter};
13use std::iter::zip;
14use std::ops::{BitAnd, BitOr, BitXor, Div, Mul, Sub};
15use std::rc::Rc;
16use std::time::SystemTime;
17
18pub type ValueRef = Rc<RefCell<Value>>;
19
20#[derive(PartialEq)]
21pub struct Value {
22 pub number: Option<BigRational>,
23 pub meaning: Meaning,
24 pub variable: Option<String>,
25 pub comment: Option<String>,
26}
27
28const CHUNK_DIGITS: usize = 8;
29const CHUNK_VALUE: usize = 0x1_0000_0000;
30const ROUNDING_LIMIT: usize = 6;
31
32impl Value {
34 pub const fn new(number: Option<BigRational>) -> Self {
35 Self {
36 number,
37 meaning: Meaning::Plain,
38 variable: None,
39 comment: None,
40 }
41 }
42
43 pub fn with_meaning(mut self, meaning: Meaning) -> Self {
44 self.meaning = meaning;
45 self
46 }
47
48 pub fn set_meaning(&mut self, meaning: Meaning) {
49 self.meaning = meaning;
50 }
51
52 pub fn with_variable(mut self, variable: &str) -> Self {
53 self.variable = Some(String::from(variable));
54 self
55 }
56
57 pub fn set_variable(&mut self, variable: &str) {
58 self.variable = Some(String::from(variable));
59 }
60
61 pub fn with_comment(mut self, comment: &str) -> Self {
62 self.comment = Some(String::from(comment));
63 self
64 }
65
66 pub fn set_comment(&mut self, comment: &str) {
67 self.comment = Some(String::from(comment));
68 }
69
70 fn with_rounding(mut self) -> Self {
71 if let Some(number) = &self.number {
72 if let Some(multiplier) = Self::measure_multiplier(number) {
73 if let Some(number) = number.checked_mul(&multiplier) {
74 let number = number.round();
75 if let Some(number) = number.checked_div(&multiplier) {
76 self.number = Some(number);
77 }
78 }
79 }
80 }
81 self
82 }
83
84 fn measure_multiplier(number: &BigRational) -> Option<BigRational> {
85 let string = big_rational_str::big_rational_ref_to_string(number);
86 if let Some(period) = string.find('.') {
87 let string = remove_char(&string, period);
88 for offset in 1..=ROUNDING_LIMIT {
89 if let Some((start, count)) = Self::measure_offset(&string, offset) {
90 if let Some(start) = start.checked_sub(period) {
91 if let Some(remain) = string.len().checked_sub(start + count) {
92 if remain >= count * 2 {
93 let multiplier = BigInt::from(10)
94 .pow(start as u32);
95 let multiplier = BigInt::from(10)
96 .pow(offset as u32)
97 .sub(&BigInt::from(1))
98 .mul(&multiplier);
99 return Some(BigRational::from_integer(multiplier));
100 }
101 }
102 }
103 }
104 }
105 }
106 None
107 }
108
109 fn measure_offset(string: &str, offset: usize) -> Option<(usize, usize)> {
114 let left = string.chars();
115 let right = string.chars().skip(offset);
116 let mut span = None;
117 for (index, (left, right)) in zip(left, right).enumerate() {
118 if let Some((start, count)) = span {
119 if left == right {
120 span = Some((start, count + 1));
121 } else if count >= ROUNDING_LIMIT {
122 return span;
123 } else {
124 span = None;
125 }
126 } else {
127 if left == right {
128 span = Some((index, 0));
129 }
130 }
131 }
132 None
133 }
134
135 pub fn from_string(number: &str) -> MyResult<Self> {
136 if number.starts_with("0x") || number.starts_with("0X") {
137 Self::from_hexadecimal(&number[2..])
138 } else if let Some(value) = Self::from_time(number) {
139 Ok(value)
140 } else if let Some(value) = Self::from_delta(number) {
141 Ok(value)
142 } else if let Some(number) = number.strip_prefix(".") {
143 let number = format!("0.{}", number);
144 Self::from_decimal(&number)
145 } else if let Some(number) = number.strip_prefix("-.") {
146 let number = format!("-0.{}", number);
147 Self::from_decimal(&number)
148 } else {
149 Self::from_decimal(number)
150 }
151 }
152
153 fn from_time(time: &str) -> Option<Self> {
154 if let Some(time) = Self::parse_time(time) {
155 let numer = time.and_utc().timestamp_millis();
156 let numer = BigInt::from(numer);
157 let denom = BigInt::from(1000);
158 let number = BigRational::new(numer, denom);
159 let value = Self::new(Some(number)).with_meaning(Meaning::Time);
160 return Some(value);
161 }
162 None
163 }
164
165 fn parse_time(time: &str) -> Option<NaiveDateTime> {
166 let regex = regex!(r#"^(\d+-\d+-\d+T\d+:\d+(:\d+(\.\d+)?)?)Z?$"#);
167 if let Some(captures) = regex.captures(time) {
168 let time = captures.get(1).as_ref().map(Match::as_str).unwrap_or_default();
169 let format = if captures.get(2).is_none() {
170 "%Y-%m-%dT%H:%M"
171 } else if captures.get(3).is_none() {
172 "%Y-%m-%dT%H:%M:%S"
173 } else {
174 "%Y-%m-%dT%H:%M:%S%.f" };
176 return NaiveDateTime::parse_from_str(time, format).ok();
177 }
178 None
179 }
180
181 fn from_delta(delta: &str) -> Option<Self> {
182 if let Some(delta) = Self::parse_delta(delta) {
183 let numer = delta.num_milliseconds();
184 let numer = BigInt::from(numer);
185 let denom = BigInt::from(1000);
186 let number = BigRational::new(numer, denom);
187 let value = Self::new(Some(number)).with_meaning(Meaning::Delta);
188 return Some(value);
189 }
190 None
191 }
192
193 fn parse_delta(delta: &str) -> Option<Duration> {
194 let regex = regex!(r#"^(-)?(?:(?:(\d+)[T:])?(\d+):)?(\d+):(\d+)(?:\.(\d+))?$"#);
195 if let Some(captures) = regex.captures(delta) {
196 let negative = captures.get(1).is_some();
197 let days = Self::parse_capture(&captures, 2, None);
198 let hours = Self::parse_capture(&captures, 3, None) + (days * 24);
199 let minutes = Self::parse_capture(&captures, 4, None) + (hours * 60);
200 let seconds = Self::parse_capture(&captures, 5, None) + (minutes * 60);
201 let nanos = Self::parse_capture(&captures, 6, Some(9)) + (seconds * 1_000_000_000);
202 let delta = Duration::nanoseconds(nanos);
203 let delta = if negative { -delta } else { delta };
204 return Some(delta);
205 }
206 None
207 }
208
209 fn parse_capture(captures: &Captures, index: usize, expected: Option<usize>) -> i64 {
210 if let Some(capture) = captures.get(index) {
211 let number = capture.as_str().parse::<i64>().unwrap_or_default();
212 if let Some(expected) = expected {
213 let length = capture.as_str().len();
214 if let Some(diff) = expected.checked_sub(length) {
215 return number * pow(10, diff);
216 }
217 if let Some(diff) = length.checked_sub(expected) {
218 return number / pow(10, diff);
219 }
220 }
221 return number;
222 }
223 0
224 }
225
226 fn from_decimal(number: &str) -> MyResult<Self> {
227 let number = number.replace(&[',', '_'], "");
228 let number = BigRational::from_dec_str(&number)?;
229 let value = Self::new(Some(number));
230 Ok(value)
231 }
232
233 fn from_hexadecimal(number: &str) -> MyResult<Self> {
234 let number = number.replace(&[',', '_'], "");
235 let number = BigInt::from_str_radix(&number, 16)?;
236 let number = BigRational::from_integer(number);
237 let value = Self::new(Some(number));
238 Ok(value)
239 }
240
241 pub fn to_strings(&self, context: &Context) -> (String, String, Option<String>, Option<String>) {
242 if let Some(number) = &self.number {
243 self.format_ratio(context, number)
244 } else {
245 (String::from("NaN"), String::from(""), self.variable.clone(), self.comment.clone())
246 }
247 }
248
249 fn format_ratio(
250 &self,
251 context: &Context,
252 number: &BigRational,
253 ) -> (String, String, Option<String>, Option<String>) {
254 if self.meaning == Meaning::Time {
255 let number = number * BigInt::from(1000);
256 let number = number.to_i64().unwrap_or_default();
257 let number = Self::format_time(number);
258 self.format_split(context, number)
259 } else if self.meaning == Meaning::Delta {
260 let number = number * BigInt::from(1000);
261 let number = number.to_i64().unwrap_or_default();
262 let number = Self::format_delta(number);
263 self.format_split(context, number)
264 } else if let Format::Base16(chunks) = context.format {
265 let number = number.to_integer();
266 let number = Self::format_hexadecimal(number, chunks, context.sep);
267 (number, String::from(""), self.variable.clone(), self.comment.clone())
268 } else if let Some(dp) = context.dp {
269 let power = BigInt::from(10).pow(dp as u32);
270 let number = number.mul(&power).round().div(&power);
271 let number = big_rational_str::big_rational_to_string(number);
272 self.format_split(context, number)
273 } else {
274 let number = big_rational_str::big_rational_ref_to_string(number);
275 self.format_split(context, number)
276 }
277 }
278
279 fn format_time(millis: i64) -> String {
280 let time = DateTime::from_timestamp_millis(millis).unwrap_or_default();
281 time.format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string()
282 }
283
284 fn format_delta(millis: i64) -> String {
285 let (minus, millis) = (if millis < 0 { "-" } else { "" }, abs(millis));
286 let (seconds, millis) = (millis / 1000, millis % 1000);
287 let (minutes, seconds) = (seconds / 60, seconds % 60);
288 let (hours, minutes) = (minutes / 60, minutes % 60);
289 let (days, hours) = (hours / 24, hours % 24);
290 if days != 0 {
291 format!("{}{}T{:02}:{:02}:{:02}.{:03}", minus, days, hours, minutes, seconds, millis)
292 } else if hours != 0 {
293 format!("{}{:02}:{:02}:{:02}.{:03}", minus, hours, minutes, seconds, millis)
294 } else if minutes != 0 {
295 format!("{}{:02}:{:02}.{:03}", minus, minutes, seconds, millis)
296 } else {
297 format!("{}{:02}.{:03}", minus, seconds, millis)
298 }
299 }
300
301 fn format_hexadecimal(
302 mut number: BigInt,
303 chunks: usize,
304 sep: bool,
305 ) -> String {
306 if number.is_negative() {
307 let range = BigInt::from(CHUNK_VALUE).pow(chunks as u32);
308 number += range;
309 }
310 let number = format!("{:x}", number);
311 let padding = create_padding('0', chunks * CHUNK_DIGITS, number.len(), 0);
312 if sep {
313 let number = format!("{}{}", padding, number);
314 let chunks = number.as_bytes()
315 .chunks(CHUNK_DIGITS)
316 .map(std::str::from_utf8);
317 std::iter::once(Ok("0x"))
318 .chain(chunks)
319 .collect::<Result<Vec<&str>, _>>()
320 .unwrap_or_default()
321 .join(",")
322 } else {
323 format!("0x{}{}", padding, number)
324 }
325 }
326
327 fn format_split(
328 &self,
329 context: &Context,
330 number: String,
331 ) -> (String, String, Option<String>, Option<String>) {
332 let index = number.find('.').unwrap_or(number.len());
333 let (integer, fraction) = number.split_at(index);
334 let integer = self.modify_integer(context, integer);
335 let fraction = self.modify_fraction(context, fraction);
336 (integer, fraction, self.variable.clone(), self.comment.clone())
337 }
338
339 fn modify_integer(&self, context: &Context, number: &str) -> String {
340 if self.meaning == Meaning::Plain && context.sep {
341 let index = if number.starts_with('-') { 1 } else { 0 };
342 let (sign, number) = number.split_at(index);
343 let number = number.as_bytes()
344 .rchunks(3)
345 .rev()
346 .map(std::str::from_utf8)
347 .collect::<Result<Vec<&str>, _>>()
348 .unwrap_or_default()
349 .join(",");
350 return format!("{}{}", sign, number);
351 }
352 String::from(number)
353 }
354
355 fn modify_fraction(&self, context: &Context, number: &str) -> String {
356 if self.meaning == Meaning::Plain {
357 if let Some(dp) = context.dp {
358 if !number.is_empty() || dp > 0 {
359 let index = if number.starts_with('.') { 1 } else { 0 };
360 let number = &number[index..];
361 let dp = dp as usize;
362 return ".".chars()
363 .chain(number.chars().take(dp))
364 .chain(std::iter::repeat('0'))
365 .take(dp + 1)
366 .collect::<String>();
367 }
368 }
369 }
370 String::from(number)
371 }
372
373 pub fn measure_hexadecimal(&self) -> usize {
374 if let Some(number) = &self.number {
375 let number = number.to_integer();
376 Self::count_hexadecimal(number)
377 } else {
378 1
379 }
380 }
381
382 fn count_hexadecimal(mut number: BigInt) -> usize {
383 if number.is_negative() {
384 number = number.abs() - 1;
385 }
386 let count = number.iter_u32_digits().count().max(1);
387 let chunk = number.iter_u32_digits().last().unwrap_or_default();
388 if chunk & 0x80000000 != 0 { count + 1 } else { count }
389 }
390
391 fn perform_unary(
392 value: ValueRef,
393 meaning: Meaning,
394 function: fn(&BigRational) -> Option<BigRational>,
395 ) -> ValueRef {
396 if let Some(number) = &value.borrow().number {
397 let result = Self::new(function(number)).with_rounding().with_meaning(meaning);
398 return Rc::new(RefCell::new(result));
399 }
400 value
401 }
402
403 fn perform_binary(
404 lhs: ValueRef,
405 rhs: ValueRef,
406 meaning: Meaning,
407 function: fn(&BigRational, &BigRational) -> Option<BigRational>,
408 ) -> ValueRef {
409 if let Some(lhs) = &lhs.borrow().number {
410 if let Some(rhs) = &rhs.borrow().number {
411 let result = Self::new(function(lhs, rhs)).with_rounding().with_meaning(meaning);
412 return Rc::new(RefCell::new(result));
413 }
414 return rhs;
415 }
416 lhs
417 }
418
419 pub fn calc_add(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
426 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pdt, Meaning::ddt, Meaning::ttx)?;
427 let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_add(&y));
428 Ok(result)
429 }
430
431 pub fn calc_sub(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
438 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pdx, Meaning::ddx, Meaning::ttd)?;
439 let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_sub(&y));
440 Ok(result)
441 }
442
443 pub fn calc_mul(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
450 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pdx, Meaning::dxx, Meaning::xxx)?;
451 let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_mul(&y));
452 Ok(result)
453 }
454
455 pub fn calc_div(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
462 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::dxx, Meaning::xxx)?;
463 let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_div(&y));
464 Ok(result)
465 }
466
467 pub fn calc_mod(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
468 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::dxx, Meaning::xxx)?;
469 let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_mod);
470 Ok(result)
471 }
472
473 fn checked_mod(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
474 lhs.checked_div(rhs)
475 .map(|result| &result - result.to_integer())
476 .map(|result| result * rhs)
477 }
478
479 pub fn calc_neg(value: ValueRef) -> MyResult<ValueRef> {
484 let meaning = value.borrow().meaning.pdx()?;
485 let result = Self::perform_unary(value, meaning, |x| Some(-x));
486 Ok(result)
487 }
488
489 pub fn calc_inv(value: ValueRef) -> MyResult<ValueRef> {
494 let meaning = value.borrow().meaning.pxx()?;
495 let result = Self::perform_unary(value, meaning, Self::checked_inv);
496 Ok(result)
497 }
498
499 fn checked_inv(number: &BigRational) -> Option<BigRational> {
500 if number.is_zero() { None } else { Some(number.inv()) }
501 }
502
503 pub fn calc_pow(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
510 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
511 let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_pow);
512 Ok(result)
513 }
514
515 fn checked_pow(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
516 if rhs.is_integer() {
517 if let Some(rhs) = rhs.to_i32() {
518 return Some(lhs.pow(rhs));
519 }
520 } else {
521 if let Some(lhs) = lhs.to_f64() {
522 if let Some(rhs) = rhs.to_f64() {
523 let result = f64::powf(lhs, rhs);
524 return BigRational::from_f64(result);
525 }
526 }
527 }
528 None
529 }
530
531 pub fn calc_sqrt(value: ValueRef) -> MyResult<ValueRef> {
536 let meaning = value.borrow().meaning.pxx()?;
537 let result = Self::perform_unary(value, meaning, Self::checked_sqrt);
538 Ok(result)
539 }
540
541 fn checked_sqrt(number: &BigRational) -> Option<BigRational> {
542 if let Some(number) = number.to_f64() {
543 let result = number.sqrt();
544 return BigRational::from_f64(result);
545 }
546 None
547 }
548
549 pub fn calc_sum(values: Vec<ValueRef>) -> MyResult<ValueRef> {
550 let mut result = BigRational::from(BigInt::zero());
551 for value in values {
552 if let Some(number) = &value.borrow().number {
553 result += number;
554 }
555 }
556 let result = Self::new(Some(result)).with_rounding();
557 Ok(Rc::new(RefCell::new(result)))
558 }
559
560 pub fn calc_prod(values: Vec<ValueRef>) -> MyResult<ValueRef> {
561 let mut result = BigRational::from(BigInt::one());
562 for value in values {
563 if let Some(number) = &value.borrow().number {
564 result *= number;
565 }
566 }
567 let result = Self::new(Some(result)).with_rounding();
568 Ok(Rc::new(RefCell::new(result)))
569 }
570
571 pub fn calc_and(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
578 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
579 let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_and);
580 Ok(result)
581 }
582
583 pub fn calc_or(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
584 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
585 let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_or);
586 Ok(result)
587 }
588
589 pub fn calc_xor(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
590 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
591 let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_xor);
592 Ok(result)
593 }
594
595 fn checked_and(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
596 let lhs = lhs.to_integer();
597 let rhs = rhs.to_integer();
598 let result = lhs.bitand(rhs);
599 Some(BigRational::from(result))
600 }
601
602 fn checked_or(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
603 let lhs = lhs.to_integer();
604 let rhs = rhs.to_integer();
605 let result = lhs.bitor(rhs);
606 Some(BigRational::from(result))
607 }
608
609 fn checked_xor(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
610 let lhs = lhs.to_integer();
611 let rhs = rhs.to_integer();
612 let result = lhs.bitxor(rhs);
613 Some(BigRational::from(result))
614 }
615
616 pub fn calc_shl(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
617 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
618 let result = Self::perform_binary(lhs, rhs, meaning, |x, y| Self::checked_shl(x, y));
619 Ok(result)
620 }
621
622 pub fn calc_shr(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
623 let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
624 let result = Self::perform_binary(lhs, rhs, meaning, |x, y| Self::checked_shr(x, y));
625 Ok(result)
626 }
627
628 fn checked_shl(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
629 if let Some(rhs) = rhs.to_i32() {
630 let two = BigRational::new(BigInt::from(2), BigInt::from(1));
631 Some(lhs * two.pow(rhs))
632 } else {
633 None
634 }
635 }
636
637 fn checked_shr(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
638 if let Some(rhs) = rhs.to_i32() {
639 let two = BigRational::new(BigInt::from(2), BigInt::from(1));
640 Some(lhs * two.pow(-rhs))
641 } else {
642 None
643 }
644 }
645
646 pub fn calc_now(time: &Option<SystemTime>) -> MyResult<ValueRef> {
647 let time = time.unwrap_or_else(SystemTime::now)
648 .duration_since(SystemTime::UNIX_EPOCH)
649 .unwrap_or_default()
650 .as_millis();
651 let numer = BigInt::from(time);
652 let denom = BigInt::from(1000);
653 let number = BigRational::new(numer, denom);
654 let result = Self::new(Some(number)).with_meaning(Meaning::Time);
655 Ok(Rc::new(RefCell::new(result)))
656 }
657
658 pub fn cast_plain(value: ValueRef) -> MyResult<()> {
659 value.borrow_mut().set_meaning(Meaning::Plain);
660 Ok(())
661 }
662
663 pub fn cast_delta(value: ValueRef) -> MyResult<()> {
664 value.borrow_mut().set_meaning(Meaning::Delta);
665 Ok(())
666 }
667
668 pub fn cast_time(value: ValueRef) -> MyResult<()> {
669 value.borrow_mut().set_meaning(Meaning::Time);
670 Ok(())
671 }
672}
673
674impl Default for Value {
675 fn default() -> Self {
676 Self::new(Some(BigRational::zero()))
677 }
678}
679
680impl Clone for Value {
681 fn clone(&self) -> Self {
682 let number = self.number.clone();
684 let mut value = Self::new(number);
685 value.meaning = self.meaning;
686 value.comment = self.comment.clone();
687 value
688 }
689}
690
691impl Debug for Value {
692 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
693 if let Some(number) = &self.number {
694 write!(f, "{}", big_rational_str::big_rational_ref_to_string(number))?;
695 } else {
696 write!(f, "NaN")?;
697 }
698 match self.meaning {
699 Meaning::Plain => (),
700 Meaning::Delta => write!(f, " [delta]")?,
701 Meaning::Time => write!(f, " [time]")?,
702 }
703 if let Some(variable) = &self.variable {
704 write!(f, " = {}", variable)?;
705 }
706 if let Some(comment) = &self.comment {
707 write!(f, " # {}", comment)?;
708 }
709 Ok(())
710 }
711}
712
713#[cfg(test)]
714pub mod tests {
715 use crate::calc::context::{Context, Format};
716 use crate::calc::meaning::Meaning;
717 use crate::calc::value::{Value, ValueRef};
718 use crate::error::{EngineError, MyError, MyResult};
719 use crate::regex;
720 use num::{BigInt, BigRational, CheckedMul, CheckedSub, FromPrimitive, ToPrimitive};
721 use pretty_assertions::assert_eq;
722 use regex::Match;
723 use std::cell::RefCell;
724 use std::rc::Rc;
725
726 const VALUE_NAN: Value = Value::new(None);
727
728 #[test]
729 fn test_decimal_is_created_from_string_no_separator() {
730 assert_eq!(create_value(0, 1), Value::from_string("0").unwrap());
731 assert_eq!(create_value(123456789, 1), Value::from_string("123456789").unwrap());
732 assert_eq!(create_value(-123456789, 1), Value::from_string("-123456789").unwrap());
733 assert_eq!(create_value(123456789, 100), Value::from_string("1234567.89").unwrap());
734 assert_eq!(create_value(-123456789, 100), Value::from_string("-1234567.89").unwrap());
735 assert_eq!(create_value(999, 1000), Value::from_string(".999").unwrap());
736 assert_eq!(create_value(-999, 1000), Value::from_string("-.999").unwrap());
737 assert!(Value::from_string("").is_err());
738 assert!(Value::from_string("foo").is_err());
739 }
740
741 #[test]
742 fn test_decimal_is_created_from_string_with_separator() {
743 assert_eq!(create_value(123456789, 1), Value::from_string("123,456,789").unwrap());
744 assert_eq!(create_value(123456789, 1), Value::from_string("123_456_789").unwrap());
745 assert_eq!(create_value(-123456789, 1), Value::from_string("-123,456,789").unwrap());
746 assert_eq!(create_value(-123456789, 1), Value::from_string("-123_456_789").unwrap());
747 assert_eq!(create_value(123456789, 100), Value::from_string("1,234,567.89").unwrap());
748 assert_eq!(create_value(123456789, 100), Value::from_string("1_234_567.89").unwrap());
749 assert_eq!(create_value(-123456789, 100), Value::from_string("-1,234,567.89").unwrap());
750 assert_eq!(create_value(-123456789, 100), Value::from_string("-1_234_567.89").unwrap());
751 }
752
753 #[test]
754 fn test_hexadecimal_is_created_from_lowercase_no_separator() {
755 assert_eq!(create_value(0, 1), Value::from_string("0x0").unwrap());
756 assert_eq!(create_value(0xffff, 1), Value::from_string("0xffff").unwrap());
757 assert_eq!(create_value(0xffffffff, 1), Value::from_string("0xffffffff").unwrap());
758 assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0xffffffffffff").unwrap());
759 assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0x0123456789abcdef").unwrap());
760 assert!(Value::from_string("0x").is_err());
761 assert!(Value::from_string("0xfoo").is_err());
762 }
763
764 #[test]
765 fn test_hexadecimal_is_created_from_uppercase_no_separator() {
766 assert_eq!(create_value(0, 1), Value::from_string("0X0").unwrap());
767 assert_eq!(create_value(0xffff, 1), Value::from_string("0XFFFF").unwrap());
768 assert_eq!(create_value(0xffffffff, 1), Value::from_string("0XFFFFFFFF").unwrap());
769 assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0XFFFFFFFFFFFF").unwrap());
770 assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0X0123456789ABCDEF").unwrap());
771 assert!(Value::from_string("0X").is_err());
772 assert!(Value::from_string("0XFOO").is_err());
773 }
774
775 #[test]
776 fn test_hexadecimal_is_created_from_lowercase_with_separator() {
777 assert_eq!(create_value(0, 1), Value::from_string("0x_0").unwrap());
778 assert_eq!(create_value(0xffff, 1), Value::from_string("0x_ffff").unwrap());
779 assert_eq!(create_value(0xffffffff, 1), Value::from_string("0x_ffff_ffff").unwrap());
780 assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0x,ffff,ffff,ffff").unwrap());
781 assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0x,0123,4567,89ab,cdef").unwrap());
782 assert!(Value::from_string("0x_").is_err());
783 assert!(Value::from_string("0x,foo").is_err());
784 }
785
786 #[test]
787 fn test_hexadecimal_is_created_from_uppercase_with_separator() {
788 assert_eq!(create_value(0, 1), Value::from_string("0X_0").unwrap());
789 assert_eq!(create_value(0xffff, 1), Value::from_string("0X_FFFF").unwrap());
790 assert_eq!(create_value(0xffffffff, 1), Value::from_string("0X_FFFF_FFFF").unwrap());
791 assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0X,FFFF,FFFF,FFFF").unwrap());
792 assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0X,0123,4567,89AB,CDEF").unwrap());
793 assert!(Value::from_string("0X_").is_err());
794 assert!(Value::from_string("0X,FOO").is_err());
795 }
796
797 #[test]
798 fn test_time_is_created_from_string_no_zulu() {
799 let summer1 = Value::from_string("2024-06-30T23:59").unwrap();
800 let summer2 = Value::from_string("2024-06-30T23:59:59").unwrap();
801 let summer3 = Value::from_string("2024-06-30T23:59:59.999").unwrap();
802 let winter1 = Value::from_string("2024-12-31T23:59").unwrap();
803 let winter2 = Value::from_string("2024-12-31T23:59:59").unwrap();
804 let winter3 = Value::from_string("2024-12-31T23:59:59.999").unwrap();
805 assert_eq!(create_value(1719791940000, 1000).with_meaning(Meaning::Time), summer1);
806 assert_eq!(create_value(1719791999000, 1000).with_meaning(Meaning::Time), summer2);
807 assert_eq!(create_value(1719791999999, 1000).with_meaning(Meaning::Time), summer3);
808 assert_eq!(create_value(1735689540000, 1000).with_meaning(Meaning::Time), winter1);
809 assert_eq!(create_value(1735689599000, 1000).with_meaning(Meaning::Time), winter2);
810 assert_eq!(create_value(1735689599999, 1000).with_meaning(Meaning::Time), winter3);
811 }
812
813 #[test]
814 fn test_time_is_created_from_string_with_zulu() {
815 let summer1 = Value::from_string("2024-06-30T23:59Z").unwrap();
816 let summer2 = Value::from_string("2024-06-30T23:59:59Z").unwrap();
817 let summer3 = Value::from_string("2024-06-30T23:59:59.999Z").unwrap();
818 let winter1 = Value::from_string("2024-12-31T23:59Z").unwrap();
819 let winter2 = Value::from_string("2024-12-31T23:59:59Z").unwrap();
820 let winter3 = Value::from_string("2024-12-31T23:59:59.999Z").unwrap();
821 assert_eq!(create_value(1719791940000, 1000).with_meaning(Meaning::Time), summer1);
822 assert_eq!(create_value(1719791999000, 1000).with_meaning(Meaning::Time), summer2);
823 assert_eq!(create_value(1719791999999, 1000).with_meaning(Meaning::Time), summer3);
824 assert_eq!(create_value(1735689540000, 1000).with_meaning(Meaning::Time), winter1);
825 assert_eq!(create_value(1735689599000, 1000).with_meaning(Meaning::Time), winter2);
826 assert_eq!(create_value(1735689599999, 1000).with_meaning(Meaning::Time), winter3);
827 }
828
829 #[test]
830 fn test_delta_is_created_from_string_old_format() {
831 let minutes1 = Value::from_string("34:56").unwrap();
832 let minutes2 = Value::from_string("34:56.7").unwrap();
833 let minutes3 = Value::from_string("34:56.789").unwrap();
834 let minutes4 = Value::from_string("-34:56").unwrap();
835 let minutes5 = Value::from_string("-34:56.7").unwrap();
836 let minutes6 = Value::from_string("-34:56.789").unwrap();
837 let hours1 = Value::from_string("12:34:56").unwrap();
838 let hours2 = Value::from_string("12:34:56.7").unwrap();
839 let hours3 = Value::from_string("12:34:56.789").unwrap();
840 let hours4 = Value::from_string("-12:34:56").unwrap();
841 let hours5 = Value::from_string("-12:34:56.7").unwrap();
842 let hours6 = Value::from_string("-12:34:56.789").unwrap();
843 let days1 = Value::from_string("9:12:34:56").unwrap();
844 let days2 = Value::from_string("9:12:34:56.7").unwrap();
845 let days3 = Value::from_string("9:12:34:56.789").unwrap();
846 let days4 = Value::from_string("-9:12:34:56").unwrap();
847 let days5 = Value::from_string("-9:12:34:56.7").unwrap();
848 let days6 = Value::from_string("-9:12:34:56.789").unwrap();
849 assert_eq!(create_value(2096000, 1000).with_meaning(Meaning::Delta), minutes1);
850 assert_eq!(create_value(2096700, 1000).with_meaning(Meaning::Delta), minutes2);
851 assert_eq!(create_value(2096789, 1000).with_meaning(Meaning::Delta), minutes3);
852 assert_eq!(create_value(-2096000, 1000).with_meaning(Meaning::Delta), minutes4);
853 assert_eq!(create_value(-2096700, 1000).with_meaning(Meaning::Delta), minutes5);
854 assert_eq!(create_value(-2096789, 1000).with_meaning(Meaning::Delta), minutes6);
855 assert_eq!(create_value(45296000, 1000).with_meaning(Meaning::Delta), hours1);
856 assert_eq!(create_value(45296700, 1000).with_meaning(Meaning::Delta), hours2);
857 assert_eq!(create_value(45296789, 1000).with_meaning(Meaning::Delta), hours3);
858 assert_eq!(create_value(-45296000, 1000).with_meaning(Meaning::Delta), hours4);
859 assert_eq!(create_value(-45296700, 1000).with_meaning(Meaning::Delta), hours5);
860 assert_eq!(create_value(-45296789, 1000).with_meaning(Meaning::Delta), hours6);
861 assert_eq!(create_value(822896000, 1000).with_meaning(Meaning::Delta), days1);
862 assert_eq!(create_value(822896700, 1000).with_meaning(Meaning::Delta), days2);
863 assert_eq!(create_value(822896789, 1000).with_meaning(Meaning::Delta), days3);
864 assert_eq!(create_value(-822896000, 1000).with_meaning(Meaning::Delta), days4);
865 assert_eq!(create_value(-822896700, 1000).with_meaning(Meaning::Delta), days5);
866 assert_eq!(create_value(-822896789, 1000).with_meaning(Meaning::Delta), days6);
867 }
868
869 #[test]
870 fn test_delta_is_created_from_string_new_format() {
871 let days1 = Value::from_string("9T12:34:56").unwrap();
872 let days2 = Value::from_string("9T12:34:56.7").unwrap();
873 let days3 = Value::from_string("9T12:34:56.789").unwrap();
874 let days4 = Value::from_string("-9T12:34:56").unwrap();
875 let days5 = Value::from_string("-9T12:34:56.7").unwrap();
876 let days6 = Value::from_string("-9T12:34:56.789").unwrap();
877 assert_eq!(create_value(822896000, 1000).with_meaning(Meaning::Delta), days1);
878 assert_eq!(create_value(822896700, 1000).with_meaning(Meaning::Delta), days2);
879 assert_eq!(create_value(822896789, 1000).with_meaning(Meaning::Delta), days3);
880 assert_eq!(create_value(-822896000, 1000).with_meaning(Meaning::Delta), days4);
881 assert_eq!(create_value(-822896700, 1000).with_meaning(Meaning::Delta), days5);
882 assert_eq!(create_value(-822896789, 1000).with_meaning(Meaning::Delta), days6);
883 }
884
885 #[test]
886 fn test_value_with_repeating_zero_or_nine_is_rounded() {
887 let number1 = fudge_ratio(create_ratio(17, 8)).and_then(opposite_ratio); let number2 = fudge_ratio(create_ratio(16, 8)).and_then(opposite_ratio); let number3 = fudge_ratio(create_ratio(16, 8)); let number4 = fudge_ratio(create_ratio(17, 8)); assert_eq!(create_value(15, 8), Value::new(number1).with_rounding());
892 assert_eq!(create_value(16, 8), Value::new(number2).with_rounding());
893 assert_eq!(create_value(16, 8), Value::new(number3).with_rounding());
894 assert_eq!(create_value(17, 8), Value::new(number4).with_rounding());
895 }
896
897 #[test]
898 fn test_value_with_repeating_one_to_eight_is_rounded() {
899 let number1 = fudge_ratio(create_ratio(908992, 9000)); let number2 = fudge_ratio(create_ratio(1088924, 99000)); let number3 = fudge_ratio(create_ratio(1997457, 999000)); let number4 = fudge_ratio(create_ratio(19995891, 9999000)); assert_eq!(create_value(908992, 9000), Value::new(number1).with_rounding());
904 assert_eq!(create_value(1088924, 99000), Value::new(number2).with_rounding());
905 assert_eq!(create_value(1997457, 999000), Value::new(number3).with_rounding());
906 assert_eq!(create_value(19995891, 9999000), Value::new(number4).with_rounding());
907 }
908
909 #[test]
910 fn test_decimal_is_formatted_with_default() {
911 let context = Context::new();
912 assert_eq!((String::from("0"), String::from(""), None, None), create_value(0, 1).to_strings(&context));
913 assert_eq!((String::from("1"), String::from(""), None, None), create_value(1, 1).to_strings(&context));
914 assert_eq!((String::from("12"), String::from(""), None, None), create_value(12, 1).to_strings(&context));
915 assert_eq!((String::from("123"), String::from(""), None, None), create_value(123, 1).to_strings(&context));
916 assert_eq!((String::from("1234"), String::from(""), None, None), create_value(1234, 1).to_strings(&context));
917 assert_eq!((String::from("12345"), String::from(""), None, None), create_value(12345, 1).to_strings(&context));
918 assert_eq!((String::from("123456"), String::from(""), None, None), create_value(123456, 1).to_strings(&context));
919 assert_eq!((String::from("1234567"), String::from(""), None, None), create_value(1234567, 1).to_strings(&context));
920 assert_eq!((String::from("12345678"), String::from(""), None, None), create_value(12345678, 1).to_strings(&context));
921 assert_eq!((String::from("123456789"), String::from(""), None, None), create_value(123456789, 1).to_strings(&context));
922 assert_eq!((String::from("-1"), String::from(""), None, None), create_value(-1, 1).to_strings(&context));
923 assert_eq!((String::from("-12"), String::from(""), None, None), create_value(-12, 1).to_strings(&context));
924 assert_eq!((String::from("-123"), String::from(""), None, None), create_value(-123, 1).to_strings(&context));
925 assert_eq!((String::from("-1234"), String::from(""), None, None), create_value(-1234, 1).to_strings(&context));
926 assert_eq!((String::from("-12345"), String::from(""), None, None), create_value(-12345, 1).to_strings(&context));
927 assert_eq!((String::from("-123456"), String::from(""), None, None), create_value(-123456, 1).to_strings(&context));
928 assert_eq!((String::from("-1234567"), String::from(""), None, None), create_value(-1234567, 1).to_strings(&context));
929 assert_eq!((String::from("-12345678"), String::from(""), None, None), create_value(-12345678, 1).to_strings(&context));
930 assert_eq!((String::from("-123456789"), String::from(""), None, None), create_value(-123456789, 1).to_strings(&context));
931 assert_eq!((String::from("0"), String::from(".00001"), None, None), create_value(1, 100000).to_strings(&context));
932 assert_eq!((String::from("0"), String::from(".0001"), None, None), create_value(1, 10000).to_strings(&context));
933 assert_eq!((String::from("0"), String::from(".001"), None, None), create_value(1, 1000).to_strings(&context));
934 assert_eq!((String::from("0"), String::from(".01"), None, None), create_value(1, 100).to_strings(&context));
935 assert_eq!((String::from("0"), String::from(".1"), None, None), create_value(1, 10).to_strings(&context));
936 assert_eq!((String::from("0"), String::from(".4994"), None, None), create_value(49940, 100000).to_strings(&context));
937 assert_eq!((String::from("0"), String::from(".49949"), None, None), create_value(49949, 100000).to_strings(&context));
938 assert_eq!((String::from("0"), String::from(".4995"), None, None), create_value(49950, 100000).to_strings(&context));
939 assert_eq!((String::from("0"), String::from(".49951"), None, None), create_value(49951, 100000).to_strings(&context));
940 assert_eq!((String::from("0"), String::from(".9"), None, None), create_value(9, 10).to_strings(&context));
941 assert_eq!((String::from("0"), String::from(".99"), None, None), create_value(99, 100).to_strings(&context));
942 assert_eq!((String::from("0"), String::from(".999"), None, None), create_value(999, 1000).to_strings(&context));
943 assert_eq!((String::from("0"), String::from(".9999"), None, None), create_value(9999, 10000).to_strings(&context));
944 assert_eq!((String::from("0"), String::from(".99999"), None, None), create_value(99999, 100000).to_strings(&context));
945 assert_eq!((String::from("-0"), String::from(".00001"), None, None), create_value(-1, 100000).to_strings(&context));
946 assert_eq!((String::from("-0"), String::from(".0001"), None, None), create_value(-1, 10000).to_strings(&context));
947 assert_eq!((String::from("-0"), String::from(".001"), None, None), create_value(-1, 1000).to_strings(&context));
948 assert_eq!((String::from("-0"), String::from(".01"), None, None), create_value(-1, 100).to_strings(&context));
949 assert_eq!((String::from("-0"), String::from(".1"), None, None), create_value(-1, 10).to_strings(&context));
950 assert_eq!((String::from("-0"), String::from(".4994"), None, None), create_value(-49940, 100000).to_strings(&context));
951 assert_eq!((String::from("-0"), String::from(".49949"), None, None), create_value(-49949, 100000).to_strings(&context));
952 assert_eq!((String::from("-0"), String::from(".4995"), None, None), create_value(-49950, 100000).to_strings(&context));
953 assert_eq!((String::from("-0"), String::from(".49951"), None, None), create_value(-49951, 100000).to_strings(&context));
954 assert_eq!((String::from("-0"), String::from(".9"), None, None), create_value(-9, 10).to_strings(&context));
955 assert_eq!((String::from("-0"), String::from(".99"), None, None), create_value(-99, 100).to_strings(&context));
956 assert_eq!((String::from("-0"), String::from(".999"), None, None), create_value(-999, 1000).to_strings(&context));
957 assert_eq!((String::from("-0"), String::from(".9999"), None, None), create_value(-9999, 10000).to_strings(&context));
958 assert_eq!((String::from("-0"), String::from(".99999"), None, None), create_value(-99999, 100000).to_strings(&context));
959 }
960
961 #[test]
962 fn test_decimal_is_formatted_with_separator() {
963 let context = Context::new().with_sep(true);
964 assert_eq!((String::from("0"), String::from(""), None, None), create_value(0, 1).to_strings(&context));
965 assert_eq!((String::from("1"), String::from(""), None, None), create_value(1, 1).to_strings(&context));
966 assert_eq!((String::from("12"), String::from(""), None, None), create_value(12, 1).to_strings(&context));
967 assert_eq!((String::from("123"), String::from(""), None, None), create_value(123, 1).to_strings(&context));
968 assert_eq!((String::from("1,234"), String::from(""), None, None), create_value(1234, 1).to_strings(&context));
969 assert_eq!((String::from("12,345"), String::from(""), None, None), create_value(12345, 1).to_strings(&context));
970 assert_eq!((String::from("123,456"), String::from(""), None, None), create_value(123456, 1).to_strings(&context));
971 assert_eq!((String::from("1,234,567"), String::from(""), None, None), create_value(1234567, 1).to_strings(&context));
972 assert_eq!((String::from("12,345,678"), String::from(""), None, None), create_value(12345678, 1).to_strings(&context));
973 assert_eq!((String::from("123,456,789"), String::from(""), None, None), create_value(123456789, 1).to_strings(&context));
974 assert_eq!((String::from("-1"), String::from(""), None, None), create_value(-1, 1).to_strings(&context));
975 assert_eq!((String::from("-12"), String::from(""), None, None), create_value(-12, 1).to_strings(&context));
976 assert_eq!((String::from("-123"), String::from(""), None, None), create_value(-123, 1).to_strings(&context));
977 assert_eq!((String::from("-1,234"), String::from(""), None, None), create_value(-1234, 1).to_strings(&context));
978 assert_eq!((String::from("-12,345"), String::from(""), None, None), create_value(-12345, 1).to_strings(&context));
979 assert_eq!((String::from("-123,456"), String::from(""), None, None), create_value(-123456, 1).to_strings(&context));
980 assert_eq!((String::from("-1,234,567"), String::from(""), None, None), create_value(-1234567, 1).to_strings(&context));
981 assert_eq!((String::from("-12,345,678"), String::from(""), None, None), create_value(-12345678, 1).to_strings(&context));
982 assert_eq!((String::from("-123,456,789"), String::from(""), None, None), create_value(-123456789, 1).to_strings(&context));
983 assert_eq!((String::from("0"), String::from(".00001"), None, None), create_value(1, 100000).to_strings(&context));
984 assert_eq!((String::from("0"), String::from(".0001"), None, None), create_value(1, 10000).to_strings(&context));
985 assert_eq!((String::from("0"), String::from(".001"), None, None), create_value(1, 1000).to_strings(&context));
986 assert_eq!((String::from("0"), String::from(".01"), None, None), create_value(1, 100).to_strings(&context));
987 assert_eq!((String::from("0"), String::from(".1"), None, None), create_value(1, 10).to_strings(&context));
988 assert_eq!((String::from("0"), String::from(".4994"), None, None), create_value(49940, 100000).to_strings(&context));
989 assert_eq!((String::from("0"), String::from(".49949"), None, None), create_value(49949, 100000).to_strings(&context));
990 assert_eq!((String::from("0"), String::from(".4995"), None, None), create_value(49950, 100000).to_strings(&context));
991 assert_eq!((String::from("0"), String::from(".49951"), None, None), create_value(49951, 100000).to_strings(&context));
992 assert_eq!((String::from("0"), String::from(".9"), None, None), create_value(9, 10).to_strings(&context));
993 assert_eq!((String::from("0"), String::from(".99"), None, None), create_value(99, 100).to_strings(&context));
994 assert_eq!((String::from("0"), String::from(".999"), None, None), create_value(999, 1000).to_strings(&context));
995 assert_eq!((String::from("0"), String::from(".9999"), None, None), create_value(9999, 10000).to_strings(&context));
996 assert_eq!((String::from("0"), String::from(".99999"), None, None), create_value(99999, 100000).to_strings(&context));
997 assert_eq!((String::from("-0"), String::from(".00001"), None, None), create_value(-1, 100000).to_strings(&context));
998 assert_eq!((String::from("-0"), String::from(".0001"), None, None), create_value(-1, 10000).to_strings(&context));
999 assert_eq!((String::from("-0"), String::from(".001"), None, None), create_value(-1, 1000).to_strings(&context));
1000 assert_eq!((String::from("-0"), String::from(".01"), None, None), create_value(-1, 100).to_strings(&context));
1001 assert_eq!((String::from("-0"), String::from(".1"), None, None), create_value(-1, 10).to_strings(&context));
1002 assert_eq!((String::from("-0"), String::from(".4994"), None, None), create_value(-49940, 100000).to_strings(&context));
1003 assert_eq!((String::from("-0"), String::from(".49949"), None, None), create_value(-49949, 100000).to_strings(&context));
1004 assert_eq!((String::from("-0"), String::from(".4995"), None, None), create_value(-49950, 100000).to_strings(&context));
1005 assert_eq!((String::from("-0"), String::from(".49951"), None, None), create_value(-49951, 100000).to_strings(&context));
1006 assert_eq!((String::from("-0"), String::from(".9"), None, None), create_value(-9, 10).to_strings(&context));
1007 assert_eq!((String::from("-0"), String::from(".99"), None, None), create_value(-99, 100).to_strings(&context));
1008 assert_eq!((String::from("-0"), String::from(".999"), None, None), create_value(-999, 1000).to_strings(&context));
1009 assert_eq!((String::from("-0"), String::from(".9999"), None, None), create_value(-9999, 10000).to_strings(&context));
1010 assert_eq!((String::from("-0"), String::from(".99999"), None, None), create_value(-99999, 100000).to_strings(&context));
1011 }
1012
1013 #[test]
1014 fn test_decimal_is_formatted_with_precision() {
1015 let context = Context::new().with_dp(Some(3));
1016 assert_eq!((String::from("0"), String::from(".000"), None, None), create_value(0, 1).to_strings(&context));
1017 assert_eq!((String::from("1"), String::from(".000"), None, None), create_value(1, 1).to_strings(&context));
1018 assert_eq!((String::from("12"), String::from(".000"), None, None), create_value(12, 1).to_strings(&context));
1019 assert_eq!((String::from("123"), String::from(".000"), None, None), create_value(123, 1).to_strings(&context));
1020 assert_eq!((String::from("1234"), String::from(".000"), None, None), create_value(1234, 1).to_strings(&context));
1021 assert_eq!((String::from("12345"), String::from(".000"), None, None), create_value(12345, 1).to_strings(&context));
1022 assert_eq!((String::from("123456"), String::from(".000"), None, None), create_value(123456, 1).to_strings(&context));
1023 assert_eq!((String::from("1234567"), String::from(".000"), None, None), create_value(1234567, 1).to_strings(&context));
1024 assert_eq!((String::from("12345678"), String::from(".000"), None, None), create_value(12345678, 1).to_strings(&context));
1025 assert_eq!((String::from("123456789"), String::from(".000"), None, None), create_value(123456789, 1).to_strings(&context));
1026 assert_eq!((String::from("-1"), String::from(".000"), None, None), create_value(-1, 1).to_strings(&context));
1027 assert_eq!((String::from("-12"), String::from(".000"), None, None), create_value(-12, 1).to_strings(&context));
1028 assert_eq!((String::from("-123"), String::from(".000"), None, None), create_value(-123, 1).to_strings(&context));
1029 assert_eq!((String::from("-1234"), String::from(".000"), None, None), create_value(-1234, 1).to_strings(&context));
1030 assert_eq!((String::from("-12345"), String::from(".000"), None, None), create_value(-12345, 1).to_strings(&context));
1031 assert_eq!((String::from("-123456"), String::from(".000"), None, None), create_value(-123456, 1).to_strings(&context));
1032 assert_eq!((String::from("-1234567"), String::from(".000"), None, None), create_value(-1234567, 1).to_strings(&context));
1033 assert_eq!((String::from("-12345678"), String::from(".000"), None, None), create_value(-12345678, 1).to_strings(&context));
1034 assert_eq!((String::from("-123456789"), String::from(".000"), None, None), create_value(-123456789, 1).to_strings(&context));
1035 assert_eq!((String::from("0"), String::from(".000"), None, None), create_value(1, 100000).to_strings(&context));
1036 assert_eq!((String::from("0"), String::from(".000"), None, None), create_value(1, 10000).to_strings(&context));
1037 assert_eq!((String::from("0"), String::from(".001"), None, None), create_value(1, 1000).to_strings(&context));
1038 assert_eq!((String::from("0"), String::from(".010"), None, None), create_value(1, 100).to_strings(&context));
1039 assert_eq!((String::from("0"), String::from(".100"), None, None), create_value(1, 10).to_strings(&context));
1040 assert_eq!((String::from("0"), String::from(".499"), None, None), create_value(49940, 100000).to_strings(&context));
1041 assert_eq!((String::from("0"), String::from(".499"), None, None), create_value(49949, 100000).to_strings(&context));
1042 assert_eq!((String::from("0"), String::from(".500"), None, None), create_value(49950, 100000).to_strings(&context));
1043 assert_eq!((String::from("0"), String::from(".500"), None, None), create_value(49951, 100000).to_strings(&context));
1044 assert_eq!((String::from("0"), String::from(".900"), None, None), create_value(9, 10).to_strings(&context));
1045 assert_eq!((String::from("0"), String::from(".990"), None, None), create_value(99, 100).to_strings(&context));
1046 assert_eq!((String::from("0"), String::from(".999"), None, None), create_value(999, 1000).to_strings(&context));
1047 assert_eq!((String::from("1"), String::from(".000"), None, None), create_value(9999, 10000).to_strings(&context));
1048 assert_eq!((String::from("1"), String::from(".000"), None, None), create_value(99999, 100000).to_strings(&context));
1049 assert_eq!((String::from("0"), String::from(".000"), None, None), create_value(-1, 100000).to_strings(&context));
1050 assert_eq!((String::from("0"), String::from(".000"), None, None), create_value(-1, 10000).to_strings(&context));
1051 assert_eq!((String::from("-0"), String::from(".001"), None, None), create_value(-1, 1000).to_strings(&context));
1052 assert_eq!((String::from("-0"), String::from(".010"), None, None), create_value(-1, 100).to_strings(&context));
1053 assert_eq!((String::from("-0"), String::from(".100"), None, None), create_value(-1, 10).to_strings(&context));
1054 assert_eq!((String::from("-0"), String::from(".499"), None, None), create_value(-49940, 100000).to_strings(&context));
1055 assert_eq!((String::from("-0"), String::from(".499"), None, None), create_value(-49949, 100000).to_strings(&context));
1056 assert_eq!((String::from("-0"), String::from(".500"), None, None), create_value(-49950, 100000).to_strings(&context));
1057 assert_eq!((String::from("-0"), String::from(".500"), None, None), create_value(-49951, 100000).to_strings(&context));
1058 assert_eq!((String::from("-0"), String::from(".900"), None, None), create_value(-9, 10).to_strings(&context));
1059 assert_eq!((String::from("-0"), String::from(".990"), None, None), create_value(-99, 100).to_strings(&context));
1060 assert_eq!((String::from("-0"), String::from(".999"), None, None), create_value(-999, 1000).to_strings(&context));
1061 assert_eq!((String::from("-1"), String::from(".000"), None, None), create_value(-9999, 10000).to_strings(&context));
1062 assert_eq!((String::from("-1"), String::from(".000"), None, None), create_value(-99999, 100000).to_strings(&context));
1063 }
1064
1065 #[test]
1066 fn test_recurring_is_formatted_with_precision() {
1067 let value = create_value(1, 3);
1068 let format = |dp: Option<u8>| {
1069 let context = Context::new().with_dp(dp);
1070 let (_, fraction, _, _) = value.to_strings(&context);
1071 return fraction;
1072 };
1073 assert_eq!(String::from(""), format(Some(0)));
1074 assert_eq!(String::from(".333333"), format(Some(6)));
1075 assert_eq!(String::from(".(3)"), format(None));
1076 }
1077
1078 #[test]
1079 fn test_hexadecimal_is_formatted_with_default() {
1080 let context = Context::new().with_format(Format::Base16(3));
1081 assert_eq!((String::from("0x000000000000000000000000"), String::from(""), None, None), create_value(0, 1).to_strings(&context));
1082 assert_eq!((String::from("0x000000000000000000000001"), String::from(""), None, None), create_value(1, 1).to_strings(&context));
1083 assert_eq!((String::from("0x00000000000000007ffffffe"), String::from(""), None, None), create_value(2147483646, 1).to_strings(&context));
1084 assert_eq!((String::from("0x00000000000000007fffffff"), String::from(""), None, None), create_value(2147483647, 1).to_strings(&context));
1085 assert_eq!((String::from("0x000000000000000080000000"), String::from(""), None, None), create_value(2147483648, 1).to_strings(&context));
1086 assert_eq!((String::from("0x000000000000000080000001"), String::from(""), None, None), create_value(2147483649, 1).to_strings(&context));
1087 assert_eq!((String::from("0x0000000000000000fffffffe"), String::from(""), None, None), create_value(4294967294, 1).to_strings(&context));
1088 assert_eq!((String::from("0x0000000000000000ffffffff"), String::from(""), None, None), create_value(4294967295, 1).to_strings(&context));
1089 assert_eq!((String::from("0x000000000000000100000000"), String::from(""), None, None), create_value(4294967296, 1).to_strings(&context));
1090 assert_eq!((String::from("0x000000000000000100000001"), String::from(""), None, None), create_value(4294967297, 1).to_strings(&context));
1091 assert_eq!((String::from("0x000000007ffffffffffffffe"), String::from(""), None, None), create_value(9223372036854775806, 1).to_strings(&context));
1092 assert_eq!((String::from("0x000000007fffffffffffffff"), String::from(""), None, None), create_value(9223372036854775807, 1).to_strings(&context));
1093 assert_eq!((String::from("0x000000008000000000000000"), String::from(""), None, None), create_value(9223372036854775808, 1).to_strings(&context));
1094 assert_eq!((String::from("0x000000008000000000000001"), String::from(""), None, None), create_value(9223372036854775809, 1).to_strings(&context));
1095 assert_eq!((String::from("0x00000000fffffffffffffffe"), String::from(""), None, None), create_value(18446744073709551614, 1).to_strings(&context));
1096 assert_eq!((String::from("0x00000000ffffffffffffffff"), String::from(""), None, None), create_value(18446744073709551615, 1).to_strings(&context));
1097 assert_eq!((String::from("0x000000010000000000000000"), String::from(""), None, None), create_value(18446744073709551616, 1).to_strings(&context));
1098 assert_eq!((String::from("0x000000010000000000000001"), String::from(""), None, None), create_value(18446744073709551617, 1).to_strings(&context));
1099 assert_eq!((String::from("0xffffffff0000000000000000"), String::from(""), None, None), create_value(-18446744073709551616, 1).to_strings(&context));
1100 assert_eq!((String::from("0xffffffff0000000000000001"), String::from(""), None, None), create_value(-18446744073709551615, 1).to_strings(&context));
1101 assert_eq!((String::from("0xffffffff8000000000000000"), String::from(""), None, None), create_value(-9223372036854775808, 1).to_strings(&context));
1102 assert_eq!((String::from("0xffffffff8000000000000001"), String::from(""), None, None), create_value(-9223372036854775807, 1).to_strings(&context));
1103 assert_eq!((String::from("0xffffffffffffffff00000000"), String::from(""), None, None), create_value(-4294967296, 1).to_strings(&context));
1104 assert_eq!((String::from("0xffffffffffffffff00000001"), String::from(""), None, None), create_value(-4294967295, 1).to_strings(&context));
1105 assert_eq!((String::from("0xffffffffffffffff80000000"), String::from(""), None, None), create_value(-2147483648, 1).to_strings(&context));
1106 assert_eq!((String::from("0xffffffffffffffff80000001"), String::from(""), None, None), create_value(-2147483647, 1).to_strings(&context));
1107 assert_eq!((String::from("0xfffffffffffffffffffffffe"), String::from(""), None, None), create_value(-2, 1).to_strings(&context));
1108 assert_eq!((String::from("0xffffffffffffffffffffffff"), String::from(""), None, None), create_value(-1, 1).to_strings(&context));
1109 }
1110
1111 #[test]
1112 fn test_hexadecimal_is_formatted_with_separator() {
1113 let context = Context::new().with_format(Format::Base16(3)).with_sep(true);
1114 assert_eq!((String::from("0x,00000000,00000000,00000000"), String::from(""), None, None), create_value(0, 1).to_strings(&context));
1115 assert_eq!((String::from("0x,00000000,00000000,00000001"), String::from(""), None, None), create_value(1, 1).to_strings(&context));
1116 assert_eq!((String::from("0x,00000000,00000000,7ffffffe"), String::from(""), None, None), create_value(2147483646, 1).to_strings(&context));
1117 assert_eq!((String::from("0x,00000000,00000000,7fffffff"), String::from(""), None, None), create_value(2147483647, 1).to_strings(&context));
1118 assert_eq!((String::from("0x,00000000,00000000,80000000"), String::from(""), None, None), create_value(2147483648, 1).to_strings(&context));
1119 assert_eq!((String::from("0x,00000000,00000000,80000001"), String::from(""), None, None), create_value(2147483649, 1).to_strings(&context));
1120 assert_eq!((String::from("0x,00000000,00000000,fffffffe"), String::from(""), None, None), create_value(4294967294, 1).to_strings(&context));
1121 assert_eq!((String::from("0x,00000000,00000000,ffffffff"), String::from(""), None, None), create_value(4294967295, 1).to_strings(&context));
1122 assert_eq!((String::from("0x,00000000,00000001,00000000"), String::from(""), None, None), create_value(4294967296, 1).to_strings(&context));
1123 assert_eq!((String::from("0x,00000000,00000001,00000001"), String::from(""), None, None), create_value(4294967297, 1).to_strings(&context));
1124 assert_eq!((String::from("0x,00000000,7fffffff,fffffffe"), String::from(""), None, None), create_value(9223372036854775806, 1).to_strings(&context));
1125 assert_eq!((String::from("0x,00000000,7fffffff,ffffffff"), String::from(""), None, None), create_value(9223372036854775807, 1).to_strings(&context));
1126 assert_eq!((String::from("0x,00000000,80000000,00000000"), String::from(""), None, None), create_value(9223372036854775808, 1).to_strings(&context));
1127 assert_eq!((String::from("0x,00000000,80000000,00000001"), String::from(""), None, None), create_value(9223372036854775809, 1).to_strings(&context));
1128 assert_eq!((String::from("0x,00000000,ffffffff,fffffffe"), String::from(""), None, None), create_value(18446744073709551614, 1).to_strings(&context));
1129 assert_eq!((String::from("0x,00000000,ffffffff,ffffffff"), String::from(""), None, None), create_value(18446744073709551615, 1).to_strings(&context));
1130 assert_eq!((String::from("0x,00000001,00000000,00000000"), String::from(""), None, None), create_value(18446744073709551616, 1).to_strings(&context));
1131 assert_eq!((String::from("0x,00000001,00000000,00000001"), String::from(""), None, None), create_value(18446744073709551617, 1).to_strings(&context));
1132 assert_eq!((String::from("0x,ffffffff,00000000,00000000"), String::from(""), None, None), create_value(-18446744073709551616, 1).to_strings(&context));
1133 assert_eq!((String::from("0x,ffffffff,00000000,00000001"), String::from(""), None, None), create_value(-18446744073709551615, 1).to_strings(&context));
1134 assert_eq!((String::from("0x,ffffffff,80000000,00000000"), String::from(""), None, None), create_value(-9223372036854775808, 1).to_strings(&context));
1135 assert_eq!((String::from("0x,ffffffff,80000000,00000001"), String::from(""), None, None), create_value(-9223372036854775807, 1).to_strings(&context));
1136 assert_eq!((String::from("0x,ffffffff,ffffffff,00000000"), String::from(""), None, None), create_value(-4294967296, 1).to_strings(&context));
1137 assert_eq!((String::from("0x,ffffffff,ffffffff,00000001"), String::from(""), None, None), create_value(-4294967295, 1).to_strings(&context));
1138 assert_eq!((String::from("0x,ffffffff,ffffffff,80000000"), String::from(""), None, None), create_value(-2147483648, 1).to_strings(&context));
1139 assert_eq!((String::from("0x,ffffffff,ffffffff,80000001"), String::from(""), None, None), create_value(-2147483647, 1).to_strings(&context));
1140 assert_eq!((String::from("0x,ffffffff,ffffffff,fffffffe"), String::from(""), None, None), create_value(-2, 1).to_strings(&context));
1141 assert_eq!((String::from("0x,ffffffff,ffffffff,ffffffff"), String::from(""), None, None), create_value(-1, 1).to_strings(&context));
1142 }
1143
1144 #[test]
1145 fn test_hexadecimal_is_measured_from_valid() {
1146 assert_eq!(1, create_value(0, 1).measure_hexadecimal()); assert_eq!(1, create_value(1, 1).measure_hexadecimal()); assert_eq!(1, create_value(2147483646, 1).measure_hexadecimal()); assert_eq!(1, create_value(2147483647, 1).measure_hexadecimal()); assert_eq!(2, create_value(2147483648, 1).measure_hexadecimal()); assert_eq!(2, create_value(2147483649, 1).measure_hexadecimal()); assert_eq!(2, create_value(4294967294, 1).measure_hexadecimal()); assert_eq!(2, create_value(4294967295, 1).measure_hexadecimal()); assert_eq!(2, create_value(4294967296, 1).measure_hexadecimal()); assert_eq!(2, create_value(4294967297, 1).measure_hexadecimal()); assert_eq!(2, create_value(9223372036854775806, 1).measure_hexadecimal()); assert_eq!(2, create_value(9223372036854775807, 1).measure_hexadecimal()); assert_eq!(3, create_value(9223372036854775808, 1).measure_hexadecimal()); assert_eq!(3, create_value(9223372036854775809, 1).measure_hexadecimal()); assert_eq!(3, create_value(18446744073709551614, 1).measure_hexadecimal()); assert_eq!(3, create_value(18446744073709551615, 1).measure_hexadecimal()); assert_eq!(3, create_value(18446744073709551616, 1).measure_hexadecimal()); assert_eq!(3, create_value(18446744073709551617, 1).measure_hexadecimal()); assert_eq!(3, create_value(-18446744073709551616, 1).measure_hexadecimal()); assert_eq!(3, create_value(-18446744073709551615, 1).measure_hexadecimal()); assert_eq!(2, create_value(-9223372036854775808, 1).measure_hexadecimal()); assert_eq!(2, create_value(-9223372036854775807, 1).measure_hexadecimal()); assert_eq!(2, create_value(-4294967296, 1).measure_hexadecimal()); assert_eq!(2, create_value(-4294967295, 1).measure_hexadecimal()); assert_eq!(1, create_value(-2147483648, 1).measure_hexadecimal()); assert_eq!(1, create_value(-2147483647, 1).measure_hexadecimal()); assert_eq!(1, create_value(-2, 1).measure_hexadecimal()); assert_eq!(1, create_value(-1, 1).measure_hexadecimal()); }
1175
1176 #[test]
1177 fn test_time_is_formatted_without_separator() {
1178 let context = Context::new().with_sep(true).with_dp(Some(6));
1179 assert_time("2024-06-30T12:00:00", ".000Z", create_value(1719748800000, 1000), &context);
1180 assert_time("2024-06-30T12:00:00", ".987Z", create_value(1719748800987, 1000), &context);
1181 assert_time("2024-12-31T12:00:00", ".000Z", create_value(1735646400000, 1000), &context);
1182 assert_time("2024-12-31T12:00:00", ".987Z", create_value(1735646400987, 1000), &context);
1183 }
1184
1185 #[test]
1186 fn test_delta_is_formatted_without_separator() {
1187 let context = Context::new().with_sep(true).with_dp(Some(6));
1188 assert_delta("00", ".000", create_value(0, 1), &context);
1189 assert_delta("59", ".999", create_value(59999, 1000), &context);
1190 assert_delta("01:00", ".000", create_value(60000, 1000), &context);
1191 assert_delta("59:59", ".999", create_value(3599999, 1000), &context);
1192 assert_delta("01:00:00", ".000", create_value(3600000, 1000), &context);
1193 assert_delta("23:59:59", ".999", create_value(86399999, 1000), &context);
1194 assert_delta("1T00:00:00", ".000", create_value(86400000, 1000), &context);
1195 assert_delta("100T00:00:00", ".000", create_value(8640000000, 1000), &context);
1196 assert_delta("-59", ".999", create_value(-59999, 1000), &context);
1197 assert_delta("-01:00", ".000", create_value(-60000, 1000), &context);
1198 assert_delta("-59:59", ".999", create_value(-3599999, 1000), &context);
1199 assert_delta("-01:00:00", ".000", create_value(-3600000, 1000), &context);
1200 assert_delta("-23:59:59", ".999", create_value(-86399999, 1000), &context);
1201 assert_delta("-1T00:00:00", ".000", create_value(-86400000, 1000), &context);
1202 assert_delta("-100T00:00:00", ".000", create_value(-8640000000, 1000), &context);
1203 }
1204
1205 fn assert_time(integer: &str, fraction: &str, value: Value, context: &Context) {
1206 let expected = (String::from(integer), String::from(fraction), None, None);
1207 let actual = value.with_meaning(Meaning::Time).to_strings(context);
1208 assert_eq!(expected, actual);
1209 }
1210
1211 fn assert_delta(integer: &str, fraction: &str, value: Value, context: &Context) {
1212 let expected = (String::from(integer), String::from(fraction), None, None);
1213 let actual = value.with_meaning(Meaning::Delta).to_strings(context);
1214 assert_eq!(expected, actual);
1215 }
1216
1217 #[test]
1218 fn test_decimal_is_formatted_from_nan() {
1219 let expected = (String::from("NaN"), String::from(""), None, None);
1220 let context = Context::new();
1221 let actual = VALUE_NAN.to_strings(&context);
1222 assert_eq!(expected, actual);
1223 }
1224
1225 #[test]
1226 fn test_hexadecimal_is_measured_from_nan() {
1227 assert_eq!(1, VALUE_NAN.measure_hexadecimal());
1228 }
1229
1230 #[test]
1237 fn test_plain_values_are_added_by_value() {
1238 assert_eq!(Value::calc_add(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(8, 1)));
1239 assert_eq!(Value::calc_add(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1240 assert_eq!(Value::calc_add(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1241 assert_eq!(Value::calc_add(create_nan(), create_nan()).ok(), Some(create_nan()));
1242 }
1243
1244 #[test]
1245 fn test_plain_values_are_added_by_meaning() {
1246 assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1247 assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Plain, Meaning::Delta), Some(Meaning::Delta));
1248 assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Plain, Meaning::Time), Some(Meaning::Time));
1249 assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Delta, Meaning::Plain), Some(Meaning::Delta));
1250 assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Delta, Meaning::Delta), Some(Meaning::Delta));
1251 assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Delta, Meaning::Time), Some(Meaning::Time));
1252 assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Time, Meaning::Plain), Some(Meaning::Time));
1253 assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Time, Meaning::Delta), Some(Meaning::Time));
1254 assert_eq!(perform_binary_err(Value::calc_add, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1255 }
1256
1257 #[test]
1264 fn test_plain_values_are_subtracted_by_value() {
1265 assert_eq!(Value::calc_sub(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(3, 1)));
1266 assert_eq!(Value::calc_sub(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1267 assert_eq!(Value::calc_sub(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1268 assert_eq!(Value::calc_sub(create_nan(), create_nan()).ok(), Some(create_nan()));
1269 }
1270
1271 #[test]
1272 fn test_plain_values_are_subtracted_by_meaning() {
1273 assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1274 assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Plain, Meaning::Delta), Some(Meaning::Delta));
1275 assert_eq!(perform_binary_err(Value::calc_sub, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1276 assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Delta, Meaning::Plain), Some(Meaning::Delta));
1277 assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Delta, Meaning::Delta), Some(Meaning::Delta));
1278 assert_eq!(perform_binary_err(Value::calc_sub, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1279 assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Time, Meaning::Plain), Some(Meaning::Time));
1280 assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Time, Meaning::Delta), Some(Meaning::Time));
1281 assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Time, Meaning::Time), Some(Meaning::Delta));
1282 }
1283
1284 #[test]
1291 fn test_plain_values_are_multiplied_by_value() {
1292 assert_eq!(Value::calc_mul(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(1375, 100)));
1293 assert_eq!(Value::calc_mul(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1294 assert_eq!(Value::calc_mul(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1295 assert_eq!(Value::calc_mul(create_nan(), create_nan()).ok(), Some(create_nan()));
1296 }
1297
1298 #[test]
1299 fn test_plain_values_are_multiplied_by_meaning() {
1300 assert_eq!(perform_binary_ok(Value::calc_mul, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1301 assert_eq!(perform_binary_ok(Value::calc_mul, Meaning::Plain, Meaning::Delta), Some(Meaning::Delta));
1302 assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1303 assert_eq!(perform_binary_ok(Value::calc_mul, Meaning::Delta, Meaning::Plain), Some(Meaning::Delta));
1304 assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1305 assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1306 assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1307 assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1308 assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1309 }
1310
1311 #[test]
1318 fn test_plain_values_are_divided_by_value() {
1319 assert_eq!(Value::calc_div(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(22, 10)));
1320 assert_eq!(Value::calc_div(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1321 assert_eq!(Value::calc_div(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1322 assert_eq!(Value::calc_div(create_nan(), create_nan()).ok(), Some(create_nan()));
1323 }
1324
1325 #[test]
1326 fn test_plain_values_are_divided_by_zero() {
1327 assert_eq!(Value::calc_div(create_ref(55, 10), create_ref(0, 1)).ok(), Some(create_nan()));
1328 assert_eq!(Value::calc_div(create_nan(), create_ref(0, 1)).ok(), Some(create_nan()));
1329 }
1330
1331 #[test]
1332 fn test_plain_values_are_divided_by_meaning() {
1333 assert_eq!(perform_binary_ok(Value::calc_div, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1334 assert_eq!(perform_binary_err(Value::calc_div, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1335 assert_eq!(perform_binary_err(Value::calc_div, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1336 assert_eq!(perform_binary_ok(Value::calc_div, Meaning::Delta, Meaning::Plain), Some(Meaning::Delta));
1337 assert_eq!(perform_binary_err(Value::calc_div, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1338 assert_eq!(perform_binary_err(Value::calc_div, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1339 assert_eq!(perform_binary_err(Value::calc_div, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1340 assert_eq!(perform_binary_err(Value::calc_div, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1341 assert_eq!(perform_binary_err(Value::calc_div, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1342 }
1343
1344 #[test]
1345 fn test_plain_values_are_remaindered_by_value() {
1346 assert_eq!(Value::calc_mod(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(5, 10)));
1347 assert_eq!(Value::calc_mod(create_ref(55, 10), create_ref(-25, 10)).ok(), Some(create_ref(5, 10)));
1348 assert_eq!(Value::calc_mod(create_ref(-55, 10), create_ref(25, 10)).ok(), Some(create_ref(-5, 10)));
1349 assert_eq!(Value::calc_mod(create_ref(-55, 10), create_ref(-25, 10)).ok(), Some(create_ref(-5, 10)));
1350 assert_eq!(Value::calc_mod(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1351 assert_eq!(Value::calc_mod(create_ref(-55, 10), create_nan()).ok(), Some(create_nan()));
1352 assert_eq!(Value::calc_mod(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1353 assert_eq!(Value::calc_mod(create_nan(), create_ref(-25, 10)).ok(), Some(create_nan()));
1354 assert_eq!(Value::calc_mod(create_nan(), create_nan()).ok(), Some(create_nan()));
1355 }
1356
1357 #[test]
1358 fn test_plain_values_are_remaindered_by_zero() {
1359 assert_eq!(Value::calc_mod(create_ref(55, 10), create_ref(0, 1)).ok(), Some(create_nan()));
1360 assert_eq!(Value::calc_mod(create_nan(), create_ref(0, 1)).ok(), Some(create_nan()));
1361 }
1362
1363 #[test]
1364 fn test_plain_values_are_remaindered_by_meaning() {
1365 assert_eq!(perform_binary_ok(Value::calc_mod, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1366 assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1367 assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1368 assert_eq!(perform_binary_ok(Value::calc_mod, Meaning::Delta, Meaning::Plain), Some(Meaning::Delta));
1369 assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1370 assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1371 assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1372 assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1373 assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1374 }
1375
1376 #[test]
1381 fn test_plain_values_are_negated_by_value() {
1382 assert_eq!(Value::calc_neg(create_ref(5, 10)).ok(), Some(create_ref(-5, 10)));
1383 assert_eq!(Value::calc_neg(create_ref(-5, 10)).ok(), Some(create_ref(5, 10)));
1384 assert_eq!(Value::calc_neg(create_nan()).ok(), Some(create_nan()));
1385 }
1386
1387 #[test]
1388 fn test_plain_values_are_negated_by_meaning() {
1389 assert_eq!(perform_unary_ok(Value::calc_neg, Meaning::Plain), Some(Meaning::Plain));
1390 assert_eq!(perform_unary_ok(Value::calc_neg, Meaning::Delta), Some(Meaning::Delta));
1391 assert_eq!(perform_unary_err(Value::calc_neg, Meaning::Time), Some(EngineError::BadTimeOp));
1392 }
1393
1394 #[test]
1399 fn test_plain_values_are_inverted_if_valid() {
1400 assert_eq!(Value::calc_inv(create_ref(5, 10)).ok(), Some(create_ref(10, 5)));
1401 assert_eq!(Value::calc_inv(create_ref(-5, 10)).ok(), Some(create_ref(-10, 5)));
1402 assert_eq!(Value::calc_inv(create_nan()).ok(), Some(create_nan()));
1403 }
1404
1405 #[test]
1406 fn test_plain_values_are_inverted_if_zero() {
1407 assert_eq!(Value::calc_inv(create_ref(0, 1)).ok(), Some(create_nan()));
1408 }
1409
1410 #[test]
1411 fn test_plain_values_are_inverted_by_meaning() {
1412 assert_eq!(perform_unary_ok(Value::calc_inv, Meaning::Plain), Some(Meaning::Plain));
1413 assert_eq!(perform_unary_err(Value::calc_inv, Meaning::Delta), Some(EngineError::BadTimeOp));
1414 assert_eq!(perform_unary_err(Value::calc_inv, Meaning::Time), Some(EngineError::BadTimeOp));
1415 }
1416
1417 #[test]
1424 fn test_plain_values_are_raised_to_integer_power() {
1425 assert_eq!(Value::calc_pow(create_ref(3, 1), create_ref(4, 1)).ok(), Some(create_ref(81, 1)));
1426 assert_eq!(Value::calc_pow(create_ref(3, 1), create_nan()).ok(), Some(create_nan()));
1427 assert_eq!(Value::calc_pow(create_nan(), create_ref(4, 1)).ok(), Some(create_nan()));
1428 assert_eq!(Value::calc_pow(create_nan(), create_nan()).ok(), Some(create_nan()));
1429 }
1430
1431 #[test]
1432 fn test_plain_values_are_raised_to_fractional_power() {
1433 assert_eq!(Value::calc_pow(create_ref(3, 1), create_nan()).ok(), Some(create_nan()));
1434 assert_eq!(Value::calc_pow(create_nan(), create_ref(1, 2)).ok(), Some(create_nan()));
1435 assert_eq!(Value::calc_pow(create_nan(), create_nan()).ok(), Some(create_nan()));
1436 }
1437
1438 #[test]
1439 fn test_plain_values_are_raised_by_meaning() {
1440 assert_eq!(perform_binary_ok(Value::calc_pow, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1441 assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1442 assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1443 assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1444 assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1445 assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1446 assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1447 assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1448 assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1449 }
1450
1451 #[test]
1456 fn test_plain_values_have_square_root_if_positive() {
1457 assert_eq!(Value::calc_sqrt(create_nan()).ok(), Some(create_nan()));
1458 }
1459
1460 #[test]
1461 fn test_plain_values_have_square_root_if_negative() {
1462 assert_eq!(Value::calc_sqrt(create_ref(-3, 1)).ok(), Some(create_nan()));
1463 }
1464
1465 #[test]
1466 fn test_plain_values_have_square_root_by_meaning() {
1467 assert_eq!(perform_unary_ok(Value::calc_sqrt, Meaning::Plain), Some(Meaning::Plain));
1468 assert_eq!(perform_unary_err(Value::calc_sqrt, Meaning::Delta), Some(EngineError::BadTimeOp));
1469 assert_eq!(perform_unary_err(Value::calc_sqrt, Meaning::Time), Some(EngineError::BadTimeOp));
1470 }
1471
1472 #[test]
1473 fn test_plain_values_are_summed() {
1474 assert_eq!(Some(create_ref(0, 1)), Value::calc_sum(vec![]).ok());
1475 assert_eq!(Some(create_ref(0, 1)), Value::calc_sum(vec![create_nan(), create_nan(), create_nan()]).ok());
1476 assert_eq!(Some(create_ref(25, 10)), Value::calc_sum(vec![create_ref(25, 10), create_nan(), create_nan()]).ok());
1477 assert_eq!(Some(create_ref(65, 10)), Value::calc_sum(vec![create_ref(25, 10), create_ref(4, 1), create_nan()]).ok());
1478 assert_eq!(Some(create_ref(120, 10)), Value::calc_sum(vec![create_ref(25, 10), create_ref(4, 1), create_ref(55, 10)]).ok());
1479 }
1480
1481 #[test]
1482 fn test_plain_values_are_producted() {
1483 assert_eq!(Some(create_ref(1, 1)), Value::calc_prod(vec![]).ok());
1484 assert_eq!(Some(create_ref(1, 1)), Value::calc_prod(vec![create_nan(), create_nan(), create_nan()]).ok());
1485 assert_eq!(Some(create_ref(25, 10)), Value::calc_prod(vec![create_ref(25, 10), create_nan(), create_nan()]).ok());
1486 assert_eq!(Some(create_ref(100, 10)), Value::calc_prod(vec![create_ref(25, 10), create_ref(4, 1), create_nan()]).ok());
1487 assert_eq!(Some(create_ref(550, 10)), Value::calc_prod(vec![create_ref(25, 10), create_ref(4, 1), create_ref(55, 10)]).ok());
1488 }
1489
1490 #[test]
1497 fn test_plain_values_have_bitwise_and_by_value() {
1498 assert_eq!(Value::calc_and(create_ref(0xff00, 1), create_ref(0xf0f0, 1)).ok(), Some(create_ref(0xf000, 1)));
1499 assert_eq!(Value::calc_and(create_ref(0xff00, 1), create_nan()).ok(), Some(create_nan()));
1500 assert_eq!(Value::calc_and(create_nan(), create_ref(0xf0f0, 1)).ok(), Some(create_nan()));
1501 assert_eq!(Value::calc_and(create_nan(), create_nan()).ok(), Some(create_nan()));
1502 }
1503
1504 #[test]
1505 fn test_plain_values_have_bitwise_and_by_meaning() {
1506 assert_eq!(perform_binary_ok(Value::calc_and, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1507 assert_eq!(perform_binary_err(Value::calc_and, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1508 assert_eq!(perform_binary_err(Value::calc_and, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1509 assert_eq!(perform_binary_err(Value::calc_and, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1510 assert_eq!(perform_binary_err(Value::calc_and, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1511 assert_eq!(perform_binary_err(Value::calc_and, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1512 assert_eq!(perform_binary_err(Value::calc_and, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1513 assert_eq!(perform_binary_err(Value::calc_and, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1514 assert_eq!(perform_binary_err(Value::calc_and, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1515 }
1516
1517 #[test]
1518 fn test_plain_values_have_bitwise_or_by_value() {
1519 assert_eq!(Value::calc_or(create_ref(0xff00, 1), create_ref(0xf0f0, 1)).ok(), Some(create_ref(0xfff0, 1)));
1520 assert_eq!(Value::calc_or(create_ref(0xff00, 1), create_nan()).ok(), Some(create_nan()));
1521 assert_eq!(Value::calc_or(create_nan(), create_ref(0xf0f0, 1)).ok(), Some(create_nan()));
1522 assert_eq!(Value::calc_or(create_nan(), create_nan()).ok(), Some(create_nan()));
1523 }
1524
1525 #[test]
1526 fn test_plain_values_have_bitwise_or_by_meaning() {
1527 assert_eq!(perform_binary_ok(Value::calc_or, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1528 assert_eq!(perform_binary_err(Value::calc_or, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1529 assert_eq!(perform_binary_err(Value::calc_or, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1530 assert_eq!(perform_binary_err(Value::calc_or, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1531 assert_eq!(perform_binary_err(Value::calc_or, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1532 assert_eq!(perform_binary_err(Value::calc_or, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1533 assert_eq!(perform_binary_err(Value::calc_or, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1534 assert_eq!(perform_binary_err(Value::calc_or, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1535 assert_eq!(perform_binary_err(Value::calc_or, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1536 }
1537
1538 #[test]
1539 fn test_plain_values_have_bitwise_xor_by_value() {
1540 assert_eq!(Value::calc_xor(create_ref(0xff00, 1), create_ref(0xf0f0, 1)).ok(), Some(create_ref(0x0ff0, 1)));
1541 assert_eq!(Value::calc_xor(create_ref(0xff00, 1), create_nan()).ok(), Some(create_nan()));
1542 assert_eq!(Value::calc_xor(create_nan(), create_ref(0xf0f0, 1)).ok(), Some(create_nan()));
1543 assert_eq!(Value::calc_xor(create_nan(), create_nan()).ok(), Some(create_nan()));
1544 }
1545
1546 #[test]
1547 fn test_plain_values_have_bitwise_xor_by_meaning() {
1548 assert_eq!(perform_binary_ok(Value::calc_xor, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1549 assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1550 assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1551 assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1552 assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1553 assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1554 assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1555 assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1556 assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1557 }
1558
1559 #[test]
1560 fn test_plain_values_are_shifted_left_by_value() {
1561 assert_eq!(Value::calc_shl(create_ref(35, 10), create_ref(29, 10)).ok(), Some(create_ref(14, 1)));
1562 assert_eq!(Value::calc_shl(create_ref(-35, 10), create_ref(29, 10)).ok(), Some(create_ref(-14, 1)));
1563 assert_eq!(Value::calc_shl(create_ref(35, 10), create_ref(-29, 10)).ok(), Some(create_ref(875, 1000)));
1564 assert_eq!(Value::calc_shl(create_ref(-35, 10), create_ref(-29, 10)).ok(), Some(create_ref(-875, 1000)));
1565 assert_eq!(Value::calc_shl(create_ref(35, 10), create_nan()).ok(), Some(create_nan()));
1566 assert_eq!(Value::calc_shl(create_ref(-35, 10), create_nan()).ok(), Some(create_nan()));
1567 assert_eq!(Value::calc_shl(create_nan(), create_ref(29, 10)).ok(), Some(create_nan()));
1568 assert_eq!(Value::calc_shl(create_nan(), create_ref(-29, 10)).ok(), Some(create_nan()));
1569 assert_eq!(Value::calc_shl(create_nan(), create_nan()).ok(), Some(create_nan()));
1570 }
1571
1572 #[test]
1573 fn test_plain_values_are_shifted_left_by_meaning() {
1574 assert_eq!(perform_binary_ok(Value::calc_shl, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1575 assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1576 assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1577 assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1578 assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1579 assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1580 assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1581 assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1582 assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1583 }
1584
1585 #[test]
1586 fn test_plain_values_are_shifted_right_by_value() {
1587 assert_eq!(Value::calc_shr(create_ref(35, 10), create_ref(29, 10)).ok(), Some(create_ref(875, 1000)));
1588 assert_eq!(Value::calc_shr(create_ref(-35, 10), create_ref(29, 10)).ok(), Some(create_ref(-875, 1000)));
1589 assert_eq!(Value::calc_shr(create_ref(35, 10), create_ref(-29, 10)).ok(), Some(create_ref(14, 1)));
1590 assert_eq!(Value::calc_shr(create_ref(-35, 10), create_ref(-29, 10)).ok(), Some(create_ref(-14, 1)));
1591 assert_eq!(Value::calc_shr(create_ref(35, 10), create_nan()).ok(), Some(create_nan()));
1592 assert_eq!(Value::calc_shr(create_ref(-35, 10), create_nan()).ok(), Some(create_nan()));
1593 assert_eq!(Value::calc_shr(create_nan(), create_ref(29, 10)).ok(), Some(create_nan()));
1594 assert_eq!(Value::calc_shr(create_nan(), create_ref(-29, 10)).ok(), Some(create_nan()));
1595 assert_eq!(Value::calc_shr(create_nan(), create_nan()).ok(), Some(create_nan()));
1596 }
1597
1598 #[test]
1599 fn test_plain_values_are_shifted_right_by_meaning() {
1600 assert_eq!(perform_binary_ok(Value::calc_shr, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1601 assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1602 assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1603 assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1604 assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1605 assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1606 assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1607 assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1608 assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1609 }
1610
1611 fn perform_unary_ok(
1612 function: fn(ValueRef) -> MyResult<ValueRef>,
1613 meaning: Meaning,
1614 ) -> Option<Meaning> {
1615 let value = create_value(1, 1).with_meaning(meaning);
1616 let value = Rc::new(RefCell::new(value));
1617 let result = function(value);
1618 result.ok().map(get_meaning)
1619 }
1620
1621 fn perform_unary_err(
1622 function: fn(ValueRef) -> MyResult<ValueRef>,
1623 meaning: Meaning,
1624 ) -> Option<EngineError> {
1625 let value = create_value(1, 1).with_meaning(meaning);
1626 let value = Rc::new(RefCell::new(value));
1627 let result = function(value);
1628 result.err().and_then(filter_error)
1629 }
1630
1631 fn perform_binary_ok(
1632 function: fn(ValueRef, ValueRef) -> MyResult<ValueRef>,
1633 lhs: Meaning,
1634 rhs: Meaning,
1635 ) -> Option<Meaning> {
1636 let lhs = create_value(1, 1).with_meaning(lhs);
1637 let rhs = create_value(1, 1).with_meaning(rhs);
1638 let lhs = Rc::new(RefCell::new(lhs));
1639 let rhs = Rc::new(RefCell::new(rhs));
1640 let result = function(lhs, rhs);
1641 result.ok().map(get_meaning)
1642 }
1643
1644 fn perform_binary_err(
1645 function: fn(ValueRef, ValueRef) -> MyResult<ValueRef>,
1646 lhs: Meaning,
1647 rhs: Meaning,
1648 ) -> Option<EngineError> {
1649 let lhs = create_value(1, 1).with_meaning(lhs);
1650 let rhs = create_value(1, 1).with_meaning(rhs);
1651 let lhs = Rc::new(RefCell::new(lhs));
1652 let rhs = Rc::new(RefCell::new(rhs));
1653 let result = function(lhs, rhs);
1654 result.err().and_then(filter_error)
1655 }
1656
1657 fn get_meaning(value: ValueRef) -> Meaning {
1658 value.borrow().meaning
1659 }
1660
1661 fn filter_error(error: MyError) -> Option<EngineError> {
1662 match error {
1663 MyError::Engine(error) => Some(error),
1664 _ => None,
1665 }
1666 }
1667
1668 fn create_value(numer: i128, denom: i128) -> Value {
1669 let number = create_ratio(numer, denom);
1670 Value::new(Some(number))
1671 }
1672
1673 fn create_ref(numer: i128, denom: i128) -> ValueRef {
1674 let number = create_ratio(numer, denom);
1675 let value = Value::new(Some(number));
1676 Rc::new(RefCell::new(value))
1677 }
1678
1679 pub fn create_nan() -> ValueRef {
1680 let value = Value::new(None);
1681 Rc::new(RefCell::new(value))
1682 }
1683
1684 pub fn parse_string(number: &str) -> ValueRef {
1685 let regex = regex!(r#"^(\S+)(?: \[(delta|time)\])?(?: = (\w+))?(?: # (.+))?$"#);
1686 let captures = regex.captures(number).unwrap();
1687 let number = captures.get(1).as_ref().map(Match::as_str).unwrap();
1688 let mut value = Value::from_string(number).unwrap();
1689 match captures.get(2).as_ref().map(Match::as_str) {
1690 Some("delta") => value.set_meaning(Meaning::Delta),
1691 Some("time") => value.set_meaning(Meaning::Time),
1692 _ => value.set_meaning(Meaning::Plain),
1693 }
1694 if let Some(variable) = captures.get(3).as_ref().map(Match::as_str) {
1695 value.set_variable(variable);
1696 }
1697 if let Some(comment) = captures.get(4).as_ref().map(Match::as_str) {
1698 value.set_comment(comment);
1699 }
1700 Rc::new(RefCell::new(value))
1701 }
1702
1703 pub fn parse_strings(values: Vec<&str>) -> Vec<ValueRef> {
1704 values.iter().map(|x| parse_string(x)).collect()
1705 }
1706
1707 fn create_ratio(numer: i128, denom: i128) -> BigRational {
1708 let numer = BigInt::from(numer);
1709 let denom = BigInt::from(denom);
1710 BigRational::new(numer, denom)
1711 }
1712
1713 fn fudge_ratio(number: BigRational) -> Option<BigRational> {
1714 number.to_f64()
1715 .map(f64::sqrt)
1716 .and_then(BigRational::from_f64)
1717 .and_then(square_ratio)
1718 }
1719
1720 fn square_ratio(number: BigRational) -> Option<BigRational> {
1721 number.checked_mul(&number)
1722 }
1723
1724 fn opposite_ratio(number: BigRational) -> Option<BigRational> {
1725 create_ratio(2, 1).checked_mul(&number.round()).and_then(|x| x.checked_sub(&number))
1726 }
1727}