Qore Programming Language 2.1.2
Loading...
Searching...
No Matches
qore_number_private.h
1/* -*- mode: c++; indent-tabs-mode: nil -*- */
2/*
3 qore_number_private.h
4
5 Qore Programming Language
6
7 Copyright (C) 2003 - 2024 Qore Technologies, s.r.o.
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 and/or sell copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26
27 Note that the Qore library is released under a choice of three open-source
28 licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
29 information.
30*/
31
32#ifndef _QORE_QORE_NUMBER_PRIVATE_H
33
34#define _QORE_QORE_NUMBER_PRIVATE_H
35
36#include <cmath>
37#include <memory>
38using namespace std;
39
40// the number of consecutive trailing 0 or 9 digits that will be rounded in string output
41#define QORE_MPFR_ROUND_THRESHOLD 9
42// the number of consecutive trailing 0 or 9 digits that will be rounded in string output if there are 2 trailing non-0/9 digits
43#define QORE_MPFR_ROUND_THRESHOLD_2 15
44
45// the magic precesion number that indicates that all decimals should be included in the output string when formatting
46#define QORE_NUM_ALL_DIGITS -999999
47
48#define QORE_DEFAULT_PREC 128
49#define QORE_MAX_PREC 8192
50#ifndef HAVE_MPFR_RNDN
51#define MPFR_RNDN GMP_RNDN
52#define MPFR_RNDZ GMP_RNDZ
53#endif
54// round to nearest (roundTiesToEven in IEEE 754-2008)
55#define QORE_MPFR_RND MPFR_RNDN
56// round toward zero
57#define QORE_MPFR_RNDZ MPFR_RNDZ
58// MPFR_RNDA
59
60#ifndef HAVE_MPFR_EXP_T
61typedef mp_exp_t mpfr_exp_t;
62#endif
63
64#ifdef HAVE_MPFR_SPRINTF
65#define QORE_MPFR_SPRINTF_ARG 'R'
66#else
67#define QORE_MPFR_SPRINTF_ARG 'L'
68#endif
69
70// some compilers (sun/oracle pro c notably) do not support arrays with a variable size
71// if not, we can't use the stack for the temporary variable and have to use a dynamically-allocated one
72// also MPFR_DECL_INIT is compiled incorrectly on g 5.2 on Solaris SPARC with all optimization levels
73// for some unknown reason (https://github.com/qorelanguage/qore/issues/958)
74#if defined(HAVE_LOCAL_VARIADIC_ARRAYS) && !(defined(SPARC) && defined(SOLARIS) && defined(__GNUC__))
75#define MPFR_TMP_VAR(x, p) MPFR_DECL_INIT(x, (p))
76#else
77#define MPFR_TMP_VAR(x, p) qore_number_private tmp_x((mpfr_prec_t)p); mpfr_t& x = tmp_x.num
78#endif
79
80// for binary operations on MPFR data
81typedef int (*q_mpfr_binary_func_t)(mpfr_t, const mpfr_t, const mpfr_t, mpfr_rnd_t);
82// for unary operations on MPFR data
83typedef int (*q_mpfr_unary_func_t)(mpfr_t, const mpfr_t, mpfr_rnd_t);
84// for unary operations on MPFR data without a rounding argument
85typedef int (*q_mpfr_unary_nr_func_t)(mpfr_t, const mpfr_t);
86
87hashdecl qore_number_private_intern {
88 mpfr_t num;
89
90 DLLLOCAL qore_number_private_intern() {
91 mpfr_init2(num, QORE_DEFAULT_PREC);
92 }
93
94 DLLLOCAL qore_number_private_intern(mpfr_prec_t prec) {
95 if (prec > QORE_MAX_PREC)
96 prec = QORE_MAX_PREC;
97 mpfr_init2(num, prec);
98 }
99
100 DLLLOCAL ~qore_number_private_intern() {
101 mpfr_clear(num);
102 }
103
104 DLLLOCAL void checkPrec(q_mpfr_binary_func_t func, const mpfr_t r) {
105 mpfr_prec_t prec;
106 if (func == mpfr_mul || func == mpfr_div) {
107 prec = mpfr_get_prec(num) + mpfr_get_prec(r);
108 } else {
109 prec = QORE_MAX(mpfr_get_prec(num), mpfr_get_prec(r)) + 1;
110 }
111 if (prec > mpfr_get_prec(num))
112 mpfr_prec_round(num, prec, QORE_MPFR_RND);
113 }
114
115 DLLLOCAL void setPrec(mpfr_prec_t prec) {
116 if (prec > QORE_MAX_PREC)
117 prec = QORE_MAX_PREC;
118 mpfr_prec_round(num, prec, QORE_MPFR_RND);
119 }
120
121 DLLLOCAL static void do_divide_by_zero(ExceptionSink* xsink) {
122 xsink->raiseException("DIVISION-BY-ZERO", "division by zero error in numeric operator");
123 }
124
125 DLLLOCAL static void checkFlags(ExceptionSink* xsink) {
126#ifdef HAVE_MPFR_DIVBY0
127 if (mpfr_divby0_p()) {
128 mpfr_clear_divby0();
129 do_divide_by_zero(xsink);
130 }
131#endif
132 if (mpfr_erangeflag_p()) {
133 mpfr_clear_erangeflag();
134 xsink->raiseException("INVALID-NUMERIC-OPERATION", "invalid numeric operation attempted");
135 }
136 }
137};
138
139hashdecl qore_number_private : public qore_number_private_intern {
140 DLLLOCAL explicit qore_number_private(mpfr_prec_t prec) : qore_number_private_intern(prec) {
141 }
142
143 DLLLOCAL qore_number_private(double f) {
144 /* from the MPFR docs: http://www.mpfr.org/mpfr-current/mpfr.html
145 Note: If you want to store a floating-point constant to a mpfr_t, you should use mpfr_set_str
146 (or one of the MPFR constant functions, such as mpfr_const_pi for Pi) instead of mpfr_set_flt,
147 mpfr_set_d, mpfr_set_ld or mpfr_set_decimal64. Otherwise the floating-point constant will be
148 first converted into a reduced-precision (e.g., 53-bit) binary (or decimal, for
149 mpfr_set_decimal64) number before MPFR can work with it.
150 */
151
152 QoreStringMaker str("%.17g", f);
153 mpfr_set_str(num, str.getBuffer(), 10, QORE_MPFR_RND);
154 }
155
156 DLLLOCAL qore_number_private(int64 i) {
157 mpfr_set_sj(num, i, QORE_MPFR_RND);
158 }
159
160 DLLLOCAL qore_number_private(const char* str) : qore_number_private_intern(QORE_MAX(QORE_DEFAULT_PREC, strlen(str)*5)) {
161 // see if number has an exponent and increase the number's precision if necessary
162 const char* p = strchrs(str, "eE");
163 if (p) {
164 int exp = abs(atoi(p + 1));
165 mpfr_prec_t np = exp * 5;
166 if (np > getPrec())
167 setPrec(np);
168 }
169 if (!str[0])
170 mpfr_set_sj(num, 0, QORE_MPFR_RND);
171 else
172 mpfr_set_str(num, str, 10, QORE_MPFR_RND);
173 }
174
175 DLLLOCAL qore_number_private(const char* str, unsigned prec) : qore_number_private_intern(QORE_MAX(QORE_DEFAULT_PREC, prec)) {
176 mpfr_set_str(num, str, 10, QORE_MPFR_RND);
177 }
178
179 DLLLOCAL qore_number_private(const qore_number_private& old) : qore_number_private_intern(mpfr_get_prec(old.num)) {
180 mpfr_set(num, old.num, QORE_MPFR_RND);
181 }
182
183 DLLLOCAL double getAsFloat() const {
184 return mpfr_get_d(num, QORE_MPFR_RND);
185 }
186
187 DLLLOCAL int64 getAsBigInt() const {
188 return mpfr_get_sj(num, QORE_MPFR_RNDZ);
189 }
190
191 DLLLOCAL bool getAsBool() const {
192 return !zero();
193 }
194
195 DLLLOCAL bool zero() const {
196 return (bool)mpfr_zero_p(num);
197 }
198
199 DLLLOCAL bool nan() const {
200 return (bool)mpfr_nan_p(num);
201 }
202
203 DLLLOCAL bool inf() const {
204 return (bool)mpfr_inf_p(num);
205 }
206
207 DLLLOCAL bool number() const {
208 return (bool)mpfr_number_p(num);
209 }
210
211#ifdef HAVE_MPFR_REGULAR
212 // regular and not zero
213 DLLLOCAL bool regular() const {
214 return (bool)mpfr_regular_p(num);
215 }
216#endif
217
218 DLLLOCAL int sign() const {
219 return mpfr_sgn(num);
220 }
221
222 DLLLOCAL void sprintf(QoreString& str, const char* fmt) const {
223#ifdef HAVE_MPFR_SPRINTF
224 //printd(5, "qore_number_private::sprintf() fmt: '%s'\n", fmt);
225 int len = mpfr_snprintf(0, 0, fmt, num);
226 if (!len)
227 return;
228 if (len < 0) {
229 numError(str);
230 return;
231 }
232 str.allocate(str.size() + len + 1);
233 mpfr_sprintf((char*)(str.getBuffer() + str.size()), fmt, num);
234 str.terminate(str.size() + len);
235#else
236 // if there is no mpfr_sprintf, then we convert to a long double and output the number
237 long double ld = mpfr_get_ld(num, QORE_MPFR_RND);
238 int len = ::snprintf(0, 0, fmt, ld);
239 if (len <= 0)
240 return;
241 str.allocate(str.size() + len + 1);
242 ::sprintf((char*)(str.getBuffer() + str.size()), fmt, ld);
243 str.terminate(str.size() + len);
244#endif
245 }
246
247 DLLLOCAL void getScientificString(QoreString& str, bool round = true) const {
248#ifdef HAVE_MPFR_SPRINTF
249 sprintf(str, "%Re");
250#else
251 sprintf(str, "%Le");
252#endif
253
254 if (round) {
255 qore_offset_t i = str.find('.');
256 if (i != -1) {
257 qore_offset_t e = str.rfind('e');
258 if (e != -1) {
259 applyRoundingHeuristic(str, i, e);
260 }
261 }
262 }
263 }
264
265 DLLLOCAL void getAsString(QoreString& str, bool round = true, int base = 10) const;
266
267 DLLLOCAL void toString(QoreString& str, int fmt = QORE_NF_DEFAULT) const {
268 bool raw = !(fmt & QORE_NF_RAW);
269 if (fmt & QORE_NF_SCIENTIFIC)
270 getScientificString(str, raw);
271 else
272 getAsString(str, raw);
273 }
274
275 DLLLOCAL int format(QoreString& str, const QoreString& fmt, ExceptionSink* xsink) {
276 getAsString(str);
277 return formatNumberString(str, fmt, xsink);
278 }
279
280 DLLLOCAL int format(QoreString& str, int prec, const QoreString& dsep_str, const QoreString& tsep_str, ExceptionSink* xsink) {
281 getAsString(str);
282 return formatNumberString(str, prec, dsep_str, tsep_str, xsink);
283 }
284
285 DLLLOCAL bool lessThan(const qore_number_private& right) const {
286 return mpfr_less_p(num, right.num);
287 }
288
289 DLLLOCAL bool lessThan(double right) const {
290 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
291 if (mpfr_nan_p(num) || std::isnan(right)) // If any of the "numbers" is NaN.
292 return false;
293 mpfr_set_d(r, right, QORE_MPFR_RND);
294 return mpfr_less_p(num, r);
295 }
296
297 DLLLOCAL bool lessThan(int64 right) const {
298 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
299 if (mpfr_nan_p(num)) // If the number is NaN.
300 return false;
301 mpfr_set_sj(r, right, QORE_MPFR_RND);
302 return mpfr_less_p(num, r);
303 }
304
305 DLLLOCAL bool lessThanOrEqual(const qore_number_private& right) const {
306 return mpfr_lessequal_p(num, right.num);
307 }
308
309 DLLLOCAL bool lessThanOrEqual(double right) const {
310 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
311 if (mpfr_nan_p(num) || std::isnan(right)) // If any of the "numbers" is NaN.
312 return false;
313 mpfr_set_d(r, right, QORE_MPFR_RND);
314 return mpfr_lessequal_p(num, r);
315 }
316
317 DLLLOCAL bool lessThanOrEqual(int64 right) const {
318 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
319 if (mpfr_nan_p(num)) // If the number is NaN.
320 return false;
321 mpfr_set_sj(r, right, QORE_MPFR_RND);
322 return mpfr_lessequal_p(num, r);
323 }
324
325 DLLLOCAL bool greaterThan(const qore_number_private& right) const {
326 return mpfr_greater_p(num, right.num);
327 }
328
329 DLLLOCAL bool greaterThan(double right) const {
330 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
331 if (mpfr_nan_p(num) || std::isnan(right)) // If any of the "numbers" is NaN.
332 return false;
333 mpfr_set_d(r, right, QORE_MPFR_RND);
334 return mpfr_greater_p(num, r);
335 }
336
337 DLLLOCAL bool greaterThan(int64 right) const {
338 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
339 if (mpfr_nan_p(num)) // If the number is NaN.
340 return false;
341 mpfr_set_sj(r, right, QORE_MPFR_RND);
342 return mpfr_greater_p(num, r);
343 }
344
345 DLLLOCAL bool greaterThanOrEqual(const qore_number_private& right) const {
346 return mpfr_greaterequal_p(num, right.num);
347 }
348
349 DLLLOCAL bool greaterThanOrEqual(double right) const {
350 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
351 if (mpfr_nan_p(num) || std::isnan(right)) // If any of the "numbers" is NaN.
352 return false;
353 mpfr_set_d(r, right, QORE_MPFR_RND);
354 return mpfr_greaterequal_p(num, r);
355 }
356
357 DLLLOCAL bool greaterThanOrEqual(int64 right) const {
358 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
359 if (mpfr_nan_p(num)) // If the number is NaN.
360 return false;
361 mpfr_set_sj(r, right, QORE_MPFR_RND);
362 return mpfr_greaterequal_p(num, r);
363 }
364
365 DLLLOCAL bool equals(const qore_number_private& right) const {
366 return mpfr_equal_p(num, right.num);
367 }
368
369 DLLLOCAL bool equals(double right) const {
370 if (mpfr_nan_p(num) || std::isnan(right)) // If any of the "numbers" is NaN.
371 return false;
372 return 0 == mpfr_cmp_d(num, right);
373 }
374
375 DLLLOCAL bool equals(int64 right) const {
376 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
377 if (mpfr_nan_p(num)) // If the number is NaN.
378 return false;
379 mpfr_set_sj(r, right, QORE_MPFR_RND);
380 return mpfr_equal_p(num, r);
381 }
382
383 DLLLOCAL qore_number_private* doBinary(q_mpfr_binary_func_t func, const qore_number_private& r, ExceptionSink* xsink = 0) const {
384 mpfr_prec_t prec;
385 if (func == mpfr_pow) {
386 prec = mpfr_get_prec(num) * QORE_MIN(QORE_MAX_PREC, r.getAsBigInt());
387 } else if (func == mpfr_mul || func == mpfr_div) {
388 prec = mpfr_get_prec(num) + mpfr_get_prec(r.num);
389 } else {
390 prec = QORE_MAX(mpfr_get_prec(num), mpfr_get_prec(r.num)) + 1;
391 }
392 std::unique_ptr<qore_number_private> p(new qore_number_private(prec));
393 func(p->num, num, r.num, QORE_MPFR_RND);
394 if (xsink)
395 checkFlags(xsink);
396
397 return (xsink && *xsink) ? 0 : p.release();
398 }
399
400 DLLLOCAL qore_number_private* doPlus(const qore_number_private& r) const {
401 return doBinary(mpfr_add, r);
402 }
403
404 DLLLOCAL qore_number_private* doMinus(const qore_number_private& r) const {
405 return doBinary(mpfr_sub, r);
406 }
407
408 DLLLOCAL qore_number_private* doMultiply(const qore_number_private& r) const {
409 return doBinary(mpfr_mul, r);
410 }
411
412 DLLLOCAL qore_number_private* doDivideBy(const qore_number_private& r, ExceptionSink* xsink) const {
413#ifndef HAVE_MPFR_DIVBY0
414 if (r.zero()) {
415 do_divide_by_zero(xsink);
416 return 0;
417 }
418#endif
419 return doBinary(mpfr_div, r, xsink);
420 }
421
422 DLLLOCAL qore_number_private* doUnary(q_mpfr_unary_func_t func, ExceptionSink* xsink = 0) const {
423 qore_number_private* p = new qore_number_private(*this);
424 func(p->num, num, QORE_MPFR_RND);
425 if (xsink)
426 checkFlags(xsink);
427
428 return p;
429 }
430
431 DLLLOCAL void negateInPlace() {
432 mpfr_neg(num, num, QORE_MPFR_RND);
433 }
434
435 DLLLOCAL qore_number_private* negate() const {
436 return doUnary(mpfr_neg);
437 }
438
439 DLLLOCAL qore_number_private* absolute() const {
440 return doUnary(mpfr_abs);
441 }
442
443 DLLLOCAL qore_number_private* doUnaryNR(q_mpfr_unary_nr_func_t func, ExceptionSink* xsink = 0) const {
444 qore_number_private* p = new qore_number_private(*this);
445 func(p->num, num);
446 if (xsink)
447 checkFlags(xsink);
448
449 return p;
450 }
451
452 // for round functions: round(), ceil(), floor()
453 DLLLOCAL qore_number_private* doRoundNR(q_mpfr_unary_nr_func_t func, int prec = 0, ExceptionSink* xsink = NULL) const {
454 unique_ptr<qore_number_private> p0(new qore_number_private(*this));
455
456 if (prec == 0) {
457 func(p0 -> num, num);
458
459 if (xsink)
460 checkFlags(xsink);
461
462 return p0.release();
463 }
464
465 qore_number_private* p2;
466
467 if (prec > 0) {
468 unique_ptr<qore_number_private> c(new qore_number_private(pow(10, prec)));
469 unique_ptr<qore_number_private> p1(p0 -> doMultiply(*c));
470 func(p1 -> num, p1 -> num);
471 p2 = p1 -> doDivideBy(*c, xsink);
472 } else {
473 unique_ptr<qore_number_private> c(new qore_number_private(pow(10, -prec)));
474 unique_ptr<qore_number_private> p1(p0 -> doDivideBy(*c, xsink));
475 func(p1 -> num, p1 -> num);
476 p2 = p1 -> doMultiply(*c);
477 }
478
479 if (xsink)
480 checkFlags(xsink);
481
482 return p2;
483 }
484
485 DLLLOCAL mpfr_prec_t getPrec() const {
486 return mpfr_get_prec(num);
487 }
488
489 DLLLOCAL void inc() {
490 MPFR_TMP_VAR(tmp, mpfr_get_prec(num));
491 mpfr_set(tmp, num, QORE_MPFR_RND);
492 mpfr_add_si(num, tmp, 1, QORE_MPFR_RND);
493 }
494
495 DLLLOCAL void dec() {
496 MPFR_TMP_VAR(tmp, mpfr_get_prec(num));
497 mpfr_set(tmp, num, QORE_MPFR_RND);
498 mpfr_sub_si(num, tmp, 1, QORE_MPFR_RND);
499 }
500
501 DLLLOCAL void doBinaryInplace(q_mpfr_binary_func_t func, const qore_number_private& r, ExceptionSink* xsink = 0) {
502 checkPrec(func, r.num);
503 // some compilers (sun/oracle pro c++ notably) do not support arrays with a variable size
504 // if not, we can't use the stack for the temporary variable and have to use a dynamically-allocated one
505 MPFR_TMP_VAR(tmp, mpfr_get_prec(num));
506 mpfr_set(tmp, num, QORE_MPFR_RND);
507 func(num, tmp, r.num, QORE_MPFR_RND);
508 if (xsink)
509 checkFlags(xsink);
510 }
511
512 DLLLOCAL void plusEquals(const qore_number_private& r) {
513 doBinaryInplace(mpfr_add, r);
514 }
515
516 DLLLOCAL void minusEquals(const qore_number_private& r) {
517 doBinaryInplace(mpfr_sub, r);
518 }
519
520 DLLLOCAL void multiplyEquals(const qore_number_private& r) {
521 doBinaryInplace(mpfr_mul, r);
522 }
523
524 DLLLOCAL void divideEquals(const qore_number_private& r) {
525 assert(!r.zero());
526 doBinaryInplace(mpfr_div, r);
527 }
528
529 DLLLOCAL static void negateInPlace(QoreNumberNode& n) {
530 n.priv->negateInPlace();
531 }
532
533 DLLLOCAL static int doRound(QoreString& num, qore_offset_t& dp, int prec);
534
535 DLLLOCAL static int formatNumberString(QoreString& num, const QoreString& fmt, ExceptionSink* xsink);
536
537 DLLLOCAL static int formatNumberString(QoreString& num, int prec, const QoreString& dsep_str, const QoreString& tsep_str, ExceptionSink* xsink);
538
539protected:
540 // assumes dsep, tsep and num all have the same encoding
541 DLLLOCAL static int formatNumberStringIntern(QoreString& num, int prec, const QoreString& dsep, const QoreString& tsep, ExceptionSink* xsink);
542
543public:
544 DLLLOCAL static void numError(QoreString& str) {
545 str.concat("<number error>");
546 }
547
548 // try to remove noise from the binary -> decimal conversion process in insignificant digits
549 DLLLOCAL static void applyRoundingHeuristic(QoreString& str, size_t dp, size_t last,
550 int round_threshold_1 = QORE_MPFR_ROUND_THRESHOLD, int round_threshold_2 = QORE_MPFR_ROUND_THRESHOLD_2);
551
552 // try to remove noise from the binary -> decimal conversion process in insignificant digits
555 DLLLOCAL static void applyRoundingHeuristicToString(QoreString& str,
556 int round_threshold_1 = QORE_MPFR_ROUND_THRESHOLD,
557 int round_threshold_2 = QORE_MPFR_ROUND_THRESHOLD_2) {
558 qore_offset_t i = str.find('.');
559 if (i != -1) {
560 applyRoundingHeuristic(str, i, str.size(), round_threshold_1, round_threshold_2);
561 }
562 }
563
564 // returns number of digits inserted
565 DLLLOCAL static int roundUp(QoreString& str, qore_offset_t pos);
566
567 // static accessor methods
568 DLLLOCAL static void sprintf(const QoreNumberNode& n, QoreString& str, const char* fmt) {
569 n.priv->sprintf(str, fmt);
570 }
571
572 DLLLOCAL static void inc(QoreNumberNode& n) {
573 n.priv->inc();
574 }
575
576 DLLLOCAL static void dec(QoreNumberNode& n) {
577 n.priv->dec();
578 }
579
580 DLLLOCAL static void plusEquals(QoreNumberNode& n, const QoreNumberNode& r) {
581 n.priv->plusEquals(*r.priv);
582 }
583
584 DLLLOCAL static void minusEquals(QoreNumberNode& n, const QoreNumberNode& r) {
585 n.priv->minusEquals(*r.priv);
586 }
587
588 DLLLOCAL static void multiplyEquals(QoreNumberNode& n, const QoreNumberNode& r) {
589 n.priv->multiplyEquals(*r.priv);
590 }
591
592 DLLLOCAL static void divideEquals(QoreNumberNode& n, const QoreNumberNode& r) {
593 n.priv->divideEquals(*r.priv);
594 }
595
596 DLLLOCAL static QoreNumberNode* doUnary(const QoreNumberNode& n, q_mpfr_unary_func_t func, ExceptionSink* xsink = 0) {
597 qore_number_private* p = n.priv->doUnary(func, xsink);
598 return p ? new QoreNumberNode(p) : 0;
599 }
600
601 DLLLOCAL static QoreNumberNode* doBinary(const QoreNumberNode& n, q_mpfr_binary_func_t func, const QoreNumberNode& r, ExceptionSink* xsink = 0) {
602 qore_number_private* p = n.priv->doBinary(func, *r.priv, xsink);
603 return p ? new QoreNumberNode(p) : 0;
604 }
605
606 DLLLOCAL static QoreNumberNode* doUnaryNR(const QoreNumberNode& n, q_mpfr_unary_nr_func_t func, ExceptionSink* xsink = 0) {
607 qore_number_private* p = n.priv->doUnaryNR(func, xsink);
608 return p ? new QoreNumberNode(p) : 0;
609 }
610
611 DLLLOCAL static QoreNumberNode* doRoundNR(const QoreNumberNode& n, q_mpfr_unary_nr_func_t func, int prec = 0, ExceptionSink* xsink = 0) {
612 qore_number_private* p = n.priv->doRoundNR(func, prec, xsink);
613 return p ? new QoreNumberNode(p) : 0;
614 }
615
616 DLLLOCAL static QoreNumberNode* getNaNumber() {
617 return new QoreNumberNode(new qore_number_private("@NaN@"));
618 }
619
620 DLLLOCAL static QoreNumberNode* getInfinity() {
621 return new QoreNumberNode(new qore_number_private("@Inf@"));
622 }
623
624 DLLLOCAL static QoreNumberNode* getPi() {
625 qore_number_private* p = new qore_number_private(0ll);
626 mpfr_const_pi(p->num, QORE_MPFR_RND);
627 return new QoreNumberNode(p);
628 }
629
630 DLLLOCAL static qore_number_private* get(const QoreNumberNode& n) {
631 return n.priv;
632 }
633
634 DLLLOCAL static QoreStringNode* toBase(double f, int base, ExceptionSink* xsink) {
635 std::unique_ptr<qore_number_private> n(new qore_number_private(f));
636 return qore_number_private::toBase(n.get(), base, xsink);
637 }
638
639 DLLLOCAL static QoreStringNode* toBase(const QoreNumberNode& n, int base, ExceptionSink* xsink) {
640 return qore_number_private::toBase(n.priv, base, xsink);
641 }
642
643 DLLLOCAL static QoreStringNode* toBase(qore_number_private* n, int base, ExceptionSink* xsink) {
644 if (base < 2 || base > 36) {
645 xsink -> raiseException("INVALID-BASE", "base %d is invalid; base must be 2 - 36 inclusive", base);
646 return 0;
647 }
648
649 QoreString qs;
650 n -> getAsString(qs, 1, base);
651 qs.toupr();
652 return new QoreStringNode(qs);
653 }
654};
655
656#endif
static char * strchrs(const char *str, const char *chars)
find one of any characters in a string
Definition QoreLib.h:247
#define QORE_MAX(a, b)
macro to return the maximum of 2 numbers
Definition QoreLib.h:613
#define QORE_MIN(a, b)
macro to return the minimum of 2 numbers
Definition QoreLib.h:616
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition ExceptionSink.h:50
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
Qore's arbitrary-precision number value type, dynamically-allocated only, reference counted.
Definition QoreNumberNode.h:51
hashdecl qore_number_private * priv
the private implementation of the type
Definition QoreNumberNode.h:69
Qore's string type supported by the QoreEncoding class.
Definition QoreString.h:93
DLLEXPORT void terminate(size_t size)
terminates the string at byte position "size", the string is reallocated if necessary
DLLEXPORT void allocate(unsigned requested_size)
Ensure the internal buffer has at least expected size in bytes.
DLLEXPORT void concat(const QoreString *str, ExceptionSink *xsink)
concatenates a string and converts encodings if necessary
DLLEXPORT const char * getBuffer() const
returns the string's buffer; this data should not be changed
DLLEXPORT qore_offset_t find(char c, qore_offset_t pos=0) const
returns the byte position of a character (byte) within the string or -1 if not found
DLLEXPORT size_t size() const
returns number of bytes in the string (not including the null pointer)
DLLEXPORT void toupr()
converts the string to upper-case in place
DLLEXPORT qore_offset_t rfind(char c, qore_offset_t pos=-1) const
returns the last byte position of a character (byte) within the string or -1 if not found
Qore's string value type, reference counted, dynamically-allocated only.
Definition QoreStringNode.h:50
intptr_t qore_offset_t
used for offsets that could be negative
Definition common.h:82
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition common.h:266
#define QORE_NF_DEFAULT
Definition QoreNumberNode.h:43
#define QORE_NF_RAW
number format bitfield: raw (unrounded)
Definition QoreNumberNode.h:47
#define QORE_NF_SCIENTIFIC
number format bitfield: scientific
Definition QoreNumberNode.h:45