diff options
| -rw-r--r-- | libc/stdlib/Makefile | 4 | ||||
| -rw-r--r-- | libc/stdlib/ldiv.c | 78 | ||||
| -rw-r--r-- | libc/stdlib/lldiv.c | 63 | 
3 files changed, 119 insertions, 26 deletions
| diff --git a/libc/stdlib/Makefile b/libc/stdlib/Makefile index 878d2bd03..02dd8887e 100644 --- a/libc/stdlib/Makefile +++ b/libc/stdlib/Makefile @@ -82,8 +82,8 @@ MSRC2 = atexit.c  MOBJ2 = atexit.o on_exit.o __exit_handler.o exit.o  CSRC =	abort.c getenv.c mkdtemp.c mktemp.c realpath.c mkstemp.c mkstemp64.c \ -	rand.c random.c random_r.c setenv.c system.c div.c ldiv.c getpt.c \ -	ptsname.c grantpt.c unlockpt.c gcvt.c drand48-iter.c jrand48.c \ +	rand.c random.c random_r.c setenv.c system.c div.c ldiv.c lldiv.c \ +	getpt.c ptsname.c grantpt.c unlockpt.c gcvt.c drand48-iter.c jrand48.c \  	jrand48_r.c lrand48.c lrand48_r.c mrand48.c mrand48_r.c nrand48.c \  	nrand48_r.c rand_r.c srand48.c srand48_r.c seed48.c seed48_r.c \  	valloc.c diff --git a/libc/stdlib/ldiv.c b/libc/stdlib/ldiv.c index 230b6a944..c66470fb2 100644 --- a/libc/stdlib/ldiv.c +++ b/libc/stdlib/ldiv.c @@ -1,32 +1,62 @@ -/* vi: set sw=4 ts=4: */ -/* ldiv for uClibc - * - * Copyright (C) 2000 by Lineo, inc. and Erik Andersen - * Copyright (C) 2000,2001 by Erik Andersen <andersen@uclibc.org> - * Written by Erik Andersen <andersen@uclibc.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Library General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License - * for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ +/* Copyright (C) 1992, 1997 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <features.h>  #include <stdlib.h> -ldiv_t ldiv(long numer, long denom) + +/* Return the `ldiv_t' representation of NUMER over DENOM.  */ +ldiv_t +ldiv (long int numer, long int denom)  {      ldiv_t result; +      result.quot = numer / denom; -    result.rem  = numer - (result.quot * denom); -    return(result); +    result.rem = numer % denom; + +    /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where +       NUMER / DENOM is to be computed in infinite precision.  In +       other words, we should always truncate the quotient towards +       zero, never -infinity.  Machine division and remainer may +       work either way when one or both of NUMER or DENOM is +       negative.  If only one is negative and QUOT has been +       truncated towards -infinity, REM will have the same sign as +       DENOM and the opposite sign of NUMER; if both are negative +       and QUOT has been truncated towards -infinity, REM will be +       positive (will have the opposite sign of NUMER).  These are +       considered `wrong'.  If both are NUM and DENOM are positive, +       RESULT will always be positive.  This all boils down to: if +       NUMER >= 0, but REM < 0, we got the wrong answer.  In that +       case, to get the right answer, add 1 to QUOT and subtract +       DENOM from REM.  */ + +    if (numer >= 0 && result.rem < 0) +    { +	++result.quot; +	result.rem -= denom; +    } + +    return result;  } +#if __WORDSIZE == 64 +#undef imaxdiv +weak_alias (ldiv, imaxdiv); +#endif + diff --git a/libc/stdlib/lldiv.c b/libc/stdlib/lldiv.c new file mode 100644 index 000000000..2b382db6c --- /dev/null +++ b/libc/stdlib/lldiv.c @@ -0,0 +1,63 @@ +/* `long long int' divison with remainder. +   Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#define _GNU_SOURCE +#include <features.h> +#include <stdlib.h> + + +/* Return the `lldiv_t' representation of NUMER over DENOM.  */ +lldiv_t +lldiv (long long int numer, long long int denom) +{ +    lldiv_t result; + +    result.quot = numer / denom; +    result.rem = numer % denom; + +    /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where +       NUMER / DENOM is to be computed in infinite precision.  In +       other words, we should always truncate the quotient towards +       zero, never -infinity.  Machine division and remainer may +       work either way when one or both of NUMER or DENOM is +       negative.  If only one is negative and QUOT has been +       truncated towards -infinity, REM will have the same sign as +       DENOM and the opposite sign of NUMER; if both are negative +       and QUOT has been truncated towards -infinity, REM will be +       positive (will have the opposite sign of NUMER).  These are +       considered `wrong'.  If both are NUM and DENOM are positive, +       RESULT will always be positive.  This all boils down to: if +       NUMER >= 0, but REM < 0, we got the wrong answer.  In that +       case, to get the right answer, add 1 to QUOT and subtract +       DENOM from REM.  */ + +    if (numer >= 0 && result.rem < 0) +    { +	++result.quot; +	result.rem -= denom; +    } + +    return result; +} + +#if __WORDSIZE != 64 +#undef imaxdiv +weak_alias (lldiv, imaxdiv); +#endif + | 
