Changeset View
Changeset View
Standalone View
Standalone View
knumber/knumber_float.cpp
Show All 10 Lines | |||||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | 13 | GNU General Public License for more details. | ||
14 | 14 | | |||
15 | You should have received a copy of the GNU General Public License | 15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | 17 | */ | ||
18 | 18 | | |||
19 | #include <config-kcalc.h> | | |||
20 | #include "knumber_integer.h" | 19 | #include "knumber_integer.h" | ||
21 | #include "knumber_float.h" | 20 | #include "knumber_float.h" | ||
22 | #include "knumber_fraction.h" | 21 | #include "knumber_fraction.h" | ||
23 | #include "knumber_error.h" | 22 | #include "knumber_error.h" | ||
24 | #include <QScopedArrayPointer> | 23 | #include <QScopedArrayPointer> | ||
25 | #include <QDebug> | 24 | #include <QDebug> | ||
26 | #include <math.h> | 25 | #include <math.h> | ||
27 | 26 | | |||
Show All 9 Lines | |||||
37 | #endif | 36 | #endif | ||
38 | 37 | | |||
39 | #ifndef isnan | 38 | #ifndef isnan | ||
40 | #define isnan(x) ((x) != (x)) | 39 | #define isnan(x) ((x) != (x)) | ||
41 | #endif | 40 | #endif | ||
42 | 41 | | |||
43 | namespace detail { | 42 | namespace detail { | ||
44 | 43 | | |||
45 | #ifdef KNUMBER_USE_MPFR | | |||
46 | const mpfr_rnd_t knumber_float::rounding_mode = MPFR_RNDN; | 44 | const mpfr_rnd_t knumber_float::rounding_mode = MPFR_RNDN; | ||
47 | const mpfr_prec_t knumber_float::precision = 1024; | 45 | const mpfr_prec_t knumber_float::precision = 1024; | ||
48 | #endif | | |||
49 | 46 | | |||
50 | template <double F(double)> | 47 | knumber_base *knumber_float::ensureIsValid(mpfr_ptr mpfr) { | ||
51 | knumber_base *knumber_float::execute_libc_func(double x) { | 48 | if (mpfr_nan_p(mpfr)) { | ||
52 | const double r = F(x); | | |||
53 | if(isnan(r)) { | | |||
54 | knumber_error *e = new knumber_error(knumber_error::ERROR_UNDEFINED); | 49 | knumber_error *e = new knumber_error(knumber_error::ERROR_UNDEFINED); | ||
55 | delete this; | 50 | delete this; | ||
56 | return e; | 51 | return e; | ||
57 | } else if(isinf(r)) { | 52 | } else if (mpfr_inf_p(mpfr)) { | ||
58 | knumber_error *e = new knumber_error(knumber_error::ERROR_POS_INFINITY); | 53 | knumber_error *e = new knumber_error(knumber_error::ERROR_POS_INFINITY); | ||
59 | delete this; | 54 | delete this; | ||
60 | return e; | 55 | return e; | ||
61 | } else { | 56 | } else { | ||
62 | mpf_set_d(mpf_, r); | | |||
63 | return this; | 57 | return this; | ||
64 | } | 58 | } | ||
65 | } | 59 | } | ||
66 | 60 | | |||
67 | template <double F(double, double)> | 61 | template <int F(mpfr_ptr rop, mpfr_srcptr op)> | ||
68 | knumber_base *knumber_float::execute_libc_func(double x, double y) { | 62 | knumber_base *knumber_float::execute_mpfr_func() { | ||
69 | const double r = F(x, y); | 63 | F(mpfr_, mpfr_); | ||
70 | if(isnan(r)) { | 64 | return ensureIsValid(mpfr_); | ||
71 | knumber_error *e = new knumber_error(knumber_error::ERROR_UNDEFINED); | 65 | } | ||
72 | delete this; | 66 | | ||
73 | return e; | 67 | template <int F(mpfr_ptr rop, mpfr_srcptr op, mpfr_rnd_t rnd)> | ||
74 | } else if(isinf(r)) { | 68 | knumber_base *knumber_float::execute_mpfr_func() { | ||
75 | knumber_error *e = new knumber_error(knumber_error::ERROR_POS_INFINITY); | 69 | F(mpfr_, mpfr_, rounding_mode); | ||
76 | delete this; | 70 | return ensureIsValid(mpfr_); | ||
77 | return e; | 71 | } | ||
78 | } else { | 72 | | ||
79 | mpf_set_d(mpf_, r); | 73 | template <int F(mpfr_ptr rop, mpfr_srcptr op1, mpfr_srcptr op2, mpfr_rnd_t rnd)> | ||
80 | return this; | 74 | knumber_base *knumber_float::execute_mpfr_func(mpfr_srcptr op) { | ||
81 | } | 75 | F(mpfr_, mpfr_, op, rounding_mode); | ||
76 | return ensureIsValid(mpfr_); | ||||
82 | } | 77 | } | ||
83 | 78 | | |||
84 | //------------------------------------------------------------------------------ | 79 | //------------------------------------------------------------------------------ | ||
85 | // Name: | 80 | // Name: | ||
86 | //------------------------------------------------------------------------------ | 81 | //------------------------------------------------------------------------------ | ||
87 | knumber_float::knumber_float(const QString &s) { | 82 | knumber_float::knumber_float(const QString &s) { | ||
88 | 83 | mpfr_set_str(new_mpfr(), s.toLatin1().constData(), 10, rounding_mode); | |||
89 | mpf_init(mpf_); | | |||
90 | mpf_set_str(mpf_, s.toLatin1().constData(), 10); | | |||
91 | } | 84 | } | ||
92 | 85 | | |||
93 | //------------------------------------------------------------------------------ | 86 | //------------------------------------------------------------------------------ | ||
94 | // Name: | 87 | // Name: | ||
95 | //------------------------------------------------------------------------------ | 88 | //------------------------------------------------------------------------------ | ||
96 | knumber_float::knumber_float(double value) { | 89 | knumber_float::knumber_float(double value) { | ||
97 | 90 | | |||
98 | Q_ASSERT(!isinf(value)); | 91 | Q_ASSERT(!isinf(value)); | ||
99 | Q_ASSERT(!isnan(value)); | 92 | Q_ASSERT(!isnan(value)); | ||
100 | 93 | | |||
101 | mpf_init_set_d(mpf_, value); | 94 | mpfr_set_d(new_mpfr(), value, rounding_mode); | ||
102 | } | 95 | } | ||
103 | 96 | | |||
104 | #ifdef HAVE_LONG_DOUBLE | 97 | #ifdef HAVE_LONG_DOUBLE | ||
105 | //------------------------------------------------------------------------------ | 98 | //------------------------------------------------------------------------------ | ||
106 | // Name: | 99 | // Name: | ||
107 | //------------------------------------------------------------------------------ | 100 | //------------------------------------------------------------------------------ | ||
108 | knumber_float::knumber_float(long double value) { | 101 | knumber_float::knumber_float(long double value) { | ||
109 | 102 | | |||
110 | Q_ASSERT(!isinf(value)); | 103 | Q_ASSERT(!isinf(value)); | ||
111 | Q_ASSERT(!isnan(value)); | 104 | Q_ASSERT(!isnan(value)); | ||
112 | 105 | | |||
113 | mpf_init_set_d(mpf_, value); | 106 | mpfr_set_ld(new_mpfr(), value, rounding_mode); | ||
114 | } | 107 | } | ||
115 | #endif | 108 | #endif | ||
116 | 109 | | |||
117 | //------------------------------------------------------------------------------ | 110 | //------------------------------------------------------------------------------ | ||
118 | // Name: | 111 | // Name: | ||
119 | //------------------------------------------------------------------------------ | 112 | //------------------------------------------------------------------------------ | ||
120 | knumber_float::knumber_float(mpf_t mpf) { | 113 | knumber_float::knumber_float(mpfr_t mpfr) { | ||
121 | 114 | | |||
122 | mpf_init(mpf_); | 115 | mpfr_set(new_mpfr(), mpfr, rounding_mode); | ||
123 | mpf_set(mpf_, mpf); | | |||
124 | } | 116 | } | ||
125 | 117 | | |||
126 | //------------------------------------------------------------------------------ | 118 | //------------------------------------------------------------------------------ | ||
127 | // Name: | 119 | // Name: | ||
128 | //------------------------------------------------------------------------------ | 120 | //------------------------------------------------------------------------------ | ||
129 | knumber_float::knumber_float(const knumber_float *value) { | 121 | knumber_float::knumber_float(const knumber_float *value) { | ||
130 | 122 | mpfr_set(new_mpfr(), value->mpfr_, rounding_mode); | |||
131 | mpf_init_set(mpf_, value->mpf_); | | |||
132 | } | 123 | } | ||
133 | 124 | | |||
134 | //------------------------------------------------------------------------------ | 125 | //------------------------------------------------------------------------------ | ||
135 | // Name: | 126 | // Name: | ||
136 | //------------------------------------------------------------------------------ | 127 | //------------------------------------------------------------------------------ | ||
137 | knumber_float::knumber_float(const knumber_integer *value) { | 128 | knumber_float::knumber_float(const knumber_integer *value) { | ||
138 | 129 | mpfr_set_z(new_mpfr(), value->mpz_, rounding_mode); | |||
139 | mpf_init(mpf_); | | |||
140 | mpf_set_z(mpf_, value->mpz_); | | |||
141 | } | 130 | } | ||
142 | 131 | | |||
143 | //------------------------------------------------------------------------------ | 132 | //------------------------------------------------------------------------------ | ||
144 | // Name: | 133 | // Name: | ||
145 | //------------------------------------------------------------------------------ | 134 | //------------------------------------------------------------------------------ | ||
146 | knumber_float::knumber_float(const knumber_fraction *value) { | 135 | knumber_float::knumber_float(const knumber_fraction *value) { | ||
147 | 136 | mpfr_set_q(new_mpfr(), value->mpq_, rounding_mode); | |||
148 | mpf_init(mpf_); | | |||
149 | mpf_set_q(mpf_, value->mpq_); | | |||
150 | } | 137 | } | ||
151 | 138 | | |||
152 | //------------------------------------------------------------------------------ | 139 | //------------------------------------------------------------------------------ | ||
153 | // Name: | 140 | // Name: | ||
154 | //------------------------------------------------------------------------------ | 141 | //------------------------------------------------------------------------------ | ||
155 | knumber_base *knumber_float::clone() { | 142 | knumber_base *knumber_float::clone() { | ||
156 | 143 | | |||
157 | return new knumber_float(this); | 144 | return new knumber_float(this); | ||
158 | } | 145 | } | ||
159 | 146 | | |||
147 | mpfr_ptr knumber_float::new_mpfr() { | ||||
148 | mpfr_init(mpfr_); | ||||
149 | return mpfr_; | ||||
150 | } | ||||
151 | | ||||
160 | //------------------------------------------------------------------------------ | 152 | //------------------------------------------------------------------------------ | ||
161 | // Name: | 153 | // Name: | ||
162 | //------------------------------------------------------------------------------ | 154 | //------------------------------------------------------------------------------ | ||
163 | knumber_float::~knumber_float() { | 155 | knumber_float::~knumber_float() { | ||
164 | 156 | mpfr_clear(mpfr_); | |||
165 | mpf_clear(mpf_); | | |||
166 | } | 157 | } | ||
167 | 158 | | |||
168 | //------------------------------------------------------------------------------ | 159 | //------------------------------------------------------------------------------ | ||
169 | // Name: | 160 | // Name: | ||
170 | //------------------------------------------------------------------------------ | 161 | //------------------------------------------------------------------------------ | ||
171 | knumber_base *knumber_float::add(knumber_base *rhs) { | 162 | knumber_base *knumber_float::add(knumber_base *rhs) { | ||
172 | 163 | | |||
173 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | 164 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | ||
174 | knumber_float f(p); | 165 | knumber_float f(p); | ||
175 | return add(&f); | 166 | return add(&f); | ||
176 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | 167 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | ||
177 | mpf_add(mpf_, mpf_, p->mpf_); | 168 | mpfr_add(mpfr_, mpfr_, p->mpfr_, rounding_mode); | ||
178 | return this; | 169 | return this; | ||
179 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | 170 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | ||
180 | knumber_float f(p); | 171 | knumber_float f(p); | ||
181 | return add(&f); | 172 | return add(&f); | ||
182 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | 173 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | ||
183 | knumber_error *e = new knumber_error(p); | 174 | knumber_error *e = new knumber_error(p); | ||
184 | delete this; | 175 | delete this; | ||
185 | return e; | 176 | return e; | ||
186 | } | 177 | } | ||
187 | 178 | | |||
188 | Q_ASSERT(0); | 179 | Q_ASSERT(0); | ||
189 | return nullptr; | 180 | return nullptr; | ||
190 | } | 181 | } | ||
191 | 182 | | |||
192 | //------------------------------------------------------------------------------ | 183 | //------------------------------------------------------------------------------ | ||
193 | // Name: | 184 | // Name: | ||
194 | //------------------------------------------------------------------------------ | 185 | //------------------------------------------------------------------------------ | ||
195 | knumber_base *knumber_float::sub(knumber_base *rhs) { | 186 | knumber_base *knumber_float::sub(knumber_base *rhs) { | ||
196 | 187 | | |||
197 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | 188 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | ||
198 | knumber_float f(p); | 189 | knumber_float f(p); | ||
199 | return sub(&f); | 190 | return sub(&f); | ||
200 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | 191 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | ||
201 | mpf_sub(mpf_, mpf_, p->mpf_); | 192 | mpfr_sub(mpfr_, mpfr_, p->mpfr_, rounding_mode); | ||
202 | return this; | 193 | return this; | ||
203 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | 194 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | ||
204 | knumber_float f(p); | 195 | knumber_float f(p); | ||
205 | return sub(&f); | 196 | return sub(&f); | ||
206 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | 197 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | ||
207 | knumber_error *e = new knumber_error(p); | 198 | knumber_error *e = new knumber_error(p); | ||
208 | delete this; | 199 | delete this; | ||
209 | return e->neg(); | 200 | return e->neg(); | ||
210 | } | 201 | } | ||
211 | 202 | | |||
212 | Q_ASSERT(0); | 203 | Q_ASSERT(0); | ||
213 | return nullptr; | 204 | return nullptr; | ||
214 | } | 205 | } | ||
215 | 206 | | |||
216 | //------------------------------------------------------------------------------ | 207 | //------------------------------------------------------------------------------ | ||
217 | // Name: | 208 | // Name: | ||
218 | //------------------------------------------------------------------------------ | 209 | //------------------------------------------------------------------------------ | ||
219 | knumber_base *knumber_float::mul(knumber_base *rhs) { | 210 | knumber_base *knumber_float::mul(knumber_base *rhs) { | ||
220 | 211 | | |||
221 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | 212 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | ||
222 | knumber_float f(p); | 213 | knumber_float f(p); | ||
223 | return mul(&f); | 214 | return mul(&f); | ||
224 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | 215 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | ||
225 | mpf_mul(mpf_, mpf_, p->mpf_); | 216 | mpfr_mul(mpfr_, mpfr_, p->mpfr_, rounding_mode); | ||
226 | return this; | 217 | return this; | ||
227 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | 218 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | ||
228 | knumber_float f(p); | 219 | knumber_float f(p); | ||
229 | return mul(&f); | 220 | return mul(&f); | ||
230 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | 221 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | ||
231 | if(is_zero()) { | 222 | if(is_zero()) { | ||
232 | delete this; | 223 | delete this; | ||
233 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | 224 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | ||
Show All 27 Lines | 250 | } else { | |||
261 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | 252 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | ||
262 | } | 253 | } | ||
263 | } | 254 | } | ||
264 | 255 | | |||
265 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | 256 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | ||
266 | knumber_float f(p); | 257 | knumber_float f(p); | ||
267 | return div(&f); | 258 | return div(&f); | ||
268 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | 259 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | ||
269 | mpf_div(mpf_, mpf_, p->mpf_); | 260 | mpfr_div(mpfr_, mpfr_, p->mpfr_, rounding_mode); | ||
270 | return this; | 261 | return this; | ||
271 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | 262 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | ||
272 | knumber_float f(p); | 263 | knumber_float f(p); | ||
273 | return div(&f); | 264 | return div(&f); | ||
274 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | 265 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | ||
275 | if(p->sign() > 0 || p->sign() < 0) { | 266 | if(p->sign() > 0 || p->sign() < 0) { | ||
276 | delete this; | 267 | delete this; | ||
277 | return new knumber_integer(0); | 268 | return new knumber_integer(0); | ||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Line(s) | 328 | knumber_base *knumber_float::bitwise_shift(knumber_base *rhs) { | |||
341 | // NOTE: we don't support bitwise operations with non-integer operands | 332 | // NOTE: we don't support bitwise operations with non-integer operands | ||
342 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | 333 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | ||
343 | } | 334 | } | ||
344 | 335 | | |||
345 | //------------------------------------------------------------------------------ | 336 | //------------------------------------------------------------------------------ | ||
346 | // Name: | 337 | // Name: | ||
347 | //------------------------------------------------------------------------------ | 338 | //------------------------------------------------------------------------------ | ||
348 | knumber_base *knumber_float::neg() { | 339 | knumber_base *knumber_float::neg() { | ||
349 | 340 | mpfr_neg(mpfr_, mpfr_, rounding_mode); | |||
350 | mpf_neg(mpf_, mpf_); | | |||
351 | return this; | 341 | return this; | ||
352 | } | 342 | } | ||
353 | 343 | | |||
354 | //------------------------------------------------------------------------------ | 344 | //------------------------------------------------------------------------------ | ||
355 | // Name: | 345 | // Name: | ||
356 | //------------------------------------------------------------------------------ | 346 | //------------------------------------------------------------------------------ | ||
357 | knumber_base *knumber_float::cmp() { | 347 | knumber_base *knumber_float::cmp() { | ||
358 | 348 | | |||
359 | delete this; | 349 | delete this; | ||
360 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | 350 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | ||
361 | } | 351 | } | ||
362 | 352 | | |||
363 | //------------------------------------------------------------------------------ | 353 | //------------------------------------------------------------------------------ | ||
364 | // Name: | 354 | // Name: | ||
365 | //------------------------------------------------------------------------------ | 355 | //------------------------------------------------------------------------------ | ||
366 | knumber_base *knumber_float::abs() { | 356 | knumber_base *knumber_float::abs() { | ||
367 | 357 | mpfr_abs(mpfr_, mpfr_, rounding_mode); | |||
368 | mpf_abs(mpf_, mpf_); | | |||
369 | return this; | 358 | return this; | ||
370 | } | 359 | } | ||
371 | 360 | | |||
372 | //------------------------------------------------------------------------------ | 361 | //------------------------------------------------------------------------------ | ||
373 | // Name: | 362 | // Name: | ||
374 | //------------------------------------------------------------------------------ | 363 | //------------------------------------------------------------------------------ | ||
375 | knumber_base *knumber_float::sqrt() { | 364 | knumber_base *knumber_float::sqrt() { | ||
376 | 365 | | |||
377 | if(sign() < 0) { | 366 | if(sign() < 0) { | ||
378 | delete this; | 367 | delete this; | ||
379 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | 368 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | ||
380 | } | 369 | } | ||
381 | 370 | | |||
382 | #ifdef KNUMBER_USE_MPFR | 371 | mpfr_sqrt(mpfr_, mpfr_, rounding_mode); | ||
383 | mpfr_t mpfr; | | |||
384 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
385 | mpfr_sqrt(mpfr, mpfr, rounding_mode); | | |||
386 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
387 | mpfr_clear(mpfr); | | |||
388 | #else | | |||
389 | mpf_sqrt(mpf_, mpf_); | | |||
390 | #endif | | |||
391 | return this; | 372 | return this; | ||
392 | } | 373 | } | ||
393 | 374 | | |||
394 | //------------------------------------------------------------------------------ | 375 | //------------------------------------------------------------------------------ | ||
395 | // Name: | 376 | // Name: | ||
396 | //------------------------------------------------------------------------------ | 377 | //------------------------------------------------------------------------------ | ||
397 | knumber_base *knumber_float::cbrt() { | 378 | knumber_base *knumber_float::cbrt() { | ||
398 | 379 | return execute_mpfr_func< ::mpfr_cbrt>(); | |||
399 | #ifdef KNUMBER_USE_MPFR | | |||
400 | mpfr_t mpfr; | | |||
401 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
402 | mpfr_cbrt(mpfr, mpfr, rounding_mode); | | |||
403 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
404 | mpfr_clear(mpfr); | | |||
405 | #else | | |||
406 | const double x = mpf_get_d(mpf_); | | |||
407 | if(isinf(x)) { | | |||
408 | delete this; | | |||
409 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
410 | } else { | | |||
411 | #ifdef Q_CC_MSVC | | |||
412 | return execute_libc_func< ::pow>(x, 1.0 / 3.0); | | |||
413 | #else | | |||
414 | return execute_libc_func< ::cbrt>(x); | | |||
415 | #endif | | |||
416 | } | | |||
417 | #endif | | |||
418 | return this; | | |||
419 | } | 380 | } | ||
420 | 381 | | |||
421 | //------------------------------------------------------------------------------ | 382 | //------------------------------------------------------------------------------ | ||
422 | // Name: | 383 | // Name: | ||
423 | //------------------------------------------------------------------------------ | 384 | //------------------------------------------------------------------------------ | ||
424 | knumber_base *knumber_float::factorial() { | 385 | knumber_base *knumber_float::factorial() { | ||
425 | 386 | | |||
426 | if(sign() < 0) { | 387 | if(sign() < 0) { | ||
427 | delete this; | 388 | delete this; | ||
428 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | 389 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | ||
429 | } | 390 | } | ||
430 | 391 | | |||
431 | knumber_integer *i = new knumber_integer(this); | 392 | knumber_integer *i = new knumber_integer(this); | ||
432 | delete this; | 393 | delete this; | ||
433 | return i->factorial(); | 394 | return i->factorial(); | ||
434 | } | 395 | } | ||
435 | 396 | | |||
436 | //------------------------------------------------------------------------------ | 397 | //------------------------------------------------------------------------------ | ||
437 | // Name: | 398 | // Name: | ||
438 | //------------------------------------------------------------------------------ | 399 | //------------------------------------------------------------------------------ | ||
439 | knumber_base *knumber_float::sin() { | 400 | knumber_base *knumber_float::sin() { | ||
440 | 401 | return execute_mpfr_func< ::mpfr_sin>(); | |||
441 | #ifdef KNUMBER_USE_MPFR | | |||
442 | mpfr_t mpfr; | | |||
443 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
444 | mpfr_sin(mpfr, mpfr, rounding_mode); | | |||
445 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
446 | mpfr_clear(mpfr); | | |||
447 | return this; | | |||
448 | #else | | |||
449 | const double x = mpf_get_d(mpf_); | | |||
450 | if(isinf(x)) { | | |||
451 | delete this; | | |||
452 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
453 | } else { | | |||
454 | return execute_libc_func< ::sin>(x); | | |||
455 | } | | |||
456 | #endif | | |||
457 | | ||||
458 | } | 402 | } | ||
459 | 403 | | |||
460 | //------------------------------------------------------------------------------ | 404 | //------------------------------------------------------------------------------ | ||
461 | // Name: | 405 | // Name: | ||
462 | //------------------------------------------------------------------------------ | 406 | //------------------------------------------------------------------------------ | ||
463 | knumber_base *knumber_float::floor() { | 407 | knumber_base *knumber_float::floor() { | ||
464 | #ifdef KNUMBER_USE_MPFR | 408 | return execute_mpfr_func< ::mpfr_floor>(); | ||
465 | mpfr_t mpfr; | | |||
466 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
467 | mpfr_floor(mpfr, mpfr); | | |||
468 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
469 | mpfr_clear(mpfr); | | |||
470 | return this; | | |||
471 | #else | | |||
472 | const double x = mpf_get_d(mpf_); | | |||
473 | if(isinf(x)) { | | |||
474 | delete this; | | |||
475 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
476 | } else { | | |||
477 | return execute_libc_func< ::floor>(x); | | |||
478 | } | | |||
479 | #endif | | |||
480 | } | 409 | } | ||
481 | 410 | | |||
482 | //------------------------------------------------------------------------------ | 411 | //------------------------------------------------------------------------------ | ||
483 | // Name: | 412 | // Name: | ||
484 | //------------------------------------------------------------------------------ | 413 | //------------------------------------------------------------------------------ | ||
485 | knumber_base *knumber_float::ceil() { | 414 | knumber_base *knumber_float::ceil() { | ||
486 | #ifdef KNUMBER_USE_MPFR | 415 | return execute_mpfr_func< ::mpfr_ceil>(); | ||
487 | mpfr_t mpfr; | | |||
488 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
489 | mpfr_ceil(mpfr, mpfr); | | |||
490 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
491 | mpfr_clear(mpfr); | | |||
492 | return this; | | |||
493 | #else | | |||
494 | const double x = mpf_get_d(mpf_); | | |||
495 | if(isinf(x)) { | | |||
496 | delete this; | | |||
497 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
498 | } else { | | |||
499 | return execute_libc_func< ::ceil>(x); | | |||
500 | } | | |||
501 | #endif | | |||
502 | } | 416 | } | ||
503 | //------------------------------------------------------------------------------ | 417 | //------------------------------------------------------------------------------ | ||
504 | // Name: | 418 | // Name: | ||
505 | //------------------------------------------------------------------------------ | 419 | //------------------------------------------------------------------------------ | ||
506 | knumber_base *knumber_float::cos() { | 420 | knumber_base *knumber_float::cos() { | ||
507 | 421 | return execute_mpfr_func< ::mpfr_cos>(); | |||
508 | #ifdef KNUMBER_USE_MPFR | | |||
509 | mpfr_t mpfr; | | |||
510 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
511 | mpfr_cos(mpfr, mpfr, rounding_mode); | | |||
512 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
513 | mpfr_clear(mpfr); | | |||
514 | return this; | | |||
515 | #else | | |||
516 | const double x = mpf_get_d(mpf_); | | |||
517 | if(isinf(x)) { | | |||
518 | delete this; | | |||
519 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
520 | } else { | | |||
521 | return execute_libc_func< ::cos>(x); | | |||
522 | } | | |||
523 | #endif | | |||
524 | } | 422 | } | ||
525 | 423 | | |||
526 | //------------------------------------------------------------------------------ | 424 | //------------------------------------------------------------------------------ | ||
527 | // Name: | 425 | // Name: | ||
528 | //------------------------------------------------------------------------------ | 426 | //------------------------------------------------------------------------------ | ||
529 | knumber_base *knumber_float::tan() { | 427 | knumber_base *knumber_float::tan() { | ||
530 | 428 | return execute_mpfr_func< ::mpfr_tan>(); | |||
531 | #ifdef KNUMBER_USE_MPFR | | |||
532 | mpfr_t mpfr; | | |||
533 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
534 | mpfr_tan(mpfr, mpfr, rounding_mode); | | |||
535 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
536 | mpfr_clear(mpfr); | | |||
537 | return this; | | |||
538 | #else | | |||
539 | const double x = mpf_get_d(mpf_); | | |||
540 | if(isinf(x)) { | | |||
541 | delete this; | | |||
542 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
543 | } else { | | |||
544 | return execute_libc_func< ::tan>(x); | | |||
545 | } | | |||
546 | #endif | | |||
547 | } | 429 | } | ||
548 | 430 | | |||
549 | //------------------------------------------------------------------------------ | 431 | //------------------------------------------------------------------------------ | ||
550 | // Name: | 432 | // Name: | ||
551 | //------------------------------------------------------------------------------ | 433 | //------------------------------------------------------------------------------ | ||
552 | knumber_base *knumber_float::asin() { | 434 | knumber_base *knumber_float::asin() { | ||
553 | if(mpf_cmp_d(mpf_, 1.0) > 0 || mpf_cmp_d(mpf_, -1.0) < 0) { | 435 | if (mpfr_cmp_d(mpfr_, 1.0) > 0 || mpfr_cmp_d(mpfr_, -1.0) < 0) { | ||
554 | delete this; | 436 | delete this; | ||
555 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | 437 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | ||
556 | } | 438 | } | ||
557 | 439 | | |||
558 | #ifdef KNUMBER_USE_MPFR | 440 | return execute_mpfr_func< ::mpfr_asin>(); | ||
559 | mpfr_t mpfr; | | |||
560 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
561 | mpfr_asin(mpfr, mpfr, rounding_mode); | | |||
562 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
563 | mpfr_clear(mpfr); | | |||
564 | return this; | | |||
565 | #else | | |||
566 | const double x = mpf_get_d(mpf_); | | |||
567 | if(isinf(x)) { | | |||
568 | delete this; | | |||
569 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
570 | } else { | | |||
571 | return execute_libc_func< ::asin>(x); | | |||
572 | } | | |||
573 | #endif | | |||
574 | } | 441 | } | ||
575 | 442 | | |||
576 | //------------------------------------------------------------------------------ | 443 | //------------------------------------------------------------------------------ | ||
577 | // Name: | 444 | // Name: | ||
578 | //------------------------------------------------------------------------------s | 445 | //------------------------------------------------------------------------------s | ||
579 | knumber_base *knumber_float::acos() { | 446 | knumber_base *knumber_float::acos() { | ||
580 | if(mpf_cmp_d(mpf_, 1.0) > 0 || mpf_cmp_d(mpf_, -1.0) < 0) { | 447 | if (mpfr_cmp_d(mpfr_, 1.0) > 0 || mpfr_cmp_d(mpfr_, -1.0) < 0) { | ||
581 | delete this; | 448 | delete this; | ||
582 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | 449 | return new knumber_error(knumber_error::ERROR_UNDEFINED); | ||
583 | } | 450 | } | ||
584 | 451 | | |||
585 | #ifdef KNUMBER_USE_MPFR | 452 | return execute_mpfr_func< ::mpfr_acos>(); | ||
586 | mpfr_t mpfr; | | |||
587 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
588 | mpfr_acos(mpfr, mpfr, rounding_mode); | | |||
589 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
590 | mpfr_clear(mpfr); | | |||
591 | return this; | | |||
592 | #else | | |||
593 | const double x = mpf_get_d(mpf_); | | |||
594 | if(isinf(x)) { | | |||
595 | delete this; | | |||
596 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
597 | } else { | | |||
598 | return execute_libc_func< ::acos>(x); | | |||
599 | } | | |||
600 | #endif | | |||
601 | } | 453 | } | ||
602 | 454 | | |||
603 | //------------------------------------------------------------------------------ | 455 | //------------------------------------------------------------------------------ | ||
604 | // Name: | 456 | // Name: | ||
605 | //------------------------------------------------------------------------------ | 457 | //------------------------------------------------------------------------------ | ||
606 | knumber_base *knumber_float::atan() { | 458 | knumber_base *knumber_float::atan() { | ||
607 | 459 | return execute_mpfr_func< ::mpfr_atan>(); | |||
608 | #ifdef KNUMBER_USE_MPFR | | |||
609 | mpfr_t mpfr; | | |||
610 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
611 | mpfr_atan(mpfr, mpfr, rounding_mode); | | |||
612 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
613 | mpfr_clear(mpfr); | | |||
614 | return this; | | |||
615 | #else | | |||
616 | const double x = mpf_get_d(mpf_); | | |||
617 | if(isinf(x)) { | | |||
618 | delete this; | | |||
619 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
620 | } else { | | |||
621 | return execute_libc_func< ::atan>(x); | | |||
622 | } | | |||
623 | #endif | | |||
624 | } | 460 | } | ||
625 | 461 | | |||
626 | //------------------------------------------------------------------------------ | 462 | //------------------------------------------------------------------------------ | ||
627 | // Name: | 463 | // Name: | ||
628 | //------------------------------------------------------------------------------ | 464 | //------------------------------------------------------------------------------ | ||
629 | knumber_base *knumber_float::sinh() { | 465 | knumber_base *knumber_float::sinh() { | ||
630 | #ifdef KNUMBER_USE_MPFR | 466 | return execute_mpfr_func< ::mpfr_sinh>(); | ||
631 | mpfr_t mpfr; | | |||
632 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
633 | mpfr_sinh(mpfr, mpfr, rounding_mode); | | |||
634 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
635 | mpfr_clear(mpfr); | | |||
636 | return this; | | |||
637 | #else | | |||
638 | const double x = mpf_get_d(mpf_); | | |||
639 | return execute_libc_func< ::sinh>(x); | | |||
640 | #endif | | |||
641 | | ||||
642 | } | 467 | } | ||
643 | 468 | | |||
644 | //------------------------------------------------------------------------------ | 469 | //------------------------------------------------------------------------------ | ||
645 | // Name: | 470 | // Name: | ||
646 | //------------------------------------------------------------------------------ | 471 | //------------------------------------------------------------------------------ | ||
647 | knumber_base *knumber_float::cosh() { | 472 | knumber_base *knumber_float::cosh() { | ||
648 | #ifdef KNUMBER_USE_MPFR | 473 | return execute_mpfr_func< ::mpfr_cosh>(); | ||
649 | mpfr_t mpfr; | | |||
650 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
651 | mpfr_cosh(mpfr, mpfr, rounding_mode); | | |||
652 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
653 | mpfr_clear(mpfr); | | |||
654 | return this; | | |||
655 | #else | | |||
656 | const double x = mpf_get_d(mpf_); | | |||
657 | return execute_libc_func< ::cosh>(x); | | |||
658 | #endif | | |||
659 | } | 474 | } | ||
660 | 475 | | |||
661 | //------------------------------------------------------------------------------ | 476 | //------------------------------------------------------------------------------ | ||
662 | // Name: | 477 | // Name: | ||
663 | //------------------------------------------------------------------------------ | 478 | //------------------------------------------------------------------------------ | ||
664 | knumber_base *knumber_float::tanh() { | 479 | knumber_base *knumber_float::tanh() { | ||
665 | #ifdef KNUMBER_USE_MPFR | 480 | return execute_mpfr_func< ::mpfr_tanh>(); | ||
666 | mpfr_t mpfr; | | |||
667 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
668 | mpfr_tanh(mpfr, mpfr, rounding_mode); | | |||
669 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
670 | mpfr_clear(mpfr); | | |||
671 | return this; | | |||
672 | #else | | |||
673 | const double x = mpf_get_d(mpf_); | | |||
674 | return execute_libc_func< ::tanh>(x); | | |||
675 | #endif | | |||
676 | } | 481 | } | ||
677 | 482 | | |||
678 | //------------------------------------------------------------------------------ | 483 | //------------------------------------------------------------------------------ | ||
679 | // Name: | 484 | // Name: | ||
680 | //------------------------------------------------------------------------------ | 485 | //------------------------------------------------------------------------------ | ||
681 | knumber_base *knumber_float::tgamma() { | 486 | knumber_base *knumber_float::tgamma() { | ||
682 | 487 | return execute_mpfr_func< ::mpfr_gamma>(); | |||
683 | #ifdef KNUMBER_USE_MPFR | | |||
684 | mpfr_t mpfr; | | |||
685 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
686 | mpfr_gamma(mpfr, mpfr, rounding_mode); | | |||
687 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
688 | mpfr_clear(mpfr); | | |||
689 | return this; | | |||
690 | #else | | |||
691 | const double x = mpf_get_d(mpf_); | | |||
692 | if(isinf(x)) { | | |||
693 | delete this; | | |||
694 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
695 | | ||||
696 | } else { | | |||
697 | return execute_libc_func< ::tgamma>(x); | | |||
698 | } | | |||
699 | #endif | | |||
700 | | ||||
701 | } | 488 | } | ||
702 | 489 | | |||
703 | //------------------------------------------------------------------------------ | 490 | //------------------------------------------------------------------------------ | ||
704 | // Name: | 491 | // Name: | ||
705 | //------------------------------------------------------------------------------ | 492 | //------------------------------------------------------------------------------ | ||
706 | knumber_base *knumber_float::asinh() { | 493 | knumber_base *knumber_float::asinh() { | ||
707 | #ifdef KNUMBER_USE_MPFR | 494 | return execute_mpfr_func< ::mpfr_asinh>(); | ||
708 | mpfr_t mpfr; | | |||
709 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
710 | mpfr_asinh(mpfr, mpfr, rounding_mode); | | |||
711 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
712 | mpfr_clear(mpfr); | | |||
713 | return this; | | |||
714 | #else | | |||
715 | const double x = mpf_get_d(mpf_); | | |||
716 | return execute_libc_func< ::asinh>(x); | | |||
717 | #endif | | |||
718 | } | 495 | } | ||
719 | 496 | | |||
720 | //------------------------------------------------------------------------------ | 497 | //------------------------------------------------------------------------------ | ||
721 | // Name: | 498 | // Name: | ||
722 | //------------------------------------------------------------------------------ | 499 | //------------------------------------------------------------------------------ | ||
723 | knumber_base *knumber_float::acosh() { | 500 | knumber_base *knumber_float::acosh() { | ||
724 | #ifdef KNUMBER_USE_MPFR | 501 | return execute_mpfr_func< ::mpfr_acosh>(); | ||
725 | mpfr_t mpfr; | | |||
726 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
727 | mpfr_acosh(mpfr, mpfr, rounding_mode); | | |||
728 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
729 | mpfr_clear(mpfr); | | |||
730 | return this; | | |||
731 | #else | | |||
732 | const double x = mpf_get_d(mpf_); | | |||
733 | return execute_libc_func< ::acosh>(x); | | |||
734 | #endif | | |||
735 | } | 502 | } | ||
736 | 503 | | |||
737 | //------------------------------------------------------------------------------ | 504 | //------------------------------------------------------------------------------ | ||
738 | // Name: | 505 | // Name: | ||
739 | //------------------------------------------------------------------------------ | 506 | //------------------------------------------------------------------------------ | ||
740 | knumber_base *knumber_float::atanh() { | 507 | knumber_base *knumber_float::atanh() { | ||
741 | #ifdef KNUMBER_USE_MPFR | 508 | return execute_mpfr_func< ::mpfr_atanh>(); | ||
742 | mpfr_t mpfr; | | |||
743 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
744 | mpfr_atanh(mpfr, mpfr, rounding_mode); | | |||
745 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
746 | mpfr_clear(mpfr); | | |||
747 | return this; | | |||
748 | #else | | |||
749 | const double x = mpf_get_d(mpf_); | | |||
750 | return execute_libc_func< ::atanh>(x); | | |||
751 | #endif | | |||
752 | } | 509 | } | ||
753 | 510 | | |||
754 | //------------------------------------------------------------------------------ | 511 | //------------------------------------------------------------------------------ | ||
755 | // Name: | 512 | // Name: | ||
756 | //------------------------------------------------------------------------------ | 513 | //------------------------------------------------------------------------------ | ||
757 | knumber_base *knumber_float::pow(knumber_base *rhs) { | 514 | knumber_base *knumber_float::pow(knumber_base *rhs) { | ||
758 | 515 | | |||
759 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | 516 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | ||
760 | mpf_pow_ui(mpf_, mpf_, mpz_get_ui(p->mpz_)); | 517 | mpfr_pow_ui(mpfr_, mpfr_, mpz_get_ui(p->mpz_), rounding_mode); | ||
761 | 518 | | |||
762 | if(p->sign() < 0) { | 519 | if(p->sign() < 0) { | ||
763 | return reciprocal(); | 520 | return reciprocal(); | ||
764 | } else { | 521 | } else { | ||
765 | return this; | 522 | return this; | ||
766 | } | 523 | } | ||
767 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | 524 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | ||
768 | return execute_libc_func< ::pow>(mpf_get_d(mpf_), mpf_get_d(p->mpf_)); | 525 | return execute_mpfr_func< ::mpfr_pow>(p->mpfr_); | ||
769 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | 526 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | ||
770 | knumber_float f(p); | 527 | knumber_float f(p); | ||
771 | return execute_libc_func< ::pow>(mpf_get_d(mpf_), mpf_get_d(f.mpf_)); | 528 | return execute_mpfr_func< ::mpfr_pow>(f.mpfr_); | ||
772 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | 529 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | ||
773 | if(p->sign() > 0) { | 530 | if(p->sign() > 0) { | ||
774 | knumber_error *e = new knumber_error(knumber_error::ERROR_POS_INFINITY); | 531 | knumber_error *e = new knumber_error(knumber_error::ERROR_POS_INFINITY); | ||
775 | delete this; | 532 | delete this; | ||
776 | return e; | 533 | return e; | ||
777 | } else if(p->sign() < 0) { | 534 | } else if(p->sign() < 0) { | ||
778 | knumber_integer *n = new knumber_integer(0); | 535 | knumber_integer *n = new knumber_integer(0); | ||
779 | delete this; | 536 | delete this; | ||
Show All 13 Lines | |||||
793 | // Name: | 550 | // Name: | ||
794 | //------------------------------------------------------------------------------ | 551 | //------------------------------------------------------------------------------ | ||
795 | int knumber_float::compare(knumber_base *rhs) { | 552 | int knumber_float::compare(knumber_base *rhs) { | ||
796 | 553 | | |||
797 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | 554 | if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { | ||
798 | knumber_float f(p); | 555 | knumber_float f(p); | ||
799 | return compare(&f); | 556 | return compare(&f); | ||
800 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | 557 | } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { | ||
801 | return mpf_cmp(mpf_, p->mpf_); | 558 | return mpfr_cmp(mpfr_, p->mpfr_); | ||
802 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | 559 | } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { | ||
803 | knumber_float f(p); | 560 | knumber_float f(p); | ||
804 | return compare(&f); | 561 | return compare(&f); | ||
805 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | 562 | } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { | ||
806 | // NOTE: any number compared to NaN/Inf/-Inf always compares less | 563 | // NOTE: any number compared to NaN/Inf/-Inf always compares less | ||
807 | // at the moment | 564 | // at the moment | ||
808 | return -1; | 565 | return -1; | ||
809 | } | 566 | } | ||
810 | 567 | | |||
811 | Q_ASSERT(0); | 568 | Q_ASSERT(0); | ||
812 | return 0; | 569 | return 0; | ||
813 | } | 570 | } | ||
814 | 571 | | |||
815 | //------------------------------------------------------------------------------ | 572 | //------------------------------------------------------------------------------ | ||
816 | // Name: | 573 | // Name: | ||
817 | //------------------------------------------------------------------------------ | 574 | //------------------------------------------------------------------------------ | ||
818 | QString knumber_float::toString(int precision) const { | 575 | QString knumber_float::toString(int precision) const { | ||
819 | 576 | | |||
820 | size_t size; | 577 | size_t size; | ||
578 | | ||||
821 | if (precision > 0) { | 579 | if (precision > 0) { | ||
822 | size = gmp_snprintf(nullptr, 0, "%.*Fg", precision, mpf_) + 1; | 580 | size = static_cast<size_t>(mpfr_snprintf(nullptr, 0, "%.*Rg", precision, mpfr_) + 1); | ||
823 | } else { | 581 | } else { | ||
824 | size = gmp_snprintf(nullptr, 0, "%.Fg", mpf_) + 1; | 582 | size = static_cast<size_t>(mpfr_snprintf(nullptr, 0, "%.Rg", mpfr_) + 1); | ||
825 | } | 583 | } | ||
826 | 584 | | |||
827 | QScopedArrayPointer<char> buf(new char[size]); | 585 | QScopedArrayPointer<char> buf(new char[size]); | ||
828 | 586 | | |||
829 | if (precision > 0) { | 587 | if (precision > 0) { | ||
830 | gmp_snprintf(&buf[0], size, "%.*Fg", precision, mpf_); | 588 | mpfr_snprintf(&buf[0], size, "%.*Rg", precision, mpfr_); | ||
831 | } else { | 589 | } else { | ||
832 | gmp_snprintf(&buf[0], size, "%.Fg", mpf_); | 590 | mpfr_snprintf(&buf[0], size, "%.Rg", mpfr_); | ||
833 | } | 591 | } | ||
834 | 592 | | |||
835 | return QLatin1String(&buf[0]); | 593 | return QLatin1String(&buf[0]); | ||
836 | } | 594 | } | ||
837 | 595 | | |||
838 | //------------------------------------------------------------------------------ | 596 | //------------------------------------------------------------------------------ | ||
839 | // Name: | 597 | // Name: | ||
840 | //------------------------------------------------------------------------------ | 598 | //------------------------------------------------------------------------------ | ||
841 | bool knumber_float::is_integer() const { | 599 | bool knumber_float::is_integer() const { | ||
842 | 600 | return mpfr_integer_p(mpfr_) != 0; | |||
843 | return mpf_integer_p(mpf_) != 0; | | |||
844 | } | 601 | } | ||
845 | 602 | | |||
846 | //------------------------------------------------------------------------------ | 603 | //------------------------------------------------------------------------------ | ||
847 | // Name: | 604 | // Name: | ||
848 | //------------------------------------------------------------------------------ | 605 | //------------------------------------------------------------------------------ | ||
849 | bool knumber_float::is_zero() const { | 606 | bool knumber_float::is_zero() const { | ||
850 | 607 | return mpfr_zero_p(mpfr_); | |||
851 | return mpf_sgn(mpf_) == 0; | | |||
852 | } | 608 | } | ||
853 | 609 | | |||
854 | //------------------------------------------------------------------------------ | 610 | //------------------------------------------------------------------------------ | ||
855 | // Name: | 611 | // Name: | ||
856 | //------------------------------------------------------------------------------ | 612 | //------------------------------------------------------------------------------ | ||
857 | int knumber_float::sign() const { | 613 | int knumber_float::sign() const { | ||
858 | 614 | return mpfr_sgn(mpfr_); | |||
859 | return mpf_sgn(mpf_); | | |||
860 | } | 615 | } | ||
861 | 616 | | |||
862 | //------------------------------------------------------------------------------ | 617 | //------------------------------------------------------------------------------ | ||
863 | // Name: | 618 | // Name: | ||
864 | //------------------------------------------------------------------------------ | 619 | //------------------------------------------------------------------------------ | ||
865 | knumber_base *knumber_float::reciprocal() { | 620 | knumber_base *knumber_float::reciprocal() { | ||
866 | 621 | mpfr_t mpfr; | |||
867 | mpf_t mpf; | 622 | mpfr_init_set_d(mpfr, 1.0, rounding_mode); | ||
868 | mpf_init_set_d(mpf, 1.0); | 623 | mpfr_div(mpfr_, mpfr, mpfr_, rounding_mode); | ||
869 | mpf_div(mpf_, mpf, mpf_); | 624 | mpfr_clear(mpfr); | ||
870 | return this; | 625 | return this; | ||
871 | } | 626 | } | ||
872 | 627 | | |||
873 | //------------------------------------------------------------------------------ | 628 | //------------------------------------------------------------------------------ | ||
874 | // Name: | 629 | // Name: | ||
875 | //------------------------------------------------------------------------------ | 630 | //------------------------------------------------------------------------------ | ||
876 | knumber_base *knumber_float::log2() { | 631 | knumber_base *knumber_float::log2() { | ||
877 | #ifdef KNUMBER_USE_MPFR | 632 | return execute_mpfr_func< ::mpfr_log2>(); | ||
878 | mpfr_t mpfr; | | |||
879 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
880 | mpfr_log2(mpfr, mpfr, rounding_mode); | | |||
881 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
882 | mpfr_clear(mpfr); | | |||
883 | return this; | | |||
884 | #else | | |||
885 | const double x = mpf_get_d(mpf_); | | |||
886 | if(isinf(x)) { | | |||
887 | delete this; | | |||
888 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
889 | } else { | | |||
890 | return execute_libc_func< ::log2>(x); | | |||
891 | } | | |||
892 | #endif | | |||
893 | } | 633 | } | ||
894 | 634 | | |||
895 | //------------------------------------------------------------------------------ | 635 | //------------------------------------------------------------------------------ | ||
896 | // Name: | 636 | // Name: | ||
897 | //------------------------------------------------------------------------------ | 637 | //------------------------------------------------------------------------------ | ||
898 | knumber_base *knumber_float::log10() { | 638 | knumber_base *knumber_float::log10() { | ||
899 | #ifdef KNUMBER_USE_MPFR | 639 | return execute_mpfr_func< ::mpfr_log10>(); | ||
900 | mpfr_t mpfr; | | |||
901 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
902 | mpfr_log10(mpfr, mpfr, rounding_mode); | | |||
903 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
904 | mpfr_clear(mpfr); | | |||
905 | return this; | | |||
906 | #else | | |||
907 | const double x = mpf_get_d(mpf_); | | |||
908 | if(isinf(x)) { | | |||
909 | delete this; | | |||
910 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
911 | } else { | | |||
912 | return execute_libc_func< ::log10>(x); | | |||
913 | } | | |||
914 | #endif | | |||
915 | } | 640 | } | ||
916 | 641 | | |||
917 | //------------------------------------------------------------------------------ | 642 | //------------------------------------------------------------------------------ | ||
918 | // Name: | 643 | // Name: | ||
919 | //------------------------------------------------------------------------------ | 644 | //------------------------------------------------------------------------------ | ||
920 | knumber_base *knumber_float::ln() { | 645 | knumber_base *knumber_float::ln() { | ||
921 | #ifdef KNUMBER_USE_MPFR | 646 | return execute_mpfr_func< ::mpfr_log>(); | ||
922 | mpfr_t mpfr; | | |||
923 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
924 | mpfr_log(mpfr, mpfr, rounding_mode); | | |||
925 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
926 | mpfr_clear(mpfr); | | |||
927 | return this; | | |||
928 | #else | | |||
929 | const double x = mpf_get_d(mpf_); | | |||
930 | if(isinf(x)) { | | |||
931 | delete this; | | |||
932 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
933 | } else { | | |||
934 | return execute_libc_func< ::log>(x); | | |||
935 | } | | |||
936 | #endif | | |||
937 | } | 647 | } | ||
938 | 648 | | |||
939 | //------------------------------------------------------------------------------ | 649 | //------------------------------------------------------------------------------ | ||
940 | // Name: | 650 | // Name: | ||
941 | //------------------------------------------------------------------------------ | 651 | //------------------------------------------------------------------------------ | ||
942 | knumber_base *knumber_float::exp2() { | 652 | knumber_base *knumber_float::exp2() { | ||
943 | #ifdef KNUMBER_USE_MPFR | 653 | return execute_mpfr_func< ::mpfr_exp2>(); | ||
944 | mpfr_t mpfr; | | |||
945 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
946 | mpfr_exp2(mpfr, mpfr, rounding_mode); | | |||
947 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
948 | mpfr_clear(mpfr); | | |||
949 | return this; | | |||
950 | #else | | |||
951 | const double x = mpf_get_d(mpf_); | | |||
952 | if(isinf(x)) { | | |||
953 | delete this; | | |||
954 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
955 | } else { | | |||
956 | return execute_libc_func< ::exp2>(x); | | |||
957 | } | | |||
958 | #endif | | |||
959 | } | 654 | } | ||
960 | 655 | | |||
961 | //------------------------------------------------------------------------------ | 656 | //------------------------------------------------------------------------------ | ||
962 | // Name: | 657 | // Name: | ||
963 | //------------------------------------------------------------------------------ | 658 | //------------------------------------------------------------------------------ | ||
964 | knumber_base *knumber_float::exp10() { | 659 | knumber_base *knumber_float::exp10() { | ||
965 | #ifdef KNUMBER_USE_MPFR | 660 | return execute_mpfr_func< ::mpfr_exp10>(); | ||
966 | mpfr_t mpfr; | | |||
967 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
968 | mpfr_exp10(mpfr, mpfr, rounding_mode); | | |||
969 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
970 | mpfr_clear(mpfr); | | |||
971 | return this; | | |||
972 | #else | | |||
973 | const double x = mpf_get_d(mpf_); | | |||
974 | if(isinf(x)) { | | |||
975 | delete this; | | |||
976 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
977 | } else { | | |||
978 | return execute_libc_func< ::pow>(10, x); | | |||
979 | } | | |||
980 | #endif | | |||
981 | } | 661 | } | ||
982 | 662 | | |||
983 | //------------------------------------------------------------------------------ | 663 | //------------------------------------------------------------------------------ | ||
984 | // Name: | 664 | // Name: | ||
985 | //------------------------------------------------------------------------------ | 665 | //------------------------------------------------------------------------------ | ||
986 | knumber_base *knumber_float::exp() { | 666 | knumber_base *knumber_float::exp() { | ||
987 | #ifdef KNUMBER_USE_MPFR | 667 | return execute_mpfr_func< ::mpfr_exp>(); | ||
988 | mpfr_t mpfr; | | |||
989 | mpfr_init_set_f(mpfr, mpf_, rounding_mode); | | |||
990 | mpfr_exp(mpfr, mpfr, rounding_mode); | | |||
991 | mpfr_get_f(mpf_, mpfr, rounding_mode); | | |||
992 | mpfr_clear(mpfr); | | |||
993 | return this; | | |||
994 | #else | | |||
995 | const double x = mpf_get_d(mpf_); | | |||
996 | if(isinf(x)) { | | |||
997 | delete this; | | |||
998 | return new knumber_error(knumber_error::ERROR_POS_INFINITY); | | |||
999 | } else { | | |||
1000 | return execute_libc_func< ::exp>(x); | | |||
1001 | } | | |||
1002 | #endif | | |||
1003 | } | 668 | } | ||
1004 | 669 | | |||
1005 | //------------------------------------------------------------------------------ | 670 | //------------------------------------------------------------------------------ | ||
1006 | // Name: | 671 | // Name: | ||
1007 | //------------------------------------------------------------------------------ | 672 | //------------------------------------------------------------------------------ | ||
1008 | quint64 knumber_float::toUint64() const { | 673 | quint64 knumber_float::toUint64() const { | ||
1009 | return knumber_integer(this).toUint64(); | 674 | return knumber_integer(this).toUint64(); | ||
1010 | } | 675 | } | ||
Show All 18 Lines |