Actually call on_reset callback
[lsnes.git] / src / library / mathexpr-ntype.cpp
blob166a90e9efd8656317515f64e59a919834acd301
1 #include "mathexpr-ntype.hpp"
2 #include "mathexpr-error.hpp"
3 #include "mathexpr-format.hpp"
4 #include "string.hpp"
5 #include <functional>
6 #include <iostream>
7 #include <map>
9 namespace mathexpr
11 namespace
13 void throw_domain(const std::string& err)
15 throw error(error::WDOMAIN, err);
18 template<typename T> int _cmp_values(T a, T b)
20 if(a < b)
21 return -1;
22 if(a > b)
23 return 1;
24 return 0;
27 class expr_val;
29 class expr_val_numeric
31 enum _type
33 T_UNSIGNED,
34 T_SIGNED,
35 T_FLOAT,
36 T_COMPLEX,
38 public:
39 struct unsigned_tag {};
40 struct signed_tag {};
41 struct float_tag {};
42 struct complex_tag {};
43 expr_val_numeric()
45 type = T_SIGNED;
46 v_signed = 0;
47 v_imag = 0;
49 expr_val_numeric(unsigned_tag, uint64_t v)
51 type = T_UNSIGNED;
52 v_unsigned = v;
53 v_imag = 0;
55 expr_val_numeric(signed_tag, int64_t v)
57 type = T_SIGNED;
58 v_signed = v;
59 v_imag = 0;
61 expr_val_numeric(float_tag, double v)
63 type = T_FLOAT;
64 v_float = v;
65 v_imag = 0;
67 expr_val_numeric(complex_tag, double re, double im)
69 type = T_COMPLEX;
70 v_float = re;
71 v_imag = im;
73 expr_val_numeric(const std::string& str)
75 if(str == "i") {
76 type = T_COMPLEX;
77 v_float = 0;
78 v_imag = 1;
79 } else if(regex("[0-9]+|0x[0-9a-fA-F]+", str)) {
80 //UNSIGNED.
81 v_unsigned = parse_value<uint64_t>(str);
82 v_imag = 0;
83 type = T_UNSIGNED;
84 } else if(regex("[+-][0-9]+|[+-]0x[0-9a-fA-F]+", str)) {
85 //SIGNED.
86 v_signed = parse_value<int64_t>(str);
87 v_imag = 0;
88 type = T_SIGNED;
89 } else if(regex("[+-]?([0-9]+|[0-9]*\\.[0-9]+)([eE][0-9]+)?", str)) {
90 //FLOAT.
91 v_float = parse_value<double>(str);
92 v_imag = 0;
93 type = T_FLOAT;
94 } else
95 throw std::runtime_error("Bad number '" + str + "'");
97 double as_float() const
99 switch(type) {
100 case T_UNSIGNED: return v_unsigned;
101 case T_SIGNED: return v_signed;
102 case T_FLOAT: return v_float;
103 case T_COMPLEX: return v_float;
105 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
107 int64_t as_signed() const
109 switch(type) {
110 case T_UNSIGNED: return v_unsigned;
111 case T_SIGNED: return v_signed;
112 case T_FLOAT: return v_float;
113 case T_COMPLEX: return v_float;
115 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
117 uint64_t as_unsigned() const
119 switch(type) {
120 case T_UNSIGNED: return v_unsigned;
121 case T_SIGNED: return v_signed;
122 case T_FLOAT: return v_float;
123 case T_COMPLEX: return v_float;
125 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
127 std::string tostring()
129 switch(type) {
130 case T_UNSIGNED:
131 return (stringfmt() << v_unsigned).str();
132 case T_SIGNED:
133 return (stringfmt() << v_signed).str();
134 case T_FLOAT:
135 //FIXME: Saner formatting.
136 return (stringfmt() << v_float).str();
137 case T_COMPLEX:
138 //FIXME: Saner formatting.
139 if(v_imag < 0)
140 return (stringfmt() << v_float << v_imag << "*i").str();
141 if(v_imag > 0)
142 return (stringfmt() << v_float << "+" << v_imag << "*i").str();
143 return (stringfmt() << v_float).str();
145 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
147 uint64_t tounsigned()
149 return as_unsigned();
151 int64_t tosigned()
153 return as_signed();
155 void scale(uint64_t scale)
157 switch(type) {
158 case T_UNSIGNED:
159 type = T_FLOAT;
160 v_float = (1.0 * v_unsigned / scale);
161 break;
162 case T_SIGNED:
163 type = T_FLOAT;
164 v_float = (1.0 * v_signed / scale);
165 break;
166 case T_COMPLEX:
167 v_imag /= scale;
168 case T_FLOAT:
169 v_float /= scale;
170 break;
173 bool toboolean()
175 switch(type) {
176 case T_UNSIGNED: return (v_unsigned != 0);
177 case T_SIGNED: return (v_signed != 0);
178 case T_FLOAT: return (v_float != 0);
179 case T_COMPLEX: return (v_float != 0) || (v_imag != 0);
181 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
183 std::string format(_format fmt)
185 switch(type) {
186 case T_UNSIGNED: return format_unsigned(v_unsigned, fmt);
187 case T_SIGNED: return format_signed(v_signed, fmt);
188 case T_FLOAT: return format_float(v_float, fmt);
189 case T_COMPLEX: return format_complex(v_float, v_imag, fmt);
191 throw error(error::INTERNAL, "Don't know how to print numeric type");
193 expr_val_numeric operator~() const
195 switch(type) {
196 case T_UNSIGNED: return expr_val_numeric(unsigned_tag(), ~v_unsigned);
197 case T_SIGNED: return expr_val_numeric(signed_tag(), ~v_signed);
198 case T_FLOAT: throw_domain("Bit operations are only for integers");
199 case T_COMPLEX: throw_domain("Bit operations are only for integers");
201 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
203 expr_val_numeric operator&(const expr_val_numeric& b) const
205 if(type == T_COMPLEX || b.type == T_COMPLEX)
206 throw_domain("Bit operations are only for integers");
207 if(type == T_FLOAT || b.type == T_FLOAT)
208 throw_domain("Bit operations are only for integers");
209 if(type == T_SIGNED || b.type == T_SIGNED)
210 return expr_val_numeric(signed_tag(), as_signed() & b.as_signed());
211 return expr_val_numeric(unsigned_tag(), as_unsigned() & b.as_unsigned());
213 expr_val_numeric operator|(const expr_val_numeric& b) const
215 if(type == T_COMPLEX || b.type == T_COMPLEX)
216 throw_domain("Bit operations are only for integers");
217 if(type == T_FLOAT || b.type == T_FLOAT)
218 throw_domain("Bit operations are only for integers");
219 if(type == T_SIGNED || b.type == T_SIGNED)
220 return expr_val_numeric(signed_tag(), as_signed() | b.as_signed());
221 return expr_val_numeric(unsigned_tag(), as_unsigned() | b.as_unsigned());
223 expr_val_numeric operator^(const expr_val_numeric& b) const
225 if(type == T_COMPLEX || b.type == T_COMPLEX)
226 throw_domain("Bit operations are only for integers");
227 if(type == T_FLOAT || b.type == T_FLOAT)
228 throw_domain("Bit operations are only for integers");
229 if(type == T_SIGNED || b.type == T_SIGNED)
230 return expr_val_numeric(signed_tag(), as_signed() ^ b.as_signed());
231 return expr_val_numeric(unsigned_tag(), as_unsigned() ^ b.as_unsigned());
233 expr_val_numeric operator-() const
235 switch(type) {
236 case T_COMPLEX: return expr_val_numeric(complex_tag(), -v_float, -v_imag);
237 case T_UNSIGNED: return expr_val_numeric(signed_tag(), -(int64_t)v_unsigned);
238 case T_SIGNED: return expr_val_numeric(signed_tag(), -v_signed);
239 case T_FLOAT: return expr_val_numeric(float_tag(), -v_float);
241 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
243 expr_val_numeric operator+(const expr_val_numeric& b) const
245 if(type == T_COMPLEX || b.type == T_COMPLEX)
246 return expr_val_numeric(complex_tag(), as_float() + b.as_float(),
247 v_imag + b.v_imag);
248 if(type == T_FLOAT || b.type == T_FLOAT)
249 return expr_val_numeric(float_tag(), as_float() + b.as_float());
250 if(type == T_SIGNED || b.type == T_SIGNED)
251 return expr_val_numeric(signed_tag(), as_signed() + b.as_signed());
252 return expr_val_numeric(unsigned_tag(), as_unsigned() + b.as_unsigned());
254 expr_val_numeric operator-(const expr_val_numeric& b) const
256 if(type == T_COMPLEX || b.type == T_COMPLEX)
257 return expr_val_numeric(complex_tag(), as_float() - b.as_float(),
258 v_imag - b.v_imag);
259 if(type == T_FLOAT || b.type == T_FLOAT)
260 return expr_val_numeric(float_tag(), as_float() - b.as_float());
261 if(type == T_SIGNED || b.type == T_SIGNED)
262 return expr_val_numeric(signed_tag(), as_signed() - b.as_signed());
263 return expr_val_numeric(unsigned_tag(), as_unsigned() - b.as_unsigned());
265 expr_val_numeric operator*(const expr_val_numeric& b) const
267 if(type == T_COMPLEX || b.type == T_COMPLEX)
268 return expr_val_numeric(complex_tag(), as_float() * b.as_float() - v_imag * b.v_imag,
269 as_float() * b.v_imag + b.as_float() * v_imag);
270 if(type == T_FLOAT || b.type == T_FLOAT)
271 return expr_val_numeric(float_tag(), as_float() * b.as_float());
272 if(type == T_SIGNED || b.type == T_SIGNED)
273 return expr_val_numeric(signed_tag(), as_signed() * b.as_signed());
274 return expr_val_numeric(unsigned_tag(), as_unsigned() * b.as_unsigned());
276 expr_val_numeric operator/(const expr_val_numeric& b) const
278 if(type == T_COMPLEX || b.type == T_COMPLEX) {
279 double div = b.as_float() * b.as_float() + b.v_imag * b.v_imag;
280 if(div == 0)
281 throw error(error::DIV_BY_0, "Division by 0");
282 return expr_val_numeric(complex_tag(),
283 (as_float() * b.as_float() + v_imag * b.v_imag) / div,
284 (v_imag * b.as_float() - as_float() * b.v_imag) / div);
286 if(type == T_FLOAT || b.type == T_FLOAT) {
287 if(b.as_float() == 0)
288 throw error(error::DIV_BY_0, "Division by 0");
289 return expr_val_numeric(float_tag(), as_float() / b.as_float());
291 if(type == T_SIGNED || b.type == T_SIGNED) {
292 if(b.as_signed() == 0)
293 throw error(error::DIV_BY_0, "Division by 0");
294 return expr_val_numeric(signed_tag(), as_signed() / b.as_signed());
296 if(b.as_unsigned() == 0)
297 throw error(error::DIV_BY_0, "Division by 0");
298 return expr_val_numeric(unsigned_tag(), as_unsigned() / b.as_unsigned());
300 expr_val_numeric operator%(const expr_val_numeric& b) const
302 if(type == T_COMPLEX || b.type == T_COMPLEX)
303 throw_domain("Remainder is only for integers");
304 if(type == T_FLOAT || b.type == T_FLOAT)
305 throw_domain("Remainder is only for integers");
306 if(type == T_SIGNED || b.type == T_SIGNED) {
307 if(b.as_signed() == 0)
308 throw error(error::DIV_BY_0, "Division by 0");
309 return expr_val_numeric(signed_tag(), as_signed() / b.as_signed());
311 if(b.as_unsigned() == 0)
312 throw error(error::DIV_BY_0, "Division by 0");
313 return expr_val_numeric(unsigned_tag(), as_unsigned() / b.as_unsigned());
315 expr_val_numeric log() const
317 if(type == T_COMPLEX) {
318 double mag = as_float() * as_float() + v_imag * v_imag;
319 if(mag == 0)
320 throw error(error::LOG_BY_0, "Can't take logarithm of 0");
321 double r = 0.5 * ::log(mag);
322 double i = ::atan2(v_imag, as_float());
323 return expr_val_numeric(complex_tag(), r, i);
325 if(as_float() == 0)
326 throw error(error::LOG_BY_0, "Can't take logarithm of 0");
327 if(as_float() <= 0)
328 return expr_val_numeric(complex_tag(), ::log(std::abs(as_float())), 4 * ::atan(1));
329 return expr_val_numeric(float_tag(), ::log(as_float()));
331 static expr_val_numeric log2(expr_val_numeric a, expr_val_numeric b)
333 return b.log() / a.log();
335 expr_val_numeric exp() const
337 if(type == T_COMPLEX) {
338 double mag = ::exp(as_float());
339 return expr_val_numeric(complex_tag(), mag * ::cos(v_imag),
340 mag * ::sin(v_imag));
342 return expr_val_numeric(float_tag(), ::exp(as_float()));
344 static expr_val_numeric exp2(expr_val_numeric a, expr_val_numeric b)
346 expr_val_numeric tmp = b * a.log();
347 return tmp.exp();
349 expr_val_numeric sqrt() const
351 if(as_float() < 0 && type != T_COMPLEX)
352 return expr_val_numeric(complex_tag(), 0, ::sqrt(-as_float()));
353 if(type == T_COMPLEX) {
354 double mag = ::sqrt(::sqrt(as_float() * as_float() + v_imag * v_imag));
355 double ar = 0.5 * ::atan2(v_imag, as_float());
356 return expr_val_numeric(complex_tag(), mag * ::cos(ar), mag * ::sin(ar));
358 return expr_val_numeric(float_tag(), ::sqrt(as_float()));
360 expr_val_numeric sin() const
362 if(type == T_COMPLEX) {
363 return expr_val_numeric(complex_tag(), ::sin(as_float()) * ::cosh(v_imag),
364 ::cos(as_float()) * ::sinh(v_imag));
366 return expr_val_numeric(float_tag(), ::sin(as_float()));
368 expr_val_numeric cos() const
370 if(type == T_COMPLEX) {
371 return expr_val_numeric(complex_tag(), ::cos(as_float()) * ::cosh(v_imag),
372 -::sin(as_float()) * ::sinh(v_imag));
374 return expr_val_numeric(float_tag(), ::cos(as_float()));
376 expr_val_numeric tan() const
378 return sin()/cos();
380 expr_val_numeric atan() const
382 if(type == T_COMPLEX) {
383 expr_val_numeric x = expr_val_numeric(complex_tag(), 0, 1) * *this;
384 expr_val_numeric n = expr_val_numeric(complex_tag(), 1, 0) + x;
385 expr_val_numeric d = expr_val_numeric(complex_tag(), 1, 0) - x;
386 expr_val_numeric y = n / d;
387 expr_val_numeric w = y.log();
388 return w / expr_val_numeric(complex_tag(), 0, 2);
390 return expr_val_numeric(float_tag(), ::atan(as_float()));
392 expr_val_numeric acos() const
394 expr_val_numeric sinesqr = (expr_val_numeric(float_tag(), 1) - *this * *this);
395 expr_val_numeric sine = sinesqr.sqrt();
396 expr_val_numeric tangent = sine / *this;
397 return tangent.atan();
399 expr_val_numeric asin() const
401 expr_val_numeric cosinesqr = (expr_val_numeric(float_tag(), 1) - *this * *this);
402 expr_val_numeric cosine = cosinesqr.sqrt();
403 expr_val_numeric tangent = *this / cosine;
404 return tangent.atan();
406 expr_val_numeric sinh() const
408 return (exp() - (-*this).exp()) / expr_val_numeric(float_tag(), 2);
410 expr_val_numeric cosh() const
412 return (exp() + (-*this).exp()) / expr_val_numeric(float_tag(), 2);
414 expr_val_numeric tanh() const
416 return sinh() / cosh();
418 expr_val_numeric arsinh() const
420 //x - 1/x = 2u
421 //x^2 - 2ux - 1 = 0
422 //(x-u)^2 - x^2 + 2ux - u^2 + x^2 - 2ux - 1 = 0
423 //(x-u)^2 = u^2 + 1
424 expr_val_numeric xmu = (*this * *this) + expr_val_numeric(float_tag(), 1);
425 expr_val_numeric x = xmu.sqrt() + *this;
426 return x.log();
428 expr_val_numeric arcosh() const
430 expr_val_numeric xmu = (*this * *this) - expr_val_numeric(float_tag(), 1);
431 expr_val_numeric x = xmu.sqrt() + *this;
432 return x.log();
434 expr_val_numeric artanh() const
436 //(x-1/x)/(x+1/x)=u
437 //x^2=u+1/(1-u)
438 expr_val_numeric t(float_tag(), 1);
439 return ((t + *this) / (t - *this)).sqrt().log();
441 static expr_val_numeric atan2(expr_val_numeric a, expr_val_numeric b)
443 if(a.type == T_COMPLEX || b.type == T_COMPLEX)
444 throw_domain("atan2 is only for reals");
445 return expr_val_numeric(float_tag(), ::atan2(a.as_float(), b.as_float()));
447 expr_val_numeric torad() const
449 return expr_val_numeric(float_tag(), ::atan(1) / 45 * as_float());
451 expr_val_numeric todeg() const
453 return expr_val_numeric(float_tag(), 45 / ::atan(1) * as_float());
455 static expr_val_numeric shift(expr_val_numeric a, expr_val_numeric b, bool inv)
457 int64_t s = b.as_signed();
458 if(inv)
459 s = -s;
460 if(a.type == T_SIGNED) {
461 int64_t _a = a.v_signed;
462 if(s < -63)
463 return expr_val_numeric(signed_tag(), -1);
464 if(s > 63)
465 return expr_val_numeric(signed_tag(), 0);
466 if(s < 0) {
467 uint64_t r = _a;
468 uint64_t r2 = r >> -s;
469 uint64_t m = 0xFFFFFFFFFFFFFFFFULL - ((1ULL << (64 - s)) - 1);
470 return expr_val_numeric(signed_tag(), m | r2);
471 } else if(s > 0)
472 return expr_val_numeric(signed_tag(), _a << s);
473 else
474 return expr_val_numeric(signed_tag(), _a);
475 } else if(a.type == T_UNSIGNED) {
476 uint64_t _a = a.v_unsigned;
477 if(s < -63 || s > 63)
478 return expr_val_numeric(unsigned_tag(), 0);
479 if(s < 0)
480 return expr_val_numeric(unsigned_tag(), _a >> -s);
481 else if(s > 0)
482 return expr_val_numeric(unsigned_tag(), _a << s);
483 else
484 return expr_val_numeric(unsigned_tag(), _a);
485 } else
486 throw_domain("Bit operations are only for integers");
487 return expr_val_numeric(unsigned_tag(), 0); //NOTREACHED
489 static expr_val_numeric op_pi()
491 return expr_val_numeric(float_tag(), 4 * ::atan(1));
493 static expr_val_numeric op_e()
495 return expr_val_numeric(float_tag(), ::exp(1));
497 bool operator==(const expr_val_numeric& b) const
499 if(type == T_COMPLEX || b.type == T_COMPLEX)
500 return as_float() == b.as_float() && v_imag == b.v_imag;
501 return (_cmp(*this, b) == 0);
503 static int _cmp_float_unsigned(uint64_t a, float b)
505 if(b < 0)
506 return 1;
507 //TODO: Handle values too large for exact integer representation.
508 if((double)a < b)
509 return -1;
510 if((double)a > b)
511 return 1;
512 return 0;
514 static int _cmp_float_signed(int64_t a, float b)
516 //TODO: Handle values too large for exact integer representation.
517 if((double)a < b)
518 return -1;
519 if((double)a > b)
520 return 1;
521 return 0;
523 static int _cmp(expr_val_numeric a, expr_val_numeric b)
525 if(a.type == T_COMPLEX || b.type == T_COMPLEX)
526 throw_domain("Can't compare complex numbers");
527 switch(a.type) {
528 case T_UNSIGNED:
529 switch(b.type) {
530 case T_UNSIGNED:
531 return _cmp_values(a.v_unsigned, b.v_unsigned);
532 case T_SIGNED:
533 if(b.v_signed < 0)
534 return 1;
535 if((int64_t)a.v_unsigned < 0)
536 return 1;
537 return _cmp_values((int64_t)a.v_unsigned, b.v_signed);
538 case T_FLOAT:
539 return _cmp_float_unsigned(a.v_unsigned, b.v_float);
540 case T_COMPLEX:
541 throw error(error::INTERNAL,
542 "Internal error (shouldn't be here)");
544 case T_SIGNED:
545 switch(b.type) {
546 case T_UNSIGNED:
547 if(a.v_signed < 0)
548 return -1;
549 if((int64_t)b.v_unsigned < 0)
550 return -1;
551 return _cmp_values(a.v_signed, (int64_t)b.v_unsigned);
552 case T_SIGNED:
553 return _cmp_values(a.v_signed, b.v_signed);
554 case T_FLOAT:
555 return _cmp_float_signed(a.v_signed, b.v_float);
556 case T_COMPLEX:
557 throw error(error::INTERNAL,
558 "Internal error (shouldn't be here)");
560 case T_FLOAT:
561 switch(b.type) {
562 case T_UNSIGNED:
563 return -_cmp_float_unsigned(b.v_unsigned, a.v_float);
564 case T_SIGNED:
565 return -_cmp_float_signed(b.v_signed, a.v_float);
566 case T_FLOAT:
567 if(a.v_float < b.v_float)
568 return -1;
569 if(a.v_float > b.v_float)
570 return 1;
571 return 0;
572 case T_COMPLEX:
573 throw error(error::INTERNAL,
574 "Internal error (shouldn't be here)");
576 case T_COMPLEX:
577 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
579 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
581 static expr_val_numeric x_unsigned(expr_val_numeric a)
583 switch(a.type) {
584 case T_UNSIGNED: return expr_val_numeric(unsigned_tag(), a.v_unsigned);
585 case T_SIGNED: return expr_val_numeric(unsigned_tag(), a.v_signed);
586 case T_FLOAT: return expr_val_numeric(unsigned_tag(), a.v_float);
587 default: throw_domain("Can't convert non-real into unsigned");
589 return expr_val_numeric(unsigned_tag(), 0); //NOTREACHED.
591 static expr_val_numeric x_signed(expr_val_numeric a)
593 switch(a.type) {
594 case T_UNSIGNED: return expr_val_numeric(signed_tag(), a.v_unsigned);
595 case T_SIGNED: return expr_val_numeric(signed_tag(), a.v_signed);
596 case T_FLOAT: return expr_val_numeric(signed_tag(), a.v_float);
597 default: throw_domain("Can't convert non-real into signed");
599 return expr_val_numeric(signed_tag(), 0); //NOTREACHED.
601 static expr_val_numeric x_float(expr_val_numeric a)
603 switch(a.type) {
604 case T_UNSIGNED: return expr_val_numeric(float_tag(), a.v_unsigned);
605 case T_SIGNED: return expr_val_numeric(float_tag(), a.v_signed);
606 case T_FLOAT: return expr_val_numeric(float_tag(), a.v_float);
607 default: throw_domain("Can't convert non-real into float");
609 return expr_val_numeric(float_tag(), 0); //NOTREACHED.
611 expr_val_numeric re() const
613 if(type == T_COMPLEX)
614 return expr_val_numeric(float_tag(), v_float);
615 return expr_val_numeric(float_tag(), as_float());
617 expr_val_numeric im() const
619 if(type == T_COMPLEX)
620 return expr_val_numeric(float_tag(), v_imag);
621 return expr_val_numeric(float_tag(), 0);
623 expr_val_numeric conj() const
625 if(type == T_COMPLEX)
626 return expr_val_numeric(complex_tag(), v_float, -v_imag);
627 return expr_val_numeric(float_tag(), as_float());
629 expr_val_numeric abs() const
631 switch(type) {
632 case T_COMPLEX: return expr_val_numeric(float_tag(), v_float * v_float + v_imag * v_imag);
633 case T_FLOAT: return expr_val_numeric(float_tag(), ::fabs(v_float));
634 case T_SIGNED: return expr_val_numeric(signed_tag(), ::abs(v_signed));
635 case T_UNSIGNED: return expr_val_numeric(unsigned_tag(), v_unsigned);
637 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
639 expr_val_numeric arg() const
641 switch(type) {
642 case T_COMPLEX: return expr_val_numeric(float_tag(), ::atan2(v_imag, v_float));
643 default:
644 if(as_float() < 0)
645 return expr_val_numeric(float_tag(), 4 * ::atan(1));
646 else
647 return expr_val_numeric(float_tag(), 0);
650 private:
651 enum _type type;
652 union {
653 uint64_t v_unsigned;
654 int64_t v_signed;
655 double v_float;
657 double v_imag;
660 class expr_val
662 struct number_tag {};
663 struct string_tag {};
664 struct boolean_tag {};
665 enum _type
667 T_BOOLEAN,
668 T_NUMERIC,
669 T_STRING,
671 expr_val_numeric& as_numeric()
673 if(type != T_NUMERIC)
674 throw_domain("Can't operate with non-numbers");
675 return v_numeric;
677 public:
678 expr_val()
680 type = T_NUMERIC;
681 v_boolean = false;
683 expr_val(const std::string& str, bool string)
685 v_boolean = false;
686 if(string) {
687 v_string = str;
688 type = T_STRING;
689 } else if(str == "false") {
690 v_boolean = false;
691 type = T_BOOLEAN;
692 } else if(str == "true") {
693 v_boolean = true;
694 type = T_BOOLEAN;
695 } else if(str == "e") {
696 v_numeric = expr_val_numeric::op_e();
697 type = T_NUMERIC;
698 } else if(str == "pi") {
699 v_numeric = expr_val_numeric::op_pi();
700 type = T_NUMERIC;
701 } else {
702 v_numeric = expr_val_numeric(str);
703 type = T_NUMERIC;
706 expr_val(typeinfo_wrapper<expr_val>::unsigned_tag t, uint64_t v)
707 : type(T_NUMERIC), v_boolean(false), v_numeric(expr_val_numeric::unsigned_tag(), v)
710 expr_val(typeinfo_wrapper<expr_val>::signed_tag t, int64_t v)
711 : type(T_NUMERIC), v_boolean(false), v_numeric(expr_val_numeric::signed_tag(), v)
714 expr_val(typeinfo_wrapper<expr_val>::float_tag t, double v)
715 : type(T_NUMERIC), v_boolean(false), v_numeric(expr_val_numeric::float_tag(), v)
718 expr_val(typeinfo_wrapper<expr_val>::boolean_tag, bool b)
719 : type(T_BOOLEAN), v_boolean(b)
722 expr_val(expr_val_numeric v)
723 : type(T_NUMERIC), v_boolean(false), v_numeric(v)
726 expr_val(string_tag, std::string s)
727 : type(T_STRING), v_boolean(false), v_string(s)
730 expr_val(boolean_tag, bool b)
731 : type(T_BOOLEAN), v_boolean(b)
734 std::string tostring()
736 switch(type) {
737 case T_BOOLEAN:
738 if(v_boolean)
739 return "true";
740 else
741 return "false";
742 case T_NUMERIC:
743 return v_numeric.tostring();
744 case T_STRING:
745 return v_string;
747 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
749 uint64_t tounsigned()
751 if(type != T_NUMERIC)
752 throw_domain("Can't convert non-number into unsigned");
753 return v_numeric.tounsigned();
755 int64_t tosigned()
757 if(type != T_NUMERIC)
758 throw_domain("Can't convert non-number into signed");
759 return v_numeric.tosigned();
761 void scale(uint64_t _scale)
763 if(type != T_NUMERIC)
764 throw_domain("Can't scale non-number");
765 v_numeric.scale(_scale);
767 bool toboolean()
769 switch(type) {
770 case T_BOOLEAN:
771 return v_boolean;
772 case T_NUMERIC:
773 return v_numeric.toboolean();
774 case T_STRING:
775 return (v_string.length() != 0);
777 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
779 static expr_val op_lnot(std::vector<std::function<expr_val&()>> promises)
781 if(promises.size() != 1)
782 throw error(error::ARGCOUNT, "logical not takes 1 argument");
783 return expr_val(boolean_tag(), !(promises[0]().toboolean()));
785 static expr_val op_lor(std::vector<std::function<expr_val&()>> promises)
787 if(promises.size() != 2)
788 throw error(error::ARGCOUNT, "logical or takes 2 arguments");
789 if(promises[0]().toboolean())
790 return expr_val(boolean_tag(), true);
791 return expr_val(boolean_tag(), promises[1]().toboolean());
793 static expr_val op_land(std::vector<std::function<expr_val&()>> promises)
795 if(promises.size() != 2)
796 throw error(error::ARGCOUNT, "logical and takes 2 arguments");
797 if(!(promises[0]().toboolean()))
798 return expr_val(boolean_tag(), false);
799 return expr_val(boolean_tag(), promises[1]().toboolean());
801 static expr_val fun_if(std::vector<std::function<expr_val&()>> promises)
803 if(promises.size() == 2) {
804 if((promises[0]().toboolean()))
805 return promises[1]();
806 else
807 return expr_val(boolean_tag(), false);
808 } else if(promises.size() == 3) {
809 if((promises[0]().toboolean()))
810 return promises[1]();
811 else
812 return promises[2]();
813 } else
814 throw error(error::ARGCOUNT, "if takes 2 or 3 arguments");
816 static expr_val fun_select(std::vector<std::function<expr_val&()>> promises)
818 for(auto& i : promises) {
819 expr_val v = i();
820 if(v.type != T_BOOLEAN || v.v_boolean)
821 return v;
823 return expr_val(boolean_tag(), false);
825 static expr_val fun_pyth(std::vector<std::function<expr_val&()>> promises)
827 std::vector<expr_val> v;
828 for(auto& i : promises)
829 v.push_back(i());
830 expr_val_numeric n(expr_val_numeric::float_tag(), 0);
831 expr_val_numeric one(expr_val_numeric::float_tag(), 1);
832 for(auto& i : v) {
833 if(i.type != T_NUMERIC)
834 throw error(error::WDOMAIN, "pyth requires numeric args");
835 n = n + one * i.v_numeric * i.v_numeric;
837 return n.sqrt();
839 template<expr_val (*T)(expr_val& a, expr_val& b)>
840 static expr_val fun_fold(std::vector<std::function<expr_val&()>> promises)
842 if(!promises.size())
843 return expr_val(boolean_tag(), false);
844 expr_val v = promises[0]();
845 for(size_t i = 1; i < promises.size(); i++)
846 v = T(v, promises[i]());
847 return v;
849 static expr_val fold_min(expr_val& a, expr_val& b)
851 int t = _cmp_values(a.type, b.type);
852 if(t < 0)
853 return a;
854 if(t > 0)
855 return b;
856 return (_cmp(a, b) < 0) ? a : b;
858 static expr_val fold_max(expr_val& a, expr_val& b)
860 int t = _cmp_values(a.type, b.type);
861 if(t < 0)
862 return a;
863 if(t > 0)
864 return b;
865 return (_cmp(a, b) > 0) ? a : b;
867 static expr_val fold_sum(expr_val& a, expr_val& b)
869 return add(a, b);
871 static expr_val fold_prod(expr_val& a, expr_val& b)
873 return mul(a, b);
875 template<expr_val (*T)(expr_val a, expr_val b)>
876 static expr_val op_binary(std::vector<std::function<expr_val&()>> promises)
878 if(promises.size() != 2)
879 throw error(error::ARGCOUNT, "Operation takes 2 arguments");
880 expr_val a = promises[0]();
881 expr_val b = promises[1]();
882 return T(a, b);
884 template<expr_val (*T)(expr_val a)>
885 static expr_val op_unary(std::vector<std::function<expr_val&()>> promises)
887 if(promises.size() != 1)
888 throw error(error::ARGCOUNT, "Operation takes 1 argument");
889 expr_val a = promises[0]();
890 return T(a);
892 template<expr_val (*T)(expr_val a),expr_val (*U)(expr_val a, expr_val b)>
893 static expr_val op_unary_binary(std::vector<std::function<expr_val&()>> promises)
895 if(promises.size() == 1)
896 return T(promises[0]());
897 if(promises.size() == 2)
898 return U(promises[0](), promises[1]());
899 throw error(error::ARGCOUNT, "Operation takes 1 or 2 arguments");
901 static expr_val bnot(expr_val a)
903 return ~a.as_numeric();
905 static expr_val band(expr_val a, expr_val b)
907 return a.as_numeric() & b.as_numeric();
909 static expr_val bor(expr_val a, expr_val b)
911 return a.as_numeric() | b.as_numeric();
913 static expr_val bxor(expr_val a, expr_val b)
915 return a.as_numeric() ^ b.as_numeric();
917 static expr_val neg(expr_val a)
919 return -a.as_numeric();
921 template<expr_val_numeric (expr_val_numeric::*T)() const>
922 static expr_val f_n_fn(expr_val a)
924 return (a.as_numeric().*T)();
926 template<expr_val_numeric (*T)(expr_val_numeric x, expr_val_numeric y)>
927 static expr_val f_n_fn2(expr_val a, expr_val b)
929 return T(a.as_numeric(), b.as_numeric());
931 static expr_val lshift(expr_val a, expr_val b)
933 return expr_val_numeric::shift(a.as_numeric(), b.as_numeric(), false);
935 static expr_val rshift(expr_val a, expr_val b)
937 return expr_val_numeric::shift(a.as_numeric(), b.as_numeric(), true);
939 static expr_val op_pi(std::vector<std::function<expr_val&()>> promises)
941 return expr_val_numeric::op_pi();
943 static expr_val add(expr_val a, expr_val b)
945 if(a.type == T_STRING && b.type == T_STRING)
946 return expr_val(string_tag(), a.v_string + b.v_string);
947 return a.as_numeric() + b.as_numeric();
949 static expr_val sub(expr_val a, expr_val b)
951 return a.as_numeric() - b.as_numeric();
953 static expr_val mul(expr_val a, expr_val b)
955 return a.as_numeric() * b.as_numeric();
957 static expr_val div(expr_val a, expr_val b)
959 return a.as_numeric() / b.as_numeric();
961 static expr_val rem(expr_val a, expr_val b)
963 return a.as_numeric() % b.as_numeric();
965 static bool _eq(const expr_val& a, const expr_val& b)
967 if(a.type != b.type)
968 return false;
969 switch(a.type) {
970 case T_BOOLEAN: return (a.v_boolean == b.v_boolean);
971 case T_STRING: return (a.v_string == b.v_string);
972 case T_NUMERIC: return (a.v_numeric == b.v_numeric);
974 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
976 static expr_val eq(expr_val a, expr_val b)
978 return expr_val(boolean_tag(), _eq(a, b));
980 static expr_val ne(expr_val a, expr_val b)
982 return expr_val(boolean_tag(), !_eq(a, b));
984 static int _cmp(expr_val a, expr_val b)
986 if(a.type != b.type)
987 throw_domain("Can't compare distinct value types");
988 switch(a.type) {
989 case T_BOOLEAN: return _cmp_values(a.v_boolean, b.v_boolean);
990 case T_STRING: return _cmp_values(a.v_string, b.v_string);
991 case T_NUMERIC: return expr_val_numeric::_cmp(a.v_numeric, b.v_numeric);
993 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
995 template<expr_val_numeric(*T)(expr_val_numeric v)>
996 static expr_val x_nconv(expr_val a)
998 return T(a.as_numeric());
1000 static expr_val lt(expr_val a, expr_val b)
1002 return expr_val(boolean_tag(), _cmp(a, b) < 0);
1004 static expr_val le(expr_val a, expr_val b)
1006 return expr_val(boolean_tag(), _cmp(a, b) <= 0);
1008 static expr_val ge(expr_val a, expr_val b)
1010 return expr_val(boolean_tag(), _cmp(a, b) >= 0);
1012 static expr_val gt(expr_val a, expr_val b)
1014 return expr_val(boolean_tag(), _cmp(a, b) > 0);
1016 std::string format_string(std::string val, _format fmt)
1018 if((int)val.length() > fmt.precision && fmt.precision >= 0)
1019 val = val.substr(0, fmt.precision);
1020 while((int)val.length() < fmt.width)
1021 val = " " + val;
1022 return val;
1024 std::string print_bool_numeric(bool val, _format fmt)
1026 std::string out = val ? "1" : "0";
1027 if(fmt.precision > 0) {
1028 out += ".";
1029 for(int i = 0; i < fmt.precision; i++)
1030 out += "0";
1032 while((int)out.length() < fmt.width)
1033 out = ((fmt.fillzeros) ? "0" : " ") + out;
1034 return out;
1036 std::string format(_format fmt)
1038 switch(type) {
1039 case T_BOOLEAN: return format_bool(v_boolean, fmt);
1040 case T_NUMERIC: return v_numeric.format(fmt);
1041 case T_STRING: return format_string(v_string, fmt);
1042 default:
1043 return "#Notprintable";
1046 static std::set<operinfo*> operations()
1048 static operinfo_set<expr_val> x({
1049 {"-", expr_val::op_unary<expr_val::neg>, true, 1, -3, true},
1050 {"!", expr_val::op_lnot, true, 1, -3, true},
1051 {"~", expr_val::op_unary<expr_val::bnot>, true, 1, -3, true},
1052 {"*", expr_val::op_binary<expr_val::mul>, true, 2, -5, false},
1053 {"/", expr_val::op_binary<expr_val::div>, true, 2, -5, false},
1054 {"%", expr_val::op_binary<expr_val::rem>, true, 2, -5, false},
1055 {"+", expr_val::op_binary<expr_val::add>, true, 2, -6, false},
1056 {"-", expr_val::op_binary<expr_val::sub>, true, 2, -6, false},
1057 {"<<", expr_val::op_binary<expr_val::lshift>, true, 2, -7, false},
1058 {">>", expr_val::op_binary<expr_val::rshift>, true, 2, -7, false},
1059 {"<", expr_val::op_binary<expr_val::lt>, true, 2, -8, false},
1060 {"<=", expr_val::op_binary<expr_val::le>, true, 2, -8, false},
1061 {">", expr_val::op_binary<expr_val::gt>, true, 2, -8, false},
1062 {">=", expr_val::op_binary<expr_val::ge>, true, 2, -8, false},
1063 {"==", expr_val::op_binary<expr_val::eq>, true, 2, -9, false},
1064 {"!=", expr_val::op_binary<expr_val::ne>, true, 2, -9, false},
1065 {"&", expr_val::op_binary<expr_val::band>, true, 2, -10, false},
1066 {"^", expr_val::op_binary<expr_val::bxor>, true, 2, -11, false},
1067 {"|", expr_val::op_binary<expr_val::bor>, true, 2, -12, false},
1068 {"&&", expr_val::op_land, true, 2, -13, false},
1069 {"||", expr_val::op_lor, true, 2, -14, false},
1070 {"π", expr_val::op_pi, true, 0, 0, false},
1071 {"if", expr_val::fun_if},
1072 {"select", expr_val::fun_select},
1073 {"unsigned", expr_val::op_unary<expr_val::x_nconv<expr_val_numeric::x_unsigned>>},
1074 {"signed", expr_val::op_unary<expr_val::x_nconv<expr_val_numeric::x_signed>>},
1075 {"float", expr_val::op_unary<expr_val::x_nconv<expr_val_numeric::x_float>>},
1076 {"min", expr_val::fun_fold<expr_val::fold_min>},
1077 {"max", expr_val::fun_fold<expr_val::fold_max>},
1078 {"sum", expr_val::fun_fold<expr_val::fold_sum>},
1079 {"prod", expr_val::fun_fold<expr_val::fold_prod>},
1080 {"sqrt", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::sqrt>>},
1081 {"log", expr_val::op_unary_binary<expr_val::f_n_fn<&expr_val_numeric::log>,
1082 expr_val::f_n_fn2<expr_val_numeric::log2>>},
1083 {"exp", expr_val::op_unary_binary<expr_val::f_n_fn<&expr_val_numeric::exp>,
1084 expr_val::f_n_fn2<expr_val_numeric::exp2>>},
1085 {"sin", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::sin>>},
1086 {"cos", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::cos>>},
1087 {"tan", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::tan>>},
1088 {"atan", expr_val::op_unary_binary<expr_val::f_n_fn<&expr_val_numeric::atan>,
1089 expr_val::f_n_fn2<expr_val_numeric::atan2>>},
1090 {"asin", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::asin>>},
1091 {"acos", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::acos>>},
1092 {"sinh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::sinh>>},
1093 {"cosh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::cosh>>},
1094 {"tanh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::tanh>>},
1095 {"artanh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::artanh>>},
1096 {"arsinh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::arsinh>>},
1097 {"arcosh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::arcosh>>},
1098 {"torad", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::torad>>},
1099 {"todeg", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::todeg>>},
1100 {"re", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::re>>},
1101 {"im", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::im>>},
1102 {"conj", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::conj>>},
1103 {"abs", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::abs>>},
1104 {"arg", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::arg>>},
1105 {"pyth", expr_val::fun_pyth},
1107 return x.get_set();
1109 private:
1110 _type type;
1111 bool v_boolean;
1112 expr_val_numeric v_numeric;
1113 std::string v_string;
1117 struct typeinfo* expression_value()
1119 static typeinfo_wrapper<expr_val> expession_value_obj;
1120 return &expession_value_obj;