1#![cfg_attr(rustfmt, rustfmt_skip)]
6
7use std::cmp::Ordering;
8
9use crate::value::is::IsNumber;
10
11pub trait Promote<R> where Self: IsNumber, R: IsNumber {
12 type Output: IsNumber;
13 fn checked_promote(&self, r: &R) -> Option<(Self::Output, Self::Output)>;
14 fn saturating_promote(&self, r: &R) -> (Self::Output, Self::Output);
15 fn wrapping_promote(&self, r: &R) -> (Self::Output, Self::Output);
16
17 fn compare(&self, r: &R) -> Option<Ordering> {
18 self.checked_promote(r).and_then(|(l, r)| l.partial_cmp(&r))
19 }
20}
21
22macro_rules! impl_promote_float_float {
23 ($l:ty, $r:ty => $common:ty) => {
24 impl Promote<$r> for $l {
25 type Output = $common;
26
27 fn checked_promote(&self, r: &$r) -> Option<(Self::Output, Self::Output)> {
28 Some((*self as $common, *r as $common))
29 }
30
31 fn saturating_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
32 let l = if self.is_finite() {
33 *self as $common
34 } else if self.is_sign_negative() {
35 <$common>::MIN
36 } else {
37 <$common>::MAX
38 };
39 let r = if r.is_finite() {
40 *r as $common
41 } else if r.is_sign_negative() {
42 <$common>::MIN
43 } else {
44 <$common>::MAX
45 };
46 (l, r)
47 }
48
49 fn wrapping_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
50 (*self as $common, *r as $common)
51 }
52 }
53 };
54}
55
56macro_rules! impl_promote_float_integer {
57 ($l:ty, $r:ty => $common:ty) => {
58 impl Promote<$r> for $l {
59 type Output = $common;
60
61 fn checked_promote(&self, r: &$r) -> Option<(Self::Output, Self::Output)> {
62 if self.is_finite() {
63 Some((*self as $common, *r as $common))
64 } else {
65 None
66 }
67 }
68
69 fn saturating_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
70 let l = if self.is_finite() {
71 *self as $common
72 } else if self.is_sign_negative() {
73 <$common>::MIN
74 } else {
75 <$common>::MAX
76 };
77
78 let r = *r as $common;
79 (l, r)
80 }
81
82 fn wrapping_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
83 (*self as $common, *r as $common)
84 }
85 }
86 };
87}
88
89
90macro_rules! impl_promote_integer_float {
91 ($l:ty, $r:ty => $common:ty) => {
92 impl Promote<$r> for $l {
93 type Output = $common;
94
95 fn checked_promote(&self, r: &$r) -> Option<(Self::Output, Self::Output)> {
96 if r.is_finite() {
97 Some((*self as $common, *r as $common))
98 } else {
99 None
100 }
101 }
102
103 fn saturating_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
104 let l = *self as $common;
105 let r = if r.is_finite() {
106 *r as $common
107 } else if r.is_sign_negative() {
108 <$common>::MIN
109 } else {
110 <$common>::MAX
111 };
112 (l, r)
113 }
114
115 fn wrapping_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
116 (*self as $common, *r as $common)
117 }
118 }
119 };
120}
121
122
123
124impl_promote_float_float!(f32, f32 => f64);
125impl_promote_float_float!(f32, f64 => f64); impl_promote_float_float!(f64, f32 => f64);
126impl_promote_float_float!(f64, f64 => f64);
127
128
129
130impl_promote_float_integer!(f32, i8 => f64); impl_promote_integer_float!(i8, f32 => f64);
131impl_promote_float_integer!(f32, i16 => f64); impl_promote_integer_float!(i16, f32 => f64);
132impl_promote_float_integer!(f32, i32 => f64); impl_promote_integer_float!(i32, f32 => f64);
133impl_promote_float_integer!(f32, i64 => f64); impl_promote_integer_float!(i64, f32 => f64);
134impl_promote_float_integer!(f32, i128 => f64); impl_promote_integer_float!(i128, f32 => f64);
135
136impl_promote_float_integer!(f64, i8 => f64); impl_promote_integer_float!(i8, f64 => f64);
137impl_promote_float_integer!(f64, i16 => f64); impl_promote_integer_float!(i16, f64 => f64);
138impl_promote_float_integer!(f64, i32 => f64); impl_promote_integer_float!(i32, f64 => f64);
139impl_promote_float_integer!(f64, i64 => f64); impl_promote_integer_float!(i64, f64 => f64);
140impl_promote_float_integer!(f64, i128 => f64); impl_promote_integer_float!(i128, f64 => f64);
141
142
143
144impl_promote_float_integer!(f32, u8 => f64); impl_promote_integer_float!(u8, f32 => f64);
145impl_promote_float_integer!(f32, u16 => f64); impl_promote_integer_float!(u16, f32 => f64);
146impl_promote_float_integer!(f32, u32 => f64); impl_promote_integer_float!(u32, f32 => f64);
147impl_promote_float_integer!(f32, u64 => f64); impl_promote_integer_float!(u64, f32 => f64);
148impl_promote_float_integer!(f32, u128 => f64); impl_promote_integer_float!(u128, f32 => f64);
149
150impl_promote_float_integer!(f64, u8 => f64); impl_promote_integer_float!(u8, f64 => f64);
151impl_promote_float_integer!(f64, u16 => f64); impl_promote_integer_float!(u16, f64 => f64);
152impl_promote_float_integer!(f64, u32 => f64); impl_promote_integer_float!(u32, f64 => f64);
153impl_promote_float_integer!(f64, u64 => f64); impl_promote_integer_float!(u64, f64 => f64);
154impl_promote_float_integer!(f64, u128 => f64); impl_promote_integer_float!(u128, f64 => f64);
155
156
157macro_rules! impl_promote_signed_signed {
158 ($l:ty, $r:ty => $common:ty) => {
159 impl Promote<$r> for $l {
160 type Output = $common;
161
162 fn checked_promote(&self, r: &$r) -> Option<(Self::Output, Self::Output)>{
163 let l: Option<$common> = <$common>::try_from(*self).ok();
164 let r: Option<$common> = <$common>::try_from(*r).ok();
165 match(l,r){
166 (Some(l),Some(r)) => Some((l,r)),
167 _ => None
168 }
169 }
170
171 fn saturating_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
172 let l = match <$common>::try_from(*self) {
173 Ok(v) => v,
174 Err(_) => if *self < 0 { <$common>::MIN } else { <$common>::MAX }};
175 let r = match <$common>::try_from(*r) {
176 Ok(v) => v,
177 Err(_) => if *r < 0 { <$common>::MIN } else { <$common>::MAX }};
178 (l, r)
179 }
180
181 fn wrapping_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
182 (*self as $common, *r as $common)
183 }
184 }
185 };
186}
187impl_promote_signed_signed!(i8, i8 => i128);
188impl_promote_signed_signed!(i8, i16 => i128); impl_promote_signed_signed!(i16, i8 => i128);
189impl_promote_signed_signed!(i8, i32 => i128); impl_promote_signed_signed!(i32, i8 => i128);
190impl_promote_signed_signed!(i8, i64 => i128); impl_promote_signed_signed!(i64, i8 => i128);
191impl_promote_signed_signed!(i8, i128 => i128); impl_promote_signed_signed!(i128, i8 => i128);
192
193impl_promote_signed_signed!(i16, i16 => i128);
194impl_promote_signed_signed!(i16, i32 => i128); impl_promote_signed_signed!(i32, i16 => i128);
195impl_promote_signed_signed!(i16, i64 => i128); impl_promote_signed_signed!(i64, i16 => i128);
196impl_promote_signed_signed!(i16, i128 => i128); impl_promote_signed_signed!(i128, i16 => i128);
197
198impl_promote_signed_signed!(i32, i32 => i128);
199impl_promote_signed_signed!(i32, i64 => i128); impl_promote_signed_signed!(i64, i32 => i128);
200impl_promote_signed_signed!(i32, i128 => i128); impl_promote_signed_signed!(i128, i32 => i128);
201
202impl_promote_signed_signed!(i64, i64 => i128);
203impl_promote_signed_signed!(i64, i128 => i128); impl_promote_signed_signed!(i128, i64 => i128);
204
205impl_promote_signed_signed!(i128, i128 => i128);
206
207macro_rules! impl_promote_unsigned_unsigned {
208 ($l:ty, $r:ty => $common:ty) => {
209 impl Promote<$r> for $l {
210 type Output = $common;
211
212 fn checked_promote(&self, r: &$r) -> Option<(Self::Output, Self::Output)>{
213 let l: Option<$common> = <$common>::try_from(*self).ok();
214 let r: Option<$common> = <$common>::try_from(*r).ok();
215 match(l,r){
216 (Some(l),Some(r)) => Some((l,r)),
217 _ => None
218 }
219 }
220
221 fn saturating_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
222 let l = match <$common>::try_from(*self) {
223 Ok(v) => v,
224 Err(_) => <$common>::MAX};
225 let r = match <$common>::try_from(*r) {
226 Ok(v) => v,
227 Err(_) => <$common>::MAX};
228 (l, r)
229 }
230
231 fn wrapping_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
232 (*self as $common, *r as $common)
233 }
234 }
235 };
236}
237
238impl_promote_unsigned_unsigned!(u8, u8 => u128);
239impl_promote_unsigned_unsigned!(u8, u16 => u128); impl_promote_unsigned_unsigned!(u16, u8 => u128);
240impl_promote_unsigned_unsigned!(u8, u32 => u128); impl_promote_unsigned_unsigned!(u32, u8 => u128);
241impl_promote_unsigned_unsigned!(u8, u64 => u128); impl_promote_unsigned_unsigned!(u64, u8 => u128);
242impl_promote_unsigned_unsigned!(u8, u128 => u128); impl_promote_unsigned_unsigned!(u128, u8 => u128);
243
244impl_promote_unsigned_unsigned!(u16, u16 => u128);
245impl_promote_unsigned_unsigned!(u16, u32 => u128); impl_promote_unsigned_unsigned!(u32, u16 => u128);
246impl_promote_unsigned_unsigned!(u16, u64 => u128); impl_promote_unsigned_unsigned!(u64, u16 => u128);
247impl_promote_unsigned_unsigned!(u16, u128 => u128); impl_promote_unsigned_unsigned!(u128, u16 => u128);
248
249impl_promote_unsigned_unsigned!(u32, u32 => u128);
250impl_promote_unsigned_unsigned!(u32, u64 => u128); impl_promote_unsigned_unsigned!(u64, u32 => u128);
251impl_promote_unsigned_unsigned!(u32, u128 => u128); impl_promote_unsigned_unsigned!(u128, u32 => u128);
252
253impl_promote_unsigned_unsigned!(u64, u64 => u128);
254impl_promote_unsigned_unsigned!(u64, u128 => u128); impl_promote_unsigned_unsigned!(u128, u64 => u128);
255
256impl_promote_unsigned_unsigned!(u128, u128 => u128);
257
258
259macro_rules! impl_promote_signed_unsigned {
260 ($l:ty, $r:ty => $common:ty) => {
261 impl Promote<$r> for $l {
262 type Output = $common;
263
264 fn checked_promote(&self, r: &$r) -> Option<(Self::Output, Self::Output)>{
265 let l: Option<$common> = <$common>::try_from(*self).ok();
266 let r: Option<$common> = <$common>::try_from(*r).ok();
267 match(l,r){
268 (Some(l),Some(r)) => Some((l,r)),
269 _ => None
270 }
271 }
272
273 fn saturating_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
274 let l = match <$common>::try_from(*self) {
275 Ok(v) => v,
276 Err(_) => if *self < 0 { <$common>::MIN } else { <$common>::MAX }};
277 let r = match <$common>::try_from(*r) {
278 Ok(v) => v,
279 Err(_) => <$common>::MAX};
280 (l, r)
281 }
282
283 fn wrapping_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
284 (*self as $common, *r as $common)
285 }
286
287 fn compare(&self, r: &$r) -> Option<Ordering> {
288 if *self < 0 {
289 return Some(Ordering::Less);
290 }
291 Some((*self as u128).cmp(&(*r as u128)))
292 }
293 }
294 };
295}
296
297macro_rules! impl_promote_unsigned_signed {
298 ($l:ty, $r:ty => $common:ty) => {
299 impl Promote<$r> for $l {
300 type Output = $common;
301
302 fn checked_promote(&self, r: &$r) -> Option<(Self::Output, Self::Output)>{
303 let l: Option<$common> = <$common>::try_from(*self).ok();
304 let r: Option<$common> = <$common>::try_from(*r).ok();
305 match(l,r){
306 (Some(l),Some(r)) => Some((l,r)),
307 _ => None
308 }
309 }
310
311 fn saturating_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
312 let l = match <$common>::try_from(*self) {
313 Ok(v) => v,
314 Err(_) => <$common>::MAX};
315 let r = match <$common>::try_from(*r) {
316 Ok(v) => v,
317 Err(_) => if *r < 0 { <$common>::MIN } else { <$common>::MAX }};
318 (l, r)
319 }
320
321 fn wrapping_promote(&self, r: &$r) -> (Self::Output, Self::Output) {
322 (*self as $common, *r as $common)
323 }
324
325 fn compare(&self, r: &$r) -> Option<Ordering> {
326 if *r < 0 {
327 return Some(Ordering::Greater);
328 }
329 Some((*self as u128).cmp(&(*r as u128)))
330 }
331 }
332 };
333}
334
335impl_promote_signed_unsigned!(i8, u8 => i128); impl_promote_unsigned_signed!(u8, i8 => i128);
336impl_promote_signed_unsigned!(i8, u16 => i128); impl_promote_unsigned_signed!(u16, i8 => i128);
337impl_promote_signed_unsigned!(i8, u32 => i128); impl_promote_unsigned_signed!(u32, i8 => i128);
338impl_promote_signed_unsigned!(i8, u64 => i128); impl_promote_unsigned_signed!(u64, i8 => i128);
339impl_promote_signed_unsigned!(i8, u128 => i128); impl_promote_unsigned_signed!(u128, i8 => i128);
340impl_promote_signed_unsigned!(i16, u8 => i128); impl_promote_unsigned_signed!(u8, i16 => i128);
341impl_promote_signed_unsigned!(i16, u16 => i128); impl_promote_unsigned_signed!(u16, i16 => i128);
342impl_promote_signed_unsigned!(i16, u32 => i128); impl_promote_unsigned_signed!(u32, i16 => i128);
343impl_promote_signed_unsigned!(i16, u64 => i128); impl_promote_unsigned_signed!(u64, i16 => i128);
344impl_promote_signed_unsigned!(i16, u128 => i128); impl_promote_unsigned_signed!(u128, i16 => i128);
345impl_promote_signed_unsigned!(i32, u8 => i128); impl_promote_unsigned_signed!(u8, i32 => i128);
346impl_promote_signed_unsigned!(i32, u16 => i128); impl_promote_unsigned_signed!(u16, i32 => i128);
347impl_promote_signed_unsigned!(i32, u32 => i128); impl_promote_unsigned_signed!(u32, i32 => i128);
348impl_promote_signed_unsigned!(i32, u64 => i128); impl_promote_unsigned_signed!(u64, i32 => i128);
349impl_promote_signed_unsigned!(i32, u128 => i128); impl_promote_unsigned_signed!(u128, i32 => i128);
350impl_promote_signed_unsigned!(i64, u8 => i128); impl_promote_unsigned_signed!(u8, i64 => i128);
351impl_promote_signed_unsigned!(i64, u16 => i128); impl_promote_unsigned_signed!(u16, i64 => i128);
352impl_promote_signed_unsigned!(i64, u32 => i128); impl_promote_unsigned_signed!(u32, i64 => i128);
353impl_promote_signed_unsigned!(i64, u64 => i128); impl_promote_unsigned_signed!(u64, i64 => i128);
354impl_promote_signed_unsigned!(i64, u128 => i128); impl_promote_unsigned_signed!(u128, i64 => i128);
355impl_promote_signed_unsigned!(i128, u8 => i128); impl_promote_unsigned_signed!(u8, i128 => i128);
356impl_promote_signed_unsigned!(i128, u16 => i128); impl_promote_unsigned_signed!(u16, i128 => i128);
357impl_promote_signed_unsigned!(i128, u32 => i128); impl_promote_unsigned_signed!(u32, i128 => i128);
358impl_promote_signed_unsigned!(i128, u64 => i128); impl_promote_unsigned_signed!(u64, i128 => i128);
359impl_promote_signed_unsigned!(i128, u128 => i128); impl_promote_unsigned_signed!(u128, i128 => i128);
360
361use crate::value::decimal::Decimal;
362
363impl Promote<Decimal> for Decimal {
364 type Output = Decimal;
365
366 fn checked_promote(&self, r: &Decimal) -> Option<(Self::Output, Self::Output)> {
367 Some((self.clone(), r.clone()))
368 }
369
370 fn saturating_promote(&self, r: &Decimal) -> (Self::Output, Self::Output) {
371 (self.clone(), r.clone())
372 }
373
374 fn wrapping_promote(&self, r: &Decimal) -> (Self::Output, Self::Output) {
375 (self.clone(), r.clone())
376 }
377}
378
379impl Promote<Decimal> for f32 {
380 type Output = Decimal;
381
382 fn checked_promote(&self, r: &Decimal) -> Option<(Self::Output, Self::Output)> {
383 if self.is_finite() {
384 Some((Decimal::from(*self), r.clone()))
385 } else {
386 None
387 }
388 }
389
390 fn saturating_promote(&self, r: &Decimal) -> (Self::Output, Self::Output) {
391 let l_as_decimal = if self.is_finite() {
392 Decimal::from(*self)
393 } else {
394 Decimal::zero()
395 };
396 (l_as_decimal, r.clone())
397 }
398
399 fn wrapping_promote(&self, r: &Decimal) -> (Self::Output, Self::Output) {
400 let l_as_decimal = if self.is_finite() {
401 Decimal::from(*self)
402 } else {
403 Decimal::zero()
404 };
405 (l_as_decimal, r.clone())
406 }
407}
408
409impl Promote<f32> for Decimal {
410 type Output = Decimal;
411
412 fn checked_promote(&self, r: &f32) -> Option<(Self::Output, Self::Output)> {
413 if r.is_finite() {
414 Some((self.clone(), Decimal::from(*r)))
415 } else {
416 None
417 }
418 }
419
420 fn saturating_promote(&self, r: &f32) -> (Self::Output, Self::Output) {
421 let r_as_decimal = if r.is_finite() {
422 Decimal::from(*r)
423 } else {
424 Decimal::zero()
425 };
426 (self.clone(), r_as_decimal)
427 }
428
429 fn wrapping_promote(&self, r: &f32) -> (Self::Output, Self::Output) {
430 let r_as_decimal = if r.is_finite() {
431 Decimal::from(*r)
432 } else {
433 Decimal::zero()
434 };
435 (self.clone(), r_as_decimal)
436 }
437}
438
439
440impl Promote<Decimal> for f64 {
441 type Output = Decimal;
442
443 fn checked_promote(&self, r: &Decimal) -> Option<(Self::Output, Self::Output)> {
444 if self.is_finite() {
445 let l_as_decimal = Decimal::from(*self);
446 Some((l_as_decimal, r.clone()))
447 } else {
448 None
449 }
450 }
451
452 fn saturating_promote(&self, r: &Decimal) -> (Self::Output, Self::Output) {
453 let l_as_decimal = if self.is_finite() {
454 Decimal::from(*self)
455 } else {
456 Decimal::zero()
457 };
458 (l_as_decimal, r.clone())
459 }
460
461 fn wrapping_promote(&self, r: &Decimal) -> (Self::Output, Self::Output) {
462 let l_as_decimal = if self.is_finite() {
463 Decimal::from(*self)
464 } else {
465 Decimal::zero()
466 };
467 (l_as_decimal, r.clone())
468 }
469}
470
471impl Promote<f64> for Decimal {
472 type Output = Decimal;
473
474 fn checked_promote(&self, r: &f64) -> Option<(Self::Output, Self::Output)> {
475 if r.is_finite() {
476 let r_as_decimal = Decimal::from(*r);
477 Some((self.clone(), r_as_decimal))
478 } else {
479 None
480 }
481 }
482
483 fn saturating_promote(&self, r: &f64) -> (Self::Output, Self::Output) {
484 let r_as_decimal = if r.is_finite() {
485 Decimal::from(*r)
486 } else {
487 Decimal::zero()
488 };
489 (self.clone(), r_as_decimal)
490 }
491
492 fn wrapping_promote(&self, r: &f64) -> (Self::Output, Self::Output) {
493 let r_as_decimal = if r.is_finite() {
494 Decimal::from(*r)
495 } else {
496 Decimal::zero()
497 };
498 (self.clone(), r_as_decimal)
499 }
500}
501
502
503macro_rules! impl_promote_int_to_decimal {
504 ($($t:ty),*) => {
505 $(
506 impl Promote<Decimal> for $t {
507 type Output = Decimal;
508
509 fn checked_promote(&self, r: &Decimal) -> Option<(Self::Output, Self::Output)> {
510 Some((Decimal::from(*self), r.clone()))
511 }
512
513 fn saturating_promote(&self, r: &Decimal) -> (Self::Output, Self::Output) {
514 (Decimal::from(*self), r.clone())
515 }
516
517 fn wrapping_promote(&self, r: &Decimal) -> (Self::Output, Self::Output) {
518 (Decimal::from(*self), r.clone())
519 }
520 }
521
522 impl Promote<$t> for Decimal {
523 type Output = Decimal;
524
525 fn checked_promote(&self, r: &$t) -> Option<(Self::Output, Self::Output)> {
526 Some((self.clone(), Decimal::from(*r)))
527 }
528
529 fn saturating_promote(&self, r: &$t) -> (Self::Output, Self::Output) {
530 (self.clone(), Decimal::from(*r))
531 }
532
533 fn wrapping_promote(&self, r: &$t) -> (Self::Output, Self::Output) {
534 (self.clone(), Decimal::from(*r))
535 }
536 }
537 )*
538 }
539}
540
541impl_promote_int_to_decimal!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128);