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 +2 -0
- data/.yardopts +2 -0
- data/CHANGELOG +27 -5
- data/Gemfile +3 -1
- data/README.md +61 -5
- data/Rakefile +11 -3
- data/ext/extconf.rb +5 -1
- data/ext/gmprandstate.c +54 -0
- data/ext/mpc.c +358 -186
- data/ext/mpcrnd.c +3 -3
- data/ext/ruby_gmp.h +4 -4
- data/ext/ruby_mpc.h +2 -0
- data/manual.md +40 -14
- data/manual.pdf +0 -0
- data/spec/acos_spec.rb +15 -15
- data/spec/add_args_spec.rb +21 -21
- data/spec/add_fr_spec.rb +22 -22
- data/spec/add_spec.rb +12 -12
- data/spec/arg_spec.rb +14 -0
- data/spec/asin_spec.rb +12 -12
- data/spec/atan_spec.rb +26 -26
- data/spec/fma_spec.rb +20 -0
- data/spec/imag_spec.rb +23 -0
- data/spec/log10_spec.rb +21 -13
- data/spec/mpc_single_function_args_spec.rb +6 -6
- data/spec/new_spec.rb +54 -23
- data/spec/pow_spec.rb +79 -0
- data/spec/prec_arguments_spec.rb +40 -0
- data/spec/prec_spec.rb +17 -0
- data/spec/sub_spec.rb +35 -2
- data/spec/urandom_spec.rb +14 -0
- metadata +16 -5
data/.rspec
ADDED
data/.yardopts
ADDED
data/CHANGELOG
CHANGED
@@ -1,5 +1,27 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
*
|
5
|
-
|
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
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
|
-
|
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
|
31
|
-
|
32
|
-
z.sin(MPC::
|
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
|
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 :
|
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.
|
49
|
+
version = ENV['GMP'] || '5.1.3'
|
42
50
|
'--with-gmp-dir='+File.join(DEPENDENCIES_DIR, "gmp-#{version}")
|
43
51
|
end
|
44
52
|
|
data/ext/extconf.rb
CHANGED
@@ -37,7 +37,11 @@ unless have_macro('SIZEOF_INTPTR_T')
|
|
37
37
|
check_sizeof('intptr_t')
|
38
38
|
end
|
39
39
|
|
40
|
-
|
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"
|
data/ext/gmprandstate.c
ADDED
@@ -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
|
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
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
101
|
-
|
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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
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 (
|
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
|
-
|
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)
|
225
|
-
*
|
226
|
-
*
|
227
|
-
*
|
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 *
|
232
|
-
VALUE
|
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 (
|
239
|
-
rb_obj_call_init (
|
292
|
+
mpc_make_struct (res_val, res);
|
293
|
+
rb_obj_call_init (res_val, argc, argv);
|
240
294
|
|
241
|
-
return
|
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]) >=
|
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
|
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
|
-
|
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
|
-
|
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
|
471
|
+
VALUE r_mpc_prec(VALUE self_val)
|
406
472
|
{
|
407
|
-
MP_COMPLEX *
|
408
|
-
mpc_get_struct (
|
409
|
-
return INT2NUM (mpc_get_prec (
|
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
|
505
|
+
VALUE r_mpc_to_s(int argc, VALUE *argv, VALUE self_val)
|
426
506
|
{
|
427
|
-
MP_COMPLEX *
|
507
|
+
MP_COMPLEX *self;
|
428
508
|
char *str;
|
429
|
-
VALUE
|
430
|
-
int
|
431
|
-
size_t
|
432
|
-
mpc_rnd_t
|
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 (
|
514
|
+
mpc_get_struct (self_val, self)
|
436
515
|
|
437
|
-
rb_scan_args (argc, argv, "03", &
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
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 (
|
446
|
-
|
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
|
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 *
|
534
|
+
int mpc_cmp_value(MP_COMPLEX *self, VALUE arg_val)
|
458
535
|
{
|
459
|
-
MP_COMPLEX *
|
536
|
+
MP_COMPLEX *arg;
|
460
537
|
int result;
|
461
538
|
|
462
|
-
if (MPC_P (
|
463
|
-
mpc_get_struct (arg
|
464
|
-
return mpc_cmp (
|
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 (
|
467
|
-
mpc_set_value (
|
468
|
-
result = mpc_cmp (
|
469
|
-
mpc_temp_free (
|
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
|
551
|
+
VALUE r_mpc_eq(VALUE self_val, VALUE arg_val)
|
475
552
|
{
|
476
|
-
MP_COMPLEX *
|
477
|
-
mpc_get_struct (self
|
478
|
-
return (mpc_cmp_value (
|
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
|
558
|
+
VALUE r_mpc_cmp(VALUE self_val, VALUE arg_val)
|
482
559
|
{
|
483
|
-
MP_COMPLEX *
|
560
|
+
MP_COMPLEX *self;
|
484
561
|
int res;
|
485
|
-
mpc_get_struct (
|
486
|
-
res = mpc_cmp_value (
|
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,
|
504
|
-
static VALUE r_mpc_##fname(int argc, VALUE *argv, VALUE
|
505
|
-
{
|
506
|
-
MP_COMPLEX *
|
507
|
-
MP_FLOAT *
|
508
|
-
VALUE
|
509
|
-
|
510
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
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
|
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
|
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
|
-
|
705
|
-
|
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
|
-
|
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
|
796
|
+
return r_mpc_sub_compute (self, arg_val, res_val, r_mpc_default_rounding_mode);
|
724
797
|
}
|
725
798
|
|
726
|
-
VALUE
|
727
|
-
MP_COMPLEX *
|
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(
|
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
|
-
*
|
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",
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1135
|
-
rb_define_method (cMPC, "
|
1136
|
-
rb_define_method (cMPC, "
|
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
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
init_mpcrnd();
|
1328
|
+
init_mpcrnd ();
|
1329
|
+
init_gmprandstate_mpc ();
|
1158
1330
|
}
|