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
36impl 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 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" };
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 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 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 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 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 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 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 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 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 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 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 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 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 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#[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); let number2 = fudge_ratio(create_ratio(16, 8)).and_then(opposite_ratio); let number3 = fudge_ratio(create_ratio(16, 8)); let number4 = fudge_ratio(create_ratio(17, 8)); assert_eq!(create_value(15, 8), Value::new(number1).with_rounding());
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)); let number2 = fudge_ratio(create_ratio(1088924, 99000)); let number3 = fudge_ratio(create_ratio(1997457, 999000)); let number4 = fudge_ratio(create_ratio(19995891, 9999000)); assert_eq!(create_value(908992, 9000), Value::new(number1).with_rounding());
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()); assert_eq!(1, create_value(1, 1).measure_hexadecimal()); assert_eq!(1, create_value(2147483646, 1).measure_hexadecimal()); assert_eq!(1, create_value(2147483647, 1).measure_hexadecimal()); assert_eq!(2, create_value(2147483648, 1).measure_hexadecimal()); assert_eq!(2, create_value(2147483649, 1).measure_hexadecimal()); assert_eq!(2, create_value(4294967294, 1).measure_hexadecimal()); assert_eq!(2, create_value(4294967295, 1).measure_hexadecimal()); assert_eq!(2, create_value(4294967296, 1).measure_hexadecimal()); assert_eq!(2, create_value(4294967297, 1).measure_hexadecimal()); assert_eq!(2, create_value(9223372036854775806, 1).measure_hexadecimal()); assert_eq!(2, create_value(9223372036854775807, 1).measure_hexadecimal()); assert_eq!(3, create_value(9223372036854775808, 1).measure_hexadecimal()); assert_eq!(3, create_value(9223372036854775809, 1).measure_hexadecimal()); assert_eq!(3, create_value(18446744073709551614, 1).measure_hexadecimal()); assert_eq!(3, create_value(18446744073709551615, 1).measure_hexadecimal()); assert_eq!(3, create_value(18446744073709551616, 1).measure_hexadecimal()); assert_eq!(3, create_value(18446744073709551617, 1).measure_hexadecimal()); assert_eq!(3, create_value(-18446744073709551616, 1).measure_hexadecimal()); assert_eq!(3, create_value(-18446744073709551615, 1).measure_hexadecimal()); assert_eq!(2, create_value(-9223372036854775808, 1).measure_hexadecimal()); assert_eq!(2, create_value(-9223372036854775807, 1).measure_hexadecimal()); assert_eq!(2, create_value(-4294967296, 1).measure_hexadecimal()); assert_eq!(2, create_value(-4294967295, 1).measure_hexadecimal()); assert_eq!(1, create_value(-2147483648, 1).measure_hexadecimal()); assert_eq!(1, create_value(-2147483647, 1).measure_hexadecimal()); assert_eq!(1, create_value(-2, 1).measure_hexadecimal()); assert_eq!(1, create_value(-1, 1).measure_hexadecimal()); }
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}