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