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 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