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 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 badasses: [YARDoc](http://rubydoc.info/gems/gmp/frames).
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`, `#congruent?`, `#rootrem`, `#kronecker`, `#bin`, `#fib2`, `#lucnum`, `#lucnum2`, `#combit`, `#fits_x?`
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.17
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 00:00:00.000000000 Z
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