gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash/server/asobj Number.cpp


From: Martin Guy
Subject: [Gnash-commit] gnash/server/asobj Number.cpp
Date: Tue, 06 Feb 2007 18:02:52 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Martin Guy <martinwguy> 07/02/06 18:02:52

Modified files:
        server/asobj   : Number.cpp 

Log message:
        onvert numbers to strings the same way as a certain commercial Flash 
Player:
        a modified "%.15g".

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Number.cpp?cvsroot=gnash&r1=1.11&r2=1.12

Patches:
Index: Number.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Number.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- Number.cpp  1 Feb 2007 13:40:08 -0000       1.11
+++ Number.cpp  6 Feb 2007 18:02:52 -0000       1.12
@@ -2,9 +2,7 @@
 //   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
+// it under the terms of the GNU 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
@@ -18,10 +16,11 @@
 //
 //
 
-/* $Id: Number.cpp,v 1.11 2007/02/01 13:40:08 strk Exp $ */
+/* $Id: Number.cpp,v 1.12 2007/02/06 18:02:52 martinwguy Exp $ */
 
 // Implementation of ActionScript Number class.
 
+#include "log.h"
 #include "tu_config.h"
 #include "Number.h"
 #include "smart_ptr.h"
@@ -81,7 +80,132 @@
                as_object(getNumberInterface()),
                _val(val)
        {
-               sprintf(_str, "%g", _val);
+               // Printing formats:
+               //
+               // If _val > 1, Print up to 15 significant digits, then switch
+               // to scientific notation, rounding at the last place and
+               // omitting trailing zeroes.
+               // e.g. for 9*.1234567890123456789
+               // ...
+               // 9999.12345678901
+               // 99999.123456789
+               // 999999.123456789
+               // 9999999.12345679
+               // 99999999.1234568
+               // 999999999.123457
+               // 9999999999.12346
+               // 99999999999.1235
+               // 999999999999.123
+               // 9999999999999.12
+               // 99999999999999.1
+               // 999999999999999
+               // 1e+16
+               // 1e+17
+               // ...
+               // e.g. for 1*.111111111111111111111111111111111111
+               // ...
+               // 1111111111111.11
+               // 11111111111111.1
+               // 111111111111111
+               // 1.11111111111111e+15
+               // 1.11111111111111e+16
+               // ...
+               // For values < 1, print up to 4 leading zeroes after the
+               // deciman point, then switch to scientific notation with up
+               // to 15 significant digits, rounding with no trailing zeroes
+               // e.g. for 1.234567890123456789 * 10^-i:
+               // 1.23456789012346
+               // 0.123456789012346
+               // 0.0123456789012346
+               // 0.00123456789012346
+               // 0.000123456789012346
+               // 0.0000123456789012346
+               // 0.00000123456789012346
+               // 1.23456789012346e-6
+               // 1.23456789012346e-7
+               // ...
+               //
+               // If the value is negative, just add a '-' to the start; this
+               // does not affect the precision of the printed value.
+               //
+               // This almost corresponds to printf("%.15g") format, except
+               // that %.15g switches to scientific notation at e-05 not e-06,
+               // and %g always prints at least two digits for the exponent.
+
+               // The following code gives the same results as Adobe player
+               // except for
+               // 9.99999999999999[39-61] e{-2,-3}. Adobe prints these as
+               // 0.0999999999999999 and 0.00999999999999 while we print them
+               // as 0.1 and 0.01
+               // These values are at the limit of a double's precision,
+               // for example, in C,
+               // .99999999999999938 printfs as
+               // .99999999999999933387 and
+               // .99999999999999939 printfs as
+               // .99999999999999944489
+               // so this behaviour is probably too compiler-dependent to
+               // reproduce exactly.
+               //
+               // There may be some milage in comparing against
+               // 0.00009999999999999995 and
+               // 0.000009999999999999995 instead.
+
+               if (std::fabs(_val) >= 0.0001 ||
+                   std::fabs(_val) < 0.00001) {
+                       char *cp;
+
+                       sprintf(_str, "%.15g", _val);
+                       // Remove a leading zero from 2-digit exponent if any
+                       if ((cp = strchr(_str, 'e')) != NULL &&
+                           cp[2] == '0') {
+                               // We can't use strcpy() cos its src&dest can't
+                               // overlap. However, this can only be "...e+0n"
+                               // or ...e-0n;  3+digit exponents never have
+                               // leading 0s.
+                               cp[2] = cp[3]; cp[3] = '\0';
+                       }
+               } else {
+                       // This is the range for which %.15g gives scientific
+                       // notation but for which we must give decimal.
+                       // We can't easily use %f bcos it prints a fixed number
+                       // of digits after the point, not the maximum number of
+                       // significant digits with trailing zeroes removed that
+                       // we require. So we just get %g to do its non-e stuff
+                       // by multiplying the value by ten and then stuffing
+                       // an extra zero into the result after the decimal
+                       // point. Yuk!
+                       char *cp;
+                       
+                       sprintf(_str, "%.15g", _val * 10.0);
+                       if ((cp = strchr(_str, '.')) == NULL || cp[1] != '0') {
+                               log_error("Internal error: cannot find \".0\" 
in %s for %.15g\n", _str, _val);
+                               // Just give it to them raw instead
+                               sprintf(_str, "%.15g", _val);
+                       } else {
+#if HAVE_MEMMOVE
+                               // Shunt the digits right one place after the
+                               // decimal point.
+                               memmove(cp+2, cp+1, strlen(cp+1)+1);
+#else
+                               // We can't use strcpy() cos the args overlap.
+
+                               char c; // character being moved forward
+                               
+                               // At this point, cp points at the '.'
+                               //
+                               // In the loop body it points at where we pick
+                               // up the next char to move forward and where
+                               // we drop the one we picked up on its left.
+                               // We stop when we have just picked up the \0.
+                               for (c = '0', cp++; c != '\0'; cp++) {
+                                       char tmp = *cp; *cp = c; c = tmp;
+                               }
+                               // Store the '\0' we just picked up
+                               *cp = c;
+#endif
+                       }
+                       
+               }
        }
 
        // override from as_object




reply via email to

[Prev in Thread] Current Thread [Next in Thread]