[gimp] libgimpwidgets: add exponentiation support to eevl
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] libgimpwidgets: add exponentiation support to eevl
- Date: Fri, 1 Jun 2018 14:55:04 +0000 (UTC)
commit 8d35299410442411872dd693c4a96ab47416552d
Author: Ell <ell_se yahoo com>
Date: Fri Jun 1 10:37:47 2018 -0400
libgimpwidgets: add exponentiation support to eevl
Add support for exponentiation (using the ^ operator) to eevl.
This is occasionally useful, e.g., in geometrically-derived
quantities involving square roots.
libgimpwidgets/gimpeevl.c | 63 +++++++++++++++++++++++++++++++++++++++-------
libgimpwidgets/test-eevl.c | 35 ++++++++++++++------------
2 files changed, 73 insertions(+), 25 deletions(-)
---
diff --git a/libgimpwidgets/gimpeevl.c b/libgimpwidgets/gimpeevl.c
index fe0281e30f..27658b0abe 100644
--- a/libgimpwidgets/gimpeevl.c
+++ b/libgimpwidgets/gimpeevl.c
@@ -46,13 +46,15 @@
*
* signed factor ::= ( '+' | '-' )? factor ;
*
- * unit factor ::= factor unit? ;
+ * factor ::= quantity ( '^' signed factor )? ;
*
- * factor ::= number | '(' expression ')' ;
+ * quantity ::= number unit? | '(' expression ')' ;
*
* number ::= ? what g_strtod() consumes ? ;
*
- * unit ::= ? what not g_strtod() consumes and not whitespace ? ;
+ * unit ::= simple unit ( '^' signed factor )? ;
+ *
+ * simple unit ::= ? what not g_strtod() consumes and not whitespace ? ;
*
* The code should match the EBNF rather closely (except for the
* non-terminal unit factor, which is inlined into factor) for
@@ -70,6 +72,8 @@
#include <glib-object.h>
+#include "libgimpmath/gimpmath.h"
+
#include "gimpeevl.h"
#include "gimpwidgets-error.h"
@@ -128,6 +132,7 @@ static GimpEevlQuantity gimp_eevl_term (GimpEevl
static GimpEevlQuantity gimp_eevl_ratio (GimpEevl *eva);
static GimpEevlQuantity gimp_eevl_signed_factor (GimpEevl *eva);
static GimpEevlQuantity gimp_eevl_factor (GimpEevl *eva);
+static GimpEevlQuantity gimp_eevl_quantity (GimpEevl *eva);
static gboolean gimp_eevl_accept (GimpEevl *eva,
GimpEevlTokenType token_type,
GimpEevlToken *consumed_token);
@@ -387,18 +392,42 @@ gimp_eevl_signed_factor (GimpEevl *eva)
static GimpEevlQuantity
gimp_eevl_factor (GimpEevl *eva)
{
- GimpEevlQuantity evaluated_factor = { 0, 0 };
+ GimpEevlQuantity evaluated_factor;
+
+ evaluated_factor = gimp_eevl_quantity (eva);
+
+ if (gimp_eevl_accept (eva, '^', NULL))
+ {
+ GimpEevlQuantity evaluated_exponent;
+
+ evaluated_exponent = gimp_eevl_signed_factor (eva);
+
+ if (evaluated_exponent.dimension != 0)
+ gimp_eevl_error (eva, "Exponent is not a dimensionless quantity");
+
+ evaluated_factor.value = pow (evaluated_factor.value,
+ evaluated_exponent.value);
+ evaluated_factor.dimension *= evaluated_exponent.value;
+ }
+
+ return evaluated_factor;
+}
+
+static GimpEevlQuantity
+gimp_eevl_quantity (GimpEevl *eva)
+{
+ GimpEevlQuantity evaluated_quantity = { 0, 0 };
GimpEevlToken consumed_token;
if (gimp_eevl_accept (eva,
GIMP_EEVL_TOKEN_NUM,
&consumed_token))
{
- evaluated_factor.value = consumed_token.value.fl;
+ evaluated_quantity.value = consumed_token.value.fl;
}
else if (gimp_eevl_accept (eva, '(', NULL))
{
- evaluated_factor = gimp_eevl_expression (eva);
+ evaluated_quantity = gimp_eevl_expression (eva);
gimp_eevl_expect (eva, ')', 0);
}
else
@@ -424,8 +453,24 @@ gimp_eevl_factor (GimpEevl *eva)
&result,
eva->options.data))
{
- evaluated_factor.value /= result.value;
- evaluated_factor.dimension += result.dimension;
+ if (gimp_eevl_accept (eva, '^', NULL))
+ {
+ GimpEevlQuantity evaluated_exponent;
+
+ evaluated_exponent = gimp_eevl_signed_factor (eva);
+
+ if (evaluated_exponent.dimension != 0)
+ {
+ gimp_eevl_error (eva,
+ "Exponent is not a dimensionless quantity");
+ }
+
+ result.value = pow (result.value, evaluated_exponent.value);
+ result.dimension *= evaluated_exponent.value;
+ }
+
+ evaluated_quantity.value /= result.value;
+ evaluated_quantity.dimension += result.dimension;
}
else
{
@@ -433,7 +478,7 @@ gimp_eevl_factor (GimpEevl *eva)
}
}
- return evaluated_factor;
+ return evaluated_quantity;
}
static gboolean
diff --git a/libgimpwidgets/test-eevl.c b/libgimpwidgets/test-eevl.c
index aac6e106e5..9656c14d4a 100644
--- a/libgimpwidgets/test-eevl.c
+++ b/libgimpwidgets/test-eevl.c
@@ -28,6 +28,8 @@
#include <glib-object.h>
+#include "libgimpmath/gimpmath.h"
+
#include "gimpeevl.h"
@@ -41,32 +43,33 @@ typedef struct
static TestCase cases[] =
{
/* "Default" test case */
- { "2in + 3in", { 2 + 3, 1}, TRUE },
+ { "2in + 3in", { 2 + 3, 1}, TRUE },
/* Whitespace variations */
- { "2in+3in", { 2 + 3, 1}, TRUE },
- { " 2in + 3in", { 2 + 3, 1}, TRUE },
- { "2in + 3in ", { 2 + 3, 1}, TRUE },
- { "2 in + 3 in", { 2 + 3, 1}, TRUE },
- { " 2 in + 3 in ", { 2 + 3, 1}, TRUE },
+ { "2in+3in", { 2 + 3, 1}, TRUE },
+ { " 2in + 3in", { 2 + 3, 1}, TRUE },
+ { "2in + 3in ", { 2 + 3, 1}, TRUE },
+ { "2 in + 3 in", { 2 + 3, 1}, TRUE },
+ { " 2 in + 3 in ", { 2 + 3, 1}, TRUE },
/* Make sure the default unit is applied as it should */
- { "2 + 3in", { 2 + 3, 1 }, TRUE },
- { "3", { 3, 1 }, TRUE },
+ { "2 + 3in", { 2 + 3, 1 }, TRUE },
+ { "3", { 3, 1 }, TRUE },
/* Somewhat complicated input */
- { "(2 + 3)in", { 2 + 3, 1}, TRUE },
-// { "2 / 3 in", { 2 / 3., 1}, TRUE },
- { "(2 + 2/3)in", { 2 + 2 / 3., 1}, TRUE },
- { "1/2 + 1/2", { 1, 1}, TRUE },
+ { "(2 + 3)in", { 2 + 3, 1}, TRUE },
+// { "2 / 3 in", { 2 / 3., 1}, TRUE },
+ { "(2 + 2/3)in", { 2 + 2 / 3., 1}, TRUE },
+ { "1/2 + 1/2", { 1, 1}, TRUE },
+ { "2 ^ 3 ^ 4", { pow (2, pow (3, 4)), 1}, TRUE },
/* Mixing of units */
- { "2mm + 3in", { 2 / 25.4 + 3, 1}, TRUE },
+ { "2mm + 3in", { 2 / 25.4 + 3, 1}, TRUE },
/* 'odd' behavior */
- { "2 ++ 1", { 3, 1}, TRUE },
- { "2 +- 1", { 1, 1}, TRUE },
- { "2 -- 1", { 3, 1}, TRUE },
+ { "2 ++ 1", { 3, 1}, TRUE },
+ { "2 +- 1", { 1, 1}, TRUE },
+ { "2 -- 1", { 3, 1}, TRUE },
/* End of test cases */
{ NULL, { 0, 0 }, TRUE }
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]