dashu_int/modular/
repr.rs1use crate::div_const::{ConstDoubleDivisor, ConstLargeDivisor, ConstSingleDivisor};
4use crate::{
5 arch::word::{DoubleWord, Word},
6 buffer::Buffer,
7 cmp,
8 error::panic_different_rings,
9 math,
10};
11use alloc::boxed::Box;
12use core::ptr;
13
14pub struct Reduced<'a>(ReducedRepr<'a>);
26
27pub(crate) enum ReducedRepr<'a> {
28 Single(ReducedWord, &'a ConstSingleDivisor),
29 Double(ReducedDword, &'a ConstDoubleDivisor),
30 Large(ReducedLarge, &'a ConstLargeDivisor),
31}
32
33#[derive(Clone, Copy, Debug, Eq, PartialEq)]
37pub(crate) struct ReducedWord(pub(crate) Word);
38
39#[derive(Clone, Copy, Debug, Eq, PartialEq)]
43pub(crate) struct ReducedDword(pub(crate) DoubleWord);
44
45#[derive(Clone, PartialEq, Eq)]
47pub(crate) struct ReducedLarge(pub(crate) Box<[Word]>);
48
49impl<'a> Reduced<'a> {
50 #[inline]
52 pub(crate) fn repr(&self) -> &ReducedRepr<'a> {
53 &self.0
54 }
55
56 #[inline]
58 pub(crate) fn repr_mut(&mut self) -> &mut ReducedRepr<'a> {
59 &mut self.0
60 }
61
62 #[inline]
63 pub(crate) fn into_repr(self) -> ReducedRepr<'a> {
64 self.0
65 }
66
67 #[inline]
68 pub(crate) const fn from_single(raw: ReducedWord, ring: &'a ConstSingleDivisor) -> Self {
69 debug_assert!(raw.is_valid(ring));
70 Reduced(ReducedRepr::Single(raw, ring))
71 }
72
73 #[inline]
74 pub(crate) const fn from_double(raw: ReducedDword, ring: &'a ConstDoubleDivisor) -> Self {
75 debug_assert!(raw.is_valid(ring));
76 Reduced(ReducedRepr::Double(raw, ring))
77 }
78
79 #[inline]
80 pub(crate) fn from_large(raw: ReducedLarge, ring: &'a ConstLargeDivisor) -> Self {
81 debug_assert!(raw.is_valid(ring));
82 Reduced(ReducedRepr::Large(raw, ring))
83 }
84
85 #[inline]
86 pub(crate) fn check_same_ring_single(lhs: &ConstSingleDivisor, rhs: &ConstSingleDivisor) {
87 if !ptr::eq(lhs, rhs) {
88 panic_different_rings();
90 }
91 }
92
93 #[inline]
94 pub(crate) fn check_same_ring_double(lhs: &ConstDoubleDivisor, rhs: &ConstDoubleDivisor) {
95 if !ptr::eq(lhs, rhs) {
96 panic_different_rings();
98 }
99 }
100
101 #[inline]
102 pub(crate) fn check_same_ring_large(lhs: &ConstLargeDivisor, rhs: &ConstLargeDivisor) {
103 if !ptr::eq(lhs, rhs) {
104 panic_different_rings();
106 }
107 }
108}
109
110impl ReducedWord {
111 pub const fn one(ring: &ConstSingleDivisor) -> Self {
112 Self(1 << ring.shift())
113 }
114
115 #[inline]
116 pub(crate) const fn is_valid(&self, ring: &ConstSingleDivisor) -> bool {
117 self.0 & math::ones_word(ring.shift()) == 0 && self.0 < ring.normalized_divisor()
118 }
119}
120
121impl ReducedDword {
122 pub const fn one(ring: &ConstDoubleDivisor) -> Self {
123 Self(1 << ring.shift())
124 }
125
126 #[inline]
127 pub(crate) const fn is_valid(&self, ring: &ConstDoubleDivisor) -> bool {
128 self.0 & math::ones_dword(ring.shift()) == 0 && self.0 < ring.normalized_divisor()
129 }
130}
131
132impl ReducedLarge {
133 pub fn one(ring: &ConstLargeDivisor) -> Self {
134 let modulus = &ring.normalized_divisor;
135 let mut buf = Buffer::allocate_exact(modulus.len());
136 buf.push(1 << ring.shift);
137 buf.push_zeros(modulus.len() - 1);
138 Self(buf.into_boxed_slice())
139 }
140
141 #[inline]
142 pub(crate) fn is_valid(&self, ring: &ConstLargeDivisor) -> bool {
143 self.0.len() == ring.normalized_divisor.len()
144 && cmp::cmp_same_len(&self.0, &ring.normalized_divisor).is_le()
145 && self.0[0] & math::ones_word(ring.shift) == 0
146 }
147}
148
149impl Clone for Reduced<'_> {
150 #[inline]
151 fn clone(&self) -> Self {
152 Reduced(self.0.clone())
153 }
154 #[inline]
155 fn clone_from(&mut self, source: &Self) {
156 self.0.clone_from(&source.0);
157 }
158}
159
160impl Clone for ReducedRepr<'_> {
161 #[inline]
162 fn clone(&self) -> Self {
163 match self {
164 ReducedRepr::Single(modulo, ring) => ReducedRepr::Single(*modulo, ring),
165 ReducedRepr::Double(modulo, ring) => ReducedRepr::Double(*modulo, ring),
166 ReducedRepr::Large(modulo, ring) => ReducedRepr::Large(modulo.clone(), ring),
167 }
168 }
169
170 #[inline]
171 fn clone_from(&mut self, source: &Self) {
172 if let (ReducedRepr::Large(raw, ring), ReducedRepr::Large(src_raw, src_ring)) =
173 (&mut *self, source)
174 {
175 *ring = src_ring;
176
177 raw.0.clone_from(&src_raw.0);
179 } else {
180 *self = source.clone();
181 }
182 }
183}
184
185impl PartialEq for Reduced<'_> {
191 #[inline]
192 fn eq(&self, other: &Self) -> bool {
193 match (self.repr(), other.repr()) {
194 (ReducedRepr::Single(raw0, ring0), ReducedRepr::Single(raw1, ring1)) => {
195 Reduced::check_same_ring_single(ring0, ring1);
196 raw0.eq(raw1)
197 }
198 (ReducedRepr::Double(raw0, ring0), ReducedRepr::Double(raw1, ring1)) => {
199 Reduced::check_same_ring_double(ring0, ring1);
200 raw0.eq(raw1)
201 }
202 (ReducedRepr::Large(raw0, ring0), ReducedRepr::Large(raw1, ring1)) => {
203 Reduced::check_same_ring_large(ring0, ring1);
204 raw0.eq(raw1)
205 }
206 _ => panic_different_rings(),
207 }
208 }
209}
210
211impl Eq for Reduced<'_> {}