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:
parent
9cd195bf5b
commit
6f2dc7fb0b
11
README
11
README
@ -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
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 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
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_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
18
fpd.y
@ -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 */
|
||||||
|
24
unparse.c
24
unparse.c
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user