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

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



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...
;-)

> +
> +    return res;
> +}
> +
> +double round(double x)
> +{
> +    return roundl(x);
> +}
> +
> +float roundf(float x)
> +{
> +    return roundl(x);
> +}
> +
> +long double nearbyintl(long double x)
> +{
> +    switch (rounding_mode) {
> +        case FE_TONEAREST:
> +            return roundl(x);
> +        case FE_TOWARDZERO:
> +            return truncl(x);
> +        case FE_DOWNWARD:
> +            return floorl(x);
> +        case FE_UPWARD:
> +            return ceill(x);
> +    }
> +
> +    abort();
> +    return x;
> +}
> +
> +double nearbyint(double x)
> +{
> +    return nearbyintl(x);
> +}
> +
> +float nearbyintf(float x)
> +{
> +    return nearbyintl(x);
> +}
> +
> +int fegetround(void)
> +{
> +    return rounding_mode;
> +}
> +
> +int fesetround(int mode)
> +{
> +    switch(mode) {
> +        case FE_TONEAREST:
> +        case FE_TOWARDZERO:
> +        case FE_DOWNWARD:
> +        case FE_UPWARD:
> +            rounding_mode = mode;
> +            return 0;
> +
> +        default:
> +            return -1;
> +    }
> +}

Sonst sieht das einigermassen vernünftig aus.

Acked-by: Antoine Kaufmann <toni@xxxxxxxxxx>

-- 
Antoine Kaufmann
<toni@xxxxxxxxxxxxxxxx>

Attachment: pgpqoQlal61gp.pgp
Description: PGP signature