1
0
mirror of git://projects.qi-hardware.com/fped.git synced 2024-11-26 03:01:53 +02:00

Added functions sin(), cos(), and sqrt().

git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5732 99fdad57-331a-0410-800a-d7fa5415bdb3
This commit is contained in:
werner 2009-12-01 12:43:59 +00:00
parent 9cd195bf5b
commit 6f2dc7fb0b
5 changed files with 108 additions and 4 deletions

11
README
View File

@ -438,9 +438,18 @@ Expressions
----------- -----------
Expressions can contain numeric constants (in non-exponential notation), 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. 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 GUI
--- ---

55
expr.c
View File

@ -249,6 +249,56 @@ static struct num compatible_mult(struct num *a, struct num *b,
} }
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 op_minus(const struct expr *self, const struct frame *frame)
{ {
struct num res; struct num res;
@ -306,7 +356,7 @@ struct num op_div(const struct expr *self, const struct frame *frame)
{ {
BINARY; BINARY;
if (!b.n) { if (!b.n) {
fail("Division by zero"); fail("division by zero");
return undef; return undef;
} }
res = compatible_mult(&a, &b, a.exponent-b.exponent); res = compatible_mult(&a, &b, a.exponent-b.exponent);
@ -471,7 +521,8 @@ static void vacate_op(struct expr *expr)
free(expr->u.str); free(expr->u.str);
return; 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); free_expr(expr->u.op.a);
return; return;
} }

4
expr.h
View File

@ -111,6 +111,10 @@ struct num op_num(const struct expr *self, const struct frame *frame);
struct num op_var(const struct expr *self, const struct frame *frame); 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_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_minus(const struct expr *self, const struct frame *frame);
struct num op_add(const struct expr *self, const struct frame *frame); struct num op_add(const struct expr *self, const struct frame *frame);

18
fpd.y
View File

@ -43,6 +43,8 @@ static struct obj **next_obj;
static int n_vars, n_values; static int n_vars, n_values;
static const char *id_sin, *id_cos, *id_sqrt;
static struct frame *find_frame(const char *name) static struct frame *find_frame(const char *name)
{ {
@ -186,6 +188,9 @@ all:
{ {
root_frame = zalloc_type(struct frame); root_frame = zalloc_type(struct frame);
set_frame(root_frame); set_frame(root_frame);
id_sin = unique("sin");
id_cos = unique("cos");
id_sqrt = unique("sqrt");
} }
fpd fpd
{ {
@ -704,6 +709,19 @@ primary_expr:
{ {
$$ = $2; $$ = $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 */ /* special sub-grammar */

View File

@ -38,7 +38,8 @@ static int precedence(op_type op)
return prec_mult; return prec_mult;
if (op == op_minus) if (op == op_minus)
return prec_unary; 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; return prec_primary;
abort(); abort();
} }
@ -67,6 +68,21 @@ static char *merge2(const char *op, char *a)
} }
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) static char *unparse_op(const struct expr *expr, enum prec prec)
{ {
char tmp[100]; char tmp[100];
@ -103,6 +119,12 @@ static char *unparse_op(const struct expr *expr, enum prec prec)
if (expr->op == op_div) if (expr->op == op_div)
return merge3(unparse_op(expr->u.op.a, prec_mult), "/", return merge3(unparse_op(expr->u.op.a, prec_mult), "/",
unparse_op(expr->u.op.b, prec_primary)); 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(); abort();
} }