dyadic_rationals/
dyadic.rs

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/// Represents a type-level, signed dyadic monoterm,
12/// eg: 3* a * b^2 * c^3 * 2^(d+e+f+2)
13///     -2 * x * 2^y
14#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
15pub struct Mono<Id> {
16    mult: i32,          // 3
17    terms: Ctx<Id, u8>, // a * b^2 * c^3
18    bin: Bin<Id>        // 2^(d+e+f+2)
19}
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    /// Doubling a term
47    pub fn double(self) -> Self where Id: Clone {
48        Mono { mult: self.mult, terms: self.terms, bin: self.bin.double() }
49    }
50    /// Halving a term could fail (ex: 3*a^2*2^c)
51    pub fn half(self) -> Option<Self> {
52        if self.mult % 2 == 0 && self.mult > 0 { // broken invariant
53            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    /// Division by a bin (with remainder)
62    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
76/// Multiplication of monoterms [normalizes]
77impl<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        // No normalization needed
83        // if a % 2 == 1, b % 2 == 1, then a * b % 2 == 1
84        self.mult *= other.mult;
85        self.bin *= other.bin;
86    }
87}
88
89/// Multiplication of monoterms to bin [normalizes]
90impl<T: Ord> MulAssign<Bin<T>> for Mono<T> {
91    fn mul_assign(&mut self, other: Bin<T>) {
92        self.bin *= other;
93    }
94}
95
96/// Multiplication of monoterms to integers [normalizes]
97impl <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    // ex: 12*a^2*b^3*2^(c+1) -> a = 2 -> 48*b^3*2^(c+3)
167    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            // We already performed [id] substitution so don't fail
171            self.bin.specialize(id, val);
172            self.normalize();
173        }
174        // substitute denominator
175        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    // ex: 12 * a * b^2 * 2^(c+1) -> 3 * a * b^2 * 2^(c + 3)
185    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
193////////////////////////////////////////////////////////////////////////////////////////
194/* Pretty Formatting & Display */
195////////////////////////////////////////////////////////////////////////////////////////
196impl<'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
223/// Display instance calls the pretty printer
224impl<'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/// Arbitrary instance for Mono
238#[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/// Finally a dyadic number
252/// (Mono + ... + Mono) / Bin
253/// Dyadic(Set(), Bin::lit(0)) = Dyadic(Set(Mono::lit(0)), Bin::lit(0)) = 0
254#[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    // Unit of addition
279    pub fn unit_add() -> Self {
280        Dyadic { numer: Set::new(), denom: Bin::default() }
281    }
282    // Unit of multiplication (2^0 / 2^0)
283    pub fn unit_mul() -> Self {
284        Dyadic { numer: Set::singleton(Mono::bin(Bin::default())), denom: Bin::default() }
285    }
286    // -p
287    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    // 2*p
294    pub fn double(self) -> Self where T: Clone {
295        if let Some(p) = self.denom.clone().half() {
296            // First try halving the denominator
297            Dyadic { numer: self.numer, denom: p }
298        } else {
299            // Otherwise multiply all the numerator terms by 2
300            Dyadic {
301                numer: self.numer.into_iter().map(|v| v.double()).collect(),
302                denom: self.denom
303            }
304        }
305    }
306    // p / 2
307    pub fn half(self) -> Self where T: Clone {
308        Dyadic { numer: self.numer, denom: self.denom.double() }
309    }
310    // p / b
311    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
321//////////////////////////////////////////////////////////////////////////////////////////////
322/// Addition of dyadic numbers
323//////////////////////////////////////////////////////////////////////////////////////////////
324impl<T: Ord + Clone> AddAssign<Mono<T>> for Dyadic<T> {
325    fn add_assign(&mut self, other: Mono<T>) {
326        // a / 2^n + b = (a + 2^n * b) / 2^n
327        let mono = &other * &self.denom;
328        // if not normalized, manually combine terms
329        let join = self.numer.extract_if(&|v: &Mono<T>| v.terms == mono.terms && v.bin == mono.bin);
330        // Sum multipliers
331        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        // Compute denominator as the LCM of the two denominators
353        let lcm = self.denom.lcm(&other.denom);
354
355        // Compute the left multiplicative factor (remainder is 0 by LCM property)
356        let (lm, _) = &lcm / &self.denom;
357        // Compute the right multiplicative factor
358        let (rm, _) = &lcm / &other.denom;
359
360        // Make a reverse map of all mono terms to their multipliers
361        let mut hm: Ctx<(&Ctx<T, u8>, Bin<T>), i32> = Ctx::new();
362
363        // Multiply each term by the multiplicative factor and denominator is the lcd
364        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
423//////////////////////////////////////////////////////////////////////////////////////////////
424/// Subtraction of dyadic numbers
425//////////////////////////////////////////////////////////////////////////////////////////////
426impl<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
498//////////////////////////////////////////////////////////////////////////////////////////////
499/// Multiplication of dyadic numbers
500//////////////////////////////////////////////////////////////////////////////////////////////
501impl<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        // Calculate GCD of binary terms
511        let gcd = self.denom.gcd(&other);
512        // Multiply numerator by [other / GCD]
513        let (mult, _) = other / gcd.clone();
514        self.numer.modify(|x| *x *= mult.clone());
515        // Denominator is [denom / GCD]
516        (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
588//////////////////////////////////////////////////////////////////////////////////////////////
589/// Division of dyadic numbers by binary powers
590//////////////////////////////////////////////////////////////////////////////////////////////
591impl<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
613//////////////////////////////////////////////////////////////////////////////////////////////
614/// Pretty printing, display and Arbitrary for Dyadic
615//////////////////////////////////////////////////////////////////////////////////////////////
616impl<'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
633/// Display instance calls the pretty printer
634impl<'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/// Arbitrary instance for Dyadic
646#[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        // 1. Normalize numerator and remove zero terms
670        self.numer.modify(|x| x.normalize());
671        self.numer.retain(|x| x.mult > 0);
672
673        // 2. Take denominator and normalize it
674        let mut acc = self.denom.clone();
675        acc.normalize();
676
677        // 3. Compute greatest-common divisor of all binary multipliers and denominator
678        for v in self.numer.iter() {
679            acc = acc.gcd(&v.bin);
680        }
681
682        // Divide both numerator and denominator by the GCD
683        self.numer.modify(|x| *x = x.div_bin(&acc).0);
684        self.denom = self.denom.clone().div(acc).0;
685
686        // Make a reverse map of all mono terms to their multipliers
687        let mut hm: Ctx<(&Ctx<T, u8>, Bin<T>), i32> = Ctx::new();
688
689        // Cancel out terms
690        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////////////////////////////////////////////////////////////////////////////////////////
698/* Unit Tests for Mono */
699////////////////////////////////////////////////////////////////////////////////////////
700#[test]
701fn test_mono_mul() {
702    // 2 * X * 3 * 2^Y = 6 * X * 2^Y
703    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    // 2 * (2^X * 2^2)
714    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    // 2*(2^X * 2^2) / (2*2^X) = 2^2
718    assert_eq!(
719        a.div_bin(&b),
720        (Mono { mult: 1, terms: Ctx::new(), bin: Bin::lit(2) }, Bin::default())
721    );
722    // 2*(2^X * 2^2) / (2^Y * 2^3) = 2^x /  2^Y
723    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    // 2*x*y -> x = 2 -> 4*y
736    assert_eq!(l1, Mono::var("y") * Mono::lit(4));
737
738    let mut l2 = l.clone();
739    l2.specialize(&"y", 3);
740    // 2*x*y -> y = 3 -> 6*x
741    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////////////////////////////////////////////////////////////////////////////////////////
748/* Unit Tests for Dyadic */
749////////////////////////////////////////////////////////////////////////////////////////
750
751#[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    // 2 * X * 4 / 2^Y = X / 2^(Y-3)
794    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    // 2*x*y -> x = 2 -> 4*y
811    assert_eq!(l1, Dyadic::var("y") * Dyadic::lit(4));
812
813    let mut l2 = l.clone();
814    l2.specialize(&"y", 3);
815    // 2*x*y -> y = 3 -> 6*x
816    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////////////////////////////////////////////////////////////////////////////////////////
840/* Prop tests */
841////////////////////////////////////////////////////////////////////////////////////////
842#[cfg(test)] use arbtest::arbtest;
843#[cfg(test)] use crate::id::Id;
844
845#[test]
846fn test_mono_mul_prop() {
847    // Associativity of multiplication for monoterms
848    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    // Commutativity
857    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    // Unit
865    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    // Double and half
873    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    // Associativity of addition for dyadic numbers
883    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    // Commutativity of addition
892    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    // Unit of addition
900    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    // Cancellativity
911    arbtest(|u| {
912        let a = u.arbitrary::<Dyadic<Id>>()?;
913        assert_eqn!(&a - &a, Dyadic::<Id>::unit_add());
914        Ok(())
915    });
916
917    // Unit of addition
918    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    // Negate twice (idempotence)
926    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    // Associativity of addition for dyadic numbers
936    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    // Commutativity of addition
945    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    // Unit of addition
953    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    // Double and half
961    arbtest(|u| {
962        let a = u.arbitrary::<Dyadic<Id>>()?;
963        assert_eqn!(a.clone().double().half(), a);
964        Ok(())
965    });
966}