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