malachite_nz/gaussian_integer/arithmetic/abs_squared.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 crate::integer::Integer;
11use malachite_base::num::arithmetic::traits::{AbsSquared, AbsSquaredAssign, Square, SquareAssign};
12
13impl AbsSquared for GaussianInteger {
14 type Output = Integer;
15
16 /// Computes the squared absolute value of a [`GaussianInteger`], taking it by value. This is
17 /// the sum of the squares of the real and imaginary parts, also known as the norm. It is always
18 /// a non-negative [`Integer`].
19 ///
20 /// $$
21 /// f(x) = |x|^2 = \Re(x)^2 + \Im(x)^2.
22 /// $$
23 ///
24 /// # Worst-case complexity
25 /// $T(n) = O(n \log n \log\log n)$
26 ///
27 /// $M(n) = O(n \log n)$
28 ///
29 /// where $T$ is time, $M$ is additional memory, and $n$ is the maximum number of significant
30 /// bits of the real and imaginary parts.
31 ///
32 /// # Examples
33 /// ```
34 /// use malachite_base::num::arithmetic::traits::AbsSquared;
35 /// use malachite_base::num::basic::traits::{I, Zero};
36 /// use malachite_nz::gaussian_integer::GaussianInteger;
37 /// use std::str::FromStr;
38 ///
39 /// assert_eq!(GaussianInteger::ZERO.abs_squared(), 0);
40 /// assert_eq!(GaussianInteger::I.abs_squared(), 1);
41 /// assert_eq!(GaussianInteger::from_str("2-3i").unwrap().abs_squared(), 13);
42 /// assert_eq!(GaussianInteger::from(-123).abs_squared(), 15129);
43 /// ```
44 #[inline]
45 fn abs_squared(self) -> Integer {
46 self.real.square() + self.imaginary.square()
47 }
48}
49
50impl AbsSquared for &GaussianInteger {
51 type Output = Integer;
52
53 /// Computes the squared absolute value of a [`GaussianInteger`], taking it by reference. This
54 /// is the sum of the squares of the real and imaginary parts, also known as the norm. It is
55 /// always a non-negative [`Integer`].
56 ///
57 /// $$
58 /// f(x) = |x|^2 = \Re(x)^2 + \Im(x)^2.
59 /// $$
60 ///
61 /// # Worst-case complexity
62 /// $T(n) = O(n \log n \log\log n)$
63 ///
64 /// $M(n) = O(n \log n)$
65 ///
66 /// where $T$ is time, $M$ is additional memory, and $n$ is the maximum number of significant
67 /// bits of the real and imaginary parts.
68 ///
69 /// # Examples
70 /// ```
71 /// use malachite_base::num::arithmetic::traits::AbsSquared;
72 /// use malachite_base::num::basic::traits::{I, Zero};
73 /// use malachite_nz::gaussian_integer::GaussianInteger;
74 /// use std::str::FromStr;
75 ///
76 /// assert_eq!((&GaussianInteger::ZERO).abs_squared(), 0);
77 /// assert_eq!((&GaussianInteger::I).abs_squared(), 1);
78 /// let x = GaussianInteger::from_str("2-3i").unwrap();
79 /// assert_eq!((&x).abs_squared(), 13);
80 /// ```
81 #[inline]
82 fn abs_squared(self) -> Integer {
83 (&self.real).square() + (&self.imaginary).square()
84 }
85}
86
87impl AbsSquaredAssign for GaussianInteger {
88 /// Replaces a [`GaussianInteger`] with its squared absolute value: the purely real value
89 /// $|x|^2$, embedded in the same type. The real part becomes the sum of the squares of the real
90 /// and imaginary parts (the norm), and the imaginary part becomes zero.
91 ///
92 /// $$
93 /// x \gets |x|^2 = \Re(x)^2 + \Im(x)^2.
94 /// $$
95 ///
96 /// # Worst-case complexity
97 /// $T(n) = O(n \log n \log\log n)$
98 ///
99 /// $M(n) = O(n \log n)$
100 ///
101 /// where $T$ is time, $M$ is additional memory, and $n$ is the maximum number of significant
102 /// bits of the real and imaginary parts.
103 ///
104 /// # Examples
105 /// ```
106 /// use malachite_base::num::arithmetic::traits::AbsSquaredAssign;
107 /// use malachite_nz::gaussian_integer::GaussianInteger;
108 /// use std::str::FromStr;
109 ///
110 /// let mut x = GaussianInteger::from_str("2-3i").unwrap();
111 /// x.abs_squared_assign();
112 /// assert_eq!(x.to_string(), "13");
113 /// ```
114 fn abs_squared_assign(&mut self) {
115 self.real.square_assign();
116 self.imaginary.square_assign();
117 self.real += core::mem::take(&mut self.imaginary);
118 }
119}