This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
hv_iterkeysv() actually creates a mortal SV for every call.
[perl5.git] / numeric.c
index 5eafdda..34264f3 100644 (file)
--- a/numeric.c
+++ b/numeric.c
@@ -1,7 +1,7 @@
 /*    numeric.c
  *
  *    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2005 by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -30,6 +30,7 @@ values, including such things as replacements for the OS's atof() function
 U32
 Perl_cast_ulong(pTHX_ NV f)
 {
+    PERL_UNUSED_CONTEXT;
   if (f < 0.0)
     return f < I32_MIN ? (U32) I32_MIN : (U32)(I32) f;
   if (f < U32_MAX_P1) {
@@ -48,6 +49,7 @@ Perl_cast_ulong(pTHX_ NV f)
 I32
 Perl_cast_i32(pTHX_ NV f)
 {
+    PERL_UNUSED_CONTEXT;
   if (f < I32_MAX_P1)
     return f < I32_MIN ? I32_MIN : (I32) f;
   if (f < U32_MAX_P1) {
@@ -66,6 +68,7 @@ Perl_cast_i32(pTHX_ NV f)
 IV
 Perl_cast_iv(pTHX_ NV f)
 {
+    PERL_UNUSED_CONTEXT;
   if (f < IV_MAX_P1)
     return f < IV_MIN ? IV_MIN : (IV) f;
   if (f < UV_MAX_P1) {
@@ -85,6 +88,7 @@ Perl_cast_iv(pTHX_ NV f)
 UV
 Perl_cast_uv(pTHX_ NV f)
 {
+    PERL_UNUSED_CONTEXT;
   if (f < 0.0)
     return f < IV_MIN ? (UV) IV_MIN : (UV)(IV) f;
   if (f < UV_MAX_P1) {
@@ -100,22 +104,6 @@ Perl_cast_uv(pTHX_ NV f)
   return f > 0 ? UV_MAX : 0 /* NaN */;
 }
 
-#if defined(HUGE_VAL) || (defined(USE_LONG_DOUBLE) && defined(HUGE_VALL))
-/*
- * This hack is to force load of "huge" support from libm.a
- * So it is in perl for (say) POSIX to use.
- * Needed for SunOS with Sun's 'acc' for example.
- */
-NV
-Perl_huge(void)
-{
-#   if defined(USE_LONG_DOUBLE) && defined(HUGE_VALL)
-    return HUGE_VALL;
-#   endif
-    return HUGE_VAL;
-}
-#endif
-
 /*
 =for apidoc grok_bin
 
@@ -151,7 +139,7 @@ Perl_grok_bin(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) {
     NV value_nv = 0;
 
     const UV max_div_2 = UV_MAX / 2;
-    const bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
+    const bool allow_underscores = (bool)(*flags & PERL_SCAN_ALLOW_UNDERSCORES);
     bool overflowed = FALSE;
     char bit;
 
@@ -268,7 +256,7 @@ Perl_grok_hex(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) {
     NV value_nv = 0;
 
     const UV max_div_16 = UV_MAX / 16;
-    const bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
+    const bool allow_underscores = (bool)(*flags & PERL_SCAN_ALLOW_UNDERSCORES);
     bool overflowed = FALSE;
 
     if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) {
@@ -382,7 +370,7 @@ Perl_grok_oct(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) {
     NV value_nv = 0;
 
     const UV max_div_8 = UV_MAX / 8;
-    const bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
+    const bool allow_underscores = (bool)(*flags & PERL_SCAN_ALLOW_UNDERSCORES);
     bool overflowed = FALSE;
 
     for (; len-- && *s; s++) {
@@ -514,9 +502,10 @@ bool
 Perl_grok_numeric_radix(pTHX_ const char **sp, const char *send)
 {
 #ifdef USE_LOCALE_NUMERIC
+    dVAR;
     if (PL_numeric_radix_sv && IN_LOCALE) { 
         STRLEN len;
-        const char* radix = SvPV(PL_numeric_radix_sv, len);
+        const char * const radix = SvPV(PL_numeric_radix_sv, len);
         if (*sp + len <= send && memEQ(*sp, radix, len)) {
             *sp += len;
             return TRUE; 
@@ -559,7 +548,7 @@ int
 Perl_grok_number(pTHX_ const char *pv, STRLEN len, UV *valuep)
 {
   const char *s = pv;
-  const char *send = pv + len;
+  const char * const send = pv + len;
   const UV max_div_10 = UV_MAX / 10;
   const char max_mod_10 = UV_MAX % 10;
   int numtype = 0;
@@ -781,7 +770,7 @@ S_mulexp10(NV value, I32 exponent)
 
 #if ((defined(VMS) && !defined(__IEEE_FP)) || defined(_UNICOS)) && defined(NV_MAX_10_EXP)
     STMT_START {
-       NV exp_v = log10(value);
+       const NV exp_v = log10(value);
        if (exponent >= NV_MAX_10_EXP || exponent + exp_v >= NV_MAX_10_EXP)
            return NV_MAX;
        if (exponent < 0) {
@@ -819,6 +808,7 @@ Perl_my_atof(pTHX_ const char* s)
 {
     NV x = 0.0;
 #ifdef USE_LOCALE_NUMERIC
+    dVAR;
     if (PL_numeric_local && IN_LOCALE) {
        NV y;
 
@@ -897,7 +887,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
 
 #ifdef HAS_STRTOD
     if (*s == 'n' || *s == 'N' || *s == 'i' || *s == 'I') {
-        char *p = negative ? s-1 : s;
+        const char *p = negative ? s - 1 : s;
         char *endp;
         NV rslt;
         rslt = strtod(p, &endp);
@@ -963,10 +953,9 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
        else if (!seen_dp && GROK_NUMERIC_RADIX(&s, send)) {
            seen_dp = 1;
            if (sig_digits > MAX_SIG_DIGITS) {
-               ++s;
-               while (isDIGIT(*s)) {
+               do {
                    ++s;
-               }
+               } while (isDIGIT(*s));
                break;
            }
        }
@@ -1034,6 +1023,38 @@ Perl_my_frexpl(long double x, int *e) {
 #endif
 
 /*
+=for apidoc Perl_signbit
+
+Return a non-zero integer if the sign bit on an NV is set, and 0 if
+it is not.  
+
+If Configure detects this system has a signbit() that will work with
+our NVs, then we just use it via the #define in perl.h.  Otherwise,
+fall back on this implementation.  As a first pass, this gets everything
+right except -0.0.  Alas, catching -0.0 is the main use for this function,
+so this is not too helpful yet.  Still, at least we have the scaffolding
+in place to support other systems, should that prove useful.
+
+
+Configure notes:  This function is called 'Perl_signbit' instead of a
+plain 'signbit' because it is easy to imagine a system having a signbit()
+function or macro that doesn't happen to work with our particular choice
+of NVs.  We shouldn't just re-#define signbit as Perl_signbit and expect
+the standard system headers to be happy.  Also, this is a no-context
+function (no pTHX_) because Perl_signbit() is usually re-#defined in
+perl.h as a simple macro call to the system's signbit().
+Users should just always call Perl_signbit().
+
+=cut
+*/
+#if !defined(HAS_SIGNBIT)
+int
+Perl_signbit(NV x) {
+    return (x < 0.0) ? 1 : 0;
+}
+#endif
+
+/*
  * Local variables:
  * c-indentation-style: bsd
  * c-basic-offset: 4