gmp 0.6.17 → 0.6.19
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -0
- data/README.markdown +5 -2
- data/ext/gmpz.c +148 -1
- data/test/gmp_tcong.rb +72 -0
- data/test/tc_z_export_import.rb +21 -0
- data/test/unit_tests.rb +3 -0
- metadata +4 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
0.6.19:
|
2
|
+
* Added GMP::Z#congruent? and tests
|
3
|
+
* Added GMP::Z#export and GMP::Z.import and _minimal_ tests
|
4
|
+
|
5
|
+
0.6.17:
|
6
|
+
* Added GMP::Z#out_raw, GMP::Z.inp_raw
|
7
|
+
|
1
8
|
0.6.13:
|
2
9
|
* Added three new GMP::Z methods for GMP 5.1.x: GMP::Z#2fac
|
3
10
|
(GMP::Z#double_fac), GMP::Z#mfac, and GMP::Z#primorial
|
data/README.markdown
CHANGED
@@ -250,6 +250,7 @@ Methods
|
|
250
250
|
tmod,fmod,cmod truncate, floor and ceil modulus
|
251
251
|
>> shift right, floor
|
252
252
|
divisible?(b) true if divisible by b
|
253
|
+
congruent?(c,d) true if congruent to c modulus d
|
253
254
|
** power
|
254
255
|
powmod power modulo
|
255
256
|
\[\],\[\]= testing and setting bits (as booleans)
|
@@ -286,6 +287,8 @@ Methods
|
|
286
287
|
hamdist the hamming distance between two integers
|
287
288
|
out_raw output to IO object
|
288
289
|
inp_raw input from IO object
|
290
|
+
export export to a byte array (String)
|
291
|
+
import import from a byte array (String)
|
289
292
|
sizeinbase(b) digits in base b
|
290
293
|
size_in_bin digits in binary
|
291
294
|
size number of limbs
|
@@ -406,7 +409,7 @@ Documentation
|
|
406
409
|
-------------
|
407
410
|
|
408
411
|
* [This README](https://github.com/srawlins/gmp)
|
409
|
-
* Loren Segal and the guys at RubyGems.org are
|
412
|
+
* Loren Segal and the guys at RubyGems.org are awesome: [YARDoc](http://rubydoc.info/gems/gmp/frames).
|
410
413
|
* There should be a manual.pdf [here](https://github.com/srawlins/gmp/blob/master/manual.pdf). I spend waaay too much time working on this, but it looks very pretty.
|
411
414
|
* [CHANGELOG](https://github.com/srawlins/gmp/blob/master/CHANGELOG)
|
412
415
|
|
@@ -452,7 +455,7 @@ Please see [performance](performance.md)
|
|
452
455
|
Todo
|
453
456
|
----
|
454
457
|
|
455
|
-
* `GMP::Z#to_d_2exp`, `#
|
458
|
+
* `GMP::Z#to_d_2exp`, `#rootrem`, `#kronecker`, `#bin`, `#fib2`, `#lucnum`, `#lucnum2`, `#combit`, `#fits_x?`
|
456
459
|
* `GMP::Q#to_s(base)`, `GMP::F#to_s(base)` (test it!)
|
457
460
|
* benchmark pi
|
458
461
|
* a butt-load of functional mappings. 47-ish sets.
|
data/ext/gmpz.c
CHANGED
@@ -1502,7 +1502,7 @@ static VALUE r_gmpz_divisible(VALUE self, VALUE arg)
|
|
1502
1502
|
MP_INT *self_val, *arg_val;
|
1503
1503
|
int res;
|
1504
1504
|
mpz_get_struct (self, self_val);
|
1505
|
-
|
1505
|
+
|
1506
1506
|
if (FIXNUM_P (arg) && FIX2NUM (arg) > 0) {
|
1507
1507
|
mpz_temp_alloc(arg_val);
|
1508
1508
|
mpz_init_set_ui(arg_val, FIX2NUM(arg));
|
@@ -1527,6 +1527,60 @@ static VALUE r_gmpz_divisible(VALUE self, VALUE arg)
|
|
1527
1527
|
return (res != 0) ? Qtrue : Qfalse;
|
1528
1528
|
}
|
1529
1529
|
|
1530
|
+
/*
|
1531
|
+
* call-seq:
|
1532
|
+
* n.congruent?(c, d)
|
1533
|
+
*
|
1534
|
+
* @since 0.6.19
|
1535
|
+
*
|
1536
|
+
* Returns true if _n_ is congruent to _c_ modulo _d_. _c_ and _d_ can be an instance any of the following:
|
1537
|
+
* * GMP::Z
|
1538
|
+
* * Fixnum
|
1539
|
+
* * Bignum
|
1540
|
+
*/
|
1541
|
+
static VALUE r_gmpz_congruent(VALUE self_val, VALUE c_val, VALUE d_val)
|
1542
|
+
{
|
1543
|
+
MP_INT *self, *c, *d;
|
1544
|
+
int res, free_c, free_d;
|
1545
|
+
mpz_get_struct (self_val, self);
|
1546
|
+
free_c = free_d = 0;
|
1547
|
+
|
1548
|
+
if (FIXNUM_P (c_val) && FIX2NUM (c_val) > 0 &&
|
1549
|
+
FIXNUM_P (d_val) && FIX2NUM (d_val) > 0) {
|
1550
|
+
res = mpz_congruent_ui_p (self, FIX2NUM (c_val), FIX2NUM (d_val));
|
1551
|
+
} else {
|
1552
|
+
if (FIXNUM_P (c_val)) {
|
1553
|
+
mpz_make_struct_init (c_val, c);
|
1554
|
+
mpz_init_set_si (c, FIX2NUM (c_val));
|
1555
|
+
} else if (BIGNUM_P (c_val)) {
|
1556
|
+
mpz_temp_from_bignum (c, c_val);
|
1557
|
+
free_c = 1;
|
1558
|
+
} else if (GMPZ_P (c_val)) {
|
1559
|
+
mpz_get_struct (c_val, c);
|
1560
|
+
} else {
|
1561
|
+
typeerror_as (ZXB, "c");
|
1562
|
+
}
|
1563
|
+
|
1564
|
+
if (FIXNUM_P (d_val)) {
|
1565
|
+
mpz_make_struct_init (d_val, d);
|
1566
|
+
mpz_init_set_si (d, FIX2NUM (d_val));
|
1567
|
+
} else if (BIGNUM_P (d_val)) {
|
1568
|
+
mpz_temp_from_bignum (d, d_val);
|
1569
|
+
free_d = 1;
|
1570
|
+
} else if (GMPZ_P (d_val)) {
|
1571
|
+
mpz_get_struct (d_val, d);
|
1572
|
+
} else {
|
1573
|
+
if (free_c) { mpz_temp_free (c); }
|
1574
|
+
typeerror_as (ZXB, "d");
|
1575
|
+
}
|
1576
|
+
|
1577
|
+
res = mpz_congruent_p (self, c, d);
|
1578
|
+
if (free_c) { mpz_temp_free (c); }
|
1579
|
+
if (free_d) { mpz_temp_free (d); }
|
1580
|
+
}
|
1581
|
+
return (res != 0) ? Qtrue : Qfalse;
|
1582
|
+
}
|
1583
|
+
|
1530
1584
|
|
1531
1585
|
/**********************************************************************
|
1532
1586
|
* Integer Exponentiation *
|
@@ -2731,6 +2785,94 @@ VALUE r_gmpzsg_inp_raw(VALUE klass, VALUE a_val, VALUE stream_val)
|
|
2731
2785
|
}
|
2732
2786
|
|
2733
2787
|
|
2788
|
+
/**********************************************************************
|
2789
|
+
* Integer Import and Export *
|
2790
|
+
**********************************************************************/
|
2791
|
+
|
2792
|
+
/*
|
2793
|
+
* call-seq:
|
2794
|
+
* GMP::Z.import(str, order = -1) #=> GMP::Z
|
2795
|
+
*
|
2796
|
+
* Return a GMP::Z from a String, `str`.
|
2797
|
+
*
|
2798
|
+
* `order` can be 1 for most significant word first or -1 for least significant first.
|
2799
|
+
*
|
2800
|
+
* There is no sign taken from the data, the result will simply be a positive integer. An application can handle any sign itself, and apply it for instance with `GMP::Z#neg`.
|
2801
|
+
*/
|
2802
|
+
VALUE r_gmpzsg_import(int argc, VALUE *argv, VALUE klass)
|
2803
|
+
{
|
2804
|
+
MP_INT *res;
|
2805
|
+
VALUE string_val, order_val, res_val;
|
2806
|
+
char *string;
|
2807
|
+
int order, endian;
|
2808
|
+
size_t nails;
|
2809
|
+
(void)klass;
|
2810
|
+
|
2811
|
+
endian = 0;
|
2812
|
+
nails = 0;
|
2813
|
+
|
2814
|
+
rb_scan_args (argc, argv, "11", &string_val, &order_val);
|
2815
|
+
|
2816
|
+
if (NIL_P (order_val))
|
2817
|
+
order = -1;
|
2818
|
+
else if (! FIXNUM_P (order_val))
|
2819
|
+
typeerror_as (X, "order");
|
2820
|
+
else
|
2821
|
+
order = FIX2INT (order_val);
|
2822
|
+
|
2823
|
+
mpz_make_struct(res_val, res);
|
2824
|
+
mpz_init(res);
|
2825
|
+
|
2826
|
+
string = StringValuePtr (string_val);
|
2827
|
+
|
2828
|
+
mpz_import (res, RSTRING_LEN(string_val), order, sizeof(char), endian, nails, string);
|
2829
|
+
return res_val;
|
2830
|
+
}
|
2831
|
+
|
2832
|
+
/*
|
2833
|
+
* call-seq:
|
2834
|
+
* a.export(order = -1) #=> String
|
2835
|
+
*
|
2836
|
+
* Return a String with word data from _a_.
|
2837
|
+
*
|
2838
|
+
* `order` can be 1 for most significant word first or -1 for least significant
|
2839
|
+
* first.
|
2840
|
+
*
|
2841
|
+
* If `a` is non-zero then the most significant word produced will be non-zero.
|
2842
|
+
* `GMP::Z(0).export` returns `""`.
|
2843
|
+
*
|
2844
|
+
* The sign of _a_ is ignored, just the absolute value is exported. An
|
2845
|
+
* application can use `GMP::Z#sgn` to get the sign and handle it as desired.
|
2846
|
+
*/
|
2847
|
+
VALUE r_gmpz_export(int argc, VALUE *argv, VALUE self_val)
|
2848
|
+
{
|
2849
|
+
MP_INT *self;
|
2850
|
+
VALUE order_val, res;
|
2851
|
+
int order, endian;
|
2852
|
+
size_t countp, nails;
|
2853
|
+
char *string;
|
2854
|
+
|
2855
|
+
endian = 0;
|
2856
|
+
nails = 0;
|
2857
|
+
mpz_get_struct(self_val, self);
|
2858
|
+
|
2859
|
+
rb_scan_args (argc, argv, "01", &order_val);
|
2860
|
+
|
2861
|
+
if (NIL_P (order_val))
|
2862
|
+
order = -1;
|
2863
|
+
else if (! FIXNUM_P (order_val))
|
2864
|
+
typeerror_as (X, "order");
|
2865
|
+
else
|
2866
|
+
order = FIX2INT (order_val);
|
2867
|
+
|
2868
|
+
string = mpz_export (NULL, &countp, order, sizeof(char), endian, nails, self);
|
2869
|
+
res = rb_str_new (string, countp);
|
2870
|
+
free (string);
|
2871
|
+
|
2872
|
+
return res;
|
2873
|
+
}
|
2874
|
+
|
2875
|
+
|
2734
2876
|
/**********************************************************************
|
2735
2877
|
* Miscellaneous Integer Functions *
|
2736
2878
|
**********************************************************************/
|
@@ -2877,6 +3019,7 @@ void init_gmpz()
|
|
2877
3019
|
rb_define_method(cGMP_Z, "cmod", r_gmpz_cmod, 1);
|
2878
3020
|
rb_define_method(cGMP_Z, "%", r_gmpz_mod, 1);
|
2879
3021
|
rb_define_method(cGMP_Z, "divisible?", r_gmpz_divisible, 1);
|
3022
|
+
rb_define_method(cGMP_Z, "congruent?", r_gmpz_congruent, 2);
|
2880
3023
|
// Functional Mappings
|
2881
3024
|
rb_define_singleton_method(cGMP_Z, "divexact", r_gmpzsg_divexact, 3);
|
2882
3025
|
rb_define_singleton_method(cGMP_Z, "cdiv_q_2exp", r_gmpzsg_cdiv_q_2exp, 3);
|
@@ -2964,6 +3107,10 @@ void init_gmpz()
|
|
2964
3107
|
// Functional Mapping
|
2965
3108
|
rb_define_singleton_method(cGMP_Z, "inp_raw", r_gmpzsg_inp_raw, 2);
|
2966
3109
|
|
3110
|
+
// Integer Import and Export
|
3111
|
+
rb_define_singleton_method(cGMP_Z, "import", r_gmpzsg_import, -1);
|
3112
|
+
rb_define_method(cGMP_Z, "export", r_gmpz_export, -1);
|
3113
|
+
|
2967
3114
|
// Miscellaneous Integer Functions
|
2968
3115
|
rb_define_method(cGMP_Z, "even?", r_gmpz_is_even, 0);
|
2969
3116
|
rb_define_method(cGMP_Z, "odd?", r_gmpz_is_odd, 0);
|
data/test/gmp_tcong.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
|
2
|
+
|
3
|
+
class GMP_TCong < Test::Unit::TestCase
|
4
|
+
Data = [
|
5
|
+
# strict equality mod 0
|
6
|
+
[ "0", "0", "0", true],
|
7
|
+
["11", "11", "0", true],
|
8
|
+
[ "3", "11", "0", false],
|
9
|
+
|
10
|
+
# anything congruent mod 1
|
11
|
+
[ "0", "0", "1", true ],
|
12
|
+
[ "1", "0", "1", true ],
|
13
|
+
[ "0", "1", "1", true ],
|
14
|
+
[ "123", "456", "1", true ],
|
15
|
+
["0x123456789123456789", "0x987654321987654321", "1", true ],
|
16
|
+
|
17
|
+
# csize==1, dsize==2 changing to 1 after stripping 2s
|
18
|
+
[ "0x3333333333333333", "0x33333333", "0x180000000", true],
|
19
|
+
["0x33333333333333333333333333333333", "0x3333333333333333", "0x18000000000000000", true],
|
20
|
+
|
21
|
+
# another dsize==2 becoming 1, with opposite signs this time */
|
22
|
+
[ "0x444444441", "-0x22222221F", "0x333333330", true],
|
23
|
+
["0x44444444444444441", "-0x2222222222222221F", "0x33333333333333330", true]
|
24
|
+
]
|
25
|
+
RS = GMP::RandState.new(11213)
|
26
|
+
Reps = 2_000 # The original was 10_000 but that took like 5 seconds
|
27
|
+
|
28
|
+
def test_congruent()
|
29
|
+
Data.each do |a, c, d, want|
|
30
|
+
got = GMP::Z(a).congruent?(GMP::Z(c), GMP::Z(d))
|
31
|
+
assert_equal(want, got, "congruent? should produce the correct result for #{a}, #{c}, #{d}")
|
32
|
+
end
|
33
|
+
|
34
|
+
Reps.times do
|
35
|
+
size = RS.urandomb(32)
|
36
|
+
size = RS.urandomb((size % 16 + 1).to_i)
|
37
|
+
a = RS.rrandomb(size.to_i)
|
38
|
+
|
39
|
+
size = RS.urandomb(32)
|
40
|
+
size = RS.urandomb((size % 16 + 1).to_i)
|
41
|
+
c = RS.rrandomb(size.to_i)
|
42
|
+
|
43
|
+
d = 0
|
44
|
+
until d != 0
|
45
|
+
size = RS.urandomb(32)
|
46
|
+
size = RS.urandomb((size % 16 + 1).to_i)
|
47
|
+
d = RS.rrandomb(size.to_i)
|
48
|
+
end
|
49
|
+
|
50
|
+
a = negrandom(a)
|
51
|
+
c = negrandom(c)
|
52
|
+
d = negrandom(d)
|
53
|
+
|
54
|
+
ra = a.fmod d
|
55
|
+
rc = c.fmod d
|
56
|
+
want = (ra <=> rc) == 0
|
57
|
+
|
58
|
+
got = GMP::Z(a).congruent?(GMP::Z(c), GMP::Z(d))
|
59
|
+
assert_equal(want, got, "congruent? should produce the correct result for #{a}, #{c}, #{d}")
|
60
|
+
|
61
|
+
ra = ra - rc
|
62
|
+
a = a - ra
|
63
|
+
|
64
|
+
got = GMP::Z(a).congruent?(GMP::Z(c), GMP::Z(d))
|
65
|
+
assert_equal(true, got, "congruent? should produce the correct result for #{a}, #{c}, #{d}")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def negrandom(z)
|
70
|
+
return (RS.urandomb(1) != 0) ? z.neg : z
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
|
2
|
+
|
3
|
+
class TC_Z_ExportImport < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@a = GMP::Z.new(3)**40
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_export_import_identity
|
9
|
+
assert_equal(@a, GMP::Z.import(@a.export), "An integer should export and then import to itself")
|
10
|
+
assert_equal(@a, GMP::Z.import(@a.export(-1)), "An integer should export and then import to itself")
|
11
|
+
assert_equal(@a, GMP::Z.import(@a.export, -1), "An integer should export and then import to itself")
|
12
|
+
assert_equal(@a, GMP::Z.import(@a.export(-1), -1), "An integer should export and then import to itself")
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_export_import_order
|
16
|
+
assert_equal(@a, GMP::Z.import(@a.export(1), 1), "An integer should export and then import to itself")
|
17
|
+
|
18
|
+
assert_false(@a == GMP::Z.import(@a.export( 1), -1), "An integer exported one way and then imported should not be equal")
|
19
|
+
assert_false(@a == GMP::Z.import(@a.export(-1), 1), "An integer exported one way and then imported should not be equal")
|
20
|
+
end
|
21
|
+
end
|
data/test/unit_tests.rb
CHANGED
@@ -13,6 +13,7 @@ require './tc_z_addmul'
|
|
13
13
|
require './tc_z_submul'
|
14
14
|
require './tc_z_logic'
|
15
15
|
require './tc_z_exponentiation'
|
16
|
+
require './tc_z_export_import'
|
16
17
|
require './tc_z_hamdist'
|
17
18
|
require './tc_z_io'
|
18
19
|
require './tc_z_to_dis'
|
@@ -32,7 +33,9 @@ require './tc_random'
|
|
32
33
|
require './tc_hashes'
|
33
34
|
require './tc_z_functional_mappings'
|
34
35
|
|
36
|
+
require './gmp_tcong'
|
35
37
|
require './gmp_tgcd'
|
38
|
+
require './gmp_tlcm'
|
36
39
|
require './gmp_tprintf'
|
37
40
|
|
38
41
|
begin
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gmp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.19
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-12-
|
13
|
+
date: 2012-12-31 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: gmp - providing Ruby bindings to the GMP library.
|
16
16
|
email:
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- ext/takeover.h
|
37
37
|
- ext/extconf.rb
|
38
38
|
- lib/gmp.rb
|
39
|
+
- test/gmp_tcong.rb
|
39
40
|
- test/gmp_tgcd.rb
|
40
41
|
- test/gmp_tlcm.rb
|
41
42
|
- test/gmp_tprintf.rb
|
@@ -68,6 +69,7 @@ files:
|
|
68
69
|
- test/tc_z_addmul.rb
|
69
70
|
- test/tc_z_basic.rb
|
70
71
|
- test/tc_z_exponentiation.rb
|
72
|
+
- test/tc_z_export_import.rb
|
71
73
|
- test/tc_z_functional_mappings.rb
|
72
74
|
- test/tc_z_gcd_lcm_invert.rb
|
73
75
|
- test/tc_z_hamdist.rb
|