1 // Copyright 2017 Brian Smith. 2 // 3 // Permission to use, copy, modify, and/or distribute this software for any 4 // purpose with or without fee is hereby granted, provided that the above 5 // copyright notice and this permission notice appear in all copies. 6 // 7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 15 // Indicates that the element is not encoded; there is no *R* factor 16 // that needs to be canceled out. 17 #[derive(Copy, Clone)] 18 pub enum Unencoded {} 19 20 // Indicates that the element is encoded; the value has one *R* 21 // factor that needs to be canceled out. 22 #[derive(Copy, Clone)] 23 pub enum R {} 24 25 // Indicates the element is encoded twice; the value has two *R* 26 // factors that need to be canceled out. 27 #[derive(Copy, Clone)] 28 pub enum RR {} 29 30 // Indicates the element is inversely encoded; the value has one 31 // 1/*R* factor that needs to be canceled out. 32 #[derive(Copy, Clone)] 33 pub enum RInverse {} 34 35 pub trait Encoding {} 36 37 impl Encoding for RR {} 38 impl Encoding for R {} 39 impl Encoding for Unencoded {} 40 impl Encoding for RInverse {} 41 42 /// The encoding of the result of a reduction. 43 pub trait ReductionEncoding { 44 type Output: Encoding; 45 } 46 47 impl ReductionEncoding for RR { 48 type Output = R; 49 } 50 impl ReductionEncoding for R { 51 type Output = Unencoded; 52 } 53 impl ReductionEncoding for Unencoded { 54 type Output = RInverse; 55 } 56 57 /// The encoding of the result of a multiplication. 58 pub trait ProductEncoding { 59 type Output: Encoding; 60 } 61 62 impl<E: ReductionEncoding> ProductEncoding for (Unencoded, E) { 63 type Output = E::Output; 64 } 65 66 impl<E: Encoding> ProductEncoding for (R, E) { 67 type Output = E; 68 } 69 70 impl<E: ReductionEncoding> ProductEncoding for (RInverse, E) 71 where 72 E::Output: ReductionEncoding, 73 { 74 type Output = <<E as ReductionEncoding>::Output as ReductionEncoding>::Output; 75 } 76 77 // XXX: Rust doesn't allow overlapping impls, 78 // TODO (if/when Rust allows it): 79 // impl<E1, E2: ReductionEncoding> ProductEncoding for 80 // (E1, E2) { 81 // type Output = <(E2, E1) as ProductEncoding>::Output; 82 // } 83 impl ProductEncoding for (RR, Unencoded) { 84 type Output = <(Unencoded, RR) as ProductEncoding>::Output; 85 } 86 impl ProductEncoding for (RR, RInverse) { 87 type Output = <(RInverse, RR) as ProductEncoding>::Output; 88 } 89