gmp 0.6.17 → 0.6.19
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 +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
|