blob: eca2951be670245c86366d2e96c50659f0b6ae47 [file] [log] [blame]
Paul Sokolovsky966879c2014-01-17 20:01:36 +02001#include <stdlib.h>
2#include <stdint.h>
3#include <string.h>
4#include <assert.h>
5
6#include "nlr.h"
7#include "misc.h"
8#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +00009#include "qstr.h"
Paul Sokolovsky966879c2014-01-17 20:01:36 +020010#include "obj.h"
Damien George438c88d2014-02-22 19:25:23 +000011#include "mpz.h"
Paul Sokolovsky966879c2014-01-17 20:01:36 +020012#include "objint.h"
13#include "runtime0.h"
14
15#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
16
Paul Sokolovsky966879c2014-01-17 20:01:36 +020017// Python3 no longer has "l" suffix for long ints. We allow to use it
18// for debugging purpose though.
19#ifdef DEBUG
20#define SUFFIX "l"
21#else
22#define SUFFIX ""
23#endif
24
25void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
Damien George5fa93b62014-01-22 14:35:10 +000026 if (MP_OBJ_IS_SMALL_INT(self_in)) {
Damien George0379b552014-02-22 17:34:09 +000027 print(env, INT_FMT, MP_OBJ_SMALL_INT_VALUE(self_in));
Damien George5fa93b62014-01-22 14:35:10 +000028 } else {
29 mp_obj_int_t *self = self_in;
30 print(env, "%lld" SUFFIX, self->val);
31 }
Paul Sokolovsky966879c2014-01-17 20:01:36 +020032}
33
Paul Sokolovsky9b00dad2014-01-27 09:05:50 +020034mp_obj_t int_unary_op(int op, mp_obj_t o_in) {
35 mp_obj_int_t *o = o_in;
36 switch (op) {
Paul Sokolovskyc1d9bbc2014-01-30 04:37:19 +020037 case RT_UNARY_OP_BOOL: return MP_BOOL(o->val != 0);
Paul Sokolovsky9b00dad2014-01-27 09:05:50 +020038 case RT_UNARY_OP_POSITIVE: return o_in;
39 case RT_UNARY_OP_NEGATIVE: return mp_obj_new_int_from_ll(-o->val);
40 case RT_UNARY_OP_INVERT: return mp_obj_new_int_from_ll(~o->val);
41 default: return NULL; // op not supported
42 }
43}
44
Paul Sokolovsky966879c2014-01-17 20:01:36 +020045mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
46 mp_obj_int_t *lhs = lhs_in;
47 mp_obj_int_t *rhs = rhs_in;
48 long long rhs_val;
49
50 if (MP_OBJ_IS_SMALL_INT(rhs)) {
51 rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
52 } else if (MP_OBJ_IS_TYPE(rhs, &int_type)) {
53 rhs_val = rhs->val;
54 } else {
55 return MP_OBJ_NULL;
56 }
57
58 switch (op) {
59 case RT_BINARY_OP_ADD:
60 return mp_obj_new_int_from_ll(lhs->val + rhs_val);
61 case RT_BINARY_OP_SUBTRACT:
62 return mp_obj_new_int_from_ll(lhs->val - rhs_val);
Paul Sokolovsky9b00dad2014-01-27 09:05:50 +020063 case RT_BINARY_OP_MULTIPLY:
64 return mp_obj_new_int_from_ll(lhs->val * rhs_val);
65 case RT_BINARY_OP_FLOOR_DIVIDE:
66 return mp_obj_new_int_from_ll(lhs->val / rhs_val);
67 case RT_BINARY_OP_MODULO:
68 return mp_obj_new_int_from_ll(lhs->val % rhs_val);
Paul Sokolovsky966879c2014-01-17 20:01:36 +020069
70 case RT_BINARY_OP_INPLACE_ADD:
Paul Sokolovsky9b00dad2014-01-27 09:05:50 +020071 lhs->val += rhs_val; return lhs;
Paul Sokolovsky966879c2014-01-17 20:01:36 +020072 case RT_BINARY_OP_INPLACE_SUBTRACT:
Paul Sokolovsky9b00dad2014-01-27 09:05:50 +020073 lhs->val -= rhs_val; return lhs;
74 case RT_BINARY_OP_INPLACE_MULTIPLY:
75 lhs->val *= rhs_val; return lhs;
76 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE:
77 lhs->val /= rhs_val; return lhs;
78 case RT_BINARY_OP_INPLACE_MODULO:
79 lhs->val %= rhs_val; return lhs;
Paul Sokolovsky966879c2014-01-17 20:01:36 +020080
81 case RT_BINARY_OP_AND:
82 return mp_obj_new_int_from_ll(lhs->val & rhs_val);
83 case RT_BINARY_OP_OR:
84 return mp_obj_new_int_from_ll(lhs->val | rhs_val);
85 case RT_BINARY_OP_XOR:
86 return mp_obj_new_int_from_ll(lhs->val ^ rhs_val);
87
Paul Sokolovsky9b00dad2014-01-27 09:05:50 +020088 case RT_BINARY_OP_INPLACE_AND:
89 lhs->val &= rhs_val; return lhs;
90 case RT_BINARY_OP_INPLACE_OR:
91 lhs->val |= rhs_val; return lhs;
92 case RT_BINARY_OP_INPLACE_XOR:
93 lhs->val ^= rhs_val; return lhs;
94
Paul Sokolovsky966879c2014-01-17 20:01:36 +020095 case RT_BINARY_OP_LSHIFT:
96 return mp_obj_new_int_from_ll(lhs->val << (int)rhs_val);
97 case RT_BINARY_OP_RSHIFT:
98 return mp_obj_new_int_from_ll(lhs->val >> (int)rhs_val);
99
Paul Sokolovsky9b00dad2014-01-27 09:05:50 +0200100 case RT_BINARY_OP_INPLACE_LSHIFT:
101 lhs->val <<= (int)rhs_val; return lhs;
102 case RT_BINARY_OP_INPLACE_RSHIFT:
103 lhs->val >>= (int)rhs_val; return lhs;
104
Damien George9aa2a522014-02-01 23:04:09 +0000105 case RT_BINARY_OP_LESS:
Paul Sokolovsky966879c2014-01-17 20:01:36 +0200106 return MP_BOOL(lhs->val < rhs_val);
Damien George9aa2a522014-02-01 23:04:09 +0000107 case RT_BINARY_OP_MORE:
Paul Sokolovsky966879c2014-01-17 20:01:36 +0200108 return MP_BOOL(lhs->val > rhs_val);
Damien George9aa2a522014-02-01 23:04:09 +0000109 case RT_BINARY_OP_LESS_EQUAL:
Paul Sokolovsky966879c2014-01-17 20:01:36 +0200110 return MP_BOOL(lhs->val <= rhs_val);
Damien George9aa2a522014-02-01 23:04:09 +0000111 case RT_BINARY_OP_MORE_EQUAL:
Paul Sokolovsky966879c2014-01-17 20:01:36 +0200112 return MP_BOOL(lhs->val >= rhs_val);
Damien George9aa2a522014-02-01 23:04:09 +0000113 case RT_BINARY_OP_EQUAL:
Paul Sokolovsky966879c2014-01-17 20:01:36 +0200114 return MP_BOOL(lhs->val == rhs_val);
Damien George9aa2a522014-02-01 23:04:09 +0000115 case RT_BINARY_OP_NOT_EQUAL:
Paul Sokolovsky966879c2014-01-17 20:01:36 +0200116 return MP_BOOL(lhs->val != rhs_val);
117
118 default:
119 // op not supported
120 return MP_OBJ_NULL;
121 }
122}
123
124mp_obj_t mp_obj_new_int(machine_int_t value) {
125 if (MP_OBJ_FITS_SMALL_INT(value)) {
126 return MP_OBJ_NEW_SMALL_INT(value);
127 }
128 return mp_obj_new_int_from_ll(value);
129}
130
131mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
132 // SMALL_INT accepts only signed numbers, of one bit less size
133 // than word size, which totals 2 bits less for unsigned numbers.
134 if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) {
135 return MP_OBJ_NEW_SMALL_INT(value);
136 }
137 return mp_obj_new_int_from_ll(value);
138}
139
140mp_obj_t mp_obj_new_int_from_ll(long long val) {
141 mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
142 o->base.type = &int_type;
143 o->val = val;
144 return o;
145}
146
147mp_obj_t mp_obj_new_int_from_long_str(const char *s) {
148 long long v;
149 char *end;
150 // TODO: this doesn't handle Python hacked 0o octal syntax
151 v = strtoll(s, &end, 0);
Paul Sokolovsky4d0588d2014-02-18 00:21:11 +0200152 if (*end != 0) {
153 nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
154 }
Paul Sokolovsky966879c2014-01-17 20:01:36 +0200155 mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
156 o->base.type = &int_type;
157 o->val = v;
158 return o;
159}
160
Paul Sokolovskyd26b3792014-01-18 16:07:16 +0200161machine_int_t mp_obj_int_get(mp_obj_t self_in) {
162 if (MP_OBJ_IS_SMALL_INT(self_in)) {
163 return MP_OBJ_SMALL_INT_VALUE(self_in);
164 }
Paul Sokolovsky966879c2014-01-17 20:01:36 +0200165 mp_obj_int_t *self = self_in;
166 return self->val;
167}
168
Paul Sokolovskyd26b3792014-01-18 16:07:16 +0200169machine_int_t mp_obj_int_get_checked(mp_obj_t self_in) {
170 // TODO: Check overflow
171 return mp_obj_int_get(self_in);
172}
173
Paul Sokolovsky966879c2014-01-17 20:01:36 +0200174#endif