]> git.proxmox.com Git - rustc.git/blame - src/librustc_const_math/int.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc_const_math / int.rs
CommitLineData
54a0048b
SL
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
11use std::cmp::Ordering;
12use syntax::attr::IntType;
13use syntax::ast::{IntTy, UintTy};
14
15use super::is::*;
16use super::us::*;
17use super::err::*;
18
19#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
20pub enum ConstInt {
21 I8(i8),
22 I16(i16),
23 I32(i32),
24 I64(i64),
32a655c1 25 I128(i128),
54a0048b
SL
26 Isize(ConstIsize),
27 U8(u8),
28 U16(u16),
29 U32(u32),
30 U64(u64),
32a655c1 31 U128(u128),
54a0048b 32 Usize(ConstUsize),
54a0048b
SL
33}
34pub use self::ConstInt::*;
35
36
37macro_rules! bounds {
32a655c1
SL
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
52mod ubounds {
53 #![allow(dead_code)]
32a655c1
SL
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
54a0048b
SL
59 }
60}
61
32a655c1
SL
62mod ibounds {
63 #![allow(dead_code)]
32a655c1
SL
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 }
54a0048b
SL
75}
76
77impl ConstInt {
32a655c1
SL
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
8bb4bdeb 93 /// Creates a new signed ConstInt with matching type while also checking that overflow does
32a655c1
SL
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
8bb4bdeb
XL
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 }
54a0048b
SL
118 }
119
8bb4bdeb
XL
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)
54a0048b
SL
129 }
130 }
131
132 /// Description of the type, not the value
133 pub fn description(&self) -> &'static str {
134 match *self {
54a0048b
SL
135 I8(_) => "i8",
136 I16(_) => "i16",
137 I32(_) => "i32",
138 I64(_) => "i64",
32a655c1 139 I128(_) => "i128",
54a0048b
SL
140 Isize(_) => "isize",
141 U8(_) => "u8",
142 U16(_) => "u16",
143 U32(_) => "u32",
144 U64(_) => "u64",
32a655c1 145 U128(_) => "u128",
54a0048b
SL
146 Usize(_) => "usize",
147 }
148 }
149
32a655c1
SL
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 {
8bb4bdeb
XL
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,
54a0048b
SL
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> {
32a655c1
SL
175 self.to_u128().and_then(|v| if v <= u32::max_value() as u128 {
176 Some(v as u32)
177 } else {
178 None
179 })
54a0048b
SL
180 }
181
32a655c1 182 /// Converts the value to a `u64` if it's in the range 0...std::u64::MAX
54a0048b 183 pub fn to_u64(&self) -> Option<u64> {
32a655c1
SL
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> {
54a0048b 193 match *self {
32a655c1
SL
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),
54a0048b
SL
210 _ => None,
211 }
212 }
213
8bb4bdeb
XL
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
54a0048b
SL
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,
32a655c1 262 I128(v) => v < 0,
3157f602 263 Isize(Is16(v)) => v < 0,
54a0048b
SL
264 Isize(Is32(v)) => v < 0,
265 Isize(Is64(v)) => v < 0,
54a0048b
SL
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> {
8bb4bdeb 272 match (self, rhs) {
54a0048b
SL
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)),
32a655c1 277 (I128(a), I128(b)) => Ok(a.cmp(&b)),
3157f602 278 (Isize(Is16(a)), Isize(Is16(b))) => Ok(a.cmp(&b)),
54a0048b
SL
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)),
32a655c1 285 (U128(a), U128(b)) => Ok(a.cmp(&b)),
3157f602 286 (Usize(Us16(a)), Usize(Us16(b))) => Ok(a.cmp(&b)),
54a0048b
SL
287 (Usize(Us32(a)), Usize(Us32(b))) => Ok(a.cmp(&b)),
288 (Usize(Us64(a)), Usize(Us64(b))) => Ok(a.cmp(&b)),
54a0048b
SL
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)),
32a655c1 303 ConstInt::I128(i) => ConstInt::I128(add1!(i)),
3157f602 304 ConstInt::Isize(ConstIsize::Is16(i)) => ConstInt::Isize(ConstIsize::Is16(add1!(i))),
54a0048b
SL
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)),
32a655c1 311 ConstInt::U128(i) => ConstInt::U128(add1!(i)),
3157f602 312 ConstInt::Usize(ConstUsize::Us16(i)) => ConstInt::Usize(ConstUsize::Us16(add1!(i))),
54a0048b
SL
313 ConstInt::Usize(ConstUsize::Us32(i)) => ConstInt::Usize(ConstUsize::Us32(add1!(i))),
314 ConstInt::Usize(ConstUsize::Us64(i)) => ConstInt::Usize(ConstUsize::Us64(add1!(i))),
54a0048b
SL
315 }
316 }
317
8bb4bdeb 318 pub fn int_type(self) -> IntType {
54a0048b 319 match self {
8bb4bdeb
XL
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),
54a0048b
SL
332 }
333 }
334}
335
336impl ::std::cmp::PartialOrd for ConstInt {
337 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
338 self.try_cmp(*other).ok()
339 }
340}
341
342impl ::std::cmp::Ord for ConstInt {
343 fn cmp(&self, other: &Self) -> Ordering {
344 self.try_cmp(*other).unwrap()
345 }
346}
347
348impl ::std::fmt::Display for ConstInt {
349 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
350 match *self {
54a0048b
SL
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),
32a655c1 355 I128(i) => write!(fmt, "{}i128", i),
54a0048b
SL
356 Isize(ConstIsize::Is64(i)) => write!(fmt, "{}isize", i),
357 Isize(ConstIsize::Is32(i)) => write!(fmt, "{}isize", i),
3157f602 358 Isize(ConstIsize::Is16(i)) => write!(fmt, "{}isize", i),
54a0048b
SL
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),
32a655c1 363 U128(i) => write!(fmt, "{}u128", i),
54a0048b
SL
364 Usize(ConstUsize::Us64(i)) => write!(fmt, "{}usize", i),
365 Usize(ConstUsize::Us32(i)) => write!(fmt, "{}usize", i),
3157f602 366 Usize(ConstUsize::Us16(i)) => write!(fmt, "{}usize", i),
54a0048b
SL
367 }
368 }
369}
370
371macro_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
381macro_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> {
8bb4bdeb 386 match (self, rhs) {
54a0048b
SL
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),
32a655c1 391 (I128(a), I128(b)) => a.$checked_func(b).map(I128),
3157f602 392 (Isize(Is16(a)), Isize(Is16(b))) => a.$checked_func(b).map(Is16).map(Isize),
54a0048b
SL
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),
32a655c1 399 (U128(a), U128(b)) => a.$checked_func(b).map(U128),
3157f602 400 (Usize(Us16(a)), Usize(Us16(b))) => a.$checked_func(b).map(Us16).map(Usize),
54a0048b
SL
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),
54a0048b
SL
403 _ => return Err(UnequalTypes(Op::$op)),
404 }.ok_or(Overflow(Op::$op))
405 }
406 }
407 }
408}
409
410macro_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> {
8bb4bdeb 415 match (self, rhs) {
54a0048b
SL
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))),
32a655c1 420 (I128(a), I128(b)) => Ok(I128(a.$func(b))),
3157f602 421 (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a.$func(b)))),
54a0048b
SL
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))),
32a655c1 428 (U128(a), U128(b)) => Ok(U128(a.$func(b))),
3157f602 429 (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a.$func(b)))),
54a0048b
SL
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)))),
54a0048b
SL
432 _ => Err(UnequalTypes(Op::$op)),
433 }
434 }
435 }
436 }
437}
438
439impl_binop!(Add, add, checked_add);
440impl_binop!(Sub, sub, checked_sub);
441impl_binop!(Mul, mul, checked_mul);
442derive_binop!(BitAnd, bitand);
443derive_binop!(BitOr, bitor);
444derive_binop!(BitXor, bitxor);
445
32a655c1 446const I128_MIN: i128 = ::std::i128::MIN;
32a655c1 447
54a0048b
SL
448fn 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),
32a655c1 459 (I128(_), I128(0)) => Err(zerr),
3157f602 460 (Isize(_), Isize(Is16(0))) => Err(zerr),
54a0048b
SL
461 (Isize(_), Isize(Is32(0))) => Err(zerr),
462 (Isize(_), Isize(Is64(0))) => Err(zerr),
54a0048b
SL
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),
32a655c1 468 (U128(_), U128(0)) => Err(zerr),
3157f602 469 (Usize(_), Usize(Us16(0))) => Err(zerr),
54a0048b
SL
470 (Usize(_), Usize(Us32(0))) => Err(zerr),
471 (Usize(_), Usize(Us64(0))) => Err(zerr),
54a0048b
SL
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)),
32a655c1 477 (I128(I128_MIN), I128(-1)) => Err(Overflow(op)),
3157f602 478 (Isize(Is16(::std::i16::MIN)), Isize(Is16(-1))) => Err(Overflow(op)),
54a0048b
SL
479 (Isize(Is32(::std::i32::MIN)), Isize(Is32(-1))) => Err(Overflow(op)),
480 (Isize(Is64(::std::i64::MIN)), Isize(Is64(-1))) => Err(Overflow(op)),
54a0048b
SL
481
482 _ => Ok(()),
483 }
484}
485
486impl ::std::ops::Div for ConstInt {
487 type Output = Result<Self, ConstMathErr>;
488 fn div(self, rhs: Self) -> Result<Self, ConstMathErr> {
8bb4bdeb 489 let (lhs, rhs) = (self, rhs);
54a0048b
SL
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)),
32a655c1 496 (I128(a), I128(b)) => Ok(I128(a/b)),
3157f602 497 (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a/b))),
54a0048b
SL
498 (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a/b))),
499 (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a/b))),
54a0048b
SL
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)),
32a655c1 505 (U128(a), U128(b)) => Ok(U128(a/b)),
3157f602 506 (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a/b))),
54a0048b
SL
507 (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a/b))),
508 (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a/b))),
54a0048b
SL
509
510 _ => Err(UnequalTypes(Op::Div)),
511 }
512 }
513}
514
515impl ::std::ops::Rem for ConstInt {
516 type Output = Result<Self, ConstMathErr>;
517 fn rem(self, rhs: Self) -> Result<Self, ConstMathErr> {
8bb4bdeb 518 let (lhs, rhs) = (self, rhs);
54a0048b
SL
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)),
32a655c1 526 (I128(a), I128(b)) => Ok(I128(a%b)),
3157f602 527 (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a%b))),
54a0048b
SL
528 (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a%b))),
529 (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a%b))),
54a0048b
SL
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)),
32a655c1 535 (U128(a), U128(b)) => Ok(U128(a%b)),
3157f602 536 (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a%b))),
54a0048b
SL
537 (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a%b))),
538 (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a%b))),
54a0048b
SL
539
540 _ => Err(UnequalTypes(Op::Rem)),
541 }
542 }
543}
544
545impl ::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))),
32a655c1 554 I128(a) => Ok(I128(overflowing!(a.overflowing_shl(b), Op::Shl))),
3157f602 555 Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shl(b), Op::Shl)))),
54a0048b
SL
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))),
32a655c1 562 U128(a) => Ok(U128(overflowing!(a.overflowing_shl(b), Op::Shl))),
3157f602 563 Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shl(b), Op::Shl)))),
54a0048b
SL
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)))),
54a0048b
SL
566 }
567 }
568}
569
570impl ::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))),
a7813a04 578 I64(a) => Ok(I64(overflowing!(a.overflowing_shr(b), Op::Shr))),
32a655c1 579 I128(a) => Ok(I128(overflowing!(a.overflowing_shr(b), Op::Shr))),
3157f602 580 Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shr(b), Op::Shr)))),
54a0048b
SL
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))),
32a655c1 587 U128(a) => Ok(U128(overflowing!(a.overflowing_shr(b), Op::Shr))),
3157f602 588 Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shr(b), Op::Shr)))),
54a0048b
SL
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)))),
54a0048b
SL
591 }
592 }
593}
594
595impl ::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))),
32a655c1 603 I128(a) => Ok(I128(overflowing!(a.overflowing_neg(), Op::Neg))),
3157f602 604 Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_neg(), Op::Neg)))),
54a0048b
SL
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)))),
32a655c1
SL
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),
54a0048b
SL
610 }
611 }
612}
613
614impl ::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)),
32a655c1 622 I128(a) => Ok(I128(!a)),
3157f602 623 Isize(Is16(a)) => Ok(Isize(Is16(!a))),
54a0048b
SL
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)),
32a655c1 630 U128(a) => Ok(U128(!a)),
3157f602 631 Usize(Us16(a)) => Ok(Usize(Us16(!a))),
54a0048b
SL
632 Usize(Us32(a)) => Ok(Usize(Us32(!a))),
633 Usize(Us64(a)) => Ok(Usize(Us64(!a))),
54a0048b
SL
634 }
635 }
636}