Skip to main content

base_traits/traits/
is_negative.rs

1// src/traits/is_negative.rs : `IsNegative`
2
3/// Trait defining instance method `is_negative() : bool` that indicates
4/// whether the implementing type instance has a value that is deemed to be
5/// negative.
6///
7/// # Additional Implementations on Foreign Types
8///
9/// ## Built-in Types
10///
11/// If the feature `"implement-IsNegative-for-built_ins"`
12/// is defined (as it is by `"default"`), then this is also implemented
13/// for the following types:
14/// - [`f32`];
15/// - [`f64`];
16/// - [`i8`];
17/// - [`i16`];
18/// - [`i32`];
19/// - [`i64`];
20/// - [`i128`];
21/// - [`u8`];
22/// - [`u16`];
23/// - [`u32`];
24/// - [`u64`];
25/// - [`u128`];
26/// - [`isize`];
27/// - [`usize`];
28pub trait IsNegative {
29    fn is_negative(&self) -> bool;
30}
31
32
33#[cfg(any(test, not(feature = "nostd")))]
34impl<T : IsNegative + ?Sized> IsNegative for Box<T> {
35    fn is_negative(&self) -> bool {
36        (**self).is_negative()
37    }
38}
39
40#[cfg(any(test, not(feature = "nostd")))]
41impl<T : IsNegative + ?Sized> IsNegative for std::rc::Rc<T> {
42    fn is_negative(&self) -> bool {
43        (**self).is_negative()
44    }
45}
46
47
48#[cfg(feature = "implement-IsNegative-for-built_ins")]
49mod impl_for_built_ins {
50    #![allow(non_snake_case)]
51
52    macro_rules! implement_IsNegative_fp_ {
53        ($type:tt) => {
54            impl super::IsNegative for $type {
55                #[inline]
56                fn is_negative(&self) -> bool {
57                    $type::is_sign_negative(*self)
58                }
59            }
60        };
61    }
62
63    macro_rules! implement_IsNegative_si_ {
64        ($type:tt) => {
65            impl super::IsNegative for $type {
66                #[inline]
67                fn is_negative(&self) -> bool {
68                    *self < 0
69                }
70            }
71        };
72    }
73
74    macro_rules! implement_IsNegative_su_ {
75        ($type:tt) => {
76            impl super::IsNegative for $type {
77                #[inline]
78                fn is_negative(&self) -> bool {
79                    false
80                }
81            }
82        };
83    }
84
85    implement_IsNegative_fp_!(f32);
86    implement_IsNegative_fp_!(f64);
87
88    implement_IsNegative_si_!(i8);
89    implement_IsNegative_si_!(i16);
90    implement_IsNegative_si_!(i32);
91    implement_IsNegative_si_!(i64);
92    implement_IsNegative_si_!(i128);
93    implement_IsNegative_si_!(isize);
94
95    implement_IsNegative_su_!(u8);
96    implement_IsNegative_su_!(u16);
97    implement_IsNegative_su_!(u32);
98    implement_IsNegative_su_!(u64);
99    implement_IsNegative_su_!(u128);
100    implement_IsNegative_su_!(usize);
101}
102
103
104#[cfg(test)]
105mod tests {
106    #![allow(non_snake_case)]
107
108    use super::IsNegative;
109
110    use std::rc::Rc;
111
112
113    #[allow(unused)]
114    fn as_IsNegative<T : IsNegative>(t : &T) -> &impl IsNegative {
115        t
116    }
117
118    fn assert_is_negative_<T : IsNegative + std::fmt::Debug>(
119        value : &T,
120        expected : bool,
121    ) {
122        assert_eq!(expected, value.is_negative());
123
124        let via = as_IsNegative(value);
125
126        assert_eq!(expected, via.is_negative());
127    }
128
129
130    mod TEST_CUSTOM_TYPE {
131        #![allow(non_snake_case)]
132
133        use super::*;
134
135
136        #[derive(Debug)]
137        struct CustomType {
138            value : i32,
139        }
140
141        impl IsNegative for CustomType {
142            fn is_negative(&self) -> bool {
143                self.value < 0
144            }
145        }
146
147
148        #[test]
149        fn TEST_WHEN_NEGATIVE() {
150            let ct = CustomType {
151                value : -1
152            };
153
154            assert!(ct.is_negative());
155
156            let ct = &ct;
157
158            assert!(ct.is_negative());
159        }
160
161        #[test]
162        fn TEST_WHEN_ZERO() {
163            let ct = CustomType {
164                value : 0
165            };
166
167            assert!(!ct.is_negative());
168
169            let ct = &ct;
170
171            assert!(!ct.is_negative());
172        }
173
174        #[test]
175        fn TEST_WHEN_POSITIVE() {
176            let ct = CustomType {
177                value : 1
178            };
179
180            assert!(!ct.is_negative());
181
182            let ct = &ct;
183
184            assert!(!ct.is_negative());
185        }
186
187        #[test]
188        fn TEST_WHEN_NEGATIVE_IN_Box() {
189            {
190                let ct = Box::new(CustomType {
191                    value : -1
192                });
193
194                assert!(ct.is_negative());
195
196                let ct = &ct;
197
198                assert!(ct.is_negative());
199            }
200
201            {
202                let ct = &Box::new(CustomType {
203                    value : -1
204                });
205
206                assert!(ct.is_negative());
207
208                let ct = &ct;
209
210                assert!(ct.is_negative());
211            }
212
213            {
214                let ct = Box::new(&CustomType {
215                    value : -1
216                });
217
218                assert!(ct.is_negative());
219
220                let ct = &ct;
221
222                assert!(ct.is_negative());
223            }
224
225            {
226                let ct = &Box::new(&CustomType {
227                    value : -1
228                });
229
230                assert!(ct.is_negative());
231
232                let ct = &ct;
233
234                assert!(ct.is_negative());
235            }
236        }
237
238        #[test]
239        fn TEST_WHEN_NEGATIVE_IN_Rc() {
240            {
241                let ct = Rc::new(CustomType {
242                    value : -1
243                });
244
245                assert!(ct.is_negative());
246
247                let ct = &ct;
248
249                assert!(ct.is_negative());
250            }
251
252            {
253                let ct = &Rc::new(CustomType {
254                    value : -1
255                });
256
257                assert!(ct.is_negative());
258
259                let ct = &ct;
260
261                assert!(ct.is_negative());
262            }
263
264            {
265                let ct = Rc::new(&CustomType {
266                    value : -1
267                });
268
269                assert!(ct.is_negative());
270
271                let ct = &ct;
272
273                assert!(ct.is_negative());
274            }
275
276            {
277                let ct = &Rc::new(&CustomType {
278                    value : -1
279                });
280
281                assert!(ct.is_negative());
282
283                let ct = &ct;
284
285                assert!(ct.is_negative());
286            }
287        }
288    }
289
290
291    #[cfg(feature = "implement-IsNegative-for-built_ins")]
292    mod TEST_BUILTIN_TYPES {
293        #![allow(non_snake_case)]
294
295        use super::*;
296
297
298        fn assert_signed_<T>(
299            zero : T,
300            one : T,
301            neg_one : T,
302            min : T,
303            max : T,
304        ) where
305            T : Copy + IsNegative + std::fmt::Debug,
306        {
307            assert_is_negative_(&zero, false);
308            assert_is_negative_(&one, false);
309            assert_is_negative_(&neg_one, true);
310            assert_is_negative_(&min, true);
311            assert_is_negative_(&max, false);
312        }
313
314        fn assert_unsigned_<T>(
315            zero : T,
316            one : T,
317            max : T,
318        ) where
319            T : Copy + IsNegative + std::fmt::Debug,
320        {
321            assert_is_negative_(&zero, false);
322            assert_is_negative_(&one, false);
323            assert_is_negative_(&max, false);
324        }
325
326        fn assert_float_<T>(
327            value : T,
328            expected : bool,
329        ) where
330            T : Copy + IsNegative + std::fmt::Debug,
331        {
332            assert_is_negative_(&value, expected);
333
334            let boxed = Box::new(value);
335
336            assert_eq!(expected, boxed.is_negative());
337
338            let boxed = &boxed;
339
340            assert_eq!(expected, boxed.is_negative());
341
342            let rc = Rc::new(value);
343
344            assert_eq!(expected, rc.is_negative());
345
346            let rc = &rc;
347
348            assert_eq!(expected, rc.is_negative());
349        }
350
351
352        mod TEST_f32 {
353            #![allow(non_snake_case)]
354
355            use super::*;
356
357
358            #[test]
359            fn TEST_SIGN_CASES() {
360                assert_float_(0.0f32, false);
361                assert_float_(-0.0f32, true);
362                assert_float_(1.0f32, false);
363                assert_float_(-1.0f32, true);
364                assert_float_(f32::MIN_POSITIVE, false);
365                assert_float_(-f32::MIN_POSITIVE, true);
366                assert_float_(f32::MIN, true);
367                assert_float_(f32::MAX, false);
368                assert_float_(f32::INFINITY, false);
369                assert_float_(f32::NEG_INFINITY, true);
370                assert_float_(f32::from_bits(1), false);
371                assert_float_(f32::from_bits(0x8000_0001), true);
372                assert_float_(f32::NAN.copysign(1.0), false);
373                assert_float_(f32::NAN.copysign(-1.0), true);
374            }
375        }
376
377
378        mod TEST_f64 {
379            #![allow(non_snake_case)]
380
381            use super::*;
382
383
384            #[test]
385            fn TEST_SIGN_CASES() {
386                assert_float_(0.0f64, false);
387                assert_float_(-0.0f64, true);
388                assert_float_(1.0f64, false);
389                assert_float_(-1.0f64, true);
390                assert_float_(f64::MIN_POSITIVE, false);
391                assert_float_(-f64::MIN_POSITIVE, true);
392                assert_float_(f64::MIN, true);
393                assert_float_(f64::MAX, false);
394                assert_float_(f64::INFINITY, false);
395                assert_float_(f64::NEG_INFINITY, true);
396                assert_float_(f64::from_bits(1), false);
397                assert_float_(f64::from_bits(0x8000_0000_0000_0001), true);
398                assert_float_(f64::NAN.copysign(1.0), false);
399                assert_float_(f64::NAN.copysign(-1.0), true);
400            }
401        }
402
403
404        mod TEST_i8 {
405            #![allow(non_snake_case)]
406
407            use super::*;
408
409
410            #[test]
411            fn TEST_SIGN_CASES() {
412                assert_signed_(0i8, 1, -1, i8::MIN, i8::MAX);
413            }
414        }
415
416
417        mod TEST_i16 {
418            #![allow(non_snake_case)]
419
420            use super::*;
421
422
423            #[test]
424            fn TEST_SIGN_CASES() {
425                assert_signed_(0i16, 1, -1, i16::MIN, i16::MAX);
426            }
427        }
428
429
430        mod TEST_i32 {
431            #![allow(non_snake_case)]
432
433            use super::*;
434
435
436            #[test]
437            fn TEST_SIGN_CASES() {
438                assert_signed_(0i32, 1, -1, i32::MIN, i32::MAX);
439            }
440        }
441
442
443        mod TEST_i64 {
444            #![allow(non_snake_case)]
445
446            use super::*;
447
448
449            #[test]
450            fn TEST_SIGN_CASES() {
451                assert_signed_(0i64, 1, -1, i64::MIN, i64::MAX);
452            }
453        }
454
455
456        mod TEST_i128 {
457            #![allow(non_snake_case)]
458
459            use super::*;
460
461
462            #[test]
463            fn TEST_SIGN_CASES() {
464                assert_signed_(0i128, 1, -1, i128::MIN, i128::MAX);
465            }
466        }
467
468
469        mod TEST_isize {
470            #![allow(non_snake_case)]
471
472            use super::*;
473
474
475            #[test]
476            fn TEST_SIGN_CASES() {
477                assert_signed_(0isize, 1, -1, isize::MIN, isize::MAX);
478            }
479        }
480
481
482        mod TEST_u8 {
483            #![allow(non_snake_case)]
484
485            use super::*;
486
487
488            #[test]
489            fn TEST_SIGN_CASES() {
490                assert_unsigned_(0u8, 1, u8::MAX);
491            }
492        }
493
494
495        mod TEST_u16 {
496            #![allow(non_snake_case)]
497
498            use super::*;
499
500
501            #[test]
502            fn TEST_SIGN_CASES() {
503                assert_unsigned_(0u16, 1, u16::MAX);
504            }
505        }
506
507
508        mod TEST_u32 {
509            #![allow(non_snake_case)]
510
511            use super::*;
512
513
514            #[test]
515            fn TEST_SIGN_CASES() {
516                assert_unsigned_(0u32, 1, u32::MAX);
517            }
518        }
519
520
521        mod TEST_u64 {
522            #![allow(non_snake_case)]
523
524            use super::*;
525
526
527            #[test]
528            fn TEST_SIGN_CASES() {
529                assert_unsigned_(0u64, 1, u64::MAX);
530            }
531        }
532
533
534        mod TEST_u128 {
535            #![allow(non_snake_case)]
536
537            use super::*;
538
539
540            #[test]
541            fn TEST_SIGN_CASES() {
542                assert_unsigned_(0u128, 1, u128::MAX);
543            }
544        }
545
546
547        mod TEST_usize {
548            #![allow(non_snake_case)]
549
550            use super::*;
551
552
553            #[test]
554            fn TEST_SIGN_CASES() {
555                assert_unsigned_(0usize, 1, usize::MAX);
556            }
557        }
558    }
559}
560
561
562// ///////////////////////////// end of file //////////////////////////// //