]> git.proxmox.com Git - rustc.git/blob - src/libcore/num/wrapping.rs
Imported Upstream version 1.2.0+dfsg1
[rustc.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 #![allow(deprecated)]
13 #![unstable(feature = "wrapping", reason = "may be removed or relocated")]
14
15 use super::Wrapping;
16
17 use ops::*;
18
19 use intrinsics::{i8_add_with_overflow, u8_add_with_overflow};
20 use intrinsics::{i16_add_with_overflow, u16_add_with_overflow};
21 use intrinsics::{i32_add_with_overflow, u32_add_with_overflow};
22 use intrinsics::{i64_add_with_overflow, u64_add_with_overflow};
23 use intrinsics::{i8_sub_with_overflow, u8_sub_with_overflow};
24 use intrinsics::{i16_sub_with_overflow, u16_sub_with_overflow};
25 use intrinsics::{i32_sub_with_overflow, u32_sub_with_overflow};
26 use intrinsics::{i64_sub_with_overflow, u64_sub_with_overflow};
27 use intrinsics::{i8_mul_with_overflow, u8_mul_with_overflow};
28 use intrinsics::{i16_mul_with_overflow, u16_mul_with_overflow};
29 use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow};
30 use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};
31
32 use ::{i8,i16,i32,i64};
33
34 pub trait OverflowingOps {
35 fn overflowing_add(self, rhs: Self) -> (Self, bool);
36 fn overflowing_sub(self, rhs: Self) -> (Self, bool);
37 fn overflowing_mul(self, rhs: Self) -> (Self, bool);
38
39 fn overflowing_div(self, rhs: Self) -> (Self, bool);
40 fn overflowing_rem(self, rhs: Self) -> (Self, bool);
41 fn overflowing_neg(self) -> (Self, bool);
42
43 fn overflowing_shl(self, rhs: u32) -> (Self, bool);
44 fn overflowing_shr(self, rhs: u32) -> (Self, bool);
45 }
46
47 macro_rules! sh_impl {
48 ($t:ty, $f:ty) => (
49 #[stable(feature = "rust1", since = "1.0.0")]
50 impl Shl<$f> for Wrapping<$t> {
51 type Output = Wrapping<$t>;
52
53 #[inline(always)]
54 fn shl(self, other: $f) -> Wrapping<$t> {
55 Wrapping(self.0 << other)
56 }
57 }
58
59 #[stable(feature = "rust1", since = "1.0.0")]
60 impl Shr<$f> for Wrapping<$t> {
61 type Output = Wrapping<$t>;
62
63 #[inline(always)]
64 fn shr(self, other: $f) -> Wrapping<$t> {
65 Wrapping(self.0 >> other)
66 }
67 }
68 )
69 }
70
71 // FIXME (#23545): uncomment the remaining impls
72 macro_rules! sh_impl_all {
73 ($($t:ty)*) => ($(
74 // sh_impl! { $t, u8 }
75 // sh_impl! { $t, u16 }
76 // sh_impl! { $t, u32 }
77 // sh_impl! { $t, u64 }
78 sh_impl! { $t, usize }
79
80 // sh_impl! { $t, i8 }
81 // sh_impl! { $t, i16 }
82 // sh_impl! { $t, i32 }
83 // sh_impl! { $t, i64 }
84 // sh_impl! { $t, isize }
85 )*)
86 }
87
88 sh_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
89
90 macro_rules! wrapping_impl {
91 ($($t:ty)*) => ($(
92 #[stable(feature = "rust1", since = "1.0.0")]
93 impl Add for Wrapping<$t> {
94 type Output = Wrapping<$t>;
95
96 #[inline(always)]
97 fn add(self, other: Wrapping<$t>) -> Wrapping<$t> {
98 Wrapping(self.0.wrapping_add(other.0))
99 }
100 }
101
102 #[stable(feature = "rust1", since = "1.0.0")]
103 impl Sub for Wrapping<$t> {
104 type Output = Wrapping<$t>;
105
106 #[inline(always)]
107 fn sub(self, other: Wrapping<$t>) -> Wrapping<$t> {
108 Wrapping(self.0.wrapping_sub(other.0))
109 }
110 }
111
112 #[stable(feature = "rust1", since = "1.0.0")]
113 impl Mul for Wrapping<$t> {
114 type Output = Wrapping<$t>;
115
116 #[inline(always)]
117 fn mul(self, other: Wrapping<$t>) -> Wrapping<$t> {
118 Wrapping(self.0.wrapping_mul(other.0))
119 }
120 }
121
122 #[stable(feature = "rust1", since = "1.0.0")]
123 impl Not for Wrapping<$t> {
124 type Output = Wrapping<$t>;
125
126 #[inline(always)]
127 fn not(self) -> Wrapping<$t> {
128 Wrapping(!self.0)
129 }
130 }
131
132 #[stable(feature = "rust1", since = "1.0.0")]
133 impl BitXor for Wrapping<$t> {
134 type Output = Wrapping<$t>;
135
136 #[inline(always)]
137 fn bitxor(self, other: Wrapping<$t>) -> Wrapping<$t> {
138 Wrapping(self.0 ^ other.0)
139 }
140 }
141
142 #[stable(feature = "rust1", since = "1.0.0")]
143 impl BitOr for Wrapping<$t> {
144 type Output = Wrapping<$t>;
145
146 #[inline(always)]
147 fn bitor(self, other: Wrapping<$t>) -> Wrapping<$t> {
148 Wrapping(self.0 | other.0)
149 }
150 }
151
152 #[stable(feature = "rust1", since = "1.0.0")]
153 impl BitAnd for Wrapping<$t> {
154 type Output = Wrapping<$t>;
155
156 #[inline(always)]
157 fn bitand(self, other: Wrapping<$t>) -> Wrapping<$t> {
158 Wrapping(self.0 & other.0)
159 }
160 }
161 )*)
162 }
163
164 wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
165
166 mod shift_max {
167 #![allow(non_upper_case_globals)]
168
169 pub const i8: u32 = (1 << 3) - 1;
170 pub const i16: u32 = (1 << 4) - 1;
171 pub const i32: u32 = (1 << 5) - 1;
172 pub const i64: u32 = (1 << 6) - 1;
173
174 pub const u8: u32 = i8;
175 pub const u16: u32 = i16;
176 pub const u32: u32 = i32;
177 pub const u64: u32 = i64;
178 }
179
180 macro_rules! signed_overflowing_impl {
181 ($($t:ident)*) => ($(
182 impl OverflowingOps for $t {
183 #[inline(always)]
184 fn overflowing_add(self, rhs: $t) -> ($t, bool) {
185 unsafe {
186 concat_idents!($t, _add_with_overflow)(self, rhs)
187 }
188 }
189 #[inline(always)]
190 fn overflowing_sub(self, rhs: $t) -> ($t, bool) {
191 unsafe {
192 concat_idents!($t, _sub_with_overflow)(self, rhs)
193 }
194 }
195 #[inline(always)]
196 fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
197 unsafe {
198 concat_idents!($t, _mul_with_overflow)(self, rhs)
199 }
200 }
201
202 #[inline(always)]
203 fn overflowing_div(self, rhs: $t) -> ($t, bool) {
204 if self == $t::MIN && rhs == -1 {
205 (self, true)
206 } else {
207 (self/rhs, false)
208 }
209 }
210 #[inline(always)]
211 fn overflowing_rem(self, rhs: $t) -> ($t, bool) {
212 if self == $t::MIN && rhs == -1 {
213 (0, true)
214 } else {
215 (self % rhs, false)
216 }
217 }
218
219 #[inline(always)]
220 fn overflowing_shl(self, rhs: u32) -> ($t, bool) {
221 (self << (rhs & self::shift_max::$t),
222 (rhs > self::shift_max::$t))
223 }
224 #[inline(always)]
225 fn overflowing_shr(self, rhs: u32) -> ($t, bool) {
226 (self >> (rhs & self::shift_max::$t),
227 (rhs > self::shift_max::$t))
228 }
229
230 #[inline(always)]
231 fn overflowing_neg(self) -> ($t, bool) {
232 if self == $t::MIN {
233 ($t::MIN, true)
234 } else {
235 (-self, false)
236 }
237 }
238 }
239 )*)
240 }
241
242 macro_rules! unsigned_overflowing_impl {
243 ($($t:ident)*) => ($(
244 impl OverflowingOps for $t {
245 #[inline(always)]
246 fn overflowing_add(self, rhs: $t) -> ($t, bool) {
247 unsafe {
248 concat_idents!($t, _add_with_overflow)(self, rhs)
249 }
250 }
251 #[inline(always)]
252 fn overflowing_sub(self, rhs: $t) -> ($t, bool) {
253 unsafe {
254 concat_idents!($t, _sub_with_overflow)(self, rhs)
255 }
256 }
257 #[inline(always)]
258 fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
259 unsafe {
260 concat_idents!($t, _mul_with_overflow)(self, rhs)
261 }
262 }
263
264 #[inline(always)]
265 fn overflowing_div(self, rhs: $t) -> ($t, bool) {
266 (self/rhs, false)
267 }
268 #[inline(always)]
269 fn overflowing_rem(self, rhs: $t) -> ($t, bool) {
270 (self % rhs, false)
271 }
272
273 #[inline(always)]
274 fn overflowing_shl(self, rhs: u32) -> ($t, bool) {
275 (self << (rhs & self::shift_max::$t),
276 (rhs > self::shift_max::$t))
277 }
278 #[inline(always)]
279 fn overflowing_shr(self, rhs: u32) -> ($t, bool) {
280 (self >> (rhs & self::shift_max::$t),
281 (rhs > self::shift_max::$t))
282 }
283
284 #[inline(always)]
285 fn overflowing_neg(self) -> ($t, bool) {
286 ((!self).wrapping_add(1), true)
287 }
288 }
289 )*)
290 }
291
292 signed_overflowing_impl! { i8 i16 i32 i64 }
293 unsigned_overflowing_impl! { u8 u16 u32 u64 }
294
295 #[cfg(target_pointer_width = "64")]
296 impl OverflowingOps for usize {
297 #[inline(always)]
298 fn overflowing_add(self, rhs: usize) -> (usize, bool) {
299 unsafe {
300 let res = u64_add_with_overflow(self as u64, rhs as u64);
301 (res.0 as usize, res.1)
302 }
303 }
304 #[inline(always)]
305 fn overflowing_sub(self, rhs: usize) -> (usize, bool) {
306 unsafe {
307 let res = u64_sub_with_overflow(self as u64, rhs as u64);
308 (res.0 as usize, res.1)
309 }
310 }
311 #[inline(always)]
312 fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
313 unsafe {
314 let res = u64_mul_with_overflow(self as u64, rhs as u64);
315 (res.0 as usize, res.1)
316 }
317 }
318 #[inline(always)]
319 fn overflowing_div(self, rhs: usize) -> (usize, bool) {
320 let (r, f) = (self as u64).overflowing_div(rhs as u64);
321 (r as usize, f)
322 }
323 #[inline(always)]
324 fn overflowing_rem(self, rhs: usize) -> (usize, bool) {
325 let (r, f) = (self as u64).overflowing_rem(rhs as u64);
326 (r as usize, f)
327 }
328 #[inline(always)]
329 fn overflowing_neg(self) -> (usize, bool) {
330 let (r, f) = (self as u64).overflowing_neg();
331 (r as usize, f)
332 }
333 #[inline(always)]
334 fn overflowing_shl(self, rhs: u32) -> (usize, bool) {
335 let (r, f) = (self as u64).overflowing_shl(rhs);
336 (r as usize, f)
337 }
338 #[inline(always)]
339 fn overflowing_shr(self, rhs: u32) -> (usize, bool) {
340 let (r, f) = (self as u64).overflowing_shr(rhs);
341 (r as usize, f)
342 }
343 }
344
345 #[cfg(target_pointer_width = "32")]
346 impl OverflowingOps for usize {
347 #[inline(always)]
348 fn overflowing_add(self, rhs: usize) -> (usize, bool) {
349 unsafe {
350 let res = u32_add_with_overflow(self as u32, rhs as u32);
351 (res.0 as usize, res.1)
352 }
353 }
354 #[inline(always)]
355 fn overflowing_sub(self, rhs: usize) -> (usize, bool) {
356 unsafe {
357 let res = u32_sub_with_overflow(self as u32, rhs as u32);
358 (res.0 as usize, res.1)
359 }
360 }
361 #[inline(always)]
362 fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
363 unsafe {
364 let res = u32_mul_with_overflow(self as u32, rhs as u32);
365 (res.0 as usize, res.1)
366 }
367 }
368 #[inline(always)]
369 fn overflowing_div(self, rhs: usize) -> (usize, bool) {
370 let (r, f) = (self as u32).overflowing_div(rhs as u32);
371 (r as usize, f)
372 }
373 #[inline(always)]
374 fn overflowing_rem(self, rhs: usize) -> (usize, bool) {
375 let (r, f) = (self as u32).overflowing_rem(rhs as u32);
376 (r as usize, f)
377 }
378 #[inline(always)]
379 fn overflowing_neg(self) -> (usize, bool) {
380 let (r, f) = (self as u32).overflowing_neg();
381 (r as usize, f)
382 }
383 #[inline(always)]
384 fn overflowing_shl(self, rhs: u32) -> (usize, bool) {
385 let (r, f) = (self as u32).overflowing_shl(rhs);
386 (r as usize, f)
387 }
388 #[inline(always)]
389 fn overflowing_shr(self, rhs: u32) -> (usize, bool) {
390 let (r, f) = (self as u32).overflowing_shr(rhs);
391 (r as usize, f)
392 }
393 }
394
395 #[cfg(target_pointer_width = "64")]
396 impl OverflowingOps for isize {
397 #[inline(always)]
398 fn overflowing_add(self, rhs: isize) -> (isize, bool) {
399 unsafe {
400 let res = i64_add_with_overflow(self as i64, rhs as i64);
401 (res.0 as isize, res.1)
402 }
403 }
404 #[inline(always)]
405 fn overflowing_sub(self, rhs: isize) -> (isize, bool) {
406 unsafe {
407 let res = i64_sub_with_overflow(self as i64, rhs as i64);
408 (res.0 as isize, res.1)
409 }
410 }
411 #[inline(always)]
412 fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
413 unsafe {
414 let res = i64_mul_with_overflow(self as i64, rhs as i64);
415 (res.0 as isize, res.1)
416 }
417 }
418 #[inline(always)]
419 fn overflowing_div(self, rhs: isize) -> (isize, bool) {
420 let (r, f) = (self as i64).overflowing_div(rhs as i64);
421 (r as isize, f)
422 }
423 #[inline(always)]
424 fn overflowing_rem(self, rhs: isize) -> (isize, bool) {
425 let (r, f) = (self as i64).overflowing_rem(rhs as i64);
426 (r as isize, f)
427 }
428 #[inline(always)]
429 fn overflowing_neg(self) -> (isize, bool) {
430 let (r, f) = (self as i64).overflowing_neg();
431 (r as isize, f)
432 }
433 #[inline(always)]
434 fn overflowing_shl(self, rhs: u32) -> (isize, bool) {
435 let (r, f) = (self as i64).overflowing_shl(rhs);
436 (r as isize, f)
437 }
438 #[inline(always)]
439 fn overflowing_shr(self, rhs: u32) -> (isize, bool) {
440 let (r, f) = (self as i64).overflowing_shr(rhs);
441 (r as isize, f)
442 }
443 }
444
445 #[cfg(target_pointer_width = "32")]
446 impl OverflowingOps for isize {
447 #[inline(always)]
448 fn overflowing_add(self, rhs: isize) -> (isize, bool) {
449 unsafe {
450 let res = i32_add_with_overflow(self as i32, rhs as i32);
451 (res.0 as isize, res.1)
452 }
453 }
454 #[inline(always)]
455 fn overflowing_sub(self, rhs: isize) -> (isize, bool) {
456 unsafe {
457 let res = i32_sub_with_overflow(self as i32, rhs as i32);
458 (res.0 as isize, res.1)
459 }
460 }
461 #[inline(always)]
462 fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
463 unsafe {
464 let res = i32_mul_with_overflow(self as i32, rhs as i32);
465 (res.0 as isize, res.1)
466 }
467 }
468 #[inline(always)]
469 fn overflowing_div(self, rhs: isize) -> (isize, bool) {
470 let (r, f) = (self as i32).overflowing_div(rhs as i32);
471 (r as isize, f)
472 }
473 #[inline(always)]
474 fn overflowing_rem(self, rhs: isize) -> (isize, bool) {
475 let (r, f) = (self as i32).overflowing_rem(rhs as i32);
476 (r as isize, f)
477 }
478 #[inline(always)]
479 fn overflowing_neg(self) -> (isize, bool) {
480 let (r, f) = (self as i32).overflowing_neg();
481 (r as isize, f)
482 }
483 #[inline(always)]
484 fn overflowing_shl(self, rhs: u32) -> (isize, bool) {
485 let (r, f) = (self as i32).overflowing_shl(rhs);
486 (r as isize, f)
487 }
488 #[inline(always)]
489 fn overflowing_shr(self, rhs: u32) -> (isize, bool) {
490 let (r, f) = (self as i32).overflowing_shr(rhs);
491 (r as isize, f)
492 }
493 }