Fix some compilation errors on Mac OS X
[lsnes.git] / src / library / mathexpr-ntype.cpp
blob80f19d2471c0dab93effabd3c92d45b41a9ef92d
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 mathexpr
10 namespace
12 void throw_domain(const std::string& err)
14 throw error(error::WDOMAIN, err);
17 template<typename T> int _cmp_values(T a, T b)
19 if(a < b)
20 return -1;
21 if(a > b)
22 return 1;
23 return 0;
26 class expr_val;
28 class expr_val_numeric
30 enum _type
32 T_UNSIGNED,
33 T_SIGNED,
34 T_FLOAT,
35 T_COMPLEX,
37 public:
38 struct unsigned_tag {};
39 struct signed_tag {};
40 struct float_tag {};
41 struct complex_tag {};
42 expr_val_numeric()
44 type = T_SIGNED;
45 v_signed = 0;
46 v_imag = 0;
48 expr_val_numeric(unsigned_tag, uint64_t v)
50 type = T_UNSIGNED;
51 v_unsigned = v;
52 v_imag = 0;
54 expr_val_numeric(signed_tag, int64_t v)
56 type = T_SIGNED;
57 v_signed = v;
58 v_imag = 0;
60 expr_val_numeric(float_tag, double v)
62 type = T_FLOAT;
63 v_float = v;
64 v_imag = 0;
66 expr_val_numeric(complex_tag, double re, double im)
68 type = T_COMPLEX;
69 v_float = re;
70 v_imag = im;
72 expr_val_numeric(const std::string& str)
74 if(str == "i") {
75 type = T_COMPLEX;
76 v_float = 0;
77 v_imag = 1;
78 } else if(regex("[0-9]+|0x[0-9a-fA-F]+", str)) {
79 //UNSIGNED.
80 v_unsigned = parse_value<uint64_t>(str);
81 v_imag = 0;
82 type = T_UNSIGNED;
83 } else if(regex("[+-][0-9]+|[+-]0x[0-9a-fA-F]+", str)) {
84 //SIGNED.
85 v_signed = parse_value<int64_t>(str);
86 v_imag = 0;
87 type = T_SIGNED;
88 } else if(regex("[+-]?([0-9]+|[0-9]*\\.[0-9]+)([eE][0-9]+)?", str)) {
89 //FLOAT.
90 v_float = parse_value<double>(str);
91 v_imag = 0;
92 type = T_FLOAT;
93 } else
94 throw std::runtime_error("Bad number '" + str + "'");
96 double as_float() const
98 switch(type) {
99 case T_UNSIGNED: return v_unsigned;
100 case T_SIGNED: return v_signed;
101 case T_FLOAT: return v_float;
102 case T_COMPLEX: return v_float;
104 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
106 int64_t as_signed() const
108 switch(type) {
109 case T_UNSIGNED: return v_unsigned;
110 case T_SIGNED: return v_signed;
111 case T_FLOAT: return v_float;
112 case T_COMPLEX: return v_float;
114 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
116 uint64_t as_unsigned() const
118 switch(type) {
119 case T_UNSIGNED: return v_unsigned;
120 case T_SIGNED: return v_signed;
121 case T_FLOAT: return v_float;
122 case T_COMPLEX: return v_float;
124 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
126 std::string tostring()
128 switch(type) {
129 case T_UNSIGNED:
130 return (stringfmt() << v_unsigned).str();
131 case T_SIGNED:
132 return (stringfmt() << v_signed).str();
133 case T_FLOAT:
134 //FIXME: Saner formatting.
135 return (stringfmt() << v_float).str();
136 case T_COMPLEX:
137 //FIXME: Saner formatting.
138 if(v_imag < 0)
139 return (stringfmt() << v_float << v_imag << "*i").str();
140 if(v_imag > 0)
141 return (stringfmt() << v_float << "+" << v_imag << "*i").str();
142 return (stringfmt() << v_float).str();
144 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
146 uint64_t tounsigned()
148 return as_unsigned();
150 int64_t tosigned()
152 return as_signed();
154 void scale(uint64_t scale)
156 switch(type) {
157 case T_UNSIGNED:
158 type = T_FLOAT;
159 v_float = (1.0 * v_unsigned / scale);
160 break;
161 case T_SIGNED:
162 type = T_FLOAT;
163 v_float = (1.0 * v_signed / scale);
164 break;
165 case T_COMPLEX:
166 v_imag /= scale;
167 case T_FLOAT:
168 v_float /= scale;
169 break;
172 bool toboolean()
174 switch(type) {
175 case T_UNSIGNED: return (v_unsigned != 0);
176 case T_SIGNED: return (v_signed != 0);
177 case T_FLOAT: return (v_float != 0);
178 case T_COMPLEX: return (v_float != 0) || (v_imag != 0);
180 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
182 std::string format(_format fmt)
184 switch(type) {
185 case T_UNSIGNED: return format_unsigned(v_unsigned, fmt);
186 case T_SIGNED: return format_signed(v_signed, fmt);
187 case T_FLOAT: return format_float(v_float, fmt);
188 case T_COMPLEX: return format_complex(v_float, v_imag, fmt);
190 throw error(error::INTERNAL, "Don't know how to print numeric type");
192 expr_val_numeric operator~() const
194 switch(type) {
195 case T_UNSIGNED: return expr_val_numeric(unsigned_tag(), ~v_unsigned);
196 case T_SIGNED: return expr_val_numeric(signed_tag(), ~v_signed);
197 case T_FLOAT: throw_domain("Bit operations are only for integers");
198 case T_COMPLEX: throw_domain("Bit operations are only for integers");
200 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
202 expr_val_numeric operator&(const expr_val_numeric& b) const
204 if(type == T_COMPLEX || b.type == T_COMPLEX)
205 throw_domain("Bit operations are only for integers");
206 if(type == T_FLOAT || b.type == T_FLOAT)
207 throw_domain("Bit operations are only for integers");
208 if(type == T_SIGNED || b.type == T_SIGNED)
209 return expr_val_numeric(signed_tag(), as_signed() & b.as_signed());
210 return expr_val_numeric(unsigned_tag(), as_unsigned() & b.as_unsigned());
212 expr_val_numeric operator|(const expr_val_numeric& b) const
214 if(type == T_COMPLEX || b.type == T_COMPLEX)
215 throw_domain("Bit operations are only for integers");
216 if(type == T_FLOAT || b.type == T_FLOAT)
217 throw_domain("Bit operations are only for integers");
218 if(type == T_SIGNED || b.type == T_SIGNED)
219 return expr_val_numeric(signed_tag(), as_signed() | b.as_signed());
220 return expr_val_numeric(unsigned_tag(), as_unsigned() | b.as_unsigned());
222 expr_val_numeric operator^(const expr_val_numeric& b) const
224 if(type == T_COMPLEX || b.type == T_COMPLEX)
225 throw_domain("Bit operations are only for integers");
226 if(type == T_FLOAT || b.type == T_FLOAT)
227 throw_domain("Bit operations are only for integers");
228 if(type == T_SIGNED || b.type == T_SIGNED)
229 return expr_val_numeric(signed_tag(), as_signed() ^ b.as_signed());
230 return expr_val_numeric(unsigned_tag(), as_unsigned() ^ b.as_unsigned());
232 expr_val_numeric operator-() const
234 switch(type) {
235 case T_COMPLEX: return expr_val_numeric(complex_tag(), -v_float, -v_imag);
236 case T_UNSIGNED: return expr_val_numeric(signed_tag(), -(int64_t)v_unsigned);
237 case T_SIGNED: return expr_val_numeric(signed_tag(), -v_signed);
238 case T_FLOAT: return expr_val_numeric(float_tag(), -v_float);
240 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
242 expr_val_numeric operator+(const expr_val_numeric& b) const
244 if(type == T_COMPLEX || b.type == T_COMPLEX)
245 return expr_val_numeric(complex_tag(), as_float() + b.as_float(),
246 v_imag + b.v_imag);
247 if(type == T_FLOAT || b.type == T_FLOAT)
248 return expr_val_numeric(float_tag(), as_float() + b.as_float());
249 if(type == T_SIGNED || b.type == T_SIGNED)
250 return expr_val_numeric(signed_tag(), as_signed() + b.as_signed());
251 return expr_val_numeric(unsigned_tag(), as_unsigned() + b.as_unsigned());
253 expr_val_numeric operator-(const expr_val_numeric& b) const
255 if(type == T_COMPLEX || b.type == T_COMPLEX)
256 return expr_val_numeric(complex_tag(), as_float() - b.as_float(),
257 v_imag - b.v_imag);
258 if(type == T_FLOAT || b.type == T_FLOAT)
259 return expr_val_numeric(float_tag(), as_float() - b.as_float());
260 if(type == T_SIGNED || b.type == T_SIGNED)
261 return expr_val_numeric(signed_tag(), as_signed() - b.as_signed());
262 return expr_val_numeric(unsigned_tag(), as_unsigned() - b.as_unsigned());
264 expr_val_numeric operator*(const expr_val_numeric& b) const
266 if(type == T_COMPLEX || b.type == T_COMPLEX)
267 return expr_val_numeric(complex_tag(), as_float() * b.as_float() - v_imag * b.v_imag,
268 as_float() * b.v_imag + b.as_float() * v_imag);
269 if(type == T_FLOAT || b.type == T_FLOAT)
270 return expr_val_numeric(float_tag(), as_float() * b.as_float());
271 if(type == T_SIGNED || b.type == T_SIGNED)
272 return expr_val_numeric(signed_tag(), as_signed() * b.as_signed());
273 return expr_val_numeric(unsigned_tag(), as_unsigned() * b.as_unsigned());
275 expr_val_numeric operator/(const expr_val_numeric& b) const
277 if(type == T_COMPLEX || b.type == T_COMPLEX) {
278 double div = b.as_float() * b.as_float() + b.v_imag * b.v_imag;
279 if(div == 0)
280 throw error(error::DIV_BY_0, "Division by 0");
281 return expr_val_numeric(complex_tag(),
282 (as_float() * b.as_float() + v_imag * b.v_imag) / div,
283 (v_imag * b.as_float() - as_float() * b.v_imag) / div);
285 if(type == T_FLOAT || b.type == T_FLOAT) {
286 if(b.as_float() == 0)
287 throw error(error::DIV_BY_0, "Division by 0");
288 return expr_val_numeric(float_tag(), as_float() / b.as_float());
290 if(type == T_SIGNED || b.type == T_SIGNED) {
291 if(b.as_signed() == 0)
292 throw error(error::DIV_BY_0, "Division by 0");
293 return expr_val_numeric(signed_tag(), as_signed() / b.as_signed());
295 if(b.as_unsigned() == 0)
296 throw error(error::DIV_BY_0, "Division by 0");
297 return expr_val_numeric(unsigned_tag(), as_unsigned() / b.as_unsigned());
299 expr_val_numeric operator%(const expr_val_numeric& b) const
301 if(type == T_COMPLEX || b.type == T_COMPLEX)
302 throw_domain("Remainder is only for integers");
303 if(type == T_FLOAT || b.type == T_FLOAT)
304 throw_domain("Remainder is only for integers");
305 if(type == T_SIGNED || b.type == T_SIGNED) {
306 if(b.as_signed() == 0)
307 throw error(error::DIV_BY_0, "Division by 0");
308 return expr_val_numeric(signed_tag(), as_signed() / b.as_signed());
310 if(b.as_unsigned() == 0)
311 throw error(error::DIV_BY_0, "Division by 0");
312 return expr_val_numeric(unsigned_tag(), as_unsigned() / b.as_unsigned());
314 expr_val_numeric log() const
316 if(type == T_COMPLEX) {
317 double mag = as_float() * as_float() + v_imag * v_imag;
318 if(mag == 0)
319 throw error(error::LOG_BY_0, "Can't take logarithm of 0");
320 double r = 0.5 * ::log(mag);
321 double i = ::atan2(v_imag, as_float());
322 return expr_val_numeric(complex_tag(), r, i);
324 if(as_float() == 0)
325 throw error(error::LOG_BY_0, "Can't take logarithm of 0");
326 if(as_float() <= 0)
327 return expr_val_numeric(complex_tag(), ::log(std::abs(as_float())), 4 * ::atan(1));
328 return expr_val_numeric(float_tag(), ::log(as_float()));
330 static expr_val_numeric log2(expr_val_numeric a, expr_val_numeric b)
332 return b.log() / a.log();
334 expr_val_numeric exp() const
336 if(type == T_COMPLEX) {
337 double mag = ::exp(as_float());
338 return expr_val_numeric(complex_tag(), mag * ::cos(v_imag),
339 mag * ::sin(v_imag));
341 return expr_val_numeric(float_tag(), ::exp(as_float()));
343 static expr_val_numeric exp2(expr_val_numeric a, expr_val_numeric b)
345 expr_val_numeric tmp = b * a.log();
346 return tmp.exp();
348 expr_val_numeric sqrt() const
350 if(as_float() < 0 && type != T_COMPLEX)
351 return expr_val_numeric(complex_tag(), 0, ::sqrt(-as_float()));
352 if(type == T_COMPLEX) {
353 double mag = ::sqrt(::sqrt(as_float() * as_float() + v_imag * v_imag));
354 double ar = 0.5 * ::atan2(v_imag, as_float());
355 return expr_val_numeric(complex_tag(), mag * ::cos(ar), mag * ::sin(ar));
357 return expr_val_numeric(float_tag(), ::sqrt(as_float()));
359 expr_val_numeric sin() const
361 if(type == T_COMPLEX) {
362 return expr_val_numeric(complex_tag(), ::sin(as_float()) * ::cosh(v_imag),
363 ::cos(as_float()) * ::sinh(v_imag));
365 return expr_val_numeric(float_tag(), ::sin(as_float()));
367 expr_val_numeric cos() const
369 if(type == T_COMPLEX) {
370 return expr_val_numeric(complex_tag(), ::cos(as_float()) * ::cosh(v_imag),
371 -::sin(as_float()) * ::sinh(v_imag));
373 return expr_val_numeric(float_tag(), ::cos(as_float()));
375 expr_val_numeric tan() const
377 return sin()/cos();
379 expr_val_numeric atan() const
381 if(type == T_COMPLEX) {
382 expr_val_numeric x = expr_val_numeric(complex_tag(), 0, 1) * *this;
383 expr_val_numeric n = expr_val_numeric(complex_tag(), 1, 0) + x;
384 expr_val_numeric d = expr_val_numeric(complex_tag(), 1, 0) - x;
385 expr_val_numeric y = n / d;
386 expr_val_numeric w = y.log();
387 return w / expr_val_numeric(complex_tag(), 0, 2);
389 return expr_val_numeric(float_tag(), ::atan(as_float()));
391 expr_val_numeric acos() const
393 expr_val_numeric sinesqr = (expr_val_numeric(float_tag(), 1) - *this * *this);
394 expr_val_numeric sine = sinesqr.sqrt();
395 expr_val_numeric tangent = sine / *this;
396 return tangent.atan();
398 expr_val_numeric asin() const
400 expr_val_numeric cosinesqr = (expr_val_numeric(float_tag(), 1) - *this * *this);
401 expr_val_numeric cosine = cosinesqr.sqrt();
402 expr_val_numeric tangent = *this / cosine;
403 return tangent.atan();
405 expr_val_numeric sinh() const
407 return (exp() - (-*this).exp()) / expr_val_numeric(float_tag(), 2);
409 expr_val_numeric cosh() const
411 return (exp() + (-*this).exp()) / expr_val_numeric(float_tag(), 2);
413 expr_val_numeric tanh() const
415 return sinh() / cosh();
417 expr_val_numeric arsinh() const
419 //x - 1/x = 2u
420 //x^2 - 2ux - 1 = 0
421 //(x-u)^2 - x^2 + 2ux - u^2 + x^2 - 2ux - 1 = 0
422 //(x-u)^2 = u^2 + 1
423 expr_val_numeric xmu = (*this * *this) + expr_val_numeric(float_tag(), 1);
424 expr_val_numeric x = xmu.sqrt() + *this;
425 return x.log();
427 expr_val_numeric arcosh() const
429 expr_val_numeric xmu = (*this * *this) - expr_val_numeric(float_tag(), 1);
430 expr_val_numeric x = xmu.sqrt() + *this;
431 return x.log();
433 expr_val_numeric artanh() const
435 //(x-1/x)/(x+1/x)=u
436 //x^2=u+1/(1-u)
437 expr_val_numeric t(float_tag(), 1);
438 return ((t + *this) / (t - *this)).sqrt().log();
440 static expr_val_numeric atan2(expr_val_numeric a, expr_val_numeric b)
442 if(a.type == T_COMPLEX || b.type == T_COMPLEX)
443 throw_domain("atan2 is only for reals");
444 return expr_val_numeric(float_tag(), ::atan2(a.as_float(), b.as_float()));
446 expr_val_numeric torad() const
448 return expr_val_numeric(float_tag(), ::atan(1) / 45 * as_float());
450 expr_val_numeric todeg() const
452 return expr_val_numeric(float_tag(), 45 / ::atan(1) * as_float());
454 static expr_val_numeric shift(expr_val_numeric a, expr_val_numeric b, bool inv)
456 int64_t s = b.as_signed();
457 if(inv)
458 s = -s;
459 if(a.type == T_SIGNED) {
460 int64_t _a = a.v_signed;
461 if(s < -63)
462 return expr_val_numeric(signed_tag(), -1);
463 if(s > 63)
464 return expr_val_numeric(signed_tag(), 0);
465 if(s < 0) {
466 uint64_t r = _a;
467 uint64_t r2 = r >> -s;
468 uint64_t m = 0xFFFFFFFFFFFFFFFFULL - ((1ULL << (64 - s)) - 1);
469 return expr_val_numeric(signed_tag(), m | r2);
470 } else if(s > 0)
471 return expr_val_numeric(signed_tag(), _a << s);
472 else
473 return expr_val_numeric(signed_tag(), _a);
474 } else if(a.type == T_UNSIGNED) {
475 uint64_t _a = a.v_unsigned;
476 if(s < -63 || s > 63)
477 return expr_val_numeric(unsigned_tag(), 0);
478 if(s < 0)
479 return expr_val_numeric(unsigned_tag(), _a >> -s);
480 else if(s > 0)
481 return expr_val_numeric(unsigned_tag(), _a << s);
482 else
483 return expr_val_numeric(unsigned_tag(), _a);
484 } else
485 throw_domain("Bit operations are only for integers");
486 return expr_val_numeric(unsigned_tag(), 0); //NOTREACHED
488 static expr_val_numeric op_pi()
490 return expr_val_numeric(float_tag(), 4 * ::atan(1));
492 static expr_val_numeric op_e()
494 return expr_val_numeric(float_tag(), ::exp(1));
496 bool operator==(const expr_val_numeric& b) const
498 if(type == T_COMPLEX || b.type == T_COMPLEX)
499 return as_float() == b.as_float() && v_imag == b.v_imag;
500 return (_cmp(*this, b) == 0);
502 static int _cmp_float_unsigned(uint64_t a, float b)
504 if(b < 0)
505 return 1;
506 //TODO: Handle values too large for exact integer representation.
507 if((double)a < b)
508 return -1;
509 if((double)a > b)
510 return 1;
511 return 0;
513 static int _cmp_float_signed(int64_t a, float b)
515 //TODO: Handle values too large for exact integer representation.
516 if((double)a < b)
517 return -1;
518 if((double)a > b)
519 return 1;
520 return 0;
522 static int _cmp(expr_val_numeric a, expr_val_numeric b)
524 if(a.type == T_COMPLEX || b.type == T_COMPLEX)
525 throw_domain("Can't compare complex numbers");
526 switch(a.type) {
527 case T_UNSIGNED:
528 switch(b.type) {
529 case T_UNSIGNED:
530 return _cmp_values(a.v_unsigned, b.v_unsigned);
531 case T_SIGNED:
532 if(b.v_signed < 0)
533 return 1;
534 if((int64_t)a.v_unsigned < 0)
535 return 1;
536 return _cmp_values((int64_t)a.v_unsigned, b.v_signed);
537 case T_FLOAT:
538 return _cmp_float_unsigned(a.v_unsigned, b.v_float);
539 case T_COMPLEX:
540 throw error(error::INTERNAL,
541 "Internal error (shouldn't be here)");
543 case T_SIGNED:
544 switch(b.type) {
545 case T_UNSIGNED:
546 if(a.v_signed < 0)
547 return -1;
548 if((int64_t)b.v_unsigned < 0)
549 return -1;
550 return _cmp_values(a.v_signed, (int64_t)b.v_unsigned);
551 case T_SIGNED:
552 return _cmp_values(a.v_signed, b.v_signed);
553 case T_FLOAT:
554 return _cmp_float_signed(a.v_signed, b.v_float);
555 case T_COMPLEX:
556 throw error(error::INTERNAL,
557 "Internal error (shouldn't be here)");
559 case T_FLOAT:
560 switch(b.type) {
561 case T_UNSIGNED:
562 return -_cmp_float_unsigned(b.v_unsigned, a.v_float);
563 case T_SIGNED:
564 return -_cmp_float_signed(b.v_signed, a.v_float);
565 case T_FLOAT:
566 if(a.v_float < b.v_float)
567 return -1;
568 if(a.v_float > b.v_float)
569 return 1;
570 return 0;
571 case T_COMPLEX:
572 throw error(error::INTERNAL,
573 "Internal error (shouldn't be here)");
575 case T_COMPLEX:
576 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
578 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
580 static expr_val_numeric x_unsigned(expr_val_numeric a)
582 switch(a.type) {
583 case T_UNSIGNED: return expr_val_numeric(unsigned_tag(), a.v_unsigned);
584 case T_SIGNED: return expr_val_numeric(unsigned_tag(), a.v_signed);
585 case T_FLOAT: return expr_val_numeric(unsigned_tag(), a.v_float);
586 default: throw_domain("Can't convert non-real into unsigned");
588 return expr_val_numeric(unsigned_tag(), 0); //NOTREACHED.
590 static expr_val_numeric x_signed(expr_val_numeric a)
592 switch(a.type) {
593 case T_UNSIGNED: return expr_val_numeric(signed_tag(), a.v_unsigned);
594 case T_SIGNED: return expr_val_numeric(signed_tag(), a.v_signed);
595 case T_FLOAT: return expr_val_numeric(signed_tag(), a.v_float);
596 default: throw_domain("Can't convert non-real into signed");
598 return expr_val_numeric(signed_tag(), 0); //NOTREACHED.
600 static expr_val_numeric x_float(expr_val_numeric a)
602 switch(a.type) {
603 case T_UNSIGNED: return expr_val_numeric(float_tag(), a.v_unsigned);
604 case T_SIGNED: return expr_val_numeric(float_tag(), a.v_signed);
605 case T_FLOAT: return expr_val_numeric(float_tag(), a.v_float);
606 default: throw_domain("Can't convert non-real into float");
608 return expr_val_numeric(float_tag(), 0); //NOTREACHED.
610 expr_val_numeric re() const
612 if(type == T_COMPLEX)
613 return expr_val_numeric(float_tag(), v_float);
614 return expr_val_numeric(float_tag(), as_float());
616 expr_val_numeric im() const
618 if(type == T_COMPLEX)
619 return expr_val_numeric(float_tag(), v_imag);
620 return expr_val_numeric(float_tag(), 0);
622 expr_val_numeric conj() const
624 if(type == T_COMPLEX)
625 return expr_val_numeric(complex_tag(), v_float, -v_imag);
626 return expr_val_numeric(float_tag(), as_float());
628 expr_val_numeric abs() const
630 switch(type) {
631 case T_COMPLEX: return expr_val_numeric(float_tag(), v_float * v_float + v_imag * v_imag);
632 case T_FLOAT: return expr_val_numeric(float_tag(), ::fabs(v_float));
633 case T_SIGNED: return expr_val_numeric(signed_tag(), ::abs(v_signed));
634 case T_UNSIGNED: return expr_val_numeric(unsigned_tag(), v_unsigned);
636 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
638 expr_val_numeric arg() const
640 switch(type) {
641 case T_COMPLEX: return expr_val_numeric(float_tag(), ::atan2(v_imag, v_float));
642 default:
643 if(as_float() < 0)
644 return expr_val_numeric(float_tag(), 4 * ::atan(1));
645 else
646 return expr_val_numeric(float_tag(), 0);
649 private:
650 enum _type type;
651 union {
652 uint64_t v_unsigned;
653 int64_t v_signed;
654 double v_float;
656 double v_imag;
659 class expr_val
661 struct number_tag {};
662 struct string_tag {};
663 struct boolean_tag {};
664 enum _type
666 T_BOOLEAN,
667 T_NUMERIC,
668 T_STRING,
670 expr_val_numeric& as_numeric()
672 if(type != T_NUMERIC)
673 throw_domain("Can't operate with non-numbers");
674 return v_numeric;
676 public:
677 expr_val()
679 type = T_NUMERIC;
681 expr_val(const std::string& str, bool string)
683 if(string) {
684 v_string = str;
685 type = T_STRING;
686 } else if(str == "false") {
687 v_boolean = false;
688 type = T_BOOLEAN;
689 } else if(str == "true") {
690 v_boolean = true;
691 type = T_BOOLEAN;
692 } else if(str == "e") {
693 v_numeric = expr_val_numeric::op_e();
694 type = T_NUMERIC;
695 } else if(str == "pi") {
696 v_numeric = expr_val_numeric::op_pi();
697 type = T_NUMERIC;
698 } else {
699 v_numeric = expr_val_numeric(str);
700 type = T_NUMERIC;
703 expr_val(typeinfo_wrapper<expr_val>::unsigned_tag t, uint64_t v)
704 : type(T_NUMERIC), v_numeric(expr_val_numeric::unsigned_tag(), v)
707 expr_val(typeinfo_wrapper<expr_val>::signed_tag t, int64_t v)
708 : type(T_NUMERIC), v_numeric(expr_val_numeric::signed_tag(), v)
711 expr_val(typeinfo_wrapper<expr_val>::float_tag t, double v)
712 : type(T_NUMERIC), v_numeric(expr_val_numeric::float_tag(), v)
715 expr_val(typeinfo_wrapper<expr_val>::boolean_tag, bool b)
716 : type(T_BOOLEAN), v_boolean(b)
719 expr_val(expr_val_numeric v)
720 : type(T_NUMERIC), v_numeric(v)
723 expr_val(string_tag, std::string s)
724 : type(T_STRING), v_string(s)
727 expr_val(boolean_tag, bool b)
728 : type(T_BOOLEAN), v_boolean(b)
731 std::string tostring()
733 switch(type) {
734 case T_BOOLEAN:
735 if(v_boolean)
736 return "true";
737 else
738 return "false";
739 case T_NUMERIC:
740 return v_numeric.tostring();
741 case T_STRING:
742 return v_string;
744 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
746 uint64_t tounsigned()
748 if(type != T_NUMERIC)
749 throw_domain("Can't convert non-number into unsigned");
750 return v_numeric.tounsigned();
752 int64_t tosigned()
754 if(type != T_NUMERIC)
755 throw_domain("Can't convert non-number into signed");
756 return v_numeric.tosigned();
758 void scale(uint64_t _scale)
760 if(type != T_NUMERIC)
761 throw_domain("Can't scale non-number");
762 v_numeric.scale(_scale);
764 bool toboolean()
766 switch(type) {
767 case T_BOOLEAN:
768 return v_boolean;
769 case T_NUMERIC:
770 return v_numeric.toboolean();
771 case T_STRING:
772 return (v_string.length() != 0);
774 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
776 static expr_val op_lnot(std::vector<std::function<expr_val&()>> promises)
778 if(promises.size() != 1)
779 throw error(error::ARGCOUNT, "logical not takes 1 argument");
780 return expr_val(boolean_tag(), !(promises[0]().toboolean()));
782 static expr_val op_lor(std::vector<std::function<expr_val&()>> promises)
784 if(promises.size() != 2)
785 throw error(error::ARGCOUNT, "logical or takes 2 arguments");
786 if(promises[0]().toboolean())
787 return expr_val(boolean_tag(), true);
788 return expr_val(boolean_tag(), promises[1]().toboolean());
790 static expr_val op_land(std::vector<std::function<expr_val&()>> promises)
792 if(promises.size() != 2)
793 throw error(error::ARGCOUNT, "logical and takes 2 arguments");
794 if(!(promises[0]().toboolean()))
795 return expr_val(boolean_tag(), false);
796 return expr_val(boolean_tag(), promises[1]().toboolean());
798 static expr_val fun_if(std::vector<std::function<expr_val&()>> promises)
800 if(promises.size() == 2) {
801 if((promises[0]().toboolean()))
802 return promises[1]();
803 else
804 return expr_val(boolean_tag(), false);
805 } else if(promises.size() == 3) {
806 if((promises[0]().toboolean()))
807 return promises[1]();
808 else
809 return promises[2]();
810 } else
811 throw error(error::ARGCOUNT, "if takes 2 or 3 arguments");
813 static expr_val fun_select(std::vector<std::function<expr_val&()>> promises)
815 for(auto& i : promises) {
816 expr_val v = i();
817 if(v.type != T_BOOLEAN || v.v_boolean)
818 return v;
820 return expr_val(boolean_tag(), false);
822 static expr_val fun_pyth(std::vector<std::function<expr_val&()>> promises)
824 std::vector<expr_val> v;
825 for(auto& i : promises)
826 v.push_back(i());
827 expr_val_numeric n(expr_val_numeric::float_tag(), 0);
828 expr_val_numeric one(expr_val_numeric::float_tag(), 1);
829 for(auto& i : v) {
830 if(i.type != T_NUMERIC)
831 throw error(error::WDOMAIN, "pyth requires numeric args");
832 n = n + one * i.v_numeric * i.v_numeric;
834 return n.sqrt();
836 template<expr_val (*T)(expr_val& a, expr_val& b)>
837 static expr_val fun_fold(std::vector<std::function<expr_val&()>> promises)
839 if(!promises.size())
840 return expr_val(boolean_tag(), false);
841 expr_val v = promises[0]();
842 for(size_t i = 1; i < promises.size(); i++)
843 v = T(v, promises[i]());
844 return v;
846 static expr_val fold_min(expr_val& a, expr_val& b)
848 int t = _cmp_values(a.type, b.type);
849 if(t < 0)
850 return a;
851 if(t > 0)
852 return b;
853 return (_cmp(a, b) < 0) ? a : b;
855 static expr_val fold_max(expr_val& a, expr_val& b)
857 int t = _cmp_values(a.type, b.type);
858 if(t < 0)
859 return a;
860 if(t > 0)
861 return b;
862 return (_cmp(a, b) > 0) ? a : b;
864 static expr_val fold_sum(expr_val& a, expr_val& b)
866 return add(a, b);
868 static expr_val fold_prod(expr_val& a, expr_val& b)
870 return mul(a, b);
872 template<expr_val (*T)(expr_val a, expr_val b)>
873 static expr_val op_binary(std::vector<std::function<expr_val&()>> promises)
875 if(promises.size() != 2)
876 throw error(error::ARGCOUNT, "Operation takes 2 arguments");
877 expr_val a = promises[0]();
878 expr_val b = promises[1]();
879 return T(a, b);
881 template<expr_val (*T)(expr_val a)>
882 static expr_val op_unary(std::vector<std::function<expr_val&()>> promises)
884 if(promises.size() != 1)
885 throw error(error::ARGCOUNT, "Operation takes 1 argument");
886 expr_val a = promises[0]();
887 return T(a);
889 template<expr_val (*T)(expr_val a),expr_val (*U)(expr_val a, expr_val b)>
890 static expr_val op_unary_binary(std::vector<std::function<expr_val&()>> promises)
892 if(promises.size() == 1)
893 return T(promises[0]());
894 if(promises.size() == 2)
895 return U(promises[0](), promises[1]());
896 throw error(error::ARGCOUNT, "Operation takes 1 or 2 arguments");
898 static expr_val bnot(expr_val a)
900 return ~a.as_numeric();
902 static expr_val band(expr_val a, expr_val b)
904 return a.as_numeric() & b.as_numeric();
906 static expr_val bor(expr_val a, expr_val b)
908 return a.as_numeric() | b.as_numeric();
910 static expr_val bxor(expr_val a, expr_val b)
912 return a.as_numeric() ^ b.as_numeric();
914 static expr_val neg(expr_val a)
916 return -a.as_numeric();
918 template<expr_val_numeric (expr_val_numeric::*T)() const>
919 static expr_val f_n_fn(expr_val a)
921 return (a.as_numeric().*T)();
923 template<expr_val_numeric (*T)(expr_val_numeric x, expr_val_numeric y)>
924 static expr_val f_n_fn2(expr_val a, expr_val b)
926 return T(a.as_numeric(), b.as_numeric());
928 static expr_val lshift(expr_val a, expr_val b)
930 return expr_val_numeric::shift(a.as_numeric(), b.as_numeric(), false);
932 static expr_val rshift(expr_val a, expr_val b)
934 return expr_val_numeric::shift(a.as_numeric(), b.as_numeric(), true);
936 static expr_val op_pi(std::vector<std::function<expr_val&()>> promises)
938 return expr_val_numeric::op_pi();
940 static expr_val add(expr_val a, expr_val b)
942 if(a.type == T_STRING && b.type == T_STRING)
943 return expr_val(string_tag(), a.v_string + b.v_string);
944 return a.as_numeric() + b.as_numeric();
946 static expr_val sub(expr_val a, expr_val b)
948 return a.as_numeric() - b.as_numeric();
950 static expr_val mul(expr_val a, expr_val b)
952 return a.as_numeric() * b.as_numeric();
954 static expr_val div(expr_val a, expr_val b)
956 return a.as_numeric() / b.as_numeric();
958 static expr_val rem(expr_val a, expr_val b)
960 return a.as_numeric() % b.as_numeric();
962 static bool _eq(const expr_val& a, const expr_val& b)
964 if(a.type != b.type)
965 return false;
966 switch(a.type) {
967 case T_BOOLEAN: return (a.v_boolean == b.v_boolean);
968 case T_STRING: return (a.v_string == b.v_string);
969 case T_NUMERIC: return (a.v_numeric == b.v_numeric);
971 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
973 static expr_val eq(expr_val a, expr_val b)
975 return expr_val(boolean_tag(), _eq(a, b));
977 static expr_val ne(expr_val a, expr_val b)
979 return expr_val(boolean_tag(), !_eq(a, b));
981 static int _cmp(expr_val a, expr_val b)
983 if(a.type != b.type)
984 throw_domain("Can't compare distinct value types");
985 switch(a.type) {
986 case T_BOOLEAN: return _cmp_values(a.v_boolean, b.v_boolean);
987 case T_STRING: return _cmp_values(a.v_string, b.v_string);
988 case T_NUMERIC: return expr_val_numeric::_cmp(a.v_numeric, b.v_numeric);
990 throw error(error::INTERNAL, "Internal error (shouldn't be here)");
992 template<expr_val_numeric(*T)(expr_val_numeric v)>
993 static expr_val x_nconv(expr_val a)
995 return T(a.as_numeric());
997 static expr_val lt(expr_val a, expr_val b)
999 return expr_val(boolean_tag(), _cmp(a, b) < 0);
1001 static expr_val le(expr_val a, expr_val b)
1003 return expr_val(boolean_tag(), _cmp(a, b) <= 0);
1005 static expr_val ge(expr_val a, expr_val b)
1007 return expr_val(boolean_tag(), _cmp(a, b) >= 0);
1009 static expr_val gt(expr_val a, expr_val b)
1011 return expr_val(boolean_tag(), _cmp(a, b) > 0);
1013 std::string format_string(std::string val, _format fmt)
1015 if((int)val.length() > fmt.precision && fmt.precision >= 0)
1016 val = val.substr(0, fmt.precision);
1017 while((int)val.length() < fmt.width)
1018 val = " " + val;
1019 return val;
1021 std::string print_bool_numeric(bool val, _format fmt)
1023 std::string out = val ? "1" : "0";
1024 if(fmt.precision > 0) {
1025 out += ".";
1026 for(int i = 0; i < fmt.precision; i++)
1027 out += "0";
1029 while((int)out.length() < fmt.width)
1030 out = ((fmt.fillzeros) ? "0" : " ") + out;
1031 return out;
1033 std::string format(_format fmt)
1035 switch(type) {
1036 case T_BOOLEAN: return format_bool(v_boolean, fmt);
1037 case T_NUMERIC: return v_numeric.format(fmt);
1038 case T_STRING: return format_string(v_string, fmt);
1039 default:
1040 return "#Notprintable";
1043 static std::set<operinfo*> operations()
1045 static operinfo_set<expr_val> x({
1046 {"-", expr_val::op_unary<expr_val::neg>, true, 1, -3, true},
1047 {"!", expr_val::op_lnot, true, 1, -3, true},
1048 {"~", expr_val::op_unary<expr_val::bnot>, true, 1, -3, true},
1049 {"*", expr_val::op_binary<expr_val::mul>, true, 2, -5, false},
1050 {"/", expr_val::op_binary<expr_val::div>, true, 2, -5, false},
1051 {"%", expr_val::op_binary<expr_val::rem>, true, 2, -5, false},
1052 {"+", expr_val::op_binary<expr_val::add>, true, 2, -6, false},
1053 {"-", expr_val::op_binary<expr_val::sub>, true, 2, -6, false},
1054 {"<<", expr_val::op_binary<expr_val::lshift>, true, 2, -7, false},
1055 {">>", expr_val::op_binary<expr_val::rshift>, true, 2, -7, false},
1056 {"<", expr_val::op_binary<expr_val::lt>, true, 2, -8, false},
1057 {"<=", expr_val::op_binary<expr_val::le>, true, 2, -8, false},
1058 {">", expr_val::op_binary<expr_val::gt>, true, 2, -8, false},
1059 {">=", expr_val::op_binary<expr_val::ge>, true, 2, -8, false},
1060 {"==", expr_val::op_binary<expr_val::eq>, true, 2, -9, false},
1061 {"!=", expr_val::op_binary<expr_val::ne>, true, 2, -9, false},
1062 {"&", expr_val::op_binary<expr_val::band>, true, 2, -10, false},
1063 {"^", expr_val::op_binary<expr_val::bxor>, true, 2, -11, false},
1064 {"|", expr_val::op_binary<expr_val::bor>, true, 2, -12, false},
1065 {"&&", expr_val::op_land, true, 2, -13, false},
1066 {"||", expr_val::op_lor, true, 2, -14, false},
1067 {"π", expr_val::op_pi, true, 0, 0, false},
1068 {"if", expr_val::fun_if},
1069 {"select", expr_val::fun_select},
1070 {"unsigned", expr_val::op_unary<expr_val::x_nconv<expr_val_numeric::x_unsigned>>},
1071 {"signed", expr_val::op_unary<expr_val::x_nconv<expr_val_numeric::x_signed>>},
1072 {"float", expr_val::op_unary<expr_val::x_nconv<expr_val_numeric::x_float>>},
1073 {"min", expr_val::fun_fold<expr_val::fold_min>},
1074 {"max", expr_val::fun_fold<expr_val::fold_max>},
1075 {"sum", expr_val::fun_fold<expr_val::fold_sum>},
1076 {"prod", expr_val::fun_fold<expr_val::fold_prod>},
1077 {"sqrt", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::sqrt>>},
1078 {"log", expr_val::op_unary_binary<expr_val::f_n_fn<&expr_val_numeric::log>,
1079 expr_val::f_n_fn2<expr_val_numeric::log2>>},
1080 {"exp", expr_val::op_unary_binary<expr_val::f_n_fn<&expr_val_numeric::exp>,
1081 expr_val::f_n_fn2<expr_val_numeric::exp2>>},
1082 {"sin", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::sin>>},
1083 {"cos", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::cos>>},
1084 {"tan", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::tan>>},
1085 {"atan", expr_val::op_unary_binary<expr_val::f_n_fn<&expr_val_numeric::atan>,
1086 expr_val::f_n_fn2<expr_val_numeric::atan2>>},
1087 {"asin", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::asin>>},
1088 {"acos", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::acos>>},
1089 {"sinh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::sinh>>},
1090 {"cosh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::cosh>>},
1091 {"tanh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::tanh>>},
1092 {"artanh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::artanh>>},
1093 {"arsinh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::arsinh>>},
1094 {"arcosh", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::arcosh>>},
1095 {"torad", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::torad>>},
1096 {"todeg", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::todeg>>},
1097 {"re", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::re>>},
1098 {"im", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::im>>},
1099 {"conj", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::conj>>},
1100 {"abs", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::abs>>},
1101 {"arg", expr_val::op_unary<expr_val::f_n_fn<&expr_val_numeric::arg>>},
1102 {"pyth", expr_val::fun_pyth},
1104 return x.get_set();
1106 private:
1107 _type type;
1108 bool v_boolean;
1109 expr_val_numeric v_numeric;
1110 std::string v_string;
1114 struct typeinfo* expression_value()
1116 static typeinfo_wrapper<expr_val> expession_value_obj;
1117 return &expession_value_obj;