32 #ifndef _QORE_QORE_NUMBER_PRIVATE_H 34 #define _QORE_QORE_NUMBER_PRIVATE_H 41 #define QORE_MPFR_ROUND_THRESHOLD 9 43 #define QORE_MPFR_ROUND_THRESHOLD_2 15 46 #define QORE_NUM_ALL_DIGITS -999999 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 55 #define QORE_MPFR_RND MPFR_RNDN 57 #define QORE_MPFR_RNDZ MPFR_RNDZ 60 #ifndef HAVE_MPFR_EXP_T 61 typedef mp_exp_t mpfr_exp_t;
64 #ifdef HAVE_MPFR_SPRINTF 65 #define QORE_MPFR_SPRINTF_ARG 'R' 67 #define QORE_MPFR_SPRINTF_ARG 'L' 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)) 77 #define MPFR_TMP_VAR(x, p) qore_number_private tmp_x((mpfr_prec_t)p); mpfr_t& x = tmp_x.num 81 typedef int (*q_mpfr_binary_func_t)(mpfr_t,
const mpfr_t,
const mpfr_t, mpfr_rnd_t);
83 typedef int (*q_mpfr_unary_func_t)(mpfr_t,
const mpfr_t, mpfr_rnd_t);
85 typedef int (*q_mpfr_unary_nr_func_t)(mpfr_t,
const mpfr_t);
87 hashdecl qore_number_private_intern {
90 DLLLOCAL qore_number_private_intern() {
91 mpfr_init2(num, QORE_DEFAULT_PREC);
94 DLLLOCAL qore_number_private_intern(mpfr_prec_t prec) {
95 if (prec > QORE_MAX_PREC)
97 mpfr_init2(num, prec);
100 DLLLOCAL ~qore_number_private_intern() {
104 DLLLOCAL
void checkPrec(q_mpfr_binary_func_t func,
const mpfr_t r) {
106 if (func == mpfr_mul || func == mpfr_div) {
107 prec = mpfr_get_prec(num) + mpfr_get_prec(r);
109 prec =
QORE_MAX(mpfr_get_prec(num), mpfr_get_prec(r)) + 1;
111 if (prec > mpfr_get_prec(num))
112 mpfr_prec_round(num, prec, QORE_MPFR_RND);
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);
121 DLLLOCAL
static void do_divide_by_zero(
ExceptionSink* xsink) {
122 xsink->
raiseException(
"DIVISION-BY-ZERO",
"division by zero error in numeric operator");
126 #ifdef HAVE_MPFR_DIVBY0 127 if (mpfr_divby0_p()) {
129 do_divide_by_zero(xsink);
132 if (mpfr_erangeflag_p()) {
133 mpfr_clear_erangeflag();
134 xsink->
raiseException(
"INVALID-NUMERIC-OPERATION",
"invalid numeric operation attempted");
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) {
143 DLLLOCAL qore_number_private(
double f) {
152 QoreStringMaker str(
"%.17g", f);
153 mpfr_set_str(num, str.getBuffer(), 10, QORE_MPFR_RND);
156 DLLLOCAL qore_number_private(
int64 i) {
157 mpfr_set_sj(num, i, QORE_MPFR_RND);
160 DLLLOCAL qore_number_private(
const char* str) : qore_number_private_intern(
QORE_MAX(QORE_DEFAULT_PREC, strlen(str)*5)) {
162 const char* p =
strchrs(str,
"eE");
164 int exp = abs(atoi(p + 1));
165 mpfr_prec_t np = exp * 5;
170 mpfr_set_sj(num, 0, QORE_MPFR_RND);
172 mpfr_set_str(num, str, 10, QORE_MPFR_RND);
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);
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);
183 DLLLOCAL
double getAsFloat()
const {
184 return mpfr_get_d(num, QORE_MPFR_RND);
187 DLLLOCAL
int64 getAsBigInt()
const {
188 return mpfr_get_sj(num, QORE_MPFR_RNDZ);
191 DLLLOCAL
bool getAsBool()
const {
195 DLLLOCAL
bool zero()
const {
196 return (
bool)mpfr_zero_p(num);
199 DLLLOCAL
bool nan()
const {
200 return (
bool)mpfr_nan_p(num);
203 DLLLOCAL
bool inf()
const {
204 return (
bool)mpfr_inf_p(num);
207 DLLLOCAL
bool number()
const {
208 return (
bool)mpfr_number_p(num);
211 #ifdef HAVE_MPFR_REGULAR 213 DLLLOCAL
bool regular()
const {
214 return (
bool)mpfr_regular_p(num);
218 DLLLOCAL
int sign()
const {
219 return mpfr_sgn(num);
222 DLLLOCAL
void sprintf(
QoreString& str,
const char* fmt)
const {
223 #ifdef HAVE_MPFR_SPRINTF 225 int len = mpfr_snprintf(0, 0, fmt, num);
233 mpfr_sprintf((
char*)(str.
getBuffer() + str.
size()), fmt, num);
237 long double ld = mpfr_get_ld(num, QORE_MPFR_RND);
238 int len = ::snprintf(0, 0, fmt, ld);
247 DLLLOCAL
void getScientificString(
QoreString& str,
bool round =
true)
const {
248 #ifdef HAVE_MPFR_SPRINTF 258 applyRoundingHeuristic(str, i, e);
263 DLLLOCAL
void getAsString(
QoreString& str,
bool round =
true,
int base = 10)
const;
268 getScientificString(str, raw);
270 getAsString(str, raw);
275 return formatNumberString(str, fmt, xsink);
280 return formatNumberString(str, prec, dsep_str, tsep_str, xsink);
283 DLLLOCAL
bool lessThan(
const qore_number_private& right)
const {
284 return mpfr_less_p(num, right.num);
287 DLLLOCAL
bool lessThan(
double right)
const {
288 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
289 if (mpfr_nan_p(num) || std::isnan(right))
291 mpfr_set_d(r, right, QORE_MPFR_RND);
292 return mpfr_less_p(num, r);
295 DLLLOCAL
bool lessThan(
int64 right)
const {
296 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
299 mpfr_set_sj(r, right, QORE_MPFR_RND);
300 return mpfr_less_p(num, r);
303 DLLLOCAL
bool lessThanOrEqual(
const qore_number_private& right)
const {
304 return mpfr_lessequal_p(num, right.num);
307 DLLLOCAL
bool lessThanOrEqual(
double right)
const {
308 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
309 if (mpfr_nan_p(num) || std::isnan(right))
311 mpfr_set_d(r, right, QORE_MPFR_RND);
312 return mpfr_lessequal_p(num, r);
315 DLLLOCAL
bool lessThanOrEqual(
int64 right)
const {
316 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
319 mpfr_set_sj(r, right, QORE_MPFR_RND);
320 return mpfr_lessequal_p(num, r);
323 DLLLOCAL
bool greaterThan(
const qore_number_private& right)
const {
324 return mpfr_greater_p(num, right.num);
327 DLLLOCAL
bool greaterThan(
double right)
const {
328 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
329 if (mpfr_nan_p(num) || std::isnan(right))
331 mpfr_set_d(r, right, QORE_MPFR_RND);
332 return mpfr_greater_p(num, r);
335 DLLLOCAL
bool greaterThan(
int64 right)
const {
336 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
339 mpfr_set_sj(r, right, QORE_MPFR_RND);
340 return mpfr_greater_p(num, r);
343 DLLLOCAL
bool greaterThanOrEqual(
const qore_number_private& right)
const {
344 return mpfr_greaterequal_p(num, right.num);
347 DLLLOCAL
bool greaterThanOrEqual(
double right)
const {
348 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
349 if (mpfr_nan_p(num) || std::isnan(right))
351 mpfr_set_d(r, right, QORE_MPFR_RND);
352 return mpfr_greaterequal_p(num, r);
355 DLLLOCAL
bool greaterThanOrEqual(
int64 right)
const {
356 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
359 mpfr_set_sj(r, right, QORE_MPFR_RND);
360 return mpfr_greaterequal_p(num, r);
363 DLLLOCAL
bool equals(
const qore_number_private& right)
const {
364 return mpfr_equal_p(num, right.num);
367 DLLLOCAL
bool equals(
double right)
const {
368 if (mpfr_nan_p(num) || std::isnan(right))
370 return 0 == mpfr_cmp_d(num, right);
373 DLLLOCAL
bool equals(
int64 right)
const {
374 MPFR_TMP_VAR(r, QORE_DEFAULT_PREC);
377 mpfr_set_sj(r, right, QORE_MPFR_RND);
378 return mpfr_equal_p(num, r);
381 DLLLOCAL qore_number_private* doBinary(q_mpfr_binary_func_t func,
const qore_number_private& r,
ExceptionSink* xsink = 0)
const {
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);
388 prec =
QORE_MAX(mpfr_get_prec(num), mpfr_get_prec(r.num)) + 1;
390 std::unique_ptr<qore_number_private> p(
new qore_number_private(prec));
391 func(p->num, num, r.num, QORE_MPFR_RND);
395 return (xsink && *xsink) ? 0 : p.release();
398 DLLLOCAL qore_number_private* doPlus(
const qore_number_private& r)
const {
399 return doBinary(mpfr_add, r);
402 DLLLOCAL qore_number_private* doMinus(
const qore_number_private& r)
const {
403 return doBinary(mpfr_sub, r);
406 DLLLOCAL qore_number_private* doMultiply(
const qore_number_private& r)
const {
407 return doBinary(mpfr_mul, r);
410 DLLLOCAL qore_number_private* doDivideBy(
const qore_number_private& r,
ExceptionSink* xsink)
const {
411 #ifndef HAVE_MPFR_DIVBY0 413 do_divide_by_zero(xsink);
417 return doBinary(mpfr_div, r, xsink);
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);
429 DLLLOCAL
void negateInPlace() {
430 mpfr_neg(num, num, QORE_MPFR_RND);
433 DLLLOCAL qore_number_private* negate()
const {
434 return doUnary(mpfr_neg);
437 DLLLOCAL qore_number_private* absolute()
const {
438 return doUnary(mpfr_abs);
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);
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));
455 func(p0 -> num, num);
463 qore_number_private* p2;
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);
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);
484 DLLLOCAL mpfr_prec_t getPrec()
const {
485 return mpfr_get_prec(num);
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);
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);
500 DLLLOCAL
void doBinaryInplace(q_mpfr_binary_func_t func,
const qore_number_private& r,
ExceptionSink* xsink = 0) {
501 checkPrec(func, r.num);
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);
511 DLLLOCAL
void plusEquals(
const qore_number_private& r) {
512 doBinaryInplace(mpfr_add, r);
515 DLLLOCAL
void minusEquals(
const qore_number_private& r) {
516 doBinaryInplace(mpfr_sub, r);
519 DLLLOCAL
void multiplyEquals(
const qore_number_private& r) {
520 doBinaryInplace(mpfr_mul, r);
523 DLLLOCAL
void divideEquals(
const qore_number_private& r) {
525 doBinaryInplace(mpfr_div, r);
529 n.
priv->negateInPlace();
543 DLLLOCAL
static void numError(
QoreString& str) {
544 str.
concat(
"<number error>");
555 n.
priv->sprintf(str, fmt);
583 qore_number_private* p = n.
priv->doUnary(func, xsink);
588 qore_number_private* p = n.
priv->doBinary(func, *r.
priv, xsink);
593 qore_number_private* p = n.
priv->doUnaryNR(func, xsink);
598 qore_number_private* p = n.
priv->doRoundNR(func, prec, xsink);
611 qore_number_private* p =
new qore_number_private(0ll);
612 mpfr_const_pi(p->num, QORE_MPFR_RND);
616 DLLLOCAL
static qore_number_private*
get(
const QoreNumberNode& n) {
621 std::unique_ptr<qore_number_private> n(
new qore_number_private(f));
622 return qore_number_private::toBase(n.get(), base, xsink);
626 return qore_number_private::toBase(n.
priv, base, xsink);
630 if (base < 2 || base > 36) {
631 xsink -> raiseException(
"INVALID-BASE",
"base %d is invalid; base must be 2 - 36 inclusive", base);
636 n -> getAsString(qs, 1, base);
Qore's arbitrary-precision number value type, dynamically-allocated only, reference counted...
Definition: QoreNumberNode.h:51
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 ...
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's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
DLLEXPORT const char * getBuffer() const
returns the string'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
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
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