malachite_float/arithmetic/
neg.rs

1// Copyright © 2025 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::Float;
10use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
11use crate::float_nan;
12use core::ops::Neg;
13use malachite_base::num::arithmetic::traits::NegAssign;
14use malachite_base::num::logic::traits::NotAssign;
15
16impl Neg for Float {
17    type Output = Self;
18
19    /// Negates a [`Float`], taking it by value.
20    ///
21    /// $$
22    /// f(x) = -x.
23    /// $$
24    ///
25    /// Special cases:
26    /// - $f(\text{NaN}) = \text{NaN}$
27    /// - $f(\infty) = -\infty$
28    /// - $f(-\infty) = \infty$
29    /// - $f(0.0) = -0.0$
30    /// - $f(-0.0) = 0.0$
31    ///
32    /// This function does not overflow or underflow.
33    ///
34    /// # Worst-case complexity
35    /// Constant time and additional memory.
36    ///
37    /// # Examples
38    /// ```
39    /// use malachite_base::num::basic::traits::{
40    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
41    /// };
42    /// use malachite_float::{ComparableFloat, Float};
43    ///
44    /// assert_eq!(ComparableFloat(-Float::NAN), ComparableFloat(Float::NAN));
45    /// assert_eq!(-Float::INFINITY, Float::NEGATIVE_INFINITY);
46    /// assert_eq!(-Float::NEGATIVE_INFINITY, Float::INFINITY);
47    /// assert_eq!(
48    ///     ComparableFloat(-Float::ZERO),
49    ///     ComparableFloat(Float::NEGATIVE_ZERO)
50    /// );
51    /// assert_eq!(
52    ///     ComparableFloat(-Float::NEGATIVE_ZERO),
53    ///     ComparableFloat(Float::ZERO)
54    /// );
55    /// assert_eq!(-Float::ONE, Float::NEGATIVE_ONE);
56    /// assert_eq!(-Float::NEGATIVE_ONE, Float::ONE);
57    /// ```
58    #[inline]
59    fn neg(mut self) -> Self {
60        self.neg_assign();
61        self
62    }
63}
64
65impl Neg for &Float {
66    type Output = Float;
67
68    /// Negates a [`Float`], taking it by reference.
69    ///
70    /// $$
71    /// f(x) = -x.
72    /// $$
73    ///
74    /// Special cases:
75    /// - $f(\text{NaN}) = \text{NaN}$
76    /// - $f(\infty) = -\infty$
77    /// - $f(-\infty) = \infty$
78    /// - $f(0.0) = -0.0$
79    /// - $f(-0.0) = 0.0$
80    ///
81    /// This function does not overflow or underflow.
82    ///
83    /// # Worst-case complexity
84    /// $T(n) = O(n)$
85    ///
86    /// $M(n) = O(n)$
87    ///
88    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
89    ///
90    /// # Examples
91    /// ```
92    /// use malachite_base::num::basic::traits::{
93    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
94    /// };
95    /// use malachite_float::{ComparableFloat, Float};
96    ///
97    /// assert_eq!(ComparableFloat(-&Float::NAN), ComparableFloat(Float::NAN));
98    /// assert_eq!(-&Float::INFINITY, Float::NEGATIVE_INFINITY);
99    /// assert_eq!(-&Float::NEGATIVE_INFINITY, Float::INFINITY);
100    /// assert_eq!(
101    ///     ComparableFloat(-&Float::ZERO),
102    ///     ComparableFloat(Float::NEGATIVE_ZERO)
103    /// );
104    /// assert_eq!(
105    ///     ComparableFloat(-&Float::NEGATIVE_ZERO),
106    ///     ComparableFloat(Float::ZERO)
107    /// );
108    /// assert_eq!(-&Float::ONE, Float::NEGATIVE_ONE);
109    /// assert_eq!(-&Float::NEGATIVE_ONE, Float::ONE);
110    /// ```
111    fn neg(self) -> Float {
112        match self {
113            float_nan!() => float_nan!(),
114            Float(Infinity { sign }) => Float(Infinity { sign: !*sign }),
115            Float(Zero { sign }) => Float(Zero { sign: !*sign }),
116            Float(Finite {
117                sign,
118                exponent,
119                precision,
120                significand,
121            }) => Float(Finite {
122                sign: !*sign,
123                exponent: *exponent,
124                precision: *precision,
125                significand: significand.clone(),
126            }),
127        }
128    }
129}
130
131impl NegAssign for Float {
132    /// Negates a [`Float`] in place.
133    ///
134    /// $$
135    /// x \gets -x.
136    /// $$
137    ///
138    /// Special cases:
139    /// - $\text{NaN} \gets \text{NaN}$
140    /// - $\infty \gets -\infty$
141    /// - $-\infty \gets \infty$
142    /// - $0.0 \gets -0.0$
143    /// - $-0.0 \gets 0.0$
144    ///
145    /// This function does not overflow or underflow.
146    ///
147    /// # Worst-case complexity
148    /// Constant time and additional memory.
149    ///
150    /// # Examples
151    /// ```
152    /// use malachite_base::num::arithmetic::traits::NegAssign;
153    /// use malachite_base::num::basic::traits::{
154    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
155    /// };
156    /// use malachite_float::{ComparableFloat, Float};
157    ///
158    /// let mut x = Float::NAN;
159    /// x.neg_assign();
160    /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::NAN));
161    ///
162    /// let mut x = Float::INFINITY;
163    /// x.neg_assign();
164    /// assert_eq!(x, Float::NEGATIVE_INFINITY);
165    ///
166    /// let mut x = Float::NEGATIVE_INFINITY;
167    /// x.neg_assign();
168    /// assert_eq!(x, Float::INFINITY);
169    ///
170    /// let mut x = Float::ZERO;
171    /// x.neg_assign();
172    /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::NEGATIVE_ZERO));
173    ///
174    /// let mut x = Float::NEGATIVE_ZERO;
175    /// x.neg_assign();
176    /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::ZERO));
177    ///
178    /// let mut x = Float::ONE;
179    /// x.neg_assign();
180    /// assert_eq!(x, Float::NEGATIVE_ONE);
181    ///
182    /// let mut x = Float::NEGATIVE_ONE;
183    /// x.neg_assign();
184    /// assert_eq!(x, Float::ONE);
185    /// ```
186    fn neg_assign(&mut self) {
187        if let Self(Infinity { sign } | Zero { sign } | Finite { sign, .. }) = self {
188            sign.not_assign();
189        }
190    }
191}