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