r5732 - trunk/eda/fped

werner at docs.openmoko.org werner at docs.openmoko.org
Tue Dec 1 13:43:59 CET 2009


Author: werner
Date: 2009-12-01 13:43:59 +0100 (Tue, 01 Dec 2009)
New Revision: 5732

Modified:
   trunk/eda/fped/README
   trunk/eda/fped/expr.c
   trunk/eda/fped/expr.h
   trunk/eda/fped/fpd.y
   trunk/eda/fped/unparse.c
Log:
Added functions sin(), cos(), and sqrt().



Modified: trunk/eda/fped/README
===================================================================
--- trunk/eda/fped/README	2009-12-01 10:50:55 UTC (rev 5731)
+++ trunk/eda/fped/README	2009-12-01 12:43:59 UTC (rev 5732)
@@ -438,10 +438,19 @@
 -----------
 
 Expressions can contain numeric constants (in non-exponential notation),
-variable names, the arithmetic operations +, -, *, /, and unary -.
+variable names, the arithmetic operations +, -, *, /, unary -, and the
+functions sin(), cos(), and sqrt().
+
 Parentheses can be used to change precedence.
 
+The argument of sin and cos is a dimensionless number that specifies the
+angle in degrees. E.g., sin(90) yields 1.
 
+The argument of sqrt() can be dimensionless or have a dimension with an
+exponent that's a multiple of two. E.g., sqrt(2) and sqrt(2mm*3mm) are
+valid expressions, sqrt(2mm) isn't.
+
+
 GUI
 ---
 

Modified: trunk/eda/fped/expr.c
===================================================================
--- trunk/eda/fped/expr.c	2009-12-01 10:50:55 UTC (rev 5731)
+++ trunk/eda/fped/expr.c	2009-12-01 12:43:59 UTC (rev 5732)
@@ -249,6 +249,56 @@
 }
 
 
