1#![allow(deprecated)]
18
19use crate::complex::{BorrowComplex, MiniComplex};
20use crate::float::{MiniFloat, Special, ToSmall};
21use crate::{Assign, Complex};
22use core::fmt::{Debug, Formatter, Result as FmtResult};
23use core::marker::PhantomData;
24use core::mem;
25use core::ops::Deref;
26use gmp_mpfr_sys::gmp::limb_t;
27
28const ZERO_MINI: MiniComplex = MiniComplex::new();
29const ZERO_BORROW: BorrowComplex = ZERO_MINI.borrow();
30const ZERO: &Complex = BorrowComplex::const_deref(&ZERO_BORROW);
31
32#[deprecated(since = "1.23.0", note = "use `MiniComplex` instead")]
61#[derive(Clone)]
62pub struct SmallComplex {
63 inner: Option<Complex>,
64 phantom: PhantomData<*const limb_t>,
66}
67
68unsafe impl Send for SmallComplex {}
69
70impl Default for SmallComplex {
71 #[inline]
72 fn default() -> Self {
73 SmallComplex::new()
74 }
75}
76
77impl Debug for SmallComplex {
78 #[inline]
79 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
80 match &self.inner {
81 Some(c) => Debug::fmt(c, f),
82 None => Debug::fmt(ZERO, f),
83 }
84 }
85}
86
87impl SmallComplex {
88 #[inline]
102 pub const fn new() -> Self {
103 SmallComplex {
104 inner: None,
105 phantom: PhantomData,
106 }
107 }
108
109 #[inline]
132 pub unsafe fn as_nonreallocating_complex(&mut self) -> &mut Complex {
133 if self.inner.is_none() {
134 *self = SmallComplex {
135 inner: Some(Complex::new(ZERO.prec())),
136 phantom: PhantomData,
137 };
138 }
139 match &mut self.inner {
140 Some(c) => c,
141 None => unreachable!(),
142 }
143 }
144}
145
146impl Deref for SmallComplex {
147 type Target = Complex;
148 #[inline]
149 fn deref(&self) -> &Complex {
150 match &self.inner {
151 Some(c) => c,
152 None => ZERO,
153 }
154 }
155}
156
157impl<Re: ToSmall> Assign<Re> for SmallComplex {
158 fn assign(&mut self, src: Re) {
159 let mut mini = MiniFloat::from(src);
160 let src = mini.borrow_excl();
161 unsafe {
162 let dst = self.as_nonreallocating_complex();
163 dst.mut_real().set_prec(src.prec());
164 dst.mut_real().assign(src);
165 dst.mut_imag().set_prec(src.prec());
166 dst.mut_imag().assign(Special::Zero);
167 }
168 }
169}
170
171impl<Re: ToSmall> From<Re> for SmallComplex {
172 fn from(src: Re) -> Self {
173 let mut mini = MiniFloat::from(src);
174 let src = mini.borrow_excl();
175 SmallComplex {
176 inner: Some(Complex::with_val(src.prec(), src)),
177 phantom: PhantomData,
178 }
179 }
180}
181
182impl<Re: ToSmall, Im: ToSmall> Assign<(Re, Im)> for SmallComplex {
183 fn assign(&mut self, src: (Re, Im)) {
184 let mut re = MiniFloat::from(src.0);
185 let mut im = MiniFloat::from(src.1);
186 let re = re.borrow_excl();
187 let im = im.borrow_excl();
188 unsafe {
189 let dst = self.as_nonreallocating_complex();
190 dst.mut_real().set_prec(re.prec());
191 dst.mut_real().assign(re);
192 dst.mut_imag().set_prec(im.prec());
193 dst.mut_imag().assign(im);
194 }
195 }
196}
197
198impl<Re: ToSmall, Im: ToSmall> From<(Re, Im)> for SmallComplex {
199 fn from(src: (Re, Im)) -> Self {
200 let mut re = MiniFloat::from(src.0);
201 let mut im = MiniFloat::from(src.1);
202 let re = re.borrow_excl();
203 let im = im.borrow_excl();
204 SmallComplex {
205 inner: Some(Complex::with_val((re.prec(), im.prec()), (re, im))),
206 phantom: PhantomData,
207 }
208 }
209}
210
211impl Assign<&Self> for SmallComplex {
212 #[inline]
213 fn assign(&mut self, other: &Self) {
214 self.clone_from(other);
215 }
216}
217
218impl Assign for SmallComplex {
219 #[inline]
220 fn assign(&mut self, other: Self) {
221 drop(mem::replace(self, other));
222 }
223}
224
225#[cfg(test)]
226mod tests {
227 use crate::Assign;
228 use crate::complex::SmallComplex;
229 use crate::float;
230 use crate::float::FreeCache;
231
232 #[test]
233 fn check_assign() {
234 let mut c = SmallComplex::from((1.0, 2.0));
235 assert_eq!(*c, (1.0, 2.0));
236 c.assign(3.0);
237 assert_eq!(*c, (3.0, 0.0));
238 let other = SmallComplex::from((4.0, 5.0));
239 c.assign(&other);
240 assert_eq!(*c, (4.0, 5.0));
241 c.assign((6.0, 7.0));
242 assert_eq!(*c, (6.0, 7.0));
243 c.assign(other);
244 assert_eq!(*c, (4.0, 5.0));
245
246 float::free_cache(FreeCache::All);
247 }
248
249 fn swapped_parts(small: &SmallComplex) -> bool {
250 unsafe {
251 let re = (*small.real().as_raw()).d;
252 let im = (*small.imag().as_raw()).d;
253 re > im
254 }
255 }
256
257 #[test]
258 fn check_swapped_parts() {
259 let mut c = SmallComplex::from((1, 2));
260 assert_eq!(*c, (1, 2));
261 assert_eq!(*c.clone(), *c);
262 let mut orig_swapped_parts = swapped_parts(&c);
263 unsafe {
264 c.as_nonreallocating_complex().mul_i_mut(false);
265 }
266 assert_eq!(*c, (-2, 1));
267 assert_eq!(*c.clone(), *c);
268 assert!(swapped_parts(&c) != orig_swapped_parts);
269
270 c.assign(12);
271 assert_eq!(*c, 12);
272 assert_eq!(*c.clone(), *c);
273 orig_swapped_parts = swapped_parts(&c);
274 unsafe {
275 c.as_nonreallocating_complex().mul_i_mut(false);
276 }
277 assert_eq!(*c, (0, 12));
278 assert_eq!(*c.clone(), *c);
279 assert!(swapped_parts(&c) != orig_swapped_parts);
280
281 c.assign((4, 5));
282 assert_eq!(*c, (4, 5));
283 assert_eq!(*c.clone(), *c);
284 orig_swapped_parts = swapped_parts(&c);
285 unsafe {
286 c.as_nonreallocating_complex().mul_i_mut(false);
287 }
288 assert_eq!(*c, (-5, 4));
289 assert_eq!(*c.clone(), *c);
290 assert!(swapped_parts(&c) != orig_swapped_parts);
291 }
292}