overflow 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +79 -35
- data/Rakefile +1 -1
- data/example/murmurhash.rb +44 -0
- data/ext/overflow/extconf.rb +2 -0
- data/ext/overflow/overflow.c +455 -0
- data/lib/overflow.rb +0 -1
- data/overflow.gemspec +2 -2
- data/spec/numeric_spec.rb +167 -0
- data/spec/overflow_spec.rb +150 -101
- data/spec/spec_helper.rb +2 -0
- metadata +20 -4
- data/ext/overflow/init.c +0 -323
- data/lib/overflow/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 833a4630a30e7f8723e782791f9ab23b165a06e7
|
4
|
+
data.tar.gz: 449f416ff31101f37f2a320a72db5d6cf5cbe1b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d895399c9ce7b662012efc2421bcb0618cba2a4d5eeb49cb23b3ed7efbb886e016311968ee05e5275ff9ea4edcf9cf9ff97ce98d33246a3e29ac7bff8784f2b8
|
7
|
+
data.tar.gz: b6ffe5f740632d821c863d07a01963d42f43559f3eb486c26325c2d43dca6aab429fb5f9cec2e284cb7a47c7d992c7b0a6c18d64e18a6b8f0b45d7764ded48c6
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Overflow
|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/overflow)
|
4
|
+
[](https://travis-ci.org/ksss/overflow)
|
5
|
+
|
3
6
|
Overflow is a class to overflow calculated as C language in Ruby.
|
4
7
|
|
5
8
|
## Usage
|
@@ -7,43 +10,84 @@ Overflow is a class to overflow calculated as C language in Ruby.
|
|
7
10
|
```ruby
|
8
11
|
require 'overflow'
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
while 4 <= length
|
19
|
-
d = data.shift(4).pack("C*").unpack("I")[0]
|
20
|
-
h += d # calculate not need `& 0xffffffff`
|
21
|
-
h *= m
|
22
|
-
h ^= h >> r
|
23
|
-
length -= 4
|
24
|
-
end
|
25
|
-
|
26
|
-
if 2 < length
|
27
|
-
h += (data[2] << 16) & 0xffffffff
|
28
|
-
end
|
29
|
-
if 1 < length
|
30
|
-
h += (data[1] << 8) & 0xffffffff
|
31
|
-
end
|
32
|
-
if 0 < length
|
33
|
-
h += data[0]
|
34
|
-
h *= m
|
35
|
-
h ^= h >> r
|
36
|
-
end
|
37
|
-
|
38
|
-
h *= m
|
39
|
-
h ^= h >> 10
|
40
|
-
h *= m
|
41
|
-
h ^= h >> 17
|
42
|
-
|
43
|
-
h
|
44
|
-
end
|
13
|
+
over = Overflow.new "C" #=> "C" mean 8bit unsigned char (same as pack template)
|
14
|
+
over.set 255 #=> set a number (0b11111111)
|
15
|
+
p over.to_i #=> 255 (out Fixnum object)
|
16
|
+
over = over << 4 #=> left bit shift (0b11110000)
|
17
|
+
p over.to_i #=> 240 (overflow bit is dropped)
|
18
|
+
p (over >> 4).to_i #=> 15 (0b00001111)
|
19
|
+
p (200 - over) #=> -40 (Call Overflow#coerce.)
|
45
20
|
```
|
46
21
|
|
22
|
+
## APIs
|
23
|
+
|
24
|
+
### initialize(type[, number])
|
25
|
+
|
26
|
+
**type**: defined C type
|
27
|
+
|
28
|
+
All type mean same that pack template.
|
29
|
+
|
30
|
+
- c: `int8_t`
|
31
|
+
- C: `uint8_t`
|
32
|
+
- s: `int16_t`
|
33
|
+
- S: `uint16_t`
|
34
|
+
- i: `int`
|
35
|
+
- I: `unsigned int`
|
36
|
+
- l: `int32_t`
|
37
|
+
- L: `uint32_t`
|
38
|
+
- q: `int64_t`
|
39
|
+
- Q: `uint64_t`
|
40
|
+
|
41
|
+
### set(number)
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
over = Overflow.new "C"
|
45
|
+
over.set 1
|
46
|
+
p over.to_i #=> 1
|
47
|
+
over.set 10
|
48
|
+
p over.to_i #=> 10
|
49
|
+
```
|
50
|
+
|
51
|
+
### to\_i
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
over = Overflow.new "C", 256
|
55
|
+
over.to_i #=> 0
|
56
|
+
```
|
57
|
+
|
58
|
+
### +, -, \*
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
over = Overflow.new "C", 100
|
62
|
+
over += 200 #=> 44
|
63
|
+
over -= 50 #=> 250
|
64
|
+
over *= 10 #=> 196
|
65
|
+
```
|
66
|
+
|
67
|
+
### ~, &, |, ^
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
over = Overflow.new "C", 0xaa
|
71
|
+
~over #=> 0x55
|
72
|
+
over & 0x99 #=> 0x88
|
73
|
+
over | 0x99 #=> 0xbb
|
74
|
+
over ^ 0x99 #=> 0x33
|
75
|
+
```
|
76
|
+
|
77
|
+
### \<\<, \>\>
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
over = Overflow.new "C", 0xff
|
81
|
+
over << 4 #=> 0xf0
|
82
|
+
over >> 4 #=> 0x0f
|
83
|
+
```
|
84
|
+
|
85
|
+
and all `Numeric` methods.
|
86
|
+
|
87
|
+
## Class tree
|
88
|
+
|
89
|
+
Overflow < Numeric
|
90
|
+
|
47
91
|
## Installation
|
48
92
|
|
49
93
|
Add this line to your application's Gemfile:
|
data/Rakefile
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
lib = File.expand_path('../../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'overflow'
|
7
|
+
|
8
|
+
def murmur_hash str
|
9
|
+
data = str.dup.unpack("C*")
|
10
|
+
m = 0x5bd1e995
|
11
|
+
r = 16
|
12
|
+
length = Overflow.new "I", str.bytesize
|
13
|
+
h = length * m
|
14
|
+
|
15
|
+
while 4 <= length
|
16
|
+
d = data.shift(4).pack("C*").unpack("I")[0]
|
17
|
+
h += d
|
18
|
+
h *= m
|
19
|
+
h ^= h >> r
|
20
|
+
length -= 4
|
21
|
+
end
|
22
|
+
|
23
|
+
if 2 < length
|
24
|
+
h += data[2] << 16
|
25
|
+
end
|
26
|
+
if 1 < length
|
27
|
+
h += data[1] << 8
|
28
|
+
end
|
29
|
+
if 0 < length
|
30
|
+
h += data[0]
|
31
|
+
h *= m
|
32
|
+
h ^= h >> r
|
33
|
+
end
|
34
|
+
|
35
|
+
h *= m
|
36
|
+
h ^= h >> 10
|
37
|
+
h *= m
|
38
|
+
h ^= h >> 17
|
39
|
+
|
40
|
+
h.to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
# p murmur_hash "murmur" #=> 2800467524
|
44
|
+
puts murmur_hash ARGV[0]
|
data/ext/overflow/extconf.rb
CHANGED
@@ -0,0 +1,455 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
#define OVERFLOW_TYPES_ALL_CASE(ptr, callback) do { \
|
4
|
+
switch (ptr->type) { \
|
5
|
+
case i8: ptr->value = (int8_t) callback; break; \
|
6
|
+
case ui8: ptr->value = (uint8_t) callback; break; \
|
7
|
+
case i16: ptr->value = (int16_t) callback; break; \
|
8
|
+
case ui16: ptr->value = (uint16_t) callback; break; \
|
9
|
+
case in: ptr->value = (int) callback; break; \
|
10
|
+
case uin: ptr->value = (unsigned int) callback; break; \
|
11
|
+
case i32: ptr->value = (int32_t) callback; break; \
|
12
|
+
case ui32: ptr->value = (uint32_t) callback; break; \
|
13
|
+
case i64: ptr->value = (int64_t) callback; break; \
|
14
|
+
case ui64: ptr->value = (uint64_t) callback; break; \
|
15
|
+
} \
|
16
|
+
} while(0)
|
17
|
+
|
18
|
+
#define TYPE_PLUS(type, value, other) ((type)((type)(value) + (type)(other)))
|
19
|
+
#define TYPE_MINUS(type, value, other) ((type)((type)(value) - (type)(other)))
|
20
|
+
#define TYPE_MUL(type, value, other) ((type)((type)(value) * (type)(other)))
|
21
|
+
#define TYPE_DIV(type, value, other) ((type)((type)(value) / (type)(other)))
|
22
|
+
|
23
|
+
#define SWITCH_MACRO(type, macro, a, b) do { \
|
24
|
+
switch (type) { \
|
25
|
+
case i8: a = macro(int8_t, a, b); break; \
|
26
|
+
case ui8: a = macro(uint8_t, a, b); break; \
|
27
|
+
case i16: a = macro(int16_t, a, b); break; \
|
28
|
+
case ui16: a = macro(uint16_t, a, b); break; \
|
29
|
+
case in: a = macro(int, a, b); break; \
|
30
|
+
case uin: a = macro(unsigned int, a, b); break; \
|
31
|
+
case i32: a = macro(int32_t, a, b); break; \
|
32
|
+
case ui32: a = macro(uint32_t, a, b); break; \
|
33
|
+
case i64: a = macro(int64_t, a, b); break; \
|
34
|
+
case ui64: a = macro(uint64_t, a, b); break; \
|
35
|
+
} \
|
36
|
+
} while(0)
|
37
|
+
|
38
|
+
typedef enum {
|
39
|
+
i8,
|
40
|
+
ui8,
|
41
|
+
i16,
|
42
|
+
ui16,
|
43
|
+
in,
|
44
|
+
uin,
|
45
|
+
i32,
|
46
|
+
ui32,
|
47
|
+
i64,
|
48
|
+
ui64
|
49
|
+
} types;
|
50
|
+
|
51
|
+
typedef struct {
|
52
|
+
types type;
|
53
|
+
uint64_t value;
|
54
|
+
} overflow_t;
|
55
|
+
|
56
|
+
static VALUE overflow_set(VALUE self, VALUE obj);
|
57
|
+
|
58
|
+
types char2type (char c)
|
59
|
+
{
|
60
|
+
switch (c) {
|
61
|
+
case 'c': return i8;
|
62
|
+
case 'C': return ui8;
|
63
|
+
case 's': return i16;
|
64
|
+
case 'S': return ui16;
|
65
|
+
case 'i': return in;
|
66
|
+
case 'I': return uin;
|
67
|
+
case 'l': return i32;
|
68
|
+
case 'L': return ui32;
|
69
|
+
case 'q': return i64;
|
70
|
+
case 'Q': return ui64;
|
71
|
+
default:
|
72
|
+
rb_raise(rb_eArgError, "type %c is not support", c);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
static VALUE
|
77
|
+
overflow_alloc(VALUE self)
|
78
|
+
{
|
79
|
+
overflow_t* ptr = ALLOC(overflow_t);
|
80
|
+
return Data_Wrap_Struct(self, 0, -1, ptr);
|
81
|
+
}
|
82
|
+
|
83
|
+
static VALUE
|
84
|
+
overflow_initialize(int argc, VALUE *argv, VALUE self)
|
85
|
+
{
|
86
|
+
overflow_t *ptr;
|
87
|
+
char *p;
|
88
|
+
VALUE obj = argv[0];
|
89
|
+
|
90
|
+
if (argc < 1 || rb_type(obj) != T_STRING) {
|
91
|
+
rb_raise(rb_eArgError, "set a type char for `pack' template");
|
92
|
+
}
|
93
|
+
|
94
|
+
Data_Get_Struct(self, overflow_t, ptr);
|
95
|
+
p = RSTRING_PTR(obj);
|
96
|
+
|
97
|
+
ptr->type = char2type(*p);
|
98
|
+
ptr->value = 0;
|
99
|
+
if (1 < argc) {
|
100
|
+
overflow_set(self, argv[1]);
|
101
|
+
}
|
102
|
+
return self;
|
103
|
+
}
|
104
|
+
|
105
|
+
static VALUE
|
106
|
+
overflow_initialize_copy(VALUE copy, VALUE origin)
|
107
|
+
{
|
108
|
+
overflow_t *ptr_copy, *ptr_origin;
|
109
|
+
|
110
|
+
if (copy == origin) return copy;
|
111
|
+
|
112
|
+
rb_check_frozen(copy);
|
113
|
+
|
114
|
+
Data_Get_Struct(copy, overflow_t, ptr_copy);
|
115
|
+
Data_Get_Struct(origin, overflow_t, ptr_origin);
|
116
|
+
|
117
|
+
ptr_copy->value = ptr_origin->value;
|
118
|
+
ptr_copy->type = ptr_origin->type;
|
119
|
+
|
120
|
+
return copy;
|
121
|
+
}
|
122
|
+
|
123
|
+
static VALUE
|
124
|
+
overflow_to_i(VALUE self)
|
125
|
+
{
|
126
|
+
overflow_t *ptr;
|
127
|
+
Data_Get_Struct(self, overflow_t, ptr);
|
128
|
+
|
129
|
+
switch (ptr->type) {
|
130
|
+
case i8: return INT2NUM((int8_t)ptr->value);
|
131
|
+
case ui8: return UINT2NUM((uint8_t)ptr->value);
|
132
|
+
case i16: return INT2NUM((int16_t)ptr->value);
|
133
|
+
case ui16: return UINT2NUM((uint16_t)ptr->value);
|
134
|
+
case in: return LONG2NUM((int)ptr->value);
|
135
|
+
case uin: return ULONG2NUM((unsigned int)ptr->value);
|
136
|
+
case i32: return LONG2NUM((int32_t)ptr->value);
|
137
|
+
case ui32: return ULONG2NUM((uint32_t)ptr->value);
|
138
|
+
case i64: return LL2NUM((int64_t)ptr->value);
|
139
|
+
case ui64: return ULL2NUM((uint64_t)ptr->value);
|
140
|
+
}
|
141
|
+
rb_raise(rb_eRuntimeError, "undefined type seted");
|
142
|
+
return Qnil;
|
143
|
+
}
|
144
|
+
|
145
|
+
static VALUE
|
146
|
+
overflow_coerce(VALUE self, VALUE other)
|
147
|
+
{
|
148
|
+
if (CLASS_OF(self) == CLASS_OF(other)) {
|
149
|
+
return rb_assoc_new(overflow_to_i(other), overflow_to_i(self));
|
150
|
+
}
|
151
|
+
return rb_assoc_new(other, overflow_to_i(self));
|
152
|
+
}
|
153
|
+
|
154
|
+
static VALUE
|
155
|
+
overflow_cmp(VALUE self, VALUE other)
|
156
|
+
{
|
157
|
+
VALUE i;
|
158
|
+
|
159
|
+
if (self == other) return 0;
|
160
|
+
|
161
|
+
i = overflow_to_i(self);
|
162
|
+
if (i == other) return INT2FIX(0);
|
163
|
+
|
164
|
+
if (FIXNUM_P(i)) {
|
165
|
+
if (FIXNUM_P(other)) {
|
166
|
+
if (FIX2LONG(i) < FIX2LONG(other)) {
|
167
|
+
return INT2FIX(-1);
|
168
|
+
} else {
|
169
|
+
return INT2FIX(1);
|
170
|
+
}
|
171
|
+
} else if (RB_TYPE_P(other, T_BIGNUM)) {
|
172
|
+
return rb_big_cmp(rb_int2big(FIX2LONG(i)), other);
|
173
|
+
}
|
174
|
+
} else if (RB_TYPE_P(i, T_BIGNUM)) {
|
175
|
+
return rb_big_cmp(i, other);
|
176
|
+
}
|
177
|
+
return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
|
178
|
+
}
|
179
|
+
|
180
|
+
static VALUE
|
181
|
+
overflow_hash(VALUE self)
|
182
|
+
{
|
183
|
+
st_index_t h[2];
|
184
|
+
overflow_t *ptr;
|
185
|
+
Data_Get_Struct(self, overflow_t, ptr);
|
186
|
+
h[0] = NUM2LONG(rb_hash(INT2FIX(ptr->type)));
|
187
|
+
h[1] = NUM2LONG(rb_hash(overflow_to_i(self)));
|
188
|
+
return LONG2FIX(rb_memhash(h, sizeof(h)));
|
189
|
+
}
|
190
|
+
|
191
|
+
static VALUE
|
192
|
+
overflow_eql(VALUE self, VALUE other)
|
193
|
+
{
|
194
|
+
overflow_t *ptr_self;
|
195
|
+
overflow_t *ptr_other;
|
196
|
+
|
197
|
+
if (TYPE(other) != T_DATA) {
|
198
|
+
return Qfalse;
|
199
|
+
}
|
200
|
+
Data_Get_Struct(self, overflow_t, ptr_self);
|
201
|
+
Data_Get_Struct(other, overflow_t, ptr_other);
|
202
|
+
if (ptr_self->type != ptr_other->type) {
|
203
|
+
return Qfalse;
|
204
|
+
}
|
205
|
+
if (ptr_self->value != ptr_other->value) {
|
206
|
+
return Qfalse;
|
207
|
+
}
|
208
|
+
return Qtrue;
|
209
|
+
}
|
210
|
+
|
211
|
+
static VALUE
|
212
|
+
overflow_to_f(VALUE self)
|
213
|
+
{
|
214
|
+
return DBL2NUM((double)FIX2LONG(overflow_to_i(self)));
|
215
|
+
}
|
216
|
+
|
217
|
+
static VALUE
|
218
|
+
overflow_modulo(VALUE self, VALUE other)
|
219
|
+
{
|
220
|
+
return rb_funcall(overflow_to_i(self), '-', 1,
|
221
|
+
rb_funcall(other, '*', 1,
|
222
|
+
rb_funcall(overflow_to_i(self), rb_intern("div"), 1, other)));
|
223
|
+
}
|
224
|
+
|
225
|
+
static VALUE
|
226
|
+
overflow_int_p(VALUE self)
|
227
|
+
{
|
228
|
+
return Qtrue;
|
229
|
+
}
|
230
|
+
|
231
|
+
static VALUE
|
232
|
+
overflow_set(VALUE self, VALUE obj)
|
233
|
+
{
|
234
|
+
VALUE other;
|
235
|
+
overflow_t *ptr;
|
236
|
+
Data_Get_Struct(self, overflow_t, ptr);
|
237
|
+
|
238
|
+
switch (rb_type(obj)) {
|
239
|
+
case T_FIXNUM:
|
240
|
+
OVERFLOW_TYPES_ALL_CASE(ptr, NUM2LL(obj));
|
241
|
+
break;
|
242
|
+
case T_BIGNUM:
|
243
|
+
if (RBIGNUM_POSITIVE_P(obj)) {
|
244
|
+
other = rb_funcall(obj, rb_intern("&"), 1, ULL2NUM(0xffffffffffffffffLL));
|
245
|
+
ptr->value = (uint64_t) NUM2ULL(other);
|
246
|
+
} else {
|
247
|
+
ptr->value = (int64_t) NUM2LL(obj);
|
248
|
+
}
|
249
|
+
break;
|
250
|
+
}
|
251
|
+
return self;
|
252
|
+
}
|
253
|
+
|
254
|
+
static inline VALUE
|
255
|
+
pre_arithmetic(VALUE num)
|
256
|
+
{
|
257
|
+
switch (rb_type(num)) {
|
258
|
+
case T_FIXNUM:
|
259
|
+
return num;
|
260
|
+
case T_BIGNUM:
|
261
|
+
return rb_funcall(num, rb_intern("&"), 1, ULL2NUM(0xffffffffffffffffLL));
|
262
|
+
case T_DATA: // self
|
263
|
+
return overflow_to_i(num);
|
264
|
+
}
|
265
|
+
rb_raise(rb_eArgError, "cannot arithmetic");
|
266
|
+
return Qnil;
|
267
|
+
}
|
268
|
+
|
269
|
+
static inline VALUE
|
270
|
+
overflow_arithmetic(VALUE self, char method, VALUE other)
|
271
|
+
{
|
272
|
+
uint64_t b;
|
273
|
+
overflow_t *ptr;
|
274
|
+
VALUE clone = rb_obj_clone(self);
|
275
|
+
|
276
|
+
Data_Get_Struct(clone, overflow_t, ptr);
|
277
|
+
|
278
|
+
b = NUM2ULL(pre_arithmetic(other));
|
279
|
+
|
280
|
+
switch (method) {
|
281
|
+
case '+':
|
282
|
+
SWITCH_MACRO(ptr->type, TYPE_PLUS, ptr->value, b);
|
283
|
+
break;
|
284
|
+
case '-':
|
285
|
+
SWITCH_MACRO(ptr->type, TYPE_MINUS, ptr->value, b);
|
286
|
+
break;
|
287
|
+
case '*':
|
288
|
+
SWITCH_MACRO(ptr->type, TYPE_MUL, ptr->value, b);
|
289
|
+
break;
|
290
|
+
case '/':
|
291
|
+
SWITCH_MACRO(ptr->type, TYPE_DIV, ptr->value, b);
|
292
|
+
break;
|
293
|
+
}
|
294
|
+
return clone;
|
295
|
+
}
|
296
|
+
|
297
|
+
static VALUE
|
298
|
+
overflow_plus(VALUE self, VALUE num)
|
299
|
+
{
|
300
|
+
return overflow_arithmetic(self, '+', num);
|
301
|
+
}
|
302
|
+
|
303
|
+
static VALUE
|
304
|
+
overflow_minus(VALUE self, VALUE num)
|
305
|
+
{
|
306
|
+
return overflow_arithmetic(self, '-', num);
|
307
|
+
}
|
308
|
+
|
309
|
+
static VALUE
|
310
|
+
overflow_mul(VALUE self, VALUE num)
|
311
|
+
{
|
312
|
+
return overflow_arithmetic(self, '*', num);
|
313
|
+
}
|
314
|
+
|
315
|
+
static VALUE
|
316
|
+
overflow_div(VALUE self, VALUE num)
|
317
|
+
{
|
318
|
+
return overflow_arithmetic(self, '/', num);
|
319
|
+
}
|
320
|
+
|
321
|
+
static VALUE
|
322
|
+
overflow_rev(VALUE self)
|
323
|
+
{
|
324
|
+
VALUE clone = rb_obj_clone(self);
|
325
|
+
overflow_t *ptr;
|
326
|
+
Data_Get_Struct(clone, overflow_t, ptr);
|
327
|
+
|
328
|
+
ptr->value = ~ptr->value;
|
329
|
+
return clone;
|
330
|
+
}
|
331
|
+
|
332
|
+
static VALUE
|
333
|
+
overflow_and(VALUE self, VALUE num)
|
334
|
+
{
|
335
|
+
VALUE clone = rb_obj_clone(self);
|
336
|
+
overflow_t *ptr;
|
337
|
+
Data_Get_Struct(clone, overflow_t, ptr);
|
338
|
+
|
339
|
+
ptr->value = ptr->value & NUM2ULL(pre_arithmetic(num));
|
340
|
+
return clone;
|
341
|
+
}
|
342
|
+
|
343
|
+
static VALUE
|
344
|
+
overflow_or(VALUE self, VALUE num)
|
345
|
+
{
|
346
|
+
VALUE clone = rb_obj_clone(self);
|
347
|
+
overflow_t *ptr;
|
348
|
+
Data_Get_Struct(clone, overflow_t, ptr);
|
349
|
+
|
350
|
+
ptr->value = ptr->value | NUM2ULL(pre_arithmetic(num));
|
351
|
+
return clone;
|
352
|
+
}
|
353
|
+
|
354
|
+
static VALUE
|
355
|
+
overflow_xor(VALUE self, VALUE num)
|
356
|
+
{
|
357
|
+
VALUE clone = rb_obj_clone(self);
|
358
|
+
overflow_t *ptr;
|
359
|
+
Data_Get_Struct(clone, overflow_t, ptr);
|
360
|
+
|
361
|
+
ptr->value = ptr->value ^ NUM2ULL(pre_arithmetic(num));
|
362
|
+
return clone;
|
363
|
+
}
|
364
|
+
|
365
|
+
static void
|
366
|
+
lshift(overflow_t *ptr, long width)
|
367
|
+
{
|
368
|
+
OVERFLOW_TYPES_ALL_CASE(ptr, (ptr->value << width));
|
369
|
+
}
|
370
|
+
|
371
|
+
static void
|
372
|
+
rshift(overflow_t *ptr, long width)
|
373
|
+
{
|
374
|
+
OVERFLOW_TYPES_ALL_CASE(ptr, (ptr->value >> width));
|
375
|
+
}
|
376
|
+
|
377
|
+
static VALUE
|
378
|
+
overflow_lshift(VALUE self, VALUE obj)
|
379
|
+
{
|
380
|
+
VALUE clone = rb_obj_clone(self);
|
381
|
+
long width;
|
382
|
+
overflow_t *ptr;
|
383
|
+
Data_Get_Struct(clone, overflow_t, ptr);
|
384
|
+
|
385
|
+
if (!FIXNUM_P(obj))
|
386
|
+
rb_raise(rb_eArgError, "too big shift not support");
|
387
|
+
|
388
|
+
width = FIX2LONG(obj);
|
389
|
+
|
390
|
+
if (width < 0) {
|
391
|
+
rshift(ptr, -width);
|
392
|
+
} else {
|
393
|
+
lshift(ptr, width);
|
394
|
+
}
|
395
|
+
return clone;
|
396
|
+
}
|
397
|
+
|
398
|
+
static VALUE
|
399
|
+
overflow_rshift(VALUE self, VALUE obj)
|
400
|
+
{
|
401
|
+
VALUE clone = rb_obj_clone(self);
|
402
|
+
long width;
|
403
|
+
overflow_t *ptr;
|
404
|
+
Data_Get_Struct(clone, overflow_t, ptr);
|
405
|
+
|
406
|
+
if (!FIXNUM_P(obj))
|
407
|
+
rb_raise(rb_eArgError, "too big shift not support");
|
408
|
+
|
409
|
+
width = FIX2LONG(obj);
|
410
|
+
|
411
|
+
if (width < 0) {
|
412
|
+
lshift(ptr, -width);
|
413
|
+
} else {
|
414
|
+
rshift(ptr, width);
|
415
|
+
}
|
416
|
+
return clone;
|
417
|
+
}
|
418
|
+
|
419
|
+
void
|
420
|
+
Init_overflow(void)
|
421
|
+
{
|
422
|
+
VALUE cOverflow;
|
423
|
+
|
424
|
+
cOverflow = rb_define_class("Overflow", rb_cNumeric);
|
425
|
+
rb_define_const(cOverflow, "VERSION", rb_str_new2("0.0.1"));
|
426
|
+
rb_define_alloc_func(cOverflow, overflow_alloc);
|
427
|
+
rb_define_method(cOverflow, "initialize", overflow_initialize, -1);
|
428
|
+
rb_define_method(cOverflow, "initialize_copy", overflow_initialize_copy, 1);
|
429
|
+
|
430
|
+
/* override on Numeric */
|
431
|
+
rb_define_method(cOverflow, "coerce", overflow_coerce, 1);
|
432
|
+
rb_define_method(cOverflow, "<=>", overflow_cmp, 1);
|
433
|
+
rb_define_method(cOverflow, "hash", overflow_hash, 0);
|
434
|
+
rb_define_method(cOverflow, "eql?", overflow_eql, 1);
|
435
|
+
rb_define_method(cOverflow, "to_f", overflow_to_f, 0);
|
436
|
+
rb_define_method(cOverflow, "%", overflow_modulo, 1);
|
437
|
+
rb_define_method(cOverflow, "modulo", overflow_modulo, 1);
|
438
|
+
rb_define_method(cOverflow, "integer?", overflow_int_p, 0);
|
439
|
+
|
440
|
+
rb_define_method(cOverflow, "set", overflow_set, 1);
|
441
|
+
rb_define_method(cOverflow, "to_i", overflow_to_i, 0);
|
442
|
+
|
443
|
+
rb_define_method(cOverflow, "+", overflow_plus, 1);
|
444
|
+
rb_define_method(cOverflow, "-", overflow_minus, 1);
|
445
|
+
rb_define_method(cOverflow, "*", overflow_mul, 1);
|
446
|
+
rb_define_method(cOverflow, "/", overflow_div, 1);
|
447
|
+
|
448
|
+
rb_define_method(cOverflow, "~", overflow_rev, 0);
|
449
|
+
rb_define_method(cOverflow, "&", overflow_and, 1);
|
450
|
+
rb_define_method(cOverflow, "|", overflow_or, 1);
|
451
|
+
rb_define_method(cOverflow, "^", overflow_xor, 1);
|
452
|
+
|
453
|
+
rb_define_method(cOverflow, "<<", overflow_lshift, 1);
|
454
|
+
rb_define_method(cOverflow, ">>", overflow_rshift, 1);
|
455
|
+
}
|