+static struct num sin_cos(const struct expr *self,
+    const struct frame *frame, double (*fn)(double arg))
+{
+	struct num res;
+
+	res = eval_num(self->u.op.a, frame);
+	if (is_undef(res))
+		return undef;
+	if (!is_dimensionless(res)) {
+		fail("angle must be dimensionless");	
+		return undef;
+	}
+	res.n = fn(res.n/180.0*M_PI);
+	return res;
+}
+
+
+struct num op_sin(const struct expr *self, const struct frame *frame)
+{
+	return sin_cos(self, frame, sin);
+}
+
+
+struct num op_cos(const struct expr *self, const struct frame *frame)
+{
+	return sin_cos(self, frame, cos);
+}
+
+
+struct num op_sqrt(const struct expr *self, const struct frame *frame)
+{
+	struct num res;
+
+	res = eval_num(self->u.op.a, frame);
+	if (is_undef(res))
+		return undef;
+	if (res.exponent & 1) {
+		fail("exponent of sqrt argument must be a multiple of two");	
+		return undef;
+	}
+	if (res.n < 0) {
+		fail("argument of sqrt must be positive");	
+		return undef;
+	}
+	res.n = sqrt(res.n);
+	res.exponent >>= 1;
+	return res;
+}
+
+
 struct num op_minus(const struct expr *self, const struct frame *frame)
 {
 	struct num res;
@@ -306,7 +356,7 @@
 {
 	BINARY;
 	if (!b.n) {
-		fail("Division by zero");
+		fail("division by zero");
 		return undef;
 	}
 	res = compatible_mult(&a, &b, a.exponent-b.exponent);
@@ -471,7 +521,8 @@
 		free(expr->u.str);
 		return;
 	}
-	if (expr->op == op_minus) {
+	if (expr->op == op_minus ||
+	    expr->op == op_sin || expr->op == op_cos || expr->op == op_sqrt) {
 		free_expr(expr->u.op.a);
 		return;
 	}

Modified: trunk/eda/fped/expr.h
===================================================================
--- trunk/eda/fped/expr.h	2009-12-01 10:50:55 UTC (rev 5731)
+++ trunk/eda/fped/expr.h	2009-12-01 12:43:59 UTC (rev 5732)
@@ -111,6 +111,10 @@
 struct num op_var(const struct expr *self, const struct frame *frame);
 struct num op_string(const struct expr *self, const struct frame *frame);
 
+struct num op_sin(const struct expr *self, const struct frame *frame);
+struct num op_cos(const struct expr *self, const struct frame *frame);
+struct num op_sqrt(const struct expr *self, const struct frame *frame);
+
 struct num op_minus(const struct expr *self, const struct frame *frame);
 
 struct num op_add(const struct expr *self, const struct frame *frame);

Modified: trunk/eda/fped/fpd.y
===================================================================
--- trunk/eda/fped/fpd.y	2009-12-01 10:50:55 UTC (rev 5731)
+++ trunk/eda/fped/fpd.y	2009-12-01 12:43:59 UTC (rev 5732)
@@ -43,7 +43,9 @@
 
 static int n_vars, n_values;
 
+static const char *id_sin, *id_cos, *id_sqrt;
 
+
 static struct frame *find_frame(const char *name)
 {
 	struct frame *f;
@@ -186,6 +188,9 @@
 		{
 			root_frame = zalloc_type(struct frame);
 			set_frame(root_frame);
+			id_sin = unique("sin");
+			id_cos = unique("cos");
+			id_sqrt = unique("sqrt");
 		}
 	    fpd
 		{
@@ -704,6 +709,19 @@
 		{
 			$$ = $2;
 		}
+	| ID '(' expr ')'
+		{
+			if ($1 == id_sin)
+				$$ = binary_op(op_sin, $3, NULL);
+			else if ($1 == id_cos)
+				$$ = binary_op(op_cos, $3, NULL);
+			else if ($1 == id_sqrt)
+				$$ = binary_op(op_sqrt, $3, NULL);
+			else {
+				yyerrorf("unknown function \"%s\"", $1);
+				YYABORT;
+			}
+		}
 	;
 
 /* special sub-grammar */

Modified: trunk/eda/fped/unparse.c
===================================================================
--- trunk/eda/fped/unparse.c	2009-12-01 10:50:55 UTC (rev 5731)
+++ trunk/eda/fped/unparse.c	2009-12-01 12:43:59 UTC (rev 5732)
@@ -38,7 +38,8 @@
 		return prec_mult;
 	if (op == op_minus)
 		return prec_unary;
-	if (op == op_num || op == op_string || op == op_var)
+	if (op == op_num || op == op_string || op == op_var ||
+	    op == op_sin || op == op_cos || op == op_sqrt)
 		return prec_primary;
 	abort();
 }
@@ -67,6 +68,21 @@
 }
 
 
+static char *unparse_op(const struct expr *expr, enum prec prec);
+
+
+static char *unparse_fn(const char *name, const struct expr *expr)
+{
+	char *buf, *tmp;
+
+	tmp = unparse_op(expr->u.op.a, prec_add);
+	buf = alloc_size(strlen(name)+strlen(tmp)+3);
+	sprintf(buf, "%s(%s)", name, tmp);
+	free(tmp);
+	return buf;
+}
+
+
 static char *unparse_op(const struct expr *expr, enum prec prec)
 {
 	char tmp[100];
@@ -103,6 +119,12 @@
 	if (expr->op == op_div)
 		return merge3(unparse_op(expr->u.op.a, prec_mult), "/",
 		    unparse_op(expr->u.op.b, prec_primary));
+	if (expr->op == op_sin)
+		return unparse_fn("sin", expr);
+	if (expr->op == op_cos)
+		return unparse_fn("cos", expr);
+	if (expr->op == op_sqrt)
+		return unparse_fn("sqrt", expr);
 	abort();
 }
 




More information about the commitlog mailing list