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