2005-11-24 Chris Toshok <toshok@ximian.com>
[mono.git] / mcs / class / Microsoft.JScript / Microsoft.JScript / NumberPrototype.cs
1 //
2 // NumberPrototype.cs:
3 //
4 // Author:
5 //      Cesar Lopez Nataren (cesar@ciencias.unam.mx)
6 //
7 // (C) 2003, Cesar Lopez Nataren
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Text;
33 using System.Globalization;
34
35 namespace Microsoft.JScript {
36
37         public class NumberPrototype : NumberObject {
38
39                 internal static NumberPrototype Proto = new NumberPrototype ();
40
41                 public static NumberConstructor constructor {
42                         get { return NumberConstructor.Ctr; }
43                 }
44
45                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_toExponential)]
46                 public static string toExponential (object thisObj, object fractionDigits)
47                 {
48                         throw new NotImplementedException ();
49                 }
50
51                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_toFixed)]
52                 public static string toFixed (object thisObj, double fractionDigits)
53                 {
54                         if (!Convert.IsNumber (thisObj))
55                                 throw new JScriptException (JSError.NumberExpected);
56
57                         double value = Convert.ToNumber (thisObj);
58                         int prec = Convert.ToInt32 (fractionDigits);
59
60                         if (prec < 0 || prec > 21)
61                                 throw new JScriptException (JSError.PrecisionOutOfRange);
62
63                         return value.ToString ("F" + prec, CultureInfo.InvariantCulture);
64                 }
65
66                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_toLocaleString)]
67                 public static string toLocaleString (object thisObj)
68                 {
69                         if (!Convert.IsNumber (thisObj))
70                                 throw new JScriptException (JSError.NumberExpected);
71                         else
72                                 return Convert.ToNumber (thisObj).ToString ("N");
73                 }
74
75                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_toPrecision)]
76                 public static string toPrecision (object thisObj, object precision)
77                 {
78                         throw new NotImplementedException ();
79                 }
80
81                 internal static char [] Digits = new char [] {
82                         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
83                         'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
84                         'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
85                         'u', 'v', 'w', 'x', 'y', 'z'
86                 };
87
88
89                 //
90                 // We aren't 100% compatible to MS JS.NET here, because we sometimes produce slightly more
91                 // of the fractional digits. This shouldn't cause any trouble.
92                 //
93                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_toString)]
94                 public static string toString (object thisObj, object radix)
95                 {
96                         if (!Convert.IsNumber (thisObj))
97                                 throw new JScriptException (JSError.NumberExpected);
98
99                         double value = Convert.ToNumber (thisObj);
100
101                         if (Double.IsNaN (value))
102                                 return "NaN";
103                         else if (Double.IsPositiveInfinity (value))
104                                 return "Infinity";
105                         else if (Double.IsNegativeInfinity (value))
106                                 return "-Infinity";
107                         
108                         int _radix = 10;
109                         if (radix != null) {
110                                 _radix = Convert.ToInt32 (radix);
111                                 if (_radix < 2)
112                                         _radix = 10;
113                                 else if (_radix > Digits.Length)
114                                         _radix = 10;
115                         }
116                         if (_radix == 10)
117                                 return value.ToString (CultureInfo.InvariantCulture);
118
119                         string result = "";
120                         bool negative = false;
121                         if (value < 0) {
122                                 negative = true;
123                                 value = Math.Abs (value);
124                         }
125
126                         long whole = (long) value;
127                         double frac = value - whole;
128                         long digit;
129
130                         while (whole >= 1) {
131                                 whole = Math.DivRem (whole, _radix, out digit);
132                                 result = Digits [digit] + result;
133                         }
134
135                         if (result.Length == 0)
136                                 result = "0";
137
138                         int frac_digits = _radix;
139                         string frac_buf = "";
140                         bool has_frac = false;
141
142                         while (frac != 0 && frac_digits < 50) {
143                                 frac *= _radix;
144                                 digit = (long) frac;
145                                 frac -= digit;
146
147                                 if (digit == 0)
148                                         frac_buf += "0";
149                                 else {
150                                         if (!has_frac) result += ".";
151                                         result += frac_buf + Digits [digit];
152                                         frac_buf = "";
153                                         has_frac = true;
154                                 }
155
156                                 frac_digits++;
157                         }
158
159                         if (negative)
160                                 return "-" + result;
161                         else
162                                 return result;
163                 }
164
165                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_valueOf)]
166                 public static object valueOf (object thisObj)
167                 {
168                         if (!Convert.IsNumber (thisObj))
169                                 throw new JScriptException (JSError.NumberExpected);
170                         else
171                                 return Convert.ToNumber (thisObj);
172                 }
173         }
174 }