1pub 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