]> git.lizzy.rs Git - rust.git/blob - src/libcore/num/wrapping.rs
74abd6a4278d90334c6784e8e956428214164006
[rust.git] / src / libcore / num / wrapping.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![allow(missing_docs)]
12 #![unstable(feature = "old_wrapping", reason = "may be removed or relocated",
13             issue = "27755")]
14
15 use intrinsics::{add_with_overflow, sub_with_overflow, mul_with_overflow};
16
17 use super::Wrapping;
18
19 use ops::*;
20
21 use ::{i8, i16, i32, i64, isize};
22
23 #[unstable(feature = "old_wrapping", reason = "may be removed or relocated",
24            issue = "27755")]
25 #[rustc_deprecated(since = "1.7.0", reason = "moved to inherent methods")]
26 pub trait OverflowingOps {
27     fn overflowing_add(self, rhs: Self) -> (Self, bool);
28     fn overflowing_sub(self, rhs: Self) -> (Self, bool);
29     fn overflowing_mul(self, rhs: Self) -> (Self, bool);
30
31     fn overflowing_div(self, rhs: Self) -> (Self, bool);
32     fn overflowing_rem(self, rhs: Self) -> (Self, bool);
33     fn overflowing_neg(self) -> (Self, bool);
34
35     fn overflowing_shl(self, rhs: u32) -> (Self, bool);
36     fn overflowing_shr(self, rhs: u32) -> (Self, bool);
37 }
38
39 macro_rules! sh_impl_signed {
40     ($t:ident, $f:ident) => (
41         #[stable(feature = "rust1", since = "1.0.0")]
42         impl Shl<$f> for Wrapping<$t> {
43             type Output = Wrapping<$t>;
44
45             #[inline(always)]
46             fn shl(self, other: $f) -> Wrapping<$t> {
47                 if other < 0 {
48                     Wrapping(self.0.wrapping_shr((-other & self::shift_max::$t as $f) as u32))
49                 } else {
50                     Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32))
51                 }
52             }
53         }
54
55         #[stable(feature = "wrapping_impls", since = "1.7.0")]
56         impl ShlAssign<$f> for Wrapping<$t> {
57             #[inline(always)]
58             fn shl_assign(&mut self, other: $f) {
59                 *self = *self << other;
60             }
61         }
62
63         #[stable(feature = "rust1", since = "1.0.0")]
64         impl Shr<$f> for Wrapping<$t> {
65             type Output = Wrapping<$t>;
66
67             #[inline(always)]
68             fn shr(self, other: $f) -> Wrapping<$t> {
69                 if other < 0 {
70                     Wrapping(self.0.wrapping_shl((-other & self::shift_max::$t as $f) as u32))
71                 } else {
72                     Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32))
73                 }
74             }
75         }
76
77         #[stable(feature = "wrapping_impls", since = "1.7.0")]
78         impl ShrAssign<$f> for Wrapping<$t> {
79             #[inline(always)]
80             fn shr_assign(&mut self, other: $f) {
81                 *self = *self >> other;
82             }
83         }
84     )
85 }
86
87 macro_rules! sh_impl_unsigned {
88     ($t:ident, $f:ident) => (
89         #[stable(feature = "rust1", since = "1.0.0")]
90         impl Shl<$f> for Wrapping<$t> {
91             type Output = Wrapping<$t>;
92
93             #[inline(always)]
94             fn shl(self, other: $f) -> Wrapping<$t> {
95                 Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32))
96             }
97         }
98
99         #[stable(feature = "wrapping_impls", since = "1.7.0")]
100         impl ShlAssign<$f> for Wrapping<$t> {
101             #[inline(always)]
102             fn shl_assign(&mut self, other: $f) {
103                 *self = *self << other;
104             }
105         }
106
107         #[stable(feature = "rust1", since = "1.0.0")]
108         impl Shr<$f> for Wrapping<$t> {
109             type Output = Wrapping<$t>;
110
111             #[inline(always)]
112             fn shr(self, other: $f) -> Wrapping<$t> {
113                 Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32))
114             }
115         }
116
117         #[stable(feature = "wrapping_impls", since = "1.7.0")]
118         impl ShrAssign<$f> for Wrapping<$t> {
119             #[inline(always)]
120             fn shr_assign(&mut self, other: $f) {
121                 *self = *self >> other;
122             }
123         }
124     )
125 }
126
127 // FIXME (#23545): uncomment the remaining impls
128 macro_rules! sh_impl_all {
129     ($($t:ident)*) => ($(
130         //sh_impl_unsigned! { $t, u8 }
131         //sh_impl_unsigned! { $t, u16 }
132         //sh_impl_unsigned! { $t, u32 }
133         //sh_impl_unsigned! { $t, u64 }
134         sh_impl_unsigned! { $t, usize }
135
136         //sh_impl_signed! { $t, i8 }
137         //sh_impl_signed! { $t, i16 }
138         //sh_impl_signed! { $t, i32 }
139         //sh_impl_signed! { $t, i64 }
140         //sh_impl_signed! { $t, isize }
141     )*)
142 }
143
144 sh_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
145
146 // FIXME(30524): impl Op<T> for Wrapping<T>, impl OpAssign<T> for Wrapping<T>
147 macro_rules! wrapping_impl {
148     ($($t:ty)*) => ($(
149         #[stable(feature = "rust1", since = "1.0.0")]
150         impl Add for Wrapping<$t> {
151             type Output = Wrapping<$t>;
152
153             #[inline(always)]
154             fn add(self, other: Wrapping<$t>) -> Wrapping<$t> {
155                 Wrapping(self.0.wrapping_add(other.0))
156             }
157         }
158
159         #[stable(feature = "op_assign_traits", since = "1.8.0")]
160         impl AddAssign for Wrapping<$t> {
161             #[inline(always)]
162             fn add_assign(&mut self, other: Wrapping<$t>) {
163                 *self = *self + other;
164             }
165         }
166
167         #[stable(feature = "rust1", since = "1.0.0")]
168         impl Sub for Wrapping<$t> {
169             type Output = Wrapping<$t>;
170
171             #[inline(always)]
172             fn sub(self, other: Wrapping<$t>) -> Wrapping<$t> {
173                 Wrapping(self.0.wrapping_sub(other.0))
174             }
175         }
176
177         #[stable(feature = "op_assign_traits", since = "1.8.0")]
178         impl SubAssign for Wrapping<$t> {
179             #[inline(always)]
180             fn sub_assign(&mut self, other: Wrapping<$t>) {
181                 *self = *self - other;
182             }
183         }
184
185         #[stable(feature = "rust1", since = "1.0.0")]
186         impl Mul for Wrapping<$t> {
187             type Output = Wrapping<$t>;
188
189             #[inline(always)]
190             fn mul(self, other: Wrapping<$t>) -> Wrapping<$t> {
191                 Wrapping(self.0.wrapping_mul(other.0))
192             }
193         }
194
195         #[stable(feature = "op_assign_traits", since = "1.8.0")]
196         impl MulAssign for Wrapping<$t> {
197             #[inline(always)]
198             fn mul_assign(&mut self, other: Wrapping<$t>) {
199                 *self = *self * other;
200             }
201         }
202
203         #[stable(feature = "wrapping_div", since = "1.3.0")]
204         impl Div for Wrapping<$t> {
205             type Output = Wrapping<$t>;
206
207             #[inline(always)]
208             fn div(self, other: Wrapping<$t>) -> Wrapping<$t> {
209                 Wrapping(self.0.wrapping_div(other.0))
210             }
211         }
212
213         #[stable(feature = "op_assign_traits", since = "1.8.0")]
214         impl DivAssign for Wrapping<$t> {
215             #[inline(always)]
216             fn div_assign(&mut self, other: Wrapping<$t>) {
217                 *self = *self / other;
218             }
219         }
220
221         #[stable(feature = "wrapping_impls", since = "1.7.0")]
222         impl Rem for Wrapping<$t> {
223             type Output = Wrapping<$t>;
224
225             #[inline(always)]
226             fn rem(self, other: Wrapping<$t>) -> Wrapping<$t> {
227                 Wrapping(self.0.wrapping_rem(other.0))
228             }
229         }
230
231         #[stable(feature = "op_assign_traits", since = "1.8.0")]
232         impl RemAssign for Wrapping<$t> {
233             #[inline(always)]
234             fn rem_assign(&mut self, other: Wrapping<$t>) {
235                 *self = *self % other;
236             }
237         }
238
239         #[stable(feature = "rust1", since = "1.0.0")]
240         impl Not for Wrapping<$t> {
241             type Output = Wrapping<$t>;
242
243             #[inline(always)]
244             fn not(self) -> Wrapping<$t> {
245                 Wrapping(!self.0)
246             }
247         }
248
249         #[stable(feature = "rust1", since = "1.0.0")]
250         impl BitXor for Wrapping<$t> {
251             type Output = Wrapping<$t>;
252
253             #[inline(always)]
254             fn bitxor(self, other: Wrapping<$t>) -> Wrapping<$t> {
255                 Wrapping(self.0 ^ other.0)
256             }
257         }
258
259         #[stable(feature = "op_assign_traits", since = "1.8.0")]
260         impl BitXorAssign for Wrapping<$t> {
261             #[inline(always)]
262             fn bitxor_assign(&mut self, other: Wrapping<$t>) {
263                 *self = *self ^ other;
264             }
265         }
266
267         #[stable(feature = "rust1", since = "1.0.0")]
268         impl BitOr for Wrapping<$t> {
269             type Output = Wrapping<$t>;
270
271             #[inline(always)]
272             fn bitor(self, other: Wrapping<$t>) -> Wrapping<$t> {
273                 Wrapping(self.0 | other.0)
274             }
275         }
276
277         #[stable(feature = "op_assign_traits", since = "1.8.0")]
278         impl BitOrAssign for Wrapping<$t> {
279             #[inline(always)]
280             fn bitor_assign(&mut self, other: Wrapping<$t>) {
281                 *self = *self | other;
282             }
283         }
284
285         #[stable(feature = "rust1", since = "1.0.0")]
286         impl BitAnd for Wrapping<$t> {
287             type Output = Wrapping<$t>;
288
289             #[inline(always)]
290             fn bitand(self, other: Wrapping<$t>) -> Wrapping<$t> {
291                 Wrapping(self.0 & other.0)
292             }
293         }
294
295         #[stable(feature = "op_assign_traits", since = "1.8.0")]
296         impl BitAndAssign for Wrapping<$t> {
297             #[inline(always)]
298             fn bitand_assign(&mut self, other: Wrapping<$t>) {
299                 *self = *self & other;
300             }
301         }
302     )*)
303 }
304
305 wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
306
307 mod shift_max {
308     #![allow(non_upper_case_globals)]
309
310     #[cfg(target_pointer_width = "32")]
311     mod platform {
312         pub const usize: u32 = super::u32;
313         pub const isize: u32 = super::i32;
314     }
315
316     #[cfg(target_pointer_width = "64")]
317     mod platform {
318         pub const usize: u32 = super::u64;
319         pub const isize: u32 = super::i64;
320     }
321
322     pub const  i8: u32 = (1 << 3) - 1;
323     pub const i16: u32 = (1 << 4) - 1;
324     pub const i32: u32 = (1 << 5) - 1;
325     pub const i64: u32 = (1 << 6) - 1;
326     pub use self::platform::isize;
327
328     pub const  u8: u32 = i8;
329     pub const u16: u32 = i16;
330     pub const u32: u32 = i32;
331     pub const u64: u32 = i64;
332     pub use self::platform::usize;
333 }
334
335 macro_rules! signed_overflowing_impl {
336     ($($t:ident)*) => ($(
337         #[allow(deprecated)]
338         impl OverflowingOps for $t {
339             #[inline(always)]
340             fn overflowing_add(self, rhs: $t) -> ($t, bool) {
341                 unsafe {
342                     add_with_overflow(self, rhs)
343                 }
344             }
345             #[inline(always)]
346             fn overflowing_sub(self, rhs: $t) -> ($t, bool) {
347                 unsafe {
348                     sub_with_overflow(self, rhs)
349                 }
350             }
351             #[inline(always)]
352             fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
353                 unsafe {
354                     mul_with_overflow(self, rhs)
355                 }
356             }
357
358             #[inline(always)]
359             fn overflowing_div(self, rhs: $t) -> ($t, bool) {
360                 if self == $t::MIN && rhs == -1 {
361                     (self, true)
362                 } else {
363                     (self/rhs, false)
364                 }
365             }
366             #[inline(always)]
367             fn overflowing_rem(self, rhs: $t) -> ($t, bool) {
368                 if self == $t::MIN && rhs == -1 {
369                     (0, true)
370                 } else {
371                     (self % rhs, false)
372                 }
373             }
374
375             #[inline(always)]
376             fn overflowing_shl(self, rhs: u32) -> ($t, bool) {
377                 (self << (rhs & self::shift_max::$t),
378                  (rhs > self::shift_max::$t))
379             }
380             #[inline(always)]
381             fn overflowing_shr(self, rhs: u32) -> ($t, bool) {
382                 (self >> (rhs & self::shift_max::$t),
383                  (rhs > self::shift_max::$t))
384             }
385
386             #[inline(always)]
387             fn overflowing_neg(self) -> ($t, bool) {
388                 if self == $t::MIN {
389                     ($t::MIN, true)
390                 } else {
391                     (-self, false)
392                 }
393             }
394         }
395     )*)
396 }
397
398 macro_rules! unsigned_overflowing_impl {
399     ($($t:ident)*) => ($(
400         #[allow(deprecated)]
401         impl OverflowingOps for $t {
402             #[inline(always)]
403             fn overflowing_add(self, rhs: $t) -> ($t, bool) {
404                 unsafe {
405                     add_with_overflow(self, rhs)
406                 }
407             }
408             #[inline(always)]
409             fn overflowing_sub(self, rhs: $t) -> ($t, bool) {
410                 unsafe {
411                     sub_with_overflow(self, rhs)
412                 }
413             }
414             #[inline(always)]
415             fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
416                 unsafe {
417                     mul_with_overflow(self, rhs)
418                 }
419             }
420
421             #[inline(always)]
422             fn overflowing_div(self, rhs: $t) -> ($t, bool) {
423                 (self/rhs, false)
424             }
425             #[inline(always)]
426             fn overflowing_rem(self, rhs: $t) -> ($t, bool) {
427                 (self % rhs, false)
428             }
429
430             #[inline(always)]
431             fn overflowing_shl(self, rhs: u32) -> ($t, bool) {
432                 (self << (rhs & self::shift_max::$t),
433                  (rhs > self::shift_max::$t))
434             }
435             #[inline(always)]
436             fn overflowing_shr(self, rhs: u32) -> ($t, bool) {
437                 (self >> (rhs & self::shift_max::$t),
438                  (rhs > self::shift_max::$t))
439             }
440
441             #[inline(always)]
442             fn overflowing_neg(self) -> ($t, bool) {
443                 ((!self).wrapping_add(1), true)
444             }
445         }
446     )*)
447 }
448
449 signed_overflowing_impl! { i8 i16 i32 i64 isize }
450 unsigned_overflowing_impl! { u8 u16 u32 u64 usize }