1use std::fmt;
2use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign};
3use pretty::{BoxAllocator, Pretty, DocAllocator, DocBuilder};
4use crate::context::{Ctx, Set};
5use crate::traits::{Specializable, Normalizable};
6use crate::bin::Bin;
7
8#[cfg(test)]
9use crate::assert_eqn;
10
11#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
15pub struct Mono<Id> {
16 mult: i32, terms: Ctx<Id, u8>, bin: Bin<Id> }
20
21impl<Id: Ord> Mono<Id> {
22 pub fn lit(mult: i32) -> Self where Id: Ord {
23 let (p, r) = Bin::log2(mult);
24 Mono { mult: r, terms: Ctx::new(), bin: p }
25 }
26 pub fn var(v: Id) -> Self where Id: Ord {
27 Mono { mult:1, terms: Ctx::from([(v, 1)]), bin: Bin::default() }
28 }
29 pub fn term(v: Id, exp: u8) -> Self {
30 if exp == 0 {
31 Mono::lit(1)
32 } else {
33 Mono { mult: 1, terms: Ctx::from([(v, exp)]), bin: Bin::default() }
34 }
35 }
36 pub fn bin(b: Bin<Id>) -> Self where Id: Ord {
37 Mono { mult: 1, terms: Ctx::new(), bin: b }
38 }
39 pub fn log2(i: i32) -> Self {
40 let (p, r) = Bin::log2(i);
41 Mono { mult: r, terms: Ctx::new(), bin: p }
42 }
43 pub fn neg(self) -> Self {
44 Mono { mult: -self.mult, terms: self.terms, bin: self.bin }
45 }
46 pub fn double(self) -> Self where Id: Clone {
48 Mono { mult: self.mult, terms: self.terms, bin: self.bin.double() }
49 }
50 pub fn half(self) -> Option<Self> {
52 if self.mult % 2 == 0 && self.mult > 0 { Some(Mono { mult: self.mult / 2, terms: self.terms, bin: self.bin })
54 } else if let Some(b) = self.bin.half() {
55 Some(Mono { mult: self.mult, terms: self.terms, bin: b })
56 } else {
57 None
58 }
59 }
60
61 pub fn div_bin(&self, other: &Bin<Id>) -> (Self, Bin<Id>) where Id: Clone {
63 let mut res = self.clone();
64 let (q, r) = res.bin.div(other.clone());
65 res.bin = q;
66 (res, r)
67 }
68}
69
70impl<T: Ord> Default for Mono<T> {
71 fn default() -> Self {
72 Mono::bin(Bin::default())
73 }
74}
75
76impl<T: Ord> MulAssign<Mono<T>> for Mono<T> {
78 fn mul_assign(&mut self, other: Self) {
79 for (k, v) in other.terms.into_iter().filter(|(_, v)| *v > 0) {
80 self.terms.insert_with(k, v, &|x, y| x + y);
81 }
82 self.mult *= other.mult;
85 self.bin *= other.bin;
86 }
87}
88
89impl<T: Ord> MulAssign<Bin<T>> for Mono<T> {
91 fn mul_assign(&mut self, other: Bin<T>) {
92 self.bin *= other;
93 }
94}
95
96impl <T: Ord> MulAssign<i32> for Mono<T> {
98 fn mul_assign(&mut self, other: i32) {
99 let (p, r) = Bin::log2(self.mult * other);
100 self.mult = r;
101 self.bin *= p;
102 }
103}
104
105impl<T: Ord + Clone> Mul<Mono<T>> for Mono<T> {
106 type Output = Self;
107 fn mul(self, other: Self) -> Self::Output {
108 let mut res = self.clone();
109 res *= other;
110 res
111 }
112}
113
114impl<T: Ord + Clone> Mul<Bin<T>> for Mono<T> {
115 type Output = Self;
116 fn mul(self, other: Bin<T>) -> Self::Output {
117 let mut res = self.clone();
118 res *= other;
119 res
120 }
121}
122
123impl<T: Ord + Clone> Mul<i32> for Mono<T> {
124 type Output = Self;
125 fn mul(self, other: i32) -> Self::Output {
126 let mut res = self.clone();
127 res *= other;
128 res
129 }
130}
131
132impl<T: Ord + Clone> Mul for &Mono<T> {
133 type Output = Mono<T>;
134 fn mul(self, other: Self) -> Self::Output {
135 self.clone() * other.clone()
136 }
137}
138
139impl<T: Ord + Clone> Mul<&Bin<T>> for &Mono<T> {
140 type Output = Mono<T>;
141 fn mul(self, other: &Bin<T>) -> Self::Output {
142 self.clone() * other.clone()
143 }
144}
145
146
147impl<T: Ord> From<Bin<T>> for Mono<T> {
148 fn from(b: Bin<T>) -> Self {
149 Mono::bin(b)
150 }
151}
152
153impl<'a> From<&'a str> for Mono<&'a str> {
154 fn from(s: &'a str) -> Self {
155 Mono::var(s)
156 }
157}
158
159impl<T: Ord> From<i32> for Mono<T> {
160 fn from(l: i32) -> Self {
161 Mono::lit(l)
162 }
163}
164
165impl<T: fmt::Display + Ord + Clone> Specializable<T, u8> for Mono<T> {
166 fn specialize(&mut self, id: &T, val: u8) {
168 if let Some(v) = self.terms.remove(&id) {
169 self.mult *= val.pow(v as u32) as i32;
170 self.bin.specialize(id, val);
172 self.normalize();
173 }
174 self.bin.specialize(id, val)
176 }
177
178 fn free_vars(&self) -> Set<&T> {
179 self.terms.keys().union(self.bin.free_vars())
180 }
181}
182
183impl<T: Ord> Normalizable for Mono<T> {
184 fn normalize(&mut self) {
186 let (p, r) = Bin::log2(self.mult);
187 self.bin *= p;
188 self.terms.retain(|_, v| *v > 0);
189 self.mult = r;
190 }
191}
192
193impl<'a, D, A, T> Pretty<'a, D, A> for Mono<T>
197where
198 D: DocAllocator<'a, A>,
199 T: Pretty<'a, D, A> + Clone + Ord,
200 D::Doc: Clone,
201 A: 'a + Clone,
202{
203 fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D, A> {
204 if self.terms.is_empty() {
205 allocator.text(format!("{}", self.mult)).append(allocator.text("*")).append(self.bin.pretty(allocator))
206 } else {
207 allocator.text(format!("{}*", self.mult))
208 .append(allocator.intersperse(self.terms.into_iter()
209 .filter(|(_, v)| *v != 0)
210 .map(|(k, v)|
211 if v == 1 {
212 k.pretty(allocator)
213 } else {
214 k.pretty(allocator).append(allocator.text(format!("^{}", v)))
215 })
216 , "*"))
217 .append(allocator.text("*"))
218 .append(self.bin.pretty(allocator))
219 }
220 }
221}
222
223impl<'a, T> fmt::Display for Mono<T>
225where
226 T: Pretty<'a, BoxAllocator, ()> + Clone + Ord,
227{
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 <Mono<T> as Pretty<'_, BoxAllocator, ()>>::pretty(self.clone(), &BoxAllocator)
230 .1
231 .render_fmt(100, f)
232 }
233}
234
235#[cfg(test)] use arbitrary::{Unstructured, Arbitrary};
236
237#[cfg(test)]
239impl<'a, T: Ord + Clone + Arbitrary<'a>> Arbitrary<'a> for Mono<T> {
240 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
241 let mut mono = Mono {
242 mult : u.int_in_range(0..=9)?,
243 terms : Ctx::arbitrary(u)?,
244 bin : Bin::arbitrary(u)?
245 };
246 mono.normalize();
247 Ok(mono)
248 }
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, Hash)]
255pub struct Dyadic<T> { numer: Set<Mono<T>>, denom: Bin<T> }
256
257impl<T: Ord> Dyadic<T> {
258 pub fn lit(i: i32) -> Self {
259 Dyadic {
260 numer: Set::singleton(Mono::lit(i)),
261 denom: Bin::default()
262 }
263 }
264 pub fn var(v: T) -> Self {
265 Dyadic {
266 numer: Set::singleton(Mono::var(v)),
267 denom: Bin::default()
268 }
269 }
270
271 pub fn bin(b: Bin<T>) -> Self {
272 Dyadic {
273 numer: Set::singleton(Mono::bin(b)),
274 denom: Bin::default()
275 }
276 }
277
278 pub fn unit_add() -> Self {
280 Dyadic { numer: Set::new(), denom: Bin::default() }
281 }
282 pub fn unit_mul() -> Self {
284 Dyadic { numer: Set::singleton(Mono::bin(Bin::default())), denom: Bin::default() }
285 }
286 pub fn neg(self) -> Self {
288 Dyadic {
289 numer: self.numer.into_iter().map(|v| v.neg()).collect(),
290 denom: self.denom
291 }
292 }
293 pub fn double(self) -> Self where T: Clone {
295 if let Some(p) = self.denom.clone().half() {
296 Dyadic { numer: self.numer, denom: p }
298 } else {
299 Dyadic {
301 numer: self.numer.into_iter().map(|v| v.double()).collect(),
302 denom: self.denom
303 }
304 }
305 }
306 pub fn half(self) -> Self where T: Clone {
308 Dyadic { numer: self.numer, denom: self.denom.double() }
309 }
310 pub fn div_bin(&self, other: &Bin<T>) -> Self
312 where
313 T: Clone
314 {
315 let mut s = self.clone();
316 s.denom *= other.clone();
317 s
318 }
319}
320
321impl<T: Ord + Clone> AddAssign<Mono<T>> for Dyadic<T> {
325 fn add_assign(&mut self, other: Mono<T>) {
326 let mono = &other * &self.denom;
328 let join = self.numer.extract_if(&|v: &Mono<T>| v.terms == mono.terms && v.bin == mono.bin);
330 let mult = join.into_iter().fold(mono.mult, |acc, x| acc + x.mult);
332 if mult != 0 {
333 self.numer.insert(Mono { mult, terms: other.terms, bin: other.bin });
334 }
335 }
336}
337
338impl<T: Ord + Clone> AddAssign<Bin<T>> for Dyadic<T> {
339 fn add_assign(&mut self, other: Bin<T>) {
340 *self += Mono::bin(other);
341 }
342}
343
344impl<T: Ord + Clone> AddAssign<i32> for Dyadic<T> {
345 fn add_assign(&mut self, other: i32) {
346 *self += Mono::lit(other);
347 }
348}
349
350impl<T: Ord + Clone> AddAssign for Dyadic<T> {
351 fn add_assign(&mut self, other: Self) {
352 let lcm = self.denom.lcm(&other.denom);
354
355 let (lm, _) = &lcm / &self.denom;
357 let (rm, _) = &lcm / &other.denom;
359
360 let mut hm: Ctx<(&Ctx<T, u8>, Bin<T>), i32> = Ctx::new();
362
363 for l in self.numer.iter() {
365 hm.insert_with((&l.terms, &l.bin * &lm), l.mult, &|a, b| a + b);
366 }
367 for r in other.numer.iter() {
368 hm.insert_with((&r.terms, &r.bin * &rm), r.mult, &|a, b| a + b);
369 }
370 self.numer = hm.into_iter().map(|((t, b), m)| Mono { terms: t.clone(), bin: b, mult: m }).collect();
371 self.denom = lcm;
372 }
373}
374
375impl<T: Ord + Clone> Add for Dyadic<T> {
376 type Output = Dyadic<T>;
377 fn add(self, other: Self) -> Self::Output {
378 let mut res = self.clone();
379 res += other;
380 res
381 }
382}
383
384impl<T: Ord + Clone> Add<Mono<T>> for Dyadic<T> {
385 type Output = Dyadic<T>;
386 fn add(self, other: Mono<T>) -> Self::Output {
387 let mut res = self.clone();
388 res += other;
389 res
390 }
391}
392
393impl<T: Ord + Clone> Add<Bin<T>> for Dyadic<T> {
394 type Output = Dyadic<T>;
395 fn add(self, other: Bin<T>) -> Self::Output {
396 let mut res = self.clone();
397 res += other;
398 res
399 }
400}
401
402impl<T: Ord + Clone> Add for &Dyadic<T> {
403 type Output = Dyadic<T>;
404 fn add(self, other: Self) -> Self::Output {
405 self.clone() + other.clone()
406 }
407}
408
409impl<T: Ord + Clone> Add<&Mono<T>> for &Dyadic<T> {
410 type Output = Dyadic<T>;
411 fn add(self, other: &Mono<T>) -> Self::Output {
412 self.clone() + other.clone()
413 }
414}
415
416impl<T: Ord + Clone> Add<&Bin<T>> for &Dyadic<T> {
417 type Output = Dyadic<T>;
418 fn add(self, other: &Bin<T>) -> Self::Output {
419 self.clone() + other.clone()
420 }
421}
422
423impl<T: Ord + Clone> SubAssign<Mono<T>> for Dyadic<T> {
427 fn sub_assign(&mut self, other: Mono<T>) {
428 *self += other.neg()
429 }
430}
431
432impl<T: Ord + Clone> SubAssign<Bin<T>> for Dyadic<T> {
433 fn sub_assign(&mut self, other: Bin<T>) {
434 *self += Mono::bin(other).neg();
435 }
436}
437
438impl<T: Ord + Clone> SubAssign<i32> for Dyadic<T> {
439 fn sub_assign(&mut self, other: i32) {
440 *self += Mono::lit(-other);
441 }
442}
443
444impl<T: Ord + Clone> SubAssign for Dyadic<T> {
445 fn sub_assign(&mut self, other: Self) {
446 *self += other.neg();
447 }
448}
449
450impl<T: Ord + Clone> Sub for Dyadic<T> {
451 type Output = Dyadic<T>;
452 fn sub(self, other: Self) -> Self::Output {
453 let mut res = self.clone();
454 res -= other;
455 res
456 }
457}
458
459impl<T: Ord + Clone> Sub<Mono<T>> for Dyadic<T> {
460 type Output = Dyadic<T>;
461 fn sub(self, other: Mono<T>) -> Self::Output {
462 let mut res = self.clone();
463 res -= other;
464 res
465 }
466}
467
468impl<T: Ord + Clone> Sub<Bin<T>> for Dyadic<T> {
469 type Output = Dyadic<T>;
470 fn sub(self, other: Bin<T>) -> Self::Output {
471 let mut res = self.clone();
472 res -= other;
473 res
474 }
475}
476
477impl<T: Ord + Clone> Sub for &Dyadic<T> {
478 type Output = Dyadic<T>;
479 fn sub(self, other: Self) -> Self::Output {
480 self.clone() - other.clone()
481 }
482}
483
484impl<T: Ord + Clone> Sub<&Mono<T>> for &Dyadic<T> {
485 type Output = Dyadic<T>;
486 fn sub(self, other: &Mono<T>) -> Self::Output {
487 self.clone() - other.clone()
488 }
489}
490
491impl<T: Ord + Clone> Sub<&Bin<T>> for &Dyadic<T> {
492 type Output = Dyadic<T>;
493 fn sub(self, other: &Bin<T>) -> Self::Output {
494 self.clone() - other.clone()
495 }
496}
497
498impl<T: Ord + Clone> MulAssign<Mono<T>> for Dyadic<T> {
502 fn mul_assign(&mut self, other: Mono<T>) {
503 self.numer.modify(|v| *v *= other.clone());
504 self.normalize();
505 }
506}
507
508impl<T: Ord + Clone> MulAssign<Bin<T>> for Dyadic<T> {
509 fn mul_assign(&mut self, other: Bin<T>) {
510 let gcd = self.denom.gcd(&other);
512 let (mult, _) = other / gcd.clone();
514 self.numer.modify(|x| *x *= mult.clone());
515 (self.denom, _) = self.denom.clone() / gcd;
517 }
518}
519
520impl<T: Ord + Clone> MulAssign<i32> for Dyadic<T> {
521 fn mul_assign(&mut self, other: i32) {
522 let mono= Mono::<T>::log2(other);
523 *self *= mono;
524 }
525}
526
527impl<T: Ord + Clone> MulAssign for Dyadic<T> {
528 fn mul_assign(&mut self, other: Self) {
529 let mut terms = Set::new();
530 for l in self.numer.iter() {
531 for r in other.numer.iter() {
532 terms.insert_with(l * r, |v| v.double());
533 }
534 }
535 self.numer = terms;
536 self.denom *= other.denom;
537 }
538}
539
540impl<T: Ord + Clone> Mul for Dyadic<T> {
541 type Output = Dyadic<T>;
542 fn mul(self, other: Self) -> Self::Output {
543 let mut res = self.clone();
544 res *= other;
545 res
546 }
547}
548
549impl<T: Ord + Clone> Mul<Mono<T>> for Dyadic<T> {
550 type Output = Dyadic<T>;
551 fn mul(self, other: Mono<T>) -> Self::Output {
552 let mut res = self.clone();
553 res *= other;
554 res
555 }
556}
557
558impl<T: Ord + Clone> Mul<Bin<T>> for Dyadic<T> {
559 type Output = Dyadic<T>;
560 fn mul(self, other: Bin<T>) -> Self::Output {
561 let mut res = self.clone();
562 res *= other;
563 res
564 }
565}
566
567impl<T: Ord + Clone> Mul for &Dyadic<T> {
568 type Output = Dyadic<T>;
569 fn mul(self, other: Self) -> Self::Output {
570 self.clone() * other.clone()
571 }
572}
573
574impl<T: Ord + Clone> Mul<&Mono<T>> for &Dyadic<T> {
575 type Output = Dyadic<T>;
576 fn mul(self, other: &Mono<T>) -> Self::Output {
577 self.clone() * other.clone()
578 }
579}
580
581impl<T: Ord + Clone> Mul<&Bin<T>> for &Dyadic<T> {
582 type Output = Dyadic<T>;
583 fn mul(self, other: &Bin<T>) -> Self::Output {
584 self.clone() * other.clone()
585 }
586}
587
588impl<T: Ord> DivAssign<Bin<T>> for Dyadic<T> {
592 fn div_assign(&mut self, other: Bin<T>) {
593 self.denom *= other;
594 }
595}
596
597impl<T: Ord + Clone> Div<Bin<T>> for Dyadic<T> {
598 type Output = Dyadic<T>;
599 fn div(self, other: Bin<T>) -> Self::Output {
600 let mut res = self.clone();
601 res /= other;
602 res
603 }
604}
605
606impl<T: Ord + Clone> Div<&Bin<T>> for &Dyadic<T> {
607 type Output = Dyadic<T>;
608 fn div(self, other: &Bin<T>) -> Self::Output {
609 self.clone() / other.clone()
610 }
611}
612
613impl<'a, D, A, T> Pretty<'a, D, A> for Dyadic<T>
617where
618 D: DocAllocator<'a, A>,
619 T: Pretty<'a, D, A> + Clone + Ord,
620 D::Doc: Clone,
621 A: 'a + Clone,
622{
623 fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D, A> {
624 if self.numer.is_empty() {
625 return allocator.text("0 / ").append(self.denom.pretty(allocator));
626 } else {
627 let num = allocator.intersperse(self.numer.into_iter().map(|v| v.pretty(allocator)), " + ");
628 return num.append(allocator.text(" / ")).append(self.denom.pretty(allocator));
629 }
630 }
631}
632
633impl<'a, T> fmt::Display for Dyadic<T>
635where
636 T: Pretty<'a, BoxAllocator, ()> + Clone + Ord,
637{
638 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
639 <Dyadic<T> as Pretty<'_, BoxAllocator, ()>>::pretty(self.clone(), &BoxAllocator)
640 .1
641 .render_fmt(100, f)
642 }
643}
644
645#[cfg(test)]
647impl<'a, T: Ord + Clone + Arbitrary<'a>> Arbitrary<'a> for Dyadic<T> {
648 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
649 let numer = Set::arbitrary(u)?;
650 let denom = Bin::arbitrary(u)?;
651 let mut d = Dyadic { numer, denom };
652 d.normalize();
653 Ok(d)
654 }
655}
656impl<T: Ord + fmt::Display + Clone> Specializable<T, u8> for Dyadic<T> {
657 fn specialize(&mut self, id: &T, val: u8) {
658 self.numer.modify(|x| x.specialize(id, val));
659 self.denom.specialize(id, val);
660 }
661
662 fn free_vars(&self) -> Set<&T> {
663 self.numer.iter().flat_map(|x|x.free_vars()).collect::<Set<&T>>().union(self.denom.free_vars())
664 }
665}
666
667impl<T: Ord + Clone> Normalizable for Dyadic<T> {
668 fn normalize(&mut self) {
669 self.numer.modify(|x| x.normalize());
671 self.numer.retain(|x| x.mult > 0);
672
673 let mut acc = self.denom.clone();
675 acc.normalize();
676
677 for v in self.numer.iter() {
679 acc = acc.gcd(&v.bin);
680 }
681
682 self.numer.modify(|x| *x = x.div_bin(&acc).0);
684 self.denom = self.denom.clone().div(acc).0;
685
686 let mut hm: Ctx<(&Ctx<T, u8>, Bin<T>), i32> = Ctx::new();
688
689 for l in self.numer.iter() {
691 hm.insert_with((&l.terms, l.bin.clone()), l.mult, &|a, b| a + b);
692 }
693 self.numer = hm.into_iter().map(|((t, b), m)| Mono { terms: t.clone(), bin: b, mult: m }).collect();
694 }
695}
696
697#[test]
701fn test_mono_mul() {
702 let a = Mono::lit(2) * Mono::var("X");
704 let b = Mono::lit(3) * Mono::bin(Bin::var("Y"));
705 assert_eq!(
706 a * b,
707 Mono { mult: 3, terms: Ctx::from([("X", 1)]), bin: Bin::var("Y") * Bin::lit(1) }
708 );
709}
710
711#[test]
712fn test_mono_div_bin() {
713 let a = Mono::lit(2) * Mono::bin(Bin::var("X") * Bin::lit(2));
715 let b = Bin::var("X") * Bin::lit(1);
716 let c = Bin::var("Y") * Bin::lit(3);
717 assert_eq!(
719 a.div_bin(&b),
720 (Mono { mult: 1, terms: Ctx::new(), bin: Bin::lit(2) }, Bin::default())
721 );
722 assert_eq!(
724 a.div_bin(&c),
725 (Mono { mult: 1, terms: Ctx::new(), bin: Bin::var("X") }, Bin::var("Y"))
726 );
727}
728
729#[test]
730fn test_mono_specialize() {
731 let l = Mono::from("x") * Mono::from("y") * Mono::from(2);
732
733 let mut l1 = l.clone();
734 l1.specialize(&"x", 2);
735 assert_eq!(l1, Mono::var("y") * Mono::lit(4));
737
738 let mut l2 = l.clone();
739 l2.specialize(&"y", 3);
740 assert_eq!(l2, Mono::var("x") * Mono::lit(6));
742
743 let mut l3 = l.clone();
744 l3.specialize(&"z", 3);
745 assert_eq!(l3, l);
746}
747#[test]
752fn test_dyadic_add_comm_unit() {
753 let a = Dyadic::lit(2)*Dyadic::var("X")*Dyadic::bin(Bin::lit(2)* Bin::var("y"));
754 let b = Dyadic::lit(3)*Dyadic::var("Y")*Dyadic::bin(Bin::lit(0)* Bin::var("x"));
755 assert_eqn!(&a + &b, &b + &a);
756}
757
758#[test]
759fn test_dyadic_add_lcm_unit() {
760 let a = Dyadic::var("a").div_bin(&Bin::var("n"));
761 let b = Dyadic::var("b").div_bin(&Bin::var("m"));
762 assert_eqn!(&a + &b,
763 Dyadic { numer: Set::from([
764 Mono { mult: 1, terms: Ctx::from([("a", 1)]), bin: Bin::var("m") },
765 Mono { mult: 1, terms: Ctx::from([("b", 1)]), bin: Bin::var("n") }
766 ]), denom: Bin::var("n") * Bin::var("m")
767 });
768}
769
770#[test]
771fn test_dyadic_sub_lcm_unit() {
772 let a = Dyadic::var("a").div_bin(&Bin::var("n"));
773 let b = Dyadic::var("b").div_bin(&Bin::var("m"));
774 assert_eqn!(&a - &b,
775 Dyadic { numer: Set::from([
776 Mono { mult: 1, terms: Ctx::from([("a", 1)]), bin: Bin::var("m") },
777 Mono { mult: -1, terms: Ctx::from([("b", 1)]), bin: Bin::var("n") }
778 ]), denom: Bin::var("n") * Bin::var("m")
779 });
780}
781
782#[test]
783fn test_dyadic_sub_cancel_unit() {
784 let a = Dyadic {
785 numer: Set::from([Mono::<Id>::term(Id::from('a'), 7)]),
786 denom: Bin::default(),
787 };
788 assert_eqn!(&a - &a, Dyadic::<Id>::unit_add());
789}
790
791#[test]
792fn test_dyadic_mul_unit() {
793 let a = Dyadic::lit(2) * Dyadic::var("X");
795 let b = Dyadic::lit(4).div_bin(&Bin::var("Y"));
796 assert_eq!(
797 a * b,
798 Dyadic {
799 numer: Set::singleton(Mono { mult: 1, terms: Ctx::from([("X", 1)]), bin: Bin::lit(3) }),
800 denom: Bin::var("Y")
801 });
802}
803
804#[test]
805fn test_dyadic_specialize_unit() {
806 let l = Dyadic::var("x") * Dyadic::var("y") * Dyadic::lit(2);
807
808 let mut l1 = l.clone();
809 l1.specialize(&"x", 2);
810 assert_eq!(l1, Dyadic::var("y") * Dyadic::lit(4));
812
813 let mut l2 = l.clone();
814 l2.specialize(&"y", 3);
815 assert_eq!(l2, Dyadic::var("x") * Dyadic::lit(6));
817
818 let mut l3 = l.clone();
819 l3.specialize(&"z", 3);
820 assert_eq!(l3, l);
821}
822
823#[test]
824fn test_dyadic_normalize_unit() {
825 let l =
826 Dyadic { numer:
827 Set::from([
828 Mono::var("x") * Mono::var("y") * Mono::lit(4),
829 Mono::var("x") * Mono::lit(4)
830 ]),
831 denom: Bin::lit(2)
832 };
833
834 let mut l1 = l.clone();
835 l1.normalize();
836 assert_eq!(l1, Dyadic { numer: Set::from([Mono::var("x") * Mono::var("y"), Mono::var("x")]), denom: Bin::lit(0) });
837}
838
839#[cfg(test)] use arbtest::arbtest;
843#[cfg(test)] use crate::id::Id;
844
845#[test]
846fn test_mono_mul_prop() {
847 arbtest(|u| {
849 let a = u.arbitrary::<Mono<Id>>()?;
850 let b = u.arbitrary::<Mono<Id>>()?;
851 let c = u.arbitrary::<Mono<Id>>()?;
852 assert_eqn!(&a * &(&b * &c), &(&a * &b) * &c);
853 Ok(())
854 });
855
856 arbtest(|u| {
858 let a = u.arbitrary::<Mono<Id>>()?;
859 let b = u.arbitrary::<Mono<Id>>()?;
860 assert_eqn!(&a * &b, &b * &a);
861 Ok(())
862 });
863
864 arbtest(|u| {
866 let a = u.arbitrary::<Mono<Id>>()?;
867 assert_eqn!(&a * &Mono::default(), a);
868 assert_eqn!(&Mono::default() * &a, a);
869 Ok(())
870 });
871
872 arbtest(|u| {
874 let a = u.arbitrary::<Mono<Id>>()?;
875 assert_eqn!(a.clone().double().half().unwrap(), a);
876 Ok(())
877 });
878}
879
880#[test]
881fn test_dyadic_add_prop() {
882 arbtest(|u| {
884 let a = u.arbitrary::<Dyadic<Id>>()?;
885 let b = u.arbitrary::<Dyadic<Id>>()?;
886 let c = u.arbitrary::<Dyadic<Id>>()?;
887 assert_eqn!(&a + &(&b + &c), &(&a + &b) + &c);
888 Ok(())
889 });
890
891 arbtest(|u| {
893 let a = u.arbitrary::<Dyadic<Id>>()?;
894 let b = u.arbitrary::<Dyadic<Id>>()?;
895 assert_eqn!(&a + &b, &b + &a);
896 Ok(())
897 });
898
899 arbtest(|u| {
901 let a = u.arbitrary::<Dyadic<Id>>()?;
902 assert_eqn!(&a + &Dyadic::unit_add(), a);
903 assert_eqn!(&Dyadic::unit_add() + &a, a);
904 Ok(())
905 });
906}
907
908#[test]
909fn test_dyadic_sub_prop() {
910 arbtest(|u| {
912 let a = u.arbitrary::<Dyadic<Id>>()?;
913 assert_eqn!(&a - &a, Dyadic::<Id>::unit_add());
914 Ok(())
915 });
916
917 arbtest(|u| {
919 let a = u.arbitrary::<Dyadic<Id>>()?;
920 assert_eqn!(&a - &Dyadic::unit_add(), a);
921 assert_eqn!(&Dyadic::unit_add() - &a, a.clone().neg());
922 Ok(())
923 });
924
925 arbtest(|u| {
927 let a = u.arbitrary::<Dyadic<Id>>()?;
928 assert_eqn!(a, a.clone().neg().neg());
929 Ok(())
930 });
931}
932
933#[test]
934fn test_dyadic_mul_prop() {
935 arbtest(|u| {
937 let a = u.arbitrary::<Dyadic<Id>>()?;
938 let b = u.arbitrary::<Dyadic<Id>>()?;
939 let c = u.arbitrary::<Dyadic<Id>>()?;
940 assert_eqn!(&a * &(&b * &c), &(&a * &b) * &c);
941 Ok(())
942 });
943
944 arbtest(|u| {
946 let a = u.arbitrary::<Dyadic<Id>>()?;
947 let b = u.arbitrary::<Dyadic<Id>>()?;
948 assert_eqn!(&a * &b, &b * &a);
949 Ok(())
950 });
951
952 arbtest(|u| {
954 let a = u.arbitrary::<Dyadic<Id>>()?;
955 assert_eqn!(&a * &Dyadic::unit_mul(), a);
956 assert_eqn!(&Dyadic::unit_mul() * &a, a);
957 Ok(())
958 });
959
960 arbtest(|u| {
962 let a = u.arbitrary::<Dyadic<Id>>()?;
963 assert_eqn!(a.clone().double().half(), a);
964 Ok(())
965 });
966}