1use std::fmt::{Debug, Display};
4
5use num_complex::Complex64;
6use num_integer::Integer;
7use num_rational::Ratio;
8use num_traits::{FromPrimitive, One, PrimInt, ToPrimitive, Zero};
9
10use crate::gaussint::GaussInt;
11use crate::traits::{Ccw, Conj, InnerIntType, IntField, IntRing};
12use crate::zzsigned::ZSigned;
13
14pub type MyInt = i64;
17
18pub type Frac = Ratio<MyInt>;
21
22pub type GInt = GaussInt<Frac>;
26
27#[derive(Debug)]
29pub struct ZZParams<'a> {
30 pub sym_roots_sqs: &'a [f64],
32 pub sym_roots_lbls: &'a [&'a str],
34 pub sym_roots_num: usize,
36 pub full_turn_steps: i8,
38 pub scaling_fac: MyInt,
40 pub ccw_unit_coeffs: &'a [[MyInt; 2]],
42}
43
44impl ZZParams<'static> {
45 pub fn ccw_unit<T: PrimInt + Integer + IntRing>(&self) -> Vec<GaussInt<Ratio<T>>> {
47 let sc = T::from(self.scaling_fac).unwrap();
48 self.ccw_unit_coeffs
49 .into_iter()
50 .map(|x| {
51 GaussInt::new(
52 Ratio::<T>::new_raw(T::from(x[0]).unwrap(), sc),
53 Ratio::<T>::new_raw(T::from(x[1]).unwrap(), sc),
54 )
55 })
56 .collect()
57 }
58}
59
60pub trait ZScalar:
64 IntField + InnerIntType + FromPrimitive + ZSigned + Conj + Debug + Display
65{
66}
67impl<T: IntField + InnerIntType + FromPrimitive + ZSigned + Conj + Debug + Display> ZScalar for T {}
68
69pub trait ZZBase {
71 type Scalar: ZScalar;
72 type Real: ZNum;
73
74 #[inline]
76 fn turn() -> i8 {
77 Self::zz_params().full_turn_steps
78 }
79
80 #[inline]
82 fn hturn() -> i8 {
83 Self::turn() / 2
84 }
85
86 #[inline]
91 fn has_qturn() -> bool {
92 Self::turn() % 4 == 0
93 }
94
95 #[inline]
98 fn qturn() -> i8 {
99 Self::turn() / 4
100 }
101
102 #[inline]
104 fn opt_qturn() -> Option<i8> {
105 if Self::has_qturn() {
106 Some(Self::qturn())
107 } else {
108 None
109 }
110 }
111
112 fn unit(angle: i8) -> Self
114 where
115 Self: ZZNum,
116 {
117 Self::one() * Self::pow(&Self::ccw(), angle.rem_euclid(Self::turn()))
118 }
119
120 fn pow(&self, i: i8) -> Self
123 where
124 Self: ZCommon,
125 {
126 assert!(i >= 0, "Negative powers are not supported!");
127 let mut x = Self::one();
128 for _ in 0..i {
129 x = x * (*self);
130 }
131 return x;
132 }
133
134 #[inline]
136 fn scale<I: Integer + ToPrimitive>(&self, scalar: I) -> Self
137 where
138 Self: Sized,
139 {
140 let cs: Vec<Self::Scalar> = Self::zz_mul_scalar(self.zz_coeffs(), scalar.to_i64().unwrap());
141 Self::new(&cs)
142 }
143
144 fn complex64(&self) -> Complex64;
146
147 fn new(coeffs: &[Self::Scalar]) -> Self;
150
151 fn zz_coeffs(&self) -> &[Self::Scalar];
152 fn zz_coeffs_mut(&mut self) -> &mut [Self::Scalar];
153
154 fn zz_params() -> &'static ZZParams<'static>;
155 fn zz_mul_arrays(x: &[Self::Scalar], y: &[Self::Scalar]) -> Vec<Self::Scalar>;
156 fn zz_mul_scalar(arr: &[Self::Scalar], scalar: i64) -> Vec<Self::Scalar>;
157
158 #[inline]
161 fn zz_zero_vec() -> Vec<Self::Scalar> {
162 vec![Self::Scalar::zero(); Self::zz_params().sym_roots_num]
163 }
164
165 fn zz_one_vec() -> Vec<Self::Scalar> {
166 let mut ret = vec![Self::Scalar::zero(); Self::zz_params().sym_roots_num];
167 ret[0] = Self::Scalar::one();
168 ret
169 }
170
171 fn zz_add(&self, other: &Self) -> Vec<Self::Scalar> {
172 let mut ret = Self::zz_zero_vec();
173 for (i, (aval, bval)) in self.zz_coeffs().iter().zip(other.zz_coeffs()).enumerate() {
174 ret[i] = *aval + *bval;
175 }
176 ret
177 }
178
179 fn zz_sub(&self, other: &Self) -> Vec<Self::Scalar> {
180 let mut ret = Self::zz_zero_vec();
181 for (i, (aval, bval)) in self.zz_coeffs().iter().zip(other.zz_coeffs()).enumerate() {
182 ret[i] = *aval - *bval;
183 }
184 ret
185 }
186
187 fn zz_neg(&self) -> Vec<Self::Scalar> {
188 let mut ret = Self::zz_zero_vec();
189 for (i, val) in self.zz_coeffs().iter().enumerate() {
190 ret[i] = -(*val);
191 }
192 ret
193 }
194
195 #[inline]
196 fn zz_mul(&self, other: &Self) -> Vec<Self::Scalar> {
197 Self::zz_mul_arrays(self.zz_coeffs(), other.zz_coeffs())
198 }
199}
200
201pub trait ZZComplex {
202 fn is_real(&self) -> bool;
204
205 fn is_imag(&self) -> bool;
207
208 fn is_complex(&self) -> bool {
210 !self.is_real() && !self.is_imag()
211 }
212
213 fn re(&self) -> <Self as ZZBase>::Real
216 where
217 Self: ZZBase;
218
219 fn im(&self) -> <Self as ZZBase>::Real
222 where
223 Self: ZZBase;
224
225 fn re_im(&self) -> (<Self as ZZBase>::Real, <Self as ZZBase>::Real)
230 where
231 Self: ZZBase,
232 {
233 (self.re(), self.im())
234 }
235}
236
237pub trait ZCommon: ZZBase + InnerIntType + IntRing + Conj + Display {}
239
240pub trait ZNum: ZCommon + ZSigned {}
243
244pub trait ZZNum: ZCommon + ZZComplex + Ccw {}
246
247#[macro_export]
250macro_rules! zz_triv_impl {
251 ($trait_name: ident, $($t:ty)*) => ($(
252 impl $trait_name for $t {}
253 )*)
254}
255
256#[macro_export]
257macro_rules! zz_base_impl {
258 ($name:ident, $name_real:ident, $params:ident, $mul_func:ident, $re_signum_func:ident) => {
259 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
260 pub struct $name_real {
261 coeffs: [Frac; $params.sym_roots_num],
262 }
263 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
264 pub struct $name {
265 coeffs: [GInt; $params.sym_roots_num],
266 }
267
268 impl ZZBase for $name_real {
269 type Scalar = Frac;
270 type Real = $name_real;
271
272 #[inline]
273 fn zz_coeffs(&self) -> &[Self::Scalar] {
274 &self.coeffs
275 }
276
277 #[inline]
278 fn zz_coeffs_mut(&mut self) -> &mut [Self::Scalar] {
279 &mut self.coeffs
280 }
281
282 #[inline]
283 fn zz_params() -> &'static ZZParams<'static> {
284 &$params
285 }
286
287 #[inline]
288 fn zz_mul_arrays(x: &[Self::Scalar], y: &[Self::Scalar]) -> Vec<Self::Scalar> {
289 $mul_func(x, y)
290 }
291
292 #[inline]
293 fn zz_mul_scalar(x: &[Self::Scalar], scalar: i64) -> Vec<Self::Scalar> {
294 let sc: Self::Scalar = Self::Scalar::from(scalar);
295 x.into_iter().map(|c| *c * sc).collect()
296 }
297
298 fn new(coeffs: &[Self::Scalar]) -> Self {
299 let mut ret = Self {
300 coeffs: [Self::Scalar::zero(); $params.sym_roots_num],
301 };
302 ret.coeffs.clone_from_slice(coeffs);
303 ret
304 }
305
306 fn complex64(&self) -> Complex64 {
307 let nums: Vec<Complex64> = self
308 .zz_coeffs()
309 .into_iter()
310 .map(|x| {
311 let re = x.to_f64().unwrap();
312 Complex64::new(re, 0.0)
313 })
314 .collect();
315 let units: Vec<Complex64> = Self::zz_params()
316 .sym_roots_sqs
317 .into_iter()
318 .map(|x| Complex64::new(x.sqrt(), 0.0))
319 .collect();
320 let mut ret = Complex64::zero();
321 for (n, u) in nums.iter().zip(units.iter()) {
322 ret += n * u;
323 }
324 ret
325 }
326 }
327 impl ZZBase for $name {
328 type Scalar = GaussInt<Frac>;
329 type Real = $name_real;
330
331 #[inline]
332 fn zz_coeffs(&self) -> &[Self::Scalar] {
333 &self.coeffs
334 }
335
336 #[inline]
337 fn zz_coeffs_mut(&mut self) -> &mut [Self::Scalar] {
338 &mut self.coeffs
339 }
340
341 #[inline]
342 fn zz_params() -> &'static ZZParams<'static> {
343 &$params
344 }
345
346 #[inline]
347 fn zz_mul_arrays(x: &[Self::Scalar], y: &[Self::Scalar]) -> Vec<Self::Scalar> {
348 $mul_func(x, y)
349 }
350
351 #[inline]
352 fn zz_mul_scalar(x: &[Self::Scalar], scalar: i64) -> Vec<Self::Scalar> {
353 let sc: Self::Scalar = Self::Scalar::from(scalar);
354 x.into_iter().map(|c| *c * sc).collect()
355 }
356
357 fn new(coeffs: &[Self::Scalar]) -> Self {
358 let mut ret = Self {
359 coeffs: [Self::Scalar::zero(); $params.sym_roots_num],
360 };
361 ret.coeffs.clone_from_slice(coeffs);
362 ret
363 }
364
365 fn complex64(&self) -> Complex64 {
366 let nums: Vec<Complex64> = self
367 .zz_coeffs()
368 .into_iter()
369 .map(|x| {
370 let re = x.real.to_f64().unwrap();
371 let im = x.imag.to_f64().unwrap();
372 Complex64::new(re, im)
373 })
374 .collect();
375 let units: Vec<Complex64> = Self::zz_params()
376 .sym_roots_sqs
377 .into_iter()
378 .map(|x| Complex64::new(x.sqrt(), 0.0))
379 .collect();
380 let mut ret = Complex64::zero();
381 for (n, u) in nums.iter().zip(units.iter()) {
382 ret += n * u;
383 }
384 ret
385 }
386 }
387
388 impl From<$name_real> for $name {
389 fn from(value: $name_real) -> Self {
391 let cs: Vec<<$name as ZZBase>::Scalar> =
392 value.zz_coeffs().iter().map(|z| (*z).into()).collect();
393 Self::new(cs.as_slice())
394 }
395 }
396
397 impl Conj for $name_real {
398 fn conj(&self) -> Self {
399 self.clone()
400 }
401 fn co_conj(&self) -> Self {
402 self.neg()
403 }
404 }
405 impl Conj for $name {
406 fn conj(&self) -> Self {
407 let cs: Vec<GInt> = self.zz_coeffs().iter().map(|c| c.conj()).collect();
408 Self::new(&cs)
409 }
410 fn co_conj(&self) -> Self {
411 let cs: Vec<GInt> = self.zz_coeffs().iter().map(|c| c.co_conj()).collect();
412 Self::new(&cs)
413 }
414 }
415
416 impl ZSigned for $name_real {
417 fn signum(&self) -> Self {
418 $re_signum_func(self)
419 }
420 }
421
422 impl ZNum for $name_real {}
423
424 impl ZZComplex for $name {
425 fn is_real(&self) -> bool {
426 self.zz_coeffs().iter().all(|c| c.imag.is_zero())
427 }
428
429 fn is_imag(&self) -> bool {
430 self.zz_coeffs().iter().all(|c| c.real.is_zero())
431 }
432
433 fn re(&self) -> <Self as ZZBase>::Real {
434 let cs: Vec<Frac> = self.zz_coeffs().iter().map(|c| c.real).collect();
435 $name_real::new(cs.as_slice())
436 }
437
438 fn im(&self) -> <Self as ZZBase>::Real {
439 let cs: Vec<Frac> = self.zz_coeffs().iter().map(|c| c.imag).collect();
440 $name_real::new(cs.as_slice())
441 }
442 }
443
444 impl Ccw for $name {
445 fn ccw() -> Self {
446 Self::new(Self::zz_params().ccw_unit().as_slice())
447 }
448 fn is_ccw(&self) -> bool {
449 *self == Self::ccw()
450 }
451 }
452 impl ZZNum for $name {}
453 };
454}
455
456#[macro_export]
457macro_rules! zz_ops_impl {
458 ($($t:ty)*) => ($(
459 impl Add<$t> for $t {
460 type Output = Self;
461 fn add(self, other: Self) -> Self {
462 Self::new(&Self::zz_add(&self, &other))
463 }
464 }
465 impl Sub<$t> for $t {
466 type Output = Self;
467 fn sub(self, other: Self) -> Self {
468 Self::new(&Self::zz_sub(&self, &other))
469 }
470 }
471 impl Neg for $t {
472 type Output = Self;
473 fn neg(self) -> Self {
474 Self::new(&Self::zz_neg(&self))
475 }
476 }
477 impl Mul<$t> for $t {
478 type Output = Self;
479 fn mul(self, other: Self) -> Self {
480 Self::new(&Self::zz_mul(&self, &other))
481 }
482 }
483
484 impl Zero for $t {
485 fn zero() -> Self {
486 Self::new(&Self::zz_zero_vec())
487 }
488 fn is_zero(&self) -> bool {
489 self.coeffs.to_vec() == Self::zz_zero_vec()
490 }
491 }
492 impl One for $t {
493 fn one() -> Self {
494 Self::new(&Self::zz_one_vec())
495 }
496 fn is_one(&self) -> bool {
497 self.coeffs.to_vec() == Self::zz_one_vec()
498 }
499 }
500
501 impl Display for $t {
502 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503 let nums: Vec<String> = self.coeffs.into_iter().map(|x| format!("{x}")).collect();
504 let units: Vec<String> = <$t>::zz_params().sym_roots_lbls.into_iter().map(|x| format!("sqrt({x})")).collect();
505 let parts: Vec<String> = nums.iter().zip(units.iter()).filter(|(x, _)| x != &"0").map(|(x, y)| {
506 let is_real_unit = y == "sqrt(1)";
507 if (x == "1") {
508 if (is_real_unit) { "1".to_string() } else { y.to_string() }
509 } else if (is_real_unit) {
510 format!("{x}")
511 } else {
512 format!("({x})*{y}")
513 }
514 }).collect();
515 let joined = parts.join(" + ");
516 let result = if (joined.is_empty()){ "0".to_string() } else { joined };
517 return write!(f, "{result}");
518 }
519 }
520
521 impl InnerIntType for $t {
522 type IntType = <<Self as ZZBase>::Scalar as InnerIntType>::IntType;
523 }
524
525 impl From<<$t as InnerIntType>::IntType> for $t {
526 fn from(value: <<Self as ZZBase>::Scalar as InnerIntType>::IntType) -> Self {
527 Self::one().scale(value)
528 }
529 }
530
531 impl IntRing for $t {}
532 impl ZCommon for $t {}
533 )*)
534}