malachite_nz/gaussian_integer/arithmetic/mul_i_pow.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::gaussian_integer::GaussianInteger;
10use malachite_base::num::arithmetic::traits::{
11 DivIAssign, ModPowerOf2, MulIAssign, MulIPow, MulIPowAssign, NegAssign,
12};
13
14impl MulIPow for GaussianInteger {
15 type Output = Self;
16
17 /// Multiplies a [`GaussianInteger`] by $i^k$, taking the [`GaussianInteger`] by value.
18 ///
19 /// Only $k$ modulo 4 matters: $i^0 = 1$, $i^1 = i$, $i^2 = -1$, and $i^3 = -i$, so the result
20 /// is the number itself, a counterclockwise quarter turn, a half turn, or a clockwise quarter
21 /// turn. Since $i^{-k} = i^{3k}$, a negative power is a matter of tripling the exponent.
22 ///
23 /// $$
24 /// f(x, k) = i^k x.
25 /// $$
26 ///
27 /// # Worst-case complexity
28 /// Constant time and additional memory.
29 ///
30 /// # Examples
31 /// ```
32 /// use malachite_base::num::arithmetic::traits::MulIPow;
33 /// use malachite_nz::gaussian_integer::GaussianInteger;
34 /// use std::str::FromStr;
35 ///
36 /// let x = GaussianInteger::from_str("2+3i").unwrap();
37 /// assert_eq!(x.clone().mul_i_pow(0).to_string(), "2+3i");
38 /// assert_eq!(x.clone().mul_i_pow(1).to_string(), "-3+2i");
39 /// assert_eq!(x.clone().mul_i_pow(2).to_string(), "-2-3i");
40 /// assert_eq!(x.clone().mul_i_pow(3).to_string(), "3-2i");
41 /// assert_eq!(x.mul_i_pow(1000000000001).to_string(), "-3+2i");
42 /// ```
43 #[inline]
44 fn mul_i_pow(mut self, k: u64) -> Self {
45 self.mul_i_pow_assign(k);
46 self
47 }
48}
49
50impl MulIPow for &GaussianInteger {
51 type Output = GaussianInteger;
52
53 /// Multiplies a [`GaussianInteger`] by $i^k$, taking the [`GaussianInteger`] by reference.
54 ///
55 /// Only $k$ modulo 4 matters: $i^0 = 1$, $i^1 = i$, $i^2 = -1$, and $i^3 = -i$, so the result
56 /// is the number itself, a counterclockwise quarter turn, a half turn, or a clockwise quarter
57 /// turn. Since $i^{-k} = i^{3k}$, a negative power is a matter of tripling the exponent.
58 ///
59 /// $$
60 /// f(x, k) = i^k x.
61 /// $$
62 ///
63 /// # Worst-case complexity
64 /// $T(n) = O(n)$
65 ///
66 /// $M(n) = O(n)$
67 ///
68 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
69 ///
70 /// # Examples
71 /// ```
72 /// use malachite_base::num::arithmetic::traits::MulIPow;
73 /// use malachite_nz::gaussian_integer::GaussianInteger;
74 /// use std::str::FromStr;
75 ///
76 /// let x = GaussianInteger::from_str("2+3i").unwrap();
77 /// assert_eq!((&x).mul_i_pow(0).to_string(), "2+3i");
78 /// assert_eq!((&x).mul_i_pow(1).to_string(), "-3+2i");
79 /// assert_eq!((&x).mul_i_pow(2).to_string(), "-2-3i");
80 /// assert_eq!((&x).mul_i_pow(3).to_string(), "3-2i");
81 /// assert_eq!((&x).mul_i_pow(1000000000001).to_string(), "-3+2i");
82 /// ```
83 #[inline]
84 fn mul_i_pow(self, k: u64) -> GaussianInteger {
85 self.clone().mul_i_pow(k)
86 }
87}
88
89impl MulIPowAssign for GaussianInteger {
90 /// Multiplies a [`GaussianInteger`] by $i^k$ in place.
91 ///
92 /// Only $k$ modulo 4 matters: $i^0 = 1$, $i^1 = i$, $i^2 = -1$, and $i^3 = -i$, so the result
93 /// is the number itself, a counterclockwise quarter turn, a half turn, or a clockwise quarter
94 /// turn. Since $i^{-k} = i^{3k}$, a negative power is a matter of tripling the exponent.
95 ///
96 /// $$
97 /// x \gets i^k x.
98 /// $$
99 ///
100 /// # Worst-case complexity
101 /// Constant time and additional memory.
102 ///
103 /// # Examples
104 /// ```
105 /// use malachite_base::num::arithmetic::traits::MulIPowAssign;
106 /// use malachite_nz::gaussian_integer::GaussianInteger;
107 /// use std::str::FromStr;
108 ///
109 /// let mut x = GaussianInteger::from_str("2+3i").unwrap();
110 /// x.mul_i_pow_assign(1);
111 /// assert_eq!(x.to_string(), "-3+2i");
112 /// x.mul_i_pow_assign(2);
113 /// assert_eq!(x.to_string(), "3-2i");
114 /// x.mul_i_pow_assign(1000000000001);
115 /// assert_eq!(x.to_string(), "2+3i");
116 /// ```
117 fn mul_i_pow_assign(&mut self, k: u64) {
118 match k.mod_power_of_2(2) {
119 0 => {}
120 1 => self.mul_i_assign(),
121 2 => self.neg_assign(),
122 _ => self.div_i_assign(),
123 }
124 }
125}