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 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
+