Numworks Epsilon  1.4.1
Graphing Calculator Operating System
objint_longlong.c
Go to the documentation of this file.
1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2013, 2014 Damien P. George
7  * Copyright (c) 2014 Paul Sokolovsky
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25  * THE SOFTWARE.
26  */
27 
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "py/smallint.h"
32 #include "py/objint.h"
33 #include "py/runtime.h"
34 
35 #if MICROPY_PY_BUILTINS_FLOAT
36 #include <math.h>
37 #endif
38 
39 #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
40 
41 #if MICROPY_PY_SYS_MAXSIZE
42 // Export value for sys.maxsize
44 #endif
45 
46 mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) {
47  int delta = 1;
48  if (!big_endian) {
49  buf += len - 1;
50  delta = -1;
51  }
52 
53  mp_longint_impl_t value = 0;
54  for (; len--; buf += delta) {
55  value = (value << 8) | *buf;
56  }
57  return mp_obj_new_int_from_ll(value);
58 }
59 
60 void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) {
61  assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
62  mp_obj_int_t *self = self_in;
63  long long val = self->val;
64  if (big_endian) {
65  byte *b = buf + len;
66  while (b > buf) {
67  *--b = val;
68  val >>= 8;
69  }
70  } else {
71  for (; len > 0; --len) {
72  *buf++ = val;
73  val >>= 8;
74  }
75  }
76 }
77 
78 int mp_obj_int_sign(mp_obj_t self_in) {
79  mp_longint_impl_t val;
80  if (MP_OBJ_IS_SMALL_INT(self_in)) {
81  val = MP_OBJ_SMALL_INT_VALUE(self_in);
82  } else {
83  mp_obj_int_t *self = self_in;
84  val = self->val;
85  }
86  if (val < 0) {
87  return -1;
88  } else if (val > 0) {
89  return 1;
90  } else {
91  return 0;
92  }
93 }
94 
96  mp_obj_int_t *o = o_in;
97  switch (op) {
98  case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->val != 0);
99 
100  // truncate value to fit in mp_int_t, which gives the same hash as
101  // small int if the value fits without truncation
103 
104  case MP_UNARY_OP_POSITIVE: return o_in;
107  case MP_UNARY_OP_ABS: {
108  mp_obj_int_t *self = MP_OBJ_TO_PTR(o_in);
109  if (self->val >= 0) {
110  return o_in;
111  }
112  self = mp_obj_new_int_from_ll(self->val);
113  // TODO could overflow long long
114  self->val = -self->val;
115  return MP_OBJ_FROM_PTR(self);
116  }
117  default: return MP_OBJ_NULL; // op not supported
118  }
119 }
120 
122  long long lhs_val;
123  long long rhs_val;
124 
125  if (MP_OBJ_IS_SMALL_INT(lhs_in)) {
126  lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs_in);
127  } else if (MP_OBJ_IS_TYPE(lhs_in, &mp_type_int)) {
128  lhs_val = ((mp_obj_int_t*)lhs_in)->val;
129  } else {
130  return MP_OBJ_NULL; // op not supported
131  }
132 
133  if (MP_OBJ_IS_SMALL_INT(rhs_in)) {
134  rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs_in);
135  } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_int)) {
136  rhs_val = ((mp_obj_int_t*)rhs_in)->val;
137  } else {
138  // delegate to generic function to check for extra cases
139  return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
140  }
141 
142  switch (op) {
143  case MP_BINARY_OP_ADD:
145  return mp_obj_new_int_from_ll(lhs_val + rhs_val);
148  return mp_obj_new_int_from_ll(lhs_val - rhs_val);
151  return mp_obj_new_int_from_ll(lhs_val * rhs_val);
154  return mp_obj_new_int_from_ll(lhs_val / rhs_val);
155  case MP_BINARY_OP_MODULO:
157  return mp_obj_new_int_from_ll(lhs_val % rhs_val);
158 
159  case MP_BINARY_OP_AND:
161  return mp_obj_new_int_from_ll(lhs_val & rhs_val);
162  case MP_BINARY_OP_OR:
164  return mp_obj_new_int_from_ll(lhs_val | rhs_val);
165  case MP_BINARY_OP_XOR:
167  return mp_obj_new_int_from_ll(lhs_val ^ rhs_val);
168 
169  case MP_BINARY_OP_LSHIFT:
171  return mp_obj_new_int_from_ll(lhs_val << (int)rhs_val);
172  case MP_BINARY_OP_RSHIFT:
174  return mp_obj_new_int_from_ll(lhs_val >> (int)rhs_val);
175 
176  case MP_BINARY_OP_POWER:
178  if (rhs_val < 0) {
179  #if MICROPY_PY_BUILTINS_FLOAT
180  return mp_obj_float_binary_op(op, lhs_val, rhs_in);
181  #else
182  mp_raise_ValueError("negative power with no float support");
183  #endif
184  }
185  long long ans = 1;
186  while (rhs_val > 0) {
187  if (rhs_val & 1) {
188  ans *= lhs_val;
189  }
190  if (rhs_val == 1) {
191  break;
192  }
193  rhs_val /= 2;
194  lhs_val *= lhs_val;
195  }
196  return mp_obj_new_int_from_ll(ans);
197  }
198 
199  case MP_BINARY_OP_LESS:
200  return mp_obj_new_bool(lhs_val < rhs_val);
201  case MP_BINARY_OP_MORE:
202  return mp_obj_new_bool(lhs_val > rhs_val);
204  return mp_obj_new_bool(lhs_val <= rhs_val);
206  return mp_obj_new_bool(lhs_val >= rhs_val);
207  case MP_BINARY_OP_EQUAL:
208  return mp_obj_new_bool(lhs_val == rhs_val);
209 
210  default:
211  return MP_OBJ_NULL; // op not supported
212  }
213 }
214 
216  if (MP_SMALL_INT_FITS(value)) {
217  return MP_OBJ_NEW_SMALL_INT(value);
218  }
219  return mp_obj_new_int_from_ll(value);
220 }
221 
223  // SMALL_INT accepts only signed numbers, so make sure the input
224  // value fits completely in the small-int positive range.
225  if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {
226  return MP_OBJ_NEW_SMALL_INT(value);
227  }
228  return mp_obj_new_int_from_ll(value);
229 }
230 
233  o->base.type = &mp_type_int;
234  o->val = val;
235  return o;
236 }
237 
238 mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
239  // TODO raise an exception if the unsigned long long won't fit
240  if (val >> (sizeof(unsigned long long) * 8 - 1) != 0) {
241  mp_raise_msg(&mp_type_OverflowError, "ulonglong too large");
242  }
244  o->base.type = &mp_type_int;
245  o->val = val;
246  return o;
247 }
248 
249 mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
250  // TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated
251  // TODO check overflow
253  o->base.type = &mp_type_int;
254  char *endptr;
255  o->val = strtoll(*str, &endptr, base);
256  *str = endptr;
257  return o;
258 }
259 
261  if (MP_OBJ_IS_SMALL_INT(self_in)) {
262  return MP_OBJ_SMALL_INT_VALUE(self_in);
263  } else {
264  const mp_obj_int_t *self = self_in;
265  return self->val;
266  }
267 }
268 
270  // TODO: Check overflow
271  return mp_obj_int_get_truncated(self_in);
272 }
273 
274 #if MICROPY_PY_BUILTINS_FLOAT
275 mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) {
276  assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
277  mp_obj_int_t *self = self_in;
278  return self->val;
279 }
280 #endif
281 
282 #endif
intptr_t mp_int_t
Definition: mpconfigport.h:73
uintptr_t mp_uint_t
Definition: mpconfigport.h:74
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg)
Definition: runtime.c:1448
#define assert(e)
Definition: assert.h:9
mp_obj_base_t base
Definition: objint.h:33
#define MP_OBJ_IS_TYPE(o, t)
Definition: obj.h:254
mp_obj_t mp_obj_new_int_from_ll(long long val)
mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
Definition: objint.c:373
int mp_obj_int_sign(mp_obj_t self_in)
mp_longint_impl_t val
Definition: objint.h:35
#define MP_OBJ_FROM_PTR(p)
Definition: obj.h:233
mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in)
mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base)
mp_unary_op_t
Definition: runtime0.h:45
mp_obj_t mp_obj_new_int(mp_int_t value)
#define MP_OBJ_SMALL_INT_VALUE(o)
Definition: obj.h:86
void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf)
#define MP_OBJ_NEW_SMALL_INT(small_int)
Definition: obj.h:87
uint64_t mp_const_obj_t
Definition: obj.h:40
#define MP_OBJ_NULL
Definition: obj.h:73
#define MP_SMALL_INT_FITS(n)
Definition: smallint.h:40
mp_obj_t mp_obj_new_int_from_ull(unsigned long long val)
mp_binary_op_t
Definition: runtime0.h:67
mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf)
unsigned char byte
Definition: misc.h:37
NORETURN void mp_raise_ValueError(const char *msg)
Definition: runtime.c:1456
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value)
#define MP_OBJ_TO_PTR(o)
Definition: obj.h:228
const mp_obj_int_t mp_maxsize_obj
#define MP_SSIZE_MAX
Definition: mpconfig.h:1247
uint64_t mp_obj_t
Definition: obj.h:39
const mp_obj_type_t mp_type_int
Definition: obj.h:544
mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in)
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in)
#define m_new_obj(type)
Definition: misc.h:60
#define MP_SMALL_INT_POSITIVE_MASK
Definition: smallint.h:42
const mp_obj_type_t mp_type_OverflowError