Mercurial > flash_v2
diff packages/language/c/libc/current/include/stdlib.inl @ 2:443894e2e912 ecos-v1_2_1-release
Block commit of eCos version 1.2.1
| author | jlarmour |
|---|---|
| date | Tue, 11 May 1999 12:24:34 +0000 |
| parents | 3111d98ba7b3 |
| children | c38311975d4f |
line wrap: on
line diff
--- a/packages/language/c/libc/current/include/stdlib.inl +++ b/packages/language/c/libc/current/include/stdlib.inl @@ -25,76 +25,34 @@ // September 30, 1998. // // The Initial Developer of the Original Code is Cygnus. Portions created -// by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. +// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND#### //=========================================================================== //#####DESCRIPTIONBEGIN#### // -// Author(s): jlarmour -// Contributors: jlarmour@cygnus.co.uk -// Date: 1998-02-13 +// Author(s): jlarmour +// Contributors: jlarmour@ +// Date: 1999-03-02 // Purpose: // Description: -// Usage: #include <stdlib.h> - do not include this file directly +// Usage: Do not include this file directly - include <stdlib.h> instead // //####DESCRIPTIONEND#### // //=========================================================================== -// -// The div() and ldiv() functions in this file are based on original -// code with the following copyright: -// -// Note that only div() and ldiv() have this copyright -// -/* - * Copyright (c) 1990 Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - */ // CONFIGURATION #include <pkgconf/libc.h> // Configuration header -// Include the C library? -#ifdef CYGPKG_LIBC - // INCLUDES -#include <stddef.h> // NULL, wchar_t and size_t from compiler -#include <stdlib.h> // Just to be sure that the main header is there +#include <stddef.h> // NULL, wchar_t and size_t from compiler +#include <stdlib.h> // Header for this file, just in case +#include <cyg/infra/cyg_ass.h> // Assertion support +#include <cyg/infra/cyg_trac.h> // Tracing support // FUNCTIONS @@ -128,79 +86,131 @@ atol( const char *nptr ) CYGPRI_LIBC_INLINE int -abs( int j ) +abs( int __j ) { - return (j<0) ? -j : j; + return (__j<0) ? -__j : __j; } // abs() CYGPRI_LIBC_INLINE div_t -div( int numer, int denom ) +div( int __numer, int __denom ) { - div_t result; + div_t __ret; + + CYG_REPORT_FUNCNAMETYPE( "div", "quotient: %d"); + CYG_REPORT_FUNCARG2DV( __numer, __denom ); + // FIXME: what if they want it handled with SIGFPE? Should have option + CYG_PRECONDITION(__denom != 0, "division by zero attempted!"); - // The ANSI standard says that |r.quot| <= |n/d|, where - // n/d is to be computed in infinite precision. In other - // words, we should always truncate the quotient towards - // 0, never -infinity. + __ret.quot = __numer / __denom; + __ret.rem = __numer % __denom; + + // But the modulo is implementation-defined for -ve numbers (ISO C 6.3.5) + // and we are required to "round" to zero (ISO C 7.10.6.2) // - // Machine division and remainer may work either way when - // one or both of n or d is negative. If only one is - // negative and r.quot has been truncated towards -inf, - // r.rem will have the same sign as denom and the opposite - // sign of num; if both are negative and r.quot has been - // truncated towards -inf, r.rem will be positive (will - // have the opposite sign of num). These are considered - // `wrong'. + // The cases we have to deal with are inexact division of: + // a) + div + + // b) + div - + // c) - div + + // d) - div - // - // If both are num and denom are positive, r will always - // be positive. + // a) can never go wrong and the quotient and remainder are always positive + // b) only goes wrong if the negative quotient has been "rounded" to + // -infinity - if so then the remainder will be negative when it + // should be positive or zero + // c) only goes wrong if the negative quotient has been "rounded" to + // -infinity - if so then the remainder will be positive when it + // should be negative or zero + // d) only goes wrong if the positive quotient has been rounded to + // +infinity - if so then the remainder will be positive when it + // should be negative or zero // - // This all boils down to: - // if num >= 0, but r.rem < 0, we got the wrong answer. - // In that case, to get the right answer, add 1 to r.quot and - // subtract denom from r.rem. + // So the correct sign of the remainder corresponds to the sign of the + // numerator. Which means we can say that the result needs adjusting + // iff the sign of the numerator is different from the sign of the + // remainder. + // + // You may be interested to know that the Berkeley version of div() + // would get this wrong for e.g. (c) and (d) on some targets. + // e.g. for (-5)/4 it could leave the result as -2R3 - result.quot = numer / denom; - result.rem = numer % denom; + if ((__ret.rem < 0) && (__numer > 0)) { + ++__ret.quot; + __ret.rem -= __denom; + } else if ((__ret.rem > 0) && (__numer < 0)) { + --__ret.quot; + __ret.rem += __denom; + } // else - if ( (numer >= 0) && (result.rem < 0) ) - { - result.quot++; - result.rem -= denom; - } // if + CYG_REPORT_RETVAL( __ret.quot ); - return result; + return __ret; } // div() CYGPRI_LIBC_INLINE long -labs( long j ) +labs( long __j ) { - return (j<0) ? -j : j; + return (__j<0) ? -__j : __j; } // labs() CYGPRI_LIBC_INLINE ldiv_t -ldiv( long numer, long denom ) +ldiv( long __numer, long __denom ) { - ldiv_t result; + ldiv_t __ret; - result.quot = numer / denom; - result.rem = numer % denom; + CYG_REPORT_FUNCNAMETYPE( "ldiv", "quotient: %d"); + CYG_REPORT_FUNCARG2DV( __numer, __denom ); + // FIXME: what if they want it handled with SIGFPE? Should have option + CYG_PRECONDITION(__denom != 0, "division by zero attempted!"); + + __ret.quot = __numer / __denom; + __ret.rem = __numer % __denom; - if ( (numer >= 0) && (result.rem < 0) ) - { - result.quot++; - result.rem -= denom; - } // if + // But the modulo is implementation-defined for -ve numbers (ISO C 6.3.5) + // and we are required to "round" to zero (ISO C 7.10.6.2) + // + // The cases we have to deal with are inexact division of: + // a) + div + + // b) + div - + // c) - div + + // d) - div - + // + // a) can never go wrong and the quotient and remainder are always positive + // b) only goes wrong if the negative quotient has been "rounded" to + // -infinity - if so then the remainder will be negative when it + // should be positive or zero + // c) only goes wrong if the negative quotient has been "rounded" to + // -infinity - if so then the remainder will be positive when it + // should be negative or zero + // d) only goes wrong if the positive quotient has been rounded to + // +infinity - if so then the remainder will be positive when it + // should be negative or zero + // + // So the correct sign of the remainder corresponds to the sign of the + // numerator. Which means we can say that the result needs adjusting + // iff the sign of the numerator is different from the sign of the + // remainder. + // + // You may be interested to know that the Berkeley version of ldiv() + // would get this wrong for e.g. (c) and (d) on some targets. + // e.g. for (-5)/4 it could leave the result as -2R3 - return result; + if ((__ret.rem < 0) && (__numer > 0)) { + ++__ret.quot; + __ret.rem -= __denom; + } else if ((__ret.rem > 0) && (__numer < 0)) { + --__ret.quot; + __ret.rem += __denom; + } // else + + CYG_REPORT_RETVAL( __ret.quot ); + + return __ret; } // ldiv() -#endif // ifdef CYGPKG_LIBC - #endif // CYGONCE_LIBC_STDLIB_INL multiple inclusion protection // EOF stdlib.inl
