[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [tyndur-devel] [PATCH v2] libm: Rundungsfunktionen



On Sun, Sep 20, 2009 at 06:25:00PM +0200, Antoine Kaufmann wrote:
> On Fri, Sep 11 20:37, Kevin Wolf wrote:
> > + libm: floor, ceil, round, trunc, nearbyint, fesetround, fegetround
> > 
> > Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
> > ---
> >  src/modules/include/fenv.h           |   42 ++++++++
> >  src/modules/include/math.h           |   18 +++-
> >  src/modules/lib/stdlibc/math/round.c |  182 ++++++++++++++++++++++++++++++++++
> >  3 files changed, 241 insertions(+), 1 deletions(-)
> >  create mode 100644 src/modules/include/fenv.h
> >  create mode 100644 src/modules/lib/stdlibc/math/round.c
> > 
> > diff --git a/src/modules/include/fenv.h b/src/modules/include/fenv.h
> > new file mode 100644
> > index 0000000..10e9ded
> > --- /dev/null
> > +++ b/src/modules/include/fenv.h
> > @@ -0,0 +1,42 @@
> > +/*
> > + * Copyright (c) 2009 The tyndur Project. All rights reserved.
> > + *
> > + * This code is derived from software contributed to the tyndur Project
> > + * by Kevin Wolf.
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, this list of conditions and the following disclaimer.
> > + * 2. Redistributions in binary form must reproduce the above copyright
> > + *    notice, this list of conditions and the following disclaimer in the
> > + *    documentation and/or other materials provided with the distribution.
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> > + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> > + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> > + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
> > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> > + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> > + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
> > + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
> > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
> > + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +
> > +#ifndef _FENV_H_
> > +#define _FENV_H_
> > +
> > +enum {
> > +    FE_TONEAREST,
> > +    FE_UPWARD,
> > +    FE_DOWNWARD,
> > +    FE_TOWARDZERO,
> > +};
> > +
> > +int fegetround(void);
> > +int fesetround(int rounding_mode);
> > +
> > +#endif
> > diff --git a/src/modules/include/math.h b/src/modules/include/math.h
> > index 49083ab..1cbb54f 100644
> > --- a/src/modules/include/math.h
> > +++ b/src/modules/include/math.h
> > @@ -50,7 +50,6 @@
> >  #define M_SQRT1_2   0.70710678118654752440
> >  
> >  
> > -
> >  double      tan(double);
> >  float       tanf(float);
> >  long double tanl(long double);
> > @@ -94,5 +93,22 @@ double      acos(double);
> >  float       acosf(float);
> >  long double acosl(long double);
> >  
> > +
> > +double      floor(double x);
> > +float       floorf(float x);
> > +long double floorl(long double x);
> > +double      ceil(double x);
> > +float       ceilf(float x);
> > +long double ceill(long double x);
> > +double      trunc(double x);
> > +float       truncf(float x);
> > +long double truncl(long double x);
> > +double      round(double x);
> > +float       roundf(float x);
> > +long double roundl(long double x);
> > +double      nearbyint(double x);
> > +float       nearbyintf(float x);
> > +long double nearbyintl(long double x);
> > +
> >  #endif
> >  
> > diff --git a/src/modules/lib/stdlibc/math/round.c b/src/modules/lib/stdlibc/math/round.c
> > new file mode 100644
> > index 0000000..b16a95a
> > --- /dev/null
> > +++ b/src/modules/lib/stdlibc/math/round.c
> > @@ -0,0 +1,182 @@
> > +/*
> > + * Copyright (c) 2009 The tyndur Project. All rights reserved.
> > + *
> > + * This code is derived from software contributed to the tyndur Project
> > + * by Kevin Wolf.
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, this list of conditions and the following disclaimer.
> > + * 2. Redistributions in binary form must reproduce the above copyright
> > + *    notice, this list of conditions and the following disclaimer in the
> > + *    documentation and/or other materials provided with the distribution.
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> > + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> > + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> > + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
> > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> > + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> > + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
> > + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
> > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
> > + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +
> > +#include <math.h>
> > +#include <fenv.h>
> > +#include <stdint.h>
> > +#include <stdlib.h>
> > +
> > +#define ROUND_NEAR  0x000
> > +#define ROUND_DOWN  0x400
> > +#define ROUND_UP    0x800
> > +#define ROUND_TRUNC 0xc00
> > +
> > +static int rounding_mode = FE_TONEAREST;
> > +
> > +/*
> > + * Achtung:
> > + *
> > + * Die folgende Funktion basieren auf der Annahme, dass das RC-Feld im FPU
> > + * Control Word normalerweise immer auf 0 gesetzt ist, also der neue Wert durch
> > + * ein einfaches or eingetragen werden kann.
> > + */
> > +static inline long double do_round(long double x, int mode)
> > +{
> > +    long double res;
> > +    uint16_t control_word;
> > +
> > +    asm(
> > +        // Rundungsmodus setzen
> > +        "fnstcw %2;"
> > +        "mov %2, %%eax;"
> > +        "orl %3, %2;"
> > +        "fldcw %2;"
> > +
> > +        // Zahl auf dem Stack runden
> > +        "frndint;"
> > +
> > +        // Wieder den Standardrundungsmodus setzen
> > +        "mov %%eax, %2;"
> > +        "fldcw %2;"
> > +        : "=t" (res) : "0" (x), "m" (control_word), "r" (mode) : "eax");
> > +
> > +    return res;
> > +}
> > +
> > +
> > +long double floorl(long double x)
> > +{
> > +    return do_round(x, ROUND_DOWN);
> > +}
> > +
> > +double floor(double x)
> > +{
> > +    return floorl(x);
> > +}
> > +
> > +float floorf(float x)
> > +{
> > +    return floorl(x);
> > +}
> > +
> > +
> > +long double ceill(long double x)
> > +{
> > +    return do_round(x, ROUND_UP);
> > +}
> > +
> > +double ceil(double x)
> > +{
> > +    return ceill(x);
> > +}
> > +
> > +float ceilf(float x)
> > +{
> > +    return ceill(x);
> > +}
> > +
> > +long double truncl(long double x)
> > +{
> > +    return do_round(x, ROUND_TRUNC);
> > +}
> > +
> > +double trunc(double x)
> > +{
> > +    return truncl(x);
> > +}
> > +
> > +float truncf(float x)
> > +{
> > +    return truncl(x);
> > +}
> > +
> > +long double roundl(long double x)
> > +{
> > +    long double res;
> > +
> > +    asm("frndint" : "=t" (res) : "0" (x));
> 
> Hat es einen speziellen Grund, dass du hier nicht do_round mit
> ROUND_NEAR nimmst? Dann wäre man doch, sobald man mal do_round richtig
> macht, so richtig schön unabhängig von den aktuell gesetzten Flags...
> ;-)

Genuine Effizienzität! ;-)

Momentan werde ja in do_round die Flags werden nur dazugeodert, das
Feld wird vorher nicht gelöscht. Insofern ist das eh nicht generisch.
Nicht, dass es schwer wäre, das zu ändern, aber das überlasse ich
dir.