gmp 0.5.47 → 0.6.7
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/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}
|