Qore Programming Language  0.9.3.2
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 - 2017 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>
38 using 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
61 typedef 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
81 typedef int (*q_mpfr_binary_func_t)(mpfr_t, const mpfr_t, const mpfr_t, mpfr_rnd_t);
82 // for unary operations on MPFR data
83 typedef 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
85 typedef int (*q_mpfr_unary_nr_func_t)(mpfr_t, const mpfr_t);
86 
87 hashdecl 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 
139 hashdecl 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  if (round) {
254  qore_offset_t i = str.find('.');
255  if (i != -1) {
256  qore_offset_t e = str.rfind('e');
257  if (e != -1)
258  applyRoundingHeuristic(str, i, e);
259  }
260  }
261  }
262 
263  DLLLOCAL void getAsString(QoreString& str, bool round = true, int base = 10) const;
264 
265  DLLLOCAL void toString(QoreString& str, int fmt = QORE_NF_DEFAULT) const {
266  bool raw = !(fmt & QORE_NF_RAW);
267  if (fmt & QORE_NF_SCIENTIFIC)
268  getScientificString(str, raw);
269  else
270  getAsString(str, raw);
271  }
272 
273  DLLLOCAL int format(QoreString& str, const QoreString& fmt, ExceptionSink* xsink) {
274  getAsString(str);
275  return formatNumberString(str, fmt, xsink);
276  }
277 
278  DLLLOCAL int format(QoreString& str, int prec, const QoreString& dsep_str, const QoreString& tsep_str, ExceptionSink* xsink) {
279  getAsString(str);
280  return formatNumberString(str, prec, dsep_str, tsep_str, xsink);
281  }
282 
283  DLLLOCAL bool lessThan(const qore_number_private& right) const {
284  return mpfr_less_p(num, right.num);
285  }
286 
287  DLLLOCAL bool lessThan(double right) const {
288  MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
289  if (mpfr_nan_p(num) || std::isnan(right)) // If any of the "numbers" is NaN.
290  return false;
291  mpfr_set_d(r, right, QORE_MPFR_RND);
292  return mpfr_less_p(num, r);
293  }
294 
295  DLLLOCAL bool lessThan(int64 right) const {
296  MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
297  if (mpfr_nan_p(num)) // If the number is NaN.
298  return false;
299  mpfr_set_sj(r, right, QORE_MPFR_RND);
300  return mpfr_less_p(num, r);
301  }
302 
303  DLLLOCAL bool lessThanOrEqual(const qore_number_private& right) const {
304  return mpfr_lessequal_p(num, right.num);
305  }
306 
307  DLLLOCAL bool lessThanOrEqual(double right) const {
308  MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
309  if (mpfr_nan_p(num) || std::isnan(right)) // If any of the "numbers" is NaN.
310  return false;
311  mpfr_set_d(r, right, QORE_MPFR_RND);
312  return mpfr_lessequal_p(num, r);
313  }
314 
315  DLLLOCAL bool lessThanOrEqual(int64 right) const {
316  MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
317  if (mpfr_nan_p(num)) // If the number is NaN.
318  return false;
319  mpfr_set_sj(r, right, QORE_MPFR_RND);
320  return mpfr_lessequal_p(num, r);
321  }
322 
323  DLLLOCAL bool greaterThan(const qore_number_private& right) const {
324  return mpfr_greater_p(num, right.num);
325  }
326 
327  DLLLOCAL bool greaterThan(double right) const {
328  MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
329  if (mpfr_nan_p(num) || std::isnan(right)) // If any of the "numbers" is NaN.
330  return false;
331  mpfr_set_d(r, right, QORE_MPFR_RND);
332  return mpfr_greater_p(num, r);
333  }
334 
335  DLLLOCAL bool greaterThan(int64 right) const {
336  MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
337  if (mpfr_nan_p(num)) // If the number is NaN.
338  return false;
339  mpfr_set_sj(r, right, QORE_MPFR_RND);
340  return mpfr_greater_p(num, r);
341  }
342 
343  DLLLOCAL bool greaterThanOrEqual(const qore_number_private& right) const {
344  return mpfr_greaterequal_p(num, right.num);
345  }
346 
347  DLLLOCAL bool greaterThanOrEqual(double right) const {
348  MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
349  if (mpfr_nan_p(num) || std::isnan(right)) // If any of the "numbers" is NaN.
350  return false;
351  mpfr_set_d(r, right, QORE_MPFR_RND);
352  return mpfr_greaterequal_p(num, r);
353  }
354 
355  DLLLOCAL bool greaterThanOrEqual(int64 right) const {
356  MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
357  if (mpfr_nan_p(num)) // If the number is NaN.
358  return false;
359  mpfr_set_sj(r, right, QORE_MPFR_RND);
360  return mpfr_greaterequal_p(num, r);
361  }
362 
363  DLLLOCAL bool equals(const qore_number_private& right) const {
364  return mpfr_equal_p(num, right.num);
365  }
366 
367  DLLLOCAL bool equals(double right) const {
368  if (mpfr_nan_p(num) || std::isnan(right)) // If any of the "numbers" is NaN.
369  return false;
370  return 0 == mpfr_cmp_d(num, right);
371  }
372 
373  DLLLOCAL bool equals(int64 right) const {
374  MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
375  if (mpfr_nan_p(num)) // If the number is NaN.
376  return false;
377  mpfr_set_sj(r, right, QORE_MPFR_RND);
378  return mpfr_equal_p(num, r);
379  }
380 
381  DLLLOCAL qore_number_private* doBinary(q_mpfr_binary_func_t func, const qore_number_private& r, ExceptionSink* xsink = 0) const {
382  mpfr_prec_t prec;
383  if (func == mpfr_pow) {
384  prec = mpfr_get_prec(num) * QORE_MIN(QORE_MAX_PREC, r.getAsBigInt());
385  } else if (func == mpfr_mul || func == mpfr_div) {
386  prec = mpfr_get_prec(num) + mpfr_get_prec(r.num);
387  } else {
388  prec = QORE_MAX(mpfr_get_prec(num), mpfr_get_prec(r.num)) + 1;
389  }
390  std::unique_ptr<qore_number_private> p(new qore_number_private(prec));
391  func(p->num, num, r.num, QORE_MPFR_RND);
392  if (xsink)
393  checkFlags(xsink);
394 
395  return (xsink && *xsink) ? 0 : p.release();
396  }
397 
398  DLLLOCAL qore_number_private* doPlus(const qore_number_private& r) const {
399  return doBinary(mpfr_add, r);
400  }
401 
402  DLLLOCAL qore_number_private* doMinus(const qore_number_private& r) const {
403  return doBinary(mpfr_sub, r);
404  }
405 
406  DLLLOCAL qore_number_private* doMultiply(const qore_number_private& r) const {
407  return doBinary(mpfr_mul, r);
408  }
409 
410  DLLLOCAL qore_number_private* doDivideBy(const qore_number_private& r, ExceptionSink* xsink) const {
411 #ifndef HAVE_MPFR_DIVBY0
412  if (r.zero()) {
413  do_divide_by_zero(xsink);
414  return 0;
415  }
416 #endif
417  return doBinary(mpfr_div, r, xsink);
418  }
419 
420  DLLLOCAL qore_number_private* doUnary(q_mpfr_unary_func_t func, ExceptionSink* xsink = 0) const {
421  qore_number_private* p = new qore_number_private(*this);
422  func(p->num, num, QORE_MPFR_RND);
423  if (xsink)
424  checkFlags(xsink);
425 
426  return p;
427  }
428 
429  DLLLOCAL void negateInPlace() {
430  mpfr_neg(num, num, QORE_MPFR_RND);
431  }
432 
433  DLLLOCAL qore_number_private* negate() const {
434  return doUnary(mpfr_neg);
435  }
436 
437  DLLLOCAL qore_number_private* absolute() const {
438  return doUnary(mpfr_abs);
439  }
440 
441  DLLLOCAL qore_number_private* doUnaryNR(q_mpfr_unary_nr_func_t func, ExceptionSink* xsink = 0) const {
442  qore_number_private* p = new qore_number_private(*this);
443  func(p->num, num);
444  if (xsink)
445  checkFlags(xsink);
446 
447  return p;
448  }
449 
450  // for round functions: round(), ceil(), floor()
451  DLLLOCAL qore_number_private* doRoundNR(q_mpfr_unary_nr_func_t func, int prec = 0, ExceptionSink* xsink = NULL) const {
452  unique_ptr<qore_number_private> p0(new qore_number_private(*this));
453 
454  if (prec == 0) {
455  func(p0 -> num, num);
456 
457  if (xsink)
458  checkFlags(xsink);
459 
460  return p0.release();
461  }
462 
463  qore_number_private* p2;
464 
465  if (prec > 0) {
466  unique_ptr<qore_number_private> c(new qore_number_private(pow(10, prec)));
467  unique_ptr<qore_number_private> p1(p0 -> doMultiply(*c));
468  func(p1 -> num, p1 -> num);
469  p2 = p1 -> doDivideBy(*c, xsink);
470  }
471  else {
472  unique_ptr<qore_number_private> c(new qore_number_private(pow(10, -prec)));
473  unique_ptr<qore_number_private> p1(p0 -> doDivideBy(*c, xsink));
474  func(p1 -> num, p1 -> num);
475  p2 = p1 -> doMultiply(*c);
476  }
477 
478  if (xsink)
479  checkFlags(xsink);
480 
481  return p2;
482  }
483 
484  DLLLOCAL mpfr_prec_t getPrec() const {
485  return mpfr_get_prec(num);
486  }
487 
488  DLLLOCAL void inc() {
489  MPFR_TMP_VAR(tmp, mpfr_get_prec(num));
490  mpfr_set(tmp, num, QORE_MPFR_RND);
491  mpfr_add_si(num, tmp, 1, QORE_MPFR_RND);
492  }
493 
494  DLLLOCAL void dec() {
495  MPFR_TMP_VAR(tmp, mpfr_get_prec(num));
496  mpfr_set(tmp, num, QORE_MPFR_RND);
497  mpfr_sub_si(num, tmp, 1, QORE_MPFR_RND);
498  }
499 
500  DLLLOCAL void doBinaryInplace(q_mpfr_binary_func_t func, const qore_number_private& r, ExceptionSink* xsink = 0) {
501  checkPrec(func, r.num);
502  // some compilers (sun/oracle pro c++ notably) do not support arrays with a variable size
503  // if not, we can't use the stack for the temporary variable and have to use a dynamically-allocated one
504  MPFR_TMP_VAR(tmp, mpfr_get_prec(num));
505  mpfr_set(tmp, num, QORE_MPFR_RND);
506  func(num, tmp, r.num, QORE_MPFR_RND);
507  if (xsink)
508  checkFlags(xsink);
509  }
510 
511  DLLLOCAL void plusEquals(const qore_number_private& r) {
512  doBinaryInplace(mpfr_add, r);
513  }
514 
515  DLLLOCAL void minusEquals(const qore_number_private& r) {
516  doBinaryInplace(mpfr_sub, r);
517  }
518 
519  DLLLOCAL void multiplyEquals(const qore_number_private& r) {
520  doBinaryInplace(mpfr_mul, r);
521  }
522 
523  DLLLOCAL void divideEquals(const qore_number_private& r) {
524  assert(!r.zero());
525  doBinaryInplace(mpfr_div, r);
526  }
527 
528  DLLLOCAL static void negateInPlace(QoreNumberNode& n) {
529  n.priv->negateInPlace();
530  }
531 
532  DLLLOCAL static int doRound(QoreString& num, qore_offset_t& dp, int prec);
533 
534  DLLLOCAL static int formatNumberString(QoreString& num, const QoreString& fmt, ExceptionSink* xsink);
535 
536  DLLLOCAL static int formatNumberString(QoreString& num, int prec, const QoreString& dsep_str, const QoreString& tsep_str, ExceptionSink* xsink);
537 
538 protected:
539  // assumes dsep, tsep and num all have the same encoding
540  DLLLOCAL static int formatNumberStringIntern(QoreString& num, int prec, const QoreString& dsep, const QoreString& tsep, ExceptionSink* xsink);
541 
542 public:
543  DLLLOCAL static void numError(QoreString& str) {
544  str.concat("<number error>");
545  }
546 
547  // try to remove noise from the binary -> decimal conversion process in insignificant digits
548  DLLLOCAL static void applyRoundingHeuristic(QoreString& str, qore_size_t dp, qore_size_t last);
549 
550  // returns number of digits inserted
551  DLLLOCAL static int roundUp(QoreString& str, qore_offset_t pos);
552 
553  // static accessor methods
554  DLLLOCAL static void sprintf(const QoreNumberNode& n, QoreString& str, const char* fmt) {
555  n.priv->sprintf(str, fmt);
556  }
557 
558  DLLLOCAL static void inc(QoreNumberNode& n) {
559  n.priv->inc();
560  }
561 
562  DLLLOCAL static void dec(QoreNumberNode& n) {
563  n.priv->dec();
564  }
565 
566  DLLLOCAL static void plusEquals(QoreNumberNode& n, const QoreNumberNode& r) {
567  n.priv->plusEquals(*r.priv);
568  }
569 
570  DLLLOCAL static void minusEquals(QoreNumberNode& n, const QoreNumberNode& r) {
571  n.priv->minusEquals(*r.priv);
572  }
573 
574  DLLLOCAL static void multiplyEquals(QoreNumberNode& n, const QoreNumberNode& r) {
575  n.priv->multiplyEquals(*r.priv);
576  }
577 
578  DLLLOCAL static void divideEquals(QoreNumberNode& n, const QoreNumberNode& r) {
579  n.priv->divideEquals(*r.priv);
580  }
581 
582  DLLLOCAL static QoreNumberNode* doUnary(const QoreNumberNode& n, q_mpfr_unary_func_t func, ExceptionSink* xsink = 0) {
583  qore_number_private* p = n.priv->doUnary(func, xsink);
584  return p ? new QoreNumberNode(p) : 0;
585  }
586 
587  DLLLOCAL static QoreNumberNode* doBinary(const QoreNumberNode& n, q_mpfr_binary_func_t func, const QoreNumberNode& r, ExceptionSink* xsink = 0) {
588  qore_number_private* p = n.priv->doBinary(func, *r.priv, xsink);
589  return p ? new QoreNumberNode(p) : 0;
590  }
591 
592  DLLLOCAL static QoreNumberNode* doUnaryNR(const QoreNumberNode& n, q_mpfr_unary_nr_func_t func, ExceptionSink* xsink = 0) {
593  qore_number_private* p = n.priv->doUnaryNR(func, xsink);
594  return p ? new QoreNumberNode(p) : 0;
595  }
596 
597  DLLLOCAL static QoreNumberNode* doRoundNR(const QoreNumberNode& n, q_mpfr_unary_nr_func_t func, int prec = 0, ExceptionSink* xsink = 0) {
598  qore_number_private* p = n.priv->doRoundNR(func, prec, xsink);
599  return p ? new QoreNumberNode(p) : 0;
600  }
601 
602  DLLLOCAL static QoreNumberNode* getNaNumber() {
603  return new QoreNumberNode(new qore_number_private("@NaN@"));
604  }
605 
606  DLLLOCAL static QoreNumberNode* getInfinity() {
607  return new QoreNumberNode(new qore_number_private("@Inf@"));
608  }
609 
610  DLLLOCAL static QoreNumberNode* getPi() {
611  qore_number_private* p = new qore_number_private(0ll);
612  mpfr_const_pi(p->num, QORE_MPFR_RND);
613  return new QoreNumberNode(p);
614  }
615 
616  DLLLOCAL static qore_number_private* get(const QoreNumberNode& n) {
617  return n.priv;
618  }
619 
620  DLLLOCAL static QoreStringNode* toBase(double f, int base, ExceptionSink* xsink) {
621  std::unique_ptr<qore_number_private> n(new qore_number_private(f));
622  return qore_number_private::toBase(n.get(), base, xsink);
623  }
624 
625  DLLLOCAL static QoreStringNode* toBase(const QoreNumberNode& n, int base, ExceptionSink* xsink) {
626  return qore_number_private::toBase(n.priv, base, xsink);
627  }
628 
629  DLLLOCAL static QoreStringNode* toBase(qore_number_private* n, int base, ExceptionSink* xsink) {
630  if (base < 2 || base > 36) {
631  xsink -> raiseException("INVALID-BASE", "base %d is invalid; base must be 2 - 36 inclusive", base);
632  return 0;
633  }
634 
635  QoreString qs;
636  n -> getAsString(qs, 1, base);
637  qs.toupr();
638  return new QoreStringNode(qs);
639  }
640 };
641 
642 #endif
Qore&#39;s arbitrary-precision number value type, dynamically-allocated only, reference counted...
Definition: QoreNumberNode.h:51
#define QORE_NF_SCIENTIFIC
number format bitfield: scientific
Definition: QoreNumberNode.h:45
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 ...
STL namespace.
size_t qore_size_t
used for sizes (same range as a pointer)
Definition: common.h:73
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
Qore&#39;s string type supported by the QoreEncoding class.
Definition: QoreString.h:81
Qore&#39;s string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
DLLEXPORT const char * getBuffer() const
returns the string&#39;s buffer; this data should not be changed
DLLEXPORT void concat(const QoreString *str, ExceptionSink *xsink)
concatenates a string and converts encodings if necessary
hashdecl qore_number_private * priv
the private implementation of the type
Definition: QoreNumberNode.h:69
DLLEXPORT void toupr()
converts the string to upper-case in place
#define QORE_MAX(a, b)
macro to return the maximum of 2 numbers
Definition: QoreLib.h:535
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:46
#define QORE_NF_RAW
number format bitfield: raw (unrounded)
Definition: QoreNumberNode.h:47
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:260
DLLEXPORT void terminate(qore_size_t size)
terminates the string at byte position "size", the string is reallocated if necessary ...
intptr_t qore_offset_t
used for offsets that could be negative
Definition: common.h:76
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 ...
#define QORE_MIN(a, b)
macro to return the minimum of 2 numbers
Definition: QoreLib.h:538
#define QORE_NF_DEFAULT
number format bitfield: default
Definition: QoreNumberNode.h:43
DLLEXPORT void allocate(unsigned requested_size)
Ensure the internal buffer has at least expected size in bytes.
DLLEXPORT qore_size_t size() const
returns number of bytes in the string (not including the null pointer)
static char * strchrs(const char *str, const char *chars)
find one of any characters in a string
Definition: QoreLib.h:249