1 #include "mathexpr-ntype.hpp"
2 #include "mathexpr-error.hpp"
3 #include "mathexpr-format.hpp"
10 void throw_domain(const std::string
& err
)
12 throw mathexpr_error(mathexpr_error::WDOMAIN
, err
);
15 template<typename T
> int _cmp_values(T a
, T b
)
26 class expr_val_numeric
36 struct unsigned_tag
{};
39 struct complex_tag
{};
46 expr_val_numeric(unsigned_tag
, uint64_t v
)
52 expr_val_numeric(signed_tag
, int64_t v
)
58 expr_val_numeric(float_tag
, double v
)
64 expr_val_numeric(complex_tag
, double re
, double im
)
70 expr_val_numeric(const std::string
& str
)
76 } else if(regex("[0-9]+|0x[0-9a-fA-F]+", str
)) {
78 v_unsigned
= parse_value
<uint64_t>(str
);
81 } else if(regex("[+-][0-9]+|[+-]0x[0-9a-fA-F]+", str
)) {
83 v_signed
= parse_value
<int64_t>(str
);
86 } else if(regex("[+-]?([0-9]+|[0-9]*\\.[0-9]+)([eE][0-9]+)?", str
)) {
88 v_float
= parse_value
<double>(str
);
92 throw std::runtime_error("Bad number '" + str
+ "'");
94 double as_float() const
97 case T_UNSIGNED
: return v_unsigned
;
98 case T_SIGNED
: return v_signed
;
99 case T_FLOAT
: return v_float
;
100 case T_COMPLEX
: return v_float
;
102 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
104 int64_t as_signed() const
107 case T_UNSIGNED
: return v_unsigned
;
108 case T_SIGNED
: return v_signed
;
109 case T_FLOAT
: return v_float
;
110 case T_COMPLEX
: return v_float
;
112 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
114 uint64_t as_unsigned() const
117 case T_UNSIGNED
: return v_unsigned
;
118 case T_SIGNED
: return v_signed
;
119 case T_FLOAT
: return v_float
;
120 case T_COMPLEX
: return v_float
;
122 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
124 std::string
tostring()
128 return (stringfmt() << v_unsigned
).str();
130 return (stringfmt() << v_signed
).str();
132 //FIXME: Saner formatting.
133 return (stringfmt() << v_float
).str();
135 //FIXME: Saner formatting.
137 return (stringfmt() << v_float
<< v_imag
<< "*i").str();
139 return (stringfmt() << v_float
<< "+" << v_imag
<< "*i").str();
140 return (stringfmt() << v_float
).str();
142 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
144 uint64_t tounsigned()
146 return as_unsigned();
152 void scale(uint64_t scale
)
157 v_float
= (1.0 * v_unsigned
/ scale
);
161 v_float
= (1.0 * v_signed
/ scale
);
173 case T_UNSIGNED
: return (v_unsigned
!= 0);
174 case T_SIGNED
: return (v_signed
!= 0);
175 case T_FLOAT
: return (v_float
!= 0);
176 case T_COMPLEX
: return (v_float
!= 0) || (v_imag
!= 0);
178 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
180 std::string
format(mathexpr_format fmt
)
183 case T_UNSIGNED
: return math_format_unsigned(v_unsigned
, fmt
);
184 case T_SIGNED
: return math_format_signed(v_signed
, fmt
);
185 case T_FLOAT
: return math_format_float(v_float
, fmt
);
186 case T_COMPLEX
: return math_format_complex(v_float
, v_imag
, fmt
);
188 throw mathexpr_error(mathexpr_error::INTERNAL
, "Don't know how to print numeric type");
190 expr_val_numeric
operator~() const
193 case T_UNSIGNED
: return expr_val_numeric(unsigned_tag(), ~v_unsigned
);
194 case T_SIGNED
: return expr_val_numeric(signed_tag(), ~v_signed
);
195 case T_FLOAT
: throw_domain("Bit operations are only for integers");
196 case T_COMPLEX
: throw_domain("Bit operations are only for integers");
198 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
200 expr_val_numeric
operator&(const expr_val_numeric
& b
) const
202 if(type
== T_COMPLEX
|| b
.type
== T_COMPLEX
)
203 throw_domain("Bit operations are only for integers");
204 if(type
== T_FLOAT
|| b
.type
== T_FLOAT
)
205 throw_domain("Bit operations are only for integers");
206 if(type
== T_SIGNED
|| b
.type
== T_SIGNED
)
207 return expr_val_numeric(signed_tag(), as_signed() & b
.as_signed());
208 return expr_val_numeric(unsigned_tag(), as_unsigned() & b
.as_unsigned());
210 expr_val_numeric
operator|(const expr_val_numeric
& b
) const
212 if(type
== T_COMPLEX
|| b
.type
== T_COMPLEX
)
213 throw_domain("Bit operations are only for integers");
214 if(type
== T_FLOAT
|| b
.type
== T_FLOAT
)
215 throw_domain("Bit operations are only for integers");
216 if(type
== T_SIGNED
|| b
.type
== T_SIGNED
)
217 return expr_val_numeric(signed_tag(), as_signed() | b
.as_signed());
218 return expr_val_numeric(unsigned_tag(), as_unsigned() | b
.as_unsigned());
220 expr_val_numeric
operator^(const expr_val_numeric
& b
) const
222 if(type
== T_COMPLEX
|| b
.type
== T_COMPLEX
)
223 throw_domain("Bit operations are only for integers");
224 if(type
== T_FLOAT
|| b
.type
== T_FLOAT
)
225 throw_domain("Bit operations are only for integers");
226 if(type
== T_SIGNED
|| b
.type
== T_SIGNED
)
227 return expr_val_numeric(signed_tag(), as_signed() ^ b
.as_signed());
228 return expr_val_numeric(unsigned_tag(), as_unsigned() ^ b
.as_unsigned());
230 expr_val_numeric
operator-() const
233 case T_COMPLEX
: return expr_val_numeric(complex_tag(), -v_float
, -v_imag
);
234 case T_UNSIGNED
: return expr_val_numeric(signed_tag(), -(int64_t)v_unsigned
);
235 case T_SIGNED
: return expr_val_numeric(signed_tag(), -v_signed
);
236 case T_FLOAT
: return expr_val_numeric(float_tag(), -v_float
);
238 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
240 expr_val_numeric
operator+(const expr_val_numeric
& b
) const
242 if(type
== T_COMPLEX
|| b
.type
== T_COMPLEX
)
243 return expr_val_numeric(complex_tag(), as_float() + b
.as_float(),
245 if(type
== T_FLOAT
|| b
.type
== T_FLOAT
)
246 return expr_val_numeric(float_tag(), as_float() + b
.as_float());
247 if(type
== T_SIGNED
|| b
.type
== T_SIGNED
)
248 return expr_val_numeric(signed_tag(), as_signed() + b
.as_signed());
249 return expr_val_numeric(unsigned_tag(), as_unsigned() + b
.as_unsigned());
251 expr_val_numeric
operator-(const expr_val_numeric
& b
) const
253 if(type
== T_COMPLEX
|| b
.type
== T_COMPLEX
)
254 return expr_val_numeric(complex_tag(), as_float() - b
.as_float(),
256 if(type
== T_FLOAT
|| b
.type
== T_FLOAT
)
257 return expr_val_numeric(float_tag(), as_float() - b
.as_float());
258 if(type
== T_SIGNED
|| b
.type
== T_SIGNED
)
259 return expr_val_numeric(signed_tag(), as_signed() - b
.as_signed());
260 return expr_val_numeric(unsigned_tag(), as_unsigned() - b
.as_unsigned());
262 expr_val_numeric
operator*(const expr_val_numeric
& b
) const
264 if(type
== T_COMPLEX
|| b
.type
== T_COMPLEX
)
265 return expr_val_numeric(complex_tag(), as_float() * b
.as_float() - v_imag
* b
.v_imag
,
266 as_float() * b
.v_imag
+ b
.as_float() * v_imag
);
267 if(type
== T_FLOAT
|| b
.type
== T_FLOAT
)
268 return expr_val_numeric(float_tag(), as_float() * b
.as_float());
269 if(type
== T_SIGNED
|| b
.type
== T_SIGNED
)
270 return expr_val_numeric(signed_tag(), as_signed() * b
.as_signed());
271 return expr_val_numeric(unsigned_tag(), as_unsigned() * b
.as_unsigned());
273 expr_val_numeric
operator/(const expr_val_numeric
& b
) const
275 if(type
== T_COMPLEX
|| b
.type
== T_COMPLEX
) {
276 double div
= b
.as_float() * b
.as_float() + b
.v_imag
* b
.v_imag
;
278 throw mathexpr_error(mathexpr_error::DIV_BY_0
, "Division by 0");
279 return expr_val_numeric(complex_tag(),
280 (as_float() * b
.as_float() + v_imag
* b
.v_imag
) / div
,
281 (v_imag
* b
.as_float() - as_float() * b
.v_imag
) / div
);
283 if(type
== T_FLOAT
|| b
.type
== T_FLOAT
) {
284 if(b
.as_float() == 0)
285 throw mathexpr_error(mathexpr_error::DIV_BY_0
, "Division by 0");
286 return expr_val_numeric(float_tag(), as_float() / b
.as_float());
288 if(type
== T_SIGNED
|| b
.type
== T_SIGNED
) {
289 if(b
.as_signed() == 0)
290 throw mathexpr_error(mathexpr_error::DIV_BY_0
, "Division by 0");
291 return expr_val_numeric(signed_tag(), as_signed() / b
.as_signed());
293 if(b
.as_unsigned() == 0)
294 throw mathexpr_error(mathexpr_error::DIV_BY_0
, "Division by 0");
295 return expr_val_numeric(unsigned_tag(), as_unsigned() / b
.as_unsigned());
297 expr_val_numeric
operator%(const expr_val_numeric
& b
) const
299 if(type
== T_COMPLEX
|| b
.type
== T_COMPLEX
)
300 throw_domain("Remainder is only for integers");
301 if(type
== T_FLOAT
|| b
.type
== T_FLOAT
)
302 throw_domain("Remainder is only for integers");
303 if(type
== T_SIGNED
|| b
.type
== T_SIGNED
) {
304 if(b
.as_signed() == 0)
305 throw mathexpr_error(mathexpr_error::DIV_BY_0
, "Division by 0");
306 return expr_val_numeric(signed_tag(), as_signed() / b
.as_signed());
308 if(b
.as_unsigned() == 0)
309 throw mathexpr_error(mathexpr_error::DIV_BY_0
, "Division by 0");
310 return expr_val_numeric(unsigned_tag(), as_unsigned() / b
.as_unsigned());
312 expr_val_numeric
log() const
314 if(type
== T_COMPLEX
) {
315 double mag
= as_float() * as_float() + v_imag
* v_imag
;
317 throw mathexpr_error(mathexpr_error::LOG_BY_0
, "Can't take logarithm of 0");
318 double r
= 0.5 * ::log(mag
);
319 double i
= ::atan2(v_imag
, as_float());
320 return expr_val_numeric(complex_tag(), r
, i
);
323 throw mathexpr_error(mathexpr_error::LOG_BY_0
, "Can't take logarithm of 0");
325 return expr_val_numeric(complex_tag(), ::log(std::abs(as_float())), 4 * ::atan(1));
326 return expr_val_numeric(float_tag(), ::log(as_float()));
328 static expr_val_numeric
log2(expr_val_numeric a
, expr_val_numeric b
)
330 return b
.log() / a
.log();
332 expr_val_numeric
exp() const
334 if(type
== T_COMPLEX
) {
335 double mag
= ::exp(as_float());
336 return expr_val_numeric(complex_tag(), mag
* ::cos(v_imag
),
337 mag
* ::sin(v_imag
));
339 return expr_val_numeric(float_tag(), ::exp(as_float()));
341 static expr_val_numeric
exp2(expr_val_numeric a
, expr_val_numeric b
)
343 expr_val_numeric tmp
= b
* a
.log();
346 expr_val_numeric
sqrt() const
348 if(as_float() < 0 && type
!= T_COMPLEX
)
349 return expr_val_numeric(complex_tag(), 0, ::sqrt(-as_float()));
350 if(type
== T_COMPLEX
) {
351 double mag
= ::sqrt(::sqrt(as_float() * as_float() + v_imag
* v_imag
));
352 double ar
= 0.5 * ::atan2(v_imag
, as_float());
353 return expr_val_numeric(complex_tag(), mag
* ::cos(ar
), mag
* ::sin(ar
));
355 return expr_val_numeric(float_tag(), ::sqrt(as_float()));
357 expr_val_numeric
sin() const
359 if(type
== T_COMPLEX
) {
360 return expr_val_numeric(complex_tag(), ::sin(as_float()) * ::cosh(v_imag
),
361 ::cos(as_float()) * ::sinh(v_imag
));
363 return expr_val_numeric(float_tag(), ::sin(as_float()));
365 expr_val_numeric
cos() const
367 if(type
== T_COMPLEX
) {
368 return expr_val_numeric(complex_tag(), ::cos(as_float()) * ::cosh(v_imag
),
369 -::sin(as_float()) * ::sinh(v_imag
));
371 return expr_val_numeric(float_tag(), ::cos(as_float()));
373 expr_val_numeric
tan() const
377 expr_val_numeric
atan() const
379 if(type
== T_COMPLEX
) {
380 expr_val_numeric x
= expr_val_numeric(complex_tag(), 0, 1) * *this;
381 expr_val_numeric n
= expr_val_numeric(complex_tag(), 1, 0) + x
;
382 expr_val_numeric d
= expr_val_numeric(complex_tag(), 1, 0) - x
;
383 expr_val_numeric y
= n
/ d
;
384 expr_val_numeric w
= y
.log();
385 return w
/ expr_val_numeric(complex_tag(), 0, 2);
387 return expr_val_numeric(float_tag(), ::atan(as_float()));
389 expr_val_numeric
acos() const
391 expr_val_numeric sinesqr
= (expr_val_numeric(float_tag(), 1) - *this * *this);
392 expr_val_numeric sine
= sinesqr
.sqrt();
393 expr_val_numeric tangent
= sine
/ *this;
394 return tangent
.atan();
396 expr_val_numeric
asin() const
398 expr_val_numeric cosinesqr
= (expr_val_numeric(float_tag(), 1) - *this * *this);
399 expr_val_numeric cosine
= cosinesqr
.sqrt();
400 expr_val_numeric tangent
= *this / cosine
;
401 return tangent
.atan();
403 expr_val_numeric
sinh() const
405 return (exp() - (-*this).exp()) / expr_val_numeric(float_tag(), 2);
407 expr_val_numeric
cosh() const
409 return (exp() + (-*this).exp()) / expr_val_numeric(float_tag(), 2);
411 expr_val_numeric
tanh() const
413 return sinh() / cosh();
415 expr_val_numeric
arsinh() const
419 //(x-u)^2 - x^2 + 2ux - u^2 + x^2 - 2ux - 1 = 0
421 expr_val_numeric xmu
= (*this * *this) + expr_val_numeric(float_tag(), 1);
422 expr_val_numeric x
= xmu
.sqrt() + *this;
425 expr_val_numeric
arcosh() const
427 expr_val_numeric xmu
= (*this * *this) - expr_val_numeric(float_tag(), 1);
428 expr_val_numeric x
= xmu
.sqrt() + *this;
431 expr_val_numeric
artanh() const
435 expr_val_numeric
t(float_tag(), 1);
436 return ((t
+ *this) / (t
- *this)).sqrt().log();
438 static expr_val_numeric
atan2(expr_val_numeric a
, expr_val_numeric b
)
440 if(a
.type
== T_COMPLEX
|| b
.type
== T_COMPLEX
)
441 throw_domain("atan2 is only for reals");
442 return expr_val_numeric(float_tag(), ::atan2(a
.as_float(), b
.as_float()));
444 expr_val_numeric
torad() const
446 return expr_val_numeric(float_tag(), ::atan(1) / 45 * as_float());
448 expr_val_numeric
todeg() const
450 return expr_val_numeric(float_tag(), 45 / ::atan(1) * as_float());
452 static expr_val_numeric
shift(expr_val_numeric a
, expr_val_numeric b
, bool inv
)
454 int64_t s
= b
.as_signed();
457 if(a
.type
== T_SIGNED
) {
458 int64_t _a
= a
.v_signed
;
460 return expr_val_numeric(signed_tag(), -1);
462 return expr_val_numeric(signed_tag(), 0);
465 uint64_t r2
= r
>> -s
;
466 uint64_t m
= 0xFFFFFFFFFFFFFFFFULL
- ((1ULL << (64 - s
)) - 1);
467 return expr_val_numeric(signed_tag(), m
| r2
);
469 return expr_val_numeric(signed_tag(), _a
<< s
);
471 return expr_val_numeric(signed_tag(), _a
);
472 } else if(a
.type
== T_UNSIGNED
) {
473 uint64_t _a
= a
.v_unsigned
;
474 if(s
< -63 || s
> 63)
475 return expr_val_numeric(unsigned_tag(), 0);
477 return expr_val_numeric(unsigned_tag(), _a
>> -s
);
479 return expr_val_numeric(unsigned_tag(), _a
<< s
);
481 return expr_val_numeric(unsigned_tag(), _a
);
483 throw_domain("Bit operations are only for integers");
485 static expr_val_numeric
op_pi()
487 return expr_val_numeric(float_tag(), 4 * ::atan(1));
489 static expr_val_numeric
op_e()
491 return expr_val_numeric(float_tag(), ::exp(1));
493 bool operator==(const expr_val_numeric
& b
) const
495 if(type
== T_COMPLEX
|| b
.type
== T_COMPLEX
)
496 return as_float() == b
.as_float() && v_imag
== b
.v_imag
;
497 return (_cmp(*this, b
) == 0);
499 static int _cmp_float_unsigned(uint64_t a
, float b
)
503 //TODO: Handle values too large for exact integer representation.
510 static int _cmp_float_signed(int64_t a
, float b
)
512 //TODO: Handle values too large for exact integer representation.
519 static int _cmp(expr_val_numeric a
, expr_val_numeric b
)
521 if(a
.type
== T_COMPLEX
|| b
.type
== T_COMPLEX
)
522 throw_domain("Can't compare complex numbers");
527 return _cmp_values(a
.v_unsigned
, b
.v_unsigned
);
531 if((int64_t)a
.v_unsigned
< 0)
533 return _cmp_values((int64_t)a
.v_unsigned
, b
.v_signed
);
535 return _cmp_float_unsigned(a
.v_unsigned
, b
.v_float
);
537 throw mathexpr_error(mathexpr_error::INTERNAL
,
538 "Internal error (shouldn't be here)");
545 if((int64_t)b
.v_unsigned
< 0)
547 return _cmp_values(a
.v_signed
, (int64_t)b
.v_unsigned
);
549 return _cmp_values(a
.v_signed
, b
.v_signed
);
551 return _cmp_float_signed(a
.v_signed
, b
.v_float
);
553 throw mathexpr_error(mathexpr_error::INTERNAL
,
554 "Internal error (shouldn't be here)");
559 return -_cmp_float_unsigned(b
.v_unsigned
, a
.v_float
);
561 return -_cmp_float_signed(b
.v_signed
, a
.v_float
);
563 if(a
.v_float
< b
.v_float
)
565 if(a
.v_float
> b
.v_float
)
569 throw mathexpr_error(mathexpr_error::INTERNAL
,
570 "Internal error (shouldn't be here)");
573 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
575 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
577 static expr_val_numeric
x_unsigned(expr_val_numeric a
)
580 case T_UNSIGNED
: return expr_val_numeric(unsigned_tag(), a
.v_unsigned
);
581 case T_SIGNED
: return expr_val_numeric(unsigned_tag(), a
.v_signed
);
582 case T_FLOAT
: return expr_val_numeric(unsigned_tag(), a
.v_float
);
583 default: throw_domain("Can't convert non-real into unsigned");
586 static expr_val_numeric
x_signed(expr_val_numeric a
)
589 case T_UNSIGNED
: return expr_val_numeric(signed_tag(), a
.v_unsigned
);
590 case T_SIGNED
: return expr_val_numeric(signed_tag(), a
.v_signed
);
591 case T_FLOAT
: return expr_val_numeric(signed_tag(), a
.v_float
);
592 default: throw_domain("Can't convert non-real into signed");
595 static expr_val_numeric
x_float(expr_val_numeric a
)
598 case T_UNSIGNED
: return expr_val_numeric(float_tag(), a
.v_unsigned
);
599 case T_SIGNED
: return expr_val_numeric(float_tag(), a
.v_signed
);
600 case T_FLOAT
: return expr_val_numeric(float_tag(), a
.v_float
);
601 default: throw_domain("Can't convert non-real into float");
604 expr_val_numeric
re() const
606 if(type
== T_COMPLEX
)
607 return expr_val_numeric(float_tag(), v_float
);
608 return expr_val_numeric(float_tag(), as_float());
610 expr_val_numeric
im() const
612 if(type
== T_COMPLEX
)
613 return expr_val_numeric(float_tag(), v_imag
);
614 return expr_val_numeric(float_tag(), 0);
616 expr_val_numeric
conj() const
618 if(type
== T_COMPLEX
)
619 return expr_val_numeric(complex_tag(), v_float
, -v_imag
);
620 return expr_val_numeric(float_tag(), as_float());
622 expr_val_numeric
abs() const
625 case T_COMPLEX
: return expr_val_numeric(float_tag(), v_float
* v_float
+ v_imag
* v_imag
);
626 case T_FLOAT
: return expr_val_numeric(float_tag(), ::fabs(v_float
));
627 case T_SIGNED
: return expr_val_numeric(signed_tag(), ::abs(v_signed
));
628 case T_UNSIGNED
: return expr_val_numeric(unsigned_tag(), v_unsigned
);
630 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
632 expr_val_numeric
arg() const
635 case T_COMPLEX
: return expr_val_numeric(float_tag(), ::atan2(v_imag
, v_float
));
638 return expr_val_numeric(float_tag(), 4 * ::atan(1));
640 return expr_val_numeric(float_tag(), 0);
655 struct boolean_tag
{};
656 struct number_tag
{};
657 struct string_tag
{};
664 expr_val_numeric
& as_numeric()
666 if(type
!= T_NUMERIC
)
667 throw_domain("Can't operate with non-numbers");
675 expr_val(const std::string
& str
, bool string
)
680 } else if(str
== "false") {
683 } else if(str
== "true") {
686 } else if(str
== "e") {
687 v_numeric
= expr_val_numeric::op_e();
689 } else if(str
== "pi") {
690 v_numeric
= expr_val_numeric::op_pi();
693 v_numeric
= expr_val_numeric(str
);
697 expr_val(mathexpr_typeinfo_wrapper
<expr_val
>::unsigned_tag t
, uint64_t v
)
698 : type(T_NUMERIC
), v_numeric(expr_val_numeric::unsigned_tag(), v
)
701 expr_val(mathexpr_typeinfo_wrapper
<expr_val
>::signed_tag t
, int64_t v
)
702 : type(T_NUMERIC
), v_numeric(expr_val_numeric::signed_tag(), v
)
705 expr_val(mathexpr_typeinfo_wrapper
<expr_val
>::float_tag t
, double v
)
706 : type(T_NUMERIC
), v_numeric(expr_val_numeric::float_tag(), v
)
709 expr_val(boolean_tag
, bool b
)
710 : type(T_BOOLEAN
), v_boolean(b
)
713 expr_val(expr_val_numeric v
)
714 : type(T_NUMERIC
), v_numeric(v
)
717 expr_val(string_tag
, std::string s
)
718 : type(T_STRING
), v_string(s
)
721 std::string
tostring()
730 return v_numeric
.tostring();
734 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
736 uint64_t tounsigned()
738 if(type
!= T_NUMERIC
)
739 throw_domain("Can't convert non-number into unsigned");
740 return v_numeric
.tounsigned();
744 if(type
!= T_NUMERIC
)
745 throw_domain("Can't convert non-number into signed");
746 return v_numeric
.tosigned();
748 void scale(uint64_t _scale
)
750 if(type
!= T_NUMERIC
)
751 throw_domain("Can't scale non-number");
752 v_numeric
.scale(_scale
);
760 return v_numeric
.toboolean();
762 return (v_string
.length() != 0);
764 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
766 static expr_val
op_lnot(std::vector
<std::function
<expr_val
&()>> promises
)
768 if(promises
.size() != 1)
769 throw mathexpr_error(mathexpr_error::ARGCOUNT
, "logical not takes 1 argument");
770 return expr_val(boolean_tag(), !(promises
[0]().toboolean()));
772 static expr_val
op_lor(std::vector
<std::function
<expr_val
&()>> promises
)
774 if(promises
.size() != 2)
775 throw mathexpr_error(mathexpr_error::ARGCOUNT
, "logical or takes 2 arguments");
776 if(promises
[0]().toboolean())
777 return expr_val(boolean_tag(), true);
778 return expr_val(boolean_tag(), promises
[1]().toboolean());
780 static expr_val
op_land(std::vector
<std::function
<expr_val
&()>> promises
)
782 if(promises
.size() != 2)
783 throw mathexpr_error(mathexpr_error::ARGCOUNT
, "logical and takes 2 arguments");
784 if(!(promises
[0]().toboolean()))
785 return expr_val(boolean_tag(), false);
786 return expr_val(boolean_tag(), promises
[1]().toboolean());
788 static expr_val
fun_if(std::vector
<std::function
<expr_val
&()>> promises
)
790 if(promises
.size() == 2) {
791 if((promises
[0]().toboolean()))
792 return promises
[1]();
794 return expr_val(boolean_tag(), false);
795 } else if(promises
.size() == 3) {
796 if((promises
[0]().toboolean()))
797 return promises
[1]();
799 return promises
[2]();
801 throw mathexpr_error(mathexpr_error::ARGCOUNT
, "if takes 2 or 3 arguments");
803 static expr_val
fun_select(std::vector
<std::function
<expr_val
&()>> promises
)
805 for(auto& i
: promises
) {
807 if(v
.type
!= T_BOOLEAN
|| v
.v_boolean
)
810 return expr_val(boolean_tag(), false);
812 static expr_val
fun_pyth(std::vector
<std::function
<expr_val
&()>> promises
)
814 std::vector
<expr_val
> v
;
815 for(auto& i
: promises
)
817 expr_val_numeric
n(expr_val_numeric::float_tag(), 0);
818 expr_val_numeric
one(expr_val_numeric::float_tag(), 1);
820 if(i
.type
!= T_NUMERIC
)
821 throw mathexpr_error(mathexpr_error::WDOMAIN
, "pyth requires numeric args");
822 n
= n
+ one
* i
.v_numeric
* i
.v_numeric
;
826 template<expr_val (*T
)(expr_val
& a
, expr_val
& b
)>
827 static expr_val
fun_fold(std::vector
<std::function
<expr_val
&()>> promises
)
830 return expr_val(boolean_tag(), false);
831 expr_val v
= promises
[0]();
832 for(size_t i
= 1; i
< promises
.size(); i
++)
833 v
= T(v
, promises
[i
]());
836 static expr_val
fold_min(expr_val
& a
, expr_val
& b
)
838 int t
= _cmp_values(a
.type
, b
.type
);
843 return (_cmp(a
, b
) < 0) ? a
: b
;
845 static expr_val
fold_max(expr_val
& a
, expr_val
& b
)
847 int t
= _cmp_values(a
.type
, b
.type
);
852 return (_cmp(a
, b
) > 0) ? a
: b
;
854 static expr_val
fold_sum(expr_val
& a
, expr_val
& b
)
858 static expr_val
fold_prod(expr_val
& a
, expr_val
& b
)
862 template<expr_val (*T
)(expr_val a
, expr_val b
)>
863 static expr_val
op_binary(std::vector
<std::function
<expr_val
&()>> promises
)
865 if(promises
.size() != 2)
866 throw mathexpr_error(mathexpr_error::ARGCOUNT
, "Operation takes 2 arguments");
867 expr_val a
= promises
[0]();
868 expr_val b
= promises
[1]();
871 template<expr_val (*T
)(expr_val a
)>
872 static expr_val
op_unary(std::vector
<std::function
<expr_val
&()>> promises
)
874 if(promises
.size() != 1)
875 throw mathexpr_error(mathexpr_error::ARGCOUNT
, "Operation takes 1 argument");
876 expr_val a
= promises
[0]();
879 template<expr_val (*T
)(expr_val a
),expr_val (*U
)(expr_val a
, expr_val b
)>
880 static expr_val
op_unary_binary(std::vector
<std::function
<expr_val
&()>> promises
)
882 if(promises
.size() == 1)
883 return T(promises
[0]());
884 if(promises
.size() == 2)
885 return U(promises
[0](), promises
[1]());
886 throw mathexpr_error(mathexpr_error::ARGCOUNT
, "Operation takes 1 or 2 arguments");
888 static expr_val
bnot(expr_val a
)
890 return ~a
.as_numeric();
892 static expr_val
band(expr_val a
, expr_val b
)
894 return a
.as_numeric() & b
.as_numeric();
896 static expr_val
bor(expr_val a
, expr_val b
)
898 return a
.as_numeric() | b
.as_numeric();
900 static expr_val
bxor(expr_val a
, expr_val b
)
902 return a
.as_numeric() ^ b
.as_numeric();
904 static expr_val
neg(expr_val a
)
906 return -a
.as_numeric();
908 template<expr_val_numeric (expr_val_numeric::*T
)() const>
909 static expr_val
f_n_fn(expr_val a
)
911 return (a
.as_numeric().*T
)();
913 template<expr_val_numeric (*T
)(expr_val_numeric x
, expr_val_numeric y
)>
914 static expr_val
f_n_fn2(expr_val a
, expr_val b
)
916 return T(a
.as_numeric(), b
.as_numeric());
918 static expr_val
lshift(expr_val a
, expr_val b
)
920 return expr_val_numeric::shift(a
.as_numeric(), b
.as_numeric(), false);
922 static expr_val
rshift(expr_val a
, expr_val b
)
924 return expr_val_numeric::shift(a
.as_numeric(), b
.as_numeric(), true);
926 static expr_val
op_pi(std::vector
<std::function
<expr_val
&()>> promises
)
928 return expr_val_numeric::op_pi();
930 static expr_val
add(expr_val a
, expr_val b
)
932 if(a
.type
== T_STRING
&& b
.type
== T_STRING
)
933 return expr_val(string_tag(), a
.v_string
+ b
.v_string
);
934 return a
.as_numeric() + b
.as_numeric();
936 static expr_val
sub(expr_val a
, expr_val b
)
938 return a
.as_numeric() - b
.as_numeric();
940 static expr_val
mul(expr_val a
, expr_val b
)
942 return a
.as_numeric() * b
.as_numeric();
944 static expr_val
div(expr_val a
, expr_val b
)
946 return a
.as_numeric() / b
.as_numeric();
948 static expr_val
rem(expr_val a
, expr_val b
)
950 return a
.as_numeric() % b
.as_numeric();
952 static bool _eq(const expr_val
& a
, const expr_val
& b
)
957 case T_BOOLEAN
: return (a
.v_boolean
== b
.v_boolean
);
958 case T_STRING
: return (a
.v_string
== b
.v_string
);
959 case T_NUMERIC
: return (a
.v_numeric
== b
.v_numeric
);
961 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
963 static expr_val
eq(expr_val a
, expr_val b
)
965 return expr_val(boolean_tag(), _eq(a
, b
));
967 static expr_val
ne(expr_val a
, expr_val b
)
969 return expr_val(boolean_tag(), !_eq(a
, b
));
971 static int _cmp(expr_val a
, expr_val b
)
974 throw_domain("Can't compare distinct value types");
976 case T_BOOLEAN
: return _cmp_values(a
.v_boolean
, b
.v_boolean
);
977 case T_STRING
: return _cmp_values(a
.v_string
, b
.v_string
);
978 case T_NUMERIC
: return expr_val_numeric::_cmp(a
.v_numeric
, b
.v_numeric
);
980 throw mathexpr_error(mathexpr_error::INTERNAL
, "Internal error (shouldn't be here)");
982 template<expr_val_numeric(*T
)(expr_val_numeric v
)>
983 static expr_val
x_nconv(expr_val a
)
985 return T(a
.as_numeric());
987 static expr_val
lt(expr_val a
, expr_val b
)
989 return expr_val(boolean_tag(), _cmp(a
, b
) < 0);
991 static expr_val
le(expr_val a
, expr_val b
)
993 return expr_val(boolean_tag(), _cmp(a
, b
) <= 0);
995 static expr_val
ge(expr_val a
, expr_val b
)
997 return expr_val(boolean_tag(), _cmp(a
, b
) >= 0);
999 static expr_val
gt(expr_val a
, expr_val b
)
1001 return expr_val(boolean_tag(), _cmp(a
, b
) > 0);
1003 std::string
format_string(std::string val
, mathexpr_format fmt
)
1005 if((int)val
.length() > fmt
.precision
&& fmt
.precision
>= 0)
1006 val
= val
.substr(0, fmt
.precision
);
1007 while((int)val
.length() < fmt
.width
)
1011 std::string
print_bool_numeric(bool val
, mathexpr_format fmt
)
1013 std::string out
= val
? "1" : "0";
1014 if(fmt
.precision
> 0) {
1016 for(int i
= 0; i
< fmt
.precision
; i
++)
1019 while((int)out
.length() < fmt
.width
)
1020 out
= ((fmt
.fillzeros
) ? "0" : " ") + out
;
1023 std::string
format(mathexpr_format fmt
)
1026 case T_BOOLEAN
: return math_format_bool(v_boolean
, fmt
);
1027 case T_NUMERIC
: return v_numeric
.format(fmt
);
1028 case T_STRING
: return math_format_string(v_string
, fmt
);
1030 return "#Notprintable";
1033 static std::set
<mathexpr_operinfo
*> operations()
1035 static mathexpr_operinfo_set
<expr_val
> x({
1036 {"-", expr_val::op_unary
<expr_val::neg
>, true, 1, -3, true},
1037 {"!", expr_val::op_lnot
, true, 1, -3, true},
1038 {"~", expr_val::op_unary
<expr_val::bnot
>, true, 1, -3, true},
1039 {"*", expr_val::op_binary
<expr_val::mul
>, true, 2, -5, false},
1040 {"/", expr_val::op_binary
<expr_val::div
>, true, 2, -5, false},
1041 {"%", expr_val::op_binary
<expr_val::rem
>, true, 2, -5, false},
1042 {"+", expr_val::op_binary
<expr_val::add
>, true, 2, -6, false},
1043 {"-", expr_val::op_binary
<expr_val::sub
>, true, 2, -6, false},
1044 {"<<", expr_val::op_binary
<expr_val::lshift
>, true, 2, -7, false},
1045 {">>", expr_val::op_binary
<expr_val::rshift
>, true, 2, -7, false},
1046 {"<", expr_val::op_binary
<expr_val::lt
>, true, 2, -8, false},
1047 {"<=", expr_val::op_binary
<expr_val::le
>, true, 2, -8, false},
1048 {">", expr_val::op_binary
<expr_val::gt
>, true, 2, -8, false},
1049 {">=", expr_val::op_binary
<expr_val::ge
>, true, 2, -8, false},
1050 {"==", expr_val::op_binary
<expr_val::eq
>, true, 2, -9, false},
1051 {"!=", expr_val::op_binary
<expr_val::ne
>, true, 2, -9, false},
1052 {"&", expr_val::op_binary
<expr_val::band
>, true, 2, -10, false},
1053 {"^", expr_val::op_binary
<expr_val::bxor
>, true, 2, -11, false},
1054 {"|", expr_val::op_binary
<expr_val::bor
>, true, 2, -12, false},
1055 {"&&", expr_val::op_land
, true, 2, -13, false},
1056 {"||", expr_val::op_lor
, true, 2, -14, false},
1057 {"π", expr_val::op_pi
, true, 0, 0, false},
1058 {"if", expr_val::fun_if
},
1059 {"select", expr_val::fun_select
},
1060 {"unsigned", expr_val::op_unary
<expr_val::x_nconv
<expr_val_numeric::x_unsigned
>>},
1061 {"signed", expr_val::op_unary
<expr_val::x_nconv
<expr_val_numeric::x_signed
>>},
1062 {"float", expr_val::op_unary
<expr_val::x_nconv
<expr_val_numeric::x_float
>>},
1063 {"min", expr_val::fun_fold
<expr_val::fold_min
>},
1064 {"max", expr_val::fun_fold
<expr_val::fold_max
>},
1065 {"sum", expr_val::fun_fold
<expr_val::fold_sum
>},
1066 {"prod", expr_val::fun_fold
<expr_val::fold_prod
>},
1067 {"sqrt", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::sqrt
>>},
1068 {"log", expr_val::op_unary_binary
<expr_val::f_n_fn
<&expr_val_numeric::log
>,
1069 expr_val::f_n_fn2
<expr_val_numeric::log2
>>},
1070 {"exp", expr_val::op_unary_binary
<expr_val::f_n_fn
<&expr_val_numeric::exp
>,
1071 expr_val::f_n_fn2
<expr_val_numeric::exp2
>>},
1072 {"sin", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::sin
>>},
1073 {"cos", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::cos
>>},
1074 {"tan", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::tan
>>},
1075 {"atan", expr_val::op_unary_binary
<expr_val::f_n_fn
<&expr_val_numeric::atan
>,
1076 expr_val::f_n_fn2
<expr_val_numeric::atan2
>>},
1077 {"asin", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::asin
>>},
1078 {"acos", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::acos
>>},
1079 {"sinh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::sinh
>>},
1080 {"cosh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::cosh
>>},
1081 {"tanh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::tanh
>>},
1082 {"artanh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::artanh
>>},
1083 {"arsinh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::arsinh
>>},
1084 {"arcosh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::arcosh
>>},
1085 {"torad", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::torad
>>},
1086 {"todeg", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::todeg
>>},
1087 {"re", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::re
>>},
1088 {"im", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::im
>>},
1089 {"conj", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::conj
>>},
1090 {"abs", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::abs
>>},
1091 {"arg", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::arg
>>},
1092 {"pyth", expr_val::fun_pyth
},
1099 expr_val_numeric v_numeric
;
1100 std::string v_string
;
1104 struct mathexpr_typeinfo
* expression_value()
1106 static mathexpr_typeinfo_wrapper
<expr_val
> expession_value_obj
;
1107 return &expession_value_obj
;
1110 #ifdef TEST_MATHEXPR
1111 int main2(int argc
, char** argv
)
1113 std::map
<const std::string
, gcroot_pointer
<mathexpr
>> vars
;
1114 std::function
<gcroot_pointer
<mathexpr
>(const std::string
&)> vars_fn
= [&vars
](const std::string
& n
) ->
1115 gcroot_pointer
<mathexpr
> {
1117 vars
.insert(std::make_pair(n
, gcroot_pointer
<mathexpr
>(expression_value())));
1118 gcroot_pointer
<mathexpr
>& tmp
= vars
.find(n
)->second
;
1121 for(int i
= 1; i
< argc
; i
++) {
1122 regex_results r
= regex("([^=]+)=(.*)", argv
[i
]);
1124 throw std::runtime_error("Bad argument '" + std::string(argv
[i
]) + "'");
1125 *vars_fn(r
[1]) = *mathexpr::parse(*expression_value(), r
[2], vars_fn
);
1127 garbage_collectable::do_gc();
1128 garbage_collectable::do_gc();
1129 for(auto i
: vars
) {
1131 auto v
= i
.second
->evaluate();
1132 std::cout
<< i
.first
<< " --> " << v
.type
->tostring(v
.value
) << std::endl
;
1133 } catch(std::exception
& e
) {
1134 std::cout
<< i
.first
<< " --> " << e
.what() << std::endl
;
1140 int main(int argc
, char** argv
)
1142 int r
= main2(argc
, argv
);
1143 garbage_collectable::do_gc();