aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/expressions.c23
-rw-r--r--tests/testsuite.at9
2 files changed, 31 insertions, 1 deletions
diff --git a/src/expressions.c b/src/expressions.c
index 93e3fdc..cec3492 100644
--- a/src/expressions.c
+++ b/src/expressions.c
@@ -184,7 +184,28 @@ teco_expressions_calc(GError **error)
switch (op) {
case TECO_OP_POW:
- for (result = 1; vright--; result *= vleft);
+ if (!vright) {
+ result = vleft < 0 ? -1 : 1;
+ break;
+ }
+ if (vright < 0) {
+ if (!vleft) {
+ g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED,
+ "Negative power of 0 is not defined");
+ return FALSE;
+ }
+ result = ABS(vleft) == 1 ? vleft : 0;
+ break;
+ }
+ result = 1;
+ for (;;) {
+ if (vright & 1)
+ result *= vleft;
+ vright >>= 1;
+ if (!vright)
+ break;
+ vleft *= vleft;
+ }
break;
case TECO_OP_MUL:
result = vleft * vright;
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 80e111c..3a8bed8 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -27,6 +27,15 @@ AT_CHECK([$SCITECO -e "2%a,%a - 3\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "(1,) \"~|(0/0)'"], 0, ignore, ignore)
AT_CLEANUP
+AT_SETUP([Exponentiation])
+AT_CHECK([$SCITECO -e "-1^*0 - (-1)\"N(0/0)'"], 0, ignore, ignore)
+AT_CHECK([$SCITECO -e "-1^*-5 - (-1)\"N(0/0)'"], 0, ignore, ignore)
+AT_CHECK([$SCITECO -e "0^*-5="], 1, ignore, ignore)
+AT_CHECK([$SCITECO -e "0^*0 - 1\"N(0/0)'"], 0, ignore, ignore)
+AT_CHECK([$SCITECO -e "1^*-5 - 1\"N(0/0)'"], 0, ignore, ignore)
+AT_CHECK([$SCITECO -e "2^*-5 - 0\"N(0/0)'"], 0, ignore, ignore)
+AT_CLEANUP
+
AT_SETUP([Missing left operand])
AT_CHECK([$SCITECO -e '+23='], 1, ignore, ignore)
AT_CLEANUP