]> git.proxmox.com Git - rustc.git/blob - src/librustc_const_math/int.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc_const_math / int.rs
1 // Copyright 2015 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 use std::cmp::Ordering;
12 use syntax::attr::IntType;
13 use syntax::ast::{IntTy, UintTy};
14
15 use super::is::*;
16 use super::us::*;
17 use super::err::*;
18
19 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
20 pub enum ConstInt {
21 I8(i8),
22 I16(i16),
23 I32(i32),
24 I64(i64),
25 I128(i128),
26 Isize(ConstIsize),
27 U8(u8),
28 U16(u16),
29 U32(u32),
30 U64(u64),
31 U128(u128),
32 Usize(ConstUsize),
33 }
34 pub use self::ConstInt::*;
35
36
37 macro_rules! bounds {
38 ($ct: ty, $($t:ident $min:ident $max:ident)*) => {
39 $(
40 pub const $min: $ct = $t::min_value() as $ct;
41 pub const $max: $ct = $t::max_value() as $ct;
42 )*
43 };
44 ($ct: ty: $min_val: expr, $($t:ident $min:ident $max:ident)*) => {
45 $(
46 pub const $min: $ct = $min_val;
47 pub const $max: $ct = $t::max_value() as $ct;
48 )*
49 }
50 }
51
52 mod ubounds {
53 #![allow(dead_code)]
54 bounds!{u128: 0,
55 i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
56 u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX u128 U128MIN U128MAX
57 // do not add constants for isize/usize, because these are guaranteed to be wrong for
58 // arbitrary host/target combinations
59 }
60 }
61
62 mod ibounds {
63 #![allow(dead_code)]
64 bounds!(i128, u64 U64MIN U64MAX);
65
66 pub const U128MIN: i128 = 0;
67 pub const U128MAX: i128 = i128::max_value();
68
69 bounds!{i128,
70 i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
71 u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX
72 // do not add constants for isize/usize, because these are guaranteed to be wrong for
73 // arbitrary host/target combinations
74 }
75 }
76
77 impl ConstInt {
78 /// Creates a new unsigned ConstInt with matching type while also checking that overflow does
79 /// not happen.
80 pub fn new_unsigned(val: u128, ty: UintTy, usize_ty: UintTy) -> Option<ConstInt> {
81 match ty {
82 UintTy::U8 if val <= ubounds::U8MAX => Some(U8(val as u8)),
83 UintTy::U16 if val <= ubounds::U16MAX => Some(U16(val as u16)),
84 UintTy::U32 if val <= ubounds::U32MAX => Some(U32(val as u32)),
85 UintTy::U64 if val <= ubounds::U64MAX => Some(U64(val as u64)),
86 UintTy::Us if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok()
87 .map(Usize),
88 UintTy::U128 => Some(U128(val)),
89 _ => None
90 }
91 }
92
93 /// Creates a new signed ConstInt with matching type while also checking that overflow does
94 /// not happen.
95 pub fn new_signed(val: i128, ty: IntTy, isize_ty: IntTy) -> Option<ConstInt> {
96 match ty {
97 IntTy::I8 if val <= ibounds::I8MAX => Some(I8(val as i8)),
98 IntTy::I16 if val <= ibounds::I16MAX => Some(I16(val as i16)),
99 IntTy::I32 if val <= ibounds::I32MAX => Some(I32(val as i32)),
100 IntTy::I64 if val <= ibounds::I64MAX => Some(I64(val as i64)),
101 IntTy::Is if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok()
102 .map(Isize),
103 IntTy::I128 => Some(I128(val)),
104 _ => None
105 }
106 }
107
108 /// Creates a new unsigned ConstInt with matching type.
109 pub fn new_unsigned_truncating(val: u128, ty: UintTy, usize_ty: UintTy) -> ConstInt {
110 match ty {
111 UintTy::U8 => U8(val as u8),
112 UintTy::U16 => U16(val as u16),
113 UintTy::U32 => U32(val as u32),
114 UintTy::U64 => U64(val as u64),
115 UintTy::Us => Usize(ConstUsize::new_truncating(val, usize_ty)),
116 UintTy::U128 => U128(val)
117 }
118 }
119
120 /// Creates a new signed ConstInt with matching type.
121 pub fn new_signed_truncating(val: i128, ty: IntTy, isize_ty: IntTy) -> ConstInt {
122 match ty {
123 IntTy::I8 => I8(val as i8),
124 IntTy::I16 => I16(val as i16),
125 IntTy::I32 => I32(val as i32),
126 IntTy::I64 => I64(val as i64),
127 IntTy::Is => Isize(ConstIsize::new_truncating(val, isize_ty)),
128 IntTy::I128 => I128(val)
129 }
130 }
131
132 /// Description of the type, not the value
133 pub fn description(&self) -> &'static str {
134 match *self {
135 I8(_) => "i8",
136 I16(_) => "i16",
137 I32(_) => "i32",
138 I64(_) => "i64",
139 I128(_) => "i128",
140 Isize(_) => "isize",
141 U8(_) => "u8",
142 U16(_) => "u16",
143 U32(_) => "u32",
144 U64(_) => "u64",
145 U128(_) => "u128",
146 Usize(_) => "usize",
147 }
148 }
149
150 /// Erases the type and returns a u128.
151 /// This is not the same as `-5i8 as u128` but as `-5i8 as i128 as u128`
152 pub fn to_u128_unchecked(self) -> u128 {
153 match self {
154 I8(i) => i as i128 as u128,
155 I16(i) => i as i128 as u128,
156 I32(i) => i as i128 as u128,
157 I64(i) => i as i128 as u128,
158 I128(i) => i as i128 as u128,
159 Isize(Is16(i)) => i as i128 as u128,
160 Isize(Is32(i)) => i as i128 as u128,
161 Isize(Is64(i)) => i as i128 as u128,
162 U8(i) => i as u128,
163 U16(i) => i as u128,
164 U32(i) => i as u128,
165 U64(i) => i as u128,
166 U128(i) => i as u128,
167 Usize(Us16(i)) => i as u128,
168 Usize(Us32(i)) => i as u128,
169 Usize(Us64(i)) => i as u128,
170 }
171 }
172
173 /// Converts the value to a `u32` if it's in the range 0...std::u32::MAX
174 pub fn to_u32(&self) -> Option<u32> {
175 self.to_u128().and_then(|v| if v <= u32::max_value() as u128 {
176 Some(v as u32)
177 } else {
178 None
179 })
180 }
181
182 /// Converts the value to a `u64` if it's in the range 0...std::u64::MAX
183 pub fn to_u64(&self) -> Option<u64> {
184 self.to_u128().and_then(|v| if v <= u64::max_value() as u128 {
185 Some(v as u64)
186 } else {
187 None
188 })
189 }
190
191 /// Converts the value to a `u128` if it's in the range 0...std::u128::MAX
192 pub fn to_u128(&self) -> Option<u128> {
193 match *self {
194 I8(v) if v >= 0 => Some(v as u128),
195 I16(v) if v >= 0 => Some(v as u128),
196 I32(v) if v >= 0 => Some(v as u128),
197 I64(v) if v >= 0 => Some(v as u128),
198 I128(v) if v >= 0 => Some(v as u128),
199 Isize(Is16(v)) if v >= 0 => Some(v as u128),
200 Isize(Is32(v)) if v >= 0 => Some(v as u128),
201 Isize(Is64(v)) if v >= 0 => Some(v as u128),
202 U8(v) => Some(v as u128),
203 U16(v) => Some(v as u128),
204 U32(v) => Some(v as u128),
205 U64(v) => Some(v as u128),
206 U128(v) => Some(v as u128),
207 Usize(Us16(v)) => Some(v as u128),
208 Usize(Us32(v)) => Some(v as u128),
209 Usize(Us64(v)) => Some(v as u128),
210 _ => None,
211 }
212 }
213
214 pub fn to_f32(self) -> f32 {
215 match self {
216 I8(i) => i as f32,
217 I16(i) => i as f32,
218 I32(i) => i as f32,
219 I64(i) => i as f32,
220 I128(i) => i as f32,
221 Isize(Is16(i)) => i as f32,
222 Isize(Is32(i)) => i as f32,
223 Isize(Is64(i)) => i as f32,
224 U8(i) => i as f32,
225 U16(i) => i as f32,
226 U32(i) => i as f32,
227 U64(i) => i as f32,
228 U128(i) => i as f32,
229 Usize(Us16(i)) => i as f32,
230 Usize(Us32(i)) => i as f32,
231 Usize(Us64(i)) => i as f32,
232 }
233 }
234
235 pub fn to_f64(self) -> f64 {
236 match self {
237 I8(i) => i as f64,
238 I16(i) => i as f64,
239 I32(i) => i as f64,
240 I64(i) => i as f64,
241 I128(i) => i as f64,
242 Isize(Is16(i)) => i as f64,
243 Isize(Is32(i)) => i as f64,
244 Isize(Is64(i)) => i as f64,
245 U8(i) => i as f64,
246 U16(i) => i as f64,
247 U32(i) => i as f64,
248 U64(i) => i as f64,
249 U128(i) => i as f64,
250 Usize(Us16(i)) => i as f64,
251 Usize(Us32(i)) => i as f64,
252 Usize(Us64(i)) => i as f64,
253 }
254 }
255
256 pub fn is_negative(&self) -> bool {
257 match *self {
258 I8(v) => v < 0,
259 I16(v) => v < 0,
260 I32(v) => v < 0,
261 I64(v) => v < 0,
262 I128(v) => v < 0,
263 Isize(Is16(v)) => v < 0,
264 Isize(Is32(v)) => v < 0,
265 Isize(Is64(v)) => v < 0,
266 _ => false,
267 }
268 }
269
270 /// Compares the values if they are of the same type
271 pub fn try_cmp(self, rhs: Self) -> Result<::std::cmp::Ordering, ConstMathErr> {
272 match (self, rhs) {
273 (I8(a), I8(b)) => Ok(a.cmp(&b)),
274 (I16(a), I16(b)) => Ok(a.cmp(&b)),
275 (I32(a), I32(b)) => Ok(a.cmp(&b)),
276 (I64(a), I64(b)) => Ok(a.cmp(&b)),
277 (I128(a), I128(b)) => Ok(a.cmp(&b)),
278 (Isize(Is16(a)), Isize(Is16(b))) => Ok(a.cmp(&b)),
279 (Isize(Is32(a)), Isize(Is32(b))) => Ok(a.cmp(&b)),
280 (Isize(Is64(a)), Isize(Is64(b))) => Ok(a.cmp(&b)),
281 (U8(a), U8(b)) => Ok(a.cmp(&b)),
282 (U16(a), U16(b)) => Ok(a.cmp(&b)),
283 (U32(a), U32(b)) => Ok(a.cmp(&b)),
284 (U64(a), U64(b)) => Ok(a.cmp(&b)),
285 (U128(a), U128(b)) => Ok(a.cmp(&b)),
286 (Usize(Us16(a)), Usize(Us16(b))) => Ok(a.cmp(&b)),
287 (Usize(Us32(a)), Usize(Us32(b))) => Ok(a.cmp(&b)),
288 (Usize(Us64(a)), Usize(Us64(b))) => Ok(a.cmp(&b)),
289 _ => Err(CmpBetweenUnequalTypes),
290 }
291 }
292
293 /// Adds 1 to the value and wraps around if the maximum for the type is reached
294 pub fn wrap_incr(self) -> Self {
295 macro_rules! add1 {
296 ($e:expr) => { ($e).wrapping_add(1) }
297 }
298 match self {
299 ConstInt::I8(i) => ConstInt::I8(add1!(i)),
300 ConstInt::I16(i) => ConstInt::I16(add1!(i)),
301 ConstInt::I32(i) => ConstInt::I32(add1!(i)),
302 ConstInt::I64(i) => ConstInt::I64(add1!(i)),
303 ConstInt::I128(i) => ConstInt::I128(add1!(i)),
304 ConstInt::Isize(ConstIsize::Is16(i)) => ConstInt::Isize(ConstIsize::Is16(add1!(i))),
305 ConstInt::Isize(ConstIsize::Is32(i)) => ConstInt::Isize(ConstIsize::Is32(add1!(i))),
306 ConstInt::Isize(ConstIsize::Is64(i)) => ConstInt::Isize(ConstIsize::Is64(add1!(i))),
307 ConstInt::U8(i) => ConstInt::U8(add1!(i)),
308 ConstInt::U16(i) => ConstInt::U16(add1!(i)),
309 ConstInt::U32(i) => ConstInt::U32(add1!(i)),
310 ConstInt::U64(i) => ConstInt::U64(add1!(i)),
311 ConstInt::U128(i) => ConstInt::U128(add1!(i)),
312 ConstInt::Usize(ConstUsize::Us16(i)) => ConstInt::Usize(ConstUsize::Us16(add1!(i))),
313 ConstInt::Usize(ConstUsize::Us32(i)) => ConstInt::Usize(ConstUsize::Us32(add1!(i))),
314 ConstInt::Usize(ConstUsize::Us64(i)) => ConstInt::Usize(ConstUsize::Us64(add1!(i))),
315 }
316 }
317
318 pub fn int_type(self) -> IntType {
319 match self {
320 ConstInt::I8(_) => IntType::SignedInt(IntTy::I8),
321 ConstInt::I16(_) => IntType::SignedInt(IntTy::I16),
322 ConstInt::I32(_) => IntType::SignedInt(IntTy::I32),
323 ConstInt::I64(_) => IntType::SignedInt(IntTy::I64),
324 ConstInt::I128(_) => IntType::SignedInt(IntTy::I128),
325 ConstInt::Isize(_) => IntType::SignedInt(IntTy::Is),
326 ConstInt::U8(_) => IntType::UnsignedInt(UintTy::U8),
327 ConstInt::U16(_) => IntType::UnsignedInt(UintTy::U16),
328 ConstInt::U32(_) => IntType::UnsignedInt(UintTy::U32),
329 ConstInt::U64(_) => IntType::UnsignedInt(UintTy::U64),
330 ConstInt::U128(_) => IntType::UnsignedInt(UintTy::U128),
331 ConstInt::Usize(_) => IntType::UnsignedInt(UintTy::Us),
332 }
333 }
334 }
335
336 impl ::std::cmp::PartialOrd for ConstInt {
337 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
338 self.try_cmp(*other).ok()
339 }
340 }
341
342 impl ::std::cmp::Ord for ConstInt {
343 fn cmp(&self, other: &Self) -> Ordering {
344 self.try_cmp(*other).unwrap()
345 }
346 }
347
348 impl ::std::fmt::Display for ConstInt {
349 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
350 match *self {
351 I8(i) => write!(fmt, "{}i8", i),
352 I16(i) => write!(fmt, "{}i16", i),
353 I32(i) => write!(fmt, "{}i32", i),
354 I64(i) => write!(fmt, "{}i64", i),
355 I128(i) => write!(fmt, "{}i128", i),
356 Isize(ConstIsize::Is64(i)) => write!(fmt, "{}isize", i),
357 Isize(ConstIsize::Is32(i)) => write!(fmt, "{}isize", i),
358 Isize(ConstIsize::Is16(i)) => write!(fmt, "{}isize", i),
359 U8(i) => write!(fmt, "{}u8", i),
360 U16(i) => write!(fmt, "{}u16", i),
361 U32(i) => write!(fmt, "{}u32", i),
362 U64(i) => write!(fmt, "{}u64", i),
363 U128(i) => write!(fmt, "{}u128", i),
364 Usize(ConstUsize::Us64(i)) => write!(fmt, "{}usize", i),
365 Usize(ConstUsize::Us32(i)) => write!(fmt, "{}usize", i),
366 Usize(ConstUsize::Us16(i)) => write!(fmt, "{}usize", i),
367 }
368 }
369 }
370
371 macro_rules! overflowing {
372 ($e:expr, $err:expr) => {{
373 if $e.1 {
374 return Err(Overflow($err));
375 } else {
376 $e.0
377 }
378 }}
379 }
380
381 macro_rules! impl_binop {
382 ($op:ident, $func:ident, $checked_func:ident) => {
383 impl ::std::ops::$op for ConstInt {
384 type Output = Result<Self, ConstMathErr>;
385 fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
386 match (self, rhs) {
387 (I8(a), I8(b)) => a.$checked_func(b).map(I8),
388 (I16(a), I16(b)) => a.$checked_func(b).map(I16),
389 (I32(a), I32(b)) => a.$checked_func(b).map(I32),
390 (I64(a), I64(b)) => a.$checked_func(b).map(I64),
391 (I128(a), I128(b)) => a.$checked_func(b).map(I128),
392 (Isize(Is16(a)), Isize(Is16(b))) => a.$checked_func(b).map(Is16).map(Isize),
393 (Isize(Is32(a)), Isize(Is32(b))) => a.$checked_func(b).map(Is32).map(Isize),
394 (Isize(Is64(a)), Isize(Is64(b))) => a.$checked_func(b).map(Is64).map(Isize),
395 (U8(a), U8(b)) => a.$checked_func(b).map(U8),
396 (U16(a), U16(b)) => a.$checked_func(b).map(U16),
397 (U32(a), U32(b)) => a.$checked_func(b).map(U32),
398 (U64(a), U64(b)) => a.$checked_func(b).map(U64),
399 (U128(a), U128(b)) => a.$checked_func(b).map(U128),
400 (Usize(Us16(a)), Usize(Us16(b))) => a.$checked_func(b).map(Us16).map(Usize),
401 (Usize(Us32(a)), Usize(Us32(b))) => a.$checked_func(b).map(Us32).map(Usize),
402 (Usize(Us64(a)), Usize(Us64(b))) => a.$checked_func(b).map(Us64).map(Usize),
403 _ => return Err(UnequalTypes(Op::$op)),
404 }.ok_or(Overflow(Op::$op))
405 }
406 }
407 }
408 }
409
410 macro_rules! derive_binop {
411 ($op:ident, $func:ident) => {
412 impl ::std::ops::$op for ConstInt {
413 type Output = Result<Self, ConstMathErr>;
414 fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
415 match (self, rhs) {
416 (I8(a), I8(b)) => Ok(I8(a.$func(b))),
417 (I16(a), I16(b)) => Ok(I16(a.$func(b))),
418 (I32(a), I32(b)) => Ok(I32(a.$func(b))),
419 (I64(a), I64(b)) => Ok(I64(a.$func(b))),
420 (I128(a), I128(b)) => Ok(I128(a.$func(b))),
421 (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a.$func(b)))),
422 (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a.$func(b)))),
423 (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a.$func(b)))),
424 (U8(a), U8(b)) => Ok(U8(a.$func(b))),
425 (U16(a), U16(b)) => Ok(U16(a.$func(b))),
426 (U32(a), U32(b)) => Ok(U32(a.$func(b))),
427 (U64(a), U64(b)) => Ok(U64(a.$func(b))),
428 (U128(a), U128(b)) => Ok(U128(a.$func(b))),
429 (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a.$func(b)))),
430 (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a.$func(b)))),
431 (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a.$func(b)))),
432 _ => Err(UnequalTypes(Op::$op)),
433 }
434 }
435 }
436 }
437 }
438
439 impl_binop!(Add, add, checked_add);
440 impl_binop!(Sub, sub, checked_sub);
441 impl_binop!(Mul, mul, checked_mul);
442 derive_binop!(BitAnd, bitand);
443 derive_binop!(BitOr, bitor);
444 derive_binop!(BitXor, bitxor);
445
446 const I128_MIN: i128 = ::std::i128::MIN;
447
448 fn check_division(
449 lhs: ConstInt,
450 rhs: ConstInt,
451 op: Op,
452 zerr: ConstMathErr,
453 ) -> Result<(), ConstMathErr> {
454 match (lhs, rhs) {
455 (I8(_), I8(0)) => Err(zerr),
456 (I16(_), I16(0)) => Err(zerr),
457 (I32(_), I32(0)) => Err(zerr),
458 (I64(_), I64(0)) => Err(zerr),
459 (I128(_), I128(0)) => Err(zerr),
460 (Isize(_), Isize(Is16(0))) => Err(zerr),
461 (Isize(_), Isize(Is32(0))) => Err(zerr),
462 (Isize(_), Isize(Is64(0))) => Err(zerr),
463
464 (U8(_), U8(0)) => Err(zerr),
465 (U16(_), U16(0)) => Err(zerr),
466 (U32(_), U32(0)) => Err(zerr),
467 (U64(_), U64(0)) => Err(zerr),
468 (U128(_), U128(0)) => Err(zerr),
469 (Usize(_), Usize(Us16(0))) => Err(zerr),
470 (Usize(_), Usize(Us32(0))) => Err(zerr),
471 (Usize(_), Usize(Us64(0))) => Err(zerr),
472
473 (I8(::std::i8::MIN), I8(-1)) => Err(Overflow(op)),
474 (I16(::std::i16::MIN), I16(-1)) => Err(Overflow(op)),
475 (I32(::std::i32::MIN), I32(-1)) => Err(Overflow(op)),
476 (I64(::std::i64::MIN), I64(-1)) => Err(Overflow(op)),
477 (I128(I128_MIN), I128(-1)) => Err(Overflow(op)),
478 (Isize(Is16(::std::i16::MIN)), Isize(Is16(-1))) => Err(Overflow(op)),
479 (Isize(Is32(::std::i32::MIN)), Isize(Is32(-1))) => Err(Overflow(op)),
480 (Isize(Is64(::std::i64::MIN)), Isize(Is64(-1))) => Err(Overflow(op)),
481
482 _ => Ok(()),
483 }
484 }
485
486 impl ::std::ops::Div for ConstInt {
487 type Output = Result<Self, ConstMathErr>;
488 fn div(self, rhs: Self) -> Result<Self, ConstMathErr> {
489 let (lhs, rhs) = (self, rhs);
490 check_division(lhs, rhs, Op::Div, DivisionByZero)?;
491 match (lhs, rhs) {
492 (I8(a), I8(b)) => Ok(I8(a/b)),
493 (I16(a), I16(b)) => Ok(I16(a/b)),
494 (I32(a), I32(b)) => Ok(I32(a/b)),
495 (I64(a), I64(b)) => Ok(I64(a/b)),
496 (I128(a), I128(b)) => Ok(I128(a/b)),
497 (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a/b))),
498 (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a/b))),
499 (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a/b))),
500
501 (U8(a), U8(b)) => Ok(U8(a/b)),
502 (U16(a), U16(b)) => Ok(U16(a/b)),
503 (U32(a), U32(b)) => Ok(U32(a/b)),
504 (U64(a), U64(b)) => Ok(U64(a/b)),
505 (U128(a), U128(b)) => Ok(U128(a/b)),
506 (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a/b))),
507 (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a/b))),
508 (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a/b))),
509
510 _ => Err(UnequalTypes(Op::Div)),
511 }
512 }
513 }
514
515 impl ::std::ops::Rem for ConstInt {
516 type Output = Result<Self, ConstMathErr>;
517 fn rem(self, rhs: Self) -> Result<Self, ConstMathErr> {
518 let (lhs, rhs) = (self, rhs);
519 // should INT_MIN%-1 be zero or an error?
520 check_division(lhs, rhs, Op::Rem, RemainderByZero)?;
521 match (lhs, rhs) {
522 (I8(a), I8(b)) => Ok(I8(a%b)),
523 (I16(a), I16(b)) => Ok(I16(a%b)),
524 (I32(a), I32(b)) => Ok(I32(a%b)),
525 (I64(a), I64(b)) => Ok(I64(a%b)),
526 (I128(a), I128(b)) => Ok(I128(a%b)),
527 (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a%b))),
528 (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a%b))),
529 (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a%b))),
530
531 (U8(a), U8(b)) => Ok(U8(a%b)),
532 (U16(a), U16(b)) => Ok(U16(a%b)),
533 (U32(a), U32(b)) => Ok(U32(a%b)),
534 (U64(a), U64(b)) => Ok(U64(a%b)),
535 (U128(a), U128(b)) => Ok(U128(a%b)),
536 (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a%b))),
537 (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a%b))),
538 (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a%b))),
539
540 _ => Err(UnequalTypes(Op::Rem)),
541 }
542 }
543 }
544
545 impl ::std::ops::Shl<ConstInt> for ConstInt {
546 type Output = Result<Self, ConstMathErr>;
547 fn shl(self, rhs: Self) -> Result<Self, ConstMathErr> {
548 let b = rhs.to_u32().ok_or(ShiftNegative)?;
549 match self {
550 I8(a) => Ok(I8(overflowing!(a.overflowing_shl(b), Op::Shl))),
551 I16(a) => Ok(I16(overflowing!(a.overflowing_shl(b), Op::Shl))),
552 I32(a) => Ok(I32(overflowing!(a.overflowing_shl(b), Op::Shl))),
553 I64(a) => Ok(I64(overflowing!(a.overflowing_shl(b), Op::Shl))),
554 I128(a) => Ok(I128(overflowing!(a.overflowing_shl(b), Op::Shl))),
555 Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shl(b), Op::Shl)))),
556 Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shl(b), Op::Shl)))),
557 Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shl(b), Op::Shl)))),
558 U8(a) => Ok(U8(overflowing!(a.overflowing_shl(b), Op::Shl))),
559 U16(a) => Ok(U16(overflowing!(a.overflowing_shl(b), Op::Shl))),
560 U32(a) => Ok(U32(overflowing!(a.overflowing_shl(b), Op::Shl))),
561 U64(a) => Ok(U64(overflowing!(a.overflowing_shl(b), Op::Shl))),
562 U128(a) => Ok(U128(overflowing!(a.overflowing_shl(b), Op::Shl))),
563 Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shl(b), Op::Shl)))),
564 Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shl(b), Op::Shl)))),
565 Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shl(b), Op::Shl)))),
566 }
567 }
568 }
569
570 impl ::std::ops::Shr<ConstInt> for ConstInt {
571 type Output = Result<Self, ConstMathErr>;
572 fn shr(self, rhs: Self) -> Result<Self, ConstMathErr> {
573 let b = rhs.to_u32().ok_or(ShiftNegative)?;
574 match self {
575 I8(a) => Ok(I8(overflowing!(a.overflowing_shr(b), Op::Shr))),
576 I16(a) => Ok(I16(overflowing!(a.overflowing_shr(b), Op::Shr))),
577 I32(a) => Ok(I32(overflowing!(a.overflowing_shr(b), Op::Shr))),
578 I64(a) => Ok(I64(overflowing!(a.overflowing_shr(b), Op::Shr))),
579 I128(a) => Ok(I128(overflowing!(a.overflowing_shr(b), Op::Shr))),
580 Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shr(b), Op::Shr)))),
581 Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shr(b), Op::Shr)))),
582 Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shr(b), Op::Shr)))),
583 U8(a) => Ok(U8(overflowing!(a.overflowing_shr(b), Op::Shr))),
584 U16(a) => Ok(U16(overflowing!(a.overflowing_shr(b), Op::Shr))),
585 U32(a) => Ok(U32(overflowing!(a.overflowing_shr(b), Op::Shr))),
586 U64(a) => Ok(U64(overflowing!(a.overflowing_shr(b), Op::Shr))),
587 U128(a) => Ok(U128(overflowing!(a.overflowing_shr(b), Op::Shr))),
588 Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shr(b), Op::Shr)))),
589 Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shr(b), Op::Shr)))),
590 Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shr(b), Op::Shr)))),
591 }
592 }
593 }
594
595 impl ::std::ops::Neg for ConstInt {
596 type Output = Result<Self, ConstMathErr>;
597 fn neg(self) -> Result<Self, ConstMathErr> {
598 match self {
599 I8(a) => Ok(I8(overflowing!(a.overflowing_neg(), Op::Neg))),
600 I16(a) => Ok(I16(overflowing!(a.overflowing_neg(), Op::Neg))),
601 I32(a) => Ok(I32(overflowing!(a.overflowing_neg(), Op::Neg))),
602 I64(a) => Ok(I64(overflowing!(a.overflowing_neg(), Op::Neg))),
603 I128(a) => Ok(I128(overflowing!(a.overflowing_neg(), Op::Neg))),
604 Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_neg(), Op::Neg)))),
605 Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_neg(), Op::Neg)))),
606 Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_neg(), Op::Neg)))),
607 a@U8(0) | a@U16(0) | a@U32(0) | a@U64(0) | a@U128(0) |
608 a@Usize(Us16(0)) | a@Usize(Us32(0)) | a@Usize(Us64(0)) => Ok(a),
609 U8(_) | U16(_) | U32(_) | U64(_) | U128(_) | Usize(_) => Err(UnsignedNegation),
610 }
611 }
612 }
613
614 impl ::std::ops::Not for ConstInt {
615 type Output = Result<Self, ConstMathErr>;
616 fn not(self) -> Result<Self, ConstMathErr> {
617 match self {
618 I8(a) => Ok(I8(!a)),
619 I16(a) => Ok(I16(!a)),
620 I32(a) => Ok(I32(!a)),
621 I64(a) => Ok(I64(!a)),
622 I128(a) => Ok(I128(!a)),
623 Isize(Is16(a)) => Ok(Isize(Is16(!a))),
624 Isize(Is32(a)) => Ok(Isize(Is32(!a))),
625 Isize(Is64(a)) => Ok(Isize(Is64(!a))),
626 U8(a) => Ok(U8(!a)),
627 U16(a) => Ok(U16(!a)),
628 U32(a) => Ok(U32(!a)),
629 U64(a) => Ok(U64(!a)),
630 U128(a) => Ok(U128(!a)),
631 Usize(Us16(a)) => Ok(Usize(Us16(!a))),
632 Usize(Us32(a)) => Ok(Usize(Us32(!a))),
633 Usize(Us64(a)) => Ok(Usize(Us64(!a))),
634 }
635 }
636 }