rmtools 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ === Version 1.0.0
2
+
3
+ * Divided by classes and packed as gem
4
+
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
@@ -0,0 +1,10 @@
1
+ Copyright (c) 2010
2
+ Anonymous <tinbka@gmail.com>
3
+
4
+ This work is licensed under the same license as Ruby language.
5
+
6
+ == RMTools
7
+ Methods for basic classes addon collection.
8
+
9
+ == CHANGES
10
+ :include: History.txt
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
@@ -0,0 +1,12 @@
1
+ require 'mkmf'
2
+
3
+ CONFIG['CC'] = "g++"
4
+ if RUBY_VERSION >= "1.9"
5
+ $CFLAGS += " -DRUBY_IS_19"
6
+ end
7
+
8
+ $LDFLAGS += "-module"
9
+
10
+ dir_config("ruby19")
11
+ create_makefile("rmtools")
12
+
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
+