gnu_mpc 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --seed 11213
@@ -0,0 +1,2 @@
1
+ --markup markdown
2
+ ext/*.c
data/CHANGELOG CHANGED
@@ -1,5 +1,27 @@
1
- * v 0.8.1
2
- * Added MPC#/, MPC#div
3
- * Added MPC#log10
4
- * v 0.8.0
5
- * Most things
1
+ ### 0.9.0
2
+
3
+ * documented MPC#proj
4
+ * added MPC#arg, with documentation, and tests
5
+ * added MPC#fma, wtih documentation, and tests
6
+ * added MPC#prec2, with tests
7
+ * added GMP::RandState#mpc_urandom, with tests
8
+ * added MPC#** and MPC#pow, with tests
9
+ * MPC#real and MPC#imag now take an optional precision, for the result.
10
+ * added tests for `#new` args, and fixed `#new(value, real_prec, imag_prec)` bug
11
+ * MPC#sub now accepts hash arguments (other bin-ops soon!)
12
+ * Bumped rspec and converting tests to just use expect().
13
+ * Travis is good.
14
+ * For Travis, whose VMs can only reach MPC 0.9-4, we know have support for MPC 0.9
15
+
16
+ ### 0.8.2
17
+
18
+ * Added MPC#mul_i with tests
19
+
20
+ ### 0.8.1
21
+
22
+ * Added MPC#/, MPC#div
23
+ * Added MPC#log10
24
+
25
+ ### 0.8.0
26
+
27
+ * Most things
data/Gemfile CHANGED
@@ -9,9 +9,11 @@ end
9
9
  group :development do
10
10
  gem 'yard'
11
11
  gem 'redcarpet'
12
- if RUBY_PLATFORM =~ /darwin/i
12
+
13
+ group :darwin do
13
14
  gem 'rb-fsevent', :require => false
14
15
  end
16
+
15
17
  gem 'guard-rspec'
16
18
  gem 'guard-shell'
17
19
  end
data/README.md CHANGED
@@ -6,6 +6,47 @@ This gem provides Ruby bindings to the GNU MPC library.
6
6
  Methods
7
7
  =======
8
8
 
9
+ "Initialization" Methods
10
+ ------------------------
11
+
12
+ MPC.new(7) # (7,0)
13
+ MPC.new(7, 32) # (7,0) with precision 32
14
+ MPC#prec # precision if real and imag precisions are the same, 0 otherwise
15
+ MPC#prec2 # real and imaginary precisions, as a 2-element Array
16
+
17
+ Projection and Decomposing Methods
18
+ ----------------------------------
19
+
20
+ ```ruby
21
+ MPC#real # real part
22
+ MPC#imag # imaginary part
23
+ MPC#arg # argument
24
+ MPC#proj # projection
25
+ ```
26
+
27
+ Basic Arithmetic Methods
28
+ ------------------------
29
+
30
+ ```ruby
31
+ MPC#add(w) # add with w
32
+ MPC#sub(w) # difference with w
33
+ MPC#mul(w) # multiply with w
34
+ MPC#div(w) # divide by w
35
+ MPC#fma(w,x) # multiple by w, then add with x
36
+ ```
37
+
38
+ Power and Logarithm Methods
39
+ ---------------------------
40
+
41
+ ```ruby
42
+ MPC#sqrt # square root
43
+ MPC#pow(w) # raise to the power w
44
+ MPC#** w # raise to the power w
45
+ MPC#exp # exponential
46
+ MPC#log # natural logarithm
47
+ MPC#log10 # base-10 logarithm
48
+ ```
49
+
9
50
  Trigonometric Methods
10
51
  ---------------------
11
52
 
@@ -23,13 +64,27 @@ MPC#acos # inverse cosine
23
64
  MPC#atan # inverse tangent
24
65
  ```
25
66
 
26
- Each of these methods accepts optional arguments to specify the rounding mode, and precision, in the following fashions:
67
+ Miscellaneous Functions
68
+ -----------------------
69
+
70
+ ```ruby
71
+ GMP::RandState#mpc_urandom # uniformly distributed random complex number within
72
+ # [0,1] x [0,1]
73
+ ```
74
+
75
+ ...
76
+
77
+ Each of these methods accepts optional arguments to specify the rounding mode,
78
+ and precision, in the following fashions:
27
79
 
28
80
  ```
29
81
  z = MPC.new(0, 1)
30
- z.sin() # default rounding mode; precision of the receiver is applied to the return value
31
- z.sin(MPC::MPC_RNDZZ) # MPC_RNDZZ rounding mode; precision of the receiver is applied to the return value
32
- z.sin(MPC::MPC_RNDNN, 64) # MPC_RNDNN rounding mode; precision of both real and imaginary parts of return value is 64
82
+ z.sin() # default rounding mode; precision of the receiver is
83
+ # applied to the return value
84
+ z.sin(MPC::MPC_RNDZZ) # MPC_RNDZZ rounding mode; precision of the receiver
85
+ # is applied to the return value
86
+ z.sin(MPC::MPC_RNDNN, 64) # MPC_RNDNN rounding mode; precision of both real and
87
+ # imaginary parts of return value is 64
33
88
  z.sin(MPC::MPC_RNDNN, 64, 128) # MPC_RNDNN rounding mode; precision
34
89
  # of real part of return value is 64,
35
90
  # imaginary part is 128
@@ -44,4 +99,5 @@ z.sin(:pre_real => 64, :prec_imag => 128) # default rounding mode; precision of
44
99
  # imaginary part is 128
45
100
  ```
46
101
 
47
- Either the ordered list of arguments, or the options Hash may be passed; they cannot be mixed.
102
+ Either the ordered list of arguments, or the options Hash may be passed; they
103
+ cannot be mixed.
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require "rspec/core/rake_task"
4
4
  DEPENDENCIES_DIR = '/usr/local'
5
5
 
6
6
  task :clean do
7
- sh "cd ext && make clean"
7
+ sh "cd ext && make clean; echo"
8
8
  end
9
9
 
10
10
  task :extconf => [:clean] do
@@ -15,12 +15,20 @@ task :make => [:extconf] do
15
15
  sh "cd ext && make"
16
16
  end
17
17
 
18
- task :default => [:spec]
18
+ task :console do
19
+ require 'irb'
20
+ require File.join(File.dirname(__FILE__), 'lib', 'mpc')
21
+ ARGV.clear
22
+ IRB.start
23
+ end
19
24
 
20
25
  desc "Run all specs"
21
26
  RSpec::Core::RakeTask.new(:spec) do |t|
22
27
  end
23
28
 
29
+ task :default => [:ci]
30
+ task :ci => [:make, :spec]
31
+
24
32
  namespace :dependencies do
25
33
  task :list do
26
34
  suffix = (DEPENDENCIES_DIR.size+1)..-1
@@ -38,7 +46,7 @@ namespace :dependencies do
38
46
  end
39
47
 
40
48
  def gmp_opt
41
- version = ENV['GMP'] || '5.0.5'
49
+ version = ENV['GMP'] || '5.1.3'
42
50
  '--with-gmp-dir='+File.join(DEPENDENCIES_DIR, "gmp-#{version}")
43
51
  end
44
52
 
@@ -37,7 +37,11 @@ unless have_macro('SIZEOF_INTPTR_T')
37
37
  check_sizeof('intptr_t')
38
38
  end
39
39
 
40
- $CFLAGS += ' -Wall -W -O6 -g'
40
+ if try_compile('', '-O6')
41
+ $CFLAGS += ' -Wall -W -O6 -g'
42
+ else
43
+ $CFLAGS += ' -Wall -W -O3 -g'
44
+ end
41
45
 
42
46
  if not ok
43
47
  raise "Unable to build, correct above errors and rerun"
@@ -0,0 +1,54 @@
1
+ #include <ruby_mpc.h>
2
+
3
+ /**********************************************************************
4
+ * MPC Random Numbers *
5
+ **********************************************************************/
6
+
7
+ /*
8
+ * call-seq:
9
+ * rand_state.mpc_urandom()
10
+ *
11
+ * From the MPC Manual:
12
+ *
13
+ * Generate a uniformly distributed random complex in the unit square [0,1] x [0,1].
14
+ */
15
+ VALUE r_gmprandstate_mpc_urandom(int argc, VALUE *argv, VALUE self_val)
16
+ {
17
+ MP_RANDSTATE *self;
18
+ MP_COMPLEX *res;
19
+ VALUE res_val;
20
+ unsigned long prec = 0;
21
+
22
+ if (argc > 1)
23
+ rb_raise (rb_eArgError, "wrong # of arguments (%d for 0 or 1)", argc);
24
+
25
+ mprandstate_get_struct (self_val, self);
26
+
27
+ if (argc == 1) {
28
+ if (FIXNUM_P (argv[0])) {
29
+ if (FIX2INT (argv[0]) >= 2)
30
+ prec = FIX2INT (argv[0]);
31
+ else
32
+ rb_raise (rb_eRangeError, "prec must be at least 2");
33
+ } else {
34
+ rb_raise (rb_eTypeError, "prec must be a Fixnum");
35
+ }
36
+ }
37
+
38
+ mpc_make_struct (res_val, res);
39
+ if (prec == 0) { mpc_init2 (res, mpfr_get_default_prec()); }
40
+ else { mpc_init2 (res, prec); }
41
+
42
+ mpc_urandom (res, self);
43
+
44
+ return res_val;
45
+ }
46
+
47
+ void init_gmprandstate_mpc()
48
+ {
49
+ mGMP = rb_define_module("GMP");
50
+ cGMP_RandState = rb_define_class_under(mGMP, "RandState", rb_cObject);
51
+
52
+ // Complex Random Numbers
53
+ rb_define_method(cGMP_RandState, "mpc_urandom", r_gmprandstate_mpc_urandom, -1);
54
+ }
data/ext/mpc.c CHANGED
@@ -25,18 +25,18 @@ VALUE r_mpc_##name(int argc, VALUE *argv, VALUE self_val)
25
25
  { \
26
26
  MP_COMPLEX *self, *res; \
27
27
  VALUE rnd_mode_val; \
28
- VALUE res_real_prec_val, res_imag_prec_val; \
28
+ VALUE res_real_prec_val, res_imag_prec_val; \
29
29
  VALUE res_val; \
30
30
  \
31
31
  mpfr_prec_t real_prec, imag_prec; \
32
32
  mpfr_prec_t res_real_prec, res_imag_prec; \
33
33
  mpc_rnd_t rnd_mode; \
34
34
  \
35
- mpc_get_struct(self_val,self); \
36
- real_prec = mpfr_get_prec(mpc_realref(self)); \
37
- imag_prec = mpfr_get_prec(mpc_imagref(self)); \
35
+ mpc_get_struct (self_val, self); \
36
+ real_prec = mpfr_get_prec (mpc_realref (self)); \
37
+ imag_prec = mpfr_get_prec (mpc_imagref (self)); \
38
38
  \
39
- if (argc > 0 && TYPE(argv[0]) == T_HASH) { \
39
+ if (argc > 0 && TYPE (argv[0]) == T_HASH) { \
40
40
  rb_mpc_get_hash_arguments (&rnd_mode, &real_prec, &imag_prec, argv[0]); \
41
41
  res_real_prec = real_prec; \
42
42
  res_imag_prec = imag_prec; \
@@ -76,16 +76,22 @@ void r_mpc_set_default_args (VALUE rnd_mode_val, VALUE res_real_prec_val,
76
76
  }
77
77
 
78
78
  void rb_mpc_get_hash_arguments(mpc_rnd_t *rnd_mode, mpfr_prec_t *real_prec, mpfr_prec_t *imag_prec, VALUE hash) {
79
- VALUE rnd_mode_val;
80
- VALUE real_prec_val;
81
- VALUE rounding_mode_sym, rounding_sym, round_sym, rnd_sym;
82
- VALUE precision_sym, prec_sym;
83
- rounding_mode_sym = ID2SYM(rb_intern("rounding_mode"));
84
- rounding_sym = ID2SYM(rb_intern("rounding"));
85
- round_sym = ID2SYM(rb_intern("round"));
86
- rnd_sym = ID2SYM(rb_intern("rnd"));
87
- precision_sym = ID2SYM(rb_intern("precision"));
88
- prec_sym = ID2SYM(rb_intern("prec"));
79
+ VALUE rnd_mode_val,
80
+ real_prec_val, imag_prec_val,
81
+ rounding_mode_sym, rounding_sym, round_sym, rnd_sym,
82
+ precision_sym, prec_sym,
83
+ real_precision_sym, real_prec_sym, imag_precision_sym, imag_prec_sym;
84
+
85
+ rounding_mode_sym = ID2SYM(rb_intern("rounding_mode"));
86
+ rounding_sym = ID2SYM(rb_intern("rounding"));
87
+ round_sym = ID2SYM(rb_intern("round"));
88
+ rnd_sym = ID2SYM(rb_intern("rnd"));
89
+ precision_sym = ID2SYM(rb_intern("precision"));
90
+ prec_sym = ID2SYM(rb_intern("prec"));
91
+ real_precision_sym = ID2SYM(rb_intern("real_precision"));
92
+ real_prec_sym = ID2SYM(rb_intern("real_prec"));
93
+ imag_precision_sym = ID2SYM(rb_intern("imag_precision"));
94
+ imag_prec_sym = ID2SYM(rb_intern("imag_prec"));
89
95
 
90
96
  rnd_mode_val = rb_hash_aref(hash, rounding_mode_sym);
91
97
  if (rnd_mode_val == Qnil) { rnd_mode_val = rb_hash_aref(hash, rounding_sym); }
@@ -97,14 +103,26 @@ void rb_mpc_get_hash_arguments(mpc_rnd_t *rnd_mode, mpfr_prec_t *real_prec, mpfr
97
103
  *rnd_mode = __gmp_default_rounding_mode;
98
104
  }
99
105
 
100
- /* TODO: allow prec */
101
- /* TODO: allow real_prec, imag_prec */
102
- real_prec_val = rb_hash_aref(hash, precision_sym);
103
- if (real_prec_val == Qnil) { real_prec_val = rb_hash_aref(hash, prec_sym); }
106
+ real_prec_val = rb_hash_aref (hash, precision_sym);
107
+ if (real_prec_val == Qnil) { real_prec_val = rb_hash_aref (hash, prec_sym); }
104
108
  if (real_prec_val != Qnil) {
109
+ if (! FIXNUM_P (real_prec_val)) rb_raise (rb_eTypeError, "real precision must be a Fixnum.");
105
110
  *real_prec = FIX2INT (real_prec_val);
106
111
  *imag_prec = FIX2INT (real_prec_val);
107
112
  } else {
113
+ real_prec_val = rb_hash_aref (hash, real_precision_sym);
114
+ if (real_prec_val == Qnil) { real_prec_val = rb_hash_aref (hash, real_prec_sym); }
115
+ if (real_prec_val != Qnil) {
116
+ if (! FIXNUM_P (real_prec_val)) rb_raise (rb_eTypeError, "real precision must be a Fixnum.");
117
+ *real_prec = FIX2INT (real_prec_val);
118
+ }
119
+
120
+ imag_prec_val = rb_hash_aref (hash, imag_precision_sym);
121
+ if (imag_prec_val == Qnil) { imag_prec_val = rb_hash_aref (hash, imag_prec_sym); }
122
+ if (imag_prec_val != Qnil) {
123
+ if (! FIXNUM_P (imag_prec_val)) rb_raise (rb_eTypeError, "imag precision must be a Fixnum.");
124
+ *imag_prec = FIX2INT (imag_prec_val);
125
+ }
108
126
  }
109
127
 
110
128
  /* TODO: disallow any other args. Throw a fit. */
@@ -121,7 +139,7 @@ int rb_base_type_range_check(VALUE base)
121
139
  else {
122
140
  if (FIXNUM_P (base))
123
141
  if (FIX2NUM (base) >= 2 && FIX2NUM (base) <= 36)
124
- base_val = FIX2NUM (base);
142
+ base_val = (int) FIX2NUM (base);
125
143
  else
126
144
  rb_raise (rb_eRangeError, "base must be between 2 and 36.");
127
145
  else
@@ -132,18 +150,54 @@ int rb_base_type_range_check(VALUE base)
132
150
 
133
151
  size_t rb_sig_figs_type_range_check(VALUE sig_figs)
134
152
  {
135
- size_t sig_figs_val;
136
- if (NIL_P (sig_figs)) { sig_figs_val = (size_t)(0); }
137
- else {
138
- if (FIXNUM_P (sig_figs))
139
- if (FIX2NUM (sig_figs) >= 0)
140
- sig_figs_val = (size_t)(FIX2NUM (sig_figs));
141
- else
142
- rb_raise (rb_eRangeError, "significant figures must be greater than or equal to 0.");
153
+ if (NIL_P (sig_figs)) {
154
+ return (size_t)(0);
155
+ }
156
+
157
+ if (FIXNUM_P (sig_figs))
158
+ if (FIX2NUM (sig_figs) >= 0)
159
+ return (size_t)(FIX2NUM (sig_figs));
143
160
  else
144
- rb_raise (rb_eTypeError, "significant figures must be a Fixnum.");
161
+ rb_raise (rb_eRangeError, "significant figures must be greater than or equal to 0.");
162
+ else
163
+ rb_raise (rb_eTypeError, "significant figures must be a Fixnum.");
164
+ }
165
+
166
+ void r_mpc_init_mpc_res_and_set_rnd_mode(
167
+ MP_COMPLEX **res, mpc_rnd_t *rnd_mode, /* return args */
168
+ int argc, VALUE *argv, MP_COMPLEX *self, const char *scan_fmt) /* args */
169
+ {
170
+ VALUE rnd_mode_val, res_real_prec_val, res_imag_prec_val;
171
+ mpfr_prec_t real_prec, imag_prec;
172
+ mpfr_prec_t res_real_prec, res_imag_prec;
173
+ int hash_idx;
174
+
175
+ real_prec = mpfr_get_prec (mpc_realref (self));
176
+ imag_prec = mpfr_get_prec (mpc_imagref (self));
177
+
178
+ if (scan_fmt[0] == '0') {
179
+ hash_idx = 0;
180
+ } else {
181
+ hash_idx = 1;
182
+ }
183
+
184
+ if (argc > hash_idx && TYPE (argv[hash_idx]) == T_HASH) {
185
+ rb_mpc_get_hash_arguments (rnd_mode, &real_prec, &imag_prec, argv[hash_idx]);
186
+ res_real_prec = real_prec;
187
+ res_imag_prec = imag_prec;
188
+ } else {
189
+ if (scan_fmt[0] == '0') {
190
+ rb_scan_args (argc, argv, scan_fmt, &rnd_mode_val, &res_real_prec_val, &res_imag_prec_val);
191
+ } else {
192
+ rb_scan_args (argc, argv, scan_fmt, 0, &rnd_mode_val, &res_real_prec_val, &res_imag_prec_val);
193
+ }
194
+
195
+ r_mpc_set_default_args (rnd_mode_val, res_real_prec_val, res_imag_prec_val,
196
+ rnd_mode, &res_real_prec, &res_imag_prec,
197
+ real_prec, imag_prec);
145
198
  }
146
- return sig_figs_val;
199
+
200
+ mpc_init3 (*res, res_real_prec, res_imag_prec);
147
201
  }
148
202
 
149
203
 
@@ -221,24 +275,24 @@ mpc_rnd_t r_get_mpc_rounding_mode(VALUE rnd)
221
275
  * * Bignum
222
276
  *
223
277
  * @example
224
- * MPC.new(5) #=> 5
225
- *
226
- * @todo support #new(c, prec)
227
- * @todo support #new(c, prec_r, prec_i)
278
+ * MPC.new(5) #=> (5,0)
279
+ * MPC.new(1.111) #=> (1.111,0)
280
+ * MPC.new(5, 32) #=> (5,0) with precision 32
281
+ * MPC.new([1.0, 1.0], 32, 64) #=> (1.0,1.0) with real precision 32, imag precision 64
228
282
  */
229
283
  VALUE r_mpcsg_new(int argc, VALUE *argv, VALUE klass)
230
284
  {
231
- MP_COMPLEX *res_val;
232
- VALUE res;
285
+ MP_COMPLEX *res;
286
+ VALUE res_val;
233
287
  (void)klass;
234
288
 
235
289
  if (argc > 3)
236
290
  rb_raise (rb_eArgError, "wrong # of arguments (%d for 0, 1, 2, or 3)", argc);
237
291
 
238
- mpc_make_struct (res, res_val);
239
- rb_obj_call_init (res, argc, argv);
292
+ mpc_make_struct (res_val, res);
293
+ rb_obj_call_init (res_val, argc, argv);
240
294
 
241
- return res;
295
+ return res_val;
242
296
  }
243
297
 
244
298
  VALUE r_mpc_initialize(int argc, VALUE *argv, VALUE self)
@@ -266,11 +320,11 @@ VALUE r_mpc_initialize(int argc, VALUE *argv, VALUE self)
266
320
  // OR argv[0] is value, argv[1] is rnd
267
321
  if (argc >= 2) {
268
322
  if (FIXNUM_P (argv[1])) {
269
- if (FIX2INT (argv[1]) >= 0)
323
+ if (FIX2INT (argv[1]) >= 2)
270
324
  prec = FIX2INT (argv[1]);
271
325
  else {
272
326
  mpc_init2 (self_val, mpfr_get_default_prec());
273
- rb_raise (rb_eRangeError, "prec must be non-negative");
327
+ rb_raise (rb_eRangeError, "prec must be at least 2");
274
328
  }
275
329
  } else if (MPCRND_P (argv[1])) {
276
330
  rnd_mode_val = r_get_mpc_rounding_mode(argv[1]);
@@ -315,8 +369,12 @@ VALUE r_mpc_initialize(int argc, VALUE *argv, VALUE self)
315
369
  // argc = 4 ==> argv[0] is value, argv[1] is prec_r, argv[2] is prec_i, argv[3] is rnd
316
370
  // TODO
317
371
 
318
- if (prec == 0)
372
+ if (prec == 0 && prec_re == 0)
373
+ /* precision was not specified */
319
374
  mpc_init2 (self_val, mpfr_get_default_prec());
375
+ else if (prec == 0)
376
+ /* precision was specified in two parts */
377
+ mpc_init3 (self_val, prec_re, prec_im);
320
378
  else
321
379
  mpc_init2 (self_val, prec);
322
380
 
@@ -345,7 +403,6 @@ void mpc_set_value(MP_COMPLEX *self_val, VALUE arg, mpc_rnd_t rnd)
345
403
  MP_FLOAT *arg_val_f, *arg_val_f_im;
346
404
  MP_COMPLEX *arg_val_c;
347
405
  VALUE arg_re, arg_im;
348
- int result;
349
406
 
350
407
  if (FIXNUM_P (arg)) {
351
408
  mpc_set_si(self_val, FIX2NUM (arg), rnd);
@@ -358,7 +415,10 @@ void mpc_set_value(MP_COMPLEX *self_val, VALUE arg, mpc_rnd_t rnd)
358
415
  mpz_get_struct (arg, arg_val_z);
359
416
  mpc_set_z (self_val, arg_val_z, rnd);
360
417
  // TODO STRING_P
361
- // TODO BIGNUM_P
418
+ } else if (BIGNUM_P (arg)) {
419
+ mpz_temp_from_bignum (arg_val_z, arg);
420
+ mpc_set_z (self_val, arg_val_z, rnd);
421
+ mpz_temp_free (arg_val_z);
362
422
  } else if (MPC_P (arg)) {
363
423
  mpc_get_struct (arg, arg_val_c);
364
424
  mpc_set (self_val, arg_val_c, rnd);
@@ -370,6 +430,7 @@ void mpc_set_value(MP_COMPLEX *self_val, VALUE arg, mpc_rnd_t rnd)
370
430
  //rb_raise(rb_eArgError, "Value Array must contain exactly two elements, the real value, and the imaginary value.");
371
431
  arg_re = rb_ary_shift(arg);
372
432
  arg_im = rb_ary_shift(arg);
433
+ // TODO allow different classes for re and im args
373
434
  if (FIXNUM_P (arg_re) && FIXNUM_P (arg_im)) {
374
435
  mpc_set_si_si (self_val, FIX2NUM (arg_re), FIX2NUM (arg_im), rnd);
375
436
  } else if (FLOAT_P (arg_re) && FLOAT_P (arg_im)) {
@@ -387,7 +448,12 @@ void mpc_set_value(MP_COMPLEX *self_val, VALUE arg, mpc_rnd_t rnd)
387
448
  mpf_get_struct (arg_im, arg_val_f_im);
388
449
  mpc_set_fr_fr (self_val, arg_val_f, arg_val_f_im, rnd);
389
450
  // TODO STRING_P
390
- // TODO BIGNUM_P
451
+ } else if (BIGNUM_P (arg_re) && BIGNUM_P (arg_im)) {
452
+ mpz_temp_from_bignum (arg_val_z, arg_re);
453
+ mpz_temp_from_bignum (arg_val_z_im, arg_im);
454
+ mpc_set_z_z (self_val, arg_val_z, arg_val_z_im, rnd);
455
+ mpz_temp_free (arg_val_z);
456
+ mpz_temp_free (arg_val_z_im);
391
457
  } else
392
458
  rb_raise(rb_eTypeError, "Real and imaginary values must be of the same type.");
393
459
  } else {
@@ -402,11 +468,27 @@ void mpc_set_value(MP_COMPLEX *self_val, VALUE arg, mpc_rnd_t rnd)
402
468
  * If the real and imaginary part of _c_ have the same precision, it is returned. Otherwise,
403
469
  * 0 is returned.
404
470
  */
405
- VALUE r_mpc_prec(VALUE self)
471
+ VALUE r_mpc_prec(VALUE self_val)
406
472
  {
407
- MP_COMPLEX *self_val;
408
- mpc_get_struct (self, self_val);
409
- return INT2NUM (mpc_get_prec (self_val));
473
+ MP_COMPLEX *self;
474
+ mpc_get_struct (self_val, self);
475
+ return INT2NUM (mpc_get_prec (self));
476
+ }
477
+
478
+ /*
479
+ * call-seq:
480
+ * c.prec2
481
+ *
482
+ * Returns the precision of the real part and imaginary part of _c_.
483
+ */
484
+ VALUE r_mpc_prec2(VALUE self_val)
485
+ {
486
+ MP_COMPLEX *self;
487
+ mpfr_prec_t prec_re;
488
+ mpfr_prec_t prec_im;
489
+ mpc_get_struct (self_val, self);
490
+ mpc_get_prec2 (&prec_re, &prec_im, self);
491
+ return rb_assoc_new (INT2NUM (prec_re), INT2NUM (prec_im));
410
492
  }
411
493
 
412
494
 
@@ -419,34 +501,29 @@ VALUE r_mpc_prec(VALUE self)
419
501
  * c.to_s
420
502
  *
421
503
  * Returns the decimal representation of the real part and imaginary part of _c_, as a String.
422
- *
423
- * @TODO type check, range check optional argument: rounding mode
424
504
  */
425
- VALUE r_mpc_to_s(int argc, VALUE *argv, VALUE self)
505
+ VALUE r_mpc_to_s(int argc, VALUE *argv, VALUE self_val)
426
506
  {
427
- MP_COMPLEX *self_val;
507
+ MP_COMPLEX *self;
428
508
  char *str;
429
- VALUE base, sig_figs, rnd_mode, res;
430
- int base_val;
431
- size_t sig_figs_val;
432
- mpc_rnd_t rnd_mode_val;
433
- //mp_exp_t exponent;
509
+ VALUE base_val, sig_figs_val, rnd_mode_val, res_val;
510
+ int base;
511
+ size_t sig_figs;
512
+ mpc_rnd_t rnd_mode;
434
513
 
435
- mpc_get_struct (self, self_val)
514
+ mpc_get_struct (self_val, self)
436
515
 
437
- rb_scan_args (argc, argv, "03", &base, &sig_figs, &rnd_mode);
438
- base_val = rb_base_type_range_check (base);
439
- sig_figs_val = rb_sig_figs_type_range_check (sig_figs);
440
- //if (NIL_P (sig_figs)) { sig_figs_val = (size_t)(0); }
441
- //else { sig_figs_val = (size_t)(FIX2NUM(sig_figs)); }
442
- if (NIL_P (rnd_mode)) { rnd_mode_val = r_mpc_default_rounding_mode; }
443
- else { rnd_mode_val = r_get_mpc_rounding_mode(rnd_mode); }
516
+ rb_scan_args (argc, argv, "03", &base_val, &sig_figs_val, &rnd_mode_val);
517
+ base = rb_base_type_range_check (base_val);
518
+ sig_figs = rb_sig_figs_type_range_check (sig_figs_val);
519
+ if (NIL_P (rnd_mode_val)) { rnd_mode = r_mpc_default_rounding_mode; }
520
+ else { rnd_mode = r_get_mpc_rounding_mode (rnd_mode_val); }
444
521
 
445
- str = mpc_get_str (base_val, sig_figs_val, self_val, rnd_mode_val);
446
- res = rb_str_new2 (str);
522
+ str = mpc_get_str (base, sig_figs, self, rnd_mode);
523
+ res_val = rb_str_new2 (str);
447
524
 
448
525
  mpc_free_str (str);
449
- return res;
526
+ return res_val;
450
527
  }
451
528
 
452
529
 
@@ -454,37 +531,37 @@ VALUE r_mpc_to_s(int argc, VALUE *argv, VALUE self)
454
531
  * Comparison Functions *
455
532
  *********************************************************************/
456
533
 
457
- int mpc_cmp_value(MP_COMPLEX *self_val, VALUE arg)
534
+ int mpc_cmp_value(MP_COMPLEX *self, VALUE arg_val)
458
535
  {
459
- MP_COMPLEX *arg_val;
536
+ MP_COMPLEX *arg;
460
537
  int result;
461
538
 
462
- if (MPC_P (arg)) {
463
- mpc_get_struct (arg,arg_val);
464
- return mpc_cmp (self_val, arg_val);
539
+ if (MPC_P (arg_val)) {
540
+ mpc_get_struct (arg_val, arg);
541
+ return mpc_cmp (self, arg);
465
542
  } else {
466
- mpc_temp_init (arg_val, mpc_get_prec (self_val));
467
- mpc_set_value (arg_val, arg, r_mpc_default_rounding_mode);
468
- result = mpc_cmp (self_val, arg_val);
469
- mpc_temp_free (arg_val);
543
+ mpc_temp_init (arg, mpc_get_prec (self));
544
+ mpc_set_value (arg, arg_val, r_mpc_default_rounding_mode);
545
+ result = mpc_cmp (self, arg);
546
+ mpc_temp_free (arg);
470
547
  return result;
471
548
  }
472
549
  }
473
550
 
474
- VALUE r_mpc_eq(VALUE self, VALUE arg)
551
+ VALUE r_mpc_eq(VALUE self_val, VALUE arg_val)
475
552
  {
476
- MP_COMPLEX *self_val;
477
- mpc_get_struct (self,self_val);
478
- return (mpc_cmp_value (self_val, arg) == 0) ? Qtrue : Qfalse;
553
+ MP_COMPLEX *self;
554
+ mpc_get_struct (self_val, self);
555
+ return (mpc_cmp_value (self, arg_val) == 0) ? Qtrue : Qfalse;
479
556
  }
480
557
 
481
- VALUE r_mpc_cmp(VALUE self, VALUE arg)
558
+ VALUE r_mpc_cmp(VALUE self_val, VALUE arg_val)
482
559
  {
483
- MP_COMPLEX *self_val;
560
+ MP_COMPLEX *self;
484
561
  int res;
485
- mpc_get_struct (self, self_val);
486
- res = mpc_cmp_value (self_val, arg);
487
- return rb_assoc_new(INT2FIX(MPC_INEX_RE(res)), INT2FIX (MPC_INEX_IM(res)));
562
+ mpc_get_struct (self_val, self);
563
+ res = mpc_cmp_value (self, arg_val);
564
+ return rb_assoc_new (INT2FIX (MPC_INEX_RE (res)), INT2FIX (MPC_INEX_IM (res)));
488
565
  }
489
566
 
490
567
 
@@ -497,74 +574,83 @@ VALUE r_mpc_cmp(VALUE self, VALUE arg)
497
574
  * MPC as self, calls mpc_fname on the contained mpc_t, whose
498
575
  * arguments are exactly (0) the return argument (an mpfr_t), (1) self,
499
576
  * and (2) the rounding mode.
500
- *
501
- * TODO FINISH!!!
502
577
  */
503
- #define DEFUN_COMPLEX2FLOAT(fname,mpz_fname) \
504
- static VALUE r_mpc_##fname(int argc, VALUE *argv, VALUE self) \
505
- { \
506
- MP_COMPLEX *self_val; \
507
- MP_FLOAT *res_val; \
508
- VALUE rnd_mode, res_prec, res; \
509
- mpfr_prec_t prec, res_prec_value; \
510
- mpc_rnd_t rnd_mode_val; \
578
+ #define DEFUN_COMPLEX2FLOAT(fname, prec_src) \
579
+ static VALUE r_mpc_##fname(int argc, VALUE *argv, VALUE self_val) \
580
+ { \
581
+ MP_COMPLEX *self; \
582
+ MP_FLOAT *res; \
583
+ VALUE rnd_mode_val, res_val, res_prec_val; \
584
+ \
585
+ mpfr_prec_t real_prec, imag_prec; \
586
+ mpfr_prec_t res_prec; \
587
+ mpc_rnd_t rnd_mode; \
588
+ \
589
+ mpc_get_struct(self_val, self); \
590
+ real_prec = mpfr_get_prec(mpc_realref(self)); \
591
+ imag_prec = mpfr_get_prec(mpc_imagref(self)); \
592
+ \
593
+ if (argc > 0 && TYPE(argv[0]) == T_HASH) { \
594
+ rb_mpc_get_hash_arguments (&rnd_mode, &real_prec, &imag_prec, argv[0]); \
595
+ res_prec = prec_src; \
596
+ } else { \
597
+ rb_scan_args (argc, argv, "02", &rnd_mode_val, &res_prec_val); \
598
+ \
599
+ if (NIL_P (rnd_mode_val)) { rnd_mode = __gmp_default_rounding_mode; } \
600
+ else { rnd_mode = r_mpc_get_rounding_mode(rnd_mode_val); } \
601
+ \
602
+ if (NIL_P (res_prec_val)) { res_prec = prec_src; } \
603
+ else { res_prec = FIX2INT(res_prec_val); } \
604
+ } \
605
+ \
606
+ mpf_make_struct (res_val, res); \
607
+ mpfr_init2 (res, res_prec); \
608
+ mpc_##fname (res, self, rnd_mode); \
609
+ \
610
+ return res_val; \
611
+ }
612
+
511
613
 
512
614
  /*
513
615
  * call-seq:
514
616
  * c.real
515
617
  * c.real(rounding_mode)
618
+ * c.real(rounding_mode, precision)
516
619
  *
517
620
  * Returns the real part of _c_ as a GMP_F float (an MPFR float, really).
518
621
  */
519
- VALUE r_mpc_real(int argc, VALUE *argv, VALUE self)
520
- {
521
- MP_COMPLEX *self_val;
522
- MP_FLOAT *real_val;
523
- VALUE rnd_mode, real;
524
- mpfr_prec_t pr=0, pi=0;
525
- mpc_rnd_t rnd_mode_val;
526
-
527
- mpc_get_struct (self, self_val);
528
-
529
- rb_scan_args (argc, argv, "01", &rnd_mode);
530
- if (NIL_P (rnd_mode)) { rnd_mode_val = r_mpc_default_rounding_mode; }
531
- else { rnd_mode_val = r_get_mpc_rounding_mode (rnd_mode); }
532
-
533
- mpf_make_struct (real, real_val);
534
- mpc_get_prec2 (&pr, &pi, self_val);
535
- mpfr_init2 (real_val, pr);
536
- mpc_real (real_val, self_val, rnd_mode_val);
537
- return real;
538
- }
622
+ DEFUN_COMPLEX2FLOAT(real, real_prec)
539
623
 
540
624
  /*
541
625
  * call-seq:
542
626
  * c.imag
543
627
  * c.imag(rounding_mode)
628
+ * c.imag(rounding_mode, precision)
544
629
  *
545
630
  * Returns the imaginary part of _c_ as a GMP_F float (an MPFR float, really).
546
631
  */
547
- VALUE r_mpc_imag(int argc, VALUE *argv, VALUE self)
548
- {
549
- MP_COMPLEX *self_val;
550
- MP_FLOAT *imag_val;
551
- VALUE rnd_mode, imag;
552
- mpfr_prec_t pr=0, pi=0;
553
- mpc_rnd_t rnd_mode_val;
554
-
555
- mpc_get_struct (self, self_val);
632
+ DEFUN_COMPLEX2FLOAT(imag, imag_prec)
556
633
 
557
- rb_scan_args (argc, argv, "01", &rnd_mode);
558
- if (NIL_P (rnd_mode)) { rnd_mode_val = r_mpc_default_rounding_mode; }
559
- else { rnd_mode_val = r_get_mpc_rounding_mode(rnd_mode); }
560
-
561
- mpf_make_struct (imag, imag_val);
562
- mpc_get_prec2 (&pr, &pi, self_val);
563
- mpfr_init2 (imag_val, pr);
564
- mpc_imag (imag_val, self_val, rnd_mode_val);
565
- return imag;
566
- }
634
+ /*
635
+ * call-seq:
636
+ * c.arg
637
+ * c.arg(rounding_mode)
638
+ * c.arg(rounding_mode, precision)
639
+ *
640
+ * Returns the argument of _c_ (with a branch cut along the negative real axis)
641
+ * as a GMP_F float (an MPFR float, really).
642
+ */
643
+ DEFUN_COMPLEX2FLOAT(arg, real_prec)
567
644
 
645
+ /*
646
+ * call-seq:
647
+ * c.proj
648
+ * c.proj(rounding_mode)
649
+ * c.proj(rounding_mode, precision)
650
+ *
651
+ * Returns the projection of _c_ onto the Riemann sphere as a GMP_F float (an
652
+ * MPFR float, really).
653
+ */
568
654
  MPC_SINGLE_FUNCTION(proj)
569
655
 
570
656
  /*********************************************************************
@@ -678,83 +764,64 @@ VALUE r_mpc_add_do_the_work(VALUE self_val, VALUE arg_val, mpc_rnd_t rnd_mode, m
678
764
  return res_val;
679
765
  }
680
766
 
681
- VALUE r_mpc_sub_do_the_work(VALUE self_val, VALUE arg_val, mpc_rnd_t rnd_mode, mpfr_prec_t res_real_prec, mpfr_prec_t res_imag_prec);
767
+ VALUE r_mpc_sub_compute(MP_COMPLEX *self, VALUE arg_val, VALUE res_val, mpc_rnd_t rnd_mode);
682
768
  VALUE r_mpc_sub(int argc, VALUE *argv, VALUE self_val)
683
769
  {
684
- MP_COMPLEX *self;
685
- VALUE rnd_mode_val;
686
- VALUE res_real_prec_val, res_imag_prec_val;
687
- VALUE arg_val;
688
-
689
- mpfr_prec_t real_prec, imag_prec;
690
- mpfr_prec_t res_real_prec, res_imag_prec;
770
+ MP_COMPLEX *self, *res;
771
+ VALUE res_val;
691
772
  mpc_rnd_t rnd_mode;
773
+ /* TODO: test for argc >= 1 */
774
+ VALUE arg_val = argv[0];
692
775
 
693
776
  mpc_get_struct(self_val,self);
694
- real_prec = mpfr_get_prec(mpc_realref(self));
695
- imag_prec = mpfr_get_prec(mpc_imagref(self));
696
-
697
- //if (argc > 0 && TYPE(argv[0]) == T_HASH) {
698
- // rb_mpc_get_hash_arguments (&rnd_mode, &real_prec, &imag_prec, argv[0]);
699
- //res_real_prec = real_prec;
700
- //res_imag_prec = imag_prec;
701
- //} else {
702
- rb_scan_args (argc, argv, "13", &arg_val, &rnd_mode_val, &res_real_prec_val, &res_imag_prec_val);
703
777
 
704
- r_mpc_set_default_args (rnd_mode_val, res_real_prec_val, res_imag_prec_val,
705
- &rnd_mode, &res_real_prec, &res_imag_prec,
706
- real_prec, imag_prec);
707
- //}
778
+ mpc_make_struct (res_val, res);
779
+ r_mpc_init_mpc_res_and_set_rnd_mode (&res, &rnd_mode, argc, argv, self, "13");
708
780
 
709
- //return res_val;
710
- return r_mpc_sub_do_the_work(self_val, arg_val, rnd_mode, res_real_prec, res_imag_prec);
781
+ return r_mpc_sub_compute (self, arg_val, res_val, rnd_mode);
711
782
  }
712
783
 
713
784
  VALUE r_mpc_sub2(VALUE self_val, VALUE arg_val)
714
785
  {
715
- MP_COMPLEX *self;
716
-
786
+ MP_COMPLEX *self, *res;
787
+ VALUE res_val;
717
788
  mpfr_prec_t res_real_prec, res_imag_prec;
718
789
 
719
- mpc_get_struct(self_val, self);
720
- res_real_prec = mpfr_get_prec(mpc_realref(self));
721
- res_imag_prec = mpfr_get_prec(mpc_imagref(self));
790
+ mpc_get_struct (self_val, self);
791
+ res_real_prec = mpfr_get_prec (mpc_realref (self));
792
+ res_imag_prec = mpfr_get_prec (mpc_imagref (self));
793
+
794
+ mpc_make_struct_init3 (res_val, res, res_real_prec, res_imag_prec);
722
795
 
723
- return r_mpc_sub_do_the_work(self_val, arg_val, MPC_RNDNN, res_real_prec, res_imag_prec);
796
+ return r_mpc_sub_compute (self, arg_val, res_val, r_mpc_default_rounding_mode);
724
797
  }
725
798
 
726
- VALUE r_mpc_sub_do_the_work(VALUE self_val, VALUE arg_val, mpc_rnd_t rnd_mode, mpfr_prec_t res_real_prec, mpfr_prec_t res_imag_prec) {
727
- MP_COMPLEX *self, *res, *arg_c;
799
+ VALUE r_mpc_sub_compute(MP_COMPLEX *self, VALUE arg_val, VALUE res_val, mpc_rnd_t rnd_mode) {
800
+ MP_COMPLEX *res, *arg_c;
728
801
  MP_INT *arg_z;
729
802
  MP_FLOAT *arg_f;
730
- VALUE res_val;
731
803
 
732
- mpc_get_struct(self_val,self);
804
+ mpc_get_struct(res_val, res);
733
805
 
734
806
  if (FIXNUM_P (arg_val)) {
735
- mpc_make_struct_init3 (res_val, res, res_real_prec, res_imag_prec);
736
807
  if (FIX2NUM (arg_val) >= 0) {
737
808
  mpc_sub_ui (res, self, FIX2NUM (arg_val), rnd_mode);
738
809
  } else {
739
810
  mpc_add_ui (res, self, -FIX2NUM (arg_val), rnd_mode);
740
811
  }
741
812
  } else if (BIGNUM_P (arg_val)) {
742
- mpc_make_struct_init3 (res_val, res, res_real_prec, res_imag_prec);
743
813
  mpz_temp_from_bignum (arg_z, arg_val);
744
814
  mpc_set_z (res, arg_z, MPC_RNDNN);
745
815
  mpz_temp_free (arg_z);
746
816
  mpc_sub (res, self, res, rnd_mode);
747
817
  } else if (GMPZ_P (arg_val)) {
748
- mpc_make_struct_init3 (res_val, res, res_real_prec, res_imag_prec);
749
818
  mpz_get_struct (arg_val, arg_z);
750
819
  mpc_set_z (res, arg_z, MPC_RNDNN);
751
820
  mpc_sub (res, self, res, rnd_mode);
752
821
  } else if (GMPF_P (arg_val)) {
753
- mpc_make_struct_init3 (res_val, res, res_real_prec, res_imag_prec);
754
822
  mpf_get_struct (arg_val, arg_f);
755
823
  mpc_sub_fr (res, self, arg_f, rnd_mode);
756
824
  } else if (MPC_P (arg_val)) {
757
- mpc_make_struct_init3 (res_val, res, res_real_prec, res_imag_prec);
758
825
  mpc_get_struct (arg_val, arg_c);
759
826
  mpc_sub (res, self, arg_c, rnd_mode);
760
827
  } else {
@@ -1057,7 +1124,65 @@ VALUE r_mpc_norm(int argc, VALUE *argv, VALUE self)
1057
1124
  MPC_SINGLE_FUNCTION(sqrt)
1058
1125
  MPC_SINGLE_FUNCTION(exp)
1059
1126
  MPC_SINGLE_FUNCTION(log)
1127
+ #if MPC_VERSION_MAJOR > 0
1060
1128
  MPC_SINGLE_FUNCTION(log10)
1129
+ #endif
1130
+
1131
+ VALUE r_mpc_pow_compute(MP_COMPLEX *self, VALUE arg_val, VALUE res_val, mpc_rnd_t rnd_mode);
1132
+ VALUE r_mpc_pow(int argc, VALUE *argv, VALUE self_val)
1133
+ {
1134
+ MP_COMPLEX *self, *res;
1135
+ mpc_rnd_t rnd_mode;
1136
+ VALUE res_val;
1137
+ /* TODO: test for argc >= 1 */
1138
+ VALUE arg_val = argv[0];
1139
+ mpc_get_struct (self_val, self);
1140
+ mpc_make_struct (res_val, res);
1141
+ r_mpc_init_mpc_res_and_set_rnd_mode (&res, &rnd_mode, argc, argv, self, "13");
1142
+
1143
+ return r_mpc_pow_compute(self, arg_val, res_val, rnd_mode);
1144
+ }
1145
+
1146
+ VALUE r_mpc_pow2(VALUE self_val, VALUE arg_val)
1147
+ {
1148
+ MP_COMPLEX *self, *res;
1149
+ mpc_rnd_t rnd_mode;
1150
+ VALUE res_val;
1151
+ mpc_get_struct (self_val, self);
1152
+ mpc_make_struct (res_val, res);
1153
+ mpc_init3 (res, mpfr_get_prec (mpc_realref (self)), mpfr_get_prec (mpc_imagref (self)));
1154
+ rnd_mode = r_mpc_default_rounding_mode;
1155
+
1156
+ return r_mpc_pow_compute(self, arg_val, res_val, rnd_mode);
1157
+ }
1158
+
1159
+ VALUE r_mpc_pow_compute(MP_COMPLEX *self, VALUE arg_val, VALUE res_val, mpc_rnd_t rnd_mode) {
1160
+ MP_INT *arg_z;
1161
+ MP_FLOAT *arg_f;
1162
+ MP_COMPLEX *res;
1163
+
1164
+ mpc_get_struct (res_val, res);
1165
+
1166
+ if (FIXNUM_P (arg_val)) {
1167
+ mpc_pow_si (res, self, FIX2NUM (arg_val), rnd_mode);
1168
+ } else if (BIGNUM_P (arg_val)) {
1169
+ mpz_temp_from_bignum (arg_z, arg_val);
1170
+ mpc_pow_z (res, self, arg_z, rnd_mode);
1171
+ mpz_temp_free (arg_z);
1172
+ } else if (GMPZ_P (arg_val)) {
1173
+ mpz_get_struct (arg_val, arg_z);
1174
+ mpc_pow_z (res, self, arg_z, rnd_mode);
1175
+ } else if (FLOAT_P (arg_val)) {
1176
+ mpc_pow_d (res, self, NUM2DBL (arg_val), rnd_mode);
1177
+ } else if (GMPF_P (arg_val)) {
1178
+ mpf_get_struct (arg_val, arg_f);
1179
+ mpc_pow_fr (res, self, arg_f, rnd_mode);
1180
+ } else {
1181
+ typeerror(XBZFC);
1182
+ }
1183
+
1184
+ return res_val;
1185
+ }
1061
1186
 
1062
1187
  /*********************************************************************
1063
1188
  * Trigonometric Functions *
@@ -1069,7 +1194,7 @@ MPC_SINGLE_FUNCTION(log10)
1069
1194
  * z.sin(rounding_mode)
1070
1195
  *
1071
1196
  * Returns _sin(z)_, rounded according to `rounding_mode`.
1072
- * s3
1197
+ *
1073
1198
  */
1074
1199
  MPC_SINGLE_FUNCTION(sin)
1075
1200
  MPC_SINGLE_FUNCTION(cos)
@@ -1081,16 +1206,62 @@ MPC_SINGLE_FUNCTION(asin)
1081
1206
  MPC_SINGLE_FUNCTION(acos)
1082
1207
  MPC_SINGLE_FUNCTION(atan)
1083
1208
 
1209
+ /*
1210
+ * call-seq:
1211
+ * a.fma(b, c)
1212
+ * a.fma(b, c, rounding_mode)
1213
+ *
1214
+ * Returns _a*b + c_, rounded according to `rounding_mode`, not rounding until
1215
+ * the final calculation.
1216
+ *
1217
+ */
1218
+ VALUE r_mpc_fma(int argc, VALUE *argv, VALUE self_val)
1219
+ {
1220
+ MP_COMPLEX *self, *arg1, *arg2, *res;
1221
+ VALUE rnd_mode_val;
1222
+ VALUE res_real_prec_val, res_imag_prec_val;
1223
+ VALUE arg1_val, arg2_val, res_val;
1224
+
1225
+ mpfr_prec_t real_prec, imag_prec;
1226
+ mpfr_prec_t res_real_prec, res_imag_prec;
1227
+ mpc_rnd_t rnd_mode;
1228
+
1229
+ mpc_get_struct (self_val, self);
1230
+ real_prec = mpfr_get_prec (mpc_realref (self));
1231
+ imag_prec = mpfr_get_prec (mpc_imagref (self));
1232
+
1233
+ if (argc > 2 && TYPE(argv[2]) == T_HASH) {
1234
+ rb_scan_args (argc, argv, "21", &arg1_val, &arg2_val, &rnd_mode_val);
1235
+
1236
+ rb_mpc_get_hash_arguments (&rnd_mode, &real_prec, &imag_prec, argv[2]);
1237
+ res_real_prec = real_prec;
1238
+ res_imag_prec = imag_prec;
1239
+ } else {
1240
+ rb_scan_args (argc, argv, "23", &arg1_val, &arg2_val, &rnd_mode_val, &res_real_prec_val, &res_imag_prec_val);
1241
+
1242
+ r_mpc_set_default_args (rnd_mode_val, res_real_prec_val, res_imag_prec_val,
1243
+ &rnd_mode, &res_real_prec, &res_imag_prec,
1244
+ real_prec, imag_prec);
1245
+ }
1246
+
1247
+ mpc_get_struct (arg1_val, arg1);
1248
+ mpc_get_struct (arg2_val, arg2);
1249
+ mpc_make_struct_init3 (res_val, res, res_real_prec, res_imag_prec);
1250
+ mpc_fma (res, self, arg1, arg2, rnd_mode);
1251
+
1252
+ return res_val;
1253
+ }
1254
+
1084
1255
  void Init_mpc() {
1085
1256
  cMPC = rb_define_class ("MPC", rb_cNumeric);
1086
1257
 
1087
- rb_define_const (cMPC, "MPC_VERSION", rb_str_new2(MPC_VERSION_STRING));
1258
+ rb_define_const (cMPC, "MPC_VERSION", rb_str_new2(MPC_VERSION_STRING));
1088
1259
 
1089
1260
  // Initialization Functions and Assignment Functions
1090
1261
  rb_define_singleton_method (cMPC, "new", r_mpcsg_new, -1);
1091
1262
  rb_define_method (cMPC, "initialize", r_mpc_initialize, -1);
1092
1263
  rb_define_method (cMPC, "prec", r_mpc_prec, 0);
1093
- // TODO rb_define_method (cMPC, "prec2", r_mpc_prec, 0);
1264
+ rb_define_method (cMPC, "prec2", r_mpc_prec2, 0);
1094
1265
  // TODO rb_define_method (cMPC, "prec=", r_mpc_prec, 1);
1095
1266
 
1096
1267
  // Conversion Functions
@@ -1106,7 +1277,7 @@ void Init_mpc() {
1106
1277
  // Projection and Decomposing Functions
1107
1278
  rb_define_method (cMPC, "real", r_mpc_real, -1);
1108
1279
  rb_define_method (cMPC, "imag", r_mpc_imag, -1);
1109
- // TODO rb_define_method (cMPC, "arg", r_mpc_arg, 0);
1280
+ rb_define_method (cMPC, "arg", r_mpc_arg, -1);
1110
1281
  rb_define_method (cMPC, "proj", r_mpc_proj, -1);
1111
1282
 
1112
1283
  // Basic Arithmetic Functions
@@ -1120,7 +1291,7 @@ void Init_mpc() {
1120
1291
  rb_define_method (cMPC, "*", r_mpc_mul2, 1);
1121
1292
  rb_define_method (cMPC, "mul_i", r_mpc_mul_i, -1);
1122
1293
  rb_define_method (cMPC, "sqr", r_mpc_sqr, -1);
1123
- // TODO rb_define_method (cMPC, "fma", r_mpc_fma, 2);
1294
+ rb_define_method (cMPC, "fma", r_mpc_fma, -1);
1124
1295
  rb_define_method (cMPC, "div", r_mpc_div, -1);
1125
1296
  rb_define_method (cMPC, "/", r_mpc_div2, 1);
1126
1297
  rb_define_method (cMPC, "conj", r_mpc_conj, -1);
@@ -1131,10 +1302,13 @@ void Init_mpc() {
1131
1302
 
1132
1303
  // Power Functions and Logarithm
1133
1304
  rb_define_method (cMPC, "sqrt", r_mpc_sqrt, -1);
1134
- // TODO rb_define_method (cMPC, "**", r_mpc_pow, 1);
1135
- rb_define_method (cMPC, "exp", r_mpc_exp, -1);
1136
- rb_define_method (cMPC, "log", r_mpc_log, -1);
1305
+ rb_define_method (cMPC, "pow", r_mpc_pow, -1);
1306
+ rb_define_method (cMPC, "**", r_mpc_pow2, 1);
1307
+ rb_define_method (cMPC, "exp", r_mpc_exp, -1);
1308
+ rb_define_method (cMPC, "log", r_mpc_log, -1);
1309
+ #if MPC_VERSION_MAJOR > 0
1137
1310
  rb_define_method (cMPC, "log10", r_mpc_log10, -1);
1311
+ #endif
1138
1312
 
1139
1313
  // Trigonometric Functions
1140
1314
  rb_define_method (cMPC, "sin", r_mpc_sin, -1);
@@ -1151,8 +1325,6 @@ void Init_mpc() {
1151
1325
  // TODO rb_define_method (cMPC, "acosh", r_mpc_acosh, -1);
1152
1326
  // TODO rb_define_method (cMPC, "atanh", r_mpc_atanh, -1);
1153
1327
 
1154
- // Miscellaneous Functions
1155
- // TODO rb_define_method (cMPC, "urandom", r_mpc_urandom, 1);
1156
-
1157
- init_mpcrnd();
1328
+ init_mpcrnd ();
1329
+ init_gmprandstate_mpc ();
1158
1330
  }