rpn_cli/calc/
value.rs

1use crate::calc::context::{Context, Format};
2use crate::calc::meaning::{DeltaKind, Meaning};
3use crate::error::{EngineError, MyError, MyResult};
4use crate::util::number;
5use crate::util::text::{create_padding, remove_char};
6use crate::{combine_binary, combine_cast, combine_inner, regex};
7use big_rational_str::BigRationalExt;
8use chrono::{DateTime, Duration, NaiveDateTime};
9use itertools::Itertools;
10use num::traits::Inv;
11use num::*;
12use regex::{Captures, Match};
13use std::cell::RefCell;
14use std::cmp::Ordering;
15use std::fmt::{Debug, Formatter};
16use std::iter::zip;
17use std::ops::{BitAnd, BitOr, BitXor, Div, Mul, Sub};
18use std::rc::Rc;
19use std::time::SystemTime;
20
21pub type ValueRef = Rc<RefCell<Value>>;
22pub type ValueTuple = (String, String, Option<String>, Option<String>, Option<String>);
23
24#[derive(PartialEq)]
25pub struct Value {
26    pub number: Option<BigRational>,
27    pub meaning: Meaning,
28    pub variable: Option<String>,
29    pub comment: Option<String>,
30}
31
32const CHUNK_DIGITS: usize = 8;
33const CHUNK_VALUE: usize = 0x1_0000_0000;
34const ROUNDING_LIMIT: usize = 6;
35
36// noinspection RsLift
37impl Value {
38    pub const fn new(number: Option<BigRational>) -> Self {
39        Self {
40            number,
41            meaning: Meaning::Plain,
42            variable: None,
43            comment: None,
44        }
45    }
46
47    pub fn with_meaning(mut self, meaning: Meaning) -> Self {
48        self.meaning = meaning;
49        self
50    }
51
52    pub fn set_meaning(&mut self, meaning: Meaning) {
53        self.meaning = meaning;
54    }
55
56    pub fn with_variable(mut self, variable: &str) -> Self {
57        self.variable = Some(String::from(variable));
58        self
59    }
60
61    pub fn set_variable(&mut self, variable: &str) {
62        self.variable = Some(String::from(variable));
63    }
64
65    pub fn with_comment(mut self, comment: &str) -> Self {
66        self.comment = Some(String::from(comment));
67        self
68    }
69
70    pub fn set_comment(&mut self, comment: &str) {
71        self.comment = Some(String::from(comment));
72    }
73
74    fn with_rounding(mut self) -> Self {
75        if let Some(number) = &self.number {
76            if let Some(multiplier) = Self::measure_multiplier(number) {
77                if let Some(number) = number.checked_mul(&multiplier) {
78                    let number = number.round();
79                    if let Some(number) = number.checked_div(&multiplier) {
80                        self.number = Some(number);
81                    }
82                }
83            }
84        }
85        self
86    }
87
88    fn measure_multiplier(number: &BigRational) -> Option<BigRational> {
89        let string = number::format_ratio(number);
90        if let Some(period) = string.find('.') {
91            let string = remove_char(&string, period);
92            for offset in 1..=ROUNDING_LIMIT {
93                if let Some((start, count)) = Self::measure_offset(&string, offset) {
94                    if let Some(start) = start.checked_sub(period) {
95                        if let Some(remain) = string.len().checked_sub(start + count) {
96                            if remain >= count * 2 {
97                                let multiplier = BigInt::from(10)
98                                    .pow(start as u32);
99                                let multiplier = BigInt::from(10)
100                                    .pow(offset as u32)
101                                    .sub(&BigInt::from(1))
102                                    .mul(&multiplier);
103                                return Some(BigRational::from_integer(multiplier));
104                            }
105                        }
106                    }
107                }
108            }
109        }
110        None
111    }
112
113    // Span:      <------->
114    // Left:  19994564564564564832246034753933155512726838401327...
115    // Right: 94564564564564832246034753933155512726838401327630...
116
117    fn measure_offset(string: &str, offset: usize) -> Option<(usize, usize)> {
118        let left = string.chars();
119        let right = string.chars().skip(offset);
120        let mut span = None;
121        for (index, (left, right)) in zip(left, right).enumerate() {
122            if let Some((start, count)) = span {
123                if left == right {
124                    span = Some((start, count + 1));
125                } else if count >= ROUNDING_LIMIT {
126                    return span;
127                } else {
128                    span = None;
129                }
130            } else {
131                if left == right {
132                    span = Some((index, 0));
133                }
134            }
135        }
136        None
137    }
138
139    pub fn from_string(number: &str) -> MyResult<Self> {
140        if number.starts_with("0x") || number.starts_with("0X") {
141            Self::from_hexadecimal(&number[2..])
142        } else if let Some(value) = Self::from_time(number) {
143            Ok(value)
144        } else if let Some(value) = Self::from_delta(number) {
145            Ok(value)
146        } else if let Some(number) = number.strip_prefix(".") {
147            let number = format!("0.{}", number);
148            Self::from_decimal(&number)
149        } else if let Some(number) = number.strip_prefix("-.") {
150            let number = format!("-0.{}", number);
151            Self::from_decimal(&number)
152        } else {
153            Self::from_decimal(number)
154        }
155    }
156
157    fn from_time(time: &str) -> Option<Self> {
158        if let Some(time) = Self::parse_time(time) {
159            let numer = time.and_utc().timestamp_millis();
160            let numer = BigInt::from(numer);
161            let denom = BigInt::from(1000);
162            let number = BigRational::new(numer, denom);
163            let value = Self::new(Some(number)).with_meaning(Meaning::Time);
164            return Some(value);
165        }
166        None
167    }
168
169    fn parse_time(time: &str) -> Option<NaiveDateTime> {
170        let regex = regex!(r#"^(\d+-\d+-\d+T\d+:\d+(:\d+(\.\d+)?)?)Z?$"#);
171        if let Some(captures) = regex.captures(time) {
172            let time = captures.get(1).as_ref().map(Match::as_str).unwrap_or_default();
173            let format = if captures.get(2).is_none() {
174                "%Y-%m-%dT%H:%M"
175            } else if captures.get(3).is_none() {
176                "%Y-%m-%dT%H:%M:%S"
177            } else {
178                "%Y-%m-%dT%H:%M:%S%.f" // "%.f" not ".%f"
179            };
180            return NaiveDateTime::parse_from_str(time, format).ok();
181        }
182        None
183    }
184
185    fn from_delta(delta: &str) -> Option<Self> {
186        if let Some(delta) = Self::parse_delta(delta) {
187            let numer = delta.num_milliseconds();
188            let numer = BigInt::from(numer);
189            let denom = BigInt::from(1000);
190            let number = BigRational::new(numer, denom);
191            let value = Self::new(Some(number)).with_meaning(Meaning::Delta(DeltaKind::HMS));
192            return Some(value);
193        }
194        None
195    }
196
197    fn parse_delta(delta: &str) -> Option<Duration> {
198        let regex = regex!(r#"^(-)?(?:(?:(\d+)[T:])?(\d+):)?(\d+):(\d+)(?:\.(\d+))?$"#);
199        if let Some(captures) = regex.captures(delta) {
200            let negative = captures.get(1).is_some();
201            let days = Self::parse_capture(&captures, 2, None);
202            let hours = Self::parse_capture(&captures, 3, None) + (days * 24);
203            let minutes = Self::parse_capture(&captures, 4, None) + (hours * 60);
204            let seconds = Self::parse_capture(&captures, 5, None) + (minutes * 60);
205            let nanos = Self::parse_capture(&captures, 6, Some(9)) + (seconds * 1_000_000_000);
206            let delta = Duration::nanoseconds(nanos);
207            let delta = if negative { -delta } else { delta };
208            return Some(delta);
209        }
210        None
211    }
212
213    fn parse_capture(captures: &Captures, index: usize, expected: Option<usize>) -> i64 {
214        if let Some(capture) = captures.get(index) {
215            let number = capture.as_str().parse::<i64>().unwrap_or_default();
216            if let Some(expected) = expected {
217                let length = capture.as_str().len();
218                if let Some(diff) = expected.checked_sub(length) {
219                    return number * pow(10, diff);
220                }
221                if let Some(diff) = length.checked_sub(expected) {
222                    return number / pow(10, diff);
223                }
224            }
225            return number;
226        }
227        0
228    }
229
230    fn from_decimal(number: &str) -> MyResult<Self> {
231        let number = number.replace(&[',', '_'], "");
232        let number = BigRational::from_dec_str(&number)?;
233        let value = Self::new(Some(number));
234        Ok(value)
235    }
236
237    fn from_hexadecimal(number: &str) -> MyResult<Self> {
238        let number = number.replace(&[',', '_'], "");
239        let number = BigInt::from_str_radix(&number, 16)?;
240        let number = BigRational::from_integer(number);
241        let value = Self::new(Some(number));
242        Ok(value)
243    }
244
245    pub fn to_strings(&self, context: &Context) -> ValueTuple {
246        if let Some(number) = &self.number {
247            self.format_ratio(context, number)
248        } else {
249            self.create_tuple(String::from("NaN"), String::from(""))
250        }
251    }
252
253    fn format_ratio(
254        &self,
255        context: &Context,
256        number: &BigRational,
257    ) -> ValueTuple {
258        // Returns (integer, fraction, meaning, variable, comment).
259        if self.meaning == Meaning::Time {
260            let number = number * BigInt::from(1000);
261            let number = number.to_i64().unwrap_or_default();
262            let number = Self::format_time(number);
263            self.format_split(context, number)
264        } else if self.meaning == Meaning::Delta(DeltaKind::HMS) {
265            let number = number * BigInt::from(1000);
266            let number = number.to_i64().unwrap_or_default();
267            let number = Self::format_delta(number);
268            self.format_split(context, number)
269        } else if let Format::Base16(chunks) = context.format {
270            let number = number.to_integer();
271            let number = Self::format_hexadecimal(number, chunks, context.sep);
272            self.create_tuple(number, String::from(""))
273        } else if let Some(dp) = context.dp {
274            let power = BigInt::from(10).pow(dp as u32);
275            let number = number.mul(&power).round().div(&power);
276            let number = number::format_ratio(&number);
277            self.format_split(context, number)
278        } else {
279            let number = number::format_ratio(number);
280            self.format_split(context, number)
281        }
282    }
283
284    fn format_time(millis: i64) -> String {
285        let time = DateTime::from_timestamp_millis(millis).unwrap_or_default();
286        time.format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string()
287    }
288
289    fn format_delta(millis: i64) -> String {
290        let (minus, millis) = (if millis < 0 { "-" } else { "" }, abs(millis));
291        let (seconds, millis) = (millis / 1000, millis % 1000);
292        let (minutes, seconds) = (seconds / 60, seconds % 60);
293        let (hours, minutes) = (minutes / 60, minutes % 60);
294        let (days, hours) = (hours / 24, hours % 24);
295        if days != 0 {
296            format!("{}{}T{:02}:{:02}:{:02}.{:03}", minus, days, hours, minutes, seconds, millis)
297        } else if hours != 0 {
298            format!("{}{:02}:{:02}:{:02}.{:03}", minus, hours, minutes, seconds, millis)
299        } else if minutes != 0 {
300            format!("{}{:02}:{:02}.{:03}", minus, minutes, seconds, millis)
301        } else {
302            format!("{}{:02}.{:03}", minus, seconds, millis)
303        }
304    }
305
306    fn format_hexadecimal(
307        mut number: BigInt,
308        chunks: usize,
309        sep: bool,
310    ) -> String {
311        if number.is_negative() {
312            let range = BigInt::from(CHUNK_VALUE).pow(chunks as u32);
313            number += range;
314        }
315        let number = format!("{:x}", number);
316        let padding = create_padding('0', chunks * CHUNK_DIGITS, number.len(), 0);
317        if sep {
318            let number = format!("{}{}", padding, number);
319            let chunks = number.as_bytes()
320                .chunks(CHUNK_DIGITS)
321                .map(std::str::from_utf8);
322            std::iter::once(Ok("0x"))
323                .chain(chunks)
324                .collect::<Result<Vec<&str>, _>>()
325                .unwrap_or_default()
326                .join(",")
327        } else {
328            format!("0x{}{}", padding, number)
329        }
330    }
331
332    fn format_split(
333        &self,
334        context: &Context,
335        number: String,
336    ) -> ValueTuple {
337        let index = number.find('.').unwrap_or(number.len());
338        let (integer, fraction) = number.split_at(index);
339        let integer = self.modify_integer(context, integer);
340        let fraction = self.modify_fraction(context, fraction);
341        self.create_tuple(integer, fraction)
342    }
343
344    fn create_tuple(
345        &self,
346        integer: String,
347        fraction: String,
348    ) -> ValueTuple {
349        let meaning = self.meaning.get_symbol();
350        let variable = self.variable.clone();
351        let comment = self.comment.clone();
352        (integer, fraction, meaning, variable, comment)
353    }
354
355    fn modify_integer(&self, context: &Context, number: &str) -> String {
356        if Self::is_formattable(self.meaning) && context.sep {
357            let index = if number.starts_with('-') { 1 } else { 0 };
358            let (sign, number) = number.split_at(index);
359            let number = number.as_bytes()
360                .rchunks(3)
361                .rev()
362                .map(std::str::from_utf8)
363                .collect::<Result<Vec<&str>, _>>()
364                .unwrap_or_default()
365                .join(",");
366            return format!("{}{}", sign, number);
367        }
368        String::from(number)
369    }
370
371    fn modify_fraction(&self, context: &Context, number: &str) -> String {
372        if Self::is_formattable(self.meaning) {
373            if let Some(dp) = context.dp {
374                if !number.is_empty() || dp > 0 {
375                    let index = if number.starts_with('.') { 1 } else { 0 };
376                    let number = &number[index..];
377                    let dp = dp as usize;
378                    return ".".chars()
379                        .chain(number.chars().take(dp))
380                        .chain(std::iter::repeat('0'))
381                        .take(dp + 1)
382                        .collect::<String>();
383                }
384            }
385        }
386        String::from(number)
387    }
388
389    fn is_formattable(meaning: Meaning) -> bool {
390        match meaning {
391            Meaning::Delta(DeltaKind::HMS) => false,
392            Meaning::Time => false,
393            _ => true,
394        }
395    }
396
397    pub fn measure_hexadecimal(&self) -> usize {
398        if let Some(number) = &self.number {
399            let number = number.to_integer();
400            Self::count_hexadecimal(number)
401        } else {
402            1
403        }
404    }
405
406    fn count_hexadecimal(mut number: BigInt) -> usize {
407        if number.is_negative() {
408            number = number.abs() - 1;
409        }
410        let count = number.iter_u32_digits().count().max(1);
411        let chunk = number.iter_u32_digits().last().unwrap_or_default();
412        if chunk & 0x80000000 != 0 { count + 1 } else { count }
413    }
414
415    fn perform_unary(
416        value: ValueRef,
417        function: fn(&BigRational) -> Option<BigRational>,
418    ) -> ValueRef {
419        if let Some(number) = &value.borrow().number {
420            let meaning = value.borrow().meaning;
421            let result = function(number);
422            let result = Self::new(result).with_rounding().with_meaning(meaning);
423            return Rc::new(RefCell::new(result));
424        }
425        value
426    }
427
428    fn perform_binary(
429        lhs: ValueRef,
430        rhs: ValueRef,
431        meaning: Meaning,
432        function: fn(&BigRational, &BigRational) -> Option<BigRational>,
433    ) -> ValueRef {
434        if let Some(lhs_number) = &lhs.borrow().number {
435            if let Some(rhs_number) = &rhs.borrow().number {
436                let lhs_number = lhs.borrow().meaning.undo_meaning(&lhs_number);
437                let rhs_number = rhs.borrow().meaning.undo_meaning(&rhs_number);
438                let result_number = function(&lhs_number, &rhs_number)
439                    .map(|number| meaning.redo_meaning(&number).into_owned());
440                let result_value = Self::new(result_number).with_rounding().with_meaning(meaning);
441                return Rc::new(RefCell::new(result_value));
442            }
443            return rhs;
444        }
445        lhs
446    }
447
448    // Cast  | Plain Delta Time  | Len   Area  Vol   Speed | Mass  Temp  Data
449    // ------+-------------------+-------------------------+------------------
450    // Plain | Plain Delta Time  | Len   Area  Vol   Speed | Mass  Temp  Data
451    // Delta | Plain Delta -     | -     -     -     -     | -     -     -
452    // Time  | Plain -     Time  | -     -     -     -     | -     -     -
453    // ------+-------------------+-------------------------+------------------
454    // Len   | Plain -     -     | Len   -     -     -     | -     -     -
455    // Area  | Plain -     -     | -     Area  -     -     | -     -     -
456    // Vol   | Plain -     -     | -     -     Vol   -     | -     -     -
457    // Speed | Plain -     -     | -     -     -     Speed | -     -     -
458    // ------+-------------------+-------------------------+------------------
459    // Mass  | Plain -     -     | -     -     -     -     | Mass  -     -
460    // Temp  | Plain -     -     | -     -     -     -     | -     Temp  -
461    // Data  | Plain -     -     | -     -     -     -     | -     -     Data
462
463    pub fn apply_meaning(&self, meaning: Meaning) -> MyResult<ValueRef> {
464        let meaning = combine_cast!(
465            self.meaning,
466            meaning,
467            combine_cast_value,
468        )?;
469        // Clone everything but the variable name.
470        let number = self.number.as_ref().map(|number| {
471            if self.meaning != Meaning::Plain && meaning != Meaning::Plain {
472                let number = self.meaning.undo_meaning(number);
473                let number = meaning.redo_meaning(&number);
474                number.into_owned()
475            } else {
476                number.clone()
477            }
478        });
479        let comment = self.comment.clone();
480        let result = Self { number, meaning, variable: None, comment };
481        let result = Rc::new(RefCell::new(result.with_rounding()));
482        Ok(result)
483    }
484
485    // Add   | Plain Delta Time  | Len   Area  Vol   Speed | Mass  Temp  Data
486    // ------+-------------------+-------------------------+------------------
487    // Plain | Plain Delta Time  | Len   Area  Vol   Speed | Mass  Temp  Data
488    // Delta | Delta Delta Time  | -     -     -     -     | -     -     -
489    // Time  | Time  Time  -     | -     -     -     -     | -     -     -
490    // ------+-------------------+-------------------------+------------------
491    // Len   | Len   -     -     | Len   -     -     -     | -     -     -
492    // Area  | Area  -     -     | -     Area  -     -     | -     -     -
493    // Vol   | Vol   -     -     | -     -     Vol   -     | -     -     -
494    // Speed | Speed -     -     | -     -     -     Speed | -     -     -
495    // ------+-------------------+-------------------------+------------------
496    // Mass  | Mass  -     -     | -     -     -     -     | Mass  -     -
497    // Temp  | Temp  -     -     | -     -     -     -     | -     Temp  -
498    // Data  | Data  -     -     | -     -     -     -     | -     -     Data
499
500    pub fn calc_add(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
501        let meaning = combine_binary!(
502            lhs.borrow().meaning,
503            rhs.borrow().meaning,
504            combine_add_time,
505            combine_copy_left,
506            combine_copy_right,
507            combine_copy_same,
508        )?;
509        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_add(&y));
510        Ok(result)
511    }
512
513    // Sub   | Plain Delta Time  | Len   Area  Vol   Speed | Mass  Temp  Data
514    // ------+-------------------+-------------------------+------------------
515    // Plain | Plain Delta -     | Len   Area  Vol   Speed | Mass  Temp  Data
516    // Delta | Delta Delta -     | -     -     -     -     | -     -     -
517    // Time  | Time  Time  Delta | -     -     -     -     | -     -     -
518    // ------+-------------------+-------------------------+------------------
519    // Len   | Len   -     -     | Len   -     -     -     | -     -     -
520    // Area  | Area  -     -     | -     Area  -     -     | -     -     -
521    // Vol   | Vol   -     -     | -     -     Vol   -     | -     -     -
522    // Speed | Speed -     -     | -     -     -     Speed | -     -     -
523    // ------+-------------------+-------------------------+------------------
524    // Mass  | Mass  -     -     | -     -     -     -     | Mass  -     -
525    // Temp  | Temp  -     -     | -     -     -     -     | -     Temp  -
526    // Data  | Data  -     -     | -     -     -     -     | -     -     Data
527
528    pub fn calc_sub(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
529        let meaning = combine_binary!(
530            lhs.borrow().meaning,
531            rhs.borrow().meaning,
532            combine_sub_time,
533            combine_copy_left,
534            combine_copy_right,
535            combine_copy_same,
536        )?;
537        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_sub(&y));
538        Ok(result)
539    }
540
541    // Mul   | Plain Delta Time  | Len   Area  Vol   Speed | Mass  Temp  Data
542    // ------+-------------------+-------------------------+------------------
543    // Plain | Plain Delta -     | Len   Area  Vol   Speed | Mass  Temp  Data
544    // Delta | Delta -     -     | -     -     -     Len   | -     -     -
545    // Time  | -     -     -     | -     -     -     -     | -     -     -
546    // ------+-------------------+-------------------------+------------------
547    // Len   | Len   -     -     | Area  Vol   -     -     | -     -     -
548    // Area  | Area  -     -     | Vol   -     -     -     | -     -     -
549    // Vol   | Vol   -     -     | -     -     -     -     | -     -     -
550    // Speed | Speed Len   -     | -     -     -     -     | -     -     -
551    // ------+-------------------+-------------------------+------------------
552    // Mass  | Mass  -     -     | -     -     -     -     | -     -     -
553    // Temp  | Temp  -     -     | -     -     -     -     | -     -     -
554    // Data  | Data  -     -     | -     -     -     -     | -     -     -
555
556    pub fn calc_mul(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
557        let meaning = combine_binary!(
558            lhs.borrow().meaning,
559            rhs.borrow().meaning,
560            combine_mul_unit,
561            combine_copy_left,
562            combine_copy_right,
563        )?;
564        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_mul(&y));
565        Ok(result)
566    }
567
568    // Div   | Plain Delta Time  | Len   Area  Vol   Speed | Mass  Temp  Data
569    // ------+-------------------+-------------------------+------------------
570    // Plain | Plain -     -     | -     -     -     -     | -     -     -
571    // Delta | Delta Plain -     | -     -     -     -     | -     -     -
572    // Time  | -     -     -     | -     -     -     -     | -     -     -
573    // ------+-------------------+-------------------------+------------------
574    // Len   | Len   -     -     | Plain -     -     Delta | -     -     -
575    // Area  | Area  -     -     | Len   Plain -     -     | -     -     -
576    // Vol   | Vol   -     -     | Area  Len   Plain -     | -     -     -
577    // Speed | Speed -     -     | -     -     -     Plain | -     -     -
578    // ------+-------------------+-------------------------+------------------
579    // Mass  | Mass  -     -     | -     -     -     -     | Plain -     -
580    // Temp  | Temp  -     -     | -     -     -     -     | -     Plain -
581    // Data  | Data  -     -     | -     -     -     -     | -     -     Plain
582
583    pub fn calc_div(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
584        let meaning = combine_binary!(
585            lhs.borrow().meaning,
586            rhs.borrow().meaning,
587            combine_div_unit,
588            combine_copy_left,
589        )?;
590        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_div(&y));
591        Ok(result)
592    }
593
594    pub fn calc_mod(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
595        let meaning = combine_binary!(
596            lhs.borrow().meaning,
597            rhs.borrow().meaning,
598            combine_div_unit,
599            combine_copy_left,
600        )?;
601        let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_mod);
602        Ok(result)
603    }
604
605    fn checked_mod(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
606        lhs.checked_div(rhs)
607            .map(|result| &result - result.to_integer())
608            .map(|result| result * rhs)
609    }
610
611    // Neg   |
612    // ------+-------
613    // Plain | Plain
614    // Delta | Delta
615    // Time  | -
616    // Other | Other
617
618    pub fn calc_neg(value: ValueRef) -> MyResult<ValueRef> {
619        value.borrow().meaning.select_not_time()?;
620        let result = Self::perform_unary(value, |x| Some(-x));
621        Ok(result)
622    }
623
624    // Inv   |
625    // ------+-------
626    // Plain | Plain
627    // Delta | -
628    // Time  | -
629    // Other | -
630
631    pub fn calc_inv(value: ValueRef) -> MyResult<ValueRef> {
632        value.borrow().meaning.select_only_plain()?;
633        let result = Self::perform_unary(value, Self::checked_inv);
634        Ok(result)
635    }
636
637    fn checked_inv(number: &BigRational) -> Option<BigRational> {
638        if number.is_zero() { None } else { Some(number.inv()) }
639    }
640
641    // Pow   | Plain Delta Time  | Other
642    // ------+-------------------+-------
643    // Plain | Plain -     -     | -
644    // Delta | -     -     -     | -
645    // Time  | -     -     -     | -
646    // ------+-------------------+-------
647    // Other | -     -     -     | -
648
649    pub fn calc_pow(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
650        let meaning = combine_binary!(
651            lhs.borrow().meaning,
652            rhs.borrow().meaning,
653            combine_only_plain,
654        )?;
655        let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_pow);
656        Ok(result)
657    }
658
659    fn checked_pow(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
660        if rhs.is_integer() {
661            if let Some(rhs) = rhs.to_i32() {
662                return Some(lhs.pow(rhs));
663            }
664        } else {
665            if let Some(lhs) = lhs.to_f64() {
666                if let Some(rhs) = rhs.to_f64() {
667                    let result = f64::powf(lhs, rhs);
668                    return BigRational::from_f64(result);
669                }
670            }
671        }
672        None
673    }
674
675    // Sqrt  |
676    // ------+-------
677    // Plain | Plain
678    // Delta | -
679    // Time  | -
680    // Other | -
681
682    pub fn calc_sqrt(value: ValueRef) -> MyResult<ValueRef> {
683        value.borrow().meaning.select_only_plain()?;
684        let result = Self::perform_unary(value, Self::checked_sqrt);
685        Ok(result)
686    }
687
688    fn checked_sqrt(number: &BigRational) -> Option<BigRational> {
689        if let Some(number) = number.to_f64() {
690            let result = number.sqrt();
691            return BigRational::from_f64(result);
692        }
693        None
694    }
695
696    pub fn calc_sum(values: Vec<ValueRef>) -> MyResult<ValueRef> {
697        let mut result = BigRational::from(BigInt::zero());
698        for value in values {
699            if let Some(number) = &value.borrow().number {
700                result += number;
701            }
702        }
703        let result = Self::new(Some(result)).with_rounding();
704        Ok(Rc::new(RefCell::new(result)))
705    }
706
707    pub fn calc_prod(values: Vec<ValueRef>) -> MyResult<ValueRef> {
708        let mut result = BigRational::from(BigInt::one());
709        for value in values {
710            if let Some(number) = &value.borrow().number {
711                result *= number;
712            }
713        }
714        let result = Self::new(Some(result)).with_rounding();
715        Ok(Rc::new(RefCell::new(result)))
716    }
717
718    pub fn calc_seq(start: ValueRef, stop: ValueRef) -> MyResult<Vec<ValueRef>> {
719        let mut values = Vec::new();
720        let meaning = start.borrow().meaning;
721        if let Some(start) = &start.borrow().number {
722            if let Some(stop) = &stop.borrow().number {
723                let step = BigRational::one();
724                Self::inner_step(&mut values, meaning, start, &step, stop);
725            }
726        }
727        Ok(values)
728    }
729
730    pub fn calc_step(start: ValueRef, step: ValueRef, stop: ValueRef) -> MyResult<Vec<ValueRef>> {
731        let mut values = Vec::new();
732        let meaning = start.borrow().meaning;
733        if let Some(start) = &start.borrow().number {
734            if let Some(step) = &step.borrow().number {
735                if let Some(stop) = &stop.borrow().number {
736                    let step = step.abs();
737                    Self::inner_step(&mut values, meaning, start, &step, stop);
738                }
739            }
740        }
741        Ok(values)
742    }
743
744    fn inner_step(
745        values: &mut Vec<ValueRef>,
746        meaning: Meaning,
747        start: &BigRational,
748        step: &BigRational,
749        stop: &BigRational,
750    ) {
751        let mut number = start.clone();
752        Self::inner_push(values, meaning, &number);
753        if step.is_positive() {
754            if number <= *stop {
755                loop {
756                    number += step;
757                    if number > *stop { break }
758                    Self::inner_push(values, meaning, &number);
759                }
760            } else {
761                loop {
762                    number -= step;
763                    if number < *stop { break }
764                    Self::inner_push(values, meaning, &number);
765                }
766            }
767        }
768    }
769
770    fn inner_push(
771        values: &mut Vec<ValueRef>,
772        meaning: Meaning,
773        number: &BigRational,
774    ) {
775        let number = number.clone();
776        let value = Self::new(Some(number)).with_meaning(meaning);
777        values.push(Rc::new(RefCell::new(value)));
778    }
779
780    pub fn sort_seq(values: Vec<ValueRef>) -> MyResult<Vec<ValueRef>> {
781        let results = values.into_iter().sorted_by(Self::cmp_values).collect();
782        Ok(results)
783    }
784
785    pub fn rev_seq(values: Vec<ValueRef>) -> MyResult<Vec<ValueRef>> {
786        let results = values.into_iter().rev().collect();
787        Ok(results)
788    }
789
790    fn cmp_values(lhs: &ValueRef, rhs: &ValueRef) -> Ordering {
791        let lhs = &lhs.borrow().number;
792        let rhs = &rhs.borrow().number;
793        match (lhs, rhs) {
794            (Some(lhs), Some(rhs)) => BigRational::cmp(lhs, rhs),
795            (Some(_), None) => Ordering::Greater,
796            (None, Some(_)) => Ordering::Less,
797            (None, None) => Ordering::Equal,
798        }
799    }
800
801    // And   | Plain Delta Time  | Other
802    // ------+-------------------+-------
803    // Plain | Plain -     -     | -
804    // Delta | -     -     -     | -
805    // Time  | -     -     -     | -
806    // ------+-------------------+-------
807    // Other | -     -     -     | -
808
809    pub fn calc_and(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
810        let meaning = combine_binary!(
811            lhs.borrow().meaning,
812            rhs.borrow().meaning,
813            combine_only_plain,
814        )?;
815        let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_and);
816        Ok(result)
817    }
818
819    pub fn calc_or(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
820        let meaning = combine_binary!(
821            lhs.borrow().meaning,
822            rhs.borrow().meaning,
823            combine_only_plain,
824        )?;
825        let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_or);
826        Ok(result)
827    }
828
829    pub fn calc_xor(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
830        let meaning = combine_binary!(
831            lhs.borrow().meaning,
832            rhs.borrow().meaning,
833            combine_only_plain,
834        )?;
835        let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_xor);
836        Ok(result)
837    }
838
839    fn checked_and(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
840        let lhs = lhs.to_integer();
841        let rhs = rhs.to_integer();
842        let result = lhs.bitand(rhs);
843        Some(BigRational::from(result))
844    }
845
846    fn checked_or(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
847        let lhs = lhs.to_integer();
848        let rhs = rhs.to_integer();
849        let result = lhs.bitor(rhs);
850        Some(BigRational::from(result))
851    }
852
853    fn checked_xor(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
854        let lhs = lhs.to_integer();
855        let rhs = rhs.to_integer();
856        let result = lhs.bitxor(rhs);
857        Some(BigRational::from(result))
858    }
859
860    pub fn calc_shl(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
861        let meaning = combine_binary!(
862            lhs.borrow().meaning,
863            rhs.borrow().meaning,
864            combine_only_plain,
865        )?;
866        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| Self::checked_shl(x, y));
867        Ok(result)
868    }
869
870    pub fn calc_shr(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
871        let meaning = combine_binary!(
872            lhs.borrow().meaning,
873            rhs.borrow().meaning,
874            combine_only_plain,
875        )?;
876        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| Self::checked_shr(x, y));
877        Ok(result)
878    }
879
880    fn checked_shl(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
881        if let Some(rhs) = rhs.to_i32() {
882            let two = BigRational::new(BigInt::from(2), BigInt::from(1));
883            Some(lhs * two.pow(rhs))
884        } else {
885            None
886        }
887    }
888
889    fn checked_shr(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
890        if let Some(rhs) = rhs.to_i32() {
891            let two = BigRational::new(BigInt::from(2), BigInt::from(1));
892            Some(lhs * two.pow(-rhs))
893        } else {
894            None
895        }
896    }
897
898    pub fn calc_now(time: &Option<SystemTime>) -> MyResult<ValueRef> {
899        let time = time.unwrap_or_else(SystemTime::now)
900            .duration_since(SystemTime::UNIX_EPOCH)
901            .unwrap_or_default()
902            .as_millis();
903        let numer = BigInt::from(time);
904        let denom = BigInt::from(1000);
905        let number = BigRational::new(numer, denom);
906        let result = Self::new(Some(number)).with_meaning(Meaning::Time);
907        Ok(Rc::new(RefCell::new(result)))
908    }
909}
910
911impl Default for Value {
912    fn default() -> Self {
913        Self::new(Some(BigRational::zero()))
914    }
915}
916
917impl Clone for Value {
918    fn clone(&self) -> Self {
919        // Clone everything but the variable name.
920        let number = self.number.clone();
921        let meaning = self.meaning;
922        let comment = self.comment.clone();
923        Self { number, meaning, variable: None, comment }
924    }
925}
926
927impl Debug for Value {
928    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
929        if let Some(number) = &self.number {
930            write!(f, "{}", number::format_ratio(number))?;
931        } else {
932            write!(f, "NaN")?;
933        }
934        if self.meaning != Meaning::Plain {
935            write!(f, " [{}]", self.meaning)?;
936        }
937        if let Some(variable) = &self.variable {
938            write!(f, " = {}", variable)?;
939        }
940        if let Some(comment) = &self.comment {
941            write!(f, " # {}", comment)?;
942        }
943        Ok(())
944    }
945}
946
947// noinspection DuplicatedCode
948#[cfg(test)]
949pub mod tests {
950    use crate::calc::context::{Context, Format, Format::*};
951    use crate::calc::meaning::AreaKind::*;
952    use crate::calc::meaning::DataKind::*;
953    use crate::calc::meaning::DeltaKind::*;
954    use crate::calc::meaning::LengthKind::*;
955    use crate::calc::meaning::MassKind::*;
956    use crate::calc::meaning::PrefixKind::*;
957    use crate::calc::meaning::SpeedKind::*;
958    use crate::calc::meaning::TempKind::*;
959    use crate::calc::meaning::VolumeKind::*;
960    use crate::calc::meaning::{Meaning, Meaning::*};
961    use crate::calc::value::{Value, ValueRef};
962    use crate::regex;
963    use crate::util::number::create_ratio;
964    use num::{BigRational, CheckedMul, CheckedSub, FromPrimitive, ToPrimitive};
965    use pretty_assertions::assert_eq;
966    use std::cell::RefCell;
967    use std::rc::Rc;
968
969    const VALUE_NAN: Value = Value::new(None);
970
971    macro_rules! to_strings {
972        ($($x:expr),*) => {
973            ($($x.to_string()),*)
974        };
975    }
976
977    #[test]
978    fn test_decimal_is_created_from_string_no_separator() {
979        assert_eq!(create_value(0, 1), Value::from_string("0").unwrap());
980        assert_eq!(create_value(123456789, 1), Value::from_string("123456789").unwrap());
981        assert_eq!(create_value(-123456789, 1), Value::from_string("-123456789").unwrap());
982        assert_eq!(create_value(123456789, 100), Value::from_string("1234567.89").unwrap());
983        assert_eq!(create_value(-123456789, 100), Value::from_string("-1234567.89").unwrap());
984        assert_eq!(create_value(999, 1000), Value::from_string(".999").unwrap());
985        assert_eq!(create_value(-999, 1000), Value::from_string("-.999").unwrap());
986        assert!(Value::from_string("").is_err());
987        assert!(Value::from_string("foo").is_err());
988    }
989
990    #[test]
991    fn test_decimal_is_created_from_string_with_separator() {
992        assert_eq!(create_value(123456789, 1), Value::from_string("123,456,789").unwrap());
993        assert_eq!(create_value(123456789, 1), Value::from_string("123_456_789").unwrap());
994        assert_eq!(create_value(-123456789, 1), Value::from_string("-123,456,789").unwrap());
995        assert_eq!(create_value(-123456789, 1), Value::from_string("-123_456_789").unwrap());
996        assert_eq!(create_value(123456789, 100), Value::from_string("1,234,567.89").unwrap());
997        assert_eq!(create_value(123456789, 100), Value::from_string("1_234_567.89").unwrap());
998        assert_eq!(create_value(-123456789, 100), Value::from_string("-1,234,567.89").unwrap());
999        assert_eq!(create_value(-123456789, 100), Value::from_string("-1_234_567.89").unwrap());
1000    }
1001
1002    #[test]
1003    fn test_hexadecimal_is_created_from_lowercase_no_separator() {
1004        assert_eq!(create_value(0, 1), Value::from_string("0x0").unwrap());
1005        assert_eq!(create_value(0xffff, 1), Value::from_string("0xffff").unwrap());
1006        assert_eq!(create_value(0xffffffff, 1), Value::from_string("0xffffffff").unwrap());
1007        assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0xffffffffffff").unwrap());
1008        assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0x0123456789abcdef").unwrap());
1009        assert!(Value::from_string("0x").is_err());
1010        assert!(Value::from_string("0xfoo").is_err());
1011    }
1012
1013    #[test]
1014    fn test_hexadecimal_is_created_from_uppercase_no_separator() {
1015        assert_eq!(create_value(0, 1), Value::from_string("0X0").unwrap());
1016        assert_eq!(create_value(0xffff, 1), Value::from_string("0XFFFF").unwrap());
1017        assert_eq!(create_value(0xffffffff, 1), Value::from_string("0XFFFFFFFF").unwrap());
1018        assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0XFFFFFFFFFFFF").unwrap());
1019        assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0X0123456789ABCDEF").unwrap());
1020        assert!(Value::from_string("0X").is_err());
1021        assert!(Value::from_string("0XFOO").is_err());
1022    }
1023
1024    #[test]
1025    fn test_hexadecimal_is_created_from_lowercase_with_separator() {
1026        assert_eq!(create_value(0, 1), Value::from_string("0x_0").unwrap());
1027        assert_eq!(create_value(0xffff, 1), Value::from_string("0x_ffff").unwrap());
1028        assert_eq!(create_value(0xffffffff, 1), Value::from_string("0x_ffff_ffff").unwrap());
1029        assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0x,ffff,ffff,ffff").unwrap());
1030        assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0x,0123,4567,89ab,cdef").unwrap());
1031        assert!(Value::from_string("0x_").is_err());
1032        assert!(Value::from_string("0x,foo").is_err());
1033    }
1034
1035    #[test]
1036    fn test_hexadecimal_is_created_from_uppercase_with_separator() {
1037        assert_eq!(create_value(0, 1), Value::from_string("0X_0").unwrap());
1038        assert_eq!(create_value(0xffff, 1), Value::from_string("0X_FFFF").unwrap());
1039        assert_eq!(create_value(0xffffffff, 1), Value::from_string("0X_FFFF_FFFF").unwrap());
1040        assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0X,FFFF,FFFF,FFFF").unwrap());
1041        assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0X,0123,4567,89AB,CDEF").unwrap());
1042        assert!(Value::from_string("0X_").is_err());
1043        assert!(Value::from_string("0X,FOO").is_err());
1044    }
1045
1046    #[test]
1047    fn test_time_is_created_from_string_no_zulu() {
1048        let summer1 = Value::from_string("2024-06-30T23:59").unwrap();
1049        let summer2 = Value::from_string("2024-06-30T23:59:59").unwrap();
1050        let summer3 = Value::from_string("2024-06-30T23:59:59.999").unwrap();
1051        let winter1 = Value::from_string("2024-12-31T23:59").unwrap();
1052        let winter2 = Value::from_string("2024-12-31T23:59:59").unwrap();
1053        let winter3 = Value::from_string("2024-12-31T23:59:59.999").unwrap();
1054        assert_eq!(create_value(1719791940000, 1000).with_meaning(Time), summer1);
1055        assert_eq!(create_value(1719791999000, 1000).with_meaning(Time), summer2);
1056        assert_eq!(create_value(1719791999999, 1000).with_meaning(Time), summer3);
1057        assert_eq!(create_value(1735689540000, 1000).with_meaning(Time), winter1);
1058        assert_eq!(create_value(1735689599000, 1000).with_meaning(Time), winter2);
1059        assert_eq!(create_value(1735689599999, 1000).with_meaning(Time), winter3);
1060    }
1061
1062    #[test]
1063    fn test_time_is_created_from_string_with_zulu() {
1064        let summer1 = Value::from_string("2024-06-30T23:59Z").unwrap();
1065        let summer2 = Value::from_string("2024-06-30T23:59:59Z").unwrap();
1066        let summer3 = Value::from_string("2024-06-30T23:59:59.999Z").unwrap();
1067        let winter1 = Value::from_string("2024-12-31T23:59Z").unwrap();
1068        let winter2 = Value::from_string("2024-12-31T23:59:59Z").unwrap();
1069        let winter3 = Value::from_string("2024-12-31T23:59:59.999Z").unwrap();
1070        assert_eq!(create_value(1719791940000, 1000).with_meaning(Time), summer1);
1071        assert_eq!(create_value(1719791999000, 1000).with_meaning(Time), summer2);
1072        assert_eq!(create_value(1719791999999, 1000).with_meaning(Time), summer3);
1073        assert_eq!(create_value(1735689540000, 1000).with_meaning(Time), winter1);
1074        assert_eq!(create_value(1735689599000, 1000).with_meaning(Time), winter2);
1075        assert_eq!(create_value(1735689599999, 1000).with_meaning(Time), winter3);
1076    }
1077
1078    #[test]
1079    fn test_delta_is_created_from_string_old_format() {
1080        let minutes1 = Value::from_string("34:56").unwrap();
1081        let minutes2 = Value::from_string("34:56.7").unwrap();
1082        let minutes3 = Value::from_string("34:56.789").unwrap();
1083        let minutes4 = Value::from_string("-34:56").unwrap();
1084        let minutes5 = Value::from_string("-34:56.7").unwrap();
1085        let minutes6 = Value::from_string("-34:56.789").unwrap();
1086        let hours1 = Value::from_string("12:34:56").unwrap();
1087        let hours2 = Value::from_string("12:34:56.7").unwrap();
1088        let hours3 = Value::from_string("12:34:56.789").unwrap();
1089        let hours4 = Value::from_string("-12:34:56").unwrap();
1090        let hours5 = Value::from_string("-12:34:56.7").unwrap();
1091        let hours6 = Value::from_string("-12:34:56.789").unwrap();
1092        let days1 = Value::from_string("9:12:34:56").unwrap();
1093        let days2 = Value::from_string("9:12:34:56.7").unwrap();
1094        let days3 = Value::from_string("9:12:34:56.789").unwrap();
1095        let days4 = Value::from_string("-9:12:34:56").unwrap();
1096        let days5 = Value::from_string("-9:12:34:56.7").unwrap();
1097        let days6 = Value::from_string("-9:12:34:56.789").unwrap();
1098        assert_eq!(create_value(2096000, 1000).with_meaning(Delta(HMS)), minutes1);
1099        assert_eq!(create_value(2096700, 1000).with_meaning(Delta(HMS)), minutes2);
1100        assert_eq!(create_value(2096789, 1000).with_meaning(Delta(HMS)), minutes3);
1101        assert_eq!(create_value(-2096000, 1000).with_meaning(Delta(HMS)), minutes4);
1102        assert_eq!(create_value(-2096700, 1000).with_meaning(Delta(HMS)), minutes5);
1103        assert_eq!(create_value(-2096789, 1000).with_meaning(Delta(HMS)), minutes6);
1104        assert_eq!(create_value(45296000, 1000).with_meaning(Delta(HMS)), hours1);
1105        assert_eq!(create_value(45296700, 1000).with_meaning(Delta(HMS)), hours2);
1106        assert_eq!(create_value(45296789, 1000).with_meaning(Delta(HMS)), hours3);
1107        assert_eq!(create_value(-45296000, 1000).with_meaning(Delta(HMS)), hours4);
1108        assert_eq!(create_value(-45296700, 1000).with_meaning(Delta(HMS)), hours5);
1109        assert_eq!(create_value(-45296789, 1000).with_meaning(Delta(HMS)), hours6);
1110        assert_eq!(create_value(822896000, 1000).with_meaning(Delta(HMS)), days1);
1111        assert_eq!(create_value(822896700, 1000).with_meaning(Delta(HMS)), days2);
1112        assert_eq!(create_value(822896789, 1000).with_meaning(Delta(HMS)), days3);
1113        assert_eq!(create_value(-822896000, 1000).with_meaning(Delta(HMS)), days4);
1114        assert_eq!(create_value(-822896700, 1000).with_meaning(Delta(HMS)), days5);
1115        assert_eq!(create_value(-822896789, 1000).with_meaning(Delta(HMS)), days6);
1116    }
1117
1118    #[test]
1119    fn test_delta_is_created_from_string_new_format() {
1120        let days1 = Value::from_string("9T12:34:56").unwrap();
1121        let days2 = Value::from_string("9T12:34:56.7").unwrap();
1122        let days3 = Value::from_string("9T12:34:56.789").unwrap();
1123        let days4 = Value::from_string("-9T12:34:56").unwrap();
1124        let days5 = Value::from_string("-9T12:34:56.7").unwrap();
1125        let days6 = Value::from_string("-9T12:34:56.789").unwrap();
1126        assert_eq!(create_value(822896000, 1000).with_meaning(Delta(HMS)), days1);
1127        assert_eq!(create_value(822896700, 1000).with_meaning(Delta(HMS)), days2);
1128        assert_eq!(create_value(822896789, 1000).with_meaning(Delta(HMS)), days3);
1129        assert_eq!(create_value(-822896000, 1000).with_meaning(Delta(HMS)), days4);
1130        assert_eq!(create_value(-822896700, 1000).with_meaning(Delta(HMS)), days5);
1131        assert_eq!(create_value(-822896789, 1000).with_meaning(Delta(HMS)), days6);
1132    }
1133
1134    #[test]
1135    fn test_value_with_repeating_zero_or_nine_is_rounded() {
1136        let number1 = fudge_ratio(create_ratio(17, 8)).and_then(opposite_ratio); // 1.874999999999999801...
1137        let number2 = fudge_ratio(create_ratio(16, 8)).and_then(opposite_ratio); // 1.999999999999999726...
1138        let number3 = fudge_ratio(create_ratio(16, 8)); // 2.000000000000000273...
1139        let number4 = fudge_ratio(create_ratio(17, 8)); // 2.125000000000000198...
1140        assert_eq!(create_value(15, 8), Value::new(number1).with_rounding());
1141        assert_eq!(create_value(16, 8), Value::new(number2).with_rounding());
1142        assert_eq!(create_value(16, 8), Value::new(number3).with_rounding());
1143        assert_eq!(create_value(17, 8), Value::new(number4).with_rounding());
1144    }
1145
1146    #[test]
1147    fn test_value_with_repeating_one_to_eight_is_rounded() {
1148        let number1 = fudge_ratio(create_ratio(908992, 9000)); // 100.999111111111094...
1149        let number2 = fudge_ratio(create_ratio(1088924, 99000)); // 10.999232323232323771...
1150        let number3 = fudge_ratio(create_ratio(1997457, 999000)); // 1.999456456456456483...
1151        let number4 = fudge_ratio(create_ratio(19995891, 9999000)); // 1.999789078907890437...
1152        assert_eq!(create_value(908992, 9000), Value::new(number1).with_rounding());
1153        assert_eq!(create_value(1088924, 99000), Value::new(number2).with_rounding());
1154        assert_eq!(create_value(1997457, 999000), Value::new(number3).with_rounding());
1155        assert_eq!(create_value(19995891, 9999000), Value::new(number4).with_rounding());
1156    }
1157
1158    #[test]
1159    fn test_decimal_is_formatted_with_default() {
1160        assert_eq!(to_strings!("0", ""), format_context(Base10, false, None, 0, 1));
1161        assert_eq!(to_strings!("1", ""), format_context(Base10, false, None, 1, 1));
1162        assert_eq!(to_strings!("12", ""), format_context(Base10, false, None, 12, 1));
1163        assert_eq!(to_strings!("123", ""), format_context(Base10, false, None, 123, 1));
1164        assert_eq!(to_strings!("1234", ""), format_context(Base10, false, None, 1234, 1));
1165        assert_eq!(to_strings!("12345", ""), format_context(Base10, false, None, 12345, 1));
1166        assert_eq!(to_strings!("123456", ""), format_context(Base10, false, None, 123456, 1));
1167        assert_eq!(to_strings!("1234567", ""), format_context(Base10, false, None, 1234567, 1));
1168        assert_eq!(to_strings!("12345678", ""), format_context(Base10, false, None, 12345678, 1));
1169        assert_eq!(to_strings!("123456789", ""), format_context(Base10, false, None, 123456789, 1));
1170        assert_eq!(to_strings!("-1", ""), format_context(Base10, false, None, -1, 1));
1171        assert_eq!(to_strings!("-12", ""), format_context(Base10, false, None, -12, 1));
1172        assert_eq!(to_strings!("-123", ""), format_context(Base10, false, None, -123, 1));
1173        assert_eq!(to_strings!("-1234", ""), format_context(Base10, false, None, -1234, 1));
1174        assert_eq!(to_strings!("-12345", ""), format_context(Base10, false, None, -12345, 1));
1175        assert_eq!(to_strings!("-123456", ""), format_context(Base10, false, None, -123456, 1));
1176        assert_eq!(to_strings!("-1234567", ""), format_context(Base10, false, None, -1234567, 1));
1177        assert_eq!(to_strings!("-12345678", ""), format_context(Base10, false, None, -12345678, 1));
1178        assert_eq!(to_strings!("-123456789", ""), format_context(Base10, false, None, -123456789, 1));
1179        assert_eq!(to_strings!("0", ".00001"), format_context(Base10, false, None, 1, 100000));
1180        assert_eq!(to_strings!("0", ".0001"), format_context(Base10, false, None, 1, 10000));
1181        assert_eq!(to_strings!("0", ".001"), format_context(Base10, false, None, 1, 1000));
1182        assert_eq!(to_strings!("0", ".01"), format_context(Base10, false, None, 1, 100));
1183        assert_eq!(to_strings!("0", ".1"), format_context(Base10, false, None, 1, 10));
1184        assert_eq!(to_strings!("0", ".4994"), format_context(Base10, false, None, 49940, 100000));
1185        assert_eq!(to_strings!("0", ".49949"), format_context(Base10, false, None, 49949, 100000));
1186        assert_eq!(to_strings!("0", ".4995"), format_context(Base10, false, None, 49950, 100000));
1187        assert_eq!(to_strings!("0", ".49951"), format_context(Base10, false, None, 49951, 100000));
1188        assert_eq!(to_strings!("0", ".9"), format_context(Base10, false, None, 9, 10));
1189        assert_eq!(to_strings!("0", ".99"), format_context(Base10, false, None, 99, 100));
1190        assert_eq!(to_strings!("0", ".999"), format_context(Base10, false, None, 999, 1000));
1191        assert_eq!(to_strings!("0", ".9999"), format_context(Base10, false, None, 9999, 10000));
1192        assert_eq!(to_strings!("0", ".99999"), format_context(Base10, false, None, 99999, 100000));
1193        assert_eq!(to_strings!("-0", ".00001"), format_context(Base10, false, None, -1, 100000));
1194        assert_eq!(to_strings!("-0", ".0001"), format_context(Base10, false, None, -1, 10000));
1195        assert_eq!(to_strings!("-0", ".001"), format_context(Base10, false, None, -1, 1000));
1196        assert_eq!(to_strings!("-0", ".01"), format_context(Base10, false, None, -1, 100));
1197        assert_eq!(to_strings!("-0", ".1"), format_context(Base10, false, None, -1, 10));
1198        assert_eq!(to_strings!("-0", ".4994"), format_context(Base10, false, None, -49940, 100000));
1199        assert_eq!(to_strings!("-0", ".49949"), format_context(Base10, false, None, -49949, 100000));
1200        assert_eq!(to_strings!("-0", ".4995"), format_context(Base10, false, None, -49950, 100000));
1201        assert_eq!(to_strings!("-0", ".49951"), format_context(Base10, false, None, -49951, 100000));
1202        assert_eq!(to_strings!("-0", ".9"), format_context(Base10, false, None, -9, 10));
1203        assert_eq!(to_strings!("-0", ".99"), format_context(Base10, false, None, -99, 100));
1204        assert_eq!(to_strings!("-0", ".999"), format_context(Base10, false, None, -999, 1000));
1205        assert_eq!(to_strings!("-0", ".9999"), format_context(Base10, false, None, -9999, 10000));
1206        assert_eq!(to_strings!("-0", ".99999"), format_context(Base10, false, None, -99999, 100000));
1207    }
1208
1209    #[test]
1210    fn test_decimal_is_formatted_with_separator() {
1211        assert_eq!(to_strings!("0", ""), format_context(Base10, true, None, 0, 1));
1212        assert_eq!(to_strings!("1", ""), format_context(Base10, true, None, 1, 1));
1213        assert_eq!(to_strings!("12", ""), format_context(Base10, true, None, 12, 1));
1214        assert_eq!(to_strings!("123", ""), format_context(Base10, true, None, 123, 1));
1215        assert_eq!(to_strings!("1,234", ""), format_context(Base10, true, None, 1234, 1));
1216        assert_eq!(to_strings!("12,345", ""), format_context(Base10, true, None, 12345, 1));
1217        assert_eq!(to_strings!("123,456", ""), format_context(Base10, true, None, 123456, 1));
1218        assert_eq!(to_strings!("1,234,567", ""), format_context(Base10, true, None, 1234567, 1));
1219        assert_eq!(to_strings!("12,345,678", ""), format_context(Base10, true, None, 12345678, 1));
1220        assert_eq!(to_strings!("123,456,789", ""), format_context(Base10, true, None, 123456789, 1));
1221        assert_eq!(to_strings!("-1", ""), format_context(Base10, true, None, -1, 1));
1222        assert_eq!(to_strings!("-12", ""), format_context(Base10, true, None, -12, 1));
1223        assert_eq!(to_strings!("-123", ""), format_context(Base10, true, None, -123, 1));
1224        assert_eq!(to_strings!("-1,234", ""), format_context(Base10, true, None, -1234, 1));
1225        assert_eq!(to_strings!("-12,345", ""), format_context(Base10, true, None, -12345, 1));
1226        assert_eq!(to_strings!("-123,456", ""), format_context(Base10, true, None, -123456, 1));
1227        assert_eq!(to_strings!("-1,234,567", ""), format_context(Base10, true, None, -1234567, 1));
1228        assert_eq!(to_strings!("-12,345,678", ""), format_context(Base10, true, None, -12345678, 1));
1229        assert_eq!(to_strings!("-123,456,789", ""), format_context(Base10, true, None, -123456789, 1));
1230        assert_eq!(to_strings!("0", ".00001"), format_context(Base10, true, None, 1, 100000));
1231        assert_eq!(to_strings!("0", ".0001"), format_context(Base10, true, None, 1, 10000));
1232        assert_eq!(to_strings!("0", ".001"), format_context(Base10, true, None, 1, 1000));
1233        assert_eq!(to_strings!("0", ".01"), format_context(Base10, true, None, 1, 100));
1234        assert_eq!(to_strings!("0", ".1"), format_context(Base10, true, None, 1, 10));
1235        assert_eq!(to_strings!("0", ".4994"), format_context(Base10, true, None, 49940, 100000));
1236        assert_eq!(to_strings!("0", ".49949"), format_context(Base10, true, None, 49949, 100000));
1237        assert_eq!(to_strings!("0", ".4995"), format_context(Base10, true, None, 49950, 100000));
1238        assert_eq!(to_strings!("0", ".49951"), format_context(Base10, true, None, 49951, 100000));
1239        assert_eq!(to_strings!("0", ".9"), format_context(Base10, true, None, 9, 10));
1240        assert_eq!(to_strings!("0", ".99"), format_context(Base10, true, None, 99, 100));
1241        assert_eq!(to_strings!("0", ".999"), format_context(Base10, true, None, 999, 1000));
1242        assert_eq!(to_strings!("0", ".9999"), format_context(Base10, true, None, 9999, 10000));
1243        assert_eq!(to_strings!("0", ".99999"), format_context(Base10, true, None, 99999, 100000));
1244        assert_eq!(to_strings!("-0", ".00001"), format_context(Base10, true, None, -1, 100000));
1245        assert_eq!(to_strings!("-0", ".0001"), format_context(Base10, true, None, -1, 10000));
1246        assert_eq!(to_strings!("-0", ".001"), format_context(Base10, true, None, -1, 1000));
1247        assert_eq!(to_strings!("-0", ".01"), format_context(Base10, true, None, -1, 100));
1248        assert_eq!(to_strings!("-0", ".1"), format_context(Base10, true, None, -1, 10));
1249        assert_eq!(to_strings!("-0", ".4994"), format_context(Base10, true, None, -49940, 100000));
1250        assert_eq!(to_strings!("-0", ".49949"), format_context(Base10, true, None, -49949, 100000));
1251        assert_eq!(to_strings!("-0", ".4995"), format_context(Base10, true, None, -49950, 100000));
1252        assert_eq!(to_strings!("-0", ".49951"), format_context(Base10, true, None, -49951, 100000));
1253        assert_eq!(to_strings!("-0", ".9"), format_context(Base10, true, None, -9, 10));
1254        assert_eq!(to_strings!("-0", ".99"), format_context(Base10, true, None, -99, 100));
1255        assert_eq!(to_strings!("-0", ".999"), format_context(Base10, true, None, -999, 1000));
1256        assert_eq!(to_strings!("-0", ".9999"), format_context(Base10, true, None, -9999, 10000));
1257        assert_eq!(to_strings!("-0", ".99999"), format_context(Base10, true, None, -99999, 100000));
1258    }
1259
1260    #[test]
1261    fn test_decimal_is_formatted_with_precision() {
1262        assert_eq!(to_strings!("0", ".000"), format_context(Base10, false, Some(3), 0, 1));
1263        assert_eq!(to_strings!("1", ".000"), format_context(Base10, false, Some(3), 1, 1));
1264        assert_eq!(to_strings!("12", ".000"), format_context(Base10, false, Some(3), 12, 1));
1265        assert_eq!(to_strings!("123", ".000"), format_context(Base10, false, Some(3), 123, 1));
1266        assert_eq!(to_strings!("1234", ".000"), format_context(Base10, false, Some(3), 1234, 1));
1267        assert_eq!(to_strings!("12345", ".000"), format_context(Base10, false, Some(3), 12345, 1));
1268        assert_eq!(to_strings!("123456", ".000"), format_context(Base10, false, Some(3), 123456, 1));
1269        assert_eq!(to_strings!("1234567", ".000"), format_context(Base10, false, Some(3), 1234567, 1));
1270        assert_eq!(to_strings!("12345678", ".000"), format_context(Base10, false, Some(3), 12345678, 1));
1271        assert_eq!(to_strings!("123456789", ".000"), format_context(Base10, false, Some(3), 123456789, 1));
1272        assert_eq!(to_strings!("-1", ".000"), format_context(Base10, false, Some(3), -1, 1));
1273        assert_eq!(to_strings!("-12", ".000"), format_context(Base10, false, Some(3), -12, 1));
1274        assert_eq!(to_strings!("-123", ".000"), format_context(Base10, false, Some(3), -123, 1));
1275        assert_eq!(to_strings!("-1234", ".000"), format_context(Base10, false, Some(3), -1234, 1));
1276        assert_eq!(to_strings!("-12345", ".000"), format_context(Base10, false, Some(3), -12345, 1));
1277        assert_eq!(to_strings!("-123456", ".000"), format_context(Base10, false, Some(3), -123456, 1));
1278        assert_eq!(to_strings!("-1234567", ".000"), format_context(Base10, false, Some(3), -1234567, 1));
1279        assert_eq!(to_strings!("-12345678", ".000"), format_context(Base10, false, Some(3), -12345678, 1));
1280        assert_eq!(to_strings!("-123456789", ".000"), format_context(Base10, false, Some(3), -123456789, 1));
1281        assert_eq!(to_strings!("0", ".000"), format_context(Base10, false, Some(3), 1, 100000));
1282        assert_eq!(to_strings!("0", ".000"), format_context(Base10, false, Some(3), 1, 10000));
1283        assert_eq!(to_strings!("0", ".001"), format_context(Base10, false, Some(3), 1, 1000));
1284        assert_eq!(to_strings!("0", ".010"), format_context(Base10, false, Some(3), 1, 100));
1285        assert_eq!(to_strings!("0", ".100"), format_context(Base10, false, Some(3), 1, 10));
1286        assert_eq!(to_strings!("0", ".499"), format_context(Base10, false, Some(3), 49940, 100000));
1287        assert_eq!(to_strings!("0", ".499"), format_context(Base10, false, Some(3), 49949, 100000));
1288        assert_eq!(to_strings!("0", ".500"), format_context(Base10, false, Some(3), 49950, 100000));
1289        assert_eq!(to_strings!("0", ".500"), format_context(Base10, false, Some(3), 49951, 100000));
1290        assert_eq!(to_strings!("0", ".900"), format_context(Base10, false, Some(3), 9, 10));
1291        assert_eq!(to_strings!("0", ".990"), format_context(Base10, false, Some(3), 99, 100));
1292        assert_eq!(to_strings!("0", ".999"), format_context(Base10, false, Some(3), 999, 1000));
1293        assert_eq!(to_strings!("1", ".000"), format_context(Base10, false, Some(3), 9999, 10000));
1294        assert_eq!(to_strings!("1", ".000"), format_context(Base10, false, Some(3), 99999, 100000));
1295        assert_eq!(to_strings!("0", ".000"), format_context(Base10, false, Some(3), -1, 100000));
1296        assert_eq!(to_strings!("0", ".000"), format_context(Base10, false, Some(3), -1, 10000));
1297        assert_eq!(to_strings!("-0", ".001"), format_context(Base10, false, Some(3), -1, 1000));
1298        assert_eq!(to_strings!("-0", ".010"), format_context(Base10, false, Some(3), -1, 100));
1299        assert_eq!(to_strings!("-0", ".100"), format_context(Base10, false, Some(3), -1, 10));
1300        assert_eq!(to_strings!("-0", ".499"), format_context(Base10, false, Some(3), -49940, 100000));
1301        assert_eq!(to_strings!("-0", ".499"), format_context(Base10, false, Some(3), -49949, 100000));
1302        assert_eq!(to_strings!("-0", ".500"), format_context(Base10, false, Some(3), -49950, 100000));
1303        assert_eq!(to_strings!("-0", ".500"), format_context(Base10, false, Some(3), -49951, 100000));
1304        assert_eq!(to_strings!("-0", ".900"), format_context(Base10, false, Some(3), -9, 10));
1305        assert_eq!(to_strings!("-0", ".990"), format_context(Base10, false, Some(3), -99, 100));
1306        assert_eq!(to_strings!("-0", ".999"), format_context(Base10, false, Some(3), -999, 1000));
1307        assert_eq!(to_strings!("-1", ".000"), format_context(Base10, false, Some(3), -9999, 10000));
1308        assert_eq!(to_strings!("-1", ".000"), format_context(Base10, false, Some(3), -99999, 100000));
1309    }
1310
1311    #[test]
1312    fn test_recurring_is_formatted_with_precision() {
1313        let expected = regex!(r"^\.6+$");
1314        let value = create_value(2, 3);
1315        let format = |dp: Option<u8>| {
1316            let context = Context::new().with_dp(dp);
1317            let (_, fraction, _, _, _) = value.to_strings(&context);
1318            return fraction;
1319        };
1320        assert_eq!(String::from(""), format(Some(0)));
1321        assert_eq!(String::from(".666667"), format(Some(6)));
1322        assert_eq!(expected.is_match(&format(None)), true);
1323    }
1324
1325    #[test]
1326    fn test_hexadecimal_is_formatted_with_default() {
1327        assert_eq!(to_strings!("0x000000000000000000000000", ""), format_context(Base16(3), false, None, 0, 1));
1328        assert_eq!(to_strings!("0x000000000000000000000001", ""), format_context(Base16(3), false, None, 1, 1));
1329        assert_eq!(to_strings!("0x00000000000000007ffffffe", ""), format_context(Base16(3), false, None, 2147483646, 1));
1330        assert_eq!(to_strings!("0x00000000000000007fffffff", ""), format_context(Base16(3), false, None, 2147483647, 1));
1331        assert_eq!(to_strings!("0x000000000000000080000000", ""), format_context(Base16(3), false, None, 2147483648, 1));
1332        assert_eq!(to_strings!("0x000000000000000080000001", ""), format_context(Base16(3), false, None, 2147483649, 1));
1333        assert_eq!(to_strings!("0x0000000000000000fffffffe", ""), format_context(Base16(3), false, None, 4294967294, 1));
1334        assert_eq!(to_strings!("0x0000000000000000ffffffff", ""), format_context(Base16(3), false, None, 4294967295, 1));
1335        assert_eq!(to_strings!("0x000000000000000100000000", ""), format_context(Base16(3), false, None, 4294967296, 1));
1336        assert_eq!(to_strings!("0x000000000000000100000001", ""), format_context(Base16(3), false, None, 4294967297, 1));
1337        assert_eq!(to_strings!("0x000000007ffffffffffffffe", ""), format_context(Base16(3), false, None, 9223372036854775806, 1));
1338        assert_eq!(to_strings!("0x000000007fffffffffffffff", ""), format_context(Base16(3), false, None, 9223372036854775807, 1));
1339        assert_eq!(to_strings!("0x000000008000000000000000", ""), format_context(Base16(3), false, None, 9223372036854775808, 1));
1340        assert_eq!(to_strings!("0x000000008000000000000001", ""), format_context(Base16(3), false, None, 9223372036854775809, 1));
1341        assert_eq!(to_strings!("0x00000000fffffffffffffffe", ""), format_context(Base16(3), false, None, 18446744073709551614, 1));
1342        assert_eq!(to_strings!("0x00000000ffffffffffffffff", ""), format_context(Base16(3), false, None, 18446744073709551615, 1));
1343        assert_eq!(to_strings!("0x000000010000000000000000", ""), format_context(Base16(3), false, None, 18446744073709551616, 1));
1344        assert_eq!(to_strings!("0x000000010000000000000001", ""), format_context(Base16(3), false, None, 18446744073709551617, 1));
1345        assert_eq!(to_strings!("0xffffffff0000000000000000", ""), format_context(Base16(3), false, None, -18446744073709551616, 1));
1346        assert_eq!(to_strings!("0xffffffff0000000000000001", ""), format_context(Base16(3), false, None, -18446744073709551615, 1));
1347        assert_eq!(to_strings!("0xffffffff8000000000000000", ""), format_context(Base16(3), false, None, -9223372036854775808, 1));
1348        assert_eq!(to_strings!("0xffffffff8000000000000001", ""), format_context(Base16(3), false, None, -9223372036854775807, 1));
1349        assert_eq!(to_strings!("0xffffffffffffffff00000000", ""), format_context(Base16(3), false, None, -4294967296, 1));
1350        assert_eq!(to_strings!("0xffffffffffffffff00000001", ""), format_context(Base16(3), false, None, -4294967295, 1));
1351        assert_eq!(to_strings!("0xffffffffffffffff80000000", ""), format_context(Base16(3), false, None, -2147483648, 1));
1352        assert_eq!(to_strings!("0xffffffffffffffff80000001", ""), format_context(Base16(3), false, None, -2147483647, 1));
1353        assert_eq!(to_strings!("0xfffffffffffffffffffffffe", ""), format_context(Base16(3), false, None, -2, 1));
1354        assert_eq!(to_strings!("0xffffffffffffffffffffffff", ""), format_context(Base16(3), false, None, -1, 1));
1355    }
1356
1357    #[test]
1358    fn test_hexadecimal_is_formatted_with_separator() {
1359        assert_eq!(to_strings!("0x,00000000,00000000,00000000", ""), format_context(Base16(3), true, None, 0, 1));
1360        assert_eq!(to_strings!("0x,00000000,00000000,00000001", ""), format_context(Base16(3), true, None, 1, 1));
1361        assert_eq!(to_strings!("0x,00000000,00000000,7ffffffe", ""), format_context(Base16(3), true, None, 2147483646, 1));
1362        assert_eq!(to_strings!("0x,00000000,00000000,7fffffff", ""), format_context(Base16(3), true, None, 2147483647, 1));
1363        assert_eq!(to_strings!("0x,00000000,00000000,80000000", ""), format_context(Base16(3), true, None, 2147483648, 1));
1364        assert_eq!(to_strings!("0x,00000000,00000000,80000001", ""), format_context(Base16(3), true, None, 2147483649, 1));
1365        assert_eq!(to_strings!("0x,00000000,00000000,fffffffe", ""), format_context(Base16(3), true, None, 4294967294, 1));
1366        assert_eq!(to_strings!("0x,00000000,00000000,ffffffff", ""), format_context(Base16(3), true, None, 4294967295, 1));
1367        assert_eq!(to_strings!("0x,00000000,00000001,00000000", ""), format_context(Base16(3), true, None, 4294967296, 1));
1368        assert_eq!(to_strings!("0x,00000000,00000001,00000001", ""), format_context(Base16(3), true, None, 4294967297, 1));
1369        assert_eq!(to_strings!("0x,00000000,7fffffff,fffffffe", ""), format_context(Base16(3), true, None, 9223372036854775806, 1));
1370        assert_eq!(to_strings!("0x,00000000,7fffffff,ffffffff", ""), format_context(Base16(3), true, None, 9223372036854775807, 1));
1371        assert_eq!(to_strings!("0x,00000000,80000000,00000000", ""), format_context(Base16(3), true, None, 9223372036854775808, 1));
1372        assert_eq!(to_strings!("0x,00000000,80000000,00000001", ""), format_context(Base16(3), true, None, 9223372036854775809, 1));
1373        assert_eq!(to_strings!("0x,00000000,ffffffff,fffffffe", ""), format_context(Base16(3), true, None, 18446744073709551614, 1));
1374        assert_eq!(to_strings!("0x,00000000,ffffffff,ffffffff", ""), format_context(Base16(3), true, None, 18446744073709551615, 1));
1375        assert_eq!(to_strings!("0x,00000001,00000000,00000000", ""), format_context(Base16(3), true, None, 18446744073709551616, 1));
1376        assert_eq!(to_strings!("0x,00000001,00000000,00000001", ""), format_context(Base16(3), true, None, 18446744073709551617, 1));
1377        assert_eq!(to_strings!("0x,ffffffff,00000000,00000000", ""), format_context(Base16(3), true, None, -18446744073709551616, 1));
1378        assert_eq!(to_strings!("0x,ffffffff,00000000,00000001", ""), format_context(Base16(3), true, None, -18446744073709551615, 1));
1379        assert_eq!(to_strings!("0x,ffffffff,80000000,00000000", ""), format_context(Base16(3), true, None, -9223372036854775808, 1));
1380        assert_eq!(to_strings!("0x,ffffffff,80000000,00000001", ""), format_context(Base16(3), true, None, -9223372036854775807, 1));
1381        assert_eq!(to_strings!("0x,ffffffff,ffffffff,00000000", ""), format_context(Base16(3), true, None, -4294967296, 1));
1382        assert_eq!(to_strings!("0x,ffffffff,ffffffff,00000001", ""), format_context(Base16(3), true, None, -4294967295, 1));
1383        assert_eq!(to_strings!("0x,ffffffff,ffffffff,80000000", ""), format_context(Base16(3), true, None, -2147483648, 1));
1384        assert_eq!(to_strings!("0x,ffffffff,ffffffff,80000001", ""), format_context(Base16(3), true, None, -2147483647, 1));
1385        assert_eq!(to_strings!("0x,ffffffff,ffffffff,fffffffe", ""), format_context(Base16(3), true, None, -2, 1));
1386        assert_eq!(to_strings!("0x,ffffffff,ffffffff,ffffffff", ""), format_context(Base16(3), true, None, -1, 1));
1387    }
1388
1389    #[test]
1390    fn test_hexadecimal_is_measured_from_valid() {
1391        assert_eq!(1, create_value(0, 1).measure_hexadecimal()); // "00000000"
1392        assert_eq!(1, create_value(1, 1).measure_hexadecimal()); // "00000001"
1393        assert_eq!(1, create_value(2147483646, 1).measure_hexadecimal()); // "7ffffffe"
1394        assert_eq!(1, create_value(2147483647, 1).measure_hexadecimal()); // "7fffffff"
1395        assert_eq!(2, create_value(2147483648, 1).measure_hexadecimal()); // "00000000 80000000"
1396        assert_eq!(2, create_value(2147483649, 1).measure_hexadecimal()); // "00000000 80000001"
1397        assert_eq!(2, create_value(4294967294, 1).measure_hexadecimal()); // "00000000 fffffffe"
1398        assert_eq!(2, create_value(4294967295, 1).measure_hexadecimal()); // "00000000 ffffffff"
1399        assert_eq!(2, create_value(4294967296, 1).measure_hexadecimal()); // "00000001 00000000"
1400        assert_eq!(2, create_value(4294967297, 1).measure_hexadecimal()); // "00000001 00000001"
1401        assert_eq!(2, create_value(9223372036854775806, 1).measure_hexadecimal()); // "7fffffff fffffffe"
1402        assert_eq!(2, create_value(9223372036854775807, 1).measure_hexadecimal()); // "7fffffff ffffffff"
1403        assert_eq!(3, create_value(9223372036854775808, 1).measure_hexadecimal()); // "00000000 80000000 00000000"
1404        assert_eq!(3, create_value(9223372036854775809, 1).measure_hexadecimal()); // "00000000 80000000 00000001"
1405        assert_eq!(3, create_value(18446744073709551614, 1).measure_hexadecimal()); // "00000000 ffffffff fffffffe"
1406        assert_eq!(3, create_value(18446744073709551615, 1).measure_hexadecimal()); // "00000000 ffffffff ffffffff"
1407        assert_eq!(3, create_value(18446744073709551616, 1).measure_hexadecimal()); // "00000001 00000000 00000000"
1408        assert_eq!(3, create_value(18446744073709551617, 1).measure_hexadecimal()); // "00000001 00000000 00000001"
1409        assert_eq!(3, create_value(-18446744073709551616, 1).measure_hexadecimal()); // "ffffffff 00000000 00000000"
1410        assert_eq!(3, create_value(-18446744073709551615, 1).measure_hexadecimal()); // "ffffffff 00000000 00000001"
1411        assert_eq!(2, create_value(-9223372036854775808, 1).measure_hexadecimal()); // "80000000 00000000"
1412        assert_eq!(2, create_value(-9223372036854775807, 1).measure_hexadecimal()); // "80000000 00000001"
1413        assert_eq!(2, create_value(-4294967296, 1).measure_hexadecimal()); // "ffffffff 00000000"
1414        assert_eq!(2, create_value(-4294967295, 1).measure_hexadecimal()); // "ffffffff 00000001"
1415        assert_eq!(1, create_value(-2147483648, 1).measure_hexadecimal()); // "80000000"
1416        assert_eq!(1, create_value(-2147483647, 1).measure_hexadecimal()); // "80000001"
1417        assert_eq!(1, create_value(-2, 1).measure_hexadecimal()); // "fffffffe"
1418        assert_eq!(1, create_value(-1, 1).measure_hexadecimal()); // "ffffffff"
1419    }
1420
1421    #[test]
1422    fn test_time_is_formatted_as_iso_8601() {
1423        assert_eq!(to_strings!("2024-06-30T12:00:00", ".000Z", ""), format_meaning(Time, 1719748800000, 1000));
1424        assert_eq!(to_strings!("2024-06-30T12:00:00", ".987Z", ""), format_meaning(Time, 1719748800987, 1000));
1425        assert_eq!(to_strings!("2024-12-31T12:00:00", ".000Z", ""), format_meaning(Time, 1735646400000, 1000));
1426        assert_eq!(to_strings!("2024-12-31T12:00:00", ".987Z", ""), format_meaning(Time, 1735646400987, 1000));
1427    }
1428
1429    #[test]
1430    fn test_delta_is_formatted_as_iso_8601() {
1431        assert_eq!(to_strings!("00", ".000", ""), format_meaning(Delta(HMS), 0, 1));
1432        assert_eq!(to_strings!("59", ".999", ""), format_meaning(Delta(HMS), 59999, 1000));
1433        assert_eq!(to_strings!("01:00", ".000", ""), format_meaning(Delta(HMS), 60000, 1000));
1434        assert_eq!(to_strings!("59:59", ".999", ""), format_meaning(Delta(HMS), 3599999, 1000));
1435        assert_eq!(to_strings!("01:00:00", ".000", ""), format_meaning(Delta(HMS), 3600000, 1000));
1436        assert_eq!(to_strings!("23:59:59", ".999", ""), format_meaning(Delta(HMS), 86399999, 1000));
1437        assert_eq!(to_strings!("1T00:00:00", ".000", ""), format_meaning(Delta(HMS), 86400000, 1000));
1438        assert_eq!(to_strings!("100T00:00:00", ".000", ""), format_meaning(Delta(HMS), 8640000000, 1000));
1439        assert_eq!(to_strings!("-59", ".999", ""), format_meaning(Delta(HMS), -59999, 1000));
1440        assert_eq!(to_strings!("-01:00", ".000", ""), format_meaning(Delta(HMS), -60000, 1000));
1441        assert_eq!(to_strings!("-59:59", ".999", ""), format_meaning(Delta(HMS), -3599999, 1000));
1442        assert_eq!(to_strings!("-01:00:00", ".000", ""), format_meaning(Delta(HMS), -3600000, 1000));
1443        assert_eq!(to_strings!("-23:59:59", ".999", ""), format_meaning(Delta(HMS), -86399999, 1000));
1444        assert_eq!(to_strings!("-1T00:00:00", ".000", ""), format_meaning(Delta(HMS), -86400000, 1000));
1445        assert_eq!(to_strings!("-100T00:00:00", ".000", ""), format_meaning(Delta(HMS), -8640000000, 1000));
1446    }
1447
1448    #[test]
1449    fn test_prefix_is_formatted_with_unit() {
1450        assert_eq!(to_strings!("1", "", "Qm"), format_meaning(Length(Metre(Quetta)), 1, 1));
1451        assert_eq!(to_strings!("1", "", "Rm"), format_meaning(Length(Metre(Ronna)), 1, 1));
1452        assert_eq!(to_strings!("1", "", "Ym"), format_meaning(Length(Metre(Yotta)), 1, 1));
1453        assert_eq!(to_strings!("1", "", "Zm"), format_meaning(Length(Metre(Zetta)), 1, 1));
1454        assert_eq!(to_strings!("1", "", "Em"), format_meaning(Length(Metre(Exa)), 1, 1));
1455        assert_eq!(to_strings!("1", "", "Pm"), format_meaning(Length(Metre(Peta)), 1, 1));
1456        assert_eq!(to_strings!("1", "", "Tm"), format_meaning(Length(Metre(Tera)), 1, 1));
1457        assert_eq!(to_strings!("1", "", "Gm"), format_meaning(Length(Metre(Giga)), 1, 1));
1458        assert_eq!(to_strings!("1", "", "Mm"), format_meaning(Length(Metre(Mega)), 1, 1));
1459        assert_eq!(to_strings!("1", "", "km"), format_meaning(Length(Metre(Kilo)), 1, 1));
1460        assert_eq!(to_strings!("1", "", "hm"), format_meaning(Length(Metre(Hecto)), 1, 1));
1461        assert_eq!(to_strings!("1", "", "dam"), format_meaning(Length(Metre(Deca)), 1, 1));
1462        assert_eq!(to_strings!("1", "", "m"), format_meaning(Length(Metre(Unit)), 1, 1));
1463        assert_eq!(to_strings!("1", "", "dm"), format_meaning(Length(Metre(Deci)), 1, 1));
1464        assert_eq!(to_strings!("1", "", "cm"), format_meaning(Length(Metre(Centi)), 1, 1));
1465        assert_eq!(to_strings!("1", "", "mm"), format_meaning(Length(Metre(Milli)), 1, 1));
1466        assert_eq!(to_strings!("1", "", "um"), format_meaning(Length(Metre(Micro)), 1, 1));
1467        assert_eq!(to_strings!("1", "", "nm"), format_meaning(Length(Metre(Nano)), 1, 1));
1468        assert_eq!(to_strings!("1", "", "pm"), format_meaning(Length(Metre(Pico)), 1, 1));
1469        assert_eq!(to_strings!("1", "", "fm"), format_meaning(Length(Metre(Femto)), 1, 1));
1470        assert_eq!(to_strings!("1", "", "am"), format_meaning(Length(Metre(Atto)), 1, 1));
1471        assert_eq!(to_strings!("1", "", "zm"), format_meaning(Length(Metre(Zepto)), 1, 1));
1472        assert_eq!(to_strings!("1", "", "ym"), format_meaning(Length(Metre(Yocto)), 1, 1));
1473        assert_eq!(to_strings!("1", "", "rm"), format_meaning(Length(Metre(Ronto)), 1, 1));
1474        assert_eq!(to_strings!("1", "", "qm"), format_meaning(Length(Metre(Quecto)), 1, 1));
1475    }
1476
1477    #[test]
1478    fn test_delta_is_formatted_with_unit() {
1479        assert_eq!(to_strings!("1", "", "s"), format_meaning(Delta(Second(Unit)), 1, 1));
1480        assert_eq!(to_strings!("1", "", "ms"), format_meaning(Delta(Second(Milli)), 1, 1));
1481        assert_eq!(to_strings!("1", "", "minute"), format_meaning(Delta(Minute), 1, 1));
1482        assert_eq!(to_strings!("1", "", "hour"), format_meaning(Delta(Hour), 1, 1));
1483        assert_eq!(to_strings!("1", "", "day"), format_meaning(Delta(Day), 1, 1));
1484        assert_eq!(to_strings!("1", "", "week"), format_meaning(Delta(Week), 1, 1));
1485        assert_eq!(to_strings!("1", "", "month"), format_meaning(Delta(Month), 1, 1));
1486        assert_eq!(to_strings!("1", "", "year"), format_meaning(Delta(Year), 1, 1));
1487    }
1488
1489    #[test]
1490    fn test_length_is_formatted_with_unit() {
1491        assert_eq!(to_strings!("1", "", "m"), format_meaning(Length(Metre(Unit)), 1, 1));
1492        assert_eq!(to_strings!("1", "", "km"), format_meaning(Length(Metre(Kilo)), 1, 1));
1493        assert_eq!(to_strings!("1", "", "inch"), format_meaning(Length(Inch), 1, 1));
1494        assert_eq!(to_strings!("1", "", "foot"), format_meaning(Length(Foot), 1, 1));
1495        assert_eq!(to_strings!("1", "", "yard"), format_meaning(Length(Yard), 1, 1));
1496        assert_eq!(to_strings!("1", "", "mile"), format_meaning(Length(Mile), 1, 1));
1497    }
1498
1499    #[test]
1500    fn test_area_is_formatted_with_unit() {
1501        assert_eq!(to_strings!("1", "", "m^2"), format_meaning(Area(Square(Metre(Unit))), 1, 1));
1502        assert_eq!(to_strings!("1", "", "km^2"), format_meaning(Area(Square(Metre(Kilo))), 1, 1));
1503        assert_eq!(to_strings!("1", "", "mile^2"), format_meaning(Area(Square(Mile)), 1, 1));
1504        assert_eq!(to_strings!("1", "", "hectare"), format_meaning(Area(Hectare), 1, 1));
1505        assert_eq!(to_strings!("1", "", "acre"), format_meaning(Area(Acre), 1, 1));
1506    }
1507
1508    #[test]
1509    fn test_volume_is_formatted_with_unit() {
1510        assert_eq!(to_strings!("1", "", "m^3"), format_meaning(Volume(Cubic(Metre(Unit))), 1, 1));
1511        assert_eq!(to_strings!("1", "", "km^3"), format_meaning(Volume(Cubic(Metre(Kilo))), 1, 1));
1512        assert_eq!(to_strings!("1", "", "mile^3"), format_meaning(Volume(Cubic(Mile)), 1, 1));
1513        assert_eq!(to_strings!("1", "", "l"), format_meaning(Volume(Litre(Unit)), 1, 1));
1514        assert_eq!(to_strings!("1", "", "ml"), format_meaning(Volume(Litre(Milli)), 1, 1));
1515        assert_eq!(to_strings!("1", "", "tsp"), format_meaning(Volume(Tsp), 1, 1));
1516        assert_eq!(to_strings!("1", "", "tbsp"), format_meaning(Volume(Tbsp), 1, 1));
1517        assert_eq!(to_strings!("1", "", "floz"), format_meaning(Volume(Floz), 1, 1));
1518        assert_eq!(to_strings!("1", "", "pint"), format_meaning(Volume(Pint), 1, 1));
1519        assert_eq!(to_strings!("1", "", "quart"), format_meaning(Volume(Quart), 1, 1));
1520        assert_eq!(to_strings!("1", "", "gallon"), format_meaning(Volume(Gallon), 1, 1));
1521        assert_eq!(to_strings!("1", "", "barrel"), format_meaning(Volume(Barrel), 1, 1));
1522    }
1523
1524    #[test]
1525    fn test_speed_is_formatted_with_unit() {
1526        assert_eq!(to_strings!("1", "", "m/s"), format_meaning(Speed(Ratio(Metre(Unit), Second(Unit))), 1, 1));
1527        assert_eq!(to_strings!("1", "", "m/hour"), format_meaning(Speed(Ratio(Metre(Unit), Hour)), 1, 1));
1528        assert_eq!(to_strings!("1", "", "km/s"), format_meaning(Speed(Ratio(Metre(Kilo), Second(Unit))), 1, 1));
1529        assert_eq!(to_strings!("1", "", "km/hour"), format_meaning(Speed(Ratio(Metre(Kilo), Hour)), 1, 1));
1530        assert_eq!(to_strings!("1", "", "mile/s"), format_meaning(Speed(Ratio(Mile, Second(Unit))), 1, 1));
1531        assert_eq!(to_strings!("1", "", "mile/hour"), format_meaning(Speed(Ratio(Mile, Hour)), 1, 1));
1532        assert_eq!(to_strings!("1", "", "mach"), format_meaning(Speed(Mach), 1, 1));
1533        assert_eq!(to_strings!("1", "", "light"), format_meaning(Speed(Light), 1, 1));
1534    }
1535
1536    #[test]
1537    fn test_mass_is_formatted_with_unit() {
1538        assert_eq!(to_strings!("1", "", "g"), format_meaning(Mass(Gram(Unit)), 1, 1));
1539        assert_eq!(to_strings!("1", "", "kg"), format_meaning(Mass(Gram(Kilo)), 1, 1));
1540        assert_eq!(to_strings!("1", "", "ounce"), format_meaning(Mass(Ounce), 1, 1));
1541        assert_eq!(to_strings!("1", "", "pound"), format_meaning(Mass(Pound), 1, 1));
1542        assert_eq!(to_strings!("1", "", "stone"), format_meaning(Mass(Stone), 1, 1));
1543        assert_eq!(to_strings!("1", "", "ton"), format_meaning(Mass(Ton), 1, 1));
1544    }
1545
1546    #[test]
1547    fn test_temp_is_formatted_with_unit() {
1548        assert_eq!(to_strings!("1", "", "K"), format_meaning(Temp(Kelvin(Unit)), 1, 1));
1549        assert_eq!(to_strings!("1", "", "mK"), format_meaning(Temp(Kelvin(Milli)), 1, 1));
1550        assert_eq!(to_strings!("1", "", "C"), format_meaning(Temp(Celsius), 1, 1));
1551        assert_eq!(to_strings!("1", "", "F"), format_meaning(Temp(Fahrenheit), 1, 1));
1552        assert_eq!(to_strings!("1", "", "R"), format_meaning(Temp(Rankine), 1, 1));
1553    }
1554
1555    #[test]
1556    fn test_data_is_formatted_with_unit() {
1557        assert_eq!(to_strings!("1", "", "B"), format_meaning(Data(Byte(Unit)), 1, 1));
1558        assert_eq!(to_strings!("1", "", "kB"), format_meaning(Data(Byte(Kilo)), 1, 1));
1559        assert_eq!(to_strings!("1", "", "bit"), format_meaning(Data(Bit), 1, 1));
1560    }
1561
1562    #[test]
1563    fn test_decimal_is_formatted_from_nan() {
1564        let expected = (String::from("NaN"), String::from(""), None, None, None);
1565        let context = Context::new();
1566        let actual = VALUE_NAN.to_strings(&context);
1567        assert_eq!(expected, actual);
1568    }
1569
1570    #[test]
1571    fn test_hexadecimal_is_measured_from_nan() {
1572        assert_eq!(1, VALUE_NAN.measure_hexadecimal());
1573    }
1574
1575    #[test]
1576    fn test_plain_values_are_cast_to_unit() {
1577        assert_eq!(test_apply_meaning(Plain, Plain), Some(create_ratio(1, 1)));
1578        assert_eq!(test_apply_meaning(Plain, Time), Some(create_ratio(1, 1)));
1579        assert_eq!(test_apply_meaning(Plain, Delta(Hour)), Some(create_ratio(1, 1)));
1580        assert_eq!(test_apply_meaning(Plain, Length(Mile)), Some(create_ratio(1, 1)));
1581        assert_eq!(test_apply_meaning(Plain, Area(Acre)), Some(create_ratio(1, 1)));
1582        assert_eq!(test_apply_meaning(Plain, Volume(Pint)), Some(create_ratio(1, 1)));
1583        assert_eq!(test_apply_meaning(Plain, Speed(Light)), Some(create_ratio(1, 1)));
1584        assert_eq!(test_apply_meaning(Plain, Mass(Ounce)), Some(create_ratio(1, 1)));
1585        assert_eq!(test_apply_meaning(Plain, Temp(Rankine)), Some(create_ratio(1, 1)));
1586        assert_eq!(test_apply_meaning(Plain, Data(Bit)), Some(create_ratio(1, 1)));
1587    }
1588
1589    #[test]
1590    fn test_unit_values_are_cast_to_plain() {
1591        assert_eq!(test_apply_meaning(Plain, Plain), Some(create_ratio(1, 1)));
1592        assert_eq!(test_apply_meaning(Time, Plain), Some(create_ratio(1, 1)));
1593        assert_eq!(test_apply_meaning(Delta(Hour), Plain), Some(create_ratio(1, 1)));
1594        assert_eq!(test_apply_meaning(Length(Mile), Plain), Some(create_ratio(1, 1)));
1595        assert_eq!(test_apply_meaning(Area(Acre), Plain), Some(create_ratio(1, 1)));
1596        assert_eq!(test_apply_meaning(Volume(Pint), Plain), Some(create_ratio(1, 1)));
1597        assert_eq!(test_apply_meaning(Speed(Light), Plain), Some(create_ratio(1, 1)));
1598        assert_eq!(test_apply_meaning(Mass(Ounce), Plain), Some(create_ratio(1, 1)));
1599        assert_eq!(test_apply_meaning(Temp(Rankine), Plain), Some(create_ratio(1, 1)));
1600        assert_eq!(test_apply_meaning(Data(Bit), Plain), Some(create_ratio(1, 1)));
1601    }
1602
1603    #[test]
1604    fn test_unit_values_are_cast_to_unit() {
1605        assert_eq!(test_apply_meaning(Delta(Hour), Delta(Second(Unit))), Some(create_ratio(3600, 1)));
1606        assert_eq!(test_apply_meaning(Length(Mile), Length(Metre(Unit))), Some(create_ratio(16093440, 10000)));
1607        assert_eq!(test_apply_meaning(Area(Acre), Area(Square(Metre(Unit)))), Some(create_ratio(40468564224, 10000000)));
1608        assert_eq!(test_apply_meaning(Volume(Pint), Volume(Cubic(Metre(Unit)))), Some(create_ratio(568261250, 1000000000000)));
1609        assert_eq!(test_apply_meaning(Speed(Light), Speed(Ratio(Metre(Unit), Second(Unit)))), Some(create_ratio(299792458, 1)));
1610        assert_eq!(test_apply_meaning(Mass(Ounce), Mass(Gram(Unit))), Some(create_ratio(28349523125, 1000000000)));
1611        assert_eq!(test_apply_meaning(Temp(Rankine), Temp(Kelvin(Unit))), Some(create_ratio(5, 9)));
1612        assert_eq!(test_apply_meaning(Data(Bit), Data(Byte(Unit))), Some(create_ratio(1, 8)));
1613    }
1614
1615    fn test_apply_meaning(old: Meaning, new: Meaning) -> Option<BigRational> {
1616        let value = create_value(1, 1).with_meaning(old);
1617        let result = value.apply_meaning(new).ok()?;
1618        let result = result.borrow().number.clone();
1619        result
1620    }
1621
1622    #[test]
1623    fn test_plain_values_are_added_by_value() {
1624        assert_eq!(Value::calc_add(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(8, 1)));
1625        assert_eq!(Value::calc_add(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1626        assert_eq!(Value::calc_add(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1627        assert_eq!(Value::calc_add(create_nan(), create_nan()).ok(), Some(create_nan()));
1628    }
1629
1630    #[test]
1631    fn test_plain_values_are_subtracted_by_value() {
1632        assert_eq!(Value::calc_sub(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(3, 1)));
1633        assert_eq!(Value::calc_sub(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1634        assert_eq!(Value::calc_sub(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1635        assert_eq!(Value::calc_sub(create_nan(), create_nan()).ok(), Some(create_nan()));
1636    }
1637
1638    #[test]
1639    fn test_plain_values_are_multiplied_by_value() {
1640        assert_eq!(Value::calc_mul(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(1375, 100)));
1641        assert_eq!(Value::calc_mul(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1642        assert_eq!(Value::calc_mul(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1643        assert_eq!(Value::calc_mul(create_nan(), create_nan()).ok(), Some(create_nan()));
1644    }
1645
1646    #[test]
1647    fn test_plain_values_are_divided_by_value() {
1648        assert_eq!(Value::calc_div(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(22, 10)));
1649        assert_eq!(Value::calc_div(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1650        assert_eq!(Value::calc_div(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1651        assert_eq!(Value::calc_div(create_nan(), create_nan()).ok(), Some(create_nan()));
1652    }
1653
1654    #[test]
1655    fn test_plain_values_are_divided_by_zero() {
1656        assert_eq!(Value::calc_div(create_ref(55, 10), create_ref(0, 1)).ok(), Some(create_nan()));
1657        assert_eq!(Value::calc_div(create_nan(), create_ref(0, 1)).ok(), Some(create_nan()));
1658    }
1659
1660    #[test]
1661    fn test_plain_values_are_remaindered_by_value() {
1662        assert_eq!(Value::calc_mod(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(5, 10)));
1663        assert_eq!(Value::calc_mod(create_ref(55, 10), create_ref(-25, 10)).ok(), Some(create_ref(5, 10)));
1664        assert_eq!(Value::calc_mod(create_ref(-55, 10), create_ref(25, 10)).ok(), Some(create_ref(-5, 10)));
1665        assert_eq!(Value::calc_mod(create_ref(-55, 10), create_ref(-25, 10)).ok(), Some(create_ref(-5, 10)));
1666        assert_eq!(Value::calc_mod(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1667        assert_eq!(Value::calc_mod(create_ref(-55, 10), create_nan()).ok(), Some(create_nan()));
1668        assert_eq!(Value::calc_mod(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1669        assert_eq!(Value::calc_mod(create_nan(), create_ref(-25, 10)).ok(), Some(create_nan()));
1670        assert_eq!(Value::calc_mod(create_nan(), create_nan()).ok(), Some(create_nan()));
1671    }
1672
1673    #[test]
1674    fn test_plain_values_are_remaindered_by_zero() {
1675        assert_eq!(Value::calc_mod(create_ref(55, 10), create_ref(0, 1)).ok(), Some(create_nan()));
1676        assert_eq!(Value::calc_mod(create_nan(), create_ref(0, 1)).ok(), Some(create_nan()));
1677    }
1678
1679    #[test]
1680    fn test_plain_values_are_negated_by_value() {
1681        assert_eq!(Value::calc_neg(create_ref(5, 10)).ok(), Some(create_ref(-5, 10)));
1682        assert_eq!(Value::calc_neg(create_ref(-5, 10)).ok(), Some(create_ref(5, 10)));
1683        assert_eq!(Value::calc_neg(create_nan()).ok(), Some(create_nan()));
1684    }
1685
1686    #[test]
1687    fn test_plain_values_are_inverted_if_valid() {
1688        assert_eq!(Value::calc_inv(create_ref(5, 10)).ok(), Some(create_ref(10, 5)));
1689        assert_eq!(Value::calc_inv(create_ref(-5, 10)).ok(), Some(create_ref(-10, 5)));
1690        assert_eq!(Value::calc_inv(create_nan()).ok(), Some(create_nan()));
1691    }
1692
1693    #[test]
1694    fn test_plain_values_are_inverted_if_zero() {
1695        assert_eq!(Value::calc_inv(create_ref(0, 1)).ok(), Some(create_nan()));
1696    }
1697
1698    #[test]
1699    fn test_plain_values_are_raised_to_integer_power() {
1700        assert_eq!(Value::calc_pow(create_ref(3, 1), create_ref(4, 1)).ok(), Some(create_ref(81, 1)));
1701        assert_eq!(Value::calc_pow(create_ref(3, 1), create_nan()).ok(), Some(create_nan()));
1702        assert_eq!(Value::calc_pow(create_nan(), create_ref(4, 1)).ok(), Some(create_nan()));
1703        assert_eq!(Value::calc_pow(create_nan(), create_nan()).ok(), Some(create_nan()));
1704    }
1705
1706    #[test]
1707    fn test_plain_values_are_raised_to_fractional_power() {
1708        assert_eq!(Value::calc_pow(create_ref(3, 1), create_nan()).ok(), Some(create_nan()));
1709        assert_eq!(Value::calc_pow(create_nan(), create_ref(1, 2)).ok(), Some(create_nan()));
1710        assert_eq!(Value::calc_pow(create_nan(), create_nan()).ok(), Some(create_nan()));
1711    }
1712
1713    #[test]
1714    fn test_plain_values_have_square_root_if_positive() {
1715        assert_eq!(Value::calc_sqrt(create_nan()).ok(), Some(create_nan()));
1716    }
1717
1718    #[test]
1719    fn test_plain_values_have_square_root_if_negative() {
1720        assert_eq!(Value::calc_sqrt(create_ref(-3, 1)).ok(), Some(create_nan()));
1721    }
1722
1723    #[test]
1724    fn test_plain_values_have_bitwise_and_by_value() {
1725        assert_eq!(Value::calc_and(create_ref(0xff00, 1), create_ref(0xf0f0, 1)).ok(), Some(create_ref(0xf000, 1)));
1726        assert_eq!(Value::calc_and(create_ref(0xff00, 1), create_nan()).ok(), Some(create_nan()));
1727        assert_eq!(Value::calc_and(create_nan(), create_ref(0xf0f0, 1)).ok(), Some(create_nan()));
1728        assert_eq!(Value::calc_and(create_nan(), create_nan()).ok(), Some(create_nan()));
1729    }
1730
1731    #[test]
1732    fn test_plain_values_have_bitwise_or_by_value() {
1733        assert_eq!(Value::calc_or(create_ref(0xff00, 1), create_ref(0xf0f0, 1)).ok(), Some(create_ref(0xfff0, 1)));
1734        assert_eq!(Value::calc_or(create_ref(0xff00, 1), create_nan()).ok(), Some(create_nan()));
1735        assert_eq!(Value::calc_or(create_nan(), create_ref(0xf0f0, 1)).ok(), Some(create_nan()));
1736        assert_eq!(Value::calc_or(create_nan(), create_nan()).ok(), Some(create_nan()));
1737    }
1738
1739    #[test]
1740    fn test_plain_values_have_bitwise_xor_by_value() {
1741        assert_eq!(Value::calc_xor(create_ref(0xff00, 1), create_ref(0xf0f0, 1)).ok(), Some(create_ref(0x0ff0, 1)));
1742        assert_eq!(Value::calc_xor(create_ref(0xff00, 1), create_nan()).ok(), Some(create_nan()));
1743        assert_eq!(Value::calc_xor(create_nan(), create_ref(0xf0f0, 1)).ok(), Some(create_nan()));
1744        assert_eq!(Value::calc_xor(create_nan(), create_nan()).ok(), Some(create_nan()));
1745    }
1746
1747    #[test]
1748    fn test_plain_values_are_shifted_left_by_value() {
1749        assert_eq!(Value::calc_shl(create_ref(35, 10), create_ref(29, 10)).ok(), Some(create_ref(14, 1)));
1750        assert_eq!(Value::calc_shl(create_ref(-35, 10), create_ref(29, 10)).ok(), Some(create_ref(-14, 1)));
1751        assert_eq!(Value::calc_shl(create_ref(35, 10), create_ref(-29, 10)).ok(), Some(create_ref(875, 1000)));
1752        assert_eq!(Value::calc_shl(create_ref(-35, 10), create_ref(-29, 10)).ok(), Some(create_ref(-875, 1000)));
1753        assert_eq!(Value::calc_shl(create_ref(35, 10), create_nan()).ok(), Some(create_nan()));
1754        assert_eq!(Value::calc_shl(create_ref(-35, 10), create_nan()).ok(), Some(create_nan()));
1755        assert_eq!(Value::calc_shl(create_nan(), create_ref(29, 10)).ok(), Some(create_nan()));
1756        assert_eq!(Value::calc_shl(create_nan(), create_ref(-29, 10)).ok(), Some(create_nan()));
1757        assert_eq!(Value::calc_shl(create_nan(), create_nan()).ok(), Some(create_nan()));
1758    }
1759
1760    #[test]
1761    fn test_plain_values_are_shifted_right_by_value() {
1762        assert_eq!(Value::calc_shr(create_ref(35, 10), create_ref(29, 10)).ok(), Some(create_ref(875, 1000)));
1763        assert_eq!(Value::calc_shr(create_ref(-35, 10), create_ref(29, 10)).ok(), Some(create_ref(-875, 1000)));
1764        assert_eq!(Value::calc_shr(create_ref(35, 10), create_ref(-29, 10)).ok(), Some(create_ref(14, 1)));
1765        assert_eq!(Value::calc_shr(create_ref(-35, 10), create_ref(-29, 10)).ok(), Some(create_ref(-14, 1)));
1766        assert_eq!(Value::calc_shr(create_ref(35, 10), create_nan()).ok(), Some(create_nan()));
1767        assert_eq!(Value::calc_shr(create_ref(-35, 10), create_nan()).ok(), Some(create_nan()));
1768        assert_eq!(Value::calc_shr(create_nan(), create_ref(29, 10)).ok(), Some(create_nan()));
1769        assert_eq!(Value::calc_shr(create_nan(), create_ref(-29, 10)).ok(), Some(create_nan()));
1770        assert_eq!(Value::calc_shr(create_nan(), create_nan()).ok(), Some(create_nan()));
1771    }
1772
1773    #[test]
1774    fn test_plain_values_are_summed() {
1775        assert_eq!(Some(create_ref(0, 1)), Value::calc_sum(vec![]).ok());
1776        assert_eq!(Some(create_ref(0, 1)), Value::calc_sum(vec![create_nan(), create_nan(), create_nan()]).ok());
1777        assert_eq!(Some(create_ref(25, 10)), Value::calc_sum(vec![create_ref(25, 10), create_nan(), create_nan()]).ok());
1778        assert_eq!(Some(create_ref(65, 10)), Value::calc_sum(vec![create_ref(25, 10), create_ref(4, 1), create_nan()]).ok());
1779        assert_eq!(Some(create_ref(120, 10)), Value::calc_sum(vec![create_ref(25, 10), create_ref(4, 1), create_ref(55, 10)]).ok());
1780    }
1781
1782    #[test]
1783    fn test_plain_values_are_producted() {
1784        assert_eq!(Some(create_ref(1, 1)), Value::calc_prod(vec![]).ok());
1785        assert_eq!(Some(create_ref(1, 1)), Value::calc_prod(vec![create_nan(), create_nan(), create_nan()]).ok());
1786        assert_eq!(Some(create_ref(25, 10)), Value::calc_prod(vec![create_ref(25, 10), create_nan(), create_nan()]).ok());
1787        assert_eq!(Some(create_ref(100, 10)), Value::calc_prod(vec![create_ref(25, 10), create_ref(4, 1), create_nan()]).ok());
1788        assert_eq!(Some(create_ref(550, 10)), Value::calc_prod(vec![create_ref(25, 10), create_ref(4, 1), create_ref(55, 10)]).ok());
1789    }
1790
1791    #[test]
1792    fn test_integer_sequences_are_generated_no_step() {
1793        let expected_inc = vec![
1794            create_ref(95, 10),
1795            create_ref(105, 10),
1796            create_ref(115, 10),
1797        ];
1798        let expected_same = vec![
1799            create_ref(105, 10),
1800        ];
1801        let expected_dec = vec![
1802            create_ref(115, 10),
1803            create_ref(105, 10),
1804            create_ref(95, 10),
1805        ];
1806        assert_eq!(Some(expected_inc), Value::calc_seq(create_ref(95, 10), create_ref(115, 10)).ok());
1807        assert_eq!(Some(expected_same), Value::calc_seq(create_ref(105, 10), create_ref(105, 10)).ok());
1808        assert_eq!(Some(expected_dec), Value::calc_seq(create_ref(115, 10), create_ref(95, 10)).ok());
1809    }
1810
1811    #[test]
1812    fn test_integer_sequences_are_generated_with_step() {
1813        let expected_inc = vec![
1814            create_ref(0, 10),
1815            create_ref(5, 10),
1816            create_ref(10, 10),
1817        ];
1818        let expected_same = vec![
1819            create_ref(5, 10),
1820        ];
1821        let expected_dec = vec![
1822            create_ref(10, 10),
1823            create_ref(5, 10),
1824            create_ref(0, 10),
1825        ];
1826        assert_eq!(Some(expected_inc.clone()), Value::calc_step(create_ref(0, 10), create_ref(5, 10), create_ref(10, 10)).ok());
1827        assert_eq!(Some(expected_inc.clone()), Value::calc_step(create_ref(0, 10), create_ref(5, 10), create_ref(12, 10)).ok());
1828        assert_eq!(Some(expected_inc.clone()), Value::calc_step(create_ref(0, 10), create_ref(-5, 10), create_ref(10, 10)).ok());
1829        assert_eq!(Some(expected_inc.clone()), Value::calc_step(create_ref(0, 10), create_ref(-5, 10), create_ref(12, 10)).ok());
1830        assert_eq!(Some(expected_same.clone()), Value::calc_step(create_ref(5, 10), create_ref(0, 10), create_ref(10, 10)).ok());
1831        assert_eq!(Some(expected_same.clone()), Value::calc_step(create_ref(5, 10), create_ref(0, 10), create_ref(5, 10)).ok());
1832        assert_eq!(Some(expected_same.clone()), Value::calc_step(create_ref(5, 10), create_ref(0, 10), create_ref(0, 10)).ok());
1833        assert_eq!(Some(expected_dec.clone()), Value::calc_step(create_ref(10, 10), create_ref(5, 10), create_ref(0, 10)).ok());
1834        assert_eq!(Some(expected_dec.clone()), Value::calc_step(create_ref(10, 10), create_ref(5, 10), create_ref(-2, 10)).ok());
1835        assert_eq!(Some(expected_dec.clone()), Value::calc_step(create_ref(10, 10), create_ref(-5, 10), create_ref(0, 10)).ok());
1836        assert_eq!(Some(expected_dec.clone()), Value::calc_step(create_ref(10, 10), create_ref(-5, 10), create_ref(-2, 10)).ok());
1837    }
1838
1839    #[test]
1840    fn test_stack_is_sorted() {
1841        let expected = vec![
1842            create_nan(),
1843            create_ref(-15, 10),
1844            create_ref(-10, 10),
1845            create_ref(-5, 10),
1846            create_ref(0, 10),
1847            create_ref(5, 10),
1848            create_ref(10, 10),
1849            create_ref(15, 10),
1850        ];
1851        let original = vec![
1852            create_ref(0, 10),
1853            create_ref(5, 10),
1854            create_ref(-5, 10),
1855            create_ref(10, 10),
1856            create_ref(-10, 10),
1857            create_ref(15, 10),
1858            create_ref(-15, 10),
1859            create_nan(),
1860        ];
1861        assert_eq!(Some(expected), Value::sort_seq(original).ok());
1862    }
1863
1864    #[test]
1865    fn test_stack_is_reversed() {
1866        let expected = vec![
1867            create_nan(),
1868            create_ref(-15, 10),
1869            create_ref(15, 10),
1870            create_ref(-10, 10),
1871            create_ref(10, 10),
1872            create_ref(-5, 10),
1873            create_ref(5, 10),
1874            create_ref(0, 10),
1875        ];
1876        let original = vec![
1877            create_ref(0, 10),
1878            create_ref(5, 10),
1879            create_ref(-5, 10),
1880            create_ref(10, 10),
1881            create_ref(-10, 10),
1882            create_ref(15, 10),
1883            create_ref(-15, 10),
1884            create_nan(),
1885        ];
1886        assert_eq!(Some(expected), Value::rev_seq(original).ok());
1887    }
1888
1889    fn format_context(
1890        format: Format,
1891        sep: bool,
1892        dp: Option<u8>,
1893        numer: i128,
1894        denom: i128,
1895    ) -> (String, String) {
1896        let context = Context::new()
1897            .with_format(format)
1898            .with_sep(sep)
1899            .with_dp(dp);
1900        let (integer, fraction, _, _, _) = create_value(numer, denom)
1901            .to_strings(&context);
1902        (integer, fraction)
1903    }
1904
1905    fn format_meaning(
1906        meaning: Meaning,
1907        numer: i128,
1908        denom: i128,
1909    ) -> (String, String, String) {
1910        let context = Context::new();
1911        let (integer, fraction, symbol, _, _) = create_value(numer, denom)
1912            .with_meaning(meaning)
1913            .to_strings(&context);
1914        let symbol = symbol.unwrap_or_else(String::new);
1915        (integer, fraction, symbol)
1916    }
1917
1918    pub fn create_value(numer: i128, denom: i128) -> Value {
1919        let number = create_ratio(numer, denom);
1920        Value::new(Some(number))
1921    }
1922
1923    pub fn create_ref(numer: i128, denom: i128) -> ValueRef {
1924        let value = create_value(numer, denom);
1925        Rc::new(RefCell::new(value))
1926    }
1927
1928    pub fn create_nan() -> ValueRef {
1929        let value = Value::new(None);
1930        Rc::new(RefCell::new(value))
1931    }
1932
1933    pub fn parse_value(number: &str) -> Value {
1934        Value::from_string(number).unwrap()
1935    }
1936
1937    pub fn parse_ref(number: &str) -> ValueRef {
1938        let value = parse_value(number);
1939        Rc::new(RefCell::new(value))
1940    }
1941
1942    pub fn parse_values(numbers: Vec<&str>) -> Vec<Value> {
1943        numbers.iter().map(|x| parse_value(x)).collect()
1944    }
1945
1946    pub fn parse_refs(numbers: Vec<&str>) -> Vec<ValueRef> {
1947        numbers.iter().map(|x| parse_ref(x)).collect()
1948    }
1949
1950    fn fudge_ratio(number: BigRational) -> Option<BigRational> {
1951        number.to_f64()
1952            .map(f64::sqrt)
1953            .and_then(BigRational::from_f64)
1954            .and_then(square_ratio)
1955    }
1956
1957    fn square_ratio(number: BigRational) -> Option<BigRational> {
1958        number.checked_mul(&number)
1959    }
1960
1961    fn opposite_ratio(number: BigRational) -> Option<BigRational> {
1962        create_ratio(2, 1).checked_mul(&number.round()).and_then(|x| x.checked_sub(&number))
1963    }
1964}