1use dtoa;
2use num_bigint::{BigInt, Sign};
3use num_complex::Complex;
4use num_rational::BigRational;
5use num_traits::{FromPrimitive, Num, One, ToPrimitive, Zero};
6use std::f64::{consts, EPSILON};
7use std::fmt;
8use std::str;
9
10use crate::errors::*;
11
12pub type CalcResult = Result<Value, CalcError>;
14pub(crate) type CalcErrorResult = Result<(), CalcError>;
15
16#[derive(Clone)]
18pub enum Value {
19 Int(BigInt),
21 Float(f64),
23 Ratio(BigRational),
25 Complex(Complex<f64>),
27}
28
29const F64_BUF_LEN: usize = 48;
30fn format_f64(g: f64) -> String {
31 let mut buf = [b'\0'; F64_BUF_LEN];
32 match dtoa::write(&mut buf[..], g) {
33 Ok(len) => match str::from_utf8(&buf[..len]) {
34 Ok(s) => s.to_string(),
35 Err(..) => format!("{}", g),
36 },
37 Err(..) => format!("{}", g),
38 }
39}
40
41pub(crate) fn f64_equal(f1: f64, f2: f64) -> bool {
42 (f1 - f2).abs() <= EPSILON
43}
44
45impl fmt::Display for Value {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 match &self {
48 Value::Int(ref i) => write!(f, "{}", i),
49 Value::Float(ref g) => write!(f, "{}", format_f64(*g)),
50 Value::Ratio(ref r) => {
51 let i = r.clone().to_integer();
52 if i.is_zero() {
53 write!(f, "{}\\{}", r.numer(), r.denom())
54 } else {
55 let mut rc = r.fract();
56 if rc < BigRational::zero() {
57 rc = -rc;
58 }
59 write!(f, "{}\\{}\\{}", i, rc.numer(), rc.denom())
60 }
61 }
62 Value::Complex(ref c) => {
63 if c.im >= 0.0 {
64 write!(f, "{}+{}i", format_f64(c.re), format_f64(c.im))
65 } else {
66 write!(f, "{}{}i", format_f64(c.re), format_f64(c.im))
67 }
68 }
69 }
70 }
71}
72
73impl fmt::Debug for Value {
74 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75 match &self {
76 Value::Int(ref i) => write!(f, " Int({:?})", i),
77 Value::Float(ref g) => write!(f, " Float({:?})", g),
78 Value::Ratio(ref r) => write!(f, " Ratio({:?})", r),
79 Value::Complex(ref c) => write!(f, " Complex({:?})", c),
80 }
81 }
82}
83
84impl PartialEq for Value {
85 fn eq(&self, other: &Value) -> bool {
86 match (self, &other) {
87 (Value::Int(ref i1), Value::Int(ref i2)) => i1 == i2,
88 (Value::Float(ref f1), Value::Float(ref f2)) => f1 == f2,
89 (Value::Ratio(ref r1), Value::Ratio(ref r2)) => r1 == r2,
90 (Value::Complex(ref c1), Value::Complex(ref c2)) => c1 == c2,
91 (_, _) => false,
92 }
93 }
94}
95
96fn int_to_f64(i: &BigInt) -> Result<f64, CalcError> {
97 if let Some(f) = i.to_f64() {
98 Ok(f)
99 } else {
100 Err(CalcError::IntToFloat(i.clone()))
101 }
102}
103
104fn f64_to_int(f: f64) -> Result<BigInt, CalcError> {
105 if let Some(i) = BigInt::from_f64(f) {
106 Ok(i)
107 } else {
108 Err(CalcError::FloatToInt(f))
109 }
110}
111
112fn f64_to_ratio(f: f64) -> Result<BigRational, CalcError> {
113 if let Some(r) = BigRational::from_float(f) {
114 Ok(r)
115 } else {
116 Err(CalcError::FloatToRatio(f))
117 }
118}
119
120fn ratio_to_f64(r: &BigRational) -> Result<f64, CalcError> {
121 if r.is_zero() {
122 return Ok(0.0);
123 }
124 let i = if let Some(f) = r.clone().to_integer().to_f64() {
127 f
128 } else {
129 return Err(CalcError::RatioToFloat(r.clone()));
130 };
131 let r = r.fract();
132 let n = if let Some(f) = r.numer().to_f64() {
133 f
134 } else {
135 return Err(CalcError::RatioToFloat(r.clone()));
136 };
137 let d = if let Some(f) = r.denom().to_f64() {
138 f
139 } else {
140 return Err(CalcError::RatioToFloat(r.clone()));
141 };
142 Ok(i + n / d)
143}
144
145fn str_to_bigint(s: &str) -> Result<BigInt, CalcError> {
146 let s = s.replace("_", "");
147 let s = s.replace(" ", "");
148 let plen = "0x".len();
149 if s.starts_with("0x") || s.starts_with("0X") {
150 if let Ok(bi) = BigInt::from_str_radix(&s[plen..], 16) {
151 return Ok(bi);
152 }
153 return Err(CalcError::StrToInt(s));
154 } else if s.starts_with("0o") || s.starts_with("0O") {
155 if let Ok(bi) = BigInt::from_str_radix(&s[plen..], 8) {
156 return Ok(bi);
157 }
158 return Err(CalcError::StrToInt(s));
159 } else if s.starts_with("0b") || s.starts_with("0B") {
160 if let Ok(bi) = BigInt::from_str_radix(&s[plen..], 2) {
161 return Ok(bi);
162 }
163 return Err(CalcError::StrToInt(s));
164 }
165
166 let pos = s.find(|c: char| c == 'e' || c == 'E').unwrap_or(0);
167 if pos == 0 {
168 if let Ok(i) = s.parse() {
169 return Ok(i);
170 } else {
171 return Err(CalcError::StrToInt(s.to_owned()));
172 }
173 }
174 let (s1, s2) = s.split_at(pos);
175 let s2 = s2.trim_start_matches(|c| c == 'E' || c == 'e' || c == '+');
176
177 let base = s1.parse();
178 let pow = s2.parse();
179 if base.is_err() || pow.is_err() {
180 return Err(CalcError::StrToInt(s.to_owned()));
181 }
182
183 let mut base = base.unwrap();
184 let pow = pow.unwrap();
185 for _i in 0..pow {
187 base *= 10;
188 }
189 Ok(base)
190}
191
192fn str_to_f64(s: &str) -> Result<f64, CalcError> {
193 if let Ok(f) = s.parse::<f64>() {
194 Ok(f)
195 } else {
196 Err(CalcError::StrToFloat(s.to_owned()))
197 }
198}
199
200macro_rules! basic_op {
201 ($id:ident, $op:tt, $cond:ident) => {
202 pub fn $id(self, rhs: Value) -> CalcResult {
203 match (&self, &rhs) {
204 (Value::Complex(..), ..) | (.., Value::Complex(..)) => {
205 let c1 = self.into_raw_complex()?;
206 let c2 = rhs.into_raw_complex()?;
207 let c = Value::Complex(c1 $op c2);
208 if Value::is_like_int(&c) {
209 return Value::into_int(c);
210 }
211 Ok(c)
212 },
213 (Value::Float(..), ..) | (.., Value::Float(..)) => {
214 let f1 = self.into_raw_f64()?;
215 let f2 = rhs.into_raw_f64()?;
216 let f = Value::Float(f1 $op f2);
217 if Value::is_like_int(&f) {
218 return Value::into_int(f);
219 }
220 Ok(f)
221 },
222 (Value::Ratio(..), ..) | (.., Value::Ratio(..)) => {
223 let r1 = self.into_raw_ratio()?;
224 let r2 = rhs.into_raw_ratio()?;
225 let r = Value::Ratio(r1 $op r2);
226 if Value::is_like_int(&r) {
227 return Value::into_int(r);
228 }
229 Ok(r)
230 },
231 _ => {
232 let i1 = self.into_raw_big_int()?;
233 let i2 = rhs.into_raw_big_int()?;
234 if $cond {
235 if i1.clone() % i2.clone() == BigInt::zero() {
236 return Ok(Value::Int(i1 $op i2))
237 }
238 let f1 = i1.to_f64();
239 let f2 = i2.to_f64();
240 match (f1, f2) {
241 (Some(ff1), Some(ff2)) => {
242 Ok(Value::Float(ff1 / ff2))
243 },
244 (_, _) => {
245 Ok(Value::Int(i1 $op i2))
246 },
247 }
248 } else {
249 Ok(Value::Int(i1 $op i2))
250 }
251 },
252 }
253 }
254 }
255}
256
257macro_rules! div_op {
258 ($id:ident, $op:tt, $cond:ident) => {
259 pub fn $id(self, rhs: Value) -> CalcResult {
260 if rhs.is_zero() {
261 return Err(CalcError::DividedByZero(format!("{}", self)));
262 }
263 match (&self, &rhs) {
264 (Value::Complex(..), ..) | (.., Value::Complex(..)) => {
265 let c2 = rhs.into_raw_complex()?;
266 let c1 = self.into_raw_complex()?;
267 let c = Value::Complex(c1 $op c2);
268 if Value::is_like_int(&c) {
269 return Value::into_int(c);
270 }
271 Ok(c)
272 },
273 (Value::Float(..), ..) | (.., Value::Float(..)) => {
274 let f2 = rhs.into_raw_f64()?;
275 let f1 = self.into_raw_f64()?;
276 let f = Value::Float(f1 $op f2);
277 if Value::is_like_int(&f) {
278 return Value::into_int(f);
279 }
280 Ok(f)
281 },
282 (Value::Ratio(..), ..) | (.., Value::Ratio(..)) => {
283 let r2 = rhs.into_raw_ratio()?;
284 let r1 = self.into_raw_ratio()?;
285 let r = Value::Ratio(r1 $op r2);
286 if Value::is_like_int(&r) {
287 return Value::into_int(r);
288 }
289 Ok(r)
290 },
291 _ => {
292 let i2 = rhs.into_raw_big_int()?;
293 let i1 = self.into_raw_big_int()?;
294 if $cond {
295 if i1.clone() % i2.clone() == BigInt::zero() {
296 return Ok(Value::Int(i1 $op i2))
297 }
298 let f1 = i1.to_f64();
299 let f2 = i2.to_f64();
300 match (f1, f2) {
301 (Some(ff1), Some(ff2)) => {
302 Ok(Value::Float(ff1 / ff2))
303 },
304 (_, _) => {
305 Ok(Value::Int(i1 $op i2))
306 },
307 }
308 } else {
309 Ok(Value::Int(i1 $op i2))
310 }
311 },
312 }
313 }
314 }
315}
316
317macro_rules! cmp_op {
318 ($id:ident, $op:tt) => {
319 pub fn $id(self, rhs: Value) -> CalcResult {
320 match (&self, &rhs) {
321 (Value::Complex(..), ..) | (.., Value::Complex(..)) => {
322 let c1 = self.into_raw_complex()?;
323 let c2 = rhs.into_raw_complex()?;
324 if c1.re $op c2.re && c1.im $op c2.im {
325 Ok(Value::Int(BigInt::one()))
326 } else {
327 Ok(Value::Int(BigInt::zero()))
328 }
329 },
330 (Value::Float(..), ..) | (.., Value::Float(..)) => {
331 let f1 = self.into_raw_f64()?;
332 let f2 = rhs.into_raw_f64()?;
333 if f1 $op f2 {
334 Ok(Value::Int(BigInt::one()))
335 } else {
336 Ok(Value::Int(BigInt::zero()))
337 }
338 },
339 (Value::Ratio(..), ..) | (.., Value::Ratio(..)) => {
340 let r1 = self.into_raw_ratio()?;
341 let r2 = rhs.into_raw_ratio()?;
342 if r1 $op r2 {
343 Ok(Value::Int(BigInt::one()))
344 } else {
345 Ok(Value::Int(BigInt::zero()))
346 }
347 },
348 _ => {
349 let i1 = self.into_raw_big_int()?;
350 let i2 = rhs.into_raw_big_int()?;
351 if i1 $op i2 {
352 Ok(Value::Int(BigInt::one()))
353 } else {
354 Ok(Value::Int(BigInt::zero()))
355 }
356 },
357 }
358 }
359 }
360}
361macro_rules! cmp_op_inv {
362 ($id:ident, $idcall: ident, $op:tt) => {
363 pub fn $id(self, rhs: Value) -> CalcResult {
364 let res = self.$idcall(rhs)?;
365 if res.is_zero() {
366 Ok(Value::Int(BigInt::one()))
367 } else {
368 Ok(Value::Int(BigInt::zero()))
369 }
370 }
371 };
372}
373
374macro_rules! round_op {
375 ($id:ident) => {
376 pub fn $id(self) -> CalcResult {
377 match &self {
378 Value::Complex(c) => {
379 let v = Value::Complex(Complex::new(c.re.$id(), c.im.$id()));
380 if Value::is_like_int(&v) {
381 let v = Value::into_int(v)?;
382 Ok(v)
383 } else {
384 Ok(v)
385 }
386 }
387 Value::Ratio(r) => {
388 let v = Value::Ratio(r.$id());
389 if Value::is_like_int(&v) {
390 let v = Value::into_int(v)?;
391 Ok(v)
392 } else {
393 Ok(v)
394 }
395 }
396 Value::Float(f) => {
397 let v = Value::Float(f.$id());
398 let v = Value::into_int(v)?;
399 Ok(v)
400 }
401 Value::Int(i) => Ok(Value::Int(i.clone())),
402 }
403 }
404 };
405}
406
407macro_rules! bitwise_op {
408 ($id:ident, $op:tt) => {
409 pub fn $id(self, rhs: Value) -> CalcResult {
410 match (&self, &rhs) {
411 (Value::Int(i1), Value::Int(i2)) => {
412 let i1 = i1 $op i2;
413 Ok(Value::Int(i1))
414 },
415 _ => Err(CalcError::OnlyInt("bitwise operator".to_string())),
416 }
417 }
418 }
419}
420macro_rules! bitwise_shift_op {
421 ($id:ident, $op:tt) => {
422 pub fn $id(self, rhs: Value) -> CalcResult {
423 match (&self, &rhs) {
424 (Value::Int(i1), Value::Int(i2)) => {
425 let shift = if let Some(us) = i2.clone().to_usize() {
426 us
427 } else {
428 return Err(CalcError::InvalidShift(format!("{}", i2)))
429 };
430 let i1 = i1 $op shift;
431 Ok(Value::Int(i1))
432 },
433 _ => Err(CalcError::OnlyInt("bitwise operator".to_string())),
434 }
435 }
436 }
437}
438
439macro_rules! sin_cos {
440 ($id:ident) => {
441 pub fn $id(self) -> CalcResult {
442 match &self {
443 Value::Complex(c) => Ok(Value::Complex(c.$id())),
444 Value::Float(f) => Ok(Value::Float(f.$id())),
445 _ => {
446 let f = self.into_raw_f64()?;
447 Ok(Value::Float(f.$id()))
448 }
449 }
450 }
451 };
452}
453macro_rules! asin_cos {
454 ($id:ident) => {
455 pub fn $id(self) -> CalcResult {
456 match &self {
457 Value::Complex(c) => Ok(Value::Complex(c.$id())),
458 _ => {
459 let f = self.into_raw_f64()?;
460 if (-1.0..=1.0).contains(&f) {
461 Ok(Value::Float(f.$id()))
462 } else {
463 let cm = Complex::new(f, 0.0);
464 Ok(Value::Complex(cm.$id()))
465 }
466 }
467 }
468 }
469 };
470}
471
472macro_rules! fn_hyper {
473 ($id:ident) => {
474 pub fn $id(self) -> CalcResult {
475 match &self {
476 Value::Complex(c) => Ok(Value::Complex(c.$id())),
477 _ => {
478 let f = self.clone().into_raw_f64()?;
479 Ok(Value::Float(f.$id()))
480 }
481 }
482 }
483 };
484}
485
486impl Default for Value {
487 fn default() -> Value {
488 Value::Int(BigInt::zero())
489 }
490}
491
492impl Value {
493 pub fn new() -> Self {
494 Default::default()
495 }
496
497 pub(crate) fn into_int(self) -> CalcResult {
500 match self {
501 Value::Int(..) => Ok(self),
502 Value::Float(f) => {
503 let i = f64_to_int(f.floor())?;
504 Ok(Value::Int(i))
505 }
506 Value::Ratio(r) => Ok(Value::Int(r.to_integer())),
507 Value::Complex(c) => {
508 let i = f64_to_int(c.re.floor())?;
509 Ok(Value::Int(i))
510 }
511 }
512 }
513
514 pub(crate) fn into_float(self) -> CalcResult {
515 match self {
516 Value::Int(i) => {
517 let f = int_to_f64(&i)?;
518 Ok(Value::Float(f))
519 }
520 Value::Float(..) => Ok(self),
521 Value::Ratio(r) => {
522 let f = ratio_to_f64(&r)?;
523 Ok(Value::Float(f))
524 }
525 Value::Complex(c) => Ok(Value::Float(c.re)),
526 }
527 }
528
529 pub(crate) fn into_ratio(self) -> CalcResult {
530 match self {
531 Value::Ratio(..) => Ok(self),
532 Value::Int(i) => Ok(Value::Ratio(BigRational::from_integer(i))),
533 Value::Float(f) => {
534 let r = f64_to_ratio(f)?;
535 Ok(Value::Ratio(r))
536 }
537 Value::Complex(c) => {
538 let r = f64_to_ratio(c.re)?;
539 Ok(Value::Ratio(r))
540 }
541 }
542 }
543
544 pub(crate) fn into_complex(self) -> CalcResult {
545 match self {
546 Value::Complex(..) => Ok(self),
547 Value::Float(f) => Ok(Value::Complex(Complex::new(f, 0.0))),
548 Value::Int(i) => {
549 let f = int_to_f64(&i)?;
550 Ok(Value::Complex(Complex::new(f, 0.0)))
551 }
552 Value::Ratio(r) => {
553 let f = ratio_to_f64(&r)?;
554 Ok(Value::Complex(Complex::new(f, 0.0)))
555 }
556 }
557 }
558
559 pub(crate) fn into_raw_f64(self) -> Result<f64, CalcError> {
562 let v = Value::into_float(self)?;
563 match v {
564 Value::Float(f) => Ok(f),
565 _ => Ok(0.0), }
567 }
568
569 pub(crate) fn into_raw_big_int(self) -> Result<BigInt, CalcError> {
570 let v = Value::into_int(self)?;
571 match v {
572 Value::Int(i) => Ok(i),
573 _ => Ok(BigInt::zero()), }
575 }
576
577 pub(crate) fn into_raw_ratio(self) -> Result<BigRational, CalcError> {
578 let v = Value::into_ratio(self)?;
579 match v {
580 Value::Ratio(r) => Ok(r),
581 _ => Ok(BigRational::zero()), }
583 }
584
585 pub(crate) fn into_raw_complex(self) -> Result<Complex<f64>, CalcError> {
586 let v = Value::into_complex(self)?;
587 match v {
588 Value::Complex(c) => Ok(c),
589 _ => Ok(Complex::zero()), }
591 }
592
593 pub fn from_str_integer(s: &str) -> CalcResult {
606 let i = str_to_bigint(s)?;
607 Ok(Value::Int(i))
608 }
609
610 pub fn from_str_float(s: &str) -> CalcResult {
621 let s = s.replace("_", "");
622 let s = s.replace(" ", "");
623 let s = s.replace(',', ".");
624 let f = str_to_f64(&s)?;
625 Ok(Value::Float(f))
626 }
627
628 pub fn from_str_ratio(st: &str) -> CalcResult {
636 let s = st.replace("_", "");
637 let s = s.replace(" ", "");
638 let sp: Vec<&str> = s.splitn(3, '\\').collect();
639
640 if sp.len() == 1 {
641 return Self::from_str_integer(st);
642 }
643
644 let i = if sp.len() > 2 { str_to_bigint(sp[0])? } else { BigInt::zero() };
645 let n = str_to_bigint(sp[sp.len() - 2])?;
646 let d = str_to_bigint(sp[sp.len() - 1])?;
647
648 if d.is_zero() {
649 Ok(Value::Int(BigInt::zero()))
650 } else {
651 let d1 = d.clone();
652 Ok(Value::Ratio(BigRational::new(i * d1 + n, d)))
653 }
654 }
655
656 pub fn from_str_angle(s: &str) -> CalcResult {
670 let s = s.replace("_", "");
671 let s = s.replace(",", ".");
672 let parts: Vec<&str> = s
673 .split(|c: char| {
674 c == 'd'
675 || c == 'D'
676 || c == '°'
677 || c == 'm'
678 || c == 'M'
679 || c == '\''
680 || c == 's'
681 || c == 'S'
682 || c == '"'
683 })
684 .filter(|s| !(*s).is_empty())
685 .collect();
686
687 let deg_ex = s.find(|c: char| c == 'd' || c == 'D' || c == '°').is_some();
688 let min_ex = s.find(|c: char| c == 'm' || c == 'M' || c == '\'').is_some();
689 let sec_ex = s.find(|c: char| c == 's' || c == 'S' || c == '"').is_some();
690 let mut cnt = 0usize;
691 if deg_ex {
692 cnt += 1;
693 }
694 if min_ex {
695 cnt += 1;
696 }
697 if sec_ex {
698 cnt += 1;
699 }
700 if cnt > parts.len() {
701 return Err(CalcError::AngleToFloat(s.to_owned()));
702 }
703
704 let mut deg = 0.0f64;
705 let mut idx = 0;
706 if deg_ex {
707 deg = str_to_f64(parts[idx])?;
708 idx += 1;
709 }
710 if min_ex {
711 let min = str_to_f64(parts[idx])?;
712 deg += min / 60.0;
713 idx += 1;
714 }
715 if sec_ex {
716 let sec = str_to_f64(parts[idx])?;
717 deg += sec / 3600.0;
718 }
719 Ok(Value::Float(deg * consts::PI / 180.0))
720 }
721
722 pub fn from_str_complex(s: &str) -> CalcResult {
740 let s = s.replace("_", "");
741 let s = s.replace(",", ".");
742 if let Some(pos) = s.find(|c: char| c == 'i' || c == 'I' || c == 'j' || c == 'J') {
743 if pos == 0 {
744 let f = str_to_f64(&s[pos + 1..])?;
746 Ok(Value::Complex(Complex::new(0.0, f)))
747 } else if pos == 1 {
748 let mut f = str_to_f64(&s[pos + 1..])?;
750 if s.starts_with('-') {
751 f = -f
752 }
753 Ok(Value::Complex(Complex::new(0.0, f)))
754 } else if pos == s.len() - 1 {
755 let epos = s.rfind(|c: char| c == 'e' || c == 'E').unwrap_or_else(|| s.len());
757 let mut spos = s.rfind(|c: char| c == '-' || c == '+').unwrap_or_else(|| s.len());
758 if spos > epos {
759 spos = s[..epos].rfind(|c: char| c == '-' || c == '+').unwrap_or_else(|| s.len());
762 }
763 if spos >= epos || spos == 0 {
764 let f = str_to_f64(&s[..s.len() - 1])?;
765 return Ok(Value::Complex(Complex::new(0.0, f)));
766 }
767 let r = str_to_f64(&s[..spos])?;
768 let i = str_to_f64(&s[spos..s.len() - 1])?;
769 Ok(Value::Complex(Complex::new(r, i)))
770 } else {
771 let r = str_to_f64(&s[..pos - 1])?;
773 let mut i = str_to_f64(&s[pos + 1..])?;
774 if &s[pos - 1..pos] == "-" {
775 i = -i;
776 }
777 Ok(Value::Complex(Complex::new(r, i)))
778 }
779 } else {
780 let f = str_to_f64(&s)?;
781 Ok(Value::Complex(Complex::new(f, 0.0)))
782 }
783 }
784
785 pub fn is_zero(&self) -> bool {
789 match self {
790 Value::Int(ref i) => i.is_zero(),
791 Value::Float(ref f) => *f == 0.0,
792 Value::Ratio(ref r) => r.is_zero(),
793 Value::Complex(ref c) => c.is_zero(),
794 }
795 }
796
797 pub fn is_positive(&self) -> bool {
799 match self {
800 Value::Int(ref i) => *i >= BigInt::zero(),
801 Value::Float(ref f) => *f >= 0.0f64,
802 Value::Ratio(ref r) => *r >= BigRational::zero(),
803 Value::Complex(ref c) => c.re >= 0.0f64,
804 }
805 }
806
807 fn is_like_int(&self) -> bool {
810 match self {
811 Value::Int(..) => true,
812 Value::Float(f) => {
813 let fa: f64 = f.abs();
814 (1.0..=1e22).contains(&fa) && f64_equal(fa.floor(), fa)
817 }
818 Value::Ratio(ref r) => *r.denom() == BigInt::one(),
819 Value::Complex(ref c) => {
820 if c.im != 0.0 {
821 return false;
822 }
823 let fa: f64 = c.re.abs();
824 (1.0..=1e22).contains(&fa) && f64_equal(fa.floor(), fa)
825 }
826 }
827 }
828
829 basic_op!(addition, +, false);
830 basic_op!(subtract, -, false);
831 basic_op!(multiply, *, false);
832
833 div_op!(divide, /, true);
834 div_op!(reminder, %, false);
835
836 pub fn div_int(self, rhs: Value) -> CalcResult {
841 if rhs.is_zero() {
842 return Err(CalcError::DividedByZero(format!("{}", self)));
843 }
844 match (&self, &rhs) {
845 (Value::Complex(..), ..) | (.., Value::Complex(..)) => {
846 let c2 = rhs.into_raw_complex()?;
847 let c1 = self.into_raw_complex()?;
848 let c = Value::Complex(c1 / c2);
849 Value::into_int(c)
850 }
851 (Value::Float(..), ..) | (.., Value::Float(..)) => {
852 let f2 = rhs.into_raw_f64()?;
853 let f1 = self.into_raw_f64()?;
854 let f = Value::Float(f1 / f2);
855 Value::into_int(f)
856 }
857 (Value::Ratio(..), ..) | (.., Value::Ratio(..)) => {
858 let r2 = rhs.into_raw_ratio()?;
859 let r1 = self.into_raw_ratio()?;
860 let r = Value::Ratio(r1 / r2);
861 Value::into_int(r)
862 }
863 _ => {
864 let i2 = rhs.into_raw_big_int()?;
865 let i1 = self.into_raw_big_int()?;
866 Ok(Value::Int(i1 / i2))
867 }
868 }
869 }
870
871 pub fn negate(self) -> CalcResult {
873 match &self {
874 Value::Complex(c) => Ok(Value::Complex(-c)),
875 Value::Ratio(r) => Ok(Value::Ratio(-r)),
876 Value::Float(f) => Ok(Value::Float(-f)),
877 Value::Int(i) => Ok(Value::Int(-i)),
878 }
879 }
880
881 pub fn norm(self) -> CalcResult {
883 let v = Value::into_complex(self)?;
884 match &v {
885 Value::Complex(c) => Ok(Value::Float(c.norm())),
886 _ => Err(CalcError::Unreachable),
887 }
888 }
889
890 pub fn conj(self) -> CalcResult {
892 match &self {
893 Value::Complex(c) => Ok(Value::Complex(c.conj())),
894 _ => Ok(self),
895 }
896 }
897
898 pub fn im(self) -> CalcResult {
900 match &self {
901 Value::Complex(c) => Ok(Value::Float(c.im)),
902 _ => Ok(Value::Float(0.0)),
903 }
904 }
905
906 pub fn re(self) -> CalcResult {
908 match &self {
909 Value::Complex(c) => Ok(Value::Float(c.re)),
910 _ => Ok(self),
911 }
912 }
913
914 cmp_op!(eq, ==);
915 cmp_op!(less, <);
916 cmp_op!(lesseq, <=);
917 cmp_op_inv!(neq, eq, !=);
918 cmp_op_inv!(greater, lesseq, >);
919 cmp_op_inv!(greatereq, less, >=);
920
921 pub fn logical_not(self) -> CalcResult {
927 if self.is_zero() {
928 Ok(Value::Int(BigInt::one()))
929 } else {
930 Ok(Value::Int(BigInt::zero()))
931 }
932 }
933
934 pub fn logical_and(self, rhs: Value) -> CalcResult {
935 if self.is_zero() || rhs.is_zero() {
936 Ok(Value::Int(BigInt::zero()))
937 } else {
938 Ok(Value::Int(BigInt::one()))
939 }
940 }
941
942 pub fn logical_or(self, rhs: Value) -> CalcResult {
943 if self.is_zero() && rhs.is_zero() {
944 Ok(Value::Int(BigInt::zero()))
945 } else {
946 Ok(Value::Int(BigInt::one()))
947 }
948 }
949
950 pub fn fract(self) -> CalcResult {
952 match &self {
953 Value::Complex(c) => Ok(Value::Complex(Complex::new(c.re.fract(), c.im.fract()))),
954 Value::Ratio(r) => Ok(Value::Ratio(r.fract())),
955 Value::Float(f) => Ok(Value::Float(f.fract())),
956 Value::Int(..) => Ok(Value::Int(BigInt::zero())),
957 }
958 }
959
960 pub fn abs(self) -> CalcResult {
963 match &self {
964 Value::Complex(c) => Ok(Value::Complex(Complex::new(c.re.abs(), c.im))),
965 Value::Ratio(r) => {
966 if *r < BigRational::zero() {
967 Ok(Value::Ratio(-r))
968 } else {
969 Ok(Value::Ratio(r.clone()))
970 }
971 }
972 Value::Float(f) => Ok(Value::Float(f.abs())),
973 Value::Int(i) => {
974 if *i < BigInt::zero() {
975 Ok(Value::Int(-i))
976 } else {
977 Ok(Value::Int(i.clone()))
978 }
979 }
980 }
981 }
982
983 round_op!(floor);
984 round_op!(ceil);
985 round_op!(round);
986 round_op!(trunc);
987
988 pub fn sqr(self) -> CalcResult {
992 match &self {
993 Value::Complex(c) => {
994 let c = c * c;
995 if c.im == 0.0 {
996 Ok(Value::Float(c.re))
997 } else {
998 Ok(Value::Complex(c))
999 }
1000 }
1001 Value::Ratio(r) => Ok(Value::Ratio(r * r)),
1002 Value::Float(f) => Ok(Value::Float(f * f)),
1003 Value::Int(i) => Ok(Value::Int(i * i)),
1004 }
1005 }
1006
1007 pub fn signum(self) -> CalcResult {
1012 match &self {
1013 Value::Complex(c) => {
1014 if c.re == 0.0 {
1015 Ok(Value::Int(BigInt::zero()))
1016 } else if c.re > 0.0 {
1017 Ok(Value::Int(BigInt::one()))
1018 } else {
1019 Ok(Value::Int(-BigInt::one()))
1020 }
1021 }
1022 Value::Ratio(r) => {
1023 if r.is_zero() {
1024 Ok(Value::Int(BigInt::zero()))
1025 } else if *r > BigRational::zero() {
1026 Ok(Value::Int(BigInt::one()))
1027 } else {
1028 Ok(Value::Int(-BigInt::one()))
1029 }
1030 }
1031 Value::Float(f) => {
1032 if *f == 0.0 {
1033 Ok(Value::Int(BigInt::zero()))
1034 } else if *f > 0.0 {
1035 Ok(Value::Int(BigInt::one()))
1036 } else {
1037 Ok(Value::Int(-BigInt::one()))
1038 }
1039 }
1040 Value::Int(i) => {
1041 if i.is_zero() {
1042 Ok(Value::Int(BigInt::zero()))
1043 } else if *i > BigInt::zero() {
1044 Ok(Value::Int(BigInt::one()))
1045 } else {
1046 Ok(Value::Int(-BigInt::one()))
1047 }
1048 }
1049 }
1050 }
1051
1052 pub fn sqrt(self) -> CalcResult {
1055 match &self {
1056 Value::Complex(c) => Ok(Value::Complex(c.sqrt())),
1057 Value::Ratio(r) => {
1058 if *r >= BigRational::zero() {
1059 let n1 = r.numer().sqrt();
1060 let d1 = r.denom().sqrt();
1061 if n1.clone() * n1.clone() == *r.numer() && d1.clone() * d1.clone() == *r.denom() {
1062 return Ok(Value::Ratio(BigRational::new(n1, d1)));
1063 }
1064 }
1065 let f = ratio_to_f64(r)?;
1066 if f >= 0.0 {
1067 Ok(Value::Float(f.sqrt()))
1068 } else {
1069 let f = -f;
1070 let c = Complex::new(0.0, f.sqrt());
1071 Ok(Value::Complex(c))
1072 }
1073 }
1074 Value::Float(f) => {
1075 if *f >= 0.0 {
1076 Ok(Value::Float(f.sqrt()))
1077 } else {
1078 let f = -f;
1079 let c = Complex::new(0.0, f.sqrt());
1080 Ok(Value::Complex(c))
1081 }
1082 }
1083 Value::Int(i) => {
1084 if *i < BigInt::zero() {
1085 let i = -i;
1086 let f = int_to_f64(&i)?;
1087 Ok(Value::Complex(Complex::new(0.0, f.sqrt())))
1088 } else {
1089 let sq = i.sqrt();
1090 if sq.clone() * sq.clone() == *i {
1091 Ok(Value::Int(sq))
1092 } else {
1093 let f = int_to_f64(i)?;
1094 Ok(Value::Float(f.sqrt()))
1095 }
1096 }
1097 }
1098 }
1099 }
1100
1101 pub fn cbrt(self) -> CalcResult {
1103 match &self {
1104 Value::Complex(..) => self.power(Value::Float(1.0f64 / 3.0f64)),
1105 Value::Ratio(r) => {
1106 let f = ratio_to_f64(r)?;
1107 Ok(Value::Float(f.cbrt()))
1108 }
1109 Value::Float(f) => Ok(Value::Float(f.cbrt())),
1110 Value::Int(i) => {
1111 let cb = i.cbrt();
1112 if cb.clone() * cb.clone() * cb.clone() == *i {
1113 return Ok(Value::Int(cb));
1114 }
1115 let f = int_to_f64(&i)?;
1116 Ok(Value::Float(f.cbrt()))
1117 }
1118 }
1119 }
1120
1121 fn fast_power(self, pow: BigInt) -> CalcResult {
1122 if pow.is_zero() {
1123 return Ok(Value::Int(BigInt::one()));
1124 }
1125 let mut pow = pow;
1126 let mut inv = false;
1127 let sgn = pow.sign();
1128 if sgn == Sign::Minus {
1129 inv = true;
1130 pow = -pow;
1131 }
1132
1133 let mut res = Value::Int(BigInt::one());
1134 let mut base = self;
1135 while pow > BigInt::zero() {
1136 if pow.clone() % BigInt::from(2) == BigInt::zero() {
1137 pow /= BigInt::from(2);
1138 base = base.clone().multiply(base.clone())?;
1139 } else {
1140 pow -= BigInt::one();
1141 res = res.multiply(base.clone())?;
1142 }
1143 }
1144 if inv {
1145 return Value::Int(BigInt::one()).divide(res);
1146 }
1147 if Value::is_like_int(&res) {
1148 res = Value::into_int(res)?
1149 }
1150 Ok(res)
1151 }
1152
1153 pub fn power(self, rhs: Value) -> CalcResult {
1158 match (&self, &rhs) {
1159 (Value::Complex(..), ..) | (.., Value::Complex(..)) => {
1160 let v = self.into_raw_complex()?;
1161 let pow = rhs.into_raw_complex()?;
1162 Ok(Value::Complex(v.powc(pow)))
1163 }
1164 (.., Value::Float(..)) => {
1165 let f1 = self.into_raw_f64()?;
1166 let f2 = rhs.into_raw_f64()?;
1167 if f1 < 0.0 {
1168 let c1 = Complex::new(f1, 0.0);
1169 let c2 = Complex::new(f2, 0.0);
1170 return Ok(Value::Complex(c1.powc(c2)));
1171 }
1172 let f1 = Value::Float(f1.powf(f2));
1173 if Value::is_like_int(&f1) {
1174 return Value::into_int(f1);
1175 }
1176 Ok(f1)
1177 }
1178 (.., Value::Int(i)) => self.fast_power(i.clone()),
1179 _ => Err(CalcError::Unreachable),
1180 }
1181 }
1182
1183 pub fn fact(self) -> CalcResult {
1188 if Value::is_zero(&self) {
1189 return Ok(Value::Int(BigInt::one()));
1190 }
1191
1192 match &self {
1193 Value::Complex(..) => Err(CalcError::NotForComplex("factorial".to_owned())),
1194 Value::Ratio(..) | Value::Float(..) => {
1195 if Value::is_like_int(&self) {
1196 let i = Value::into_int(self)?;
1197 let i = if let Value::Int(i1) = i {
1198 i1
1199 } else {
1200 return Err(CalcError::Unreachable);
1201 };
1202 if i < BigInt::zero() {
1203 return Err(CalcError::NotForNegativeInt("factorial".to_owned()));
1204 }
1205 let mut res = BigInt::one();
1206 let mut cnt = BigInt::from(1);
1207 while cnt <= i {
1208 res *= cnt.clone();
1209 cnt += BigInt::one();
1210 }
1211 return Ok(Value::Int(res));
1212 }
1213 Err(CalcError::NotSupportedYet("factorial".to_owned(), "float".to_owned()))
1215 }
1216 Value::Int(i) => {
1217 if *i < BigInt::zero() {
1218 return Err(CalcError::NotForNegativeInt("factorial".to_owned()));
1219 }
1220 let mut res = BigInt::one();
1221 let mut cnt = BigInt::from(1);
1222 while cnt <= *i {
1223 res *= cnt.clone();
1224 cnt += BigInt::one();
1225 }
1226 Ok(Value::Int(res))
1227 }
1228 }
1229 }
1230
1231 bitwise_op!(bit_or, |);
1232 bitwise_op!(bit_and, &);
1233 bitwise_op!(bit_xor, ^);
1234 bitwise_shift_op!(bit_shl, <<);
1235 bitwise_shift_op!(bit_shr, >>);
1236
1237 pub fn bit_not(self) -> CalcResult {
1238 match &self {
1239 Value::Int(i1) => Ok(Value::Int(!i1)),
1240 _ => Err(CalcError::OnlyInt("bitwise not".to_string())),
1241 }
1242 }
1243
1244 sin_cos!(sin);
1245 sin_cos!(cos);
1246 pub fn tan(self) -> CalcResult {
1247 match &self {
1248 Value::Complex(c) => Ok(Value::Complex(c.tan())),
1249 _ => {
1250 let f = self.clone().into_raw_f64()?;
1251 let half = consts::PI / 2.0;
1252 let ipart = (f / half).trunc();
1253 if f64_equal(ipart * half, f) {
1254 Err(CalcError::InvalidAgrument("tan".to_owned(), format!("{}", self)))
1255 } else {
1256 Ok(Value::Float(f.tan()))
1257 }
1258 }
1259 }
1260 }
1261
1262 asin_cos!(asin);
1263 asin_cos!(acos);
1264 pub fn atan(self) -> CalcResult {
1265 match &self {
1266 Value::Complex(c) => Ok(Value::Complex(c.atan())),
1267 _ => {
1268 let f = self.into_raw_f64()?;
1269 Ok(Value::Float(f.atan()))
1270 }
1271 }
1272 }
1273
1274 fn_hyper!(sinh);
1275 fn_hyper!(cosh);
1276 fn_hyper!(tanh);
1277 fn_hyper!(asinh);
1278 fn_hyper!(acosh);
1279 fn_hyper!(exp);
1280 pub fn atanh(self) -> CalcResult {
1281 match &self {
1282 Value::Complex(c) => Ok(Value::Complex(c.atanh())),
1283 _ => {
1284 let f = self.clone().into_raw_f64()?;
1285 if (-1.0..=1.0).contains(&f) {
1286 Ok(Value::Float(f.atanh()))
1287 } else {
1288 Err(CalcError::InvalidAgrument("atanh".to_owned(), format!("{}", self)))
1289 }
1290 }
1291 }
1292 }
1293
1294 pub fn ln(self) -> CalcResult {
1297 if Value::is_zero(&self) {
1298 return Err(CalcError::InvalidAgrument("ln".to_owned(), format!("{}", self)));
1299 }
1300 match &self {
1301 Value::Complex(c) => Ok(Value::Complex(c.ln())),
1302 _ => {
1303 let f = self.clone().into_raw_f64()?;
1304 if f > 0.0 {
1305 Ok(Value::Float(f.ln()))
1306 } else {
1307 let cm = Complex::new(f, 0.0);
1308 Ok(Value::Complex(cm.ln()))
1309 }
1310 }
1311 }
1312 }
1313
1314 pub fn ratio(self) -> CalcResult {
1317 match &self {
1318 Value::Ratio(..) => Ok(self),
1319 Value::Int(i) => Ok(Value::Ratio(BigRational::new(i.clone(), BigInt::one()))),
1320 Value::Float(f) => {
1321 if let Some(r) = BigRational::from_float(*f) {
1322 Ok(Value::Ratio(r))
1323 } else {
1324 Err(CalcError::InvalidAgrument("ratio".to_owned(), format!("{}", f)))
1325 }
1326 }
1327 Value::Complex(..) => Err(CalcError::NotForComplex("ratio".to_string())),
1328 }
1329 }
1330
1331 pub fn gcd(self, rhs: Value) -> CalcResult {
1333 let mut v1 = self.into_raw_big_int()?;
1334 let mut v2 = rhs.into_raw_big_int()?;
1335 if v1 < BigInt::zero() {
1336 v1 = -v1;
1337 }
1338 if v2 < BigInt::zero() {
1339 v2 = -v2;
1340 }
1341
1342 loop {
1343 if v1.is_zero() {
1344 return Ok(Value::Int(v2));
1345 }
1346 if v2.is_zero() {
1347 return Ok(Value::Int(v1));
1348 }
1349 if v1 < v2 {
1350 std::mem::swap(&mut v1, &mut v2);
1351 }
1352
1353 let m = v1 % v2.clone();
1354 v1 = v2;
1355 v2 = m;
1356 }
1357 }
1358
1359 pub fn lcm(self, rhs: Value) -> CalcResult {
1361 let gcd = self.clone().gcd(rhs.clone())?;
1362 let gcd = gcd.into_raw_big_int()?;
1363 let mut v1 = self.into_raw_big_int()?;
1364 let mut v2 = rhs.into_raw_big_int()?;
1365 if v1 < BigInt::zero() {
1366 v1 = -v1;
1367 }
1368 if v2 < BigInt::zero() {
1369 v2 = -v2;
1370 }
1371
1372 Ok(Value::Int(v1 / gcd * v2))
1373 }
1374
1375 pub fn prime(self) -> CalcResult {
1378 let v = self.abs()?;
1379 let v = if let Value::Int(i) = v {
1380 i
1381 } else {
1382 return Err(CalcError::OnlyInt("is_prime".to_string()));
1383 };
1384
1385 let res = if v <= BigInt::one() {
1386 Value::Int(BigInt::zero())
1387 } else if v > BigInt::one() && v < BigInt::from(4) {
1388 Value::Int(BigInt::one())
1389 } else if v.clone() % BigInt::from(2) == BigInt::zero() {
1390 Value::Int(BigInt::zero())
1391 } else {
1392 let upto = v.sqrt();
1393 let mut curr = BigInt::from(3);
1394 let mut r = BigInt::one();
1395 while curr <= upto {
1396 if v.clone() % curr.clone() == BigInt::zero() {
1397 r = BigInt::zero();
1398 break;
1399 }
1400 curr += BigInt::from(2);
1401 }
1402 Value::Int(r)
1403 };
1404 Ok(res)
1405 }
1406}
1407
1408#[cfg(test)]
1409mod tests {
1410 use super::*;
1411 use std::f64::consts;
1412 #[test]
1413 fn test_int_str() {
1414 let v = Value::from_str_integer("10002");
1415 assert_eq!(v, Ok(Value::Int(BigInt::from(10002i64))));
1416 let v = Value::from_str_integer("10_00_2");
1417 assert_eq!(v, Ok(Value::Int(BigInt::from(10002i64))));
1418 let v = Value::from_str_integer("-10002");
1419 assert_eq!(v, Ok(Value::Int(BigInt::from(-10002i64))));
1420 let v = Value::from_str_integer("33e5");
1421 assert_eq!(v, Ok(Value::Int(BigInt::from(3300000i64))));
1422 let v = Value::from_str_integer("33E6");
1423 assert_eq!(v, Ok(Value::Int(BigInt::from(33000000i64))));
1424
1425 let v = Value::from_str_integer("0Xff");
1426 assert_eq!(v, Ok(Value::Int(BigInt::from(255i64))));
1427 let v = Value::from_str_integer("0xff");
1428 assert_eq!(v, Ok(Value::Int(BigInt::from(255i64))));
1429 let v = Value::from_str_integer("0O33");
1430 assert_eq!(v, Ok(Value::Int(BigInt::from(27i64))));
1431 let v = Value::from_str_integer("0o33");
1432 assert_eq!(v, Ok(Value::Int(BigInt::from(27i64))));
1433 let v = Value::from_str_integer("0B101");
1434 assert_eq!(v, Ok(Value::Int(BigInt::from(5i64))));
1435 let v = Value::from_str_integer("0b101");
1436 assert_eq!(v, Ok(Value::Int(BigInt::from(5i64))));
1437 }
1438 #[test]
1439 fn test_float_str() {
1440 let v = Value::from_str_float("10002");
1441 assert_eq!(v, Ok(Value::Float(10002.0f64)));
1442 let v = Value::from_str_float("10_00_2");
1443 assert_eq!(v, Ok(Value::Float(10002.0f64)));
1444 let v = Value::from_str_float("10_00_3.5");
1445 assert_eq!(v, Ok(Value::Float(10003.5f64)));
1446 let v = Value::from_str_float("10_00_3,5");
1447 assert_eq!(v, Ok(Value::Float(10003.5f64)));
1448 let v = Value::from_str_float("1.0002e5");
1449 assert_eq!(v, Ok(Value::Float(100020.0f64)));
1450 let v = Value::from_str_float("200e-2");
1451 assert_eq!(v, Ok(Value::Float(2.0f64)));
1452 }
1453 #[test]
1454 fn test_ratio_str() {
1455 let v = Value::from_str_ratio("1\\2");
1456 assert_eq!(v, Ok(Value::Ratio(BigRational::new(BigInt::one(), BigInt::from(2i64)))));
1457 let v = Value::from_str_ratio("3\\2\\10");
1458 assert_eq!(v, Ok(Value::Ratio(BigRational::new(BigInt::from(3i64 * 10i64 + 2i64), BigInt::from(10i64)))));
1459 }
1460 #[test]
1461 fn test_angle_str() {
1462 let coef: f64 = consts::PI / 180.0f64;
1463 let v = Value::from_str_angle("10d");
1464 assert_eq!(v, Ok(Value::Float(10f64 * coef)));
1465 let v = Value::from_str_angle("10°");
1466 assert_eq!(v, Ok(Value::Float(10f64 * coef)));
1467 let v = Value::from_str_angle("10.5d");
1468 assert_eq!(v, Ok(Value::Float(10.5f64 * coef)));
1469 let v = Value::from_str_angle("10d30m");
1470 assert_eq!(v, Ok(Value::Float(10.5f64 * coef)));
1471 let v = Value::from_str_angle("10d30m900s");
1472 assert_eq!(v, Ok(Value::Float(10.75f64 * consts::PI / 180.0f64)));
1473 }
1474 #[test]
1475 fn test_complex_str() {
1476 let v = Value::from_str_complex("10.0e-1+50e-3i");
1477 assert_eq!(v, Ok(Value::Complex(Complex::new(1.0f64, 0.05f64))));
1478 let v = Value::from_str_complex("10.0e1-50e2i");
1479 assert_eq!(v, Ok(Value::Complex(Complex::new(100.0f64, -5000.0f64))));
1480 let v = Value::from_str_complex("10.0e-1+50e-3j");
1481 assert_eq!(v, Ok(Value::Complex(Complex::new(1.0f64, 0.05f64))));
1482 let v = Value::from_str_complex("10.0e-1+50e-3I");
1483 assert_eq!(v, Ok(Value::Complex(Complex::new(1.0f64, 0.05f64))));
1484 let v = Value::from_str_complex("10.0e-1+50e-3J");
1485 assert_eq!(v, Ok(Value::Complex(Complex::new(1.0f64, 0.05f64))));
1486
1487 let v = Value::from_str_complex("10.0e-1-i50e-3");
1488 assert_eq!(v, Ok(Value::Complex(Complex::new(1.0f64, -0.05f64))));
1489 let v = Value::from_str_complex("10.0e1-i50e2");
1490 assert_eq!(v, Ok(Value::Complex(Complex::new(100.0f64, -5000.0f64))));
1491 let v = Value::from_str_complex("10.0e-1-j50e-3");
1492 assert_eq!(v, Ok(Value::Complex(Complex::new(1.0f64, -0.05f64))));
1493 let v = Value::from_str_complex("10.0e-1-I50e-3");
1494 assert_eq!(v, Ok(Value::Complex(Complex::new(1.0f64, -0.05f64))));
1495 let v = Value::from_str_complex("10.0e-1-J50e-3");
1496 assert_eq!(v, Ok(Value::Complex(Complex::new(1.0f64, -0.05f64))));
1497 let v = Value::from_str_complex("-10.0e-1-J50e-3");
1498 assert_eq!(v, Ok(Value::Complex(Complex::new(-1.0f64, -0.05f64))));
1499
1500 let v = Value::from_str_complex("-i50e-3");
1501 assert_eq!(v, Ok(Value::Complex(Complex::new(0.0f64, -0.05f64))));
1502 let v = Value::from_str_complex("j50e-3");
1503 assert_eq!(v, Ok(Value::Complex(Complex::new(0.0f64, 0.05f64))));
1504 let v = Value::from_str_complex("-50e-3J");
1505 assert_eq!(v, Ok(Value::Complex(Complex::new(0.0f64, -0.05f64))));
1506 let v = Value::from_str_complex("50e-3I");
1507 assert_eq!(v, Ok(Value::Complex(Complex::new(0.0f64, 0.05f64))));
1508 let v = Value::from_str_complex("-i50e3");
1509 assert_eq!(v, Ok(Value::Complex(Complex::new(0.0f64, -50000.0f64))));
1510 let v = Value::from_str_complex("j50e3");
1511 assert_eq!(v, Ok(Value::Complex(Complex::new(0.0f64, 50000.0f64))));
1512 let v = Value::from_str_complex("-50e3J");
1513 assert_eq!(v, Ok(Value::Complex(Complex::new(0.0f64, -50000.0f64))));
1514 let v = Value::from_str_complex("50e3I");
1515 assert_eq!(v, Ok(Value::Complex(Complex::new(0.0f64, 50000.0f64))));
1516 }
1517 #[test]
1518 fn test_to_str() {
1519 let v = Value::Int(BigInt::from(12345));
1520 assert_eq!(v.to_string(), "12345");
1521 let v = Value::Float(2.25f64);
1522 assert_eq!(v.to_string(), "2.25");
1523 let v = Value::Ratio(BigRational::new(BigInt::from(23), BigInt::from(35)));
1524 assert_eq!(v.to_string(), "23\\35");
1525 let v = Value::Ratio(BigRational::new(BigInt::from(23), BigInt::from(5)));
1526 assert_eq!(v.to_string(), "4\\3\\5");
1527 let v = Value::Complex(Complex::new(0.0, 1.25));
1528 assert_eq!(v.to_string(), "0.0+1.25i");
1529 let v = Value::Complex(Complex::new(4.5, -3.25));
1530 assert_eq!(v.to_string(), "4.5-3.25i");
1531 }
1532 #[test]
1533 fn test_convert_int() {
1534 let v = Value::Int(BigInt::from(123));
1535 let f = Value::into_float(v.clone());
1536 assert_eq!(f, Ok(Value::Float(123.0)));
1537 let f = Value::into_complex(v.clone());
1538 assert_eq!(f, Ok(Value::Complex(Complex::new(123.0, 0.0))));
1539 let f = Value::into_ratio(v.clone());
1540 assert_eq!(f, Ok(Value::Ratio(BigRational::new(BigInt::from(123), BigInt::one()))));
1541 }
1542 #[test]
1543 fn test_convert_float() {
1544 let v = Value::Float(12.5);
1545 let f = Value::into_int(v.clone());
1546 assert_eq!(f, Ok(Value::Int(BigInt::from(12))));
1547 let f = Value::into_complex(v.clone());
1548 assert_eq!(f, Ok(Value::Complex(Complex::new(12.5, 0.0))));
1549 let f = Value::into_ratio(v.clone());
1550 assert_eq!(f, Ok(Value::Ratio(BigRational::new(BigInt::from(25), BigInt::from(2)))));
1551 }
1552 #[test]
1553 fn test_convert_ratio() {
1554 let v = Value::Ratio(BigRational::new(BigInt::from(5), BigInt::from(2)));
1555 let f = Value::into_int(v.clone());
1556 assert_eq!(f, Ok(Value::Int(BigInt::from(2))));
1557 let f = Value::into_complex(v.clone());
1558 assert_eq!(f, Ok(Value::Complex(Complex::new(2.5, 0.0))));
1559 let f = Value::into_float(v.clone());
1560 assert_eq!(f, Ok(Value::Float(2.5)));
1561 }
1562 #[test]
1563 fn test_convert_complex() {
1564 let v = Value::Complex(Complex::new(2.5, 3.5));
1565 let f = Value::into_int(v.clone());
1566 assert_eq!(f, Ok(Value::Int(BigInt::from(2))));
1567 let f = Value::into_ratio(v.clone());
1568 assert_eq!(f, Ok(Value::Ratio(BigRational::new(BigInt::from(5), BigInt::from(2)))));
1569 let f = Value::into_float(v.clone());
1570 assert_eq!(f, Ok(Value::Float(2.5)));
1571 }
1572 #[test]
1573 fn test_add() {
1574 let v1 = Value::Int(BigInt::from(3));
1575 let v2 = Value::Int(BigInt::from(4));
1576 let r = v1.addition(v2);
1577 assert_eq!(r, Ok(Value::Int(BigInt::from(7))));
1578 let v1 = Value::Int(BigInt::from(3));
1579 let v2 = Value::Float(4.5);
1580 let r = v1.addition(v2);
1581 assert_eq!(r, Ok(Value::Float(7.5)));
1582 let v1 = Value::Int(BigInt::from(3));
1583 let v2 = Value::Ratio(BigRational::new(BigInt::from(4), BigInt::from(5)));
1584 let r = v1.addition(v2);
1585 assert_eq!(r, Ok(Value::Ratio(BigRational::new(BigInt::from(19), BigInt::from(5)))));
1586 let v1 = Value::Float(0.5);
1587 let v2 = Value::Complex(Complex::new(4.5, 5.0));
1588 let r = v1.addition(v2);
1589 assert_eq!(r, Ok(Value::Complex(Complex::new(5.0, 5.0))));
1590 }
1591 #[test]
1592 fn test_sub() {
1593 let v1 = Value::Int(BigInt::from(3));
1594 let v2 = Value::Int(BigInt::from(4));
1595 let r = v1.subtract(v2);
1596 assert_eq!(r, Ok(Value::Int(BigInt::from(-1))));
1597 let v1 = Value::Int(BigInt::from(3));
1598 let v2 = Value::Float(4.5);
1599 let r = v1.subtract(v2);
1600 assert_eq!(r, Ok(Value::Float(-1.5)));
1601 let v1 = Value::Int(BigInt::from(3));
1602 let v2 = Value::Ratio(BigRational::new(BigInt::from(4), BigInt::from(5)));
1603 let r = v1.subtract(v2);
1604 assert_eq!(r, Ok(Value::Ratio(BigRational::new(BigInt::from(11), BigInt::from(5)))));
1605 let v1 = Value::Float(0.5);
1606 let v2 = Value::Complex(Complex::new(4.5, 5.0));
1607 let r = v1.subtract(v2);
1608 assert_eq!(r, Ok(Value::Complex(Complex::new(-4.0, -5.0))));
1609 }
1610 #[test]
1611 fn test_mul() {
1612 let v1 = Value::Int(BigInt::from(3));
1613 let v2 = Value::Int(BigInt::from(4));
1614 let r = v1.multiply(v2);
1615 assert_eq!(r, Ok(Value::Int(BigInt::from(12))));
1616 let v1 = Value::Int(BigInt::from(3));
1617 let v2 = Value::Float(4.5);
1618 let r = v1.multiply(v2);
1619 assert_eq!(r, Ok(Value::Float(13.5)));
1620 let v1 = Value::Int(BigInt::from(3));
1621 let v2 = Value::Ratio(BigRational::new(BigInt::from(4), BigInt::from(5)));
1622 let r = v1.multiply(v2);
1623 assert_eq!(r, Ok(Value::Ratio(BigRational::new(BigInt::from(12), BigInt::from(5)))));
1624 let v1 = Value::Float(5.0);
1625 let v2 = Value::Complex(Complex::new(4.0, 1.0));
1626 let r = v1.multiply(v2);
1627 assert_eq!(r, Ok(Value::Complex(Complex::new(20.0, 5.0))));
1628 }
1629 #[test]
1630 fn test_div() {
1631 let v1 = Value::Int(BigInt::from(12));
1632 let v2 = Value::Int(BigInt::from(4));
1633 let r = v1.divide(v2);
1634 assert_eq!(r, Ok(Value::Int(BigInt::from(3))));
1635 let v1 = Value::Int(BigInt::from(3));
1636 let v2 = Value::Int(BigInt::from(4));
1637 let r = v1.divide(v2);
1638 assert_eq!(r, Ok(Value::Float(0.75)));
1639 let v1 = Value::Float(3.0);
1640 let v2 = Value::Float(1.5);
1641 let r = v1.divide(v2);
1642 assert_eq!(r, Ok(Value::Int(BigInt::from(2))));
1643 let v1 = Value::Int(BigInt::from(3));
1644 let v2 = Value::Ratio(BigRational::new(BigInt::from(4), BigInt::from(5)));
1645 let r = v1.divide(v2);
1646 assert_eq!(r, Ok(Value::Ratio(BigRational::new(BigInt::from(15), BigInt::from(4)))));
1647 let v1 = Value::Float(5.0);
1648 let v2 = Value::Complex(Complex::new(5.0, 5.0));
1649 let r = v1.divide(v2);
1650 assert_eq!(r, Ok(Value::Complex(Complex::new(0.5, -0.5))));
1651 }
1652 #[test]
1653 fn test_div_int() {
1654 let v1 = Value::Int(BigInt::from(12));
1655 let v2 = Value::Int(BigInt::from(4));
1656 let r = v1.div_int(v2);
1657 assert_eq!(r, Ok(Value::Int(BigInt::from(3))));
1658 let v1 = Value::Int(BigInt::from(3));
1659 let v2 = Value::Int(BigInt::from(4));
1660 let r = v1.div_int(v2);
1661 assert_eq!(r, Ok(Value::Int(BigInt::zero())));
1662 let v1 = Value::Float(3.0);
1663 let v2 = Value::Float(1.5);
1664 let r = v1.div_int(v2);
1665 assert_eq!(r, Ok(Value::Int(BigInt::from(2))));
1666 let v1 = Value::Float(5.0);
1667 let v2 = Value::Float(3.0);
1668 let r = v1.div_int(v2);
1669 assert_eq!(r, Ok(Value::Int(BigInt::one())));
1670 let v1 = Value::Int(BigInt::from(3));
1671 let v2 = Value::Ratio(BigRational::new(BigInt::from(4), BigInt::from(5)));
1672 let r = v1.div_int(v2);
1673 assert_eq!(r, Ok(Value::Int(BigInt::from(3))));
1674 let v1 = Value::Complex(Complex::new(50.0, 25.0));
1675 let v2 = Value::Float(5.0);
1676 let r = v1.div_int(v2);
1677 assert_eq!(r, Ok(Value::Int(BigInt::from(10))));
1678 }
1679 #[test]
1680 fn test_neg() {
1681 let v = Value::Int(BigInt::from(12)).negate();
1682 assert_eq!(v, Ok(Value::Int(BigInt::from(-12))));
1683 let v = Value::Float(3.4).negate();
1684 assert_eq!(v, Ok(Value::Float(-3.4)));
1685 let v = Value::Ratio(BigRational::new(BigInt::from(2), BigInt::from(5))).negate();
1686 assert_eq!(v, Ok(Value::Ratio(-BigRational::new(BigInt::from(2), BigInt::from(5)))));
1687 let v = Value::Complex(Complex::new(3.0, 4.0)).negate();
1688 assert_eq!(v, Ok(Value::Complex(Complex::new(-3.0, -4.0))));
1689 }
1690 #[test]
1691 fn test_conj() {
1692 let v = Value::Float(3.4).conj();
1693 assert_eq!(v, Ok(Value::Float(3.4)));
1694 let v = Value::Complex(Complex::new(3.0, 4.0)).conj();
1695 assert_eq!(v, Ok(Value::Complex(Complex::new(3.0, -4.0))));
1696 }
1697 #[test]
1698 fn test_eq() {
1699 let v1 = Value::Float(3.0);
1700 let v2 = Value::Int(BigInt::from(3));
1701 let v = v1.eq(v2);
1702 assert_eq!(v, Ok(Value::Int(BigInt::one())));
1703 let v1 = Value::Float(2.5);
1704 let v2 = Value::Ratio(BigRational::new(BigInt::from(5), BigInt::from(2)));
1705 let v = v1.eq(v2);
1706 assert_eq!(v, Ok(Value::Int(BigInt::one())));
1707 let v1 = Value::Complex(Complex::new(3.0, 2.0));
1708 let v2 = Value::Complex(Complex::new(3.0, 2.0));
1709 let v = v1.eq(v2);
1710 assert_eq!(v, Ok(Value::Int(BigInt::one())));
1711 let v1 = Value::Complex(Complex::new(3.0, 2.0));
1712 let v2 = Value::Float(3.0);
1713 let v = v1.eq(v2);
1714 assert_eq!(v, Ok(Value::Int(BigInt::zero())));
1715 }
1716 #[test]
1717 fn test_neq() {
1718 let v1 = Value::Float(3.0);
1719 let v2 = Value::Int(BigInt::from(3));
1720 let v = v1.neq(v2);
1721 assert_eq!(v, Ok(Value::Int(BigInt::zero())));
1722 let v1 = Value::Float(2.5);
1723 let v2 = Value::Ratio(BigRational::new(BigInt::from(5), BigInt::from(2)));
1724 let v = v1.neq(v2);
1725 assert_eq!(v, Ok(Value::Int(BigInt::zero())));
1726 let v1 = Value::Complex(Complex::new(3.0, 2.0));
1727 let v2 = Value::Complex(Complex::new(3.0, 2.0));
1728 let v = v1.neq(v2);
1729 assert_eq!(v, Ok(Value::Int(BigInt::zero())));
1730 let v1 = Value::Complex(Complex::new(3.0, 2.0));
1731 let v2 = Value::Float(3.0);
1732 let v = v1.neq(v2);
1733 assert_eq!(v, Ok(Value::Int(BigInt::one())));
1734 }
1735 #[test]
1736 fn test_less() {
1737 let v1 = Value::Float(3.0);
1738 let v2 = Value::Int(BigInt::from(4));
1739 let v = v1.less(v2);
1740 assert_eq!(v, Ok(Value::Int(BigInt::one())));
1741 let v1 = Value::Float(2.4);
1742 let v2 = Value::Ratio(BigRational::new(BigInt::from(5), BigInt::from(2)));
1743 let v = v1.less(v2);
1744 assert_eq!(v, Ok(Value::Int(BigInt::one())));
1745 let v1 = Value::Complex(Complex::new(3.1, 2.1));
1746 let v2 = Value::Complex(Complex::new(3.0, 2.0));
1747 let v = v1.less(v2);
1748 assert_eq!(v, Ok(Value::Int(BigInt::zero())));
1749 let v1 = Value::Complex(Complex::new(3.0, 2.0));
1750 let v2 = Value::Float(3.0);
1751 let v = v1.less(v2);
1752 assert_eq!(v, Ok(Value::Int(BigInt::zero())));
1753 }
1754 #[test]
1755 fn test_greater() {
1756 let v1 = Value::Float(3.0);
1757 let v2 = Value::Int(BigInt::from(4));
1758 let v = v1.greater(v2);
1759 assert_eq!(v, Ok(Value::Int(BigInt::zero())));
1760 let v1 = Value::Float(2.4);
1761 let v2 = Value::Ratio(BigRational::new(BigInt::from(5), BigInt::from(2)));
1762 let v = v1.greater(v2);
1763 assert_eq!(v, Ok(Value::Int(BigInt::zero())));
1764 let v1 = Value::Complex(Complex::new(3.1, 2.1));
1765 let v2 = Value::Complex(Complex::new(3.0, 2.0));
1766 let v = v1.greater(v2);
1767 assert_eq!(v, Ok(Value::Int(BigInt::one())));
1768 let v1 = Value::Complex(Complex::new(3.0, 2.0));
1769 let v2 = Value::Float(3.0);
1770 let v = v1.greater(v2);
1771 assert_eq!(v, Ok(Value::Int(BigInt::one())));
1772 }
1773 #[test]
1774 fn test_abs() {
1775 let v = Value::Float(3.0).abs();
1776 assert_eq!(v, Ok(Value::Float(3.0)));
1777 let v = Value::Float(-3.0).abs();
1778 assert_eq!(v, Ok(Value::Float(3.0)));
1779 let v = Value::Int(BigInt::from(3)).abs();
1780 assert_eq!(v, Ok(Value::Int(BigInt::from(3))));
1781 let v = Value::Int(BigInt::from(-3)).abs();
1782 assert_eq!(v, Ok(Value::Int(BigInt::from(3))));
1783 let v = Value::Ratio(BigRational::new(BigInt::from(3), BigInt::from(2))).abs();
1784 assert_eq!(v, Ok(Value::Ratio(BigRational::new(BigInt::from(3), BigInt::from(2)))));
1785 let v = Value::Ratio(BigRational::new(BigInt::from(-3), BigInt::from(2))).abs();
1786 assert_eq!(v, Ok(Value::Ratio(BigRational::new(BigInt::from(3), BigInt::from(2)))));
1787 let v = Value::Complex(Complex::new(3.0, -2.0)).abs();
1788 assert_eq!(v, Ok(Value::Complex(Complex::new(3.0, -2.0))));
1789 let v = Value::Complex(Complex::new(-3.0, -2.0)).abs();
1790 assert_eq!(v, Ok(Value::Complex(Complex::new(3.0, -2.0))));
1791 }
1792 #[test]
1793 fn test_sqr() {
1794 let v = Value::Complex(Complex::new(0.0, 3.0)).sqr();
1795 assert_eq!(v, Ok(Value::Float(-9.0)));
1796 }
1797 #[test]
1798 fn test_sqrt() {
1799 let v = Value::Int(BigInt::from(9)).sqrt();
1800 assert_eq!(v, Ok(Value::Int(BigInt::from(3))));
1801 let v = Value::Int(BigInt::from(2)).sqrt().unwrap();
1802 assert_eq!(v.clone().less(Value::Float(1.6)), Ok(Value::Int(BigInt::one())));
1803 assert_eq!(v.greater(Value::Float(1.3)), Ok(Value::Int(BigInt::one())));
1804 let v = Value::Float(0.5);
1805 let r = v.clone().sqr().unwrap().sqrt();
1806 assert_eq!(Ok(v), r);
1807 let v = Value::Float(-4.0);
1808 let r = v.sqrt();
1809 assert!(r.is_ok());
1810 let r = r.unwrap();
1811 assert_eq!(r, Value::Complex(Complex::new(0.0, 2.0)));
1812 }
1813 #[test]
1814 fn test_round() {
1815 let v = Value::Float(2.75);
1816 let a = v.clone().round();
1817 assert_eq!(a, Ok(Value::Int(BigInt::from(3))));
1818 let a = v.clone().ceil();
1819 assert_eq!(a, Ok(Value::Int(BigInt::from(3))));
1820 let a = v.clone().floor();
1821 assert_eq!(a, Ok(Value::Int(BigInt::from(2))));
1822 let v = Value::Ratio(BigRational::new(BigInt::from(9), BigInt::from(4)));
1823 let a = v.clone().round();
1824 assert_eq!(a, Ok(Value::Int(BigInt::from(2))));
1825 let a = v.clone().ceil();
1826 assert_eq!(a, Ok(Value::Int(BigInt::from(3))));
1827 let a = v.clone().floor();
1828 assert_eq!(a, Ok(Value::Int(BigInt::from(2))));
1829 }
1830 #[test]
1831 fn test_power() {
1832 let v = Value::Float(3.0);
1833 let pow = Value::Int(BigInt::from(3));
1834 let v = v.power(pow);
1835 assert_eq!(v, Ok(Value::Int(BigInt::from(27))));
1836 let v = Value::Ratio(BigRational::new(BigInt::from(2), BigInt::from(3)));
1837 let pow = Value::Int(BigInt::from(2));
1838 let v = v.power(pow);
1839 assert_eq!(v, Ok(Value::Ratio(BigRational::new(BigInt::from(4), BigInt::from(9)))));
1840 let v = Value::Float(3.0);
1841 let pow = Value::Float(2.0);
1842 let v = v.power(pow);
1843 assert_eq!(v, Ok(Value::Int(BigInt::from(9))));
1844 }
1845 #[test]
1846 fn test_factorial() {
1847 let v = Value::Float(3.0).fact();
1848 assert_eq!(v, Ok(Value::Int(BigInt::from(6))));
1849 let v = Value::Int(BigInt::from(5)).fact();
1850 assert_eq!(v, Ok(Value::Int(BigInt::from(120))));
1851 }
1852 #[test]
1853 fn test_bitwise() {
1854 let v = Value::Int(BigInt::from(4)).bit_or(Value::Int(BigInt::from(9)));
1855 assert_eq!(v, Ok(Value::Int(BigInt::from(13))));
1856 let v = Value::Int(BigInt::from(5)).bit_and(Value::Int(BigInt::from(14)));
1857 assert_eq!(v, Ok(Value::Int(BigInt::from(4))));
1858 let v = Value::Int(BigInt::from(5)).bit_xor(Value::Int(BigInt::from(14)));
1859 assert_eq!(v, Ok(Value::Int(BigInt::from(11))));
1860 }
1861 #[test]
1862 fn test_exp() {
1863 let v = Value::Float(0.5);
1864 let r = v.clone().exp().unwrap().ln();
1865 assert_eq!(Ok(v.clone()), r);
1866 }
1867 #[test]
1868 fn test_trigonometry() {
1869 let v = Value::Float(0.5);
1870 let r = v.clone().sin().unwrap().asin();
1871 assert_eq!(Ok(v.clone()), r);
1872 let r = v.clone().tan().unwrap().atan();
1873 assert_eq!(Ok(v), r);
1874 }
1875 #[test]
1876 fn test_img() {
1877 let v = Value::Complex(Complex::new(3.0, -4.0));
1878 let r = v.clone().im();
1879 assert_eq!(r, Ok(Value::Float(-4.0)));
1880 let r = v.clone().re();
1881 assert_eq!(r, Ok(Value::Float(3.0)));
1882 let r = v.clone().norm();
1883 assert_eq!(r, Ok(Value::Float(5.0)));
1884 }
1885}