malachite_float/arithmetic/mul.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::InnerFloat::{Finite, Infinity, NaN, Zero};
10use crate::{
11 Float, float_either_infinity, float_either_zero, float_infinity, float_nan,
12 float_negative_infinity, float_negative_zero, float_zero,
13};
14use core::cmp::{
15 Ordering::{self, *},
16 max,
17};
18use core::mem::swap;
19use core::ops::{Mul, MulAssign};
20use malachite_base::num::arithmetic::traits::{CheckedLogBase2, IsPowerOf2, NegAssign, Sign};
21use malachite_base::num::basic::traits::Zero as ZeroTrait;
22use malachite_base::num::conversion::traits::ExactFrom;
23use malachite_base::num::logic::traits::{NotAssign, SignificantBits};
24use malachite_base::rounding_modes::RoundingMode::{self, *};
25use malachite_nz::natural::arithmetic::float_mul::{
26 mul_float_significands_in_place, mul_float_significands_in_place_ref,
27 mul_float_significands_ref_ref,
28};
29use malachite_q::Rational;
30
31const MUL_RATIONAL_THRESHOLD: u64 = 50;
32
33fn mul_rational_prec_round_assign_naive(
34 x: &mut Float,
35 y: Rational,
36 prec: u64,
37 rm: RoundingMode,
38) -> Ordering {
39 assert_ne!(prec, 0);
40 match (&mut *x, y) {
41 (float_nan!(), _) => Equal,
42 (Float(Infinity { sign }), y) => {
43 match y.sign() {
44 Equal => *x = float_nan!(),
45 Greater => {}
46 Less => {
47 sign.not_assign();
48 }
49 };
50 Equal
51 }
52 (Float(Zero { sign }), y) => {
53 if y < 0 {
54 sign.not_assign();
55 };
56 Equal
57 }
58 (x, y) => {
59 let not_sign = *x < 0;
60 let mut z = Float::ZERO;
61 swap(x, &mut z);
62 let (mut product, o) =
63 Float::from_rational_prec_round(Rational::exact_from(z) * y, prec, rm);
64 if product == 0u32 && not_sign {
65 product.neg_assign();
66 }
67 *x = product;
68 o
69 }
70 }
71}
72
73fn mul_rational_prec_round_assign_naive_ref(
74 x: &mut Float,
75 y: &Rational,
76 prec: u64,
77 rm: RoundingMode,
78) -> Ordering {
79 assert_ne!(prec, 0);
80 match (&mut *x, y) {
81 (float_nan!(), _) => Equal,
82 (Float(Infinity { sign }), y) => {
83 match y.sign() {
84 Equal => *x = float_nan!(),
85 Greater => {}
86 Less => {
87 sign.not_assign();
88 }
89 };
90 Equal
91 }
92 (Float(Zero { sign }), y) => {
93 if *y < 0 {
94 sign.not_assign();
95 };
96 Equal
97 }
98 (x, y) => {
99 let not_sign = *x < 0;
100 let mut z = Float::ZERO;
101 swap(x, &mut z);
102 let (mut product, o) =
103 Float::from_rational_prec_round(Rational::exact_from(z) * y, prec, rm);
104 if product == 0u32 && not_sign {
105 product.neg_assign();
106 }
107 *x = product;
108 o
109 }
110 }
111}
112
113pub_test! {mul_rational_prec_round_naive(
114 mut x: Float,
115 y: Rational,
116 prec: u64,
117 rm: RoundingMode,
118) -> (Float, Ordering) {
119 let o = mul_rational_prec_round_assign_naive(&mut x, y, prec, rm);
120 (x, o)
121}}
122
123pub_test! {mul_rational_prec_round_naive_val_ref(
124 mut x: Float,
125 y: &Rational,
126 prec: u64,
127 rm: RoundingMode,
128) -> (Float, Ordering) {
129 let o = mul_rational_prec_round_assign_naive_ref(&mut x, y, prec, rm);
130 (x, o)
131}}
132
133pub_test! {mul_rational_prec_round_naive_ref_val(
134 x: &Float,
135 y: Rational,
136 prec: u64,
137 rm: RoundingMode,
138) -> (Float, Ordering) {
139 assert_ne!(prec, 0);
140 match (x, y) {
141 (float_nan!(), _) => (float_nan!(), Equal),
142 (Float(Infinity { sign }), y) => (
143 match y.sign() {
144 Equal => float_nan!(),
145 Greater => Float(Infinity { sign: *sign }),
146 Less => Float(Infinity { sign: !*sign }),
147 },
148 Equal,
149 ),
150 (Float(Zero { sign }), y) => (
151 if y >= 0u32 {
152 Float(Zero { sign: *sign })
153 } else {
154 Float(Zero { sign: !*sign })
155 },
156 Equal,
157 ),
158 (x, y) => {
159 let (mut product, o) =
160 Float::from_rational_prec_round(Rational::exact_from(x) * y, prec, rm);
161 if product == 0u32 && *x < 0 {
162 product.neg_assign();
163 }
164 (product, o)
165 }
166 }
167}}
168
169pub_test! {mul_rational_prec_round_naive_ref_ref(
170 x: &Float,
171 y: &Rational,
172 prec: u64,
173 rm: RoundingMode,
174) -> (Float, Ordering) {
175 assert_ne!(prec, 0);
176 match (x, y) {
177 (float_nan!(), _) => (float_nan!(), Equal),
178 (Float(Infinity { sign }), y) => (
179 match y.sign() {
180 Equal => float_nan!(),
181 Greater => Float(Infinity { sign: *sign }),
182 Less => Float(Infinity { sign: !*sign }),
183 },
184 Equal,
185 ),
186 (Float(Zero { sign }), y) => (
187 if *y >= 0u32 {
188 Float(Zero { sign: *sign })
189 } else {
190 Float(Zero { sign: !*sign })
191 },
192 Equal,
193 ),
194 (x, y) => {
195 let (mut product, o) =
196 Float::from_rational_prec_round(Rational::exact_from(x) * y, prec, rm);
197 if product == 0u32 && *x < 0 {
198 product.neg_assign();
199 }
200 (product, o)
201 }
202 }
203}}
204
205fn mul_rational_prec_round_assign_direct(
206 x: &mut Float,
207 y: Rational,
208 prec: u64,
209 mut rm: RoundingMode,
210) -> Ordering {
211 assert_ne!(prec, 0);
212 let sign = y >= 0;
213 let (n, d) = y.into_numerator_and_denominator();
214 if !sign {
215 rm.neg_assign();
216 }
217 let o = match (
218 if n == 0 { None } else { n.checked_log_base_2() },
219 d.checked_log_base_2(),
220 ) {
221 (Some(log_n), Some(log_d)) => {
222 let o = x.set_prec_round(prec, rm);
223 *x <<= log_n;
224 *x >>= log_d;
225 o
226 }
227 (None, Some(log_d)) => {
228 let o = x.mul_prec_round_assign(Float::exact_from(n), prec, rm);
229 *x >>= log_d;
230 o
231 }
232 (Some(log_n), None) => {
233 let o = x.div_prec_round_assign(Float::exact_from(d), prec, rm);
234 *x <<= log_n;
235 o
236 }
237 (None, None) => {
238 let n = Float::exact_from(n);
239 let d = Float::exact_from(d);
240 let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits();
241 x.mul_prec_round_assign(n, mul_prec, Floor);
242 x.div_prec_round_assign(d, prec, rm)
243 }
244 };
245 if sign {
246 o
247 } else {
248 x.neg_assign();
249 o.reverse()
250 }
251}
252
253fn mul_rational_prec_round_assign_direct_ref(
254 x: &mut Float,
255 y: &Rational,
256 prec: u64,
257 mut rm: RoundingMode,
258) -> Ordering {
259 assert_ne!(prec, 0);
260 let sign = *y >= 0;
261 let (n, d) = y.numerator_and_denominator_ref();
262 if !sign {
263 rm.neg_assign();
264 }
265 let o = match (
266 if *n == 0 {
267 None
268 } else {
269 n.checked_log_base_2()
270 },
271 d.checked_log_base_2(),
272 ) {
273 (Some(log_n), Some(log_d)) => {
274 let o = x.set_prec_round(prec, rm);
275 *x <<= log_n;
276 *x >>= log_d;
277 o
278 }
279 (None, Some(log_d)) => {
280 let o = x.mul_prec_round_assign(Float::exact_from(n), prec, rm);
281 *x >>= log_d;
282 o
283 }
284 (Some(log_n), None) => {
285 let o = x.div_prec_round_assign(Float::exact_from(d), prec, rm);
286 *x <<= log_n;
287 o
288 }
289 (None, None) => {
290 let n = Float::exact_from(n);
291 let d = Float::exact_from(d);
292 let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits();
293 x.mul_prec_round_assign(n, mul_prec, Floor);
294 x.div_prec_round_assign(d, prec, rm)
295 }
296 };
297 if sign {
298 o
299 } else {
300 x.neg_assign();
301 o.reverse()
302 }
303}
304
305pub_test! {mul_rational_prec_round_direct(
306 mut x: Float,
307 y: Rational,
308 prec: u64,
309 rm: RoundingMode,
310) -> (Float, Ordering) {
311 let o = mul_rational_prec_round_assign_direct(&mut x, y, prec, rm);
312 (x, o)
313}}
314
315pub_test! {mul_rational_prec_round_direct_val_ref(
316 mut x: Float,
317 y: &Rational,
318 prec: u64,
319 rm: RoundingMode,
320) -> (Float, Ordering) {
321 let o = mul_rational_prec_round_assign_direct_ref(&mut x, y, prec, rm);
322 (x, o)
323}}
324
325pub_test! {mul_rational_prec_round_direct_ref_val(
326 x: &Float,
327 y: Rational,
328 prec: u64,
329 mut rm: RoundingMode,
330) -> (Float, Ordering) {
331 assert_ne!(prec, 0);
332 let sign = y >= 0;
333 let (n, d) = y.into_numerator_and_denominator();
334 if !sign {
335 rm.neg_assign();
336 }
337 let (product, o) = match (
338 if n == 0 { None } else { n.checked_log_base_2() },
339 d.checked_log_base_2(),
340 ) {
341 (Some(log_n), Some(log_d)) => {
342 let (product, o) = Float::from_float_prec_round_ref(x, prec, rm);
343 (product << log_n >> log_d, o)
344 }
345 (None, Some(log_d)) => {
346 let (product, o) = x.mul_prec_round_ref_val(Float::exact_from(n), prec, rm);
347 (product >> log_d, o)
348 }
349 (Some(log_n), None) => {
350 let (product, o) = x.div_prec_round_ref_val(Float::exact_from(d), prec, rm);
351 (product << log_n, o)
352 }
353 (None, None) => {
354 let n = Float::exact_from(n);
355 let d = Float::exact_from(d);
356 let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits();
357 x.mul_prec_round_ref_val(n, mul_prec, Floor)
358 .0
359 .div_prec_round(d, prec, rm)
360 }
361 };
362 if sign {
363 (product, o)
364 } else {
365 (-product, o.reverse())
366 }
367}}
368
369pub_test! {mul_rational_prec_round_direct_ref_ref(
370 x: &Float,
371 y: &Rational,
372 prec: u64,
373 mut rm: RoundingMode,
374) -> (Float, Ordering) {
375 assert_ne!(prec, 0);
376 let sign = *y >= 0;
377 let (n, d) = y.numerator_and_denominator_ref();
378 if !sign {
379 rm.neg_assign();
380 }
381 let (product, o) = match (
382 if *n == 0 {
383 None
384 } else {
385 n.checked_log_base_2()
386 },
387 d.checked_log_base_2(),
388 ) {
389 (Some(log_n), Some(log_d)) => {
390 let (product, o) = Float::from_float_prec_round_ref(x, prec, rm);
391 (product << log_n >> log_d, o)
392 }
393 (None, Some(log_d)) => {
394 let (product, o) =
395 x.mul_prec_round_ref_val(Float::exact_from(n), prec, rm);
396 (product >> log_d, o)
397 }
398 (Some(log_n), None) => {
399 let (product, o) =
400 x.div_prec_round_ref_val(Float::exact_from(d), prec, rm);
401 (product << log_n, o)
402 }
403 (None, None) => {
404 let n = Float::exact_from(n);
405 let d = Float::exact_from(d);
406 let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits();
407 x.mul_prec_round_ref_val(n, mul_prec, Floor)
408 .0
409 .div_prec_round(d, prec, rm)
410 }
411 };
412 if sign {
413 (product, o)
414 } else {
415 (-product, o.reverse())
416 }
417}}
418
419impl Float {
420 /// Multiplies two [`Float`]s, rounding the result to the specified precision and with the
421 /// specified rounding mode. Both [`Float`]s are taken by value. An [`Ordering`] is also
422 /// returned, indicating whether the rounded product is less than, equal to, or greater than the
423 /// exact product. Although `NaN`s are not comparable to any [`Float`], whenever this function
424 /// returns a `NaN` it also returns `Equal`.
425 ///
426 /// See [`RoundingMode`] for a description of the possible rounding modes.
427 ///
428 /// $$
429 /// f(x,y,p,m) = xy+\varepsilon.
430 /// $$
431 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
432 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
433 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
434 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
435 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
436 ///
437 /// If the output has a precision, it is `prec`.
438 ///
439 /// Special cases:
440 /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm0.0,p,m)=f(\pm0.0,\pm\infty,p,m) =
441 /// \text{NaN}$
442 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x>0.0$
443 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=-\infty$ if $x<0.0$
444 /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x>0.0$
445 /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=\infty$ if $x<0.0$
446 /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or
447 /// $x>0.0$
448 /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or
449 /// $x<0.0$
450 /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or
451 /// $x>0.0$
452 /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or
453 /// $x<0.0$
454 ///
455 /// Overflow and underflow:
456 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
457 /// returned instead.
458 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
459 /// is returned instead, where `p` is the precision of the input.
460 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
461 /// returned instead.
462 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
463 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input.
464 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
465 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
466 /// instead.
467 /// - If $0<f(x,y,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
468 /// - If $2^{-2^{30}-1}<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
469 /// instead.
470 /// - If $-2^{-2^{30}}<f(x,y,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
471 /// instead.
472 /// - If $-2^{-2^{30}}<f(x,y,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
473 /// instead.
474 /// - If $-2^{-2^{30}-1}\leq f(x,y,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
475 /// - If $-2^{-2^{30}}<f(x,y,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
476 /// returned instead.
477 ///
478 /// If you know you'll be using `Nearest`, consider using [`Float::mul_prec`] instead. If you
479 /// know that your target precision is the maximum of the precisions of the two inputs, consider
480 /// using [`Float::mul_round`] instead. If both of these things are true, consider using `*`
481 /// instead.
482 ///
483 /// # Worst-case complexity
484 /// $T(n, m) = O(n \log n \log\log n + m)$
485 ///
486 /// $M(n, m) = O(n \log n + m)$
487 ///
488 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
489 /// other.significant_bits())`, and $m$ is `prec`.
490 ///
491 /// # Panics
492 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
493 ///
494 /// # Examples
495 /// ```
496 /// use core::f64::consts::{E, PI};
497 /// use malachite_base::rounding_modes::RoundingMode::*;
498 /// use malachite_float::Float;
499 /// use std::cmp::Ordering::*;
500 ///
501 /// let (product, o) = Float::from(PI).mul_prec_round(Float::from(E), 5, Floor);
502 /// assert_eq!(product.to_string(), "8.5");
503 /// assert_eq!(o, Less);
504 ///
505 /// let (product, o) = Float::from(PI).mul_prec_round(Float::from(E), 5, Ceiling);
506 /// assert_eq!(product.to_string(), "9.0");
507 /// assert_eq!(o, Greater);
508 ///
509 /// let (product, o) = Float::from(PI).mul_prec_round(Float::from(E), 5, Nearest);
510 /// assert_eq!(product.to_string(), "8.5");
511 /// assert_eq!(o, Less);
512 ///
513 /// let (product, o) = Float::from(PI).mul_prec_round(Float::from(E), 20, Floor);
514 /// assert_eq!(product.to_string(), "8.53973");
515 /// assert_eq!(o, Less);
516 ///
517 /// let (product, o) = Float::from(PI).mul_prec_round(Float::from(E), 20, Ceiling);
518 /// assert_eq!(product.to_string(), "8.53975");
519 /// assert_eq!(o, Greater);
520 ///
521 /// let (product, o) = Float::from(PI).mul_prec_round(Float::from(E), 20, Nearest);
522 /// assert_eq!(product.to_string(), "8.53973");
523 /// assert_eq!(o, Less);
524 /// ```
525 #[inline]
526 pub fn mul_prec_round(
527 mut self,
528 other: Float,
529 prec: u64,
530 rm: RoundingMode,
531 ) -> (Float, Ordering) {
532 let o = self.mul_prec_round_assign(other, prec, rm);
533 (self, o)
534 }
535
536 /// Multiplies two [`Float`]s, rounding the result to the specified precision and with the
537 /// specified rounding mode. The first [`Float`] is are taken by value and the second by
538 /// reference. An [`Ordering`] is also returned, indicating whether the rounded product is less
539 /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any
540 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
541 ///
542 /// See [`RoundingMode`] for a description of the possible rounding modes.
543 ///
544 /// $$
545 /// f(x,y,p,m) = xy+\varepsilon.
546 /// $$
547 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
548 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
549 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
550 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
551 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
552 ///
553 /// If the output has a precision, it is `prec`.
554 ///
555 /// Special cases:
556 /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm0.0,p,m)=f(\pm0.0,\pm\infty,p,m) =
557 /// \text{NaN}$
558 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x>0.0$
559 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=-\infty$ if $x<0.0$
560 /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x>0.0$
561 /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=\infty$ if $x<0.0$
562 /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or
563 /// $x>0.0$
564 /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or
565 /// $x<0.0$
566 /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or
567 /// $x>0.0$
568 /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or
569 /// $x<0.0$
570 ///
571 /// Overflow and underflow:
572 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
573 /// returned instead.
574 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
575 /// is returned instead, where `p` is the precision of the input.
576 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
577 /// returned instead.
578 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
579 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input.
580 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
581 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
582 /// instead.
583 /// - If $0<f(x,y,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
584 /// - If $2^{-2^{30}-1}<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
585 /// instead.
586 /// - If $-2^{-2^{30}}<f(x,y,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
587 /// instead.
588 /// - If $-2^{-2^{30}}<f(x,y,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
589 /// instead.
590 /// - If $-2^{-2^{30}-1}\leq f(x,y,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
591 /// - If $-2^{-2^{30}}<f(x,y,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
592 /// returned instead.
593 ///
594 /// If you know you'll be using `Nearest`, consider using [`Float::mul_prec_val_ref`] instead.
595 /// If you know that your target precision is the maximum of the precisions of the two inputs,
596 /// consider using [`Float::mul_round_val_ref`] instead. If both of these things are true,
597 /// consider using `*` instead.
598 ///
599 /// # Worst-case complexity
600 /// $T(n, m) = O(n \log n \log\log n + m)$
601 ///
602 /// $M(n, m) = O(n \log n + m)$
603 ///
604 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
605 /// other.significant_bits())`, and $m$ is `prec`.
606 ///
607 /// # Panics
608 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
609 ///
610 /// # Examples
611 /// ```
612 /// use core::f64::consts::{E, PI};
613 /// use malachite_base::rounding_modes::RoundingMode::*;
614 /// use malachite_float::Float;
615 /// use std::cmp::Ordering::*;
616 ///
617 /// let (product, o) = Float::from(PI).mul_prec_round_val_ref(&Float::from(E), 5, Floor);
618 /// assert_eq!(product.to_string(), "8.5");
619 /// assert_eq!(o, Less);
620 ///
621 /// let (product, o) = Float::from(PI).mul_prec_round_val_ref(&Float::from(E), 5, Ceiling);
622 /// assert_eq!(product.to_string(), "9.0");
623 /// assert_eq!(o, Greater);
624 ///
625 /// let (product, o) = Float::from(PI).mul_prec_round_val_ref(&Float::from(E), 5, Nearest);
626 /// assert_eq!(product.to_string(), "8.5");
627 /// assert_eq!(o, Less);
628 ///
629 /// let (product, o) = Float::from(PI).mul_prec_round_val_ref(&Float::from(E), 20, Floor);
630 /// assert_eq!(product.to_string(), "8.53973");
631 /// assert_eq!(o, Less);
632 ///
633 /// let (product, o) = Float::from(PI).mul_prec_round_val_ref(&Float::from(E), 20, Ceiling);
634 /// assert_eq!(product.to_string(), "8.53975");
635 /// assert_eq!(o, Greater);
636 ///
637 /// let (product, o) = Float::from(PI).mul_prec_round_val_ref(&Float::from(E), 20, Nearest);
638 /// assert_eq!(product.to_string(), "8.53973");
639 /// assert_eq!(o, Less);
640 /// ```
641 #[inline]
642 pub fn mul_prec_round_val_ref(
643 mut self,
644 other: &Float,
645 prec: u64,
646 rm: RoundingMode,
647 ) -> (Float, Ordering) {
648 let o = self.mul_prec_round_assign_ref(other, prec, rm);
649 (self, o)
650 }
651
652 /// Multiplies two [`Float`]s, rounding the result to the specified precision and with the
653 /// specified rounding mode. The first [`Float`] is are taken by reference and the second by
654 /// value. An [`Ordering`] is also returned, indicating whether the rounded product is less
655 /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any
656 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
657 ///
658 /// See [`RoundingMode`] for a description of the possible rounding modes.
659 ///
660 /// $$
661 /// f(x,y,p,m) = xy+\varepsilon.
662 /// $$
663 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
664 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
665 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
666 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
667 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
668 ///
669 /// If the output has a precision, it is `prec`.
670 ///
671 /// Special cases:
672 /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm0.0,p,m)=f(\pm0.0,\pm\infty,p,m) =
673 /// \text{NaN}$
674 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x>0.0$
675 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=-\infty$ if $x<0.0$
676 /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x>0.0$
677 /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=\infty$ if $x<0.0$
678 /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or
679 /// $x>0.0$
680 /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or
681 /// $x<0.0$
682 /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or
683 /// $x>0.0$
684 /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or
685 /// $x<0.0$
686 ///
687 /// Overflow and underflow:
688 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
689 /// returned instead.
690 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
691 /// is returned instead, where `p` is the precision of the input.
692 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
693 /// returned instead.
694 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
695 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input.
696 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
697 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
698 /// instead.
699 /// - If $0<f(x,y,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
700 /// - If $2^{-2^{30}-1}<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
701 /// instead.
702 /// - If $-2^{-2^{30}}<f(x,y,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
703 /// instead.
704 /// - If $-2^{-2^{30}}<f(x,y,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
705 /// instead.
706 /// - If $-2^{-2^{30}-1}\leq f(x,y,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
707 /// - If $-2^{-2^{30}}<f(x,y,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
708 /// returned instead.
709 ///
710 /// If you know you'll be using `Nearest`, consider using [`Float::mul_prec_ref_val`] instead.
711 /// If you know that your target precision is the maximum of the precisions of the two inputs,
712 /// consider using [`Float::mul_round_ref_val`] instead. If both of these things are true,
713 /// consider using `*` instead.
714 ///
715 /// # Worst-case complexity
716 /// $T(n, m) = O(n \log n \log\log n + m)$
717 ///
718 /// $M(n, m) = O(n \log n + m)$
719 ///
720 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
721 /// other.significant_bits())`, and $m$ is `prec`.
722 ///
723 /// # Panics
724 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
725 ///
726 /// # Examples
727 /// ```
728 /// use core::f64::consts::{E, PI};
729 /// use malachite_base::rounding_modes::RoundingMode::*;
730 /// use malachite_float::Float;
731 /// use std::cmp::Ordering::*;
732 ///
733 /// let (product, o) = Float::from(PI).mul_prec_round_ref_val(Float::from(E), 5, Floor);
734 /// assert_eq!(product.to_string(), "8.5");
735 /// assert_eq!(o, Less);
736 ///
737 /// let (product, o) = Float::from(PI).mul_prec_round_ref_val(Float::from(E), 5, Ceiling);
738 /// assert_eq!(product.to_string(), "9.0");
739 /// assert_eq!(o, Greater);
740 ///
741 /// let (product, o) = Float::from(PI).mul_prec_round_ref_val(Float::from(E), 5, Nearest);
742 /// assert_eq!(product.to_string(), "8.5");
743 /// assert_eq!(o, Less);
744 ///
745 /// let (product, o) = Float::from(PI).mul_prec_round_ref_val(Float::from(E), 20, Floor);
746 /// assert_eq!(product.to_string(), "8.53973");
747 /// assert_eq!(o, Less);
748 ///
749 /// let (product, o) = Float::from(PI).mul_prec_round_ref_val(Float::from(E), 20, Ceiling);
750 /// assert_eq!(product.to_string(), "8.53975");
751 /// assert_eq!(o, Greater);
752 ///
753 /// let (product, o) = Float::from(PI).mul_prec_round_ref_val(Float::from(E), 20, Nearest);
754 /// assert_eq!(product.to_string(), "8.53973");
755 /// assert_eq!(o, Less);
756 /// ```
757 #[inline]
758 pub fn mul_prec_round_ref_val(
759 &self,
760 mut other: Float,
761 prec: u64,
762 rm: RoundingMode,
763 ) -> (Float, Ordering) {
764 let o = other.mul_prec_round_assign_ref(self, prec, rm);
765 (other, o)
766 }
767
768 /// Multiplies two [`Float`]s, rounding the result to the specified precision and with the
769 /// specified rounding mode. Both [`Float`]s are taken by reference. An [`Ordering`] is also
770 /// returned, indicating whether the rounded product is less than, equal to, or greater than the
771 /// exact product. Although `NaN`s are not comparable to any [`Float`], whenever this function
772 /// returns a `NaN` it also returns `Equal`.
773 ///
774 /// See [`RoundingMode`] for a description of the possible rounding modes.
775 ///
776 /// $$
777 /// f(x,y,p,m) = xy+\varepsilon.
778 /// $$
779 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
780 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
781 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
782 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
783 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
784 ///
785 /// If the output has a precision, it is `prec`.
786 ///
787 /// Special cases:
788 /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm0.0,p,m)=f(\pm0.0,\pm\infty,p,m) =
789 /// \text{NaN}$
790 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x>0.0$
791 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=-\infty$ if $x<0.0$
792 /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x>0.0$
793 /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=\infty$ if $x<0.0$
794 /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or
795 /// $x>0.0$
796 /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or
797 /// $x<0.0$
798 /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or
799 /// $x>0.0$
800 /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or
801 /// $x<0.0$
802 ///
803 /// Overflow and underflow:
804 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
805 /// returned instead.
806 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
807 /// is returned instead, where `p` is the precision of the input.
808 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
809 /// returned instead.
810 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
811 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input.
812 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
813 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
814 /// instead.
815 /// - If $0<f(x,y,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
816 /// - If $2^{-2^{30}-1}<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
817 /// instead.
818 /// - If $-2^{-2^{30}}<f(x,y,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
819 /// instead.
820 /// - If $-2^{-2^{30}}<f(x,y,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
821 /// instead.
822 /// - If $-2^{-2^{30}-1}\leq f(x,y,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
823 /// - If $-2^{-2^{30}}<f(x,y,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
824 /// returned instead.
825 ///
826 /// If you know you'll be using `Nearest`, consider using [`Float::mul_prec_ref_ref`] instead.
827 /// If you know that your target precision is the maximum of the precisions of the two inputs,
828 /// consider using [`Float::mul_round_ref_ref`] instead. If both of these things are true,
829 /// consider using `*` instead.
830 ///
831 /// # Worst-case complexity
832 /// $T(n, m) = O(n \log n \log\log n + m)$
833 ///
834 /// $M(n, m) = O(n \log n + m)$
835 ///
836 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
837 /// other.significant_bits())`, and $m$ is `prec`.
838 ///
839 /// # Panics
840 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
841 ///
842 /// # Examples
843 /// ```
844 /// use core::f64::consts::{E, PI};
845 /// use malachite_base::rounding_modes::RoundingMode::*;
846 /// use malachite_float::Float;
847 /// use std::cmp::Ordering::*;
848 ///
849 /// let (product, o) = Float::from(PI).mul_prec_round_ref_ref(&Float::from(E), 5, Floor);
850 /// assert_eq!(product.to_string(), "8.5");
851 /// assert_eq!(o, Less);
852 ///
853 /// let (product, o) = Float::from(PI).mul_prec_round_ref_ref(&Float::from(E), 5, Ceiling);
854 /// assert_eq!(product.to_string(), "9.0");
855 /// assert_eq!(o, Greater);
856 ///
857 /// let (product, o) = Float::from(PI).mul_prec_round_ref_ref(&Float::from(E), 5, Nearest);
858 /// assert_eq!(product.to_string(), "8.5");
859 /// assert_eq!(o, Less);
860 ///
861 /// let (product, o) = Float::from(PI).mul_prec_round_ref_ref(&Float::from(E), 20, Floor);
862 /// assert_eq!(product.to_string(), "8.53973");
863 /// assert_eq!(o, Less);
864 ///
865 /// let (product, o) = Float::from(PI).mul_prec_round_ref_ref(&Float::from(E), 20, Ceiling);
866 /// assert_eq!(product.to_string(), "8.53975");
867 /// assert_eq!(o, Greater);
868 ///
869 /// let (product, o) = Float::from(PI).mul_prec_round_ref_ref(&Float::from(E), 20, Nearest);
870 /// assert_eq!(product.to_string(), "8.53973");
871 /// assert_eq!(o, Less);
872 /// ```
873 #[inline]
874 pub fn mul_prec_round_ref_ref(
875 &self,
876 other: &Float,
877 prec: u64,
878 rm: RoundingMode,
879 ) -> (Float, Ordering) {
880 assert_ne!(prec, 0);
881 match (self, other) {
882 (float_nan!(), _)
883 | (_, float_nan!())
884 | (float_either_infinity!(), float_either_zero!())
885 | (float_either_zero!(), float_either_infinity!()) => (float_nan!(), Equal),
886 (
887 Float(Infinity { sign: x_sign }),
888 Float(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }),
889 )
890 | (Float(Finite { sign: x_sign, .. }), Float(Infinity { sign: y_sign })) => (
891 Float(Infinity {
892 sign: x_sign == y_sign,
893 }),
894 Equal,
895 ),
896 (
897 Float(Zero { sign: x_sign }),
898 Float(Finite { sign: y_sign, .. } | Zero { sign: y_sign }),
899 )
900 | (Float(Finite { sign: x_sign, .. }), Float(Zero { sign: y_sign })) => (
901 Float(Zero {
902 sign: x_sign == y_sign,
903 }),
904 Equal,
905 ),
906 (
907 Float(Finite {
908 sign: x_sign,
909 exponent: x_exp,
910 precision: x_prec,
911 significand: x,
912 }),
913 Float(Finite {
914 sign: y_sign,
915 exponent: y_exp,
916 precision: y_prec,
917 significand: y,
918 }),
919 ) => {
920 let sign = x_sign == y_sign;
921 let exp_sum = x_exp + y_exp;
922 if exp_sum - 1 > Float::MAX_EXPONENT {
923 assert!(rm != Exact, "Inexact Float multiplication");
924 return match (sign, rm) {
925 (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater),
926 (true, _) => (Float::max_finite_value_with_prec(prec), Less),
927 (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less),
928 (false, _) => (-Float::max_finite_value_with_prec(prec), Greater),
929 };
930 } else if exp_sum < Float::MIN_EXPONENT - 1 {
931 assert!(rm != Exact, "Inexact Float multiplication");
932 return match (sign, rm) {
933 (true, Floor | Down | Nearest) => (float_zero!(), Less),
934 (true, _) => (Float::min_positive_value_prec(prec), Greater),
935 (false, Ceiling | Down | Nearest) => (float_negative_zero!(), Greater),
936 (false, _) => (-Float::min_positive_value_prec(prec), Less),
937 };
938 }
939 let (product, exp_offset, o) = mul_float_significands_ref_ref(
940 x,
941 *x_prec,
942 y,
943 *y_prec,
944 prec,
945 if sign { rm } else { -rm },
946 );
947 let exp = x_exp
948 .checked_add(*y_exp)
949 .unwrap()
950 .checked_add(exp_offset)
951 .unwrap();
952 if exp > Float::MAX_EXPONENT {
953 assert!(rm != Exact, "Inexact Float multiplication");
954 return match (sign, rm) {
955 (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater),
956 (true, _) => (Float::max_finite_value_with_prec(prec), Less),
957 (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less),
958 (false, _) => (-Float::max_finite_value_with_prec(prec), Greater),
959 };
960 } else if exp < Float::MIN_EXPONENT {
961 return if rm == Nearest
962 && exp == Float::MIN_EXPONENT - 1
963 && (o == Less || !product.is_power_of_2())
964 {
965 if sign {
966 (Float::min_positive_value_prec(prec), Greater)
967 } else {
968 (-Float::min_positive_value_prec(prec), Less)
969 }
970 } else {
971 match (sign, rm) {
972 (_, Exact) => panic!("Inexact float multiplication"),
973 (true, Ceiling | Up) => (Float::min_positive_value_prec(prec), Greater),
974 (true, _) => (float_zero!(), Less),
975 (false, Floor | Up) => (-Float::min_positive_value_prec(prec), Less),
976 (false, _) => (float_negative_zero!(), Greater),
977 }
978 };
979 }
980 (
981 Float(Finite {
982 sign,
983 exponent: exp,
984 precision: prec,
985 significand: product,
986 }),
987 if sign { o } else { o.reverse() },
988 )
989 }
990 }
991 }
992
993 /// Multiplies two [`Float`]s, rounding the result to the nearest value of the specified
994 /// precision. Both [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating
995 /// whether the rounded product is less than, equal to, or greater than the exact product.
996 /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
997 /// it also returns `Equal`.
998 ///
999 /// If the product is equidistant from two [`Float`]s with the specified precision, the
1000 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1001 /// description of the `Nearest` rounding mode.
1002 ///
1003 /// $$
1004 /// f(x,y,p) = xy+\varepsilon.
1005 /// $$
1006 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1007 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
1008 ///
1009 /// If the output has a precision, it is `prec`.
1010 ///
1011 /// Special cases:
1012 /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm0.0,p)=f(\pm0.0,\pm\infty,p) =
1013 /// \text{NaN}$
1014 /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x>0.0$
1015 /// - $f(\infty,x,p)=f(x,\infty,p)=-\infty$ if $x<0.0$
1016 /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x>0.0$
1017 /// - $f(-\infty,x,p)=f(x,-\infty,p)=\infty$ if $x<0.0$
1018 /// - $f(0.0,x,p)=f(x,0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1019 /// - $f(0.0,x,p)=f(x,0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1020 /// - $f(-0.0,x,p)=f(x,-0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1021 /// - $f(-0.0,x,p)=f(x,-0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1022 ///
1023 /// Overflow and underflow:
1024 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
1025 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
1026 /// - If $0<f(x,y,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1027 /// - If $2^{-2^{30}-1}<f(x,y,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1028 /// - If $-2^{-2^{30}-1}\leq f(x,y,p)<0$, $-0.0$ is returned instead.
1029 /// - If $-2^{-2^{30}}<f(x,y,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1030 ///
1031 /// If you want to use a rounding mode other than `Nearest`, consider using
1032 /// [`Float::mul_prec_round`] instead. If you know that your target precision is the maximum of
1033 /// the precisions of the two inputs, consider using `*` instead.
1034 ///
1035 /// # Worst-case complexity
1036 /// $T(n, m) = O(n \log n \log\log n + m)$
1037 ///
1038 /// $M(n, m) = O(n \log n + m)$
1039 ///
1040 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1041 /// other.significant_bits())`, and $m$ is `prec`.
1042 ///
1043 /// # Examples
1044 /// ```
1045 /// use core::f64::consts::{E, PI};
1046 /// use malachite_float::Float;
1047 /// use std::cmp::Ordering::*;
1048 ///
1049 /// let (product, o) = Float::from(PI).mul_prec(Float::from(E), 5);
1050 /// assert_eq!(product.to_string(), "8.5");
1051 /// assert_eq!(o, Less);
1052 ///
1053 /// let (product, o) = Float::from(PI).mul_prec(Float::from(E), 20);
1054 /// assert_eq!(product.to_string(), "8.53973");
1055 /// assert_eq!(o, Less);
1056 /// ```
1057 #[inline]
1058 pub fn mul_prec(self, other: Float, prec: u64) -> (Float, Ordering) {
1059 self.mul_prec_round(other, prec, Nearest)
1060 }
1061
1062 /// Multiplies two [`Float`]s, rounding the result to the nearest value of the specified
1063 /// precision. The first [`Float`] is taken by value and the second by reference. An
1064 /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal
1065 /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`],
1066 /// whenever this function returns a `NaN` it also returns `Equal`.
1067 ///
1068 /// If the product is equidistant from two [`Float`]s with the specified precision, the
1069 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1070 /// description of the `Nearest` rounding mode.
1071 ///
1072 /// $$
1073 /// f(x,y,p) = xy+\varepsilon.
1074 /// $$
1075 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1076 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
1077 ///
1078 /// If the output has a precision, it is `prec`.
1079 ///
1080 /// Special cases:
1081 /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm0.0,p)=f(\pm0.0,\pm\infty,p) =
1082 /// \text{NaN}$
1083 /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x>0.0$
1084 /// - $f(\infty,x,p)=f(x,\infty,p)=-\infty$ if $x<0.0$
1085 /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x>0.0$
1086 /// - $f(-\infty,x,p)=f(x,-\infty,p)=\infty$ if $x<0.0$
1087 /// - $f(0.0,x,p)=f(x,0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1088 /// - $f(0.0,x,p)=f(x,0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1089 /// - $f(-0.0,x,p)=f(x,-0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1090 /// - $f(-0.0,x,p)=f(x,-0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1091 ///
1092 /// Overflow and underflow:
1093 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
1094 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
1095 /// - If $0<f(x,y,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1096 /// - If $2^{-2^{30}-1}<f(x,y,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1097 /// - If $-2^{-2^{30}-1}\leq f(x,y,p)<0$, $-0.0$ is returned instead.
1098 /// - If $-2^{-2^{30}}<f(x,y,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1099 ///
1100 /// If you want to use a rounding mode other than `Nearest`, consider using
1101 /// [`Float::mul_prec_round_val_ref`] instead. If you know that your target precision is the
1102 /// maximum of the precisions of the two inputs, consider using `*` instead.
1103 ///
1104 /// # Worst-case complexity
1105 /// $T(n, m) = O(n \log n \log\log n + m)$
1106 ///
1107 /// $M(n, m) = O(n \log n + m)$
1108 ///
1109 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1110 /// other.significant_bits())`, and $m$ is `prec`.
1111 ///
1112 /// # Examples
1113 /// ```
1114 /// use core::f64::consts::{E, PI};
1115 /// use malachite_float::Float;
1116 /// use std::cmp::Ordering::*;
1117 ///
1118 /// let (product, o) = Float::from(PI).mul_prec_val_ref(&Float::from(E), 5);
1119 /// assert_eq!(product.to_string(), "8.5");
1120 /// assert_eq!(o, Less);
1121 ///
1122 /// let (product, o) = Float::from(PI).mul_prec_val_ref(&Float::from(E), 20);
1123 /// assert_eq!(product.to_string(), "8.53973");
1124 /// assert_eq!(o, Less);
1125 /// ```
1126 #[inline]
1127 pub fn mul_prec_val_ref(self, other: &Float, prec: u64) -> (Float, Ordering) {
1128 self.mul_prec_round_val_ref(other, prec, Nearest)
1129 }
1130
1131 /// Multiplies two [`Float`]s, rounding the result to the nearest value of the specified
1132 /// precision. The first [`Float`] is taken by reference and the second by value. An
1133 /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal
1134 /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`],
1135 /// whenever this function returns a `NaN` it also returns `Equal`.
1136 ///
1137 /// If the product is equidistant from two [`Float`]s with the specified precision, the
1138 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1139 /// description of the `Nearest` rounding mode.
1140 ///
1141 /// $$
1142 /// f(x,y,p) = xy+\varepsilon.
1143 /// $$
1144 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1145 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
1146 ///
1147 /// If the output has a precision, it is `prec`.
1148 ///
1149 /// Special cases:
1150 /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm0.0,p)=f(\pm0.0,\pm\infty,p) =
1151 /// \text{NaN}$
1152 /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x>0.0$
1153 /// - $f(\infty,x,p)=f(x,\infty,p)=-\infty$ if $x<0.0$
1154 /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x>0.0$
1155 /// - $f(-\infty,x,p)=f(x,-\infty,p)=\infty$ if $x<0.0$
1156 /// - $f(0.0,x,p)=f(x,0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1157 /// - $f(0.0,x,p)=f(x,0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1158 /// - $f(-0.0,x,p)=f(x,-0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1159 /// - $f(-0.0,x,p)=f(x,-0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1160 ///
1161 /// Overflow and underflow:
1162 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
1163 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
1164 /// - If $0<f(x,y,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1165 /// - If $2^{-2^{30}-1}<f(x,y,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1166 /// - If $-2^{-2^{30}-1}\leq f(x,y,p)<0$, $-0.0$ is returned instead.
1167 /// - If $-2^{-2^{30}}<f(x,y,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1168 ///
1169 /// If you want to use a rounding mode other than `Nearest`, consider using
1170 /// [`Float::mul_prec_round_ref_val`] instead. If you know that your target precision is the
1171 /// maximum of the precisions of the two inputs, consider using `*` instead.
1172 ///
1173 /// # Worst-case complexity
1174 /// $T(n, m) = O(n \log n \log\log n + m)$
1175 ///
1176 /// $M(n, m) = O(n \log n + m)$
1177 ///
1178 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1179 /// other.significant_bits())`, and $m$ is `prec`.
1180 ///
1181 /// # Examples
1182 /// ```
1183 /// use core::f64::consts::{E, PI};
1184 /// use malachite_float::Float;
1185 /// use std::cmp::Ordering::*;
1186 ///
1187 /// let (product, o) = Float::from(PI).mul_prec_ref_val(Float::from(E), 5);
1188 /// assert_eq!(product.to_string(), "8.5");
1189 /// assert_eq!(o, Less);
1190 ///
1191 /// let (product, o) = Float::from(PI).mul_prec_ref_val(Float::from(E), 20);
1192 /// assert_eq!(product.to_string(), "8.53973");
1193 /// assert_eq!(o, Less);
1194 /// ```
1195 #[inline]
1196 pub fn mul_prec_ref_val(&self, other: Float, prec: u64) -> (Float, Ordering) {
1197 self.mul_prec_round_ref_val(other, prec, Nearest)
1198 }
1199
1200 /// Multiplies two [`Float`]s, rounding the result to the nearest value of the specified
1201 /// precision. Both [`Float`]s are taken by reference. An [`Ordering`] is also returned,
1202 /// indicating whether the rounded product is less than, equal to, or greater than the exact
1203 /// product. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
1204 /// a `NaN` it also returns `Equal`.
1205 ///
1206 /// If the product is equidistant from two [`Float`]s with the specified precision, the
1207 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1208 /// description of the `Nearest` rounding mode.
1209 ///
1210 /// $$
1211 /// f(x,y,p) = xy+\varepsilon.
1212 /// $$
1213 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1214 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
1215 ///
1216 /// If the output has a precision, it is `prec`.
1217 ///
1218 /// Special cases:
1219 /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm0.0,p)=f(\pm0.0,\pm\infty,p) =
1220 /// \text{NaN}$
1221 /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x>0.0$
1222 /// - $f(\infty,x,p)=f(x,\infty,p)=-\infty$ if $x<0.0$
1223 /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x>0.0$
1224 /// - $f(-\infty,x,p)=f(x,-\infty,p)=\infty$ if $x<0.0$
1225 /// - $f(0.0,x,p)=f(x,0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1226 /// - $f(0.0,x,p)=f(x,0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1227 /// - $f(-0.0,x,p)=f(x,-0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1228 /// - $f(-0.0,x,p)=f(x,-0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1229 ///
1230 /// Overflow and underflow:
1231 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
1232 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
1233 /// - If $0<f(x,y,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1234 /// - If $2^{-2^{30}-1}<f(x,y,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1235 /// - If $-2^{-2^{30}-1}\leq f(x,y,p)<0$, $-0.0$ is returned instead.
1236 /// - If $-2^{-2^{30}}<f(x,y,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1237 ///
1238 /// If you want to use a rounding mode other than `Nearest`, consider using
1239 /// [`Float::mul_prec_round_ref_ref`] instead. If you know that your target precision is the
1240 /// maximum of the precisions of the two inputs, consider using `*` instead.
1241 ///
1242 /// # Worst-case complexity
1243 /// $T(n, m) = O(n \log n \log\log n + m)$
1244 ///
1245 /// $M(n, m) = O(n \log n + m)$
1246 ///
1247 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1248 /// other.significant_bits())`, and $m$ is `prec`.
1249 ///
1250 /// # Examples
1251 /// ```
1252 /// use core::f64::consts::{E, PI};
1253 /// use malachite_float::Float;
1254 /// use std::cmp::Ordering::*;
1255 ///
1256 /// let (product, o) = Float::from(PI).mul_prec_ref_ref(&Float::from(E), 5);
1257 /// assert_eq!(product.to_string(), "8.5");
1258 /// assert_eq!(o, Less);
1259 ///
1260 /// let (product, o) = Float::from(PI).mul_prec_ref_ref(&Float::from(E), 20);
1261 /// assert_eq!(product.to_string(), "8.53973");
1262 /// assert_eq!(o, Less);
1263 /// ```
1264 #[inline]
1265 pub fn mul_prec_ref_ref(&self, other: &Float, prec: u64) -> (Float, Ordering) {
1266 self.mul_prec_round_ref_ref(other, prec, Nearest)
1267 }
1268
1269 /// Multiplies two [`Float`]s, rounding the result with the specified rounding mode. Both
1270 /// [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating whether the
1271 /// rounded product is less than, equal to, or greater than the exact product. Although `NaN`s
1272 /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
1273 /// `Equal`.
1274 ///
1275 /// The precision of the output is the maximum of the precision of the inputs. See
1276 /// [`RoundingMode`] for a description of the possible rounding modes.
1277 ///
1278 /// $$
1279 /// f(x,y,m) = xy+\varepsilon.
1280 /// $$
1281 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1282 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1283 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs.
1284 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
1285 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs.
1286 ///
1287 /// If the output has a precision, it is the maximum of the precisions of the inputs.
1288 ///
1289 /// Special cases:
1290 /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\pm\infty,\pm0.0,m)=f(\pm0.0,\pm\infty,m) =
1291 /// \text{NaN}$
1292 /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x>0.0$
1293 /// - $f(\infty,x,m)=f(x,\infty,m)=-\infty$ if $x<0.0$
1294 /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x>0.0$
1295 /// - $f(-\infty,x,m)=f(x,-\infty,m)=\infty$ if $x<0.0$
1296 /// - $f(0.0,x,m)=f(x,0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1297 /// - $f(0.0,x,m)=f(x,0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1298 /// - $f(-0.0,x,m)=f(x,-0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1299 /// - $f(-0.0,x,m)=f(x,-0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1300 ///
1301 /// Overflow and underflow:
1302 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
1303 /// returned instead.
1304 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
1305 /// returned instead, where `p` is the precision of the input.
1306 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
1307 /// returned instead.
1308 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$
1309 /// is returned instead, where `p` is the precision of the input.
1310 /// - If $0<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1311 /// - If $0<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1312 /// instead.
1313 /// - If $0<f(x,y,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1314 /// - If $2^{-2^{30}-1}<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1315 /// instead.
1316 /// - If $-2^{-2^{30}}<f(x,y,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1317 /// - If $-2^{-2^{30}}<f(x,y,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1318 /// instead.
1319 /// - If $-2^{-2^{30}-1}\leq f(x,y,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1320 /// - If $-2^{-2^{30}}<f(x,y,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
1321 /// returned instead.
1322 ///
1323 /// If you want to specify an output precision, consider using [`Float::mul_prec_round`]
1324 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `*`
1325 /// instead.
1326 ///
1327 /// # Worst-case complexity
1328 /// $T(n) = O(n \log n \log\log n)$
1329 ///
1330 /// $M(n) = O(n \log n)$
1331 ///
1332 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1333 /// other.significant_bits())`.
1334 ///
1335 /// # Panics
1336 /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to
1337 /// represent the output.
1338 ///
1339 /// # Examples
1340 /// ```
1341 /// use core::f64::consts::{E, PI};
1342 /// use malachite_base::rounding_modes::RoundingMode::*;
1343 /// use malachite_float::Float;
1344 /// use std::cmp::Ordering::*;
1345 ///
1346 /// let (product, o) = Float::from(PI).mul_round(Float::from(E), Floor);
1347 /// assert_eq!(product.to_string(), "8.539734222673566");
1348 /// assert_eq!(o, Less);
1349 ///
1350 /// let (product, o) = Float::from(PI).mul_round(Float::from(E), Ceiling);
1351 /// assert_eq!(product.to_string(), "8.539734222673568");
1352 /// assert_eq!(o, Greater);
1353 ///
1354 /// let (product, o) = Float::from(PI).mul_round(Float::from(E), Nearest);
1355 /// assert_eq!(product.to_string(), "8.539734222673566");
1356 /// assert_eq!(o, Less);
1357 /// ```
1358 #[inline]
1359 pub fn mul_round(self, other: Float, rm: RoundingMode) -> (Float, Ordering) {
1360 let prec = max(self.significant_bits(), other.significant_bits());
1361 self.mul_prec_round(other, prec, rm)
1362 }
1363
1364 /// Multiplies two [`Float`]s, rounding the result with the specified rounding mode. The first
1365 /// [`Float`] is taken by value and the second by reference. An [`Ordering`] is also returned,
1366 /// indicating whether the rounded product is less than, equal to, or greater than the exact
1367 /// product. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
1368 /// a `NaN` it also returns `Equal`.
1369 ///
1370 /// The precision of the output is the maximum of the precision of the inputs. See
1371 /// [`RoundingMode`] for a description of the possible rounding modes.
1372 ///
1373 /// $$
1374 /// f(x,y,m) = xy+\varepsilon.
1375 /// $$
1376 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1377 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1378 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs.
1379 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
1380 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs.
1381 ///
1382 /// If the output has a precision, it is the maximum of the precisions of the inputs.
1383 ///
1384 /// Special cases:
1385 /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\pm\infty,\pm0.0,m)=f(\pm0.0,\pm\infty,m) =
1386 /// \text{NaN}$
1387 /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x>0.0$
1388 /// - $f(\infty,x,m)=f(x,\infty,m)=-\infty$ if $x<0.0$
1389 /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x>0.0$
1390 /// - $f(-\infty,x,m)=f(x,-\infty,m)=\infty$ if $x<0.0$
1391 /// - $f(0.0,x,m)=f(x,0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1392 /// - $f(0.0,x,m)=f(x,0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1393 /// - $f(-0.0,x,m)=f(x,-0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1394 /// - $f(-0.0,x,m)=f(x,-0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1395 ///
1396 /// Overflow and underflow:
1397 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
1398 /// returned instead.
1399 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
1400 /// returned instead, where `p` is the precision of the input.
1401 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
1402 /// returned instead.
1403 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$
1404 /// is returned instead, where `p` is the precision of the input.
1405 /// - If $0<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1406 /// - If $0<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1407 /// instead.
1408 /// - If $0<f(x,y,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1409 /// - If $2^{-2^{30}-1}<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1410 /// instead.
1411 /// - If $-2^{-2^{30}}<f(x,y,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1412 /// - If $-2^{-2^{30}}<f(x,y,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1413 /// instead.
1414 /// - If $-2^{-2^{30}-1}\leq f(x,y,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1415 /// - If $-2^{-2^{30}}<f(x,y,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
1416 /// returned instead.
1417 ///
1418 /// If you want to specify an output precision, consider using [`Float::mul_prec_round_val_ref`]
1419 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `*`
1420 /// instead.
1421 ///
1422 /// # Worst-case complexity
1423 /// $T(n) = O(n \log n \log\log n)$
1424 ///
1425 /// $M(n) = O(n \log n)$
1426 ///
1427 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1428 /// other.significant_bits())`.
1429 ///
1430 /// # Panics
1431 /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to
1432 /// represent the output.
1433 ///
1434 /// # Examples
1435 /// ```
1436 /// use core::f64::consts::{E, PI};
1437 /// use malachite_base::rounding_modes::RoundingMode::*;
1438 /// use malachite_float::Float;
1439 /// use std::cmp::Ordering::*;
1440 ///
1441 /// let (product, o) = Float::from(PI).mul_round_val_ref(&Float::from(E), Floor);
1442 /// assert_eq!(product.to_string(), "8.539734222673566");
1443 /// assert_eq!(o, Less);
1444 ///
1445 /// let (product, o) = Float::from(PI).mul_round_val_ref(&Float::from(E), Ceiling);
1446 /// assert_eq!(product.to_string(), "8.539734222673568");
1447 /// assert_eq!(o, Greater);
1448 ///
1449 /// let (product, o) = Float::from(PI).mul_round_val_ref(&Float::from(E), Nearest);
1450 /// assert_eq!(product.to_string(), "8.539734222673566");
1451 /// assert_eq!(o, Less);
1452 /// ```
1453 #[inline]
1454 pub fn mul_round_val_ref(self, other: &Float, rm: RoundingMode) -> (Float, Ordering) {
1455 let prec = max(self.significant_bits(), other.significant_bits());
1456 self.mul_prec_round_val_ref(other, prec, rm)
1457 }
1458
1459 /// Multiplies two [`Float`]s, rounding the result with the specified rounding mode. The first
1460 /// [`Float`] is taken by reference and the second by value. An [`Ordering`] is also returned,
1461 /// indicating whether the rounded product is less than, equal to, or greater than the exact
1462 /// product. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
1463 /// a `NaN` it also returns `Equal`.
1464 ///
1465 /// The precision of the output is the maximum of the precision of the inputs. See
1466 /// [`RoundingMode`] for a description of the possible rounding modes.
1467 ///
1468 /// $$
1469 /// f(x,y,m) = xy+\varepsilon.
1470 /// $$
1471 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1472 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1473 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs.
1474 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
1475 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs.
1476 ///
1477 /// If the output has a precision, it is the maximum of the precisions of the inputs.
1478 ///
1479 /// Special cases:
1480 /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\pm\infty,\pm0.0,m)=f(\pm0.0,\pm\infty,m) =
1481 /// \text{NaN}$
1482 /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x>0.0$
1483 /// - $f(\infty,x,m)=f(x,\infty,m)=-\infty$ if $x<0.0$
1484 /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x>0.0$
1485 /// - $f(-\infty,x,m)=f(x,-\infty,m)=\infty$ if $x<0.0$
1486 /// - $f(0.0,x,m)=f(x,0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1487 /// - $f(0.0,x,m)=f(x,0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1488 /// - $f(-0.0,x,m)=f(x,-0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1489 /// - $f(-0.0,x,m)=f(x,-0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1490 ///
1491 /// Overflow and underflow:
1492 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
1493 /// returned instead.
1494 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
1495 /// returned instead, where `p` is the precision of the input.
1496 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
1497 /// returned instead.
1498 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$
1499 /// is returned instead, where `p` is the precision of the input.
1500 /// - If $0<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1501 /// - If $0<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1502 /// instead.
1503 /// - If $0<f(x,y,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1504 /// - If $2^{-2^{30}-1}<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1505 /// instead.
1506 /// - If $-2^{-2^{30}}<f(x,y,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1507 /// - If $-2^{-2^{30}}<f(x,y,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1508 /// instead.
1509 /// - If $-2^{-2^{30}-1}\leq f(x,y,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1510 /// - If $-2^{-2^{30}}<f(x,y,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
1511 /// returned instead.
1512 ///
1513 /// If you want to specify an output precision, consider using [`Float::mul_prec_round_ref_val`]
1514 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `*`
1515 /// instead.
1516 ///
1517 /// # Worst-case complexity
1518 /// $T(n) = O(n \log n \log\log n)$
1519 ///
1520 /// $M(n) = O(n \log n)$
1521 ///
1522 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1523 /// other.significant_bits())`.
1524 ///
1525 /// # Panics
1526 /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to
1527 /// represent the output.
1528 ///
1529 /// # Examples
1530 /// ```
1531 /// use core::f64::consts::{E, PI};
1532 /// use malachite_base::rounding_modes::RoundingMode::*;
1533 /// use malachite_float::Float;
1534 /// use std::cmp::Ordering::*;
1535 ///
1536 /// let (product, o) = Float::from(PI).mul_round_ref_val(Float::from(E), Floor);
1537 /// assert_eq!(product.to_string(), "8.539734222673566");
1538 /// assert_eq!(o, Less);
1539 ///
1540 /// let (product, o) = Float::from(PI).mul_round_ref_val(Float::from(E), Ceiling);
1541 /// assert_eq!(product.to_string(), "8.539734222673568");
1542 /// assert_eq!(o, Greater);
1543 ///
1544 /// let (product, o) = Float::from(PI).mul_round_ref_val(Float::from(E), Nearest);
1545 /// assert_eq!(product.to_string(), "8.539734222673566");
1546 /// assert_eq!(o, Less);
1547 /// ```
1548 #[inline]
1549 pub fn mul_round_ref_val(&self, other: Float, rm: RoundingMode) -> (Float, Ordering) {
1550 let prec = max(self.significant_bits(), other.significant_bits());
1551 self.mul_prec_round_ref_val(other, prec, rm)
1552 }
1553
1554 /// Multiplies two [`Float`]s, rounding the result with the specified rounding mode. Both
1555 /// [`Float`]s are taken by reference. An [`Ordering`] is also returned, indicating whether the
1556 /// rounded product is less than, equal to, or greater than the exact product. Although `NaN`s
1557 /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
1558 /// `Equal`.
1559 ///
1560 /// The precision of the output is the maximum of the precision of the inputs. See
1561 /// [`RoundingMode`] for a description of the possible rounding modes.
1562 ///
1563 /// $$
1564 /// f(x,y,m) = xy+\varepsilon.
1565 /// $$
1566 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1567 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1568 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs.
1569 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
1570 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs.
1571 ///
1572 /// If the output has a precision, it is the maximum of the precisions of the inputs.
1573 ///
1574 /// Special cases:
1575 /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\pm\infty,\pm0.0,m)=f(\pm0.0,\pm\infty,m) =
1576 /// \text{NaN}$
1577 /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x>0.0$
1578 /// - $f(\infty,x,m)=f(x,\infty,m)=-\infty$ if $x<0.0$
1579 /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x>0.0$
1580 /// - $f(-\infty,x,m)=f(x,-\infty,m)=\infty$ if $x<0.0$
1581 /// - $f(0.0,x,m)=f(x,0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1582 /// - $f(0.0,x,m)=f(x,0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1583 /// - $f(-0.0,x,m)=f(x,-0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
1584 /// - $f(-0.0,x,m)=f(x,-0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
1585 ///
1586 /// Overflow and underflow:
1587 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
1588 /// returned instead.
1589 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
1590 /// returned instead, where `p` is the precision of the input.
1591 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
1592 /// returned instead.
1593 /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$
1594 /// is returned instead, where `p` is the precision of the input.
1595 /// - If $0<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1596 /// - If $0<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1597 /// instead.
1598 /// - If $0<f(x,y,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1599 /// - If $2^{-2^{30}-1}<f(x,y,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1600 /// instead.
1601 /// - If $-2^{-2^{30}}<f(x,y,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1602 /// - If $-2^{-2^{30}}<f(x,y,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1603 /// instead.
1604 /// - If $-2^{-2^{30}-1}\leq f(x,y,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1605 /// - If $-2^{-2^{30}}<f(x,y,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
1606 /// returned instead.
1607 ///
1608 /// If you want to specify an output precision, consider using [`Float::mul_prec_round_ref_ref`]
1609 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `*`
1610 /// instead.
1611 ///
1612 /// # Worst-case complexity
1613 /// $T(n) = O(n \log n \log\log n)$
1614 ///
1615 /// $M(n) = O(n \log n)$
1616 ///
1617 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1618 /// other.significant_bits())`.
1619 ///
1620 /// # Panics
1621 /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to
1622 /// represent the output.
1623 ///
1624 /// # Examples
1625 /// ```
1626 /// use core::f64::consts::{E, PI};
1627 /// use malachite_base::rounding_modes::RoundingMode::*;
1628 /// use malachite_float::Float;
1629 /// use std::cmp::Ordering::*;
1630 ///
1631 /// let (product, o) = Float::from(PI).mul_round_ref_ref(&Float::from(E), Floor);
1632 /// assert_eq!(product.to_string(), "8.539734222673566");
1633 /// assert_eq!(o, Less);
1634 ///
1635 /// let (product, o) = Float::from(PI).mul_round_ref_ref(&Float::from(E), Ceiling);
1636 /// assert_eq!(product.to_string(), "8.539734222673568");
1637 /// assert_eq!(o, Greater);
1638 ///
1639 /// let (product, o) = Float::from(PI).mul_round_ref_ref(&Float::from(E), Nearest);
1640 /// assert_eq!(product.to_string(), "8.539734222673566");
1641 /// assert_eq!(o, Less);
1642 /// ```
1643 #[inline]
1644 pub fn mul_round_ref_ref(&self, other: &Float, rm: RoundingMode) -> (Float, Ordering) {
1645 let prec = max(self.significant_bits(), other.significant_bits());
1646 self.mul_prec_round_ref_ref(other, prec, rm)
1647 }
1648
1649 /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result to the specified
1650 /// precision and with the specified rounding mode. The [`Float`] on the right-hand side is
1651 /// taken by value. An [`Ordering`] is returned, indicating whether the rounded product is less
1652 /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any
1653 /// [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns `Equal`.
1654 ///
1655 /// See [`RoundingMode`] for a description of the possible rounding modes.
1656 ///
1657 /// $$
1658 /// x \gets xy+\varepsilon.
1659 /// $$
1660 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1661 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1662 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
1663 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
1664 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
1665 ///
1666 /// If the output has a precision, it is `prec`.
1667 ///
1668 /// See the [`Float::mul_prec_round`] documentation for information on special cases, overflow,
1669 /// and underflow.
1670 ///
1671 /// If you know you'll be using `Nearest`, consider using [`Float::mul_prec_assign`] instead. If
1672 /// you know that your target precision is the maximum of the precisions of the two inputs,
1673 /// consider using [`Float::mul_round_assign`] instead. If both of these things are true,
1674 /// consider using `*=` instead.
1675 ///
1676 /// # Worst-case complexity
1677 /// $T(n, m) = O(n \log n \log\log n + m)$
1678 ///
1679 /// $M(n, m) = O(n \log n + m)$
1680 ///
1681 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1682 /// other.significant_bits())`, and $m$ is `prec`.
1683 ///
1684 /// # Panics
1685 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
1686 ///
1687 /// # Examples
1688 /// ```
1689 /// use core::f64::consts::{E, PI};
1690 /// use malachite_base::rounding_modes::RoundingMode::*;
1691 /// use malachite_float::Float;
1692 /// use std::cmp::Ordering::*;
1693 ///
1694 /// let mut product = Float::from(PI);
1695 /// assert_eq!(
1696 /// product.mul_prec_round_assign(Float::from(E), 5, Floor),
1697 /// Less
1698 /// );
1699 /// assert_eq!(product.to_string(), "8.5");
1700 ///
1701 /// let mut product = Float::from(PI);
1702 /// assert_eq!(
1703 /// product.mul_prec_round_assign(Float::from(E), 5, Ceiling),
1704 /// Greater
1705 /// );
1706 /// assert_eq!(product.to_string(), "9.0");
1707 ///
1708 /// let mut product = Float::from(PI);
1709 /// assert_eq!(
1710 /// product.mul_prec_round_assign(Float::from(E), 5, Nearest),
1711 /// Less
1712 /// );
1713 /// assert_eq!(product.to_string(), "8.5");
1714 ///
1715 /// let mut product = Float::from(PI);
1716 /// assert_eq!(
1717 /// product.mul_prec_round_assign(Float::from(E), 20, Floor),
1718 /// Less
1719 /// );
1720 /// assert_eq!(product.to_string(), "8.53973");
1721 ///
1722 /// let mut product = Float::from(PI);
1723 /// assert_eq!(
1724 /// product.mul_prec_round_assign(Float::from(E), 20, Ceiling),
1725 /// Greater
1726 /// );
1727 /// assert_eq!(product.to_string(), "8.53975");
1728 ///
1729 /// let mut product = Float::from(PI);
1730 /// assert_eq!(
1731 /// product.mul_prec_round_assign(Float::from(E), 20, Nearest),
1732 /// Less
1733 /// );
1734 /// assert_eq!(product.to_string(), "8.53973");
1735 /// ```
1736 #[inline]
1737 pub fn mul_prec_round_assign(&mut self, other: Float, prec: u64, rm: RoundingMode) -> Ordering {
1738 assert_ne!(prec, 0);
1739 match (&mut *self, other) {
1740 (float_nan!(), _)
1741 | (_, float_nan!())
1742 | (float_either_infinity!(), float_either_zero!())
1743 | (float_either_zero!(), float_either_infinity!()) => {
1744 *self = float_nan!();
1745 Equal
1746 }
1747 (
1748 Float(Infinity { sign: x_sign }),
1749 Float(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }),
1750 )
1751 | (Float(Finite { sign: x_sign, .. }), Float(Infinity { sign: y_sign })) => {
1752 *self = Float(Infinity {
1753 sign: *x_sign == y_sign,
1754 });
1755 Equal
1756 }
1757 (
1758 Float(Zero { sign: x_sign }),
1759 Float(Finite { sign: y_sign, .. } | Zero { sign: y_sign }),
1760 )
1761 | (Float(Finite { sign: x_sign, .. }), Float(Zero { sign: y_sign })) => {
1762 *self = Float(Zero {
1763 sign: *x_sign == y_sign,
1764 });
1765 Equal
1766 }
1767 (
1768 Float(Finite {
1769 sign: x_sign,
1770 exponent: x_exp,
1771 precision: x_prec,
1772 significand: x,
1773 }),
1774 Float(Finite {
1775 sign: y_sign,
1776 exponent: y_exp,
1777 precision: y_prec,
1778 significand: mut y,
1779 }),
1780 ) => {
1781 let sign = *x_sign == y_sign;
1782 let exp_sum = *x_exp + y_exp;
1783 if exp_sum - 1 > Float::MAX_EXPONENT {
1784 assert!(rm != Exact, "Inexact Float multiplication");
1785 return match (sign, rm) {
1786 (true, Ceiling | Up | Nearest) => {
1787 *self = float_infinity!();
1788 Greater
1789 }
1790 (true, _) => {
1791 *self = Float::max_finite_value_with_prec(prec);
1792 Less
1793 }
1794 (false, Floor | Up | Nearest) => {
1795 *self = float_negative_infinity!();
1796 Less
1797 }
1798 (false, _) => {
1799 *self = -Float::max_finite_value_with_prec(prec);
1800 Greater
1801 }
1802 };
1803 } else if exp_sum < Float::MIN_EXPONENT - 1 {
1804 assert!(rm != Exact, "Inexact Float multiplication");
1805 return match (sign, rm) {
1806 (true, Floor | Down | Nearest) => {
1807 *self = float_zero!();
1808 Less
1809 }
1810 (true, _) => {
1811 *self = Float::min_positive_value_prec(prec);
1812 Greater
1813 }
1814 (false, Ceiling | Down | Nearest) => {
1815 *self = float_negative_zero!();
1816 Greater
1817 }
1818 (false, _) => {
1819 *self = -Float::min_positive_value_prec(prec);
1820 Less
1821 }
1822 };
1823 }
1824 let (exp_offset, o) = mul_float_significands_in_place(
1825 x,
1826 *x_prec,
1827 &mut y,
1828 y_prec,
1829 prec,
1830 if sign { rm } else { -rm },
1831 );
1832 *x_exp = x_exp
1833 .checked_add(y_exp)
1834 .unwrap()
1835 .checked_add(exp_offset)
1836 .unwrap();
1837 if *x_exp > Float::MAX_EXPONENT {
1838 assert!(rm != Exact, "Inexact Float multiplication");
1839 return match (sign, rm) {
1840 (true, Ceiling | Up | Nearest) => {
1841 *self = float_infinity!();
1842 Greater
1843 }
1844 (true, _) => {
1845 *self = Float::max_finite_value_with_prec(prec);
1846 Less
1847 }
1848 (false, Floor | Up | Nearest) => {
1849 *self = float_negative_infinity!();
1850 Less
1851 }
1852 (false, _) => {
1853 *self = -Float::max_finite_value_with_prec(prec);
1854 Greater
1855 }
1856 };
1857 } else if *x_exp < Float::MIN_EXPONENT {
1858 return if rm == Nearest
1859 && *x_exp == Float::MIN_EXPONENT - 1
1860 && (o == Less || !x.is_power_of_2())
1861 {
1862 if sign {
1863 {
1864 *self = Float::min_positive_value_prec(prec);
1865 Greater
1866 }
1867 } else {
1868 {
1869 *self = -Float::min_positive_value_prec(prec);
1870 Less
1871 }
1872 }
1873 } else {
1874 match (sign, rm) {
1875 (_, Exact) => panic!("Inexact float multiplication"),
1876 (true, Ceiling | Up) => {
1877 *self = Float::min_positive_value_prec(prec);
1878 Greater
1879 }
1880 (true, _) => {
1881 *self = float_zero!();
1882 Less
1883 }
1884 (false, Floor | Up) => {
1885 *self = -Float::min_positive_value_prec(prec);
1886 Less
1887 }
1888 (false, _) => {
1889 *self = float_negative_zero!();
1890 Greater
1891 }
1892 }
1893 };
1894 }
1895 *x_sign = sign;
1896 *x_prec = prec;
1897 if sign { o } else { o.reverse() }
1898 }
1899 }
1900 }
1901
1902 /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result to the specified
1903 /// precision and with the specified rounding mode. The [`Float`] on the right-hand side is
1904 /// taken by reference. An [`Ordering`] is returned, indicating whether the rounded product is
1905 /// less than, equal to, or greater than the exact product. Although `NaN`s are not comparable
1906 /// to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns
1907 /// `Equal`.
1908 ///
1909 /// See [`RoundingMode`] for a description of the possible rounding modes.
1910 ///
1911 /// $$
1912 /// x \gets xy+\varepsilon.
1913 /// $$
1914 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1915 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1916 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
1917 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
1918 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
1919 ///
1920 /// If the output has a precision, it is `prec`.
1921 ///
1922 /// See the [`Float::mul_prec_round`] documentation for information on special cases, overflow,
1923 /// and underflow.
1924 ///
1925 /// If you know you'll be using `Nearest`, consider using [`Float::mul_prec_assign_ref`]
1926 /// instead. If you know that your target precision is the maximum of the precisions of the two
1927 /// inputs, consider using [`Float::mul_round_assign_ref`] instead. If both of these things are
1928 /// true, consider using `*=` instead.
1929 ///
1930 /// # Worst-case complexity
1931 /// $T(n, m) = O(n \log n \log\log n + m)$
1932 ///
1933 /// $M(n, m) = O(n \log n + m)$
1934 ///
1935 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1936 /// other.significant_bits())`, and $m$ is `prec`.
1937 ///
1938 /// # Panics
1939 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
1940 ///
1941 /// # Examples
1942 /// ```
1943 /// use core::f64::consts::{E, PI};
1944 /// use malachite_base::rounding_modes::RoundingMode::*;
1945 /// use malachite_float::Float;
1946 /// use std::cmp::Ordering::*;
1947 ///
1948 /// let mut product = Float::from(PI);
1949 /// assert_eq!(
1950 /// product.mul_prec_round_assign_ref(&Float::from(E), 5, Floor),
1951 /// Less
1952 /// );
1953 /// assert_eq!(product.to_string(), "8.5");
1954 ///
1955 /// let mut product = Float::from(PI);
1956 /// assert_eq!(
1957 /// product.mul_prec_round_assign_ref(&Float::from(E), 5, Ceiling),
1958 /// Greater
1959 /// );
1960 /// assert_eq!(product.to_string(), "9.0");
1961 ///
1962 /// let mut product = Float::from(PI);
1963 /// assert_eq!(
1964 /// product.mul_prec_round_assign_ref(&Float::from(E), 5, Nearest),
1965 /// Less
1966 /// );
1967 /// assert_eq!(product.to_string(), "8.5");
1968 ///
1969 /// let mut product = Float::from(PI);
1970 /// assert_eq!(
1971 /// product.mul_prec_round_assign_ref(&Float::from(E), 20, Floor),
1972 /// Less
1973 /// );
1974 /// assert_eq!(product.to_string(), "8.53973");
1975 ///
1976 /// let mut product = Float::from(PI);
1977 /// assert_eq!(
1978 /// product.mul_prec_round_assign_ref(&Float::from(E), 20, Ceiling),
1979 /// Greater
1980 /// );
1981 /// assert_eq!(product.to_string(), "8.53975");
1982 ///
1983 /// let mut product = Float::from(PI);
1984 /// assert_eq!(
1985 /// product.mul_prec_round_assign_ref(&Float::from(E), 20, Nearest),
1986 /// Less
1987 /// );
1988 /// assert_eq!(product.to_string(), "8.53973");
1989 /// ```
1990 #[inline]
1991 pub fn mul_prec_round_assign_ref(
1992 &mut self,
1993 other: &Float,
1994 prec: u64,
1995 rm: RoundingMode,
1996 ) -> Ordering {
1997 assert_ne!(prec, 0);
1998 match (&mut *self, other) {
1999 (float_nan!(), _)
2000 | (_, float_nan!())
2001 | (float_either_infinity!(), float_either_zero!())
2002 | (float_either_zero!(), float_either_infinity!()) => {
2003 *self = float_nan!();
2004 Equal
2005 }
2006 (
2007 Float(Infinity { sign: x_sign }),
2008 Float(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }),
2009 )
2010 | (Float(Finite { sign: x_sign, .. }), Float(Infinity { sign: y_sign })) => {
2011 *self = Float(Infinity {
2012 sign: *x_sign == *y_sign,
2013 });
2014 Equal
2015 }
2016 (
2017 Float(Zero { sign: x_sign }),
2018 Float(Finite { sign: y_sign, .. } | Zero { sign: y_sign }),
2019 )
2020 | (Float(Finite { sign: x_sign, .. }), Float(Zero { sign: y_sign })) => {
2021 *self = Float(Zero {
2022 sign: *x_sign == *y_sign,
2023 });
2024 Equal
2025 }
2026 (
2027 Float(Finite {
2028 sign: x_sign,
2029 exponent: x_exp,
2030 precision: x_prec,
2031 significand: x,
2032 }),
2033 Float(Finite {
2034 sign: y_sign,
2035 exponent: y_exp,
2036 precision: y_prec,
2037 significand: y,
2038 }),
2039 ) => {
2040 let sign = x_sign == y_sign;
2041 let exp_sum = *x_exp + y_exp;
2042 if exp_sum - 1 > Float::MAX_EXPONENT {
2043 assert!(rm != Exact, "Inexact Float multiplication");
2044 return match (sign, rm) {
2045 (true, Ceiling | Up | Nearest) => {
2046 *self = float_infinity!();
2047 Greater
2048 }
2049 (true, _) => {
2050 *self = Float::max_finite_value_with_prec(prec);
2051 Less
2052 }
2053 (false, Floor | Up | Nearest) => {
2054 *self = float_negative_infinity!();
2055 Less
2056 }
2057 (false, _) => {
2058 *self = -Float::max_finite_value_with_prec(prec);
2059 Greater
2060 }
2061 };
2062 } else if exp_sum < Float::MIN_EXPONENT - 1 {
2063 assert!(rm != Exact, "Inexact Float multiplication");
2064 return match (sign, rm) {
2065 (true, Floor | Down | Nearest) => {
2066 *self = float_zero!();
2067 Less
2068 }
2069 (true, _) => {
2070 *self = Float::min_positive_value_prec(prec);
2071 Greater
2072 }
2073 (false, Ceiling | Down | Nearest) => {
2074 *self = float_negative_zero!();
2075 Greater
2076 }
2077 (false, _) => {
2078 *self = -Float::min_positive_value_prec(prec);
2079 Less
2080 }
2081 };
2082 }
2083 let (exp_offset, o) = mul_float_significands_in_place_ref(
2084 x,
2085 *x_prec,
2086 y,
2087 *y_prec,
2088 prec,
2089 if sign { rm } else { -rm },
2090 );
2091 *x_exp = x_exp
2092 .checked_add(*y_exp)
2093 .unwrap()
2094 .checked_add(exp_offset)
2095 .unwrap();
2096 if *x_exp > Float::MAX_EXPONENT {
2097 assert!(rm != Exact, "Inexact Float multiplication");
2098 return match (sign, rm) {
2099 (true, Ceiling | Up | Nearest) => {
2100 *self = float_infinity!();
2101 Greater
2102 }
2103 (true, _) => {
2104 *self = Float::max_finite_value_with_prec(prec);
2105 Less
2106 }
2107 (false, Floor | Up | Nearest) => {
2108 *self = float_negative_infinity!();
2109 Less
2110 }
2111 (false, _) => {
2112 *self = -Float::max_finite_value_with_prec(prec);
2113 Greater
2114 }
2115 };
2116 } else if *x_exp < Float::MIN_EXPONENT {
2117 return if rm == Nearest
2118 && *x_exp == Float::MIN_EXPONENT - 1
2119 && (o == Less || !x.is_power_of_2())
2120 {
2121 if sign {
2122 {
2123 *self = Float::min_positive_value_prec(prec);
2124 Greater
2125 }
2126 } else {
2127 {
2128 *self = -Float::min_positive_value_prec(prec);
2129 Less
2130 }
2131 }
2132 } else {
2133 match (sign, rm) {
2134 (_, Exact) => panic!("Inexact float multiplication"),
2135 (true, Ceiling | Up) => {
2136 *self = Float::min_positive_value_prec(prec);
2137 Greater
2138 }
2139 (true, _) => {
2140 *self = float_zero!();
2141 Less
2142 }
2143 (false, Floor | Up) => {
2144 *self = -Float::min_positive_value_prec(prec);
2145 Less
2146 }
2147 (false, _) => {
2148 *self = float_negative_zero!();
2149 Greater
2150 }
2151 }
2152 };
2153 }
2154 *x_sign = sign;
2155 *x_prec = prec;
2156 if sign { o } else { o.reverse() }
2157 }
2158 }
2159 }
2160
2161 /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result to the nearest value of
2162 /// the specified precision. The [`Float`] on the right-hand side is taken by value. An
2163 /// [`Ordering`] is returned, indicating whether the rounded product is less than, equal to, or
2164 /// greater than the exact product. Although `NaN`s are not comparable to any [`Float`],
2165 /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`.
2166 ///
2167 /// If the product is equidistant from two [`Float`]s with the specified precision, the
2168 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2169 /// description of the `Nearest` rounding mode.
2170 ///
2171 /// $$
2172 /// x \gets xy+\varepsilon.
2173 /// $$
2174 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2175 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
2176 ///
2177 /// If the output has a precision, it is `prec`.
2178 ///
2179 /// See the [`Float::mul_prec`] documentation for information on special cases, overflow, and
2180 /// underflow.
2181 ///
2182 /// If you want to use a rounding mode other than `Nearest`, consider using
2183 /// [`Float::mul_prec_round_assign`] instead. If you know that your target precision is the
2184 /// maximum of the precisions of the two inputs, consider using `*=` instead.
2185 ///
2186 /// # Worst-case complexity
2187 /// $T(n, m) = O(n \log n \log\log n + m)$
2188 ///
2189 /// $M(n, m) = O(n \log n + m)$
2190 ///
2191 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
2192 /// other.significant_bits())`, and $m$ is `prec`.
2193 ///
2194 /// # Examples
2195 /// ```
2196 /// use core::f64::consts::{E, PI};
2197 /// use malachite_float::Float;
2198 /// use std::cmp::Ordering::*;
2199 ///
2200 /// let mut x = Float::from(PI);
2201 /// assert_eq!(x.mul_prec_assign(Float::from(E), 5), Less);
2202 /// assert_eq!(x.to_string(), "8.5");
2203 ///
2204 /// let mut x = Float::from(PI);
2205 /// assert_eq!(x.mul_prec_assign(Float::from(E), 20), Less);
2206 /// assert_eq!(x.to_string(), "8.53973");
2207 /// ```
2208 #[inline]
2209 pub fn mul_prec_assign(&mut self, other: Float, prec: u64) -> Ordering {
2210 self.mul_prec_round_assign(other, prec, Nearest)
2211 }
2212
2213 /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result to the nearest value of
2214 /// the specified precision. The [`Float`] on the right-hand side is taken by reference. An
2215 /// [`Ordering`] is returned, indicating whether the rounded product is less than, equal to, or
2216 /// greater than the exact product. Although `NaN`s are not comparable to any [`Float`],
2217 /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`.
2218 ///
2219 /// If the product is equidistant from two [`Float`]s with the specified precision, the
2220 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2221 /// description of the `Nearest` rounding mode.
2222 ///
2223 /// $$
2224 /// x \gets xy+\varepsilon.
2225 /// $$
2226 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2227 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
2228 ///
2229 /// If the output has a precision, it is `prec`.
2230 ///
2231 /// See the [`Float::mul_prec`] documentation for information on special cases, overflow, and
2232 /// underflow.
2233 ///
2234 /// If you want to use a rounding mode other than `Nearest`, consider using
2235 /// [`Float::mul_prec_round_assign_ref`] instead. If you know that your target precision is the
2236 /// maximum of the precisions of the two inputs, consider using `*=` instead.
2237 ///
2238 /// # Worst-case complexity
2239 /// $T(n, m) = O(n \log n \log\log n + m)$
2240 ///
2241 /// $M(n, m) = O(n \log n + m)$
2242 ///
2243 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
2244 /// other.significant_bits())`, and $m$ is `prec`.
2245 ///
2246 /// # Examples
2247 /// ```
2248 /// use core::f64::consts::{E, PI};
2249 /// use malachite_float::Float;
2250 /// use std::cmp::Ordering::*;
2251 ///
2252 /// let mut x = Float::from(PI);
2253 /// assert_eq!(x.mul_prec_assign_ref(&Float::from(E), 5), Less);
2254 /// assert_eq!(x.to_string(), "8.5");
2255 ///
2256 /// let mut x = Float::from(PI);
2257 /// assert_eq!(x.mul_prec_assign_ref(&Float::from(E), 20), Less);
2258 /// assert_eq!(x.to_string(), "8.53973");
2259 /// ```
2260 #[inline]
2261 pub fn mul_prec_assign_ref(&mut self, other: &Float, prec: u64) -> Ordering {
2262 self.mul_prec_round_assign_ref(other, prec, Nearest)
2263 }
2264
2265 /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result with the specified
2266 /// rounding mode. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] is
2267 /// returned, indicating whether the rounded product is less than, equal to, or greater than the
2268 /// exact product. Although `NaN`s are not comparable to any [`Float`], whenever this function
2269 /// sets the [`Float`] to `NaN` it also returns `Equal`.
2270 ///
2271 /// The precision of the output is the maximum of the precision of the inputs. See
2272 /// [`RoundingMode`] for a description of the possible rounding modes.
2273 ///
2274 /// $$
2275 /// x \gets xy+\varepsilon.
2276 /// $$
2277 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2278 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
2279 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs.
2280 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
2281 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs.
2282 ///
2283 /// If the output has a precision, it is the maximum of the precisions of the inputs.
2284 ///
2285 /// See the [`Float::mul_round`] documentation for information on special cases, overflow, and
2286 /// underflow.
2287 ///
2288 /// If you want to specify an output precision, consider using [`Float::mul_prec_round_assign`]
2289 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `*=`
2290 /// instead.
2291 ///
2292 /// # Worst-case complexity
2293 /// $T(n) = O(n \log n \log\log n)$
2294 ///
2295 /// $M(n) = O(n \log n)$
2296 ///
2297 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2298 /// other.significant_bits())`.
2299 ///
2300 /// # Panics
2301 /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to
2302 /// represent the output.
2303 ///
2304 /// # Examples
2305 /// ```
2306 /// use core::f64::consts::{E, PI};
2307 /// use malachite_base::rounding_modes::RoundingMode::*;
2308 /// use malachite_float::Float;
2309 /// use std::cmp::Ordering::*;
2310 ///
2311 /// let mut x = Float::from(PI);
2312 /// assert_eq!(x.mul_round_assign(Float::from(E), Floor), Less);
2313 /// assert_eq!(x.to_string(), "8.539734222673566");
2314 ///
2315 /// let mut x = Float::from(PI);
2316 /// assert_eq!(x.mul_round_assign(Float::from(E), Ceiling), Greater);
2317 /// assert_eq!(x.to_string(), "8.539734222673568");
2318 ///
2319 /// let mut x = Float::from(PI);
2320 /// assert_eq!(x.mul_round_assign(Float::from(E), Nearest), Less);
2321 /// assert_eq!(x.to_string(), "8.539734222673566");
2322 /// ```
2323 #[inline]
2324 pub fn mul_round_assign(&mut self, other: Float, rm: RoundingMode) -> Ordering {
2325 let prec = max(self.significant_bits(), other.significant_bits());
2326 self.mul_prec_round_assign(other, prec, rm)
2327 }
2328
2329 /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result with the specified
2330 /// rounding mode. The [`Float`] on the right-hand side is taken by reference. An [`Ordering`]
2331 /// is returned, indicating whether the rounded product is less than, equal to, or greater than
2332 /// the exact product. Although `NaN`s are not comparable to any [`Float`], whenever this
2333 /// function sets the [`Float`] to `NaN` it also returns `Equal`.
2334 ///
2335 /// The precision of the output is the maximum of the precision of the inputs. See
2336 /// [`RoundingMode`] for a description of the possible rounding modes.
2337 ///
2338 /// $$
2339 /// x \gets xy+\varepsilon.
2340 /// $$
2341 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2342 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
2343 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs.
2344 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
2345 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs.
2346 ///
2347 /// If the output has a precision, it is the maximum of the precisions of the inputs.
2348 ///
2349 /// See the [`Float::mul_round`] documentation for information on special cases, overflow, and
2350 /// underflow.
2351 ///
2352 /// If you want to specify an output precision, consider using
2353 /// [`Float::mul_prec_round_assign_ref`] instead. If you know you'll be using the `Nearest`
2354 /// rounding mode, consider using `*=` instead.
2355 ///
2356 /// # Worst-case complexity
2357 /// $T(n) = O(n \log n \log\log n)$
2358 ///
2359 /// $M(n) = O(n \log n)$
2360 ///
2361 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2362 /// other.significant_bits())`.
2363 ///
2364 /// # Panics
2365 /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to
2366 /// represent the output.
2367 ///
2368 /// # Examples
2369 /// ```
2370 /// use core::f64::consts::{E, PI};
2371 /// use malachite_base::rounding_modes::RoundingMode::*;
2372 /// use malachite_float::Float;
2373 /// use std::cmp::Ordering::*;
2374 ///
2375 /// let mut x = Float::from(PI);
2376 /// assert_eq!(x.mul_round_assign_ref(&Float::from(E), Floor), Less);
2377 /// assert_eq!(x.to_string(), "8.539734222673566");
2378 ///
2379 /// let mut x = Float::from(PI);
2380 /// assert_eq!(x.mul_round_assign_ref(&Float::from(E), Ceiling), Greater);
2381 /// assert_eq!(x.to_string(), "8.539734222673568");
2382 ///
2383 /// let mut x = Float::from(PI);
2384 /// assert_eq!(x.mul_round_assign_ref(&Float::from(E), Nearest), Less);
2385 /// assert_eq!(x.to_string(), "8.539734222673566");
2386 /// ```
2387 #[inline]
2388 pub fn mul_round_assign_ref(&mut self, other: &Float, rm: RoundingMode) -> Ordering {
2389 let prec = max(self.significant_bits(), other.significant_bits());
2390 self.mul_prec_round_assign_ref(other, prec, rm)
2391 }
2392
2393 /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the specified precision and
2394 /// with the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by
2395 /// value. An [`Ordering`] is also returned, indicating whether the rounded product is less
2396 /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any
2397 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
2398 ///
2399 /// See [`RoundingMode`] for a description of the possible rounding modes.
2400 ///
2401 /// $$
2402 /// f(x,y,p,m) = xy+\varepsilon.
2403 /// $$
2404 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2405 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
2406 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
2407 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
2408 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
2409 ///
2410 /// If the output has a precision, it is `prec`.
2411 ///
2412 /// Special cases:
2413 /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=\text{NaN}$
2414 /// - $f(\infty,x,p,m)=\infty$ if $x>0$
2415 /// - $f(\infty,x,p,m)=-\infty$ if $x<0$
2416 /// - $f(-\infty,x,p,m)=-\infty$ if $x>0$
2417 /// - $f(-\infty,x,p,m)=\infty$ if $x<0$
2418 /// - $f(0.0,x,p,m)=0.0$ if $x\geq0$
2419 /// - $f(0.0,x,p,m)=-0.0$ if $x<0$
2420 /// - $f(-0.0,x,p,m)=-0.0$ if $x\geq0$
2421 /// - $f(-0.0,x,p,m)=0.0$ if $x<0$
2422 ///
2423 /// If you know you'll be using `Nearest`, consider using [`Float::mul_rational_prec`] instead.
2424 /// If you know that your target precision is the precision of the [`Float`] input, consider
2425 /// using [`Float::mul_rational_round`] instead. If both of these things are true, consider
2426 /// using `*` instead.
2427 ///
2428 /// # Worst-case complexity
2429 /// $T(n) = O(n \log n \log\log n)$
2430 ///
2431 /// $M(n) = O(n \log n)$
2432 ///
2433 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2434 /// other.significant_bits(), prec)`.
2435 ///
2436 /// # Panics
2437 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
2438 ///
2439 /// # Examples
2440 /// ```
2441 /// use core::f64::consts::PI;
2442 /// use malachite_base::rounding_modes::RoundingMode::*;
2443 /// use malachite_float::Float;
2444 /// use malachite_q::Rational;
2445 /// use std::cmp::Ordering::*;
2446 ///
2447 /// let (product, o) =
2448 /// Float::from(PI).mul_rational_prec_round(Rational::from_unsigneds(1u8, 3), 5, Floor);
2449 /// assert_eq!(product.to_string(), "1.0");
2450 /// assert_eq!(o, Less);
2451 ///
2452 /// let (product, o) =
2453 /// Float::from(PI).mul_rational_prec_round(Rational::from_unsigneds(1u8, 3), 5, Ceiling);
2454 /// assert_eq!(product.to_string(), "1.06");
2455 /// assert_eq!(o, Greater);
2456 ///
2457 /// let (product, o) =
2458 /// Float::from(PI).mul_rational_prec_round(Rational::from_unsigneds(1u8, 3), 5, Nearest);
2459 /// assert_eq!(product.to_string(), "1.06");
2460 /// assert_eq!(o, Greater);
2461 ///
2462 /// let (product, o) =
2463 /// Float::from(PI).mul_rational_prec_round(Rational::from_unsigneds(1u8, 3), 20, Floor);
2464 /// assert_eq!(product.to_string(), "1.047197");
2465 /// assert_eq!(o, Less);
2466 ///
2467 /// let (product, o) =
2468 /// Float::from(PI).mul_rational_prec_round(Rational::from_unsigneds(1u8, 3), 20, Ceiling);
2469 /// assert_eq!(product.to_string(), "1.047199");
2470 /// assert_eq!(o, Greater);
2471 ///
2472 /// let (product, o) =
2473 /// Float::from(PI).mul_rational_prec_round(Rational::from_unsigneds(1u8, 3), 20, Nearest);
2474 /// assert_eq!(product.to_string(), "1.047197");
2475 /// assert_eq!(o, Less);
2476 /// ```
2477 #[inline]
2478 pub fn mul_rational_prec_round(
2479 mut self,
2480 other: Rational,
2481 prec: u64,
2482 rm: RoundingMode,
2483 ) -> (Float, Ordering) {
2484 let o = self.mul_rational_prec_round_assign(other, prec, rm);
2485 (self, o)
2486 }
2487
2488 /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the specified precision and
2489 /// with the specified rounding mode. The [`Float`] is taken by value and the [`Rational`] by
2490 /// reference. An [`Ordering`] is also returned, indicating whether the rounded product is less
2491 /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any
2492 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
2493 ///
2494 /// See [`RoundingMode`] for a description of the possible rounding modes.
2495 ///
2496 /// $$
2497 /// f(x,y,p,m) = xy+\varepsilon.
2498 /// $$
2499 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2500 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
2501 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
2502 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
2503 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
2504 ///
2505 /// If the output has a precision, it is `prec`.
2506 ///
2507 /// Special cases:
2508 /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=\text{NaN}$
2509 /// - $f(\infty,x,p,m)=\infty$ if $x>0$
2510 /// - $f(\infty,x,p,m)=-\infty$ if $x<0$
2511 /// - $f(-\infty,x,p,m)=-\infty$ if $x>0$
2512 /// - $f(-\infty,x,p,m)=\infty$ if $x<0$
2513 /// - $f(0.0,x,p,m)=0.0$ if $x\geq0$
2514 /// - $f(0.0,x,p,m)=-0.0$ if $x<0$
2515 /// - $f(-0.0,x,p,m)=-0.0$ if $x\geq0$
2516 /// - $f(-0.0,x,p,m)=0.0$ if $x<0$
2517 ///
2518 /// If you know you'll be using `Nearest`, consider using [`Float::mul_rational_prec_val_ref`]
2519 /// instead. If you know that your target precision is the precision of the [`Float`] input,
2520 /// consider using [`Float::mul_rational_round_val_ref`] instead. If both of these things are
2521 /// true, consider using `*` instead.
2522 ///
2523 /// # Worst-case complexity
2524 /// $T(n) = O(n \log n \log\log n)$
2525 ///
2526 /// $M(n) = O(n \log n)$
2527 ///
2528 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2529 /// other.significant_bits(), prec)`.
2530 ///
2531 /// # Panics
2532 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
2533 ///
2534 /// # Examples
2535 /// ```
2536 /// use core::f64::consts::PI;
2537 /// use malachite_base::rounding_modes::RoundingMode::*;
2538 /// use malachite_float::Float;
2539 /// use malachite_q::Rational;
2540 /// use std::cmp::Ordering::*;
2541 ///
2542 /// let (product, o) = Float::from(PI).mul_rational_prec_round_val_ref(
2543 /// &Rational::from_unsigneds(1u8, 3),
2544 /// 5,
2545 /// Floor,
2546 /// );
2547 /// assert_eq!(product.to_string(), "1.0");
2548 /// assert_eq!(o, Less);
2549 ///
2550 /// let (product, o) = Float::from(PI).mul_rational_prec_round_val_ref(
2551 /// &Rational::from_unsigneds(1u8, 3),
2552 /// 5,
2553 /// Ceiling,
2554 /// );
2555 /// assert_eq!(product.to_string(), "1.06");
2556 /// assert_eq!(o, Greater);
2557 ///
2558 /// let (product, o) = Float::from(PI).mul_rational_prec_round_val_ref(
2559 /// &Rational::from_unsigneds(1u8, 3),
2560 /// 5,
2561 /// Nearest,
2562 /// );
2563 /// assert_eq!(product.to_string(), "1.06");
2564 /// assert_eq!(o, Greater);
2565 ///
2566 /// let (product, o) = Float::from(PI).mul_rational_prec_round_val_ref(
2567 /// &Rational::from_unsigneds(1u8, 3),
2568 /// 20,
2569 /// Floor,
2570 /// );
2571 /// assert_eq!(product.to_string(), "1.047197");
2572 /// assert_eq!(o, Less);
2573 ///
2574 /// let (product, o) = Float::from(PI).mul_rational_prec_round_val_ref(
2575 /// &Rational::from_unsigneds(1u8, 3),
2576 /// 20,
2577 /// Ceiling,
2578 /// );
2579 /// assert_eq!(product.to_string(), "1.047199");
2580 /// assert_eq!(o, Greater);
2581 ///
2582 /// let (product, o) = Float::from(PI).mul_rational_prec_round_val_ref(
2583 /// &Rational::from_unsigneds(1u8, 3),
2584 /// 20,
2585 /// Nearest,
2586 /// );
2587 /// assert_eq!(product.to_string(), "1.047197");
2588 /// assert_eq!(o, Less);
2589 /// ```
2590 #[inline]
2591 pub fn mul_rational_prec_round_val_ref(
2592 mut self,
2593 other: &Rational,
2594 prec: u64,
2595 rm: RoundingMode,
2596 ) -> (Float, Ordering) {
2597 let o = self.mul_rational_prec_round_assign_ref(other, prec, rm);
2598 (self, o)
2599 }
2600
2601 /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the specified precision and
2602 /// with the specified rounding mode. The [`Float`] is taken by reference and the [`Rational`]
2603 /// by value. An [`Ordering`] is also returned, indicating whether the rounded product is less
2604 /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any
2605 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
2606 ///
2607 /// See [`RoundingMode`] for a description of the possible rounding modes.
2608 ///
2609 /// $$
2610 /// f(x,y,p,m) = xy+\varepsilon.
2611 /// $$
2612 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2613 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
2614 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
2615 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
2616 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
2617 ///
2618 /// If the output has a precision, it is `prec`.
2619 ///
2620 /// Special cases:
2621 /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=\text{NaN}$
2622 /// - $f(\infty,x,p,m)=\infty$ if $x>0$
2623 /// - $f(\infty,x,p,m)=-\infty$ if $x<0$
2624 /// - $f(-\infty,x,p,m)=-\infty$ if $x>0$
2625 /// - $f(-\infty,x,p,m)=\infty$ if $x<0$
2626 /// - $f(0.0,x,p,m)=0.0$ if $x\geq0$
2627 /// - $f(0.0,x,p,m)=-0.0$ if $x<0$
2628 /// - $f(-0.0,x,p,m)=-0.0$ if $x\geq0$
2629 /// - $f(-0.0,x,p,m)=0.0$ if $x<0$
2630 ///
2631 /// If you know you'll be using `Nearest`, consider using [`Float::mul_rational_prec_ref_val`]
2632 /// instead. If you know that your target precision is the precision of the [`Float`] input,
2633 /// consider using [`Float::mul_rational_round_ref_val`] instead. If both of these things are
2634 /// true, consider using `*` instead.
2635 ///
2636 /// # Worst-case complexity
2637 /// $T(n) = O(n \log n \log\log n)$
2638 ///
2639 /// $M(n) = O(n \log n)$
2640 ///
2641 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2642 /// other.significant_bits(), prec)`.
2643 ///
2644 /// # Panics
2645 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
2646 ///
2647 /// # Examples
2648 /// ```
2649 /// use core::f64::consts::PI;
2650 /// use malachite_base::rounding_modes::RoundingMode::*;
2651 /// use malachite_float::Float;
2652 /// use malachite_q::Rational;
2653 /// use std::cmp::Ordering::*;
2654 ///
2655 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_val(
2656 /// Rational::from_unsigneds(1u8, 3),
2657 /// 5,
2658 /// Floor,
2659 /// );
2660 /// assert_eq!(product.to_string(), "1.0");
2661 /// assert_eq!(o, Less);
2662 ///
2663 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_val(
2664 /// Rational::from_unsigneds(1u8, 3),
2665 /// 5,
2666 /// Ceiling,
2667 /// );
2668 /// assert_eq!(product.to_string(), "1.06");
2669 /// assert_eq!(o, Greater);
2670 ///
2671 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_val(
2672 /// Rational::from_unsigneds(1u8, 3),
2673 /// 5,
2674 /// Nearest,
2675 /// );
2676 /// assert_eq!(product.to_string(), "1.06");
2677 /// assert_eq!(o, Greater);
2678 ///
2679 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_val(
2680 /// Rational::from_unsigneds(1u8, 3),
2681 /// 20,
2682 /// Floor,
2683 /// );
2684 /// assert_eq!(product.to_string(), "1.047197");
2685 /// assert_eq!(o, Less);
2686 ///
2687 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_val(
2688 /// Rational::from_unsigneds(1u8, 3),
2689 /// 20,
2690 /// Ceiling,
2691 /// );
2692 /// assert_eq!(product.to_string(), "1.047199");
2693 /// assert_eq!(o, Greater);
2694 ///
2695 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_val(
2696 /// Rational::from_unsigneds(1u8, 3),
2697 /// 20,
2698 /// Nearest,
2699 /// );
2700 /// assert_eq!(product.to_string(), "1.047197");
2701 /// assert_eq!(o, Less);
2702 /// ```
2703 #[inline]
2704 pub fn mul_rational_prec_round_ref_val(
2705 &self,
2706 other: Rational,
2707 prec: u64,
2708 rm: RoundingMode,
2709 ) -> (Float, Ordering) {
2710 if max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD {
2711 mul_rational_prec_round_naive_ref_val(self, other, prec, rm)
2712 } else {
2713 mul_rational_prec_round_direct_ref_val(self, other, prec, rm)
2714 }
2715 }
2716
2717 /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the specified precision and
2718 /// with the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by
2719 /// reference. An [`Ordering`] is also returned, indicating whether the rounded product is less
2720 /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any
2721 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
2722 ///
2723 /// See [`RoundingMode`] for a description of the possible rounding modes.
2724 ///
2725 /// $$
2726 /// f(x,y,p,m) = xy+\varepsilon.
2727 /// $$
2728 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2729 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
2730 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
2731 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
2732 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
2733 ///
2734 /// If the output has a precision, it is `prec`.
2735 ///
2736 /// Special cases:
2737 /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=\text{NaN}$
2738 /// - $f(\infty,x,p,m)=\infty$ if $x>0$
2739 /// - $f(\infty,x,p,m)=-\infty$ if $x<0$
2740 /// - $f(-\infty,x,p,m)=-\infty$ if $x>0$
2741 /// - $f(-\infty,x,p,m)=\infty$ if $x<0$
2742 /// - $f(0.0,x,p,m)=0.0$ if $x\geq0$
2743 /// - $f(0.0,x,p,m)=-0.0$ if $x<0$
2744 /// - $f(-0.0,x,p,m)=-0.0$ if $x\geq0$
2745 /// - $f(-0.0,x,p,m)=0.0$ if $x<0$
2746 ///
2747 /// If you know you'll be using `Nearest`, consider using [`Float::mul_rational_prec_ref_ref`]
2748 /// instead. If you know that your target precision is the precision of the [`Float`] input,
2749 /// consider using [`Float::mul_rational_round_ref_ref`] instead. If both of these things are
2750 /// true, consider using `*` instead.
2751 ///
2752 /// # Worst-case complexity
2753 /// $T(n) = O(n \log n \log\log n)$
2754 ///
2755 /// $M(n) = O(n \log n)$
2756 ///
2757 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2758 /// other.significant_bits(), prec)`.
2759 ///
2760 /// # Panics
2761 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
2762 ///
2763 /// # Examples
2764 /// ```
2765 /// use core::f64::consts::PI;
2766 /// use malachite_base::rounding_modes::RoundingMode::*;
2767 /// use malachite_float::Float;
2768 /// use malachite_q::Rational;
2769 /// use std::cmp::Ordering::*;
2770 ///
2771 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_ref(
2772 /// &Rational::from_unsigneds(1u8, 3),
2773 /// 5,
2774 /// Floor,
2775 /// );
2776 /// assert_eq!(product.to_string(), "1.0");
2777 /// assert_eq!(o, Less);
2778 ///
2779 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_ref(
2780 /// &Rational::from_unsigneds(1u8, 3),
2781 /// 5,
2782 /// Ceiling,
2783 /// );
2784 /// assert_eq!(product.to_string(), "1.06");
2785 /// assert_eq!(o, Greater);
2786 ///
2787 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_ref(
2788 /// &Rational::from_unsigneds(1u8, 3),
2789 /// 5,
2790 /// Nearest,
2791 /// );
2792 /// assert_eq!(product.to_string(), "1.06");
2793 /// assert_eq!(o, Greater);
2794 ///
2795 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_ref(
2796 /// &Rational::from_unsigneds(1u8, 3),
2797 /// 20,
2798 /// Floor,
2799 /// );
2800 /// assert_eq!(product.to_string(), "1.047197");
2801 /// assert_eq!(o, Less);
2802 ///
2803 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_ref(
2804 /// &Rational::from_unsigneds(1u8, 3),
2805 /// 20,
2806 /// Ceiling,
2807 /// );
2808 /// assert_eq!(product.to_string(), "1.047199");
2809 /// assert_eq!(o, Greater);
2810 ///
2811 /// let (product, o) = Float::from(PI).mul_rational_prec_round_ref_ref(
2812 /// &Rational::from_unsigneds(1u8, 3),
2813 /// 20,
2814 /// Nearest,
2815 /// );
2816 /// assert_eq!(product.to_string(), "1.047197");
2817 /// assert_eq!(o, Less);
2818 /// ```
2819 #[inline]
2820 pub fn mul_rational_prec_round_ref_ref(
2821 &self,
2822 other: &Rational,
2823 prec: u64,
2824 rm: RoundingMode,
2825 ) -> (Float, Ordering) {
2826 if max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD {
2827 mul_rational_prec_round_naive_ref_ref(self, other, prec, rm)
2828 } else {
2829 mul_rational_prec_round_direct_ref_ref(self, other, prec, rm)
2830 }
2831 }
2832
2833 /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the nearest value of the
2834 /// specified precision. The [`Float`] and the [`Rational`] are both are taken by value. An
2835 /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal
2836 /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`],
2837 /// whenever this function returns a `NaN` it also returns `Equal`.
2838 ///
2839 /// If the product is equidistant from two [`Float`]s with the specified precision, the
2840 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2841 /// description of the `Nearest` rounding mode.
2842 ///
2843 /// $$
2844 /// f(x,y,p) = xy+\varepsilon.
2845 /// $$
2846 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2847 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
2848 ///
2849 /// If the output has a precision, it is `prec`.
2850 ///
2851 /// Special cases:
2852 /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=\text{NaN}$
2853 /// - $f(\infty,x,p)=\infty$ if $x>0$
2854 /// - $f(\infty,x,p)=-\infty$ if $x<0$
2855 /// - $f(-\infty,x,p)=-\infty$ if $x>0$
2856 /// - $f(-\infty,x,p)=\infty$ if $x<0$
2857 /// - $f(0.0,x,p)=0.0$ if $x\geq0$
2858 /// - $f(0.0,x,p)=-0.0$ if $x<0$
2859 /// - $f(-0.0,x,p)=-0.0$ if $x\geq0$
2860 /// - $f(-0.0,x,p)=0.0$ if $x<0$
2861 ///
2862 /// If you want to use a rounding mode other than `Nearest`, consider using
2863 /// [`Float::mul_rational_prec_round`] instead. If you know that your target precision is the
2864 /// precision of the [`Float`] input, consider using `*` instead.
2865 ///
2866 /// # Worst-case complexity
2867 /// $T(n) = O(n \log n \log\log n)$
2868 ///
2869 /// $M(n) = O(n \log n)$
2870 ///
2871 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2872 /// other.significant_bits(), prec)`.
2873 ///
2874 /// # Examples
2875 /// ```
2876 /// use core::f64::consts::PI;
2877 /// use malachite_base::num::conversion::traits::ExactFrom;
2878 /// use malachite_float::Float;
2879 /// use malachite_q::Rational;
2880 /// use std::cmp::Ordering::*;
2881 ///
2882 /// let (product, o) = Float::from(PI).mul_rational_prec(Rational::exact_from(1.5), 5);
2883 /// assert_eq!(product.to_string(), "4.8");
2884 /// assert_eq!(o, Greater);
2885 ///
2886 /// let (product, o) = Float::from(PI).mul_rational_prec(Rational::exact_from(1.5), 20);
2887 /// assert_eq!(product.to_string(), "4.712387");
2888 /// assert_eq!(o, Less);
2889 /// ```
2890 #[inline]
2891 pub fn mul_rational_prec(self, other: Rational, prec: u64) -> (Float, Ordering) {
2892 self.mul_rational_prec_round(other, prec, Nearest)
2893 }
2894
2895 /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the nearest value of the
2896 /// specified precision. The [`Float`] is taken by value and the [`Rational`] by reference. An
2897 /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal
2898 /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`],
2899 /// whenever this function returns a `NaN` it also returns `Equal`.
2900 ///
2901 /// If the product is equidistant from two [`Float`]s with the specified precision, the
2902 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2903 /// description of the `Nearest` rounding mode.
2904 ///
2905 /// $$
2906 /// f(x,y,p) = xy+\varepsilon.
2907 /// $$
2908 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2909 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
2910 ///
2911 /// If the output has a precision, it is `prec`.
2912 ///
2913 /// Special cases:
2914 /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=\text{NaN}$
2915 /// - $f(\infty,x,p)=\infty$ if $x>0$
2916 /// - $f(\infty,x,p)=-\infty$ if $x<0$
2917 /// - $f(-\infty,x,p)=-\infty$ if $x>0$
2918 /// - $f(-\infty,x,p)=\infty$ if $x<0$
2919 /// - $f(0.0,x,p)=0.0$ if $x\geq0$
2920 /// - $f(0.0,x,p)=-0.0$ if $x<0$
2921 /// - $f(-0.0,x,p)=-0.0$ if $x\geq0$
2922 /// - $f(-0.0,x,p)=0.0$ if $x<0$
2923 ///
2924 /// If you want to use a rounding mode other than `Nearest`, consider using
2925 /// [`Float::mul_rational_prec_round_val_ref`] instead. If you know that your target precision
2926 /// is the precision of the [`Float`] input, consider using `*` instead.
2927 ///
2928 /// # Worst-case complexity
2929 /// $T(n) = O(n \log n \log\log n)$
2930 ///
2931 /// $M(n) = O(n \log n)$
2932 ///
2933 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2934 /// other.significant_bits(), prec)`.
2935 ///
2936 /// # Examples
2937 /// ```
2938 /// use core::f64::consts::PI;
2939 /// use malachite_base::num::conversion::traits::ExactFrom;
2940 /// use malachite_float::Float;
2941 /// use malachite_q::Rational;
2942 /// use std::cmp::Ordering::*;
2943 ///
2944 /// let (product, o) = Float::from(PI).mul_rational_prec_val_ref(&Rational::exact_from(1.5), 5);
2945 /// assert_eq!(product.to_string(), "4.8");
2946 /// assert_eq!(o, Greater);
2947 ///
2948 /// let (product, o) =
2949 /// Float::from(PI).mul_rational_prec_val_ref(&Rational::exact_from(1.5), 20);
2950 /// assert_eq!(product.to_string(), "4.712387");
2951 /// assert_eq!(o, Less);
2952 /// ```
2953 #[inline]
2954 pub fn mul_rational_prec_val_ref(self, other: &Rational, prec: u64) -> (Float, Ordering) {
2955 self.mul_rational_prec_round_val_ref(other, prec, Nearest)
2956 }
2957
2958 /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the nearest value of the
2959 /// specified precision. The [`Float`] is taken by reference and the [`Rational`] by value. An
2960 /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal
2961 /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`],
2962 /// whenever this function returns a `NaN` it also returns `Equal`.
2963 ///
2964 /// If the product is equidistant from two [`Float`]s with the specified precision, the
2965 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2966 /// description of the `Nearest` rounding mode.
2967 ///
2968 /// $$
2969 /// f(x,y,p) = xy+\varepsilon.
2970 /// $$
2971 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
2972 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
2973 ///
2974 /// If the output has a precision, it is `prec`.
2975 ///
2976 /// Special cases:
2977 /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=\text{NaN}$
2978 /// - $f(\infty,x,p)=\infty$ if $x>0$
2979 /// - $f(\infty,x,p)=-\infty$ if $x<0$
2980 /// - $f(-\infty,x,p)=-\infty$ if $x>0$
2981 /// - $f(-\infty,x,p)=\infty$ if $x<0$
2982 /// - $f(0.0,x,p)=0.0$ if $x\geq0$
2983 /// - $f(0.0,x,p)=-0.0$ if $x<0$
2984 /// - $f(-0.0,x,p)=-0.0$ if $x\geq0$
2985 /// - $f(-0.0,x,p)=0.0$ if $x<0$
2986 ///
2987 /// If you want to use a rounding mode other than `Nearest`, consider using
2988 /// [`Float::mul_rational_prec_round_ref_val`] instead. If you know that your target precision
2989 /// is the precision of the [`Float`] input, consider using `*` instead.
2990 ///
2991 /// # Worst-case complexity
2992 /// $T(n) = O(n \log n \log\log n)$
2993 ///
2994 /// $M(n) = O(n \log n)$
2995 ///
2996 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2997 /// other.significant_bits(), prec)`.
2998 ///
2999 /// # Examples
3000 /// ```
3001 /// use core::f64::consts::PI;
3002 /// use malachite_base::num::conversion::traits::ExactFrom;
3003 /// use malachite_float::Float;
3004 /// use malachite_q::Rational;
3005 /// use std::cmp::Ordering::*;
3006 ///
3007 /// let (product, o) = Float::from(PI).mul_rational_prec_ref_val(Rational::exact_from(1.5), 5);
3008 /// assert_eq!(product.to_string(), "4.8");
3009 /// assert_eq!(o, Greater);
3010 ///
3011 /// let (product, o) = Float::from(PI).mul_rational_prec_ref_val(Rational::exact_from(1.5), 20);
3012 /// assert_eq!(product.to_string(), "4.712387");
3013 /// assert_eq!(o, Less);
3014 /// ```
3015 #[inline]
3016 pub fn mul_rational_prec_ref_val(&self, other: Rational, prec: u64) -> (Float, Ordering) {
3017 self.mul_rational_prec_round_ref_val(other, prec, Nearest)
3018 }
3019
3020 /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the nearest value of the
3021 /// specified precision. The [`Float`] and the [`Rational`] are both are taken by reference. An
3022 /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal
3023 /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`],
3024 /// whenever this function returns a `NaN` it also returns `Equal`.
3025 ///
3026 /// If the product is equidistant from two [`Float`]s with the specified precision, the
3027 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
3028 /// description of the `Nearest` rounding mode.
3029 ///
3030 /// $$
3031 /// f(x,y,p) = xy+\varepsilon.
3032 /// $$
3033 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3034 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
3035 ///
3036 /// If the output has a precision, it is `prec`.
3037 ///
3038 /// Special cases:
3039 /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=\text{NaN}$
3040 /// - $f(\infty,x,p)=\infty$ if $x>0$
3041 /// - $f(\infty,x,p)=-\infty$ if $x<0$
3042 /// - $f(-\infty,x,p)=-\infty$ if $x>0$
3043 /// - $f(-\infty,x,p)=\infty$ if $x<0$
3044 /// - $f(0.0,x,p)=0.0$ if $x\geq0$
3045 /// - $f(0.0,x,p)=-0.0$ if $x<0$
3046 /// - $f(-0.0,x,p)=-0.0$ if $x\geq0$
3047 /// - $f(-0.0,x,p)=0.0$ if $x<0$
3048 ///
3049 /// If you want to use a rounding mode other than `Nearest`, consider using
3050 /// [`Float::mul_rational_prec_round_ref_ref`] instead. If you know that your target precision
3051 /// is the precision of the [`Float`] input, consider using `*` instead.
3052 ///
3053 /// # Worst-case complexity
3054 /// $T(n) = O(n \log n \log\log n)$
3055 ///
3056 /// $M(n) = O(n \log n)$
3057 ///
3058 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3059 /// other.significant_bits(), prec)`.
3060 ///
3061 /// # Examples
3062 /// ```
3063 /// use core::f64::consts::PI;
3064 /// use malachite_base::num::conversion::traits::ExactFrom;
3065 /// use malachite_float::Float;
3066 /// use malachite_q::Rational;
3067 /// use std::cmp::Ordering::*;
3068 ///
3069 /// let (product, o) = Float::from(PI).mul_rational_prec_ref_ref(&Rational::exact_from(1.5), 5);
3070 /// assert_eq!(product.to_string(), "4.8");
3071 /// assert_eq!(o, Greater);
3072 ///
3073 /// let (product, o) =
3074 /// Float::from(PI).mul_rational_prec_ref_ref(&Rational::exact_from(1.5), 20);
3075 /// assert_eq!(product.to_string(), "4.712387");
3076 /// assert_eq!(o, Less);
3077 /// ```
3078 #[inline]
3079 pub fn mul_rational_prec_ref_ref(&self, other: &Rational, prec: u64) -> (Float, Ordering) {
3080 self.mul_rational_prec_round_ref_ref(other, prec, Nearest)
3081 }
3082
3083 /// Multiplies a [`Float`] by a [`Rational`], rounding the result with the specified rounding
3084 /// mode. The [`Float`] and the [`Rational`] are both are taken by value. An [`Ordering`] is
3085 /// also returned, indicating whether the rounded product is less than, equal to, or greater
3086 /// than the exact product. Although `NaN`s are not comparable to any [`Float`], whenever this
3087 /// function returns a `NaN` it also returns `Equal`.
3088 ///
3089 /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`]
3090 /// for a description of the possible rounding modes.
3091 ///
3092 /// $$
3093 /// f(x,y,m) = xy+\varepsilon.
3094 /// $$
3095 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3096 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
3097 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`].
3098 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
3099 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`].
3100 ///
3101 /// If the output has a precision, it is the precision of the [`Float`] input.
3102 ///
3103 /// Special cases:
3104 /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=\text{NaN}$
3105 /// - $f(\infty,x,m)=\infty$ if $x>0$
3106 /// - $f(\infty,x,m)=-\infty$ if $x<0$
3107 /// - $f(-\infty,x,m)=-\infty$ if $x>0$
3108 /// - $f(-\infty,x,m)=\infty$ if $x<0$
3109 /// - $f(0.0,x,m)=0.0$ if $x\geq0$
3110 /// - $f(0.0,x,m)=-0.0$ if $x<0$
3111 /// - $f(-0.0,x,m)=-0.0$ if $x\geq0$
3112 /// - $f(-0.0,x,m)=0.0$ if $x<0$
3113 ///
3114 /// If you want to specify an output precision, consider using
3115 /// [`Float::mul_rational_prec_round`] instead. If you know you'll be using the `Nearest`
3116 /// rounding mode, consider using `*` instead.
3117 ///
3118 /// # Worst-case complexity
3119 /// $T(n) = O(n \log n \log\log n)$
3120 ///
3121 /// $M(n) = O(n \log n)$
3122 ///
3123 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3124 /// other.significant_bits())`.
3125 ///
3126 /// # Panics
3127 /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to
3128 /// represent the output.
3129 ///
3130 /// # Examples
3131 /// ```
3132 /// use core::f64::consts::PI;
3133 /// use malachite_base::rounding_modes::RoundingMode::*;
3134 /// use malachite_float::Float;
3135 /// use malachite_q::Rational;
3136 /// use std::cmp::Ordering::*;
3137 ///
3138 /// let (product, o) =
3139 /// Float::from(PI).mul_rational_round(Rational::from_unsigneds(1u8, 3), Floor);
3140 /// assert_eq!(product.to_string(), "1.047197551196597");
3141 /// assert_eq!(o, Less);
3142 ///
3143 /// let (product, o) =
3144 /// Float::from(PI).mul_rational_round(Rational::from_unsigneds(1u8, 3), Ceiling);
3145 /// assert_eq!(product.to_string(), "1.047197551196598");
3146 /// assert_eq!(o, Greater);
3147 ///
3148 /// let (product, o) =
3149 /// Float::from(PI).mul_rational_round(Rational::from_unsigneds(1u8, 3), Nearest);
3150 /// assert_eq!(product.to_string(), "1.047197551196598");
3151 /// assert_eq!(o, Greater);
3152 /// ```
3153 #[inline]
3154 pub fn mul_rational_round(self, other: Rational, rm: RoundingMode) -> (Float, Ordering) {
3155 let prec = self.significant_bits();
3156 self.mul_rational_prec_round(other, prec, rm)
3157 }
3158
3159 /// Multiplies a [`Float`] by a [`Rational`], rounding the result with the specified rounding
3160 /// mode. The [`Float`] is taken by value and the [`Rational`] by reference. An [`Ordering`] is
3161 /// also returned, indicating whether the rounded product is less than, equal to, or greater
3162 /// than the exact product. Although `NaN`s are not comparable to any [`Float`], whenever this
3163 /// function returns a `NaN` it also returns `Equal`.
3164 ///
3165 /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`]
3166 /// for a description of the possible rounding modes.
3167 ///
3168 /// $$
3169 /// f(x,y,m) = xy+\varepsilon.
3170 /// $$
3171 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3172 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
3173 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`].
3174 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
3175 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`].
3176 ///
3177 /// If the output has a precision, it is the precision of the [`Float`] input.
3178 ///
3179 /// Special cases:
3180 /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=\text{NaN}$
3181 /// - $f(\infty,x,m)=\infty$ if $x>0$
3182 /// - $f(\infty,x,m)=-\infty$ if $x<0$
3183 /// - $f(-\infty,x,m)=-\infty$ if $x>0$
3184 /// - $f(-\infty,x,m)=\infty$ if $x<0$
3185 /// - $f(0.0,x,m)=0.0$ if $x\geq0$
3186 /// - $f(0.0,x,m)=-0.0$ if $x<0$
3187 /// - $f(-0.0,x,m)=-0.0$ if $x\geq0$
3188 /// - $f(-0.0,x,m)=0.0$ if $x<0$
3189 ///
3190 /// If you want to specify an output precision, consider using
3191 /// [`Float::mul_rational_prec_round_val_ref`] instead. If you know you'll be using the
3192 /// `Nearest` rounding mode, consider using `*` instead.
3193 ///
3194 /// # Worst-case complexity
3195 /// $T(n) = O(n \log n \log\log n)$
3196 ///
3197 /// $M(n) = O(n \log n)$
3198 ///
3199 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3200 /// other.significant_bits())`.
3201 ///
3202 /// # Panics
3203 /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to
3204 /// represent the output.
3205 ///
3206 /// # Examples
3207 /// ```
3208 /// use core::f64::consts::PI;
3209 /// use malachite_base::rounding_modes::RoundingMode::*;
3210 /// use malachite_float::Float;
3211 /// use malachite_q::Rational;
3212 /// use std::cmp::Ordering::*;
3213 ///
3214 /// let (product, o) =
3215 /// Float::from(PI).mul_rational_round_val_ref(&Rational::from_unsigneds(1u8, 3), Floor);
3216 /// assert_eq!(product.to_string(), "1.047197551196597");
3217 /// assert_eq!(o, Less);
3218 ///
3219 /// let (product, o) =
3220 /// Float::from(PI).mul_rational_round_val_ref(&Rational::from_unsigneds(1u8, 3), Ceiling);
3221 /// assert_eq!(product.to_string(), "1.047197551196598");
3222 /// assert_eq!(o, Greater);
3223 ///
3224 /// let (product, o) =
3225 /// Float::from(PI).mul_rational_round_val_ref(&Rational::from_unsigneds(1u8, 3), Nearest);
3226 /// assert_eq!(product.to_string(), "1.047197551196598");
3227 /// assert_eq!(o, Greater);
3228 /// ```
3229 #[inline]
3230 pub fn mul_rational_round_val_ref(
3231 self,
3232 other: &Rational,
3233 rm: RoundingMode,
3234 ) -> (Float, Ordering) {
3235 let prec = self.significant_bits();
3236 self.mul_rational_prec_round_val_ref(other, prec, rm)
3237 }
3238
3239 /// Multiplies a [`Float`] by a [`Rational`], rounding the result with the specified rounding
3240 /// mode. The [`Float`] is taken by reference and the [`Rational`] by value. An [`Ordering`] is
3241 /// also returned, indicating whether the rounded product is less than, equal to, or greater
3242 /// than the exact product. Although `NaN`s are not comparable to any [`Float`], whenever this
3243 /// function returns a `NaN` it also returns `Equal`.
3244 ///
3245 /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`]
3246 /// for a description of the possible rounding modes.
3247 ///
3248 /// $$
3249 /// f(x,y,m) = xy+\varepsilon.
3250 /// $$
3251 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3252 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
3253 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`].
3254 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
3255 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`].
3256 ///
3257 /// If the output has a precision, it is the precision of the [`Float`] input.
3258 ///
3259 /// Special cases:
3260 /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=\text{NaN}$
3261 /// - $f(\infty,x,m)=\infty$ if $x>0$
3262 /// - $f(\infty,x,m)=-\infty$ if $x<0$
3263 /// - $f(-\infty,x,m)=-\infty$ if $x>0$
3264 /// - $f(-\infty,x,m)=\infty$ if $x<0$
3265 /// - $f(0.0,x,m)=0.0$ if $x\geq0$
3266 /// - $f(0.0,x,m)=-0.0$ if $x<0$
3267 /// - $f(-0.0,x,m)=-0.0$ if $x\geq0$
3268 /// - $f(-0.0,x,m)=0.0$ if $x<0$
3269 ///
3270 /// If you want to specify an output precision, consider using
3271 /// [`Float::mul_rational_prec_round_ref_val`] instead. If you know you'll be using the
3272 /// `Nearest` rounding mode, consider using `*` instead.
3273 ///
3274 /// # Worst-case complexity
3275 /// $T(n) = O(n \log n \log\log n)$
3276 ///
3277 /// $M(n) = O(n \log n)$
3278 ///
3279 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3280 /// other.significant_bits())`.
3281 ///
3282 /// # Panics
3283 /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to
3284 /// represent the output.
3285 ///
3286 /// # Examples
3287 /// ```
3288 /// use core::f64::consts::PI;
3289 /// use malachite_base::rounding_modes::RoundingMode::*;
3290 /// use malachite_float::Float;
3291 /// use malachite_q::Rational;
3292 /// use std::cmp::Ordering::*;
3293 ///
3294 /// let (product, o) =
3295 /// Float::from(PI).mul_rational_round_ref_val(Rational::from_unsigneds(1u8, 3), Floor);
3296 /// assert_eq!(product.to_string(), "1.047197551196597");
3297 /// assert_eq!(o, Less);
3298 ///
3299 /// let (product, o) =
3300 /// Float::from(PI).mul_rational_round_ref_val(Rational::from_unsigneds(1u8, 3), Ceiling);
3301 /// assert_eq!(product.to_string(), "1.047197551196598");
3302 /// assert_eq!(o, Greater);
3303 ///
3304 /// let (product, o) =
3305 /// Float::from(PI).mul_rational_round_ref_val(Rational::from_unsigneds(1u8, 3), Nearest);
3306 /// assert_eq!(product.to_string(), "1.047197551196598");
3307 /// assert_eq!(o, Greater);
3308 /// ```
3309 #[inline]
3310 pub fn mul_rational_round_ref_val(
3311 &self,
3312 other: Rational,
3313 rm: RoundingMode,
3314 ) -> (Float, Ordering) {
3315 let prec = self.significant_bits();
3316 self.mul_rational_prec_round_ref_val(other, prec, rm)
3317 }
3318
3319 /// Multiplies a [`Float`] by a [`Rational`], rounding the result with the specified rounding
3320 /// mode. The [`Float`] and the [`Rational`] are both are taken by reference. An [`Ordering`] is
3321 /// also returned, indicating whether the rounded product is less than, equal to, or greater
3322 /// than the exact product. Although `NaN`s are not comparable to any [`Float`], whenever this
3323 /// function returns a `NaN` it also returns `Equal`.
3324 ///
3325 /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`]
3326 /// for a description of the possible rounding modes.
3327 ///
3328 /// $$
3329 /// f(x,y,m) = xy+\varepsilon.
3330 /// $$
3331 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3332 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
3333 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`].
3334 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
3335 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`].
3336 ///
3337 /// If the output has a precision, it is the precision of the [`Float`] input.
3338 ///
3339 /// Special cases:
3340 /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=\text{NaN}$
3341 /// - $f(\infty,x,m)=\infty$ if $x>0$
3342 /// - $f(\infty,x,m)=-\infty$ if $x<0$
3343 /// - $f(-\infty,x,m)=-\infty$ if $x>0$
3344 /// - $f(-\infty,x,m)=\infty$ if $x<0$
3345 /// - $f(0.0,x,m)=0.0$ if $x\geq0$
3346 /// - $f(0.0,x,m)=-0.0$ if $x<0$
3347 /// - $f(-0.0,x,m)=-0.0$ if $x\geq0$
3348 /// - $f(-0.0,x,m)=0.0$ if $x<0$
3349 ///
3350 /// If you want to specify an output precision, consider using
3351 /// [`Float::mul_rational_prec_round_ref_ref`] instead. If you know you'll be using the
3352 /// `Nearest` rounding mode, consider using `*` instead.
3353 ///
3354 /// # Worst-case complexity
3355 /// $T(n) = O(n \log n \log\log n)$
3356 ///
3357 /// $M(n) = O(n \log n)$
3358 ///
3359 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3360 /// other.significant_bits())`.
3361 ///
3362 /// # Panics
3363 /// Panics if `rm` is `Exact` but the precision of the [`Float`] input is not high enough to
3364 /// represent the output.
3365 ///
3366 /// # Examples
3367 /// ```
3368 /// use core::f64::consts::PI;
3369 /// use malachite_base::rounding_modes::RoundingMode::*;
3370 /// use malachite_float::Float;
3371 /// use malachite_q::Rational;
3372 /// use std::cmp::Ordering::*;
3373 ///
3374 /// let (product, o) =
3375 /// Float::from(PI).mul_rational_round_ref_ref(&Rational::from_unsigneds(1u8, 3), Floor);
3376 /// assert_eq!(product.to_string(), "1.047197551196597");
3377 /// assert_eq!(o, Less);
3378 ///
3379 /// let (product, o) =
3380 /// Float::from(PI).mul_rational_round_ref_ref(&Rational::from_unsigneds(1u8, 3), Ceiling);
3381 /// assert_eq!(product.to_string(), "1.047197551196598");
3382 /// assert_eq!(o, Greater);
3383 ///
3384 /// let (product, o) =
3385 /// Float::from(PI).mul_rational_round_ref_ref(&Rational::from_unsigneds(1u8, 3), Nearest);
3386 /// assert_eq!(product.to_string(), "1.047197551196598");
3387 /// assert_eq!(o, Greater);
3388 /// ```
3389 #[inline]
3390 pub fn mul_rational_round_ref_ref(
3391 &self,
3392 other: &Rational,
3393 rm: RoundingMode,
3394 ) -> (Float, Ordering) {
3395 let prec = self.significant_bits();
3396 self.mul_rational_prec_round_ref_ref(other, prec, rm)
3397 }
3398
3399 /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result to the specified
3400 /// precision and with the specified rounding mode. The [`Rational`] is taken by value. An
3401 /// [`Ordering`] is returned, indicating whether the rounded product is less than, equal to, or
3402 /// greater than the exact product. Although `NaN`s are not comparable to any [`Float`],
3403 /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`.
3404 ///
3405 /// See [`RoundingMode`] for a description of the possible rounding modes.
3406 ///
3407 /// $$
3408 /// x \gets xy+\varepsilon.
3409 /// $$
3410 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3411 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
3412 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
3413 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
3414 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
3415 ///
3416 /// If the output has a precision, it is `prec`.
3417 ///
3418 /// See the [`Float::mul_rational_prec_round`] documentation for information on special cases.
3419 ///
3420 /// If you know you'll be using `Nearest`, consider using [`Float::mul_rational_prec_assign`]
3421 /// instead. If you know that your target precision is the precision of the [`Float`] input,
3422 /// consider using [`Float::mul_rational_round_assign`] instead. If both of these things are
3423 /// true, consider using `*=` instead.
3424 ///
3425 /// # Worst-case complexity
3426 /// $T(n) = O(n \log n \log\log n)$
3427 ///
3428 /// $M(n) = O(n \log n)$
3429 ///
3430 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3431 /// other.significant_bits(), prec)`.
3432 ///
3433 /// # Panics
3434 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
3435 ///
3436 /// # Examples
3437 /// ```
3438 /// use core::f64::consts::PI;
3439 /// use malachite_base::rounding_modes::RoundingMode::*;
3440 /// use malachite_float::Float;
3441 /// use malachite_q::Rational;
3442 /// use std::cmp::Ordering::*;
3443 ///
3444 /// let mut x = Float::from(PI);
3445 /// assert_eq!(
3446 /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Floor),
3447 /// Less
3448 /// );
3449 /// assert_eq!(x.to_string(), "1.0");
3450 ///
3451 /// let mut x = Float::from(PI);
3452 /// assert_eq!(
3453 /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Ceiling),
3454 /// Greater
3455 /// );
3456 /// assert_eq!(x.to_string(), "1.06");
3457 ///
3458 /// let mut x = Float::from(PI);
3459 /// assert_eq!(
3460 /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Nearest),
3461 /// Greater
3462 /// );
3463 /// assert_eq!(x.to_string(), "1.06");
3464 ///
3465 /// let mut x = Float::from(PI);
3466 /// assert_eq!(
3467 /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Floor),
3468 /// Less
3469 /// );
3470 /// assert_eq!(x.to_string(), "1.047197");
3471 ///
3472 /// let mut x = Float::from(PI);
3473 /// assert_eq!(
3474 /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Ceiling),
3475 /// Greater
3476 /// );
3477 /// assert_eq!(x.to_string(), "1.047199");
3478 ///
3479 /// let mut x = Float::from(PI);
3480 /// assert_eq!(
3481 /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Nearest),
3482 /// Less
3483 /// );
3484 /// assert_eq!(x.to_string(), "1.047197");
3485 /// ```
3486 #[inline]
3487 pub fn mul_rational_prec_round_assign(
3488 &mut self,
3489 other: Rational,
3490 prec: u64,
3491 rm: RoundingMode,
3492 ) -> Ordering {
3493 if max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD {
3494 mul_rational_prec_round_assign_naive(self, other, prec, rm)
3495 } else {
3496 mul_rational_prec_round_assign_direct(self, other, prec, rm)
3497 }
3498 }
3499
3500 /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result to the specified
3501 /// precision and with the specified rounding mode. The [`Rational`] is taken by reference. An
3502 /// [`Ordering`] is returned, indicating whether the rounded product is less than, equal to, or
3503 /// greater than the exact product. Although `NaN`s are not comparable to any [`Float`],
3504 /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`.
3505 ///
3506 /// See [`RoundingMode`] for a description of the possible rounding modes.
3507 ///
3508 /// $$
3509 /// x \gets xy+\varepsilon.
3510 /// $$
3511 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3512 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
3513 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
3514 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
3515 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$.
3516 ///
3517 /// If the output has a precision, it is `prec`.
3518 ///
3519 /// See the [`Float::mul_rational_prec_round`] documentation for information on special cases.
3520 ///
3521 /// If you know you'll be using `Nearest`, consider using
3522 /// [`Float::mul_rational_prec_assign_ref`] instead. If you know that your target precision is
3523 /// the precision of the [`Float`] input, consider using
3524 /// [`Float::mul_rational_round_assign_ref`] instead. If both of these things are true, consider
3525 /// using `*=` instead.
3526 ///
3527 /// # Worst-case complexity
3528 /// $T(n) = O(n \log n \log\log n)$
3529 ///
3530 /// $M(n) = O(n \log n)$
3531 ///
3532 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3533 /// other.significant_bits(), prec)`.
3534 ///
3535 /// # Panics
3536 /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication.
3537 ///
3538 /// # Examples
3539 /// ```
3540 /// use core::f64::consts::PI;
3541 /// use malachite_base::rounding_modes::RoundingMode::*;
3542 /// use malachite_float::Float;
3543 /// use malachite_q::Rational;
3544 /// use std::cmp::Ordering::*;
3545 ///
3546 /// let mut x = Float::from(PI);
3547 /// assert_eq!(
3548 /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Floor),
3549 /// Less
3550 /// );
3551 /// assert_eq!(x.to_string(), "1.0");
3552 ///
3553 /// let mut x = Float::from(PI);
3554 /// assert_eq!(
3555 /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Ceiling),
3556 /// Greater
3557 /// );
3558 /// assert_eq!(x.to_string(), "1.06");
3559 ///
3560 /// let mut x = Float::from(PI);
3561 /// assert_eq!(
3562 /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Nearest),
3563 /// Greater
3564 /// );
3565 /// assert_eq!(x.to_string(), "1.06");
3566 ///
3567 /// let mut x = Float::from(PI);
3568 /// assert_eq!(
3569 /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Floor),
3570 /// Less
3571 /// );
3572 /// assert_eq!(x.to_string(), "1.047197");
3573 ///
3574 /// let mut x = Float::from(PI);
3575 /// assert_eq!(
3576 /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Ceiling),
3577 /// Greater
3578 /// );
3579 /// assert_eq!(x.to_string(), "1.047199");
3580 ///
3581 /// let mut x = Float::from(PI);
3582 /// assert_eq!(
3583 /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Nearest),
3584 /// Less
3585 /// );
3586 /// assert_eq!(x.to_string(), "1.047197");
3587 /// ```
3588 #[inline]
3589 pub fn mul_rational_prec_round_assign_ref(
3590 &mut self,
3591 other: &Rational,
3592 prec: u64,
3593 rm: RoundingMode,
3594 ) -> Ordering {
3595 if max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD {
3596 mul_rational_prec_round_assign_naive_ref(self, other, prec, rm)
3597 } else {
3598 mul_rational_prec_round_assign_direct_ref(self, other, prec, rm)
3599 }
3600 }
3601
3602 /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result to the nearest value
3603 /// of the specified precision. The [`Rational`] is taken by value. An [`Ordering`] is returned,
3604 /// indicating whether the rounded product is less than, equal to, or greater than the exact
3605 /// product. Although `NaN`s are not comparable to any [`Float`], whenever this function sets
3606 /// the [`Float`] to `NaN` it also returns `Equal`.
3607 ///
3608 /// If the product is equidistant from two [`Float`]s with the specified precision, the
3609 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
3610 /// description of the `Nearest` rounding mode.
3611 ///
3612 /// $$
3613 /// x \gets xy+\varepsilon.
3614 /// $$
3615 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3616 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
3617 ///
3618 /// If the output has a precision, it is `prec`.
3619 ///
3620 /// See the [`Float::mul_rational_prec`] documentation for information on special cases.
3621 ///
3622 /// If you want to use a rounding mode other than `Nearest`, consider using
3623 /// [`Float::mul_rational_prec_round_assign`] instead. If you know that your target precision is
3624 /// the maximum of the precisions of the two inputs, consider using `*=` instead.
3625 ///
3626 /// # Worst-case complexity
3627 /// $T(n) = O(n \log n \log\log n)$
3628 ///
3629 /// $M(n) = O(n \log n)$
3630 ///
3631 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3632 /// other.significant_bits(), prec)`.
3633 ///
3634 /// # Examples
3635 /// ```
3636 /// use core::f64::consts::PI;
3637 /// use malachite_base::num::conversion::traits::ExactFrom;
3638 /// use malachite_float::Float;
3639 /// use malachite_q::Rational;
3640 /// use std::cmp::Ordering::*;
3641 ///
3642 /// let mut x = Float::from(PI);
3643 /// assert_eq!(
3644 /// x.mul_rational_prec_assign(Rational::exact_from(1.5), 5),
3645 /// Greater
3646 /// );
3647 /// assert_eq!(x.to_string(), "4.8");
3648 ///
3649 /// let mut x = Float::from(PI);
3650 /// assert_eq!(
3651 /// x.mul_rational_prec_assign(Rational::exact_from(1.5), 20),
3652 /// Less
3653 /// );
3654 /// assert_eq!(x.to_string(), "4.712387");
3655 /// ```
3656 #[inline]
3657 pub fn mul_rational_prec_assign(&mut self, other: Rational, prec: u64) -> Ordering {
3658 self.mul_rational_prec_round_assign(other, prec, Nearest)
3659 }
3660
3661 /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result to the nearest value
3662 /// of the specified precision. The [`Rational`] is taken by reference. An [`Ordering`] is
3663 /// returned, indicating whether the rounded product is less than, equal to, or greater than the
3664 /// exact product. Although `NaN`s are not comparable to any [`Float`], whenever this function
3665 /// sets the [`Float`] to `NaN` it also returns `Equal`.
3666 ///
3667 /// If the product is equidistant from two [`Float`]s with the specified precision, the
3668 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
3669 /// description of the `Nearest` rounding mode.
3670 ///
3671 /// $$
3672 /// x \gets xy+\varepsilon.
3673 /// $$
3674 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3675 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$.
3676 ///
3677 /// If the output has a precision, it is `prec`.
3678 ///
3679 /// See the [`Float::mul_rational_prec`] documentation for information on special cases.
3680 ///
3681 /// If you want to use a rounding mode other than `Nearest`, consider using
3682 /// [`Float::mul_rational_prec_round_assign`] instead. If you know that your target precision is
3683 /// the maximum of the precisions of the two inputs, consider using `*=` instead.
3684 ///
3685 /// # Worst-case complexity
3686 /// $T(n) = O(n \log n \log\log n)$
3687 ///
3688 /// $M(n) = O(n \log n)$
3689 ///
3690 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3691 /// other.significant_bits(), prec)`.
3692 ///
3693 /// # Examples
3694 /// ```
3695 /// use core::f64::consts::PI;
3696 /// use malachite_base::num::conversion::traits::ExactFrom;
3697 /// use malachite_float::Float;
3698 /// use malachite_q::Rational;
3699 /// use std::cmp::Ordering::*;
3700 ///
3701 /// let mut x = Float::from(PI);
3702 /// assert_eq!(
3703 /// x.mul_rational_prec_assign_ref(&Rational::exact_from(1.5), 5),
3704 /// Greater
3705 /// );
3706 /// assert_eq!(x.to_string(), "4.8");
3707 ///
3708 /// let mut x = Float::from(PI);
3709 /// assert_eq!(
3710 /// x.mul_rational_prec_assign_ref(&Rational::exact_from(1.5), 20),
3711 /// Less
3712 /// );
3713 /// assert_eq!(x.to_string(), "4.712387");
3714 /// ```
3715 #[inline]
3716 pub fn mul_rational_prec_assign_ref(&mut self, other: &Rational, prec: u64) -> Ordering {
3717 self.mul_rational_prec_round_assign_ref(other, prec, Nearest)
3718 }
3719
3720 /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result with the specified
3721 /// rounding mode. The [`Rational`] is taken by value. An [`Ordering`] is returned, indicating
3722 /// whether the rounded product is less than, equal to, or greater than the exact product.
3723 /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the
3724 /// [`Float`] to `NaN` it also returns `Equal`.
3725 ///
3726 /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`]
3727 /// for a description of the possible rounding modes.
3728 ///
3729 /// $$
3730 /// x \gets xy+\varepsilon.
3731 /// $$
3732 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3733 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
3734 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`].
3735 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
3736 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`].
3737 ///
3738 /// If the output has a precision, it is the precision of the input [`Float`].
3739 ///
3740 /// See the [`Float::mul_rational_round`] documentation for information on special cases.
3741 ///
3742 /// If you want to specify an output precision, consider using
3743 /// [`Float::mul_rational_prec_round_assign`] instead. If you know you'll be using the `Nearest`
3744 /// rounding mode, consider using `*=` instead.
3745 ///
3746 /// # Worst-case complexity
3747 /// $T(n) = O(n \log n \log\log n)$
3748 ///
3749 /// $M(n) = O(n \log n)$
3750 ///
3751 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3752 /// other.significant_bits())`.
3753 ///
3754 /// # Panics
3755 /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to
3756 /// represent the output.
3757 ///
3758 /// # Examples
3759 /// ```
3760 /// use core::f64::consts::PI;
3761 /// use malachite_base::rounding_modes::RoundingMode::*;
3762 /// use malachite_float::Float;
3763 /// use malachite_q::Rational;
3764 /// use std::cmp::Ordering::*;
3765 ///
3766 /// let mut x = Float::from(PI);
3767 /// assert_eq!(
3768 /// x.mul_rational_round_assign(Rational::from_unsigneds(1u8, 3), Floor),
3769 /// Less
3770 /// );
3771 /// assert_eq!(x.to_string(), "1.047197551196597");
3772 ///
3773 /// let mut x = Float::from(PI);
3774 /// assert_eq!(
3775 /// x.mul_rational_round_assign(Rational::from_unsigneds(1u8, 3), Ceiling),
3776 /// Greater
3777 /// );
3778 /// assert_eq!(x.to_string(), "1.047197551196598");
3779 ///
3780 /// let mut x = Float::from(PI);
3781 /// assert_eq!(
3782 /// x.mul_rational_round_assign(Rational::from_unsigneds(1u8, 3), Nearest),
3783 /// Greater
3784 /// );
3785 /// assert_eq!(x.to_string(), "1.047197551196598");
3786 /// ```
3787 #[inline]
3788 pub fn mul_rational_round_assign(&mut self, other: Rational, rm: RoundingMode) -> Ordering {
3789 let prec = self.significant_bits();
3790 self.mul_rational_prec_round_assign(other, prec, rm)
3791 }
3792
3793 /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result with the specified
3794 /// rounding mode. The [`Rational`] is taken by reference. An [`Ordering`] is returned,
3795 /// indicating whether the rounded product is less than, equal to, or greater than the exact
3796 /// product. Although `NaN`s are not comparable to any [`Float`], whenever this function sets
3797 /// the [`Float`] to `NaN` it also returns `Equal`.
3798 ///
3799 /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`]
3800 /// for a description of the possible rounding modes.
3801 ///
3802 /// $$
3803 /// x \gets xy+\varepsilon.
3804 /// $$
3805 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3806 /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
3807 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`].
3808 /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
3809 /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`].
3810 ///
3811 /// If the output has a precision, it is the precision of the input [`Float`].
3812 ///
3813 /// See the [`Float::mul_rational_round`] documentation for information on special cases.
3814 ///
3815 /// If you want to specify an output precision, consider using
3816 /// [`Float::mul_rational_prec_round_assign`] instead. If you know you'll be using the `Nearest`
3817 /// rounding mode, consider using `*=` instead.
3818 ///
3819 /// # Worst-case complexity
3820 /// $T(n) = O(n \log n \log\log n)$
3821 ///
3822 /// $M(n) = O(n \log n)$
3823 ///
3824 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3825 /// other.significant_bits())`.
3826 ///
3827 /// # Panics
3828 /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to
3829 /// represent the output.
3830 ///
3831 /// # Examples
3832 /// ```
3833 /// use core::f64::consts::PI;
3834 /// use malachite_base::rounding_modes::RoundingMode::*;
3835 /// use malachite_float::Float;
3836 /// use malachite_q::Rational;
3837 /// use std::cmp::Ordering::*;
3838 ///
3839 /// let mut x = Float::from(PI);
3840 /// assert_eq!(
3841 /// x.mul_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Floor),
3842 /// Less
3843 /// );
3844 /// assert_eq!(x.to_string(), "1.047197551196597");
3845 ///
3846 /// let mut x = Float::from(PI);
3847 /// assert_eq!(
3848 /// x.mul_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Ceiling),
3849 /// Greater
3850 /// );
3851 /// assert_eq!(x.to_string(), "1.047197551196598");
3852 ///
3853 /// let mut x = Float::from(PI);
3854 /// assert_eq!(
3855 /// x.mul_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Nearest),
3856 /// Greater
3857 /// );
3858 /// assert_eq!(x.to_string(), "1.047197551196598");
3859 /// ```
3860 #[inline]
3861 pub fn mul_rational_round_assign_ref(
3862 &mut self,
3863 other: &Rational,
3864 rm: RoundingMode,
3865 ) -> Ordering {
3866 let prec = self.significant_bits();
3867 self.mul_rational_prec_round_assign_ref(other, prec, rm)
3868 }
3869}
3870
3871impl Mul<Float> for Float {
3872 type Output = Float;
3873
3874 /// Multiplies two [`Float`]s, taking both by value.
3875 ///
3876 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the
3877 /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
3878 /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
3879 /// `Nearest` rounding mode.
3880 ///
3881 /// $$
3882 /// f(x,y) = xy+\varepsilon.
3883 /// $$
3884 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3885 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
3886 /// where $p$ is the maximum precision of the inputs.
3887 ///
3888 /// Special cases:
3889 /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$
3890 /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x>0.0$
3891 /// - $f(\infty,x)=f(x,\infty)=-\infty$ if $x<0.0$
3892 /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x>0.0$
3893 /// - $f(-\infty,x)=f(x,-\infty)=\infty$ if $x<0.0$
3894 /// - $f(0.0,x)=f(x,0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
3895 /// - $f(0.0,x)=f(x,0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
3896 /// - $f(-0.0,x)=f(x,-0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
3897 /// - $f(-0.0,x)=f(x,-0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
3898 ///
3899 /// Overflow and underflow:
3900 /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
3901 /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
3902 /// - If $0<f(x,y)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
3903 /// - If $2^{-2^{30}-1}<f(x,y)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
3904 /// - If $-2^{-2^{30}-1}\leq f(x,y)<0$, $-0.0$ is returned instead.
3905 /// - If $-2^{-2^{30}}<f(x,y)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
3906 ///
3907 /// If you want to use a rounding mode other than `Nearest`, consider using [`Float::mul_prec`]
3908 /// instead. If you want to specify the output precision, consider using [`Float::mul_round`].
3909 /// If you want both of these things, consider using [`Float::mul_prec_round`].
3910 ///
3911 /// # Worst-case complexity
3912 /// $T(n) = O(n \log n \log\log n)$
3913 ///
3914 /// $M(n) = O(n \log n)$
3915 ///
3916 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3917 /// other.significant_bits())`.
3918 ///
3919 /// # Examples
3920 /// ```
3921 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero};
3922 /// use malachite_float::Float;
3923 ///
3924 /// assert!((Float::from(1.5) * Float::NAN).is_nan());
3925 /// assert_eq!(Float::from(1.5) * Float::INFINITY, Float::INFINITY);
3926 /// assert_eq!(
3927 /// Float::from(1.5) * Float::NEGATIVE_INFINITY,
3928 /// Float::NEGATIVE_INFINITY
3929 /// );
3930 /// assert_eq!(
3931 /// Float::from(-1.5) * Float::INFINITY,
3932 /// Float::NEGATIVE_INFINITY
3933 /// );
3934 /// assert_eq!(
3935 /// Float::from(-1.5) * Float::NEGATIVE_INFINITY,
3936 /// Float::INFINITY
3937 /// );
3938 /// assert!((Float::INFINITY * Float::ZERO).is_nan());
3939 ///
3940 /// assert_eq!(Float::from(1.5) * Float::from(2.5), 4.0);
3941 /// assert_eq!(Float::from(1.5) * Float::from(-2.5), -4.0);
3942 /// assert_eq!(Float::from(-1.5) * Float::from(2.5), -4.0);
3943 /// assert_eq!(Float::from(-1.5) * Float::from(-2.5), 4.0);
3944 /// ```
3945 #[inline]
3946 fn mul(self, other: Float) -> Float {
3947 let prec = max(self.significant_bits(), other.significant_bits());
3948 self.mul_prec_round(other, prec, Nearest).0
3949 }
3950}
3951
3952impl Mul<&Float> for Float {
3953 type Output = Float;
3954
3955 /// Multiplies two [`Float`]s, taking the first by value and the second by reference.
3956 ///
3957 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the
3958 /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
3959 /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
3960 /// `Nearest` rounding mode.
3961 ///
3962 /// $$
3963 /// f(x,y) = xy+\varepsilon.
3964 /// $$
3965 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
3966 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
3967 /// where $p$ is the maximum precision of the inputs.
3968 ///
3969 /// Special cases:
3970 /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$
3971 /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x>0.0$
3972 /// - $f(\infty,x)=f(x,\infty)=-\infty$ if $x<0.0$
3973 /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x>0.0$
3974 /// - $f(-\infty,x)=f(x,-\infty)=\infty$ if $x<0.0$
3975 /// - $f(0.0,x)=f(x,0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
3976 /// - $f(0.0,x)=f(x,0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
3977 /// - $f(-0.0,x)=f(x,-0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
3978 /// - $f(-0.0,x)=f(x,-0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
3979 ///
3980 /// Overflow and underflow:
3981 /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
3982 /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
3983 /// - If $0<f(x,y)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
3984 /// - If $2^{-2^{30}-1}<f(x,y)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
3985 /// - If $-2^{-2^{30}-1}\leq f(x,y)<0$, $-0.0$ is returned instead.
3986 /// - If $-2^{-2^{30}}<f(x,y)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
3987 ///
3988 /// If you want to use a rounding mode other than `Nearest`, consider using
3989 /// [`Float::mul_prec_val_ref`] instead. If you want to specify the output precision, consider
3990 /// using [`Float::mul_round_val_ref`]. If you want both of these things, consider using
3991 /// [`Float::mul_prec_round_val_ref`].
3992 ///
3993 /// # Worst-case complexity
3994 /// $T(n) = O(n \log n \log\log n)$
3995 ///
3996 /// $M(n) = O(n \log n)$
3997 ///
3998 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
3999 /// other.significant_bits())`.
4000 ///
4001 /// # Examples
4002 /// ```
4003 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero};
4004 /// use malachite_float::Float;
4005 ///
4006 /// assert!((Float::from(1.5) * &Float::NAN).is_nan());
4007 /// assert_eq!(Float::from(1.5) * &Float::INFINITY, Float::INFINITY);
4008 /// assert_eq!(
4009 /// Float::from(1.5) * &Float::NEGATIVE_INFINITY,
4010 /// Float::NEGATIVE_INFINITY
4011 /// );
4012 /// assert_eq!(
4013 /// Float::from(-1.5) * &Float::INFINITY,
4014 /// Float::NEGATIVE_INFINITY
4015 /// );
4016 /// assert_eq!(
4017 /// Float::from(-1.5) * &Float::NEGATIVE_INFINITY,
4018 /// Float::INFINITY
4019 /// );
4020 /// assert!((Float::INFINITY * &Float::ZERO).is_nan());
4021 ///
4022 /// assert_eq!(Float::from(1.5) * &Float::from(2.5), 4.0);
4023 /// assert_eq!(Float::from(1.5) * &Float::from(-2.5), -4.0);
4024 /// assert_eq!(Float::from(-1.5) * &Float::from(2.5), -4.0);
4025 /// assert_eq!(Float::from(-1.5) * &Float::from(-2.5), 4.0);
4026 /// ```
4027 #[inline]
4028 fn mul(self, other: &Float) -> Float {
4029 let prec = max(self.significant_bits(), other.significant_bits());
4030 self.mul_prec_round_val_ref(other, prec, Nearest).0
4031 }
4032}
4033
4034impl Mul<Float> for &Float {
4035 type Output = Float;
4036
4037 /// Multiplies two [`Float`]s, taking the first by reference and the second by value.
4038 ///
4039 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the
4040 /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
4041 /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
4042 /// `Nearest` rounding mode.
4043 ///
4044 /// $$
4045 /// f(x,y) = xy+\varepsilon.
4046 /// $$
4047 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4048 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4049 /// where $p$ is the maximum precision of the inputs.
4050 ///
4051 /// Special cases:
4052 /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$
4053 /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x>0.0$
4054 /// - $f(\infty,x)=f(x,\infty)=-\infty$ if $x<0.0$
4055 /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x>0.0$
4056 /// - $f(-\infty,x)=f(x,-\infty)=\infty$ if $x<0.0$
4057 /// - $f(0.0,x)=f(x,0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
4058 /// - $f(0.0,x)=f(x,0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
4059 /// - $f(-0.0,x)=f(x,-0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
4060 /// - $f(-0.0,x)=f(x,-0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
4061 ///
4062 /// Overflow and underflow:
4063 /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
4064 /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
4065 /// - If $0<f(x,y)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
4066 /// - If $2^{-2^{30}-1}<f(x,y)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
4067 /// - If $-2^{-2^{30}-1}\leq f(x,y)<0$, $-0.0$ is returned instead.
4068 /// - If $-2^{-2^{30}}<f(x,y)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
4069 ///
4070 /// If you want to use a rounding mode other than `Nearest`, consider using
4071 /// [`Float::mul_prec_ref_val`] instead. If you want to specify the output precision, consider
4072 /// using [`Float::mul_round_ref_val`]. If you want both of these things, consider using
4073 /// [`Float::mul_prec_round_ref_val`].
4074 ///
4075 /// # Worst-case complexity
4076 /// $T(n) = O(n \log n \log\log n)$
4077 ///
4078 /// $M(n) = O(n \log n)$
4079 ///
4080 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4081 /// other.significant_bits())`.
4082 ///
4083 /// # Examples
4084 /// ```
4085 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero};
4086 /// use malachite_float::Float;
4087 ///
4088 /// assert!((&Float::from(1.5) * Float::NAN).is_nan());
4089 /// assert_eq!(&Float::from(1.5) * Float::INFINITY, Float::INFINITY);
4090 /// assert_eq!(
4091 /// &Float::from(1.5) * Float::NEGATIVE_INFINITY,
4092 /// Float::NEGATIVE_INFINITY
4093 /// );
4094 /// assert_eq!(
4095 /// &Float::from(-1.5) * Float::INFINITY,
4096 /// Float::NEGATIVE_INFINITY
4097 /// );
4098 /// assert_eq!(
4099 /// &Float::from(-1.5) * Float::NEGATIVE_INFINITY,
4100 /// Float::INFINITY
4101 /// );
4102 /// assert!((&Float::INFINITY * Float::ZERO).is_nan());
4103 ///
4104 /// assert_eq!(&Float::from(1.5) * Float::from(2.5), 4.0);
4105 /// assert_eq!(&Float::from(1.5) * Float::from(-2.5), -4.0);
4106 /// assert_eq!(&Float::from(-1.5) * Float::from(2.5), -4.0);
4107 /// assert_eq!(&Float::from(-1.5) * Float::from(-2.5), 4.0);
4108 /// ```
4109 #[inline]
4110 fn mul(self, other: Float) -> Float {
4111 let prec = max(self.significant_bits(), other.significant_bits());
4112 self.mul_prec_round_ref_val(other, prec, Nearest).0
4113 }
4114}
4115
4116impl Mul<&Float> for &Float {
4117 type Output = Float;
4118
4119 /// Multiplies two [`Float`]s, taking both by reference.
4120 ///
4121 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the
4122 /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
4123 /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
4124 /// `Nearest` rounding mode.
4125 ///
4126 /// $$
4127 /// f(x,y) = xy+\varepsilon.
4128 /// $$
4129 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4130 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4131 /// where $p$ is the maximum precision of the inputs.
4132 ///
4133 /// Special cases:
4134 /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$
4135 /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x>0.0$
4136 /// - $f(\infty,x)=f(x,\infty)=-\infty$ if $x<0.0$
4137 /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x>0.0$
4138 /// - $f(-\infty,x)=f(x,-\infty)=\infty$ if $x<0.0$
4139 /// - $f(0.0,x)=f(x,0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
4140 /// - $f(0.0,x)=f(x,0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
4141 /// - $f(-0.0,x)=f(x,-0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$
4142 /// - $f(-0.0,x)=f(x,-0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$
4143 ///
4144 /// Overflow and underflow:
4145 /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
4146 /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
4147 /// - If $0<f(x,y)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
4148 /// - If $2^{-2^{30}-1}<f(x,y)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
4149 /// - If $-2^{-2^{30}-1}\leq f(x,y)<0$, $-0.0$ is returned instead.
4150 /// - If $-2^{-2^{30}}<f(x,y)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
4151 ///
4152 /// If you want to use a rounding mode other than `Nearest`, consider using
4153 /// [`Float::mul_prec_ref_ref`] instead. If you want to specify the output precision, consider
4154 /// using [`Float::mul_round_ref_ref`]. If you want both of these things, consider using
4155 /// [`Float::mul_prec_round_ref_ref`].
4156 ///
4157 /// # Worst-case complexity
4158 /// $T(n) = O(n \log n \log\log n)$
4159 ///
4160 /// $M(n) = O(n \log n)$
4161 ///
4162 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4163 /// other.significant_bits())`.
4164 ///
4165 /// # Examples
4166 /// ```
4167 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero};
4168 /// use malachite_float::Float;
4169 ///
4170 /// assert!((&Float::from(1.5) * &Float::NAN).is_nan());
4171 /// assert_eq!(&Float::from(1.5) * &Float::INFINITY, Float::INFINITY);
4172 /// assert_eq!(
4173 /// &Float::from(1.5) * &Float::NEGATIVE_INFINITY,
4174 /// Float::NEGATIVE_INFINITY
4175 /// );
4176 /// assert_eq!(
4177 /// &Float::from(-1.5) * &Float::INFINITY,
4178 /// Float::NEGATIVE_INFINITY
4179 /// );
4180 /// assert_eq!(
4181 /// &Float::from(-1.5) * &Float::NEGATIVE_INFINITY,
4182 /// Float::INFINITY
4183 /// );
4184 /// assert!((&Float::INFINITY * &Float::ZERO).is_nan());
4185 ///
4186 /// assert_eq!(&Float::from(1.5) * &Float::from(2.5), 4.0);
4187 /// assert_eq!(&Float::from(1.5) * &Float::from(-2.5), -4.0);
4188 /// assert_eq!(&Float::from(-1.5) * &Float::from(2.5), -4.0);
4189 /// assert_eq!(&Float::from(-1.5) * &Float::from(-2.5), 4.0);
4190 /// ```
4191 #[inline]
4192 fn mul(self, other: &Float) -> Float {
4193 let prec = max(self.significant_bits(), other.significant_bits());
4194 self.mul_prec_round_ref_ref(other, prec, Nearest).0
4195 }
4196}
4197
4198impl MulAssign<Float> for Float {
4199 /// Multiplies a [`Float`] by a [`Float`] in place, taking the [`Float`] on the right-hand side
4200 /// by value.
4201 ///
4202 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the
4203 /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
4204 /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
4205 /// `Nearest` rounding mode.
4206 ///
4207 /// $$
4208 /// x\gets = xy+\varepsilon.
4209 /// $$
4210 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4211 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4212 /// where $p$ is the maximum precision of the inputs.
4213 ///
4214 /// See the `*` documentation for information on special cases, overflow, and underflow.
4215 ///
4216 /// If you want to use a rounding mode other than `Nearest`, consider using
4217 /// [`Float::mul_prec_assign`] instead. If you want to specify the output precision, consider
4218 /// using [`Float::mul_round_assign`]. If you want both of these things, consider using
4219 /// [`Float::mul_prec_round_assign`].
4220 ///
4221 /// # Worst-case complexity
4222 /// $T(n) = O(n \log n \log\log n)$
4223 ///
4224 /// $M(n) = O(n \log n)$
4225 ///
4226 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4227 /// other.significant_bits())`.
4228 ///
4229 /// # Examples
4230 /// ```
4231 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero};
4232 /// use malachite_float::Float;
4233 ///
4234 /// let mut x = Float::from(1.5);
4235 /// x *= Float::NAN;
4236 /// assert!(x.is_nan());
4237 ///
4238 /// let mut x = Float::from(1.5);
4239 /// x *= Float::INFINITY;
4240 /// assert_eq!(x, Float::INFINITY);
4241 ///
4242 /// let mut x = Float::from(1.5);
4243 /// x *= Float::NEGATIVE_INFINITY;
4244 /// assert_eq!(x, Float::NEGATIVE_INFINITY);
4245 ///
4246 /// let mut x = Float::from(-1.5);
4247 /// x *= Float::INFINITY;
4248 /// assert_eq!(x, Float::NEGATIVE_INFINITY);
4249 ///
4250 /// let mut x = Float::from(-1.5);
4251 /// x *= Float::NEGATIVE_INFINITY;
4252 /// assert_eq!(x, Float::INFINITY);
4253 ///
4254 /// let mut x = Float::INFINITY;
4255 /// x *= Float::ZERO;
4256 /// assert!(x.is_nan());
4257 ///
4258 /// let mut x = Float::from(1.5);
4259 /// x *= Float::from(2.5);
4260 /// assert_eq!(x, 4.0);
4261 ///
4262 /// let mut x = Float::from(1.5);
4263 /// x *= Float::from(-2.5);
4264 /// assert_eq!(x, -4.0);
4265 ///
4266 /// let mut x = Float::from(-1.5);
4267 /// x *= Float::from(2.5);
4268 /// assert_eq!(x, -4.0);
4269 ///
4270 /// let mut x = Float::from(-1.5);
4271 /// x *= Float::from(-2.5);
4272 /// assert_eq!(x, 4.0);
4273 /// ```
4274 #[inline]
4275 fn mul_assign(&mut self, other: Float) {
4276 let prec = max(self.significant_bits(), other.significant_bits());
4277 self.mul_prec_round_assign(other, prec, Nearest);
4278 }
4279}
4280
4281impl MulAssign<&Float> for Float {
4282 /// Multiplies a [`Float`] by a [`Float`] in place, taking the [`Float`] on the right-hand side
4283 /// by reference.
4284 ///
4285 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the
4286 /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
4287 /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
4288 /// `Nearest` rounding mode.
4289 ///
4290 /// $$
4291 /// x\gets = xy+\varepsilon.
4292 /// $$
4293 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4294 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4295 /// where $p$ is the maximum precision of the inputs.
4296 ///
4297 /// See the `*` documentation for information on special cases, overflow, and underflow.
4298 ///
4299 /// If you want to use a rounding mode other than `Nearest`, consider using
4300 /// [`Float::mul_prec_assign`] instead. If you want to specify the output precision, consider
4301 /// using [`Float::mul_round_assign`]. If you want both of these things, consider using
4302 /// [`Float::mul_prec_round_assign`].
4303 ///
4304 /// # Worst-case complexity
4305 /// $T(n) = O(n \log n \log\log n)$
4306 ///
4307 /// $M(n) = O(n \log n)$
4308 ///
4309 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4310 /// other.significant_bits())`.
4311 ///
4312 /// # Examples
4313 /// ```
4314 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero};
4315 /// use malachite_float::Float;
4316 ///
4317 /// let mut x = Float::from(1.5);
4318 /// x *= &Float::NAN;
4319 /// assert!(x.is_nan());
4320 ///
4321 /// let mut x = Float::from(1.5);
4322 /// x *= &Float::INFINITY;
4323 /// assert_eq!(x, Float::INFINITY);
4324 ///
4325 /// let mut x = Float::from(1.5);
4326 /// x *= &Float::NEGATIVE_INFINITY;
4327 /// assert_eq!(x, Float::NEGATIVE_INFINITY);
4328 ///
4329 /// let mut x = Float::from(-1.5);
4330 /// x *= &Float::INFINITY;
4331 /// assert_eq!(x, Float::NEGATIVE_INFINITY);
4332 ///
4333 /// let mut x = Float::from(-1.5);
4334 /// x *= &Float::NEGATIVE_INFINITY;
4335 /// assert_eq!(x, Float::INFINITY);
4336 ///
4337 /// let mut x = Float::INFINITY;
4338 /// x *= &Float::ZERO;
4339 /// assert!(x.is_nan());
4340 ///
4341 /// let mut x = Float::from(1.5);
4342 /// x *= &Float::from(2.5);
4343 /// assert_eq!(x, 4.0);
4344 ///
4345 /// let mut x = Float::from(1.5);
4346 /// x *= &Float::from(-2.5);
4347 /// assert_eq!(x, -4.0);
4348 ///
4349 /// let mut x = Float::from(-1.5);
4350 /// x *= &Float::from(2.5);
4351 /// assert_eq!(x, -4.0);
4352 ///
4353 /// let mut x = Float::from(-1.5);
4354 /// x *= &Float::from(-2.5);
4355 /// assert_eq!(x, 4.0);
4356 /// ```
4357 #[inline]
4358 fn mul_assign(&mut self, other: &Float) {
4359 let prec = max(self.significant_bits(), other.significant_bits());
4360 self.mul_prec_round_assign_ref(other, prec, Nearest);
4361 }
4362}
4363
4364impl Mul<Rational> for Float {
4365 type Output = Float;
4366
4367 /// Multiplies a [`Float`] by a [`Rational`], taking both by value.
4368 ///
4369 /// If the output has a precision, it is the precision of the input [`Float`]. If the product is
4370 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4371 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4372 /// rounding mode.
4373 ///
4374 /// $$
4375 /// f(x,y) = xy+\varepsilon.
4376 /// $$
4377 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4378 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4379 /// where $p$ is the precision of the input [`Float`].
4380 ///
4381 /// Special cases:
4382 /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$
4383 /// - $f(\infty,x)=\infty$ if $x>0$
4384 /// - $f(\infty,x)=-\infty$ if $x<0$
4385 /// - $f(-\infty,x)=-\infty$ if $x>0$
4386 /// - $f(-\infty,x)=\infty$ if $x<0$
4387 /// - $f(0.0,x)=0.0$ if $x\geq0$
4388 /// - $f(0.0,x)=-0.0$ if $x<0$
4389 /// - $f(-0.0,x)=-0.0$ if $x\geq0$
4390 /// - $f(-0.0,x)=0.0$ if $x<0$
4391 ///
4392 /// If you want to use a rounding mode other than `Nearest`, consider using
4393 /// [`Float::mul_rational_prec`] instead. If you want to specify the output precision, consider
4394 /// using [`Float::mul_rational_round`]. If you want both of these things, consider using
4395 /// [`Float::mul_rational_prec_round`].
4396 ///
4397 /// # Worst-case complexity
4398 /// $T(n) = O(n \log n \log\log n)$
4399 ///
4400 /// $M(n) = O(n \log n)$
4401 ///
4402 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4403 /// other.significant_bits())`.
4404 ///
4405 /// # Examples
4406 /// ```
4407 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
4408 /// use malachite_base::num::conversion::traits::ExactFrom;
4409 /// use malachite_float::Float;
4410 /// use malachite_q::Rational;
4411 ///
4412 /// assert!((Float::NAN * Rational::exact_from(1.5)).is_nan());
4413 /// assert_eq!(Float::INFINITY * Rational::exact_from(1.5), Float::INFINITY);
4414 /// assert_eq!(
4415 /// Float::NEGATIVE_INFINITY * Rational::exact_from(1.5),
4416 /// Float::NEGATIVE_INFINITY
4417 /// );
4418 /// assert_eq!(
4419 /// Float::INFINITY * Rational::exact_from(-1.5),
4420 /// Float::NEGATIVE_INFINITY
4421 /// );
4422 /// assert_eq!(
4423 /// Float::NEGATIVE_INFINITY * Rational::exact_from(-1.5),
4424 /// Float::INFINITY
4425 /// );
4426 ///
4427 /// assert_eq!(Float::from(2.5) * Rational::exact_from(1.5), 4.0);
4428 /// assert_eq!(Float::from(2.5) * Rational::exact_from(-1.5), -4.0);
4429 /// assert_eq!(Float::from(-2.5) * Rational::exact_from(1.5), -4.0);
4430 /// assert_eq!(Float::from(-2.5) * Rational::exact_from(-1.5), 4.0);
4431 /// ```
4432 #[inline]
4433 fn mul(self, other: Rational) -> Float {
4434 let prec = self.significant_bits();
4435 self.mul_rational_prec_round(other, prec, Nearest).0
4436 }
4437}
4438
4439impl Mul<&Rational> for Float {
4440 type Output = Float;
4441
4442 /// Multiplies a [`Float`] by a [`Rational`], taking the first by value and the second by
4443 /// reference.
4444 ///
4445 /// If the output has a precision, it is the precision of the input [`Float`]. If the product is
4446 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4447 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4448 /// rounding mode.
4449 ///
4450 /// $$
4451 /// f(x,y) = xy+\varepsilon.
4452 /// $$
4453 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4454 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4455 /// where $p$ is the precision of the input [`Float`].
4456 ///
4457 /// Special cases:
4458 /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$
4459 /// - $f(\infty,x)=\infty$ if $x>0$
4460 /// - $f(\infty,x)=-\infty$ if $x<0$
4461 /// - $f(-\infty,x)=-\infty$ if $x>0$
4462 /// - $f(-\infty,x)=\infty$ if $x<0$
4463 /// - $f(0.0,x)=0.0$ if $x\geq0$
4464 /// - $f(0.0,x)=-0.0$ if $x<0$
4465 /// - $f(-0.0,x)=-0.0$ if $x\geq0$
4466 /// - $f(-0.0,x)=0.0$ if $x<0$
4467 ///
4468 /// If you want to use a rounding mode other than `Nearest`, consider using
4469 /// [`Float::mul_rational_prec_val_ref`] instead. If you want to specify the output precision,
4470 /// consider using [`Float::mul_rational_round_val_ref`]. If you want both of these things,
4471 /// consider using [`Float::mul_rational_prec_round_val_ref`].
4472 ///
4473 /// # Worst-case complexity
4474 /// $T(n) = O(n \log n \log\log n)$
4475 ///
4476 /// $M(n) = O(n \log n)$
4477 ///
4478 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4479 /// other.significant_bits())`.
4480 ///
4481 /// # Examples
4482 /// ```
4483 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
4484 /// use malachite_base::num::conversion::traits::ExactFrom;
4485 /// use malachite_float::Float;
4486 /// use malachite_q::Rational;
4487 ///
4488 /// assert!((Float::NAN * &Rational::exact_from(1.5)).is_nan());
4489 /// assert_eq!(
4490 /// Float::INFINITY * &Rational::exact_from(1.5),
4491 /// Float::INFINITY
4492 /// );
4493 /// assert_eq!(
4494 /// Float::NEGATIVE_INFINITY * &Rational::exact_from(1.5),
4495 /// Float::NEGATIVE_INFINITY
4496 /// );
4497 /// assert_eq!(
4498 /// Float::INFINITY * &Rational::exact_from(-1.5),
4499 /// Float::NEGATIVE_INFINITY
4500 /// );
4501 /// assert_eq!(
4502 /// Float::NEGATIVE_INFINITY * &Rational::exact_from(-1.5),
4503 /// Float::INFINITY
4504 /// );
4505 ///
4506 /// assert_eq!(Float::from(2.5) * &Rational::exact_from(1.5), 4.0);
4507 /// assert_eq!(Float::from(2.5) * &Rational::exact_from(-1.5), -4.0);
4508 /// assert_eq!(Float::from(-2.5) * &Rational::exact_from(1.5), -4.0);
4509 /// assert_eq!(Float::from(-2.5) * &Rational::exact_from(-1.5), 4.0);
4510 /// ```
4511 #[inline]
4512 fn mul(self, other: &Rational) -> Float {
4513 let prec = self.significant_bits();
4514 self.mul_rational_prec_round_val_ref(other, prec, Nearest).0
4515 }
4516}
4517
4518impl Mul<Rational> for &Float {
4519 type Output = Float;
4520
4521 /// Multiplies a [`Float`] by a [`Rational`], taking the first by reference and the second by
4522 /// value.
4523 ///
4524 /// If the output has a precision, it is the precision of the input [`Float`]. If the product is
4525 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4526 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4527 /// rounding mode.
4528 ///
4529 /// $$
4530 /// f(x,y) = xy+\varepsilon.
4531 /// $$
4532 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4533 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4534 /// where $p$ is the precision of the input [`Float`].
4535 ///
4536 /// Special cases:
4537 /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$
4538 /// - $f(\infty,x)=\infty$ if $x>0$
4539 /// - $f(\infty,x)=-\infty$ if $x<0$
4540 /// - $f(-\infty,x)=-\infty$ if $x>0$
4541 /// - $f(-\infty,x)=\infty$ if $x<0$
4542 /// - $f(0.0,x)=0.0$ if $x\geq0$
4543 /// - $f(0.0,x)=-0.0$ if $x<0$
4544 /// - $f(-0.0,x)=-0.0$ if $x\geq0$
4545 /// - $f(-0.0,x)=0.0$ if $x<0$
4546 ///
4547 /// If you want to use a rounding mode other than `Nearest`, consider using
4548 /// [`Float::mul_rational_prec_ref_val`] instead. If you want to specify the output precision,
4549 /// consider using [`Float::mul_rational_round_ref_val`]. If you want both of these things,
4550 /// consider using [`Float::mul_rational_prec_round_ref_val`].
4551 ///
4552 /// # Worst-case complexity
4553 /// $T(n) = O(n \log n \log\log n)$
4554 ///
4555 /// $M(n) = O(n \log n)$
4556 ///
4557 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4558 /// other.significant_bits())`.
4559 ///
4560 /// # Examples
4561 /// ```
4562 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
4563 /// use malachite_base::num::conversion::traits::ExactFrom;
4564 /// use malachite_float::Float;
4565 /// use malachite_q::Rational;
4566 ///
4567 /// assert!((&Float::NAN * Rational::exact_from(1.5)).is_nan());
4568 /// assert_eq!(
4569 /// &Float::INFINITY * Rational::exact_from(1.5),
4570 /// Float::INFINITY
4571 /// );
4572 /// assert_eq!(
4573 /// &Float::NEGATIVE_INFINITY * Rational::exact_from(1.5),
4574 /// Float::NEGATIVE_INFINITY
4575 /// );
4576 /// assert_eq!(
4577 /// &Float::INFINITY * Rational::exact_from(-1.5),
4578 /// Float::NEGATIVE_INFINITY
4579 /// );
4580 /// assert_eq!(
4581 /// &Float::NEGATIVE_INFINITY * Rational::exact_from(-1.5),
4582 /// Float::INFINITY
4583 /// );
4584 ///
4585 /// assert_eq!(&Float::from(2.5) * Rational::exact_from(1.5), 4.0);
4586 /// assert_eq!(&Float::from(2.5) * Rational::exact_from(-1.5), -4.0);
4587 /// assert_eq!(&Float::from(-2.5) * Rational::exact_from(1.5), -4.0);
4588 /// assert_eq!(&Float::from(-2.5) * Rational::exact_from(-1.5), 4.0);
4589 /// ```
4590 #[inline]
4591 fn mul(self, other: Rational) -> Float {
4592 let prec = self.significant_bits();
4593 self.mul_rational_prec_round_ref_val(other, prec, Nearest).0
4594 }
4595}
4596
4597impl Mul<&Rational> for &Float {
4598 type Output = Float;
4599
4600 /// Multiplies a [`Float`] by a [`Rational`], taking both by reference.
4601 ///
4602 /// If the output has a precision, it is the precision of the input [`Float`]. If the product is
4603 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4604 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4605 /// rounding mode.
4606 ///
4607 /// $$
4608 /// f(x,y) = xy+\varepsilon.
4609 /// $$
4610 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4611 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4612 /// where $p$ is the precision of the input [`Float`].
4613 ///
4614 /// Special cases:
4615 /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$
4616 /// - $f(\infty,x)=\infty$ if $x>0$
4617 /// - $f(\infty,x)=-\infty$ if $x<0$
4618 /// - $f(-\infty,x)=-\infty$ if $x>0$
4619 /// - $f(-\infty,x)=\infty$ if $x<0$
4620 /// - $f(0.0,x)=0.0$ if $x\geq0$
4621 /// - $f(0.0,x)=-0.0$ if $x<0$
4622 /// - $f(-0.0,x)=-0.0$ if $x\geq0$
4623 /// - $f(-0.0,x)=0.0$ if $x<0$
4624 ///
4625 /// If you want to use a rounding mode other than `Nearest`, consider using
4626 /// [`Float::mul_rational_prec_ref_ref`] instead. If you want to specify the output precision,
4627 /// consider using [`Float::mul_rational_round_ref_ref`]. If you want both of these things,
4628 /// consider using [`Float::mul_rational_prec_round_ref_ref`].
4629 ///
4630 /// # Worst-case complexity
4631 /// $T(n) = O(n \log n \log\log n)$
4632 ///
4633 /// $M(n) = O(n \log n)$
4634 ///
4635 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4636 /// other.significant_bits())`.
4637 ///
4638 /// # Examples
4639 /// ```
4640 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
4641 /// use malachite_base::num::conversion::traits::ExactFrom;
4642 /// use malachite_float::Float;
4643 /// use malachite_q::Rational;
4644 ///
4645 /// assert!((&Float::NAN * &Rational::exact_from(1.5)).is_nan());
4646 /// assert_eq!(
4647 /// &Float::INFINITY * &Rational::exact_from(1.5),
4648 /// Float::INFINITY
4649 /// );
4650 /// assert_eq!(
4651 /// &Float::NEGATIVE_INFINITY * &Rational::exact_from(1.5),
4652 /// Float::NEGATIVE_INFINITY
4653 /// );
4654 /// assert_eq!(
4655 /// &Float::INFINITY * &Rational::exact_from(-1.5),
4656 /// Float::NEGATIVE_INFINITY
4657 /// );
4658 /// assert_eq!(
4659 /// &Float::NEGATIVE_INFINITY * &Rational::exact_from(-1.5),
4660 /// Float::INFINITY
4661 /// );
4662 ///
4663 /// assert_eq!(&Float::from(2.5) * &Rational::exact_from(1.5), 4.0);
4664 /// assert_eq!(&Float::from(2.5) * &Rational::exact_from(-1.5), -4.0);
4665 /// assert_eq!(&Float::from(-2.5) * &Rational::exact_from(1.5), -4.0);
4666 /// assert_eq!(&Float::from(-2.5) * &Rational::exact_from(-1.5), 4.0);
4667 /// ```
4668 #[inline]
4669 fn mul(self, other: &Rational) -> Float {
4670 let prec = self.significant_bits();
4671 self.mul_rational_prec_round_ref_ref(other, prec, Nearest).0
4672 }
4673}
4674
4675impl MulAssign<Rational> for Float {
4676 /// Multiplies a [`Float`] by a [`Rational`] in place, taking the [`Rational`] by value.
4677 ///
4678 /// If the output has a precision, it is the precision of the input [`Float`]. If the product is
4679 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4680 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4681 /// rounding mode.
4682 ///
4683 /// $$
4684 /// x\gets = xy+\varepsilon.
4685 /// $$
4686 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4687 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4688 /// where $p$ is the precision of the input [`Float`].
4689 ///
4690 /// See the `*` documentation for information on special cases.
4691 ///
4692 /// If you want to use a rounding mode other than `Nearest`, consider using
4693 /// [`Float::mul_rational_prec_assign`] instead. If you want to specify the output precision,
4694 /// consider using [`Float::mul_rational_round_assign`]. If you want both of these things,
4695 /// consider using [`Float::mul_rational_prec_round_assign`].
4696 ///
4697 /// # Worst-case complexity
4698 /// $T(n) = O(n \log n \log\log n)$
4699 ///
4700 /// $M(n) = O(n \log n)$
4701 ///
4702 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4703 /// other.significant_bits())`.
4704 ///
4705 /// # Examples
4706 /// ```
4707 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
4708 /// use malachite_base::num::conversion::traits::ExactFrom;
4709 /// use malachite_float::Float;
4710 /// use malachite_q::Rational;
4711 ///
4712 /// let mut x = Float::NAN;
4713 /// x *= Rational::exact_from(1.5);
4714 /// assert!(x.is_nan());
4715 ///
4716 /// let mut x = Float::INFINITY;
4717 /// x *= Rational::exact_from(1.5);
4718 /// assert_eq!(x, Float::INFINITY);
4719 ///
4720 /// let mut x = Float::NEGATIVE_INFINITY;
4721 /// x *= Rational::exact_from(1.5);
4722 /// assert_eq!(x, Float::NEGATIVE_INFINITY);
4723 ///
4724 /// let mut x = Float::INFINITY;
4725 /// x *= Rational::exact_from(-1.5);
4726 /// assert_eq!(x, Float::NEGATIVE_INFINITY);
4727 ///
4728 /// let mut x = Float::NEGATIVE_INFINITY;
4729 /// x *= Rational::exact_from(-1.5);
4730 /// assert_eq!(x, Float::INFINITY);
4731 ///
4732 /// let mut x = Float::from(2.5);
4733 /// x *= Rational::exact_from(1.5);
4734 /// assert_eq!(x, 4.0);
4735 /// ```
4736 #[inline]
4737 fn mul_assign(&mut self, other: Rational) {
4738 let prec = self.significant_bits();
4739 self.mul_rational_prec_round_assign(other, prec, Nearest);
4740 }
4741}
4742
4743impl MulAssign<&Rational> for Float {
4744 /// Multiplies a [`Float`] by a [`Rational`] in place, taking the [`Rational`] by reference.
4745 ///
4746 /// If the output has a precision, it is the precision of the input [`Float`]. If the product is
4747 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4748 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4749 /// rounding mode.
4750 ///
4751 /// $$
4752 /// x\gets = xy+\varepsilon.
4753 /// $$
4754 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4755 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4756 /// where $p$ is the precision of the input [`Float`].
4757 ///
4758 /// See the `*` documentation for information on special cases.
4759 ///
4760 /// If you want to use a rounding mode other than `Nearest`, consider using
4761 /// [`Float::mul_rational_prec_assign_ref`] instead. If you want to specify the output
4762 /// precision, consider using [`Float::mul_rational_round_assign_ref`]. If you want both of
4763 /// these things, consider using [`Float::mul_rational_prec_round_assign_ref`].
4764 ///
4765 /// # Worst-case complexity
4766 /// $T(n) = O(n \log n \log\log n)$
4767 ///
4768 /// $M(n) = O(n \log n)$
4769 ///
4770 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4771 /// other.significant_bits())`.
4772 ///
4773 /// # Examples
4774 /// ```
4775 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
4776 /// use malachite_base::num::conversion::traits::ExactFrom;
4777 /// use malachite_float::Float;
4778 /// use malachite_q::Rational;
4779 ///
4780 /// let mut x = Float::NAN;
4781 /// x *= &Rational::exact_from(1.5);
4782 /// assert!(x.is_nan());
4783 ///
4784 /// let mut x = Float::INFINITY;
4785 /// x *= &Rational::exact_from(1.5);
4786 /// assert_eq!(x, Float::INFINITY);
4787 ///
4788 /// let mut x = Float::NEGATIVE_INFINITY;
4789 /// x *= &Rational::exact_from(1.5);
4790 /// assert_eq!(x, Float::NEGATIVE_INFINITY);
4791 ///
4792 /// let mut x = Float::INFINITY;
4793 /// x *= &Rational::exact_from(-1.5);
4794 /// assert_eq!(x, Float::NEGATIVE_INFINITY);
4795 ///
4796 /// let mut x = Float::NEGATIVE_INFINITY;
4797 /// x *= &Rational::exact_from(-1.5);
4798 /// assert_eq!(x, Float::INFINITY);
4799 ///
4800 /// let mut x = Float::from(2.5);
4801 /// x *= &Rational::exact_from(1.5);
4802 /// assert_eq!(x, 4.0);
4803 /// ```
4804 #[inline]
4805 fn mul_assign(&mut self, other: &Rational) {
4806 let prec = self.significant_bits();
4807 self.mul_rational_prec_round_assign_ref(other, prec, Nearest);
4808 }
4809}
4810
4811impl Mul<Float> for Rational {
4812 type Output = Float;
4813
4814 /// Multiplies a [`Rational`] by a [`Float`], taking both by value.
4815 ///
4816 /// If the output has a precision, it is the precision of the input [`Float`]. If the product is
4817 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4818 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4819 /// rounding mode.
4820 ///
4821 /// $$
4822 /// f(x,y) = xy+\varepsilon.
4823 /// $$
4824 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4825 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4826 /// where $p$ is the precision of the input [`Float`].
4827 ///
4828 /// Special cases:
4829 /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$
4830 /// - $f(x,\infty)=\infty$ if $x>0$
4831 /// - $f(x,\infty)=-\infty$ if $x<0$
4832 /// - $f(x,-\infty)=-\infty$ if $x>0$
4833 /// - $f(x,-\infty)=\infty$ if $x<0$
4834 /// - $f(x,0.0)=0.0$ if $x\geq0$
4835 /// - $f(x,0.0)=-0.0$ if $x<0$
4836 /// - $f(x,-0.0)=-0.0$ if $x\geq0$
4837 /// - $f(x,-0.0)=0.0$ if $x<0$
4838 ///
4839 /// # Worst-case complexity
4840 /// $T(n) = O(n \log n \log\log n)$
4841 ///
4842 /// $M(n) = O(n \log n)$
4843 ///
4844 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4845 /// other.significant_bits())`.
4846 ///
4847 /// # Examples
4848 /// ```
4849 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
4850 /// use malachite_base::num::conversion::traits::ExactFrom;
4851 /// use malachite_float::Float;
4852 /// use malachite_q::Rational;
4853 ///
4854 /// assert!((Rational::exact_from(1.5) * Float::NAN).is_nan());
4855 /// assert_eq!(Rational::exact_from(1.5) * Float::INFINITY, Float::INFINITY);
4856 /// assert_eq!(
4857 /// Rational::exact_from(1.5) * Float::NEGATIVE_INFINITY,
4858 /// Float::NEGATIVE_INFINITY
4859 /// );
4860 /// assert_eq!(
4861 /// Rational::exact_from(-1.5) * Float::INFINITY,
4862 /// Float::NEGATIVE_INFINITY
4863 /// );
4864 /// assert_eq!(
4865 /// Rational::exact_from(-1.5) * Float::NEGATIVE_INFINITY,
4866 /// Float::INFINITY
4867 /// );
4868 ///
4869 /// assert_eq!(Rational::exact_from(1.5) * Float::from(2.5), 4.0);
4870 /// assert_eq!(Rational::exact_from(-1.5) * Float::from(2.5), -4.0);
4871 /// assert_eq!(Rational::exact_from(1.5) * Float::from(-2.5), -4.0);
4872 /// assert_eq!(Rational::exact_from(-1.5) * Float::from(-2.5), 4.0);
4873 /// ```
4874 #[inline]
4875 fn mul(self, other: Float) -> Float {
4876 let prec = other.significant_bits();
4877 other.mul_rational_prec_round(self, prec, Nearest).0
4878 }
4879}
4880
4881impl Mul<&Float> for Rational {
4882 type Output = Float;
4883
4884 /// Multiplies a [`Rational`] by a [`Float`], taking the [`Rational`] by value and the [`Float`]
4885 /// by reference.
4886 ///
4887 /// If the output has a precision, it is the precision of the input [`Float`]. If the product is
4888 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4889 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4890 /// rounding mode.
4891 ///
4892 /// $$
4893 /// f(x,y) = xy+\varepsilon.
4894 /// $$
4895 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4896 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4897 /// where $p$ is the precision of the input [`Float`].
4898 ///
4899 /// Special cases:
4900 /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$
4901 /// - $f(x,\infty)=\infty$ if $x>0$
4902 /// - $f(x,\infty)=-\infty$ if $x<0$
4903 /// - $f(x,-\infty)=-\infty$ if $x>0$
4904 /// - $f(x,-\infty)=\infty$ if $x<0$
4905 /// - $f(x,0.0)=0.0$ if $x\geq0$
4906 /// - $f(x,0.0)=-0.0$ if $x<0$
4907 /// - $f(x,-0.0)=-0.0$ if $x\geq0$
4908 /// - $f(x,-0.0)=0.0$ if $x<0$
4909 ///
4910 /// # Worst-case complexity
4911 /// $T(n) = O(n \log n \log\log n)$
4912 ///
4913 /// $M(n) = O(n \log n)$
4914 ///
4915 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4916 /// other.significant_bits())`.
4917 ///
4918 /// # Examples
4919 /// ```
4920 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
4921 /// use malachite_base::num::conversion::traits::ExactFrom;
4922 /// use malachite_float::Float;
4923 /// use malachite_q::Rational;
4924 ///
4925 /// assert!((Rational::exact_from(1.5) * &Float::NAN).is_nan());
4926 /// assert_eq!(
4927 /// Rational::exact_from(1.5) * &Float::INFINITY,
4928 /// Float::INFINITY
4929 /// );
4930 /// assert_eq!(
4931 /// Rational::exact_from(1.5) * &Float::NEGATIVE_INFINITY,
4932 /// Float::NEGATIVE_INFINITY
4933 /// );
4934 /// assert_eq!(
4935 /// Rational::exact_from(-1.5) * &Float::INFINITY,
4936 /// Float::NEGATIVE_INFINITY
4937 /// );
4938 /// assert_eq!(
4939 /// Rational::exact_from(-1.5) * &Float::NEGATIVE_INFINITY,
4940 /// Float::INFINITY
4941 /// );
4942 ///
4943 /// assert_eq!(Rational::exact_from(1.5) * &Float::from(2.5), 4.0);
4944 /// assert_eq!(Rational::exact_from(-1.5) * &Float::from(2.5), -4.0);
4945 /// assert_eq!(Rational::exact_from(1.5) * &Float::from(-2.5), -4.0);
4946 /// assert_eq!(Rational::exact_from(-1.5) * &Float::from(-2.5), 4.0);
4947 /// ```
4948 #[inline]
4949 fn mul(self, other: &Float) -> Float {
4950 let prec = other.significant_bits();
4951 other.mul_rational_prec_round_ref_val(self, prec, Nearest).0
4952 }
4953}
4954
4955impl Mul<Float> for &Rational {
4956 type Output = Float;
4957
4958 /// Multiplies a [`Rational`] by a [`Float`], taking the [`Rational`] by reference and the
4959 /// [`Float`] by value.
4960 ///
4961 /// If the output has a precision, it is the precision of the input [`Float`]. If the product is
4962 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4963 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4964 /// rounding mode.
4965 ///
4966 /// $$
4967 /// f(x,y) = xy+\varepsilon.
4968 /// $$
4969 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
4970 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
4971 /// where $p$ is the precision of the input [`Float`].
4972 ///
4973 /// Special cases:
4974 /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$
4975 /// - $f(x,\infty)=\infty$ if $x>0$
4976 /// - $f(x,\infty)=-\infty$ if $x<0$
4977 /// - $f(x,-\infty)=-\infty$ if $x>0$
4978 /// - $f(x,-\infty)=\infty$ if $x<0$
4979 /// - $f(x,0.0)=0.0$ if $x\geq0$
4980 /// - $f(x,0.0)=-0.0$ if $x<0$
4981 /// - $f(x,-0.0)=-0.0$ if $x\geq0$
4982 /// - $f(x,-0.0)=0.0$ if $x<0$
4983 ///
4984 /// # Worst-case complexity
4985 /// $T(n) = O(n \log n \log\log n)$
4986 ///
4987 /// $M(n) = O(n \log n)$
4988 ///
4989 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
4990 /// other.significant_bits())`.
4991 ///
4992 /// # Examples
4993 /// ```
4994 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
4995 /// use malachite_base::num::conversion::traits::ExactFrom;
4996 /// use malachite_float::Float;
4997 /// use malachite_q::Rational;
4998 ///
4999 /// assert!((&Rational::exact_from(1.5) * Float::NAN).is_nan());
5000 /// assert_eq!(
5001 /// &Rational::exact_from(1.5) * Float::INFINITY,
5002 /// Float::INFINITY
5003 /// );
5004 /// assert_eq!(
5005 /// &Rational::exact_from(1.5) * Float::NEGATIVE_INFINITY,
5006 /// Float::NEGATIVE_INFINITY
5007 /// );
5008 /// assert_eq!(
5009 /// &Rational::exact_from(-1.5) * Float::INFINITY,
5010 /// Float::NEGATIVE_INFINITY
5011 /// );
5012 /// assert_eq!(
5013 /// &Rational::exact_from(-1.5) * Float::NEGATIVE_INFINITY,
5014 /// Float::INFINITY
5015 /// );
5016 ///
5017 /// assert_eq!(&Rational::exact_from(1.5) * Float::from(2.5), 4.0);
5018 /// assert_eq!(&Rational::exact_from(-1.5) * Float::from(2.5), -4.0);
5019 /// assert_eq!(&Rational::exact_from(1.5) * Float::from(-2.5), -4.0);
5020 /// assert_eq!(&Rational::exact_from(-1.5) * Float::from(-2.5), 4.0);
5021 /// ```
5022 #[inline]
5023 fn mul(self, other: Float) -> Float {
5024 let prec = other.significant_bits();
5025 other.mul_rational_prec_round_val_ref(self, prec, Nearest).0
5026 }
5027}
5028
5029impl Mul<&Float> for &Rational {
5030 type Output = Float;
5031
5032 /// Multiplies a [`Rational`] by a [`Float`], taking both by reference.
5033 ///
5034 /// If the output has a precision, it is the precision of the input [`Float`]. If the product is
5035 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
5036 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
5037 /// rounding mode.
5038 ///
5039 /// $$
5040 /// f(x,y) = xy+\varepsilon.
5041 /// $$
5042 /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
5043 /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$,
5044 /// where $p$ is the precision of the input [`Float`].
5045 ///
5046 /// Special cases:
5047 /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$
5048 /// - $f(x,\infty)=\infty$ if $x>0$
5049 /// - $f(x,\infty)=-\infty$ if $x<0$
5050 /// - $f(x,-\infty)=-\infty$ if $x>0$
5051 /// - $f(x,-\infty)=\infty$ if $x<0$
5052 /// - $f(x,0.0)=0.0$ if $x\geq0$
5053 /// - $f(x,0.0)=-0.0$ if $x<0$
5054 /// - $f(x,-0.0)=-0.0$ if $x\geq0$
5055 /// - $f(x,-0.0)=0.0$ if $x<0$
5056 ///
5057 /// # Worst-case complexity
5058 /// $T(n) = O(n \log n \log\log n)$
5059 ///
5060 /// $M(n) = O(n \log n)$
5061 ///
5062 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
5063 /// other.significant_bits())`.
5064 ///
5065 /// # Examples
5066 /// ```
5067 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
5068 /// use malachite_base::num::conversion::traits::ExactFrom;
5069 /// use malachite_float::Float;
5070 /// use malachite_q::Rational;
5071 ///
5072 /// assert!((&Rational::exact_from(1.5) * &Float::NAN).is_nan());
5073 /// assert_eq!(
5074 /// &Rational::exact_from(1.5) * &Float::INFINITY,
5075 /// Float::INFINITY
5076 /// );
5077 /// assert_eq!(
5078 /// &Rational::exact_from(1.5) * &Float::NEGATIVE_INFINITY,
5079 /// Float::NEGATIVE_INFINITY
5080 /// );
5081 /// assert_eq!(
5082 /// &Rational::exact_from(-1.5) * &Float::INFINITY,
5083 /// Float::NEGATIVE_INFINITY
5084 /// );
5085 /// assert_eq!(
5086 /// &Rational::exact_from(-1.5) * &Float::NEGATIVE_INFINITY,
5087 /// Float::INFINITY
5088 /// );
5089 ///
5090 /// assert_eq!(&Rational::exact_from(1.5) * &Float::from(2.5), 4.0);
5091 /// assert_eq!(&Rational::exact_from(-1.5) * &Float::from(2.5), -4.0);
5092 /// assert_eq!(&Rational::exact_from(1.5) * &Float::from(-2.5), -4.0);
5093 /// assert_eq!(&Rational::exact_from(-1.5) * &Float::from(-2.5), 4.0);
5094 /// ```
5095 #[inline]
5096 fn mul(self, other: &Float) -> Float {
5097 let prec = other.significant_bits();
5098 other.mul_rational_prec_round_ref_ref(self, prec, Nearest).0
5099 }
5100}