boostvoronoi_ext/extended_exp_fpt.rs
1// Boost.Polygon library detail/voronoi_structures.hpp header file
2
3// Copyright Andrii Sydorchuk 2010-2012.
4// Distributed under the Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7
8// See http://www.boost.org for updates, documentation, and revision history of C++ code..
9
10// Ported from C++ boost 1.76.0 to Rust in 2020/2021 by Eadf (github.com/eadf)
11
12//! Utilities for extended float. Supports 63 bit mantissa with 32 bit exponent.
13use crate::extended_int as EI;
14use num_traits::Float as OutputType;
15use std::fmt;
16use std::ops;
17
18/// Floating point type wrapper. Allows to extend exponent boundaries to the
19/// integer type range. This class does not handle division by zero, subnormal
20/// numbers or NaNs.
21/// Ported from the class extended_exponent_fpt in voronoi_ctypes.hpp
22#[derive(Copy, Clone)]
23pub struct ExtendedExponentFpt<F: OutputType> {
24 val_: F,
25 exp_: i32,
26}
27
28const MAX_SIGNIFICANT_EXP_DIF_F64: i32 = 54;
29
30impl From<&EI::ExtendedInt> for ExtendedExponentFpt<f64> {
31 #[inline]
32 /// Converts to ExtendedExponentFpt::<f64> from &ExtendedInt
33 /// ```
34 /// # use boostvoronoi_ext::extended_int::ExtendedInt;
35 /// # use boostvoronoi_ext::extended_exp_fpt::ExtendedExponentFpt;
36 ///
37 /// let aa = 41232131332_f64;
38 /// let a = ExtendedInt::from(aa as i64);
39 /// let e = ExtendedExponentFpt::from(&a);
40 /// approx::assert_ulps_eq!(e.d(), aa);
41 /// ```
42 fn from(that: &EI::ExtendedInt) -> Self {
43 let p = that.p();
44 Self::new(p.0, p.1)
45 }
46}
47
48impl From<EI::ExtendedInt> for ExtendedExponentFpt<f64> {
49 #[inline]
50 /// Converts to `ExtendedExponentFpt::<f64>` from `ExtendedInt`
51 /// ```
52 /// # use boostvoronoi_ext::extended_int::ExtendedInt;
53 /// # use boostvoronoi_ext::extended_exp_fpt::ExtendedExponentFpt;
54 ///
55 /// let aa = 41232131332_f64;
56 /// let a = ExtendedInt::from(aa as i64);
57 /// let e = ExtendedExponentFpt::from(a);
58 /// approx::assert_ulps_eq!(e.d(), aa);
59 /// ```
60 fn from(that: EI::ExtendedInt) -> Self {
61 let p = that.p();
62 Self::new(p.0, p.1)
63 }
64}
65
66impl From<ExtendedExponentFpt<f64>> for f64 {
67 #[inline]
68 /// Converts from `ExtendedExponentFpt<f64>` to `f64`
69 /// ```
70 /// # use boostvoronoi_ext::extended_exp_fpt::ExtendedExponentFpt;
71 ///
72 /// let f1 = 345345345453_f64;
73 /// let e = ExtendedExponentFpt::from(f1);
74 /// let f2 = f64::from(e);
75 /// approx::assert_ulps_eq!(f1, f2);
76 /// ```
77 fn from(that: ExtendedExponentFpt<f64>) -> f64 {
78 that.d()
79 }
80}
81
82impl From<f64> for ExtendedExponentFpt<f64> {
83 #[inline]
84 /// Converts from `f64` to `ExtendedExponentFpt<f64>`
85 /// ```
86 /// # use boostvoronoi_ext::extended_exp_fpt::ExtendedExponentFpt;
87 ///
88 /// let f1 = 345345345453_f64;
89 /// let e = ExtendedExponentFpt::from(f1);
90 /// let f2 = f64::from(e);
91 /// approx::assert_ulps_eq!(f1, f2);
92 /// ```
93 fn from(that: f64) -> ExtendedExponentFpt<f64> {
94 let rv = libm::frexp(that);
95 Self::new(rv.0, rv.1)
96 }
97}
98
99#[allow(dead_code)]
100impl ExtendedExponentFpt<f64> {
101 #[inline]
102 /// Constructor with value and exponent as arguments.
103 /// The value of this number is 'val_' * 2^ 'exp_'
104 /// ```
105 /// # use boostvoronoi_ext::extended_exp_fpt::ExtendedExponentFpt;
106 ///
107 /// let a = ExtendedExponentFpt::<f64>::new(1.0, 12);
108 /// approx::assert_ulps_eq!(a.d(), 4096.0);
109 /// ```
110 pub fn new(val: f64, exp: i32) -> Self {
111 let fr = libm::frexp(val);
112 Self {
113 val_: fr.0,
114 exp_: exp + fr.1,
115 }
116 }
117
118 /// Is positive method.
119 /// IMPORTANT!!!!! in the c++ boost voronoi implementation zero values can't be positive.
120 /// ```
121 /// # use boostvoronoi_ext::extended_exp_fpt::ExtendedExponentFpt;
122 ///
123 /// let aa:f64 = 0_f64;
124 /// let a = ExtendedExponentFpt::<f64>::from(aa);
125 /// assert_eq!(a.is_pos(), false);
126 ///
127 /// let aa:f64 = -0_f64;
128 /// let a = ExtendedExponentFpt::<f64>::from(aa);
129 /// assert_eq!(a.is_pos(), false);
130 ///
131 /// let aa:f64 = f64::MIN_POSITIVE;
132 /// let a = ExtendedExponentFpt::<f64>::from(aa);
133 /// assert_eq!(a.is_pos(), aa.is_sign_positive());
134 /// ```
135 #[inline]
136 pub fn is_pos(&self) -> bool {
137 self.val_ > 0.0
138 }
139
140 /// Is negative method.
141 /// IMPORTANT!!!!! in the c++ boost voronoi implementation zero values can't be negative.
142 /// ```
143 /// # use boostvoronoi_ext::extended_exp_fpt;
144 ///
145 /// let aa:f64 = 0_f64;
146 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(aa);
147 /// assert_eq!(a.is_neg(), aa.is_sign_negative());
148 ///
149 /// let aa:f64 = -0_f64;
150 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(aa);
151 /// assert_eq!(a.is_neg(), false);
152 /// ```
153 #[inline]
154 pub fn is_neg(&self) -> bool {
155 self.val_ < 0.0
156 }
157
158 /// Is zero method.
159 /// ```
160 /// # use boostvoronoi_ext::extended_exp_fpt;
161 /// # use num_traits::identities::Zero;
162 ///
163 /// let aa:f64 = 0_f64;
164 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(aa);
165 /// assert_eq!(a.is_zero(), aa.is_zero());
166 ///
167 /// let aa:f64 = -0_f64;
168 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(aa);
169 /// assert_eq!(a.is_zero(), aa.is_zero());
170 ///
171 /// let aa:f64 = f64::MIN_POSITIVE;
172 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(aa);
173 /// assert_eq!(a.is_zero(), aa.is_zero());
174 ///
175 /// let aa:f64 = -f64::MIN_POSITIVE;
176 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(aa);
177 /// assert_eq!(a.is_zero(), aa.is_zero());
178 /// ```
179 #[inline]
180 pub fn is_zero(&self) -> bool {
181 self.val_ == 0.0
182 }
183
184 /// Square root method.
185 /// ```
186 /// # use boostvoronoi_ext::extended_exp_fpt;
187 ///
188 /// let aa:f64 = f64::MAX;
189 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(aa);
190 /// approx::assert_ulps_eq!(a.d(), aa);
191 /// let a = a.sqrt();
192 /// approx::assert_ulps_eq!(a.d(), aa.sqrt());
193 /// ```
194 #[inline]
195 pub fn sqrt(&self) -> Self {
196 let mut val = self.val_;
197 let mut exp = self.exp_;
198 if (exp & 1) != 0 {
199 val *= 2.0;
200 exp -= 1;
201 }
202
203 Self::new(val.sqrt(), exp >> 1)
204 }
205
206 /// A to-float operation.
207 /// ```
208 /// # use boostvoronoi_ext::extended_exp_fpt;
209 ///
210 /// let aa:f64 = 1000000000.0;
211 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(aa);
212 /// approx::assert_ulps_eq!(a.d(), aa);
213 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(-aa);
214 /// approx::assert_ulps_eq!(a.d(), -aa);
215 /// ```
216 pub fn d(&self) -> f64 {
217 libm::ldexp(self.val_, self.exp_)
218 }
219
220 pub fn val(&self) -> f64 {
221 self.val_
222 }
223
224 pub fn exp(&self) -> i32 {
225 self.exp_
226 }
227}
228
229impl ops::Neg for ExtendedExponentFpt<f64> {
230 type Output = Self;
231
232 /// ```
233 /// # use boostvoronoi_ext::extended_exp_fpt;
234 ///
235 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1_f64);
236 ///
237 /// approx::assert_ulps_eq!(a.d(), 1_f64);
238 /// let c = -a;
239 /// approx::assert_ulps_eq!(c.d(), -1_f64);
240 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1000000000_f64);
241 /// approx::assert_ulps_eq!(a.d(), 1000000000_f64);
242 /// let c = -a;
243 /// approx::assert_ulps_eq!(c.d(), -1000000000_f64);
244 /// ```
245 fn neg(self) -> Self {
246 Self {
247 val_: -self.val_,
248 exp_: self.exp_,
249 }
250 }
251}
252
253impl ops::Add for ExtendedExponentFpt<f64> {
254 type Output = Self;
255
256 /// ```
257 /// # use boostvoronoi_ext::extended_exp_fpt;
258 ///
259 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1_f64);
260 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2_f64);
261 ///
262 /// approx::assert_ulps_eq!(a.d(), 1_f64);
263 /// approx::assert_ulps_eq!(b.d(), 2_f64);
264 /// let c = a + b;
265 /// approx::assert_ulps_eq!(c.d(), 3_f64);
266 /// let c = c + b;
267 /// approx::assert_ulps_eq!(c.d(), 5_f64);
268 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1000000000_f64);
269 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2000000000_f64);
270 /// approx::assert_ulps_eq!(a.d(), 1000000000_f64);
271 /// approx::assert_ulps_eq!(b.d(), 2000000000_f64);
272 /// let c = a + b;
273 /// approx::assert_ulps_eq!(c.d(), 3000000000_f64);
274 /// ```
275 fn add(self, that: Self) -> Self {
276 if self.val_ == 0.0 || that.exp_ > self.exp_ + MAX_SIGNIFICANT_EXP_DIF_F64 {
277 return that;
278 }
279 if that.val_ == 0.0 || self.exp_ > that.exp_ + MAX_SIGNIFICANT_EXP_DIF_F64 {
280 return self;
281 }
282 if self.exp_ >= that.exp_ {
283 let exp_dif = self.exp_ - that.exp_;
284 let val = libm::ldexp(self.val_, exp_dif) + that.val_;
285 Self::new(val, that.exp_)
286 } else {
287 let exp_dif = that.exp_ - self.exp_;
288 let val = libm::ldexp(that.val_, exp_dif) + self.val_;
289 Self::new(val, self.exp_)
290 }
291 }
292}
293
294impl ops::Sub for ExtendedExponentFpt<f64> {
295 type Output = Self;
296 /// ```
297 /// # use boostvoronoi_ext::extended_exp_fpt;
298 ///
299 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1_f64);
300 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(-2_f64);
301 ///
302 /// approx::assert_ulps_eq!(a.d(), 1_f64);
303 /// approx::assert_ulps_eq!(b.d(), -2_f64);
304 /// let c = a - b;
305 /// approx::assert_ulps_eq!(c.d(), 3_f64);
306 /// let c = c - b;
307 /// approx::assert_ulps_eq!(c.d(), 5_f64);
308 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1000000000_f64);
309 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(-3000000000_f64);
310 /// approx::assert_ulps_eq!(a.d(), 1000000000_f64);
311 /// approx::assert_ulps_eq!(b.d(), -3000000000_f64);
312 /// let c = a - b;
313 /// approx::assert_ulps_eq!(c.d(), 1000000000_f64-(-3000000000.0));
314 /// ```
315 fn sub(self, that: Self) -> Self {
316 if self.val_ == 0.0 || that.exp_ > self.exp_ + MAX_SIGNIFICANT_EXP_DIF_F64 {
317 return Self::new(-that.val_, that.exp_);
318 }
319 if that.val_ == 0.0 || self.exp_ > that.exp_ + MAX_SIGNIFICANT_EXP_DIF_F64 {
320 return self;
321 }
322 if self.exp_ >= that.exp_ {
323 let exp_dif = self.exp_ - that.exp_;
324 let val = libm::ldexp(self.val_, exp_dif) - that.val_;
325 Self::new(val, that.exp_)
326 } else {
327 let exp_dif = that.exp_ - self.exp_;
328 let val = libm::ldexp(-that.val_, exp_dif) + self.val_;
329 Self::new(val, self.exp_)
330 }
331 }
332}
333
334impl ops::Mul for ExtendedExponentFpt<f64> {
335 type Output = Self;
336 /// ```
337 /// # use boostvoronoi_ext::extended_exp_fpt;
338 ///
339 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1_f64);
340 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2_f64);
341 ///
342 /// approx::assert_ulps_eq!(a.d(), 1_f64);
343 /// approx::assert_ulps_eq!(b.d(), 2_f64);
344 /// let c = a * b;
345 /// approx::assert_ulps_eq!(c.d(), 2_f64);
346 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1000000000_f64);
347 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2000000000_f64);
348 /// approx::assert_ulps_eq!(a.d(), 1000000000_f64);
349 /// approx::assert_ulps_eq!(b.d(), 2000000000_f64);
350 /// let c = a * b;
351 /// approx::assert_ulps_eq!(c.d(), 1000000000_f64*2000000000_f64);
352 /// ```
353 fn mul(self, that: Self) -> Self {
354 let val = self.val_ * that.val_;
355 let exp = self.exp_ + that.exp_;
356 Self::new(val, exp)
357 }
358}
359
360impl ops::Mul<f64> for ExtendedExponentFpt<f64> {
361 type Output = Self;
362 /// ```
363 /// # use boostvoronoi_ext::extended_exp_fpt;
364 ///
365 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(7_f64);
366 /// let b = 2_f64;
367 ///
368 /// approx::assert_ulps_eq!(a.d(), 7_f64);
369 /// approx::assert_ulps_eq!(b, 2_f64);
370 /// let c = a * b;
371 /// approx::assert_ulps_eq!(c.d(), 7_f64*2_f64);
372 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1234567890_f64);
373 /// let b = 2000000000_f64;
374 /// approx::assert_ulps_eq!(a.d(), 1234567890_f64);
375 /// approx::assert_ulps_eq!(b, 2000000000_f64);
376 /// let c = a * b;
377 /// approx::assert_ulps_eq!(c.d(), 1234567890_f64*2000000000_f64);
378 /// ```
379 fn mul(self, that: f64) -> Self {
380 let that = Self::from(that);
381 self * that
382 }
383}
384
385impl ops::Div for ExtendedExponentFpt<f64> {
386 type Output = Self;
387 /// ```
388 /// # use boostvoronoi_ext::extended_exp_fpt;
389 ///
390 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1_f64);
391 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2_f64);
392 ///
393 /// approx::assert_ulps_eq!(a.d(), 1_f64);
394 /// approx::assert_ulps_eq!(b.d(), 2_f64);
395 /// let c = a / b;
396 /// approx::assert_ulps_eq!(c.d(), 1.0/2.0);
397 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2000000000_f64);
398 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(-2000000000_f64);
399 /// approx::assert_ulps_eq!(a.d(), 2000000000_f64);
400 /// approx::assert_ulps_eq!(b.d(), -2000000000_f64);
401 /// let c = a / b;
402 /// approx::assert_ulps_eq!(c.d(), -1f64);
403 /// ```
404 fn div(self, that: Self) -> Self {
405 let val = self.val_ / that.val_;
406 let exp = self.exp_ - that.exp_;
407 Self::new(val, exp)
408 }
409}
410
411impl ops::Div<f64> for ExtendedExponentFpt<f64> {
412 type Output = Self;
413 /// ```
414 /// # use boostvoronoi_ext::extended_exp_fpt;
415 ///
416 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1_f64);
417 /// let b = 2_f64;
418 ///
419 /// approx::assert_ulps_eq!(a.d(), 1_f64);
420 /// let c = a / b;
421 /// approx::assert_ulps_eq!(c.d(), 1.0/2.0);
422 /// let a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2000000000_f64);
423 /// let b = -2000000000_f64;
424 /// approx::assert_ulps_eq!(a.d(), 2000000000_f64);
425 /// let c = a / b;
426 /// approx::assert_ulps_eq!(c.d(), -1f64);
427 /// ```
428 fn div(self, that: f64) -> Self {
429 let that = Self::from(that);
430 let val = self.val_ / that.val_;
431 let exp = self.exp_ - that.exp_;
432 Self::new(val, exp)
433 }
434}
435
436impl ops::AddAssign for ExtendedExponentFpt<f64> {
437 /// ```
438 /// # use boostvoronoi_ext::extended_exp_fpt;
439 ///
440 /// let mut a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1_f64);
441 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2_f64);
442 ///
443 /// approx::assert_ulps_eq!(a.d(), 1_f64);
444 /// approx::assert_ulps_eq!(b.d(), 2_f64);
445 /// a += b;
446 /// approx::assert_ulps_eq!(a.d(), 3_f64);
447 /// a += b;
448 /// approx::assert_ulps_eq!(a.d(), 5_f64);
449 /// let mut a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1000000000_f64);
450 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2000000000_f64);
451 /// approx::assert_ulps_eq!(a.d(), 1000000000_f64);
452 /// approx::assert_ulps_eq!(b.d(), 2000000000_f64);
453 /// a += b;
454 /// approx::assert_ulps_eq!(a.d(), 3000000000_f64);
455 /// ```
456 fn add_assign(&mut self, that: Self) {
457 if self.val_ == 0.0 || that.exp_ > self.exp_ + MAX_SIGNIFICANT_EXP_DIF_F64 {
458 self.val_ = that.val_;
459 self.exp_ = that.exp_;
460 }
461 if that.val_ == 0.0 || self.exp_ > that.exp_ + MAX_SIGNIFICANT_EXP_DIF_F64 {
462 // do nothing
463 return;
464 }
465 if self.exp_ >= that.exp_ {
466 let exp_dif = self.exp_ - that.exp_;
467 let val = libm::ldexp(self.val_, exp_dif) + that.val_;
468 self.val_ = val;
469 self.exp_ = that.exp_;
470 } else {
471 let exp_dif = that.exp_ - self.exp_;
472 let val = libm::ldexp(that.val_, exp_dif) + self.val_;
473 self.val_ = val;
474 //self.exp_ = self.exp;
475 }
476 }
477}
478
479impl ops::SubAssign for ExtendedExponentFpt<f64> {
480 /// ```
481 /// # use boostvoronoi_ext::extended_exp_fpt;
482 ///
483 /// let mut a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1_f64);
484 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(-2_f64);
485 ///
486 /// approx::assert_ulps_eq!(a.d(), 1_f64);
487 /// approx::assert_ulps_eq!(b.d(), -2_f64);
488 /// a -= b;
489 /// approx::assert_ulps_eq!(a.d(), 3_f64);
490 /// a -= b;
491 /// approx::assert_ulps_eq!(a.d(), 5_f64);
492 /// let mut a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1000000000_f64);
493 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(-3000000000_f64);
494 /// approx::assert_ulps_eq!(a.d(), 1000000000_f64);
495 /// approx::assert_ulps_eq!(b.d(), -3000000000_f64);
496 /// a -= b;
497 /// approx::assert_ulps_eq!(a.d(), 1000000000_f64-(-3000000000.0));
498 /// ```
499 fn sub_assign(&mut self, that: Self) {
500 if self.val_ == 0.0 || that.exp_ > self.exp_ + MAX_SIGNIFICANT_EXP_DIF_F64 {
501 self.val_ = -that.val_;
502 self.exp_ = that.exp_;
503 }
504 if that.val_ == 0.0 || self.exp_ > that.exp_ + MAX_SIGNIFICANT_EXP_DIF_F64 {
505 return;
506 }
507 if self.exp_ >= that.exp_ {
508 let exp_dif = self.exp_ - that.exp_;
509 let val = libm::ldexp(self.val_, exp_dif) - that.val_;
510 self.val_ = val;
511 self.exp_ = that.exp_;
512 } else {
513 let exp_dif = that.exp_ - self.exp_;
514 let val = libm::ldexp(-that.val_, exp_dif) + self.val_;
515 self.val_ = val;
516 //self.exp_ = self.exp_;
517 }
518 }
519}
520
521impl ops::MulAssign for ExtendedExponentFpt<f64> {
522 /// ```
523 /// # use boostvoronoi_ext::extended_exp_fpt;
524 ///
525 /// let mut a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1_f64);
526 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2_f64);
527 ///
528 /// approx::assert_ulps_eq!(a.d(), 1_f64);
529 /// approx::assert_ulps_eq!(b.d(), 2_f64);
530 /// a *= b;
531 /// approx::assert_ulps_eq!(a.d(), 2_f64);
532 /// let mut a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1000000000_f64);
533 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2000000000_f64);
534 /// approx::assert_ulps_eq!(a.d(), 1000000000_f64);
535 /// approx::assert_ulps_eq!(b.d(), 2000000000_f64);
536 /// a *= b;
537 /// approx::assert_ulps_eq!(a.d(), 1000000000_f64*2000000000_f64);
538 /// ```
539 fn mul_assign(&mut self, that: Self) {
540 self.val_ *= that.val_;
541 self.exp_ += that.exp_;
542 }
543}
544
545impl ops::DivAssign for ExtendedExponentFpt<f64> {
546 /// ```
547 /// # use boostvoronoi_ext::extended_exp_fpt;
548 ///
549 /// let mut a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(1_f64);
550 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2_f64);
551 ///
552 /// approx::assert_ulps_eq!(a.d(), 1_f64);
553 /// approx::assert_ulps_eq!(b.d(), 2_f64);
554 /// a /= b;
555 /// approx::assert_ulps_eq!(a.d(), 1.0/2.0);
556 /// let mut a = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(2000000000_f64);
557 /// let b = extended_exp_fpt::ExtendedExponentFpt::<f64>::from(-2000000000_f64);
558 /// approx::assert_ulps_eq!(a.d(), 2000000000_f64);
559 /// approx::assert_ulps_eq!(b.d(), -2000000000_f64);
560 /// a /= b;
561 /// approx::assert_ulps_eq!(a.d(), -1f64);
562 /// ```
563 fn div_assign(&mut self, that: Self) {
564 self.val_ /= that.val_;
565 self.exp_ -= that.exp_;
566 }
567}
568
569impl fmt::Debug for ExtendedExponentFpt<f64> {
570 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
571 write!(f, "{}^{}", self.val_, self.exp_)
572 }
573}