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 +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
|
}
|