[Top][All Lists]
[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
- [Gnash-commit] gnash/server/asobj Number.cpp,
Martin Guy <=