rmtools 1.0.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.
- data/History.txt +4 -0
- data/License.txt +15 -0
- data/Manifest.txt +37 -0
- data/README.txt +10 -0
- data/Rakefile +39 -0
- data/ext/extconf.rb +12 -0
- data/ext/rmtools.cpp +529 -0
- data/ext/rmtools.h +161 -0
- data/lib/rmtools.rb +53 -0
- data/lib/rmtools/arguments.rb +24 -0
- data/lib/rmtools/array.rb +189 -0
- data/lib/rmtools/binding.rb +23 -0
- data/lib/rmtools/boolean.rb +57 -0
- data/lib/rmtools/coloring.rb +82 -0
- data/lib/rmtools/cyr-time.rb +49 -0
- data/lib/rmtools/cyrilic.rb +124 -0
- data/lib/rmtools/dumps.rb +192 -0
- data/lib/rmtools/enum.rb +90 -0
- data/lib/rmtools/hash.rb +40 -0
- data/lib/rmtools/io.rb +303 -0
- data/lib/rmtools/js.rb +25 -0
- data/lib/rmtools/limited_string.rb +17 -0
- data/lib/rmtools/logging.rb +158 -0
- data/lib/rmtools/module.rb +113 -0
- data/lib/rmtools/numeric.rb +82 -0
- data/lib/rmtools/object.rb +74 -0
- data/lib/rmtools/printing.rb +41 -0
- data/lib/rmtools/proc.rb +25 -0
- data/lib/rmtools/random.rb +195 -0
- data/lib/rmtools/range.rb +100 -0
- data/lib/rmtools/setup.rb +21 -0
- data/lib/rmtools/string.rb +276 -0
- data/lib/rmtools/string_to_proc.rb +113 -0
- data/lib/rmtools/stringscanner.rb +58 -0
- data/lib/rmtools/time.rb +32 -0
- data/lib/rmtools/traceback.rb +106 -0
- data/lib/rmtools/tree.rb +71 -0
- metadata +191 -0
data/History.txt
ADDED
data/License.txt
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Copyright (c) 2010 Anonymous <tinbka@gmail.com>
|
2
|
+
|
3
|
+
This work is licensed under the same license as Ruby language.
|
4
|
+
|
5
|
+
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
6
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
7
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
8
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
9
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
10
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
11
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
12
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
13
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
14
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
15
|
+
SUCH DAMAGE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
ext/extconf.rb
|
2
|
+
ext/rmtools.h
|
3
|
+
ext/rmtools.cpp
|
4
|
+
lib/rmtools.rb
|
5
|
+
lib/rmtools/arguments.rb
|
6
|
+
lib/rmtools/numeric.rb
|
7
|
+
lib/rmtools/string.rb
|
8
|
+
lib/rmtools/io.rb
|
9
|
+
lib/rmtools/js.rb
|
10
|
+
lib/rmtools/cyrilic.rb
|
11
|
+
lib/rmtools/coloring.rb
|
12
|
+
lib/rmtools/stringscanner.rb
|
13
|
+
lib/rmtools/enum.rb
|
14
|
+
lib/rmtools/string_to_proc.rb
|
15
|
+
lib/rmtools/traceback.rb
|
16
|
+
lib/rmtools/time.rb
|
17
|
+
lib/rmtools/random.rb
|
18
|
+
lib/rmtools/binding.rb
|
19
|
+
lib/rmtools/printing.rb
|
20
|
+
lib/rmtools/range.rb
|
21
|
+
lib/rmtools/tree.rb
|
22
|
+
lib/rmtools/boolean.rb
|
23
|
+
lib/rmtools/hash.rb
|
24
|
+
lib/rmtools/logging.rb
|
25
|
+
lib/rmtools/limited_string.rb
|
26
|
+
lib/rmtools/module.rb
|
27
|
+
lib/rmtools/object.rb
|
28
|
+
lib/rmtools/array.rb
|
29
|
+
lib/rmtools/setup.rb
|
30
|
+
lib/rmtools/cyr-time.rb
|
31
|
+
lib/rmtools/dumps.rb
|
32
|
+
lib/rmtools/proc.rb
|
33
|
+
./Rakefile
|
34
|
+
./Manifest.txt
|
35
|
+
./License.txt
|
36
|
+
./README.txt
|
37
|
+
./History.txt
|
data/README.txt
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require './lib/rmtools/setup'
|
3
|
+
compile_manifest
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'hoe'
|
7
|
+
config = Hoe.new('rmtools', '1.0.0') do |h|
|
8
|
+
h.developer("Shinku Templar", "tinbka@gmail.com")
|
9
|
+
|
10
|
+
h.summary = 'Yet another Ruby applied framework'
|
11
|
+
h.description = h.paragraphs_of('README.txt', 2..3).join("\n\n")
|
12
|
+
h.changes = h.paragraphs_of('History.txt', 0..1).join("\n\n")
|
13
|
+
h.url = 'http://github.com/tinbka'
|
14
|
+
|
15
|
+
h.extra_deps << ['rake','>= 0.8.7']
|
16
|
+
h.extra_deps << ['activesupport','>= 2.3.5']
|
17
|
+
end
|
18
|
+
config.spec.extensions << 'ext/extconf.rb'
|
19
|
+
rescue LoadError
|
20
|
+
STDERR.puts "cannot load the Hoe gem. Distribution is disabled"
|
21
|
+
rescue Exception => e
|
22
|
+
STDERR.puts "cannot load the Hoe gem, or Hoe fails. Distribution is disabled"
|
23
|
+
STDERR.puts "error message is: #{e.message}"
|
24
|
+
end
|
25
|
+
|
26
|
+
ruby = RbConfig::CONFIG['RUBY_INSTALL_NAME']
|
27
|
+
windoze = PLATFORM =~ /mswin32/
|
28
|
+
make = windoze ? 'nmake' : 'make'
|
29
|
+
|
30
|
+
Dir.chdir "ext" do
|
31
|
+
unless system "#{ruby} extconf.rb #{ENV['EXTCONF_OPTS']}" and system make
|
32
|
+
# don't we have a compiler?
|
33
|
+
warn "failed to compile extension, continuing installation without extension"
|
34
|
+
end
|
35
|
+
if File.file? 'Makefile'
|
36
|
+
system "#{make} clean" and FileUtils.rm_f "Makefile"
|
37
|
+
end
|
38
|
+
end unless ext_files_not_modified
|
39
|
+
|
data/ext/extconf.rb
ADDED
data/ext/rmtools.cpp
ADDED
@@ -0,0 +1,529 @@
|
|
1
|
+
#include "rmtools.h"
|
2
|
+
|
3
|
+
using namespace std;
|
4
|
+
|
5
|
+
/*
|
6
|
+
* Assign new value by variable or constant address. Can't process numeric, nil, false and true. Though, it can process containers with all of that shit.
|
7
|
+
* a = 'Object.new'
|
8
|
+
* => "Object.new"
|
9
|
+
* def inspire x
|
10
|
+
* x.define! eval x
|
11
|
+
* end
|
12
|
+
* => nil
|
13
|
+
* inspire a
|
14
|
+
* => #<Object:0xb790bed0>
|
15
|
+
* a
|
16
|
+
* => #<Object:0xb790bed0>
|
17
|
+
* It's quite buggy, you can get sudden segfault sometime after using method ^_^'\
|
18
|
+
* Maybe it could mark used objects for GC not to collect
|
19
|
+
*/
|
20
|
+
static VALUE object_define_new_value(VALUE self, VALUE new_obj)
|
21
|
+
{
|
22
|
+
if (FIXNUM_P(self) || self == Qnil || self == Qfalse || self == Qtrue || self == Qundef) {
|
23
|
+
const char* msg = STR2CSTR(rb_mod_name(rb_obj_class(self)));
|
24
|
+
rb_raise(rb_eTypeError, "can't redefine %s", msg);
|
25
|
+
}
|
26
|
+
if (FIXNUM_P(new_obj) || new_obj == Qnil || new_obj == Qfalse || new_obj == Qtrue || new_obj == Qundef) {
|
27
|
+
const char* msg = STR2CSTR(rb_mod_name(rb_obj_class(new_obj)));
|
28
|
+
rb_raise(rb_eTypeError, "can't define object as %s", msg);
|
29
|
+
}
|
30
|
+
// Place the definition of the new object in the slot of self
|
31
|
+
memcpy(reinterpret_cast<void*>(self), reinterpret_cast<void*>(new_obj), SLOT_SIZE);
|
32
|
+
return self;
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
/*
|
37
|
+
* puts ['123', '456', '789'].stranspose
|
38
|
+
* 147
|
39
|
+
* 258
|
40
|
+
* 369
|
41
|
+
*/
|
42
|
+
static VALUE rb_ary_string_transpose(VALUE ary)
|
43
|
+
{
|
44
|
+
long elen = -1, alen, i, j;
|
45
|
+
VALUE tmp, result = 0;
|
46
|
+
|
47
|
+
alen = RARRAY_LEN(ary);
|
48
|
+
if (alen == 0) return rb_ary_dup(ary);
|
49
|
+
for (i=0; i<alen; i++) {
|
50
|
+
tmp = RARRAY_PTR(ary)[i];
|
51
|
+
if (elen < 0) { /* first element */
|
52
|
+
elen = RSTRING_LEN(tmp);
|
53
|
+
result = rb_ary_new2(elen);
|
54
|
+
for (j=0; j<elen; j++) rb_ary_store(result, j, rb_str_new("", 0));
|
55
|
+
}
|
56
|
+
else if (elen != RSTRING_LEN(tmp))
|
57
|
+
rb_raise(rb_eIndexError, "element size differs (%d should be %d)",
|
58
|
+
RARRAY_LEN(tmp), elen);
|
59
|
+
for (j=0; j<elen; j++) rb_str_buf_cat(RARRAY_PTR(result)[j], &(RSTRING_PTR(tmp)[j]), 1);
|
60
|
+
}
|
61
|
+
return result;
|
62
|
+
}
|
63
|
+
|
64
|
+
/*
|
65
|
+
* puts ['123', '456', '789'].turn_ccw
|
66
|
+
* 369
|
67
|
+
* 258
|
68
|
+
* 147
|
69
|
+
*/
|
70
|
+
static VALUE rb_ary_turn_ccw(VALUE ary)
|
71
|
+
{
|
72
|
+
long elen, alen, i, j;
|
73
|
+
VALUE tmp, result = 0;
|
74
|
+
alen = RARRAY_LEN(ary);
|
75
|
+
if (alen == 0) return rb_ary_dup(ary);
|
76
|
+
|
77
|
+
tmp = RARRAY_PTR(ary)[0];
|
78
|
+
if (TYPE(tmp) == T_STRING) {
|
79
|
+
elen = RSTRING_LEN(tmp);
|
80
|
+
result = rb_ary_new2(elen);
|
81
|
+
for (j=0; j<elen; j++) rb_ary_store(result, j, rb_str_new("", 0));
|
82
|
+
for (i=0; i<alen; i++) {
|
83
|
+
if (i) tmp = RARRAY_PTR(ary)[i];
|
84
|
+
if (elen != RSTRING_LEN(tmp))
|
85
|
+
rb_raise(rb_eIndexError, "element size differs (%d should be %d)",
|
86
|
+
RARRAY_LEN(tmp), elen);
|
87
|
+
for (j=0; j<elen; j++) rb_str_buf_cat(RARRAY_PTR(result)[j], &(RSTRING_PTR(tmp)[elen-1-j]), 1);
|
88
|
+
}
|
89
|
+
}
|
90
|
+
else {
|
91
|
+
elen = RARRAY_LEN(tmp);
|
92
|
+
for (j=0; j<elen; j++) rb_ary_store(result, j, rb_ary_new2(alen));
|
93
|
+
for (i=0; i<alen; i++) {
|
94
|
+
if (i) tmp = RARRAY_PTR(ary)[i];
|
95
|
+
if (elen != RARRAY_LEN(tmp))
|
96
|
+
rb_raise(rb_eIndexError, "element size differs (%d should be %d)",
|
97
|
+
RARRAY_LEN(tmp), elen);
|
98
|
+
for (j=0; j<elen; j++) rb_ary_store(RARRAY_PTR(result)[j], i, RARRAY_PTR(tmp)[elen-1-j]);
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
return result;
|
103
|
+
}
|
104
|
+
|
105
|
+
/*
|
106
|
+
* puts ['123', '456', '789'].turn_cw
|
107
|
+
* 147
|
108
|
+
* 258
|
109
|
+
* 369
|
110
|
+
*/
|
111
|
+
static VALUE rb_ary_turn_cw(VALUE ary)
|
112
|
+
{
|
113
|
+
long elen, alen, i, j;
|
114
|
+
VALUE tmp, result = 0;
|
115
|
+
alen = RARRAY_LEN(ary);
|
116
|
+
if (alen == 0) return rb_ary_dup(ary);
|
117
|
+
|
118
|
+
tmp = RARRAY_PTR(ary)[0];
|
119
|
+
if (TYPE(tmp) == T_STRING) {
|
120
|
+
elen = RSTRING_LEN(tmp);
|
121
|
+
result = rb_ary_new2(elen);
|
122
|
+
for (j=0; j<elen; j++) rb_ary_store(result, j, rb_str_new("", 0));
|
123
|
+
for (i=alen-1; i>-1; i--) {
|
124
|
+
tmp = RARRAY_PTR(ary)[i];
|
125
|
+
if (elen != RSTRING_LEN(tmp))
|
126
|
+
rb_raise(rb_eIndexError, "element size differs (%d should be %d)",
|
127
|
+
RARRAY_LEN(tmp), elen);
|
128
|
+
for (j=0; j<elen; j++) rb_str_buf_cat(RARRAY_PTR(result)[j], &(RSTRING_PTR(tmp)[j]), 1);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
else {
|
132
|
+
elen = RARRAY_LEN(tmp);
|
133
|
+
for (j=0; j<elen; j++) rb_ary_store(result, j, rb_ary_new2(alen));
|
134
|
+
for (i=0; i<alen; i++) {
|
135
|
+
if (i) tmp = RARRAY_PTR(ary)[i];
|
136
|
+
if (elen != RARRAY_LEN(tmp))
|
137
|
+
rb_raise(rb_eIndexError, "element size differs (%d should be %d)",
|
138
|
+
RARRAY_LEN(tmp), elen);
|
139
|
+
for (j=0; j<elen; j++) rb_ary_store(RARRAY_PTR(result)[j], elen-1-i, RARRAY_PTR(tmp)[j]);
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
return result;
|
144
|
+
}
|
145
|
+
|
146
|
+
/*
|
147
|
+
* " @@@@@@".conj " @@@ @@@"
|
148
|
+
* => " @@@"
|
149
|
+
*/
|
150
|
+
static VALUE rb_str_disjunction(VALUE self, VALUE str)
|
151
|
+
{
|
152
|
+
if (RSTRING_LEN(self) != RSTRING_LEN(str))
|
153
|
+
rb_raise(rb_eIndexError, "strings sizes differs (%d and %d)",
|
154
|
+
RSTRING_LEN(self), RSTRING_LEN(str));
|
155
|
+
VALUE new_str = rb_str_new("", 0);
|
156
|
+
int i;
|
157
|
+
const char *selfptr = RSTRING_PTR(self), *strptr = RSTRING_PTR(str);
|
158
|
+
for (i=0;i<RSTRING_LEN(str);i++) {
|
159
|
+
if (strptr[i] != ' ' || selfptr[i] != ' ')
|
160
|
+
rb_str_buf_cat(new_str, "@", 1);
|
161
|
+
else
|
162
|
+
rb_str_buf_cat(new_str, " ", 1);
|
163
|
+
}
|
164
|
+
return new_str;
|
165
|
+
}
|
166
|
+
|
167
|
+
/*
|
168
|
+
* " @@@@@@".disj " @@@ @@@"
|
169
|
+
* => " @@@@@@@@@"
|
170
|
+
*/
|
171
|
+
static VALUE rb_str_conjunction(VALUE self, VALUE str)
|
172
|
+
{
|
173
|
+
if (RSTRING_LEN(self) != RSTRING_LEN(str))
|
174
|
+
rb_raise(rb_eIndexError, "strings sizes differs (%d and %d)",
|
175
|
+
RSTRING_LEN(self), RSTRING_LEN(str));
|
176
|
+
VALUE new_str = rb_str_new("", 0);
|
177
|
+
int i;
|
178
|
+
const char *selfptr = RSTRING_PTR(self), *strptr = RSTRING_PTR(str);
|
179
|
+
for (i=0;i<RSTRING_LEN(str);i++) {
|
180
|
+
if (strptr[i] == '@' && selfptr[i] == '@')
|
181
|
+
rb_str_buf_cat(new_str, "@", 1);
|
182
|
+
else
|
183
|
+
rb_str_buf_cat(new_str, " ", 1);
|
184
|
+
}
|
185
|
+
return new_str;
|
186
|
+
}
|
187
|
+
|
188
|
+
/*
|
189
|
+
* Modifies array, throwing all elements not having unique block result
|
190
|
+
* a = randarr 10
|
191
|
+
* => [8, 2, 0, 5, 4, 1, 7, 3, 9, 6]
|
192
|
+
* a.uniq_by! {|e| e%2}
|
193
|
+
* => [8, 5]
|
194
|
+
* a
|
195
|
+
* => [8, 5]
|
196
|
+
*/
|
197
|
+
static VALUE rb_ary_uniq_by_bang(VALUE ary)
|
198
|
+
{
|
199
|
+
if (!rb_block_given_p())
|
200
|
+
return rb_ary_new4(RARRAY_LEN(ary), RARRAY_PTR(ary));
|
201
|
+
VALUE hash, res;
|
202
|
+
long i, j;
|
203
|
+
|
204
|
+
hash = rb_hash_new();
|
205
|
+
for (i=j=0; i<RARRAY_LEN(ary); i++) {
|
206
|
+
res = rb_yield(RARRAY_PTR(ary)[i]);
|
207
|
+
if (!st_lookup(RHASH_TBL(hash), res, 0)) {
|
208
|
+
rb_ary_store(ary, j++, RARRAY_PTR(ary)[i]);
|
209
|
+
rb_hash_aset(hash, res, RARRAY_PTR(ary)[i]);
|
210
|
+
}
|
211
|
+
}
|
212
|
+
ARY_SET_LEN(ary, j);
|
213
|
+
|
214
|
+
return ary;
|
215
|
+
}
|
216
|
+
|
217
|
+
/*
|
218
|
+
* Safe version of uniq_by!
|
219
|
+
*/
|
220
|
+
static VALUE rb_ary_uniq_by(VALUE ary)
|
221
|
+
{
|
222
|
+
return rb_ary_uniq_by_bang(rb_ary_dup(ary));
|
223
|
+
}
|
224
|
+
|
225
|
+
/*
|
226
|
+
* Make hash with unique items of +self+ or (when block given)
|
227
|
+
* unique results of items yield for keys and
|
228
|
+
* count of them in +self, or (with option :fill) arrays of themselves,
|
229
|
+
* or (with option :indexes) arrays of indexes of them for values
|
230
|
+
*
|
231
|
+
* [1, 2, 2, 3, 3, 3].count
|
232
|
+
* => {1=>1, 2=>2, 3=>3}
|
233
|
+
* [1, 2, 2, 3, 3, 3].count :fill
|
234
|
+
* => {1=>[1], 2=>[2, 2], 3=>[3, 3, 3]}
|
235
|
+
* [1, 2, 2, 3, 3, 3].count :indexes
|
236
|
+
* => {1=>[0], 2=>[1, 2], 3=>[3, 4, 5]}
|
237
|
+
* [1, 2, 2, 3, 3, 3].count(:indexes) {|i| i%2}
|
238
|
+
* => {0=>[1, 2], 1=>[0, 3, 4, 5]}
|
239
|
+
* [1, 2, 2, 3, 3, 3].count {|i| i%2}
|
240
|
+
* => {0=>2, 1=>4}
|
241
|
+
*/
|
242
|
+
static VALUE rb_ary_count_items(int argc, VALUE *argv, VALUE ary)
|
243
|
+
{
|
244
|
+
long i, alen, block_given;
|
245
|
+
int fill, ind, group;
|
246
|
+
VALUE key, arg, storage;
|
247
|
+
VALUE hash = rb_hash_new();
|
248
|
+
VALUE val = Qnil;
|
249
|
+
|
250
|
+
block_given = rb_block_given_p();
|
251
|
+
rb_scan_args(argc, argv, "01", &arg);
|
252
|
+
ind = arg == ID2SYM(rb_intern("indexes"));
|
253
|
+
group = arg == ID2SYM(rb_intern("group"));
|
254
|
+
fill = ind || group || arg == ID2SYM(rb_intern("fill"));
|
255
|
+
|
256
|
+
alen = RARRAY_LEN(ary);
|
257
|
+
for (i=0; i<RARRAY_LEN(ary); i++) {
|
258
|
+
key = block_given ? rb_yield(RARRAY_PTR(ary)[i]) : RARRAY_PTR(ary)[i];
|
259
|
+
if (fill)
|
260
|
+
{
|
261
|
+
if (st_lookup(RHASH_TBL(hash), key, 0))
|
262
|
+
storage = rb_hash_aref(hash, key);
|
263
|
+
else {
|
264
|
+
storage = rb_ary_new2(alen);
|
265
|
+
rb_hash_aset(hash, key, storage);
|
266
|
+
}
|
267
|
+
rb_ary_push(storage, ind ? LONG2FIX(i) : group ? RARRAY_PTR(ary)[i] : key);
|
268
|
+
}
|
269
|
+
else {
|
270
|
+
if (st_lookup(RHASH_TBL(hash), key, &val))
|
271
|
+
rb_hash_aset(hash, key, LONG2FIX(FIX2LONG(val) + 1));
|
272
|
+
else
|
273
|
+
rb_hash_aset(hash, key, INT2FIX(1));
|
274
|
+
}
|
275
|
+
}
|
276
|
+
return hash;
|
277
|
+
}
|
278
|
+
|
279
|
+
static VALUE rb_ary_partition(VALUE ary)
|
280
|
+
{
|
281
|
+
VALUE select, reject;
|
282
|
+
long i, len;
|
283
|
+
|
284
|
+
RETURN_ENUMERATOR(ary, 0, 0);
|
285
|
+
len = RARRAY_LEN(ary);
|
286
|
+
select = rb_ary_new2(len);
|
287
|
+
reject = rb_ary_new2(len);
|
288
|
+
for (i = 0; i < len; i++)
|
289
|
+
rb_ary_push((RTEST(rb_yield(RARRAY_PTR(ary)[i])) ? select : reject), RARRAY_PTR(ary)[i]);
|
290
|
+
|
291
|
+
return rb_assoc_new(select, reject);
|
292
|
+
}
|
293
|
+
|
294
|
+
// HASH
|
295
|
+
|
296
|
+
static int replace_keys_i(VALUE key, VALUE value, VALUE hash)
|
297
|
+
{
|
298
|
+
if (key == Qundef) return ST_CONTINUE;
|
299
|
+
rb_hash_delete(hash, key);
|
300
|
+
rb_hash_aset(hash, rb_yield(key), value);
|
301
|
+
return ST_CONTINUE;
|
302
|
+
}
|
303
|
+
static int map_keys_i(VALUE key, VALUE value, VALUE hash)
|
304
|
+
{
|
305
|
+
if (key == Qundef) return ST_CONTINUE;
|
306
|
+
rb_hash_aset(hash, rb_yield(key), value);
|
307
|
+
return ST_CONTINUE;
|
308
|
+
}
|
309
|
+
static int map_values_i(VALUE key, VALUE value, VALUE hash)
|
310
|
+
{
|
311
|
+
if (key == Qundef) return ST_CONTINUE;
|
312
|
+
rb_hash_aset(hash, key, rb_yield(value));
|
313
|
+
return ST_CONTINUE;
|
314
|
+
}
|
315
|
+
static int map_pairs_i(VALUE key, VALUE value, VALUE hash)
|
316
|
+
{
|
317
|
+
if (key == Qundef) return ST_CONTINUE;
|
318
|
+
rb_hash_aset(hash, key, rb_yield(rb_assoc_new(key, value)));
|
319
|
+
return ST_CONTINUE;
|
320
|
+
}
|
321
|
+
|
322
|
+
/*
|
323
|
+
* Hashes map methods that doesn't make hash into array
|
324
|
+
* New hash may get shorter than source
|
325
|
+
*/
|
326
|
+
static VALUE rb_hash_map_keys_bang(VALUE hash)
|
327
|
+
{
|
328
|
+
rb_hash_foreach(hash, (int (*)(ANYARGS))replace_keys_i, hash);
|
329
|
+
return hash;
|
330
|
+
}
|
331
|
+
|
332
|
+
/*
|
333
|
+
* Hashes map methods that doesn't make hash into array
|
334
|
+
*/
|
335
|
+
static VALUE rb_hash_map_values_bang(VALUE hash)
|
336
|
+
{
|
337
|
+
rb_hash_foreach(hash, (int (*)(ANYARGS))map_values_i, hash);
|
338
|
+
return hash;
|
339
|
+
}
|
340
|
+
|
341
|
+
/*
|
342
|
+
* Hashes map methods that doesn't make hash into array
|
343
|
+
*/
|
344
|
+
static VALUE rb_hash_map_pairs_bang(VALUE hash)
|
345
|
+
{
|
346
|
+
rb_hash_foreach(hash, (int (*)(ANYARGS))map_pairs_i, hash);
|
347
|
+
return hash;
|
348
|
+
}
|
349
|
+
|
350
|
+
/*
|
351
|
+
* Hashes map methods that doesn't make hash into array
|
352
|
+
*/
|
353
|
+
static VALUE rb_hash_map_values(VALUE hash)
|
354
|
+
{
|
355
|
+
VALUE new_hash = rb_hash_new();
|
356
|
+
rb_hash_foreach(hash, (int (*)(ANYARGS))map_values_i, new_hash);
|
357
|
+
return new_hash;
|
358
|
+
}
|
359
|
+
|
360
|
+
/*
|
361
|
+
* Hashes map methods that doesn't make hash into array
|
362
|
+
* New hash may get shorter than source
|
363
|
+
*/
|
364
|
+
static VALUE rb_hash_map_keys(VALUE hash)
|
365
|
+
{
|
366
|
+
VALUE new_hash = rb_hash_new();
|
367
|
+
rb_hash_foreach(hash, (int (*)(ANYARGS))map_keys_i, new_hash);
|
368
|
+
return new_hash;
|
369
|
+
}
|
370
|
+
|
371
|
+
/*
|
372
|
+
* Hashes map methods that doesn't make hash into array
|
373
|
+
*/
|
374
|
+
static VALUE rb_hash_map_pairs(VALUE hash)
|
375
|
+
{
|
376
|
+
VALUE new_hash = rb_hash_new();
|
377
|
+
rb_hash_foreach(hash, (int (*)(ANYARGS))map_pairs_i, new_hash);
|
378
|
+
return new_hash;
|
379
|
+
}
|
380
|
+
|
381
|
+
/*
|
382
|
+
* x! ( specially for /c/ ^__^ )
|
383
|
+
* 5.fact # => 120
|
384
|
+
* x3 boost relative to 1.8.7
|
385
|
+
*/
|
386
|
+
static VALUE rb_math_factorial(VALUE x)
|
387
|
+
{
|
388
|
+
if (FIX2LONG(x) < 2) return x;
|
389
|
+
return rb_big_mul(x, rb_math_factorial(LONG2FIX(FIX2LONG(x) - 1)));
|
390
|
+
}
|
391
|
+
|
392
|
+
|
393
|
+
|
394
|
+
static int unsigned_big_lte(VALUE x, VALUE y)
|
395
|
+
{
|
396
|
+
long xlen = RBIGNUM_LEN(x);
|
397
|
+
long ylen = RBIGNUM_LEN(y);
|
398
|
+
if (xlen < ylen) return 1;
|
399
|
+
if (xlen > RBIGNUM_LEN(y)) return 0;
|
400
|
+
while(xlen-- && (BDIGITS(x)[xlen]==BDIGITS(y)[xlen]));
|
401
|
+
if (-1 == xlen) return 1; // ==
|
402
|
+
return (BDIGITS(x)[xlen] > BDIGITS(y)[xlen]) ? 0 : 1;
|
403
|
+
}
|
404
|
+
/*
|
405
|
+
* timer(100000) {1073741823.factorize}
|
406
|
+
* => "res: [3, 3, 7, 11, 31, 151, 331], one: 0.0053ms, total: 530.0ms"
|
407
|
+
* ruby count Bignums starting from 2**30
|
408
|
+
* < 2**30: x1-x30 speed, >= 2**30: x1 - x3 speed ~_~
|
409
|
+
* Caution! It can just hung up on numbers over 2**64 and you'll have to kill it -9
|
410
|
+
* And this shit doesn't think if you have 64-bit system, so it could be faster a bit
|
411
|
+
*/
|
412
|
+
static VALUE rb_math_factorization(VALUE x) {
|
413
|
+
VALUE factors = rb_ary_new2(31);
|
414
|
+
int len = 0;
|
415
|
+
long y = FIX2LONG(x);
|
416
|
+
long n = 2;
|
417
|
+
while (n*n <= y) {
|
418
|
+
if (y%n == 0) {
|
419
|
+
y /= n;
|
420
|
+
rb_ary_store(factors, len++, LONG2FIX(n));
|
421
|
+
} else
|
422
|
+
n++;
|
423
|
+
}
|
424
|
+
rb_ary_store(factors, len++, LONG2FIX(y));
|
425
|
+
ARY_SET_LEN(factors, len);
|
426
|
+
return factors;
|
427
|
+
}
|
428
|
+
/*
|
429
|
+
* timer(100000) {1073741823.factorize}
|
430
|
+
* => "res: [3, 3, 7, 11, 31, 151, 331], one: 0.0053ms, total: 530.0ms"
|
431
|
+
* ruby count Bignums starting from 2**30
|
432
|
+
* < 2**30: x1-x30 speed, >= 2**30: x1 - x3 speed ~_~
|
433
|
+
* Caution! It can just hung up on numbers over 2**64 and you'll have to kill it -9
|
434
|
+
* And this shit doesn't think if you have 64-bit system, so it could be faster a bit
|
435
|
+
*/
|
436
|
+
static VALUE rb_math_big_factorization(VALUE y) {
|
437
|
+
VALUE factors = rb_ary_new2(127);
|
438
|
+
int len = 0;
|
439
|
+
long n = 2;
|
440
|
+
int cont = 0;
|
441
|
+
VALUE big_n, divmod, mod;
|
442
|
+
while (unsigned_big_lte(rb_int2big(n*n), y)) {
|
443
|
+
divmod = rb_big_divmod(y, rb_int2big(n));
|
444
|
+
mod = RARRAY_PTR(divmod)[1];
|
445
|
+
|
446
|
+
if (FIXNUM_P(mod) && !FIX2LONG(mod)) {
|
447
|
+
y = RARRAY_PTR(divmod)[0];
|
448
|
+
if (FIXNUM_P(y)) y = rb_int2big(FIX2LONG(y));
|
449
|
+
rb_ary_store(factors, len++, LONG2FIX(n));
|
450
|
+
} else {
|
451
|
+
n++;
|
452
|
+
if (n == 46341) {
|
453
|
+
big_n = rb_int2big(n);
|
454
|
+
cont = 1;
|
455
|
+
break;
|
456
|
+
}
|
457
|
+
}
|
458
|
+
}
|
459
|
+
if (cont)
|
460
|
+
while (unsigned_big_lte(rb_big_mul(big_n, big_n), y)) {
|
461
|
+
divmod = rb_big_divmod(y, big_n);
|
462
|
+
mod = RARRAY_PTR(divmod)[1];
|
463
|
+
|
464
|
+
if (FIXNUM_P(mod) && !FIX2LONG(mod)) {
|
465
|
+
y = RARRAY_PTR(divmod)[0];
|
466
|
+
if (FIXNUM_P(y)) y = rb_int2big(FIX2LONG(y));
|
467
|
+
rb_ary_store(factors, len++, big_n);
|
468
|
+
} else {
|
469
|
+
big_n = (n < LONG_MAX) ? rb_int2big(++n) : rb_big_plus(big_n, rb_int2big(1));
|
470
|
+
}
|
471
|
+
}
|
472
|
+
rb_ary_store(factors, len++, y);
|
473
|
+
ARY_SET_LEN(factors, len);
|
474
|
+
return factors;
|
475
|
+
}
|
476
|
+
|
477
|
+
|
478
|
+
/*
|
479
|
+
static VALUE rb_eval_frame(VALUE self, VALUE src, VALUE levv)
|
480
|
+
{
|
481
|
+
struct FRAME *frame_orig = ruby_frame;
|
482
|
+
NODE *node_orig = ruby_current_node;
|
483
|
+
VALUE val;
|
484
|
+
int i = 0, lev = FIX2INT(levv);
|
485
|
+
|
486
|
+
while (lev-- > 0) {
|
487
|
+
ruby_frame = ruby_frame->prev;
|
488
|
+
if (!ruby_frame) break;
|
489
|
+
}
|
490
|
+
|
491
|
+
val = rb_funcall(self, rb_intern("eval"), 1, src);
|
492
|
+
ruby_current_node = node_orig;
|
493
|
+
ruby_frame = frame_orig;
|
494
|
+
|
495
|
+
return val;
|
496
|
+
}
|
497
|
+
*/
|
498
|
+
extern "C" void Init_rmtools()
|
499
|
+
{
|
500
|
+
// rb_define_method(rb_mKernel, "eval_frame", RUBY_METHOD_FUNC(rb_eval_frame), 2);
|
501
|
+
|
502
|
+
rb_define_method(rb_cFixnum, "fact", RUBY_METHOD_FUNC(rb_math_factorial), 0);
|
503
|
+
rb_define_method(rb_cFixnum, "factorize", RUBY_METHOD_FUNC(rb_math_factorization), 0);
|
504
|
+
rb_define_method(rb_cBignum, "factorize", RUBY_METHOD_FUNC(rb_math_big_factorization), 0);
|
505
|
+
|
506
|
+
rb_define_method(rb_cHash, "map_keys", RUBY_METHOD_FUNC(rb_hash_map_keys), 0);
|
507
|
+
rb_define_method(rb_cHash, "map_values", RUBY_METHOD_FUNC(rb_hash_map_values), 0);
|
508
|
+
rb_define_method(rb_cHash, "map2", RUBY_METHOD_FUNC(rb_hash_map_pairs), 0);
|
509
|
+
rb_define_method(rb_cHash, "map_keys!", RUBY_METHOD_FUNC(rb_hash_map_keys_bang), 0);
|
510
|
+
rb_define_method(rb_cHash, "map_values!", RUBY_METHOD_FUNC(rb_hash_map_values_bang), 0);
|
511
|
+
rb_define_method(rb_cHash, "map!", RUBY_METHOD_FUNC(rb_hash_map_pairs_bang), 0);
|
512
|
+
|
513
|
+
rb_define_method(rb_cArray, "uniq_by", RUBY_METHOD_FUNC(rb_ary_uniq_by), 0);
|
514
|
+
rb_define_method(rb_cArray, "uniq_by!", RUBY_METHOD_FUNC(rb_ary_uniq_by_bang), 0);
|
515
|
+
|
516
|
+
rb_define_method(rb_cArray, "count", RUBY_METHOD_FUNC(rb_ary_count_items), -1);
|
517
|
+
|
518
|
+
rb_define_method(rb_cArray, "partition", RUBY_METHOD_FUNC(rb_ary_partition), 0);
|
519
|
+
|
520
|
+
rb_define_method(rb_cArray, "stranspose", RUBY_METHOD_FUNC(rb_ary_string_transpose), 0);
|
521
|
+
rb_define_method(rb_cArray, "turn_cw", RUBY_METHOD_FUNC(rb_ary_turn_cw), 0);
|
522
|
+
rb_define_method(rb_cArray, "turn_ccw", RUBY_METHOD_FUNC(rb_ary_turn_ccw), 0);
|
523
|
+
|
524
|
+
rb_define_method(rb_cString, "conj", RUBY_METHOD_FUNC(rb_str_conjunction), 1);
|
525
|
+
rb_define_method(rb_cString, "disj", RUBY_METHOD_FUNC(rb_str_disjunction), 1);
|
526
|
+
|
527
|
+
rb_define_method(rb_cObject, "define!", RUBY_METHOD_FUNC(object_define_new_value), 1);
|
528
|
+
}
|
529
|
+
|