1 #include "mathexpr-ntype.hpp"
2 #include "mathexpr-error.hpp"
3 #include "mathexpr-format.hpp"
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
)
29 class expr_val_numeric
39 struct unsigned_tag
{};
42 struct complex_tag
{};
49 expr_val_numeric(unsigned_tag
, uint64_t v
)
55 expr_val_numeric(signed_tag
, int64_t v
)
61 expr_val_numeric(float_tag
, double v
)
67 expr_val_numeric(complex_tag
, double re
, double im
)
73 expr_val_numeric(const std::string
& str
)
79 } else if(regex("[0-9]+|0x[0-9a-fA-F]+", str
)) {
81 v_unsigned
= parse_value
<uint64_t>(str
);
84 } else if(regex("[+-][0-9]+|[+-]0x[0-9a-fA-F]+", str
)) {
86 v_signed
= parse_value
<int64_t>(str
);
89 } else if(regex("[+-]?([0-9]+|[0-9]*\\.[0-9]+)([eE][0-9]+)?", str
)) {
91 v_float
= parse_value
<double>(str
);
95 throw std::runtime_error("Bad number '" + str
+ "'");
97 double as_float() const
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
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
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()
131 return (stringfmt() << v_unsigned
).str();
133 return (stringfmt() << v_signed
).str();
135 //FIXME: Saner formatting.
136 return (stringfmt() << v_float
).str();
138 //FIXME: Saner formatting.
140 return (stringfmt() << v_float
<< v_imag
<< "*i").str();
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();
155 void scale(uint64_t scale
)
160 v_float
= (1.0 * v_unsigned
/ scale
);
164 v_float
= (1.0 * v_signed
/ scale
);
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
)
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
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
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(),
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(),
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
;
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
;
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
);
326 throw error(error::LOG_BY_0
, "Can't take logarithm of 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();
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
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
422 //(x-u)^2 - x^2 + 2ux - u^2 + x^2 - 2ux - 1 = 0
424 expr_val_numeric xmu
= (*this * *this) + expr_val_numeric(float_tag(), 1);
425 expr_val_numeric x
= xmu
.sqrt() + *this;
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;
434 expr_val_numeric
artanh() const
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();
460 if(a
.type
== T_SIGNED
) {
461 int64_t _a
= a
.v_signed
;
463 return expr_val_numeric(signed_tag(), -1);
465 return expr_val_numeric(signed_tag(), 0);
468 uint64_t r2
= r
>> -s
;
469 uint64_t m
= 0xFFFFFFFFFFFFFFFFULL
- ((1ULL << (64 - s
)) - 1);
470 return expr_val_numeric(signed_tag(), m
| r2
);
472 return expr_val_numeric(signed_tag(), _a
<< s
);
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);
480 return expr_val_numeric(unsigned_tag(), _a
>> -s
);
482 return expr_val_numeric(unsigned_tag(), _a
<< s
);
484 return expr_val_numeric(unsigned_tag(), _a
);
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
)
507 //TODO: Handle values too large for exact integer representation.
514 static int _cmp_float_signed(int64_t a
, float b
)
516 //TODO: Handle values too large for exact integer representation.
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");
531 return _cmp_values(a
.v_unsigned
, b
.v_unsigned
);
535 if((int64_t)a
.v_unsigned
< 0)
537 return _cmp_values((int64_t)a
.v_unsigned
, b
.v_signed
);
539 return _cmp_float_unsigned(a
.v_unsigned
, b
.v_float
);
541 throw error(error::INTERNAL
,
542 "Internal error (shouldn't be here)");
549 if((int64_t)b
.v_unsigned
< 0)
551 return _cmp_values(a
.v_signed
, (int64_t)b
.v_unsigned
);
553 return _cmp_values(a
.v_signed
, b
.v_signed
);
555 return _cmp_float_signed(a
.v_signed
, b
.v_float
);
557 throw error(error::INTERNAL
,
558 "Internal error (shouldn't be here)");
563 return -_cmp_float_unsigned(b
.v_unsigned
, a
.v_float
);
565 return -_cmp_float_signed(b
.v_signed
, a
.v_float
);
567 if(a
.v_float
< b
.v_float
)
569 if(a
.v_float
> b
.v_float
)
573 throw error(error::INTERNAL
,
574 "Internal error (shouldn't be here)");
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
)
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
)
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
)
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
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
642 case T_COMPLEX
: return expr_val_numeric(float_tag(), ::atan2(v_imag
, v_float
));
645 return expr_val_numeric(float_tag(), 4 * ::atan(1));
647 return expr_val_numeric(float_tag(), 0);
662 struct number_tag
{};
663 struct string_tag
{};
664 struct boolean_tag
{};
671 expr_val_numeric
& as_numeric()
673 if(type
!= T_NUMERIC
)
674 throw_domain("Can't operate with non-numbers");
682 expr_val(const std::string
& str
, bool string
)
687 } else if(str
== "false") {
690 } else if(str
== "true") {
693 } else if(str
== "e") {
694 v_numeric
= expr_val_numeric::op_e();
696 } else if(str
== "pi") {
697 v_numeric
= expr_val_numeric::op_pi();
700 v_numeric
= expr_val_numeric(str
);
704 expr_val(typeinfo_wrapper
<expr_val
>::unsigned_tag t
, uint64_t v
)
705 : type(T_NUMERIC
), v_numeric(expr_val_numeric::unsigned_tag(), v
)
708 expr_val(typeinfo_wrapper
<expr_val
>::signed_tag t
, int64_t v
)
709 : type(T_NUMERIC
), v_numeric(expr_val_numeric::signed_tag(), v
)
712 expr_val(typeinfo_wrapper
<expr_val
>::float_tag t
, double v
)
713 : type(T_NUMERIC
), v_numeric(expr_val_numeric::float_tag(), v
)
716 expr_val(typeinfo_wrapper
<expr_val
>::boolean_tag
, bool b
)
717 : type(T_BOOLEAN
), v_boolean(b
)
720 expr_val(expr_val_numeric v
)
721 : type(T_NUMERIC
), v_numeric(v
)
724 expr_val(string_tag
, std::string s
)
725 : type(T_STRING
), v_string(s
)
728 expr_val(boolean_tag
, bool b
)
729 : type(T_BOOLEAN
), v_boolean(b
)
732 std::string
tostring()
741 return v_numeric
.tostring();
745 throw error(error::INTERNAL
, "Internal error (shouldn't be here)");
747 uint64_t tounsigned()
749 if(type
!= T_NUMERIC
)
750 throw_domain("Can't convert non-number into unsigned");
751 return v_numeric
.tounsigned();
755 if(type
!= T_NUMERIC
)
756 throw_domain("Can't convert non-number into signed");
757 return v_numeric
.tosigned();
759 void scale(uint64_t _scale
)
761 if(type
!= T_NUMERIC
)
762 throw_domain("Can't scale non-number");
763 v_numeric
.scale(_scale
);
771 return v_numeric
.toboolean();
773 return (v_string
.length() != 0);
775 throw error(error::INTERNAL
, "Internal error (shouldn't be here)");
777 static expr_val
op_lnot(std::vector
<std::function
<expr_val
&()>> promises
)
779 if(promises
.size() != 1)
780 throw error(error::ARGCOUNT
, "logical not takes 1 argument");
781 return expr_val(boolean_tag(), !(promises
[0]().toboolean()));
783 static expr_val
op_lor(std::vector
<std::function
<expr_val
&()>> promises
)
785 if(promises
.size() != 2)
786 throw error(error::ARGCOUNT
, "logical or takes 2 arguments");
787 if(promises
[0]().toboolean())
788 return expr_val(boolean_tag(), true);
789 return expr_val(boolean_tag(), promises
[1]().toboolean());
791 static expr_val
op_land(std::vector
<std::function
<expr_val
&()>> promises
)
793 if(promises
.size() != 2)
794 throw error(error::ARGCOUNT
, "logical and takes 2 arguments");
795 if(!(promises
[0]().toboolean()))
796 return expr_val(boolean_tag(), false);
797 return expr_val(boolean_tag(), promises
[1]().toboolean());
799 static expr_val
fun_if(std::vector
<std::function
<expr_val
&()>> promises
)
801 if(promises
.size() == 2) {
802 if((promises
[0]().toboolean()))
803 return promises
[1]();
805 return expr_val(boolean_tag(), false);
806 } else if(promises
.size() == 3) {
807 if((promises
[0]().toboolean()))
808 return promises
[1]();
810 return promises
[2]();
812 throw error(error::ARGCOUNT
, "if takes 2 or 3 arguments");
814 static expr_val
fun_select(std::vector
<std::function
<expr_val
&()>> promises
)
816 for(auto& i
: promises
) {
818 if(v
.type
!= T_BOOLEAN
|| v
.v_boolean
)
821 return expr_val(boolean_tag(), false);
823 static expr_val
fun_pyth(std::vector
<std::function
<expr_val
&()>> promises
)
825 std::vector
<expr_val
> v
;
826 for(auto& i
: promises
)
828 expr_val_numeric
n(expr_val_numeric::float_tag(), 0);
829 expr_val_numeric
one(expr_val_numeric::float_tag(), 1);
831 if(i
.type
!= T_NUMERIC
)
832 throw error(error::WDOMAIN
, "pyth requires numeric args");
833 n
= n
+ one
* i
.v_numeric
* i
.v_numeric
;
837 template<expr_val (*T
)(expr_val
& a
, expr_val
& b
)>
838 static expr_val
fun_fold(std::vector
<std::function
<expr_val
&()>> promises
)
841 return expr_val(boolean_tag(), false);
842 expr_val v
= promises
[0]();
843 for(size_t i
= 1; i
< promises
.size(); i
++)
844 v
= T(v
, promises
[i
]());
847 static expr_val
fold_min(expr_val
& a
, expr_val
& b
)
849 int t
= _cmp_values(a
.type
, b
.type
);
854 return (_cmp(a
, b
) < 0) ? a
: b
;
856 static expr_val
fold_max(expr_val
& a
, expr_val
& b
)
858 int t
= _cmp_values(a
.type
, b
.type
);
863 return (_cmp(a
, b
) > 0) ? a
: b
;
865 static expr_val
fold_sum(expr_val
& a
, expr_val
& b
)
869 static expr_val
fold_prod(expr_val
& a
, expr_val
& b
)
873 template<expr_val (*T
)(expr_val a
, expr_val b
)>
874 static expr_val
op_binary(std::vector
<std::function
<expr_val
&()>> promises
)
876 if(promises
.size() != 2)
877 throw error(error::ARGCOUNT
, "Operation takes 2 arguments");
878 expr_val a
= promises
[0]();
879 expr_val b
= promises
[1]();
882 template<expr_val (*T
)(expr_val a
)>
883 static expr_val
op_unary(std::vector
<std::function
<expr_val
&()>> promises
)
885 if(promises
.size() != 1)
886 throw error(error::ARGCOUNT
, "Operation takes 1 argument");
887 expr_val a
= promises
[0]();
890 template<expr_val (*T
)(expr_val a
),expr_val (*U
)(expr_val a
, expr_val b
)>
891 static expr_val
op_unary_binary(std::vector
<std::function
<expr_val
&()>> promises
)
893 if(promises
.size() == 1)
894 return T(promises
[0]());
895 if(promises
.size() == 2)
896 return U(promises
[0](), promises
[1]());
897 throw error(error::ARGCOUNT
, "Operation takes 1 or 2 arguments");
899 static expr_val
bnot(expr_val a
)
901 return ~a
.as_numeric();
903 static expr_val
band(expr_val a
, expr_val b
)
905 return a
.as_numeric() & b
.as_numeric();
907 static expr_val
bor(expr_val a
, expr_val b
)
909 return a
.as_numeric() | b
.as_numeric();
911 static expr_val
bxor(expr_val a
, expr_val b
)
913 return a
.as_numeric() ^ b
.as_numeric();
915 static expr_val
neg(expr_val a
)
917 return -a
.as_numeric();
919 template<expr_val_numeric (expr_val_numeric::*T
)() const>
920 static expr_val
f_n_fn(expr_val a
)
922 return (a
.as_numeric().*T
)();
924 template<expr_val_numeric (*T
)(expr_val_numeric x
, expr_val_numeric y
)>
925 static expr_val
f_n_fn2(expr_val a
, expr_val b
)
927 return T(a
.as_numeric(), b
.as_numeric());
929 static expr_val
lshift(expr_val a
, expr_val b
)
931 return expr_val_numeric::shift(a
.as_numeric(), b
.as_numeric(), false);
933 static expr_val
rshift(expr_val a
, expr_val b
)
935 return expr_val_numeric::shift(a
.as_numeric(), b
.as_numeric(), true);
937 static expr_val
op_pi(std::vector
<std::function
<expr_val
&()>> promises
)
939 return expr_val_numeric::op_pi();
941 static expr_val
add(expr_val a
, expr_val b
)
943 if(a
.type
== T_STRING
&& b
.type
== T_STRING
)
944 return expr_val(string_tag(), a
.v_string
+ b
.v_string
);
945 return a
.as_numeric() + b
.as_numeric();
947 static expr_val
sub(expr_val a
, expr_val b
)
949 return a
.as_numeric() - b
.as_numeric();
951 static expr_val
mul(expr_val a
, expr_val b
)
953 return a
.as_numeric() * b
.as_numeric();
955 static expr_val
div(expr_val a
, expr_val b
)
957 return a
.as_numeric() / b
.as_numeric();
959 static expr_val
rem(expr_val a
, expr_val b
)
961 return a
.as_numeric() % b
.as_numeric();
963 static bool _eq(const expr_val
& a
, const expr_val
& b
)
968 case T_BOOLEAN
: return (a
.v_boolean
== b
.v_boolean
);
969 case T_STRING
: return (a
.v_string
== b
.v_string
);
970 case T_NUMERIC
: return (a
.v_numeric
== b
.v_numeric
);
972 throw error(error::INTERNAL
, "Internal error (shouldn't be here)");
974 static expr_val
eq(expr_val a
, expr_val b
)
976 return expr_val(boolean_tag(), _eq(a
, b
));
978 static expr_val
ne(expr_val a
, expr_val b
)
980 return expr_val(boolean_tag(), !_eq(a
, b
));
982 static int _cmp(expr_val a
, expr_val b
)
985 throw_domain("Can't compare distinct value types");
987 case T_BOOLEAN
: return _cmp_values(a
.v_boolean
, b
.v_boolean
);
988 case T_STRING
: return _cmp_values(a
.v_string
, b
.v_string
);
989 case T_NUMERIC
: return expr_val_numeric::_cmp(a
.v_numeric
, b
.v_numeric
);
991 throw error(error::INTERNAL
, "Internal error (shouldn't be here)");
993 template<expr_val_numeric(*T
)(expr_val_numeric v
)>
994 static expr_val
x_nconv(expr_val a
)
996 return T(a
.as_numeric());
998 static expr_val
lt(expr_val a
, expr_val b
)
1000 return expr_val(boolean_tag(), _cmp(a
, b
) < 0);
1002 static expr_val
le(expr_val a
, expr_val b
)
1004 return expr_val(boolean_tag(), _cmp(a
, b
) <= 0);
1006 static expr_val
ge(expr_val a
, expr_val b
)
1008 return expr_val(boolean_tag(), _cmp(a
, b
) >= 0);
1010 static expr_val
gt(expr_val a
, expr_val b
)
1012 return expr_val(boolean_tag(), _cmp(a
, b
) > 0);
1014 std::string
format_string(std::string val
, _format fmt
)
1016 if((int)val
.length() > fmt
.precision
&& fmt
.precision
>= 0)
1017 val
= val
.substr(0, fmt
.precision
);
1018 while((int)val
.length() < fmt
.width
)
1022 std::string
print_bool_numeric(bool val
, _format fmt
)
1024 std::string out
= val
? "1" : "0";
1025 if(fmt
.precision
> 0) {
1027 for(int i
= 0; i
< fmt
.precision
; i
++)
1030 while((int)out
.length() < fmt
.width
)
1031 out
= ((fmt
.fillzeros
) ? "0" : " ") + out
;
1034 std::string
format(_format fmt
)
1037 case T_BOOLEAN
: return format_bool(v_boolean
, fmt
);
1038 case T_NUMERIC
: return v_numeric
.format(fmt
);
1039 case T_STRING
: return format_string(v_string
, fmt
);
1041 return "#Notprintable";
1044 static std::set
<operinfo
*> operations()
1046 static operinfo_set
<expr_val
> x({
1047 {"-", expr_val::op_unary
<expr_val::neg
>, true, 1, -3, true},
1048 {"!", expr_val::op_lnot
, true, 1, -3, true},
1049 {"~", expr_val::op_unary
<expr_val::bnot
>, true, 1, -3, true},
1050 {"*", expr_val::op_binary
<expr_val::mul
>, true, 2, -5, false},
1051 {"/", expr_val::op_binary
<expr_val::div
>, true, 2, -5, false},
1052 {"%", expr_val::op_binary
<expr_val::rem
>, true, 2, -5, false},
1053 {"+", expr_val::op_binary
<expr_val::add
>, true, 2, -6, false},
1054 {"-", expr_val::op_binary
<expr_val::sub
>, true, 2, -6, false},
1055 {"<<", expr_val::op_binary
<expr_val::lshift
>, true, 2, -7, false},
1056 {">>", expr_val::op_binary
<expr_val::rshift
>, true, 2, -7, false},
1057 {"<", expr_val::op_binary
<expr_val::lt
>, true, 2, -8, false},
1058 {"<=", expr_val::op_binary
<expr_val::le
>, true, 2, -8, false},
1059 {">", expr_val::op_binary
<expr_val::gt
>, true, 2, -8, false},
1060 {">=", expr_val::op_binary
<expr_val::ge
>, true, 2, -8, false},
1061 {"==", expr_val::op_binary
<expr_val::eq
>, true, 2, -9, false},
1062 {"!=", expr_val::op_binary
<expr_val::ne
>, true, 2, -9, false},
1063 {"&", expr_val::op_binary
<expr_val::band
>, true, 2, -10, false},
1064 {"^", expr_val::op_binary
<expr_val::bxor
>, true, 2, -11, false},
1065 {"|", expr_val::op_binary
<expr_val::bor
>, true, 2, -12, false},
1066 {"&&", expr_val::op_land
, true, 2, -13, false},
1067 {"||", expr_val::op_lor
, true, 2, -14, false},
1068 {"π", expr_val::op_pi
, true, 0, 0, false},
1069 {"if", expr_val::fun_if
},
1070 {"select", expr_val::fun_select
},
1071 {"unsigned", expr_val::op_unary
<expr_val::x_nconv
<expr_val_numeric::x_unsigned
>>},
1072 {"signed", expr_val::op_unary
<expr_val::x_nconv
<expr_val_numeric::x_signed
>>},
1073 {"float", expr_val::op_unary
<expr_val::x_nconv
<expr_val_numeric::x_float
>>},
1074 {"min", expr_val::fun_fold
<expr_val::fold_min
>},
1075 {"max", expr_val::fun_fold
<expr_val::fold_max
>},
1076 {"sum", expr_val::fun_fold
<expr_val::fold_sum
>},
1077 {"prod", expr_val::fun_fold
<expr_val::fold_prod
>},
1078 {"sqrt", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::sqrt
>>},
1079 {"log", expr_val::op_unary_binary
<expr_val::f_n_fn
<&expr_val_numeric::log
>,
1080 expr_val::f_n_fn2
<expr_val_numeric::log2
>>},
1081 {"exp", expr_val::op_unary_binary
<expr_val::f_n_fn
<&expr_val_numeric::exp
>,
1082 expr_val::f_n_fn2
<expr_val_numeric::exp2
>>},
1083 {"sin", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::sin
>>},
1084 {"cos", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::cos
>>},
1085 {"tan", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::tan
>>},
1086 {"atan", expr_val::op_unary_binary
<expr_val::f_n_fn
<&expr_val_numeric::atan
>,
1087 expr_val::f_n_fn2
<expr_val_numeric::atan2
>>},
1088 {"asin", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::asin
>>},
1089 {"acos", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::acos
>>},
1090 {"sinh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::sinh
>>},
1091 {"cosh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::cosh
>>},
1092 {"tanh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::tanh
>>},
1093 {"artanh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::artanh
>>},
1094 {"arsinh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::arsinh
>>},
1095 {"arcosh", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::arcosh
>>},
1096 {"torad", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::torad
>>},
1097 {"todeg", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::todeg
>>},
1098 {"re", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::re
>>},
1099 {"im", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::im
>>},
1100 {"conj", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::conj
>>},
1101 {"abs", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::abs
>>},
1102 {"arg", expr_val::op_unary
<expr_val::f_n_fn
<&expr_val_numeric::arg
>>},
1103 {"pyth", expr_val::fun_pyth
},
1110 expr_val_numeric v_numeric
;
1111 std::string v_string
;
1115 struct typeinfo
* expression_value()
1117 static typeinfo_wrapper
<expr_val
> expession_value_obj
;
1118 return &expession_value_obj
;