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