bsnes: redump sprite/palette functions
[lsnes.git] / src / library / mathexpr-ntype.cpp
bloba98bdad1389deea30ea9709da2cb3d25b3d00a70
1 #include "mathexpr-ntype.hpp"
2 #include "mathexpr-error.hpp"
3 #include "mathexpr-format.hpp"
4 #include "string.hpp"
5 #include <iostream>
6 #include <map>
8 namespace
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)
17 if(a < b)
18 return -1;
19 if(a > b)
20 return 1;
21 return 0;
24 class expr_val;
26 class expr_val_numeric
28 enum _type
30 T_UNSIGNED,
31 T_SIGNED,
32 T_FLOAT,
33 T_COMPLEX,
35 public:
36 struct unsigned_tag {};
37 struct signed_tag {};
38 struct float_tag {};
39 struct complex_tag {};
40 expr_val_numeric()
42 type = T_SIGNED;
43 v_signed = 0;
44 v_imag = 0;
46 expr_val_numeric(unsigned_tag, uint64_t v)
48 type = T_UNSIGNED;
49 v_unsigned = v;
50 v_imag = 0;
52 expr_val_numeric(signed_tag, int64_t v)
54 type = T_SIGNED;
55 v_signed = v;
56 v_imag = 0;
58 expr_val_numeric(float_tag, double v)
60 type = T_FLOAT;
61 v_float = v;
62 v_imag = 0;
64 expr_val_numeric(complex_tag, double re, double im)
66 type = T_COMPLEX;
67 v_float = re;
68 v_imag = im;
70 expr_val_numeric(const std::string& str)
72 if(str == "i") {
73 type = T_COMPLEX;
74 v_float = 0;
75 v_imag = 1;
76 } else if(regex("[0-9]+|0x[0-9a-fA-F]+", str)) {
77 //UNSIGNED.
78 v_unsigned = parse_value<uint64_t>(str);
79 v_imag = 0;
80 type = T_UNSIGNED;
81 } else if(regex("[+-][0-9]+|[+-]0x[0-9a-fA-F]+", str)) {
82 //SIGNED.
83 v_signed = parse_value<int64_t>(str);
84 v_imag = 0;
85 type = T_SIGNED;
86 } else if(regex("[+-]?([0-9]+|[0-9]*\\.[0-9]+)([eE][0-9]+)?", str)) {
87 //FLOAT.
88 v_float = parse_value<double>(str);
89 v_imag = 0;
90 type = T_FLOAT;
91 } else
92 throw std::runtime_error("Bad number '" + str + "'");
94 double as_float() const
96 switch(type) {
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
106 switch(type) {
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
116 switch(type) {
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()
126 switch(type) {
127 case T_UNSIGNED:
128 return (stringfmt() << v_unsigned).str();
129 case T_SIGNED:
130 return (stringfmt() << v_signed).str();
131 case T_FLOAT:
132 //FIXME: Saner formatting.
133 return (stringfmt() << v_float).str();
134 case T_COMPLEX:
135 //FIXME: Saner formatting.
136 if(v_imag < 0)
137 return (stringfmt() << v_float << v_imag << "*i").str();
138 if(v_imag > 0)
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();
148 int64_t tosigned()
150 return as_signed();
152 void scale(uint64_t scale)
154 switch(type) {
155 case T_UNSIGNED:
156 type = T_FLOAT;
157 v_float = (1.0 * v_unsigned / scale);
158 break;
159 case T_SIGNED:
160 type = T_FLOAT;
161 v_float = (1.0 * v_signed / scale);
162 break;
163 case T_COMPLEX:
164 v_imag /= scale;
165 case T_FLOAT:
166 v_float /= scale;
167 break;
170 bool toboolean()
172 switch(type) {
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)
182 switch(type) {
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
192 switch(type) {
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
232 switch(type) {
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(),
244 v_imag + b.v_imag);
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(),
255 v_imag - b.v_imag);
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;
277 if(div == 0)
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;
316 if(mag == 0)
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);
322 if(as_float() == 0)
323 throw mathexpr_error(mathexpr_error::LOG_BY_0, "Can't take logarithm of 0");
324 if(as_float() <= 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();
344 return tmp.exp();
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
375 return sin()/cos();
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
417 //x - 1/x = 2u
418 //x^2 - 2ux - 1 = 0
419 //(x-u)^2 - x^2 + 2ux - u^2 + x^2 - 2ux - 1 = 0
420 //(x-u)^2 = u^2 + 1
421 expr_val_numeric xmu = (*this * *this) + expr_val_numeric(float_tag(), 1);
422 expr_val_numeric x = xmu.sqrt() + *this;
423 return x.log();
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;
429 return x.log();
431 expr_val_numeric artanh() const
433 //(x-1/x)/(x+1/x)=u
434 //x^2=u+1/(1-u)
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();
455 if(inv)
456 s = -s;
457 if(a.type == T_SIGNED) {
458 int64_t _a = a.v_signed;
459 if(s < -63)
460 return expr_val_numeric(signed_tag(), -1);
461 if(s > 63)
462 return expr_val_numeric(signed_tag(), 0);
463 if(s < 0) {
464 uint64_t r = _a;
465 uint64_t r2 = r >> -s;
466 uint64_t m = 0xFFFFFFFFFFFFFFFFULL - ((1ULL << (64 - s)) - 1);
467 return expr_val_numeric(signed_tag(), m | r2);
468 } else if(s > 0)
469 return expr_val_numeric(signed_tag(), _a << s);
470 else
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);
476 if(s < 0)
477 return expr_val_numeric(unsigned_tag(), _a >> -s);
478 else if(s > 0)
479 return expr_val_numeric(unsigned_tag(), _a << s);
480 else
481 return expr_val_numeric(unsigned_tag(), _a);
482 } else
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)
501 if(b < 0)
502 return 1;
503 //TODO: Handle values too large for exact integer representation.
504 if((double)a < b)
505 return -1;
506 if((double)a > b)
507 return 1;
508 return 0;
510 static int _cmp_float_signed(int64_t a, float b)
512 //TODO: Handle values too large for exact integer representation.
513 if((double)a < b)
514 return -1;
515 if((double)a > b)
516 return 1;
517 return 0;
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");
523 switch(a.type) {
524 case T_UNSIGNED:
525 switch(b.type) {
526 case T_UNSIGNED:
527 return _cmp_values(a.v_unsigned, b.v_unsigned);
528 case T_SIGNED:
529 if(b.v_signed < 0)
530 return 1;
531 if((int64_t)a.v_unsigned < 0)
532 return 1;
533 return _cmp_values((int64_t)a.v_unsigned, b.v_signed);
534 case T_FLOAT:
535 return _cmp_float_unsigned(a.v_unsigned, b.v_float);
536 case T_COMPLEX:
537 throw mathexpr_error(mathexpr_error::INTERNAL,
538 "Internal error (shouldn't be here)");
540 case T_SIGNED:
541 switch(b.type) {
542 case T_UNSIGNED:
543 if(a.v_signed < 0)
544 return -1;
545 if((int64_t)b.v_unsigned < 0)
546 return -1;
547 return _cmp_values(a.v_signed, (int64_t)b.v_unsigned);
548 case T_SIGNED:
549 return _cmp_values(a.v_signed, b.v_signed);
550 case T_FLOAT:
551 return _cmp_float_signed(a.v_signed, b.v_float);
552 case T_COMPLEX:
553 throw mathexpr_error(mathexpr_error::INTERNAL,
554 "Internal error (shouldn't be here)");
556 case T_FLOAT:
557 switch(b.type) {
558 case T_UNSIGNED:
559 return -_cmp_float_unsigned(b.v_unsigned, a.v_float);
560 case T_SIGNED:
561 return -_cmp_float_signed(b.v_signed, a.v_float);
562 case T_FLOAT:
563 if(a.v_float < b.v_float)
564 return -1;
565 if(a.v_float > b.v_float)
566 return 1;
567 return 0;
568 case T_COMPLEX:
569 throw mathexpr_error(mathexpr_error::INTERNAL,
570 "Internal error (shouldn't be here)");
572 case T_COMPLEX:
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)
579 switch(a.type) {
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)
588 switch(a.type) {
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)
597 switch(a.type) {
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
624 switch(type) {
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
634 switch(type) {
635 case T_COMPLEX: return expr_val_numeric(float_tag(), ::atan2(v_imag, v_float));
636 default:
637 if(as_float() < 0)
638 return expr_val_numeric(float_tag(), 4 * ::atan(1));
639 else
640 return expr_val_numeric(float_tag(), 0);
643 private:
644 enum _type type;
645 union {
646 uint64_t v_unsigned;
647 int64_t v_signed;
648 double v_float;
650 double v_imag;
653 class expr_val
655 struct boolean_tag {};
656 struct number_tag {};
657 struct string_tag {};
658 enum _type
660 T_BOOLEAN,
661 T_NUMERIC,
662 T_STRING,
664 expr_val_numeric& as_numeric()
666 if(type != T_NUMERIC)
667 throw_domain("Can't operate with non-numbers");
668 return v_numeric;
670 public:
671 expr_val()
673 type = T_NUMERIC;
675 expr_val(const std::string& str, bool string)
677 if(string) {
678 v_string = str;
679 type = T_STRING;
680 } else if(str == "false") {
681 v_boolean = false;
682 type = T_BOOLEAN;
683 } else if(str == "true") {
684 v_boolean = true;
685 type = T_BOOLEAN;
686 } else if(str == "e") {
687 v_numeric = expr_val_numeric::op_e();
688 type = T_NUMERIC;
689 } else if(str == "pi") {
690 v_numeric = expr_val_numeric::op_pi();
691 type = T_NUMERIC;
692 } else {
693 v_numeric = expr_val_numeric(str);
694 type = T_NUMERIC;
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()
723 switch(type) {
724 case T_BOOLEAN:
725 if(v_boolean)
726 return "true";
727 else
728 return "false";
729 case T_NUMERIC:
730 return v_numeric.tostring();
731 case T_STRING:
732 return v_string;
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();
742 int64_t tosigned()
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);
754 bool toboolean()
756 switch(type) {
757 case T_BOOLEAN:
758 return v_boolean;
759 case T_NUMERIC:
760 return v_numeric.toboolean();
761 case T_STRING:
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]();
793 else
794 return expr_val(boolean_tag(), false);
795 } else if(promises.size() == 3) {
796 if((promises[0]().toboolean()))
797 return promises[1]();
798 else
799 return promises[2]();
800 } else
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) {
806 expr_val v = i();
807 if(v.type != T_BOOLEAN || v.v_boolean)
808 return v;
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)
816 v.push_back(i());
817 expr_val_numeric n(expr_val_numeric::float_tag(), 0);
818 expr_val_numeric one(expr_val_numeric::float_tag(), 1);
819 for(auto& i : v) {
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;
824 return n.sqrt();
826 template<expr_val (*T)(expr_val& a, expr_val& b)>
827 static expr_val fun_fold(std::vector<std::function<expr_val&()>> promises)
829 if(!promises.size())
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]());
834 return v;
836 static expr_val fold_min(expr_val& a, expr_val& b)
838 int t = _cmp_values(a.type, b.type);
839 if(t < 0)
840 return a;
841 if(t > 0)
842 return b;
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);
848 if(t < 0)
849 return a;
850 if(t > 0)
851 return b;
852 return (_cmp(a, b) > 0) ? a : b;
854 static expr_val fold_sum(expr_val& a, expr_val& b)
856 return add(a, b);
858 static expr_val fold_prod(expr_val& a, expr_val& b)
860 return mul(a, 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]();
869 return T(a, b);
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]();
877 return T(a);
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)
954 if(a.type != b.type)
955 return false;
956 switch(a.type) {
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)
973 if(a.type != b.type)
974 throw_domain("Can't compare distinct value types");
975 switch(a.type) {
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)
1008 val = " " + val;
1009 return val;
1011 std::string print_bool_numeric(bool val, mathexpr_format fmt)
1013 std::string out = val ? "1" : "0";
1014 if(fmt.precision > 0) {
1015 out += ".";
1016 for(int i = 0; i < fmt.precision; i++)
1017 out += "0";
1019 while((int)out.length() < fmt.width)
1020 out = ((fmt.fillzeros) ? "0" : " ") + out;
1021 return out;
1023 std::string format(mathexpr_format fmt)
1025 switch(type) {
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);
1029 default:
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},
1094 return x.get_set();
1096 private:
1097 _type type;
1098 bool v_boolean;
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> {
1116 if(!vars.count(n))
1117 vars.insert(std::make_pair(n, gcroot_pointer<mathexpr>(expression_value())));
1118 gcroot_pointer<mathexpr>& tmp = vars.find(n)->second;
1119 return tmp;
1121 for(int i = 1; i < argc; i++) {
1122 regex_results r = regex("([^=]+)=(.*)", argv[i]);
1123 if(!r)
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) {
1130 try {
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;
1137 return 0;
1140 int main(int argc, char** argv)
1142 int r = main2(argc, argv);
1143 garbage_collectable::do_gc();
1144 return r;
1148 #endif