gnu_mpc 0.8.2 → 0.9.0

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/.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
  }