gmp 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }