Commit 8d31f4c7 authored by Morten Welinder's avatar Morten Welinder Committed by Morten Welinder

New function for more user-wanted rounding behaviour.

2000-12-20  Morten Welinder  <terra@diku.dk>

	* src/mathfunc.c (gnumeric_add_epsilon): New function for more
 	user-wanted rounding behaviour.
	(gnumeric_fake_floor, gnumeric_fake_ceil, gnumeric_fake_round):
 	New functions.

	* src/fn-math (gnumeric_round, gnumeric_roundup,
 	gnumeric_rounddown, gnumeric_trunc, gnumeric_ceil,
 	gnumeric_floor): use fake rounding.
parent c6818c48
2000-12-20 Morten Welinder <terra@diku.dk>
* src/mathfunc.c (gnumeric_add_epsilon): New function for more
user-wanted rounding behaviour.
(gnumeric_fake_floor, gnumeric_fake_ceil, gnumeric_fake_round):
New functions.
* src/fn-math (gnumeric_round, gnumeric_roundup,
gnumeric_rounddown, gnumeric_trunc, gnumeric_ceil,
gnumeric_floor): use fake rounding.
2000-12-20 Jody Goldberg <jgoldberg@home.com>
* src/workbook-control-gui.c (insert_bonobo_object) : utility routine
......
2000-12-20 Morten Welinder <terra@diku.dk>
* src/mathfunc.c (gnumeric_add_epsilon): New function for more
user-wanted rounding behaviour.
(gnumeric_fake_floor, gnumeric_fake_ceil, gnumeric_fake_round):
New functions.
* src/fn-math (gnumeric_round, gnumeric_roundup,
gnumeric_rounddown, gnumeric_trunc, gnumeric_ceil,
gnumeric_floor): use fake rounding.
2000-12-20 Jody Goldberg <jgoldberg@home.com>
* src/workbook-control-gui.c (insert_bonobo_object) : utility routine
......
2000-12-20 Morten Welinder <terra@diku.dk>
* src/mathfunc.c (gnumeric_add_epsilon): New function for more
user-wanted rounding behaviour.
(gnumeric_fake_floor, gnumeric_fake_ceil, gnumeric_fake_round):
New functions.
* src/fn-math (gnumeric_round, gnumeric_roundup,
gnumeric_rounddown, gnumeric_trunc, gnumeric_ceil,
gnumeric_floor): use fake rounding.
2000-12-20 Jody Goldberg <jgoldberg@home.com>
* src/workbook-control-gui.c (insert_bonobo_object) : utility routine
......
2000-12-20 Morten Welinder <terra@diku.dk>
* src/mathfunc.c (gnumeric_add_epsilon): New function for more
user-wanted rounding behaviour.
(gnumeric_fake_floor, gnumeric_fake_ceil, gnumeric_fake_round):
New functions.
* src/fn-math (gnumeric_round, gnumeric_roundup,
gnumeric_rounddown, gnumeric_trunc, gnumeric_ceil,
gnumeric_floor): use fake rounding.
2000-12-20 Jody Goldberg <jgoldberg@home.com>
* src/workbook-control-gui.c (insert_bonobo_object) : utility routine
......
2000-12-20 Morten Welinder <terra@diku.dk>
* src/mathfunc.c (gnumeric_add_epsilon): New function for more
user-wanted rounding behaviour.
(gnumeric_fake_floor, gnumeric_fake_ceil, gnumeric_fake_round):
New functions.
* src/fn-math (gnumeric_round, gnumeric_roundup,
gnumeric_rounddown, gnumeric_trunc, gnumeric_ceil,
gnumeric_floor): use fake rounding.
2000-12-20 Jody Goldberg <jgoldberg@home.com>
* src/workbook-control-gui.c (insert_bonobo_object) : utility routine
......
......@@ -469,7 +469,7 @@ static char *help_ceil = {
static Value *
gnumeric_ceil (FunctionEvalInfo *ei, Value **args)
{
return value_new_float (ceil (value_get_as_float (args [0])));
return value_new_float (gnumeric_fake_ceil (value_get_as_float (args [0])));
}
/***************************************************************************/
......@@ -741,7 +741,7 @@ gnumeric_ceiling (FunctionEvalInfo *ei, Value **argv)
if (s == 0 || number / s < 0)
return value_new_error (ei->pos, gnumeric_err_NUM);
return value_new_float (ceil (number / s) * s);
return value_new_float (gnumeric_fake_ceil (number / s) * s);
}
/***************************************************************************/
......@@ -947,7 +947,7 @@ gnumeric_floor (FunctionEvalInfo *ei, Value **argv)
if (s == 0 || (number / s) < 0)
return value_new_error (ei->pos, gnumeric_err_NUM);
return value_new_float (floor (number / s) * s);
return value_new_float (gnumeric_fake_floor (number / s) * s);
}
/***************************************************************************/
......@@ -971,7 +971,7 @@ static char *help_int = {
static Value *
gnumeric_int (FunctionEvalInfo *ei, Value **argv)
{
return value_new_float (floor (value_get_as_float (argv [0])));
return value_new_float (gnumeric_fake_floor (value_get_as_float (argv [0])));
}
/***************************************************************************/
......@@ -1760,11 +1760,7 @@ gnumeric_trunc (FunctionEvalInfo *ei, Value **argv)
digits = value_get_as_int (argv[1]);
p10 = gpow10 (digits);
if (number < 0)
return value_new_float (-floor (-number * p10) / p10);
else
return value_new_float (floor (number * p10) / p10);
return value_new_float (gnumeric_fake_trunc (number * p10) / p10);
}
/***************************************************************************/
......@@ -2050,10 +2046,7 @@ gnumeric_rounddown (FunctionEvalInfo *ei, Value **argv)
digits = value_get_as_int (argv[1]);
p10 = gpow10 (digits);
if (number < 0)
return value_new_float (-ceil (-number * p10) / p10);
else
return value_new_float (floor (number * p10) / p10);
return value_new_float (gnumeric_fake_floor (number * p10) / p10);
}
/***************************************************************************/
......@@ -2094,10 +2087,7 @@ gnumeric_round (FunctionEvalInfo *ei, Value **argv)
digits = argv[1] ? value_get_as_int (argv[1]) : 0;
p10 = gpow10 (digits);
if (number < 0)
return value_new_float (-floor (-number * p10 + 0.5) / p10);
else
return value_new_float (floor (number * p10 + 0.5) / p10);
return value_new_float (gnumeric_fake_round (number * p10) / p10);
}
/***************************************************************************/
......@@ -2141,10 +2131,7 @@ gnumeric_roundup (FunctionEvalInfo *ei, Value **argv)
digits = value_get_as_int (argv[1]);
p10 = gpow10 (digits);
if (number < 0)
return value_new_float (-floor (-number * p10) / p10);
else
return value_new_float (ceil (number * p10) / p10);
return value_new_float (gnumeric_fake_ceil (number * p10) / p10);
}
/***************************************************************************/
......
......@@ -469,7 +469,7 @@ static char *help_ceil = {
static Value *
gnumeric_ceil (FunctionEvalInfo *ei, Value **args)
{
return value_new_float (ceil (value_get_as_float (args [0])));
return value_new_float (gnumeric_fake_ceil (value_get_as_float (args [0])));
}
/***************************************************************************/
......@@ -741,7 +741,7 @@ gnumeric_ceiling (FunctionEvalInfo *ei, Value **argv)
if (s == 0 || number / s < 0)
return value_new_error (ei->pos, gnumeric_err_NUM);
return value_new_float (ceil (number / s) * s);
return value_new_float (gnumeric_fake_ceil (number / s) * s);
}
/***************************************************************************/
......@@ -947,7 +947,7 @@ gnumeric_floor (FunctionEvalInfo *ei, Value **argv)
if (s == 0 || (number / s) < 0)
return value_new_error (ei->pos, gnumeric_err_NUM);
return value_new_float (floor (number / s) * s);
return value_new_float (gnumeric_fake_floor (number / s) * s);
}
/***************************************************************************/
......@@ -971,7 +971,7 @@ static char *help_int = {
static Value *
gnumeric_int (FunctionEvalInfo *ei, Value **argv)
{
return value_new_float (floor (value_get_as_float (argv [0])));
return value_new_float (gnumeric_fake_floor (value_get_as_float (argv [0])));
}
/***************************************************************************/
......@@ -1760,11 +1760,7 @@ gnumeric_trunc (FunctionEvalInfo *ei, Value **argv)
digits = value_get_as_int (argv[1]);
p10 = gpow10 (digits);
if (number < 0)
return value_new_float (-floor (-number * p10) / p10);
else
return value_new_float (floor (number * p10) / p10);
return value_new_float (gnumeric_fake_trunc (number * p10) / p10);
}
/***************************************************************************/
......@@ -2050,10 +2046,7 @@ gnumeric_rounddown (FunctionEvalInfo *ei, Value **argv)
digits = value_get_as_int (argv[1]);
p10 = gpow10 (digits);
if (number < 0)
return value_new_float (-ceil (-number * p10) / p10);
else
return value_new_float (floor (number * p10) / p10);
return value_new_float (gnumeric_fake_floor (number * p10) / p10);
}
/***************************************************************************/
......@@ -2094,10 +2087,7 @@ gnumeric_round (FunctionEvalInfo *ei, Value **argv)
digits = argv[1] ? value_get_as_int (argv[1]) : 0;
p10 = gpow10 (digits);
if (number < 0)
return value_new_float (-floor (-number * p10 + 0.5) / p10);
else
return value_new_float (floor (number * p10 + 0.5) / p10);
return value_new_float (gnumeric_fake_round (number * p10) / p10);
}
/***************************************************************************/
......@@ -2141,10 +2131,7 @@ gnumeric_roundup (FunctionEvalInfo *ei, Value **argv)
digits = value_get_as_int (argv[1]);
p10 = gpow10 (digits);
if (number < 0)
return value_new_float (-floor (-number * p10) / p10);
else
return value_new_float (ceil (number * p10) / p10);
return value_new_float (gnumeric_fake_ceil (number * p10) / p10);
}
/***************************************************************************/
......
......@@ -22,7 +22,7 @@
#include <errno.h>
#include <stdlib.h>
#include <float.h>
#ifdef HAVE_IEEEFP
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
/* Make sure we have this symbol defined, since the existance of the header
file implies it. */
......@@ -83,6 +83,54 @@ d1mach (int i)
/* MW ---------------------------------------------------------------------- */
/*
* In preparation for truncation, make the value a tiny bit larger (seen
* absolutely). This makes ROUND (etc.) behave a little closer to what
* people want, even if it is a bit bogus.
*/
static double
gnumeric_add_epsilon (double x)
{
if (!finite (x) || x == 0)
return x;
else {
int exp;
double mant = frexp (fabs (x), &exp);
double absres = ldexp (mant + DBL_EPSILON, exp);
return (x < 0) ? -absres : absres;
}
}
double
gnumeric_fake_floor (double x)
{
return floor (gnumeric_add_epsilon (x));
}
double
gnumeric_fake_ceil (double x)
{
return ceil (gnumeric_add_epsilon (x));
}
double
gnumeric_fake_round (double x)
{
return (x >= 0)
? gnumeric_fake_floor (x + 0.5)
: -gnumeric_fake_floor (-x + 0.5);
}
double
gnumeric_fake_trunc (double x)
{
return (x >= 0)
? gnumeric_fake_floor (x)
: gnumeric_fake_ceil (x);
}
/* Arithmetic sum. */
int
range_sum (const float_t *xs, int n, float_t *res)
......
......@@ -22,6 +22,11 @@
/* ------------------------------------------------------------------------- */
double gnumeric_fake_floor (double x);
double gnumeric_fake_ceil (double x);
double gnumeric_fake_round (double x);
double gnumeric_fake_trunc (double x);
int range_sum (const float_t *xs, int n, float_t *res);
int range_product (const float_t *xs, int n, float_t *res);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment