Mercurial > flash_v2
diff packages/language/c/libc/current/src/stdlib/div.cxx @ 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/src/stdlib/div.cxx +++ b/packages/language/c/libc/current/src/stdlib/div.cxx @@ -2,8 +2,7 @@ // // div.cxx // -// Real alternative for inline implementation of the ANSI standard -// div() utility function defined in section 7.10.6.2 of the standard +// ISO C implementation for div() utility function // //=========================================================================== //####COPYRIGHTBEGIN#### @@ -23,138 +22,107 @@ // 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 -// Purpose: -// Description: -// Usage: +// Author(s): jlarmour +// Contributors: jlarmour +// Date: 1999-03-02 +// Purpose: Provide implementation of div() from ISO C section 7.10.6.2 +// Description: +// Usage: // //####DESCRIPTIONEND#### // //=========================================================================== // -// This code is based on code with the following 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 <cyg/infra/cyg_type.h> // Common type definitions and support +#include <cyg/infra/cyg_ass.h> // Assertion support #include <cyg/infra/cyg_trac.h> // Tracing support // We don't want the inline versions of stdlib functions defined here #ifdef CYGIMP_LIBC_STDLIB_INLINES -#undef CYGIMP_LIBC_STDLIB_INLINES +# undef CYGIMP_LIBC_STDLIB_INLINES #endif #include <stddef.h> // NULL, wchar_t and size_t from compiler #include <stdlib.h> // Main header for stdlib functions -#include "clibincl/stdlibsupp.hxx" // Support for stdlib functions + + +// FUNCTIONS + +externC div_t +__div( int __numer, int __denom ) +{ + 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!"); + + __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) + // + // 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 div() + // would get this wrong for (c) and (d) on some targets. + // e.g. for (-5)/4 it could leave the result as -2R3 + + 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; +} // __div() // EXPORTED SYMBOLS externC div_t -div( int numer, int denom ) CYGPRI_LIBC_WEAK_ALIAS("_div"); +div( int __numer, int __denom ) CYGBLD_ATTRIB_WEAK_ALIAS(__div); -// FUNCTIONS - -div_t -_div( int numer, int denom ) -{ - div_t result; - - CYG_REPORT_FUNCNAMETYPE( "_div", "quotient: %d"); - CYG_REPORT_FUNCARG2DV( numer, denom ); - - // 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. - // - // 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'. - // - // If both are num and denom are positive, r will always - // be positive. - // - // 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. - - result.quot = numer / denom; - result.rem = numer % denom; - - if ( (numer >= 0) && (result.rem < 0) ) - { - result.quot++; - result.rem -= denom; - } // if - - CYG_REPORT_RETVAL( result.quot ); - - return result; -} // _div() - -#endif // ifdef CYGPKG_LIBC - // EOF div.cxx
