gmp 0.1.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.
@@ -0,0 +1,47 @@
1
+ 0.1.6.2:
2
+ * Added optional argument to GMP::Z.to_s. Supply base as either a Fixnum or
3
+ a Symbol like :hex to get the string in a different base.
4
+
5
+ 0.1.6:
6
+ * Tested on OS X 10.5.8 with Ruby 1.9.1. It's a go!
7
+ * Tested on LinuxMint 7 with Ruby 1.8.7. It's a go! Ping me if you have Linux
8
+ problems.
9
+ * Added documentation.
10
+ * Cleaned up source.
11
+ * Added tests: tc_swap, tc_floor_ceil_truncate, tc_to_i_to_d
12
+
13
+ 0.1.5:
14
+ * Merged in reorg changes: Files like gmpz.c allow for documenting the C
15
+ extension methods.
16
+ * A good portion of the documentation has been written, may not be included
17
+ yet, but can be generated with
18
+ rdoc README.rdoc ext/*.c ext/*.h
19
+
20
+ 0.1.4:
21
+ * Fixed a lot of gemspec problems
22
+ * Many more tests
23
+ * Tested on OS X 10.5.8
24
+
25
+ 0.1.1:
26
+ * Attempting to revitalize through GitHub
27
+ * no changes to code yet
28
+ * modernizing files, eg with new ruby standards, towards a gem
29
+
30
+ 1.0:
31
+ * MPFR support
32
+ * better string conversion
33
+ * Debian package
34
+
35
+ alpha9:
36
+ * more GMP::F code
37
+ * GMP::Z division
38
+
39
+ alpha8:
40
+ * various minor changes
41
+
42
+ alpha7:
43
+ * more GMP::F code
44
+
45
+ alpha6:
46
+ * basic support for GMP::F
47
+ * various minor changes
data/INSTALL ADDED
@@ -0,0 +1,4 @@
1
+ To compile:
2
+ $ ./extconf.rb
3
+ $ make
4
+ $ make install
@@ -0,0 +1,257 @@
1
+ =gmp
2
+
3
+ gmp is library providing Ruby bindings to GMP library. Here is the introduction
4
+ paragraph at http://gmplib.org/#WHAT :
5
+
6
+ * "GMP is a free library for arbitrary precision arithmetic, operating on
7
+ signed integers, rational numbers, and floating point numbers. There is no
8
+ practical limit to the precision except the ones implied by the available
9
+ memory in the machine GMP runs on. GMP has a rich set of functions, and the
10
+ functions have a regular interface.
11
+
12
+ * The main target applications for GMP are cryptography applications and
13
+ research, Internet security applications, algebra systems, computational
14
+ algebra research, etc.
15
+
16
+ * GMP is carefully designed to be as fast as possible, both for small operands
17
+ and for huge operands. The speed is achieved by using fullwords as the basic
18
+ arithmetic type, by using fast algorithms, with highly optimised assembly
19
+ code for the most common inner loops for a lot of CPUs, and by a general
20
+ emphasis on speed.
21
+
22
+ * GMP is faster than any other bignum library. The advantage for GMP increases
23
+ with the operand sizes for many operations, since GMP uses asymptotically
24
+ faster algorithms.
25
+
26
+ * The first GMP release was made in 1991. It is continually developed and
27
+ maintained, with a new release about once a year.
28
+
29
+ * GMP is distributed under the GNU LGPL. This license makes the library free to
30
+ use, share, and improve, and allows you to pass on the result. The license
31
+ gives freedoms, but also sets firm restrictions on the use with non-free
32
+ programs.
33
+
34
+ * GMP is part of the GNU project. For more information about the GNU project,
35
+ please see the official GNU web site.
36
+
37
+ * GMP's main target platforms are Unix-type systems, such as GNU/Linux,
38
+ Solaris, HP-UX, Mac OS X/Darwin, BSD, AIX, etc. It also is known to work on
39
+ Windoze in 32-bit mode.
40
+
41
+ * GMP is brought to you by a team listed in the manual.
42
+
43
+ * GMP is carefully developed and maintained, both technically and legally. We
44
+ of course inspect and test contributed code carefully, but equally
45
+ importantly we make sure we have the legal right to distribute the
46
+ contributions, meaning users can safely use GMP. To achieve this, we will ask
47
+ contributors to sign paperwork where they allow us to distribute their work."
48
+
49
+ Only GMP 4 or newer is supported. The following environments have been tested by me:
50
+ gmp gem 0.1.4.2 on:
51
+ +-------------------------------------+-------------------+-----------+
52
+ | Platform | Ruby | GMP |
53
+ +-------------------------------------+-------------------+-----------+
54
+ | Cygwin on x86 | (MRI) Ruby 1.8.7 | GMP 4.3.1 |
55
+ | Linux (LinuxMint 7) on x86 (32-bit) | (MRI) Ruby 1.8.7 | GMP 4.3.1 |
56
+ | Mac OS X 10.5.7 on x86 (32-bit) | (MRI) Ruby 1.8.6 | GMP 4.3.1 |
57
+ | Mac OS X 10.5.7 on x86 (32-bit) | (MRI) Ruby 1.9.1 | GMP 4.3.1 |
58
+ +-------------------------------------+-------------------+-----------+
59
+
60
+ <b>Note:</b> To get this running on Mac OS X (32-bit), I compiled GMP 4.3.1 with:
61
+ ./configure ABI=32 --disable-dependency-tracking
62
+
63
+ =Authors
64
+
65
+ * Tomasz Wegrzanowski
66
+ * srawlins
67
+
68
+ =Classes
69
+
70
+ It provides module GMP with following classes:
71
+ * GMP::Z - infinite precision integer numbers
72
+ * GMP::Q - infinite precision rational numbers
73
+ * GMP::F - arbitrary precision floating point numbers
74
+
75
+ Numbers are created by using new().
76
+ Constructors can take following arguments:
77
+
78
+ GMP::Z.new()
79
+ GMP::Z.new(GMP::Z)
80
+ GMP::Z.new(FixNum)
81
+ GMP::Z.new(BigNum)
82
+ GMP::Z.new(String)
83
+ GMP::Q.new()
84
+ GMP::Q.new(GMP::Q)
85
+ GMP::Q.new(String)
86
+ GMP::Q.new(any GMP::Z initializer)
87
+ GMP::Q.new(any GMP::Z initializer, any GMP::Z initializer)
88
+ GMP::F.new()
89
+ GMP::F.new(GMP::Z, precision=0)
90
+ GMP::F.new(GMP::Q, precision=0)
91
+ GMP::F.new(GMP::F)
92
+ GMP::F.new(GMP::F, precision)
93
+ GMP::F.new(String, precision=0)
94
+ GMP::F.new(FixNum, precision=0)
95
+ GMP::F.new(BigNum, precision=0)
96
+ GMP::F.new(Float, precision=0)
97
+
98
+ You can also call them as:
99
+ GMP.Z(args)
100
+ GMP.Q(args)
101
+ todo GMP.F(args)
102
+
103
+ =Methods
104
+
105
+ GMP::Z, GMP::Q and GMP::F
106
+ + addition
107
+ - substraction
108
+ * multiplication
109
+ to_s convert to string. For GMP::Z, this method takes
110
+ one optional argument, a base. The base can be a
111
+ Fixnum in the ranges [2, 62] or [-36, -2] or a
112
+ Symbol: :bin, :oct, :dec, or :hex.
113
+ -@ negation
114
+ neg! in-place negation
115
+ abs absolute value
116
+ asb! in-place absolute value
117
+ coerce promotion of arguments
118
+ == equality test
119
+ <=>,>=,>,<=,< comparisions
120
+ class methods of GMP::Z
121
+ fac(n) factorial of n
122
+ fib(n) nth fibonacci number
123
+ pow(n,m) n to mth power
124
+ GMP::Z and GMP::Q
125
+ swap efficiently swap contents of two objects, there
126
+ is no GMP::F.swap because various GMP::F objects
127
+ may have different precisions, which would make
128
+ them unswapable
129
+ GMP::Z
130
+ .add! in-place addition
131
+ .sub! in-place subtraction
132
+ tdiv,fdiv,cdiv truncate, floor and ceil division
133
+ tmod,fmod,cmod truncate, floor and ceil modulus
134
+ .[],[]= testing and setting bits (as booleans)
135
+ scan0,scan1 starting at bitnr (1st arg), scan for a 0 or 1
136
+ (respectively), then return the index of the
137
+ first instance.
138
+ com 2's complement
139
+ com! in-place 2's complement
140
+ &,|,^ logical operations: and, or, xor
141
+ ** power
142
+ powmod power modulo
143
+ even? is even
144
+ odd? is odd
145
+ << shift left
146
+ >> shift right, floor
147
+ tshr shift right, truncate
148
+ lastbits_pos(n) last n bits of object, modulo if negative
149
+ lastbits_sgn(n) last n bits of object, preserve sign
150
+ power? is perfect power
151
+ square? is perfect square
152
+ sqrt square root
153
+ sqrt! change the object into its square root
154
+ sqrtrem square root, remainder
155
+ root(n) nth root
156
+ jacobi jacobi symbol
157
+ legendre legendre symbol
158
+ probab_prime? 0 if composite, 1 if probably prime, 2 if
159
+ certainly prime
160
+ nextprime next *probable* prime
161
+ nextprime! change the object into its next *probable* prime
162
+ popcount the number of bits equal to 1
163
+ to_i convert to FixNum or BigNum
164
+ remove(n) remove all occurences of factor n
165
+ GMP::Q and GMP::F
166
+ / division
167
+ GMP::Q
168
+ num numerator
169
+ den denominator
170
+ inv inversion
171
+ inv! in-place inversion
172
+ floor,ceil,trunc nearest integer
173
+ class methods of GMP::F
174
+ default_prec get default precision
175
+ default_prec= set default precision
176
+ GMP::F
177
+ prec get precision
178
+ floor,ceil,trunc nearest integer, GMP::F is returned, not GMP::Z
179
+ floor!,ceil!,trunc! in-place nearest integer
180
+ GMP::F (only if MPFR is available)
181
+ exp e^object
182
+ expm1 the same as (object.exp) - 1, with better precision
183
+ log natural logarithm of object
184
+ log2 binary logarithm of object
185
+ log10 decimal logarithm of object
186
+ log1p the same as (object + 1).log, with better precision
187
+ sqrt square root of the object
188
+ cos \
189
+ sin |
190
+ tan |
191
+ acos |
192
+ asin |
193
+ atan | trigonometric functions
194
+ cosh | of the object
195
+ sinh |
196
+ tanh |
197
+ aconh |
198
+ asinh |
199
+ atanh /
200
+ nan? \
201
+ infinite? | type of floating point number
202
+ finite? |
203
+ number? /
204
+ ** power
205
+
206
+ =Known Issues
207
+
208
+ * GMP::Z#pow does not appear to be working at all. Looking at the code, I don't
209
+ think it ever did.
210
+
211
+ =Precision
212
+
213
+ Precision can be explicitely set as second argument for GMP::F.new().
214
+
215
+ If there is no explicit precision, highest precision of all GMP::F arguments is
216
+ used. That doesn't ensure that result will be exact. For details, consult any
217
+ paper about floating point arithmetics.
218
+
219
+ Default precision can be explicitely set by passing 0 to GMP::F.new(). In
220
+ particular, you can set precision of copy of GMP::F object by:
221
+ new_obj = GMP::F.new(old_obj, 0)
222
+
223
+ Precision argument, and default_precision will be rounded up to whatever GMP
224
+ thinks is appropriate.
225
+
226
+ =Todo
227
+
228
+ These are inherited from Tomasz. I will go through these and see which are
229
+ still relevant.
230
+
231
+ * mpz_fits_* and 31 vs. 32 integer variables
232
+ * all appropriate module and class methods if there are any to add
233
+ * fix all sign issues (don't know what these are)
234
+ * floats with precision control
235
+ * random numbers
236
+ * to_s vs. inspect
237
+ * check if mpz_addmul_ui would optimize some statements
238
+ * some system that allows using denref and numref as normal ruby objects
239
+ * should we allocate global temporary variables like Perl GMP does?
240
+ * takeover code that replaces all Bignums with GMP::Z
241
+ * better bignum parser
242
+ * zero-copy method for strings generation
243
+ * put rb_raise into nice macros
244
+ * benchmarks against Python GMP and Perl GMP
245
+ * dup methods
246
+ * integrate F into system
247
+ * should Z.[] bits be 0/1 or true/false, 0 is true, what might badly surprise users
248
+ * seriously investigate Ruby Makefile-making system
249
+ * any2small_integer()
250
+ * check asm output, especially local memory efficiency
251
+ * it might be better to use `register' for some local variables
252
+ * powm with negative exponents
253
+ * check if different sorting of operatations gives better cache usage
254
+ * GMP::* op RubyFloat and RubyFloat op GMP::*
255
+ * sort checks
256
+ * check all new GMP4 operations
257
+ * GMP::Q.to_s(base), GMP::F.to_s(base)
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mkmf'
4
+
5
+ dir_config('gmp')
6
+ dir_config('mpfr')
7
+
8
+ ok = true
9
+ unless have_header('gmp.h')
10
+ $stderr.puts "can't find gmp.h, try --with-gmp-include=<path>"
11
+ ok = false
12
+ end
13
+
14
+ unless have_library('gmp', '__gmpz_init')
15
+ $stderr.puts "can't find -lgmp, try --with-gmp-lib=<path>"
16
+ ok = false
17
+ end
18
+
19
+ if (have_header('mpfr.h') and
20
+ have_header('mpf2mpfr.h') and
21
+ have_library('mpfr', 'mpfr_init'))
22
+ $CFLAGS += ' -DMPFR'
23
+ end
24
+
25
+ $CFLAGS += ' -Wall -W -O6 -g'
26
+ if ok
27
+ create_makefile('gmp')
28
+ else
29
+ raise "Unable to build, correct above errors and rerun"
30
+ end
@@ -0,0 +1,195 @@
1
+ /*
2
+ * gmp.c
3
+ *
4
+ * This file contains everything you would expect from a C extension.
5
+ */
6
+
7
+ #include <ruby_gmp.h>
8
+
9
+ VALUE mGMP, cGMP_Z, cGMP_Q, cGMP_F;
10
+
11
+ void r_gmpz_free(void *ptr) { mpz_clear (ptr); free (ptr); }
12
+ void r_gmpq_free(void *ptr) { mpq_clear (ptr); free (ptr); }
13
+ void r_gmpf_free(void *ptr) { mpf_clear (ptr); free (ptr); }
14
+
15
+ static void mpq_str_set(MP_RAT *ROP, char *str)
16
+ {
17
+ int i=0;
18
+
19
+ while (str[i] && str[i] != '/')
20
+ i++;
21
+
22
+ if (str[i])
23
+ {
24
+ str[i] = 0; /* You didn't see that :) */
25
+ mpz_set_str (mpq_numref(ROP), str, 0);
26
+ str[i] = '/';
27
+ mpz_set_str (mpq_denref(ROP), str+i+1, 0);
28
+ } else {
29
+ mpz_set_str (mpq_numref(ROP), str, 0);
30
+ mpz_set_ui (mpq_denref(ROP), 1);
31
+ }
32
+ mpq_canonicalize (ROP);
33
+ }
34
+
35
+ static VALUE r_gmpq_initialize(int argc, VALUE *argv, VALUE self)
36
+ {
37
+ MP_RAT *self_val, *arg_val;
38
+
39
+ if (argc != 0) {
40
+ mpq_get_struct(self, self_val);
41
+ if (argc == 1 && GMPQ_P(argv[0])) {
42
+ mpq_get_struct(argv[0], arg_val);
43
+ mpq_set (self_val, arg_val);
44
+ } else if (argc == 1 && STRING_P(argv[0])) {
45
+ mpq_str_set (self_val, STR2CSTR(argv[0]));
46
+ } else {
47
+ mpz_set_value (mpq_numref(self_val), argv[0]);
48
+ if (argc == 2) {
49
+ mpz_set_value (mpq_denref(self_val), argv[1]);
50
+ mpq_canonicalize(self_val);
51
+ }
52
+ }
53
+ }
54
+ return Qnil;
55
+ }
56
+
57
+ /* don't pass GMP::F here, it should be handled separately */
58
+ void mpf_set_value(MP_FLOAT *self_val, VALUE arg)
59
+ {
60
+ MP_RAT *arg_val_q;
61
+ MP_INT *arg_val_z;
62
+
63
+ if (GMPQ_P(arg)) {
64
+ mpq_get_struct(arg, arg_val_q);
65
+ mpf_set_q(self_val, arg_val_q);
66
+ } else if (GMPZ_P(arg)) {
67
+ mpz_get_struct(arg, arg_val_z);
68
+ mpf_set_z(self_val, arg_val_z);
69
+ } else if (FLOAT_P(arg)) {
70
+ mpf_set_d(self_val, NUM2DBL(arg));
71
+ } else if (FIXNUM_P(arg)) {
72
+ mpf_set_si(self_val, FIX2INT(arg));
73
+ } else if (STRING_P(arg)) {
74
+ if (mpf_set_str(self_val, STR2CSTR(arg), 10) == -1) {
75
+ rb_raise(rb_eRuntimeError, "Badly formatted string");
76
+ }
77
+ } else if (BIGNUM_P(arg)) {
78
+ #if 1 /* GMP3 code */
79
+ mpz_temp_from_bignum(arg_val_z, arg);
80
+ mpf_set_z(self_val, arg_val_z);
81
+ mpz_temp_free(arg_val_z);
82
+ #endif
83
+ } else {
84
+ rb_raise(rb_eTypeError, "Don't know how to convert %s into GMP::F", rb_class2name(rb_class_of(arg)));
85
+ }
86
+ }
87
+
88
+ static VALUE r_gmpz_coerce(VALUE self, VALUE arg)
89
+ {
90
+ return rb_assoc_new(r_gmpzsg_new(1, &arg, cGMP_Z), self);
91
+ }
92
+
93
+ static VALUE r_gmpq_coerce(VALUE self, VALUE arg)
94
+ {
95
+ return rb_assoc_new(r_gmpqsg_new(1, &arg, cGMP_Q), self);
96
+ }
97
+
98
+ static VALUE r_gmpf_coerce(VALUE self, VALUE arg)
99
+ {
100
+ return rb_assoc_new(r_gmpfsg_new(1, &arg, cGMP_F), self);
101
+ }
102
+
103
+ static VALUE r_gmpfsg_get_default_prec(VALUE klass)
104
+ {
105
+ (void)klass;
106
+ return INT2NUM(mpf_get_default_prec());
107
+ }
108
+
109
+ static VALUE r_gmpfsg_set_default_prec(VALUE klass, VALUE arg)
110
+ {
111
+ (void)klass;
112
+ if (FIXNUM_P(arg)) {
113
+ if (FIX2INT(arg) <= 0) {
114
+ rb_raise(rb_eRangeError, "prec must be positive");
115
+ }
116
+ mpf_set_default_prec (FIX2INT(arg));
117
+ } else {
118
+ rb_raise(rb_eTypeError, "prec must be FixNum");
119
+ }
120
+ return Qnil;
121
+ }
122
+
123
+ #include "gmpf.h"
124
+ #include "gmpq.h"
125
+ /* #include "gmpz.h" */
126
+ #include "takeover.h"
127
+
128
+ #define REGISTER_TAKEOVER(fname, ruby_fname, old_fname) \
129
+ rb_define_alias(rb_cFixnum, old_fname, ruby_fname); \
130
+ rb_define_method(rb_cFixnum, ruby_fname, takeover_fixnum_##fname, -1); \
131
+ rb_define_alias(rb_cBignum, old_fname, ruby_fname); \
132
+ rb_define_method(rb_cBignum, ruby_fname, takeover_bignum_##fname, -1);
133
+
134
+ void Init_gmp() {
135
+ mGMP = rb_define_module("GMP");
136
+ rb_define_const(mGMP, "GMP_VERSION", rb_str_new2(gmp_version));
137
+
138
+ cGMP_Z = rb_define_class_under(mGMP, "Z", rb_cInteger);
139
+ init_gmpz();
140
+ rb_define_method(cGMP_Z, "coerce", r_gmpz_coerce, 1);
141
+ /*
142
+ rb_define_method(cGMP_Z, "gcd", r_gmpz_gcd, 1);
143
+ rb_define_method(cGMP_Z, "lcm", r_gmpz_lcm, 1);
144
+ */
145
+
146
+ cGMP_Q = rb_define_class_under (mGMP, "Q", rb_cNumeric);
147
+ init_gmpq();
148
+ rb_define_method(cGMP_Q, "initialize", r_gmpq_initialize, -1);
149
+ rb_define_method(cGMP_Q, "coerce", r_gmpq_coerce, 1);
150
+ rb_define_method(cGMP_Q, "num", r_gmpq_num, 0);
151
+ rb_define_method(cGMP_Q, "den", r_gmpq_den, 0);
152
+
153
+ cGMP_F = rb_define_class_under (mGMP, "F", rb_cNumeric);
154
+ init_gmpf();
155
+ rb_define_singleton_method(cGMP_F, "default_prec", r_gmpfsg_get_default_prec, 0);
156
+ rb_define_singleton_method(cGMP_F, "default_prec=", r_gmpfsg_set_default_prec, 1);
157
+ rb_define_method(cGMP_F, "coerce", r_gmpf_coerce, 1); // new method - testing
158
+
159
+ /* rb_define_method(cGMP_F, "cmpabs", r_gmpf_cmpabs, 1);*/
160
+
161
+ #ifdef MPFR
162
+ rb_define_method(cGMP_F, "exp", r_gmpfr_exp, 0);
163
+ rb_define_method(cGMP_F, "log", r_gmpfr_log, 0);
164
+ rb_define_method(cGMP_F, "sqrt", r_gmpfr_sqrt, 0);
165
+ rb_define_method(cGMP_F, "cos", r_gmpfr_cos, 0);
166
+ rb_define_method(cGMP_F, "sin", r_gmpfr_sin, 0);
167
+ rb_define_method(cGMP_F, "tan", r_gmpfr_tan, 0);
168
+ rb_define_method(cGMP_F, "acos", r_gmpfr_acos, 0);
169
+ rb_define_method(cGMP_F, "asin", r_gmpfr_asin, 0);
170
+ rb_define_method(cGMP_F, "atan", r_gmpfr_atan, 0);
171
+ rb_define_method(cGMP_F, "cosh", r_gmpfr_cosh, 0);
172
+ rb_define_method(cGMP_F, "sinh", r_gmpfr_sinh, 0);
173
+ rb_define_method(cGMP_F, "tanh", r_gmpfr_tanh, 0);
174
+ rb_define_method(cGMP_F, "acosh", r_gmpfr_acosh, 0);
175
+ rb_define_method(cGMP_F, "asinh", r_gmpfr_asinh, 0);
176
+ rb_define_method(cGMP_F, "atanh", r_gmpfr_atanh, 0);
177
+ rb_define_method(cGMP_F, "log1p", r_gmpfr_log1p, 0);
178
+ rb_define_method(cGMP_F, "expm1", r_gmpfr_expm1, 0);
179
+ rb_define_method(cGMP_F, "log2", r_gmpfr_log2, 0);
180
+ rb_define_method(cGMP_F, "log10", r_gmpfr_log10, 0);
181
+
182
+ rb_define_method(cGMP_F, "nan?", r_gmpfr_nan_p, 0);
183
+ rb_define_method(cGMP_F, "infinite?", r_gmpfr_inf_p, 0);
184
+ rb_define_method(cGMP_F, "finite?", r_gmpfr_fin_p, 0);
185
+ rb_define_method(cGMP_F, "number?", r_gmpfr_number_p, 0);
186
+
187
+ rb_define_method(cGMP_F, "**", r_gmpfr_pow, 1);
188
+ #endif /* MPFR */
189
+ // more
190
+
191
+ REGISTER_TAKEOVER(and, "&", "old_and")
192
+ REGISTER_TAKEOVER(or, "|", "old_or")
193
+ REGISTER_TAKEOVER(xor, "^", "old_xor")
194
+ /* takeover cmpabs ? */
195
+ }