mirror of
git://projects.qi-hardware.com/fped.git
synced 2024-12-22 23:14:36 +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:
parent
9cd195bf5b
commit
6f2dc7fb0b
11
README
11
README
@ -438,9 +438,18 @@ Expressions
|
||||
-----------
|
||||
|
||||
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
|
||||
---
|
||||
|
55
expr.c
55
expr.c
@ -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 res;
|
||||
@ -306,7 +356,7 @@ struct num op_div(const struct expr *self, const struct frame *frame)
|
||||
{
|
||||
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 @@ static void vacate_op(struct expr *expr)
|
||||
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;
|
||||
}
|
||||
|
4
expr.h
4
expr.h
@ -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_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);
|
||||
|
18
fpd.y
18
fpd.y
@ -43,6 +43,8 @@ static struct obj **next_obj;
|
||||
|
||||
static int n_vars, n_values;
|
||||
|
||||
static const char *id_sin, *id_cos, *id_sqrt;
|
||||
|
||||
|
||||
static struct frame *find_frame(const char *name)
|
||||
{
|
||||
@ -186,6 +188,9 @@ all:
|
||||
{
|
||||
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 @@ primary_expr:
|
||||
{
|
||||
$$ = $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 */
|
||||
|
24
unparse.c
24
unparse.c
@ -38,7 +38,8 @@ static int precedence(op_type op)
|
||||
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 *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)
|
||||
{
|
||||
char tmp[100];
|
||||
@ -103,6 +119,12 @@ static char *unparse_op(const struct expr *expr, enum prec prec)
|
||||
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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user