gmp 0.5.47 → 0.6.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +13 -0
- data/README.markdown +10 -31
- data/benchmark/benchmark-results-5.0.5_1.9.3_0.6.7.ods +0 -0
- data/ext/gmp.c +36 -3
- data/ext/gmpbench_timing.c +9 -9
- data/ext/gmpf.c +83 -12
- data/ext/gmprandstate.c +14 -15
- data/ext/gmpz.c +145 -30
- data/ext/mprnd.c +7 -7
- data/ext/ruby_gmp.h +2 -2
- data/lib/gmp.rb +22 -1
- data/manual.pdf +0 -0
- data/manual.tex +4 -108
- data/performance.html +763 -0
- data/performance.md +321 -0
- data/performance.pdf +0 -0
- data/test/gmp_tlcm.rb +67 -0
- data/test/gmp_tprintf.rb +124 -0
- data/test/tc_division.rb +3 -3
- data/test/tc_f_arithmetics_coersion.rb +2 -2
- data/test/tc_f_to_s.rb +72 -0
- data/test/tc_mpfr_integer.rb +20 -0
- data/test/tc_mpfr_random.rb +61 -26
- data/test/test_helper.rb +1 -1
- data/test/unit_tests.rb +3 -0
- metadata +51 -57
- data/benchmark/COPYING +0 -674
- data/benchmark/README +0 -75
- data/benchmark/divide +0 -34
- data/benchmark/gcd +0 -38
- data/benchmark/gexpr.c +0 -359
- data/benchmark/multiply +0 -44
- data/benchmark/multiply.fnl +0 -47
- data/benchmark/multiply.gc +0 -57
- data/benchmark/pi +0 -126
- data/benchmark/rsa +0 -93
- data/benchmark/runbench +0 -147
- data/benchmark/srb.sh +0 -21
- data/benchmark/version +0 -1
data/ext/gmpz.c
CHANGED
@@ -605,6 +605,21 @@ VALUE r_gmpzsg_new(int argc, VALUE *argv, VALUE klass)
|
|
605
605
|
return res;
|
606
606
|
}
|
607
607
|
|
608
|
+
static VALUE r_gmpz_alloc(VALUE klass) {
|
609
|
+
MP_INT *z;
|
610
|
+
VALUE obj;
|
611
|
+
|
612
|
+
//mpz_init(z);
|
613
|
+
//obj = Data_Make_Struct(klass, MP_INT, 0, r_gmpz_free, z);
|
614
|
+
//obj = Data_Wrap_Struct(klass, 0, r_gmpz_free, z);
|
615
|
+
// mpz_make_struct_init (z, obj);
|
616
|
+
// mpz_make_struct_init (obj, z);
|
617
|
+
obj = Data_Make_Struct(klass, MP_INT, 0, r_gmpz_free, z);
|
618
|
+
mpz_init (z);
|
619
|
+
|
620
|
+
return obj;
|
621
|
+
}
|
622
|
+
|
608
623
|
VALUE r_gmpz_initialize(int argc, VALUE *argv, VALUE self)
|
609
624
|
{
|
610
625
|
MP_INT *self_val;
|
@@ -636,6 +651,22 @@ VALUE r_gmpz_initialize(int argc, VALUE *argv, VALUE self)
|
|
636
651
|
return Qnil;
|
637
652
|
}
|
638
653
|
|
654
|
+
static VALUE r_gmpz_initialize_copy(VALUE copy, VALUE orig) {
|
655
|
+
MP_INT *orig_z, *copy_z;
|
656
|
+
|
657
|
+
if (copy == orig) return copy;
|
658
|
+
|
659
|
+
if (TYPE(orig) != T_DATA) {
|
660
|
+
rb_raise(rb_eTypeError, "wrong argument type");
|
661
|
+
}
|
662
|
+
|
663
|
+
mpz_get_struct (orig, orig_z);
|
664
|
+
mpz_get_struct (copy, copy_z);
|
665
|
+
mpz_set (copy_z, orig_z);
|
666
|
+
|
667
|
+
return copy;
|
668
|
+
}
|
669
|
+
|
639
670
|
/*
|
640
671
|
* call-seq:
|
641
672
|
* a = b
|
@@ -1776,8 +1807,8 @@ VALUE r_gmpz_gcdext(VALUE self, VALUE arg)
|
|
1776
1807
|
mpz_make_struct_init (res, res_val);
|
1777
1808
|
mpz_make_struct_init (s, s_val);
|
1778
1809
|
mpz_make_struct_init (t, t_val);
|
1779
|
-
mpz_temp_alloc(arg_val);
|
1780
|
-
mpz_init_set_ui(arg_val, FIX2NUM(arg));
|
1810
|
+
mpz_temp_alloc (arg_val);
|
1811
|
+
mpz_init_set_ui (arg_val, FIX2NUM(arg));
|
1781
1812
|
free_arg_val = 1;
|
1782
1813
|
mpz_gcdext (res_val, s_val, t_val, self_val, arg_val);
|
1783
1814
|
} else if (BIGNUM_P (arg)) {
|
@@ -1789,14 +1820,94 @@ VALUE r_gmpz_gcdext(VALUE self, VALUE arg)
|
|
1789
1820
|
} else {
|
1790
1821
|
typeerror (ZXB);
|
1791
1822
|
}
|
1792
|
-
|
1823
|
+
|
1793
1824
|
if (free_arg_val)
|
1794
|
-
mpz_temp_free(arg_val);
|
1795
|
-
|
1796
|
-
ary = rb_ary_new3(3, res, s, t);
|
1825
|
+
mpz_temp_free (arg_val);
|
1826
|
+
|
1827
|
+
ary = rb_ary_new3 (3, res, s, t);
|
1828
|
+
return ary;
|
1829
|
+
}
|
1830
|
+
|
1831
|
+
/*
|
1832
|
+
* call-seq:
|
1833
|
+
* a.gcdext2(b) #=> g, s
|
1834
|
+
*
|
1835
|
+
* @since 0.5.x
|
1836
|
+
*
|
1837
|
+
* Returns the greatest common divisor of _a_ and _b_, in addition to _s_, the
|
1838
|
+
* coefficient satisfying <i>a*s + b*t = g</i>. _g_ is always positive, even if one or
|
1839
|
+
* both of _a_ and _b_ are negative. _s_ and _t_ are chosen such that
|
1840
|
+
* <i>abs(s) <= abs(b)</i> and <i>abs(t) <= abs(a)</i>.
|
1841
|
+
*/
|
1842
|
+
VALUE r_gmpz_gcdext2(VALUE self, VALUE arg)
|
1843
|
+
{
|
1844
|
+
MP_INT *self_val, *arg_val, *res_val, *s_val;
|
1845
|
+
VALUE res, s, ary;
|
1846
|
+
int free_arg_val = 0;
|
1847
|
+
|
1848
|
+
mpz_get_struct (self,self_val);
|
1849
|
+
|
1850
|
+
if (GMPZ_P (arg)) {
|
1851
|
+
mpz_make_struct_init (res, res_val);
|
1852
|
+
mpz_make_struct_init (s, s_val);
|
1853
|
+
mpz_get_struct (arg, arg_val);
|
1854
|
+
mpz_gcdext (res_val, s_val, NULL, self_val, arg_val);
|
1855
|
+
} else if (FIXNUM_P (arg)) {
|
1856
|
+
mpz_make_struct_init (res, res_val);
|
1857
|
+
mpz_make_struct_init (s, s_val);
|
1858
|
+
mpz_temp_alloc (arg_val);
|
1859
|
+
mpz_init_set_ui (arg_val, FIX2NUM(arg));
|
1860
|
+
free_arg_val = 1;
|
1861
|
+
mpz_gcdext (res_val, s_val, NULL, self_val, arg_val);
|
1862
|
+
} else if (BIGNUM_P (arg)) {
|
1863
|
+
mpz_make_struct_init (res, res_val);
|
1864
|
+
mpz_make_struct_init (s, s_val);
|
1865
|
+
mpz_set_bignum (res_val, arg);
|
1866
|
+
mpz_gcdext (res_val, s_val, NULL, res_val, self_val);
|
1867
|
+
} else {
|
1868
|
+
typeerror (ZXB);
|
1869
|
+
}
|
1870
|
+
|
1871
|
+
if (free_arg_val)
|
1872
|
+
mpz_temp_free (arg_val);
|
1873
|
+
|
1874
|
+
ary = rb_ary_new3 (2, res, s);
|
1797
1875
|
return ary;
|
1798
1876
|
}
|
1799
1877
|
|
1878
|
+
/*
|
1879
|
+
* call-seq:
|
1880
|
+
* a.lcm(b)
|
1881
|
+
*
|
1882
|
+
* @since 0.2.11
|
1883
|
+
*
|
1884
|
+
* Returns the least common multiple of a and b. The result is always positive even if
|
1885
|
+
* one or both of _a_ or _b_ are negative.
|
1886
|
+
*/
|
1887
|
+
VALUE r_gmpz_lcm(VALUE self, VALUE arg)
|
1888
|
+
{
|
1889
|
+
MP_INT *self_val, *arg_val, *res_val;
|
1890
|
+
VALUE res;
|
1891
|
+
|
1892
|
+
mpz_get_struct (self,self_val);
|
1893
|
+
|
1894
|
+
if (GMPZ_P (arg)) {
|
1895
|
+
mpz_make_struct_init (res, res_val);
|
1896
|
+
mpz_get_struct (arg, arg_val);
|
1897
|
+
mpz_lcm (res_val, self_val, arg_val);
|
1898
|
+
} else if (FIXNUM_P (arg)) {
|
1899
|
+
mpz_make_struct_init (res, res_val);
|
1900
|
+
mpz_lcm_ui (res_val, self_val, FIX2NUM(arg));
|
1901
|
+
} else if (BIGNUM_P (arg)) {
|
1902
|
+
mpz_make_struct_init (res, res_val);
|
1903
|
+
mpz_set_bignum (res_val, arg);
|
1904
|
+
mpz_lcm (res_val, res_val, self_val);
|
1905
|
+
} else {
|
1906
|
+
typeerror (ZXB);
|
1907
|
+
}
|
1908
|
+
return res;
|
1909
|
+
}
|
1910
|
+
|
1800
1911
|
/*
|
1801
1912
|
* call-seq:
|
1802
1913
|
* a.invert(b)
|
@@ -2536,15 +2647,17 @@ void init_gmpz()
|
|
2536
2647
|
cGMP_Z = rb_define_class_under(mGMP, "Z", rb_cInteger);
|
2537
2648
|
|
2538
2649
|
// Initializing, Assigning Integers
|
2539
|
-
rb_define_singleton_method(cGMP_Z, "new",
|
2540
|
-
rb_define_method(cGMP_Z, "initialize",
|
2541
|
-
rb_define_method(cGMP_Z, "
|
2650
|
+
rb_define_singleton_method(cGMP_Z, "new", r_gmpzsg_new, -1);
|
2651
|
+
rb_define_method( cGMP_Z, "initialize", r_gmpz_initialize, -1);
|
2652
|
+
rb_define_method( cGMP_Z, "initialize_copy", r_gmpz_initialize_copy, 1);
|
2653
|
+
rb_define_alloc_func(cGMP_Z, r_gmpz_alloc);
|
2654
|
+
rb_define_method( cGMP_Z, "swap", r_gmpz_swap, 1);
|
2542
2655
|
|
2543
2656
|
// Converting Integers
|
2544
2657
|
rb_define_method(cGMP_Z, "to_i", r_gmpz_to_i, 0);
|
2545
2658
|
rb_define_method(cGMP_Z, "to_d", r_gmpz_to_d, 0);
|
2546
2659
|
rb_define_method(cGMP_Z, "to_s", r_gmpz_to_s, -1);
|
2547
|
-
|
2660
|
+
|
2548
2661
|
// Integer Arithmetic
|
2549
2662
|
rb_define_method(cGMP_Z, "+", r_gmpz_add, 1);
|
2550
2663
|
rb_define_method(cGMP_Z, "add!", r_gmpz_add_self, 1);
|
@@ -2568,7 +2681,7 @@ void init_gmpz()
|
|
2568
2681
|
rb_define_singleton_method(cGMP_Z, "mul_2exp", r_gmpzsg_mul_2exp, 3);
|
2569
2682
|
rb_define_singleton_method(cGMP_Z, "neg", r_gmpzsg_neg, 2);
|
2570
2683
|
rb_define_singleton_method(cGMP_Z, "abs", r_gmpzsg_abs, 2);
|
2571
|
-
|
2684
|
+
|
2572
2685
|
// Integer Division
|
2573
2686
|
rb_define_method(cGMP_Z, "/", r_gmpz_div, 1);
|
2574
2687
|
rb_define_method(cGMP_Z, "tdiv", r_gmpz_tdiv, 1);
|
@@ -2591,7 +2704,7 @@ void init_gmpz()
|
|
2591
2704
|
rb_define_singleton_method(cGMP_Z, "tdiv_r_2exp", r_gmpzsg_tdiv_r_2exp, 3);
|
2592
2705
|
rb_define_singleton_method(cGMP_Z, "divisible?", r_gmpzsg_divisible, 2);
|
2593
2706
|
rb_define_singleton_method(cGMP_Z, "congruent?", r_gmpzsg_congruent, 3);
|
2594
|
-
|
2707
|
+
|
2595
2708
|
// Integer Exponentiation
|
2596
2709
|
rb_define_singleton_method(cGMP_Z, "pow", r_gmpzsg_pow, 2);
|
2597
2710
|
rb_define_method(cGMP_Z, "**", r_gmpz_pow, 1);
|
@@ -2606,26 +2719,28 @@ void init_gmpz()
|
|
2606
2719
|
rb_define_method(cGMP_Z, "power?", r_gmpz_is_power, 0);
|
2607
2720
|
// Functional Mappings
|
2608
2721
|
rb_define_singleton_method(cGMP_Z, "sqrt", r_gmpzsg_sqrt, 2);
|
2609
|
-
|
2722
|
+
|
2610
2723
|
// Number Theoretic Functions
|
2611
2724
|
rb_define_method( cGMP_Z, "probab_prime?", r_gmpz_is_probab_prime, -1);
|
2612
2725
|
rb_define_method( cGMP_Z, "nextprime", r_gmpz_nextprime, 0);
|
2613
2726
|
rb_define_method( cGMP_Z, "nextprime!", r_gmpz_nextprime_self, 0);
|
2614
2727
|
rb_define_alias( cGMP_Z, "next_prime", "nextprime");
|
2615
2728
|
rb_define_alias( cGMP_Z, "next_prime!", "nextprime!");
|
2616
|
-
rb_define_method( cGMP_Z, "gcd", r_gmpz_gcd,
|
2617
|
-
rb_define_method( cGMP_Z, "gcdext", r_gmpz_gcdext,
|
2618
|
-
rb_define_method( cGMP_Z, "
|
2619
|
-
rb_define_method( cGMP_Z, "
|
2620
|
-
|
2621
|
-
rb_define_method( cGMP_Z, "
|
2622
|
-
|
2623
|
-
|
2624
|
-
|
2729
|
+
rb_define_method( cGMP_Z, "gcd", r_gmpz_gcd, 1);
|
2730
|
+
rb_define_method( cGMP_Z, "gcdext", r_gmpz_gcdext, 1);
|
2731
|
+
rb_define_method( cGMP_Z, "gcdext2", r_gmpz_gcdext2, 1);
|
2732
|
+
rb_define_method( cGMP_Z, "lcm", r_gmpz_lcm, 1);
|
2733
|
+
rb_define_method( cGMP_Z, "invert", r_gmpz_invert, 1);
|
2734
|
+
rb_define_method( cGMP_Z, "jacobi", r_gmpz_jacobi, 1);
|
2735
|
+
rb_define_singleton_method(cGMP_Z, "jacobi", r_gmpzsg_jacobi, 2);
|
2736
|
+
rb_define_method( cGMP_Z, "legendre", r_gmpz_legendre, 1);
|
2737
|
+
rb_define_method( cGMP_Z, "remove", r_gmpz_remove, 1);
|
2738
|
+
rb_define_singleton_method(cGMP_Z, "fac", r_gmpzsg_fac, 1);
|
2739
|
+
rb_define_singleton_method(cGMP_Z, "fib", r_gmpzsg_fib, 1);
|
2625
2740
|
// Functional Mappings
|
2626
|
-
rb_define_singleton_method(cGMP_Z, "lcm",
|
2627
|
-
rb_define_singleton_method(cGMP_Z, "nextprime",
|
2628
|
-
|
2741
|
+
rb_define_singleton_method(cGMP_Z, "lcm", r_gmpzsg_lcm, 3);
|
2742
|
+
rb_define_singleton_method(cGMP_Z, "nextprime", r_gmpzsg_nextprime, 2);
|
2743
|
+
|
2629
2744
|
// Integer Comparisons
|
2630
2745
|
rb_define_method(cGMP_Z, "<=>", r_gmpz_cmp, 1);
|
2631
2746
|
rb_define_method(cGMP_Z, ">", r_gmpz_cmp_gt, 1);
|
@@ -2635,10 +2750,10 @@ void init_gmpz()
|
|
2635
2750
|
rb_define_method(cGMP_Z, "<=", r_gmpz_cmp_le, 1);
|
2636
2751
|
rb_define_method(cGMP_Z, "cmpabs", r_gmpz_cmpabs, 1);
|
2637
2752
|
rb_define_method(cGMP_Z, "sgn", r_gmpz_sgn, 0);
|
2638
|
-
|
2753
|
+
|
2639
2754
|
rb_define_method(cGMP_Z, "eql?", r_gmpz_eql, 1);
|
2640
2755
|
rb_define_method(cGMP_Z, "hash", r_gmpz_hash, 0);
|
2641
|
-
|
2756
|
+
|
2642
2757
|
// Integer Logic and Bit Fiddling
|
2643
2758
|
rb_define_method(cGMP_Z, "&", r_gmpz_and, 1);
|
2644
2759
|
rb_define_method(cGMP_Z, "|", r_gmpz_or, 1);
|
@@ -2652,17 +2767,17 @@ void init_gmpz()
|
|
2652
2767
|
rb_define_method(cGMP_Z, "[]", r_gmpz_getbit, 1);
|
2653
2768
|
// Functional Mappings
|
2654
2769
|
rb_define_singleton_method(cGMP_Z, "com", r_gmpzsg_com, 2);
|
2655
|
-
|
2770
|
+
|
2656
2771
|
// Miscellaneous Integer Functions
|
2657
2772
|
rb_define_method(cGMP_Z, "even?", r_gmpz_is_even, 0);
|
2658
2773
|
rb_define_method(cGMP_Z, "odd?", r_gmpz_is_odd, 0);
|
2659
2774
|
rb_define_method(cGMP_Z, "sizeinbase", r_gmpz_sizeinbase, 1);
|
2660
2775
|
rb_define_alias( cGMP_Z, "size_in_base", "sizeinbase");
|
2661
2776
|
rb_define_method(cGMP_Z, "size_in_bin", r_gmpz_size_in_bin, 0);
|
2662
|
-
|
2777
|
+
|
2663
2778
|
// Integer Special Functions
|
2664
2779
|
rb_define_method(cGMP_Z, "size", r_gmpz_size, 0);
|
2665
|
-
|
2780
|
+
|
2666
2781
|
// _unsorted_
|
2667
2782
|
rb_define_method(cGMP_Z, ">>", r_gmpz_fshr, 1);
|
2668
2783
|
rb_define_method(cGMP_Z, "lastbits_pos", r_gmpz_fshrm, 1);
|
data/ext/mprnd.c
CHANGED
@@ -10,7 +10,7 @@ VALUE r_mprndsg_new(int argc, VALUE *argv, VALUE klass)
|
|
10
10
|
int *res_value;
|
11
11
|
(void)klass;
|
12
12
|
res_value = 0;
|
13
|
-
|
13
|
+
|
14
14
|
mprnd_make_struct(res, res_value);
|
15
15
|
rb_obj_call_init(res, argc, argv);
|
16
16
|
return res;
|
@@ -19,10 +19,10 @@ VALUE r_mprndsg_new(int argc, VALUE *argv, VALUE klass)
|
|
19
19
|
VALUE r_mprnd_initialize(int argc, VALUE *argv, VALUE self)
|
20
20
|
{
|
21
21
|
VALUE mode, name, ieee754;
|
22
|
-
mode = argv[0];
|
23
|
-
(void)argc;
|
24
22
|
const char *prefix;
|
25
23
|
char name_val[10];
|
24
|
+
mode = argv[0];
|
25
|
+
(void)argc;
|
26
26
|
if (MPFR_VERSION_MAJOR < 3)
|
27
27
|
prefix = "GMP";
|
28
28
|
else
|
@@ -66,19 +66,19 @@ VALUE r_mprnd_inspect(VALUE self)
|
|
66
66
|
|
67
67
|
void init_gmprnd()
|
68
68
|
{
|
69
|
-
mGMP = rb_define_module("GMP");
|
70
69
|
ID new_id = rb_intern("new");
|
70
|
+
mGMP = rb_define_module("GMP");
|
71
71
|
|
72
72
|
cGMP_Rnd = rb_define_class_under(mGMP, "Rnd", rb_cObject);
|
73
|
-
|
73
|
+
|
74
74
|
rb_define_singleton_method(cGMP_Rnd, "new", r_mprndsg_new, -1);
|
75
75
|
rb_define_method(cGMP_Rnd, "initialize", r_mprnd_initialize, -1);
|
76
76
|
rb_define_method(cGMP_Rnd, "inspect", r_mprnd_inspect, 0);
|
77
|
-
|
77
|
+
|
78
78
|
rb_define_attr (cGMP_Rnd, "mode", 1, 0);
|
79
79
|
rb_define_attr (cGMP_Rnd, "name", 1, 0);
|
80
80
|
rb_define_attr (cGMP_Rnd, "ieee754", 1, 0);
|
81
|
-
|
81
|
+
|
82
82
|
rb_define_const(mGMP, "GMP_RNDN", rb_funcall (cGMP_Rnd, new_id, 1, INT2FIX(0)));
|
83
83
|
rb_define_const(mGMP, "GMP_RNDZ", rb_funcall (cGMP_Rnd, new_id, 1, INT2FIX(1)));
|
84
84
|
rb_define_const(mGMP, "GMP_RNDU", rb_funcall (cGMP_Rnd, new_id, 1, INT2FIX(2)));
|
data/ext/ruby_gmp.h
CHANGED
@@ -77,8 +77,8 @@ typedef __gmp_randstate_struct MP_RANDSTATE;
|
|
77
77
|
#define mpz_temp_alloc(var) { var=malloc(sizeof(MP_INT)); }
|
78
78
|
#define mpz_temp_init(var) { mpz_temp_alloc(var); mpz_init(var); }
|
79
79
|
#define mpz_temp_from_bignum(var,var_bignum) { \
|
80
|
-
mpz_temp_alloc(var); \
|
81
80
|
VALUE tmp = rb_funcall (var_bignum, rb_intern ("to_s"), 1, INT2FIX(32)); \
|
81
|
+
mpz_temp_alloc(var); \
|
82
82
|
mpz_init_set_str (var, StringValuePtr (tmp), 32); \
|
83
83
|
}
|
84
84
|
#define mpz_temp_free(var) { mpz_clear(var); free(var); }
|
@@ -265,7 +265,7 @@ extern VALUE r_gmpf_set_prec_raw(VALUE self, VALUE arg);
|
|
265
265
|
|
266
266
|
// Converting Floats
|
267
267
|
extern VALUE r_gmpf_to_d(VALUE self);
|
268
|
-
extern VALUE r_gmpf_to_s(VALUE self);
|
268
|
+
extern VALUE r_gmpf_to_s(int argc, VALUE *argv, VALUE self);
|
269
269
|
|
270
270
|
// Float Arithmetic
|
271
271
|
#ifndef MPFR
|
data/lib/gmp.rb
CHANGED
@@ -6,4 +6,25 @@ ENV['PATH'] = [File.expand_path(
|
|
6
6
|
File.join(File.dirname(__FILE__), "..", "ext")
|
7
7
|
), ENV['PATH']].compact.join(';') if RbConfig::CONFIG['host_os'] =~ /(mswin|mingw|mingw32)/i
|
8
8
|
|
9
|
-
require File.dirname(__FILE__) + '/../ext/gmp'
|
9
|
+
require File.dirname(__FILE__) + '/../ext/gmp'
|
10
|
+
|
11
|
+
unless RUBY_VERSION =~ /^1.8/
|
12
|
+
module GMP
|
13
|
+
def self.sprintf(format, *args)
|
14
|
+
first_pct = format.index '%'
|
15
|
+
result = format[0...first_pct]
|
16
|
+
#format.gsub(/(?<!%)%[0#+ ']*[0-9]*.?[0-9]*[a-zA-Z][^%]*/) do |fragment|
|
17
|
+
format.gsub(Regexp.new('(?<!%)%[0#+ \']*[0-9]*.?[0-9]*[a-zA-Z][^%]*')) do |fragment|
|
18
|
+
arg = args.shift
|
19
|
+
if fragment =~ /%[0#+ ']*[0-9]*.?[0-9]*[ZQF]/
|
20
|
+
result << sprintf2(fragment, arg)
|
21
|
+
elsif fragment =~ /%[0#+ ']*[0-9]*.?[0-9]*[PR]/ && GMP.const_defined?(:MPFR_VERSION)
|
22
|
+
result << GMP::F.sprintf2(fragment, arg)
|
23
|
+
else
|
24
|
+
result << (fragment % arg)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/manual.pdf
CHANGED
Binary file
|
data/manual.tex
CHANGED
@@ -34,8 +34,8 @@
|
|
34
34
|
\huge{gmp} &\\
|
35
35
|
\midrule[3pt]
|
36
36
|
\multicolumn{2}{r}{\large{Ruby bindings to the GMP library}}\\
|
37
|
-
\multicolumn{2}{r}{\large{Edition 0.
|
38
|
-
\multicolumn{2}{r}{\large{
|
37
|
+
\multicolumn{2}{r}{\large{Edition 0.6.7}}\\
|
38
|
+
\multicolumn{2}{r}{\large{9 December 2012}}
|
39
39
|
\end{tabular}
|
40
40
|
|
41
41
|
\vfill
|
@@ -47,7 +47,7 @@
|
|
47
47
|
This manual describes how to use the gmp Ruby gem, which provides bindings to
|
48
48
|
the GNU multiple precision arithmetic library, version 4.3.x or 5.0.x.\\
|
49
49
|
\\
|
50
|
-
Copyright 2009, 2010, 2011 Sam Rawlins.\\
|
50
|
+
Copyright 2009, 2010, 2011, 2012 Sam Rawlins.\\
|
51
51
|
No license yet.
|
52
52
|
\newpage
|
53
53
|
|
@@ -1525,110 +1525,6 @@ Every method below accepts two additional parameters in addition to any required
|
|
1525
1525
|
\newpage
|
1526
1526
|
\section{Benchmarking}
|
1527
1527
|
|
1528
|
-
|
1529
|
-
a significant improvement over version 0.1. The suite consists of 3 parts.\\\\
|
1530
|
-
|
1531
|
-
First is six individual programs that will benchmark a single concept. These are
|
1532
|
-
\texttt{multiply}, \texttt{divide}, \texttt{gcd}, \texttt{gcdext}, \texttt{rsa}, and
|
1533
|
-
\texttt{pi}.
|
1534
|
-
|
1535
|
-
Second is gexpr.c, a nifty little program (compiled with \texttt{gcc -o gexpr gexpr.c},
|
1536
|
-
or\\ \texttt{gcc -o gexpr gexpr.c -lm} on some systems). They use this basically for
|
1537
|
-
weighing the results of individual tests and stringifying them to a certain precision.
|
1538
|
-
|
1539
|
-
Third is runbench, a shell script that runs each of the six benchmark programs, each
|
1540
|
-
several times with a different set of arguments. It compiles the results, using gexpr
|
1541
|
-
to carefully calculate a final "score" for each benchmark, each benchmark family
|
1542
|
-
(\texttt{rsa} and \texttt{pi} are separated as "app" benchmarks.), and for the suite as a
|
1543
|
-
whole.
|
1544
|
-
|
1545
|
-
\subsection{gmp gem benchmarking}
|
1546
|
-
|
1547
|
-
The structure described above lends itself perfectly to some simple modifications that
|
1548
|
-
allow me to benchmark the gmp gem. Instead of using the C programs that are the
|
1549
|
-
individual benchmarks, I have converted them into Ruby programs, and called them the same
|
1550
|
-
names. When runbench executes "multiply" for example, it is running a Ruby program that
|
1551
|
-
does the same general thing as "multiply" the C program. This allows me to benchmark the
|
1552
|
-
gmp gem, and I can even compare the results with those of benchmarking GMP itself. I have
|
1553
|
-
done so below.
|
1554
|
-
|
1555
|
-
\newpage
|
1556
|
-
\subsection{Benchmark Results}
|
1557
|
-
|
1558
|
-
I've benchmarked an array of Ruby-version/GMP-version combinations, which can be compared
|
1559
|
-
with results of the actual GMPbench benchmark, in order to understand the overhead that
|
1560
|
-
Ruby and the Ruby C Extension API impose on the GMP library. The benchmarks listed were
|
1561
|
-
all executed on an Apple MacBook "5.1." booting three operating systems with rEFIt 0.14.
|
1562
|
-
Because not all of the marks from GMPbench have been ported to the Ruby gmp gem, results
|
1563
|
-
for 'base' and 'app' are not listed; they cannot be compared with GMPbench results.\\
|
1564
|
-
|
1565
|
-
\begin{LARGE}MacBook, Intel Core 2 Duo, 2 GHz, 2 GB DDR3\end{LARGE}\\
|
1566
|
-
|
1567
|
-
Mac OS X 10.6.4, x86 (32-bit)\\
|
1568
|
-
Ruby and GMP compiled with gcc 4.2.1 (Apple Inc. build 5664)\\
|
1569
|
-
\begin{tabular}{|l|l|r|r|r|r|r|}
|
1570
|
-
\hline
|
1571
|
-
GMP & bench & Ruby 1.8.7 & Ruby 1.9.1 & Ruby 1.9.2 & RBX 1.1 & C \\
|
1572
|
-
\hline
|
1573
|
-
4.3.2 & multiply & 7734.2 & 7505.9 & 7637.9 & 7469.3 & 16789 \\
|
1574
|
-
& divide & 7336.1 & 7180 & 7223.7 & 7121.2 & 9872.5 \\
|
1575
|
-
& gcd & 2356 & 2436.8 & 2448.8 & 2385.6 & 2938.9 \\
|
1576
|
-
& rsa & 2035.2 & 1995.3 & 2068.4 & 2051.1 & 2136.7 \\
|
1577
|
-
\hline
|
1578
|
-
5.0.1 & multiply & 8030.5 & 7926.7 & 8019.3 & 7944.1 & 17925 \\
|
1579
|
-
& divide & 10341 & 10070 & 10218 & 10018 & 16069 \\
|
1580
|
-
& gcd & 2501 & 2535.4 & 2578.7 & 2537.3 & 3063.7 \\
|
1581
|
-
& rsa & 2128 & 2159.1 & 2170.5 & 2162 & 2229.2 \\
|
1582
|
-
\hline
|
1583
|
-
\end{tabular}\\\\
|
1584
|
-
|
1585
|
-
Ubuntu 10.04, Kernel 2.6.32-25, x86\_64 (64-bit)\\
|
1586
|
-
Ruby and GMP compiled with gcc 4.4.3 (Ubuntu 4.4.3-4ubuntu5)\\
|
1587
|
-
\begin{small}In these tests, the classic multiply benchmark crashes with OutOfMemory. There are
|
1588
|
-
two ways this has been remedied. The first (tests marked multiply.gc) is to manually
|
1589
|
-
kick off garbage collection every so often. This solves the memory problem in all
|
1590
|
-
interpreters except Rubinius 1.1 (investigation pending). The second, and far better
|
1591
|
-
solution is to employ the new functional mapping methods. These have not been
|
1592
|
-
documented yet, but documentation is pending, and high on my priority list. Simply
|
1593
|
-
put, these methods overcome the overhead (memory and time) of instantiating new
|
1594
|
-
objects all the time.\end{small}\\
|
1595
|
-
\begin{tabular}{|l|l|r|r|r|r|r|}
|
1596
|
-
\hline
|
1597
|
-
GMP & bench & Ruby 1.8.7 & Ruby 1.9.1 & Ruby 1.9.2 & RBX 1.1 & C \\
|
1598
|
-
\hline
|
1599
|
-
4.3.2 & multiply & x & x & x & x & 14716 \\
|
1600
|
-
& multiply.gc & 7849.2 & 6911.4 & 7703.5 & x & 14716 \\
|
1601
|
-
& multiply.fnl & 9532.6 & 11182 & 10886 & 5131.3 & 14716 \\
|
1602
|
-
& divide & 7704.6 & 7591.8 & 7527.2 & 4265.1 & 8614.3 \\
|
1603
|
-
& gcd & 2420.1 & 2453.6 & 2487.4 & 1676.4 & 2779.8 \\
|
1604
|
-
& rsa & 2040.5 & 2069.2 & 2044.2 & 1758.9 & 1984.3 \\
|
1605
|
-
\hline
|
1606
|
-
5.0.1 & multiply & x & x & x & x & 17695 \\
|
1607
|
-
& multiply.gc & 8265.3 & 7289.4 & 8105.1 & x & 17695 \\
|
1608
|
-
& multiply.fnl & 10029 & 11807 & 11493 & 6036.7 & 17695 \\
|
1609
|
-
& divide & 10988 & 10935 & 10799 & 6164.9 & 15629 \\
|
1610
|
-
& gcd & 2554.2 & 2510.2 & 2538.6 & 1802.8 & 2925.1 \\
|
1611
|
-
& rsa & 2128.7 & 2189 & 2179.9 & 1941.2 & 2233.4 \\
|
1612
|
-
\hline
|
1613
|
-
\end{tabular}\\\\
|
1614
|
-
|
1615
|
-
\newpage
|
1616
|
-
Windows 7 (64-bit)\\
|
1617
|
-
Ruby and GMP compiled with gcc 4.5.0 (tdm-1)\\
|
1618
|
-
\begin{tabular}{|l|l|r|r|r|r|}
|
1619
|
-
\hline
|
1620
|
-
GMP & bench & Ruby 1.8.7 & Ruby 1.9.1 & Ruby 1.9.2 & C \\
|
1621
|
-
\hline
|
1622
|
-
4.3.2 & multiply & 3607.9 & 3679.3 & 3655.5 & 6448.7 \\
|
1623
|
-
& divide & 3062.6 & 3103.7 & 3074.5 & 3717.5 \\
|
1624
|
-
& gcd & 1165 & 1190.6 & 1211.8 & 1359.4 \\
|
1625
|
-
& rsa & 733.87 & 729.9 & 742.22 & 757.97 \\
|
1626
|
-
\hline
|
1627
|
-
5.0.1 & multiply & 3792.1 & 3869 & 3785.9 & 6835.2 \\
|
1628
|
-
& divide & 4662.2 & 4704.4 & 4692.3 & 6497.4 \\
|
1629
|
-
& gcd & 1222.8 & 1249.7 & 1245 & 1394.2 \\
|
1630
|
-
& rsa & 742.78 & 745.66 & 739.9 & 754.72 \\
|
1631
|
-
\hline
|
1632
|
-
\end{tabular}\\
|
1528
|
+
Benchmark results can be found in performance.pdf.
|
1633
1529
|
|
1634
1530
|
\end{document}
|