diff --git a/README b/README index d4dced0..876ebd7 100644 --- a/README +++ b/README @@ -509,7 +509,7 @@ Expressions Expressions can contain numeric constants (in non-exponential notation), variable names, the arithmetic operations +, -, *, /, unary -, and the -functions sin(), cos(), and sqrt(). +functions sin(), cos(), sqrt(), and floor(). Parentheses can be used to change precedence. @@ -520,6 +520,10 @@ 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. +The function floor() returns the next integer that is below or equal to +the argument. If the argument has a dimension, that dimension is +preserved. E.g., floor(-1.2) returns -2, floor(4.7mm) returns 4mm. + GUI --- diff --git a/expr.c b/expr.c index 66170b1..c1753c4 100644 --- a/expr.c +++ b/expr.c @@ -322,6 +322,17 @@ struct num op_minus(const struct expr *self, const struct frame *frame) } +struct num op_floor(const struct expr *self, const struct frame *frame) +{ + struct num res; + + res = eval_num(self->u.op.a, frame); + if (!is_undef(res)) + res.n = floor(res.n); + return res; +} + + #define BINARY \ struct num a, b, res; \ \ @@ -533,7 +544,7 @@ 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_floor || expr->op == op_sin || expr->op == op_cos || expr->op == op_sqrt) { free_expr(expr->u.op.a); return; diff --git a/expr.h b/expr.h index 6e6c201..f89f210 100644 --- a/expr.h +++ b/expr.h @@ -1,8 +1,8 @@ /* * expr.h - Expressions and values * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2012 by Werner Almesberger + * Copyright 2009, 2012 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -116,6 +116,7 @@ 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_floor(const struct expr *self, const struct frame *frame); struct num op_add(const struct expr *self, const struct frame *frame); struct num op_sub(const struct expr *self, const struct frame *frame); diff --git a/fpd.y b/fpd.y index 06278e0..d1db83c 100644 --- a/fpd.y +++ b/fpd.y @@ -48,7 +48,7 @@ static struct obj **next_obj; static int n_vars, n_values; -static const char *id_sin, *id_cos, *id_sqrt; +static const char *id_sin, *id_cos, *id_sqrt, *id_floor; static struct tsort *tsort; @@ -491,6 +491,7 @@ all: id_sin = unique("sin"); id_cos = unique("cos"); id_sqrt = unique("sqrt"); + id_floor = unique("floor"); } fpd | START_EXPR expr @@ -1245,6 +1246,8 @@ primary_expr: $$ = binary_op(op_cos, $3, NULL); else if ($1 == id_sqrt) $$ = binary_op(op_sqrt, $3, NULL); + else if ($1 == id_floor) + $$ = binary_op(op_floor, $3, NULL); else { yyerrorf("unknown function \"%s\"", $1); YYABORT; diff --git a/test/floor b/test/floor new file mode 100755 index 0000000..ced963e --- /dev/null +++ b/test/floor @@ -0,0 +1,22 @@ +#!/bin/sh +. ./Common + +############################################################################### + +fped "floor: 4.7mm" <op == op_sqrt) return unparse_fn("sqrt", expr); + if (expr->op == op_floor) + return unparse_fn("floor", expr); abort(); }