OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 // Patch file for dart:math library. | |
6 import 'dart:_foreign_helper' show JS; | |
7 import 'dart:_js_helper' show patch, checkNum; | |
8 | |
9 @patch | |
10 double sqrt(num x) | |
11 => JS('double', r'Math.sqrt(#)', checkNum(x)); | |
12 | |
13 @patch | |
14 double sin(num x) | |
15 => JS('double', r'Math.sin(#)', checkNum(x)); | |
16 | |
17 @patch | |
18 double cos(num x) | |
19 => JS('double', r'Math.cos(#)', checkNum(x)); | |
20 | |
21 @patch | |
22 double tan(num x) | |
23 => JS('double', r'Math.tan(#)', checkNum(x)); | |
24 | |
25 @patch | |
26 double acos(num x) | |
27 => JS('double', r'Math.acos(#)', checkNum(x)); | |
28 | |
29 @patch | |
30 double asin(num x) | |
31 => JS('double', r'Math.asin(#)', checkNum(x)); | |
32 | |
33 @patch | |
34 double atan(num x) | |
35 => JS('double', r'Math.atan(#)', checkNum(x)); | |
36 | |
37 @patch | |
38 double atan2(num a, num b) | |
39 => JS('double', r'Math.atan2(#, #)', checkNum(a), checkNum(b)); | |
40 | |
41 @patch | |
42 double exp(num x) | |
43 => JS('double', r'Math.exp(#)', checkNum(x)); | |
44 | |
45 @patch | |
46 double log(num x) | |
47 => JS('double', r'Math.log(#)', checkNum(x)); | |
48 | |
49 @patch | |
50 num pow(num x, num exponent) { | |
51 checkNum(x); | |
52 checkNum(exponent); | |
53 return JS('num', r'Math.pow(#, #)', x, exponent); | |
54 } | |
55 | |
56 const int _POW2_32 = 0x100000000; | |
57 | |
58 @patch | |
59 class Random { | |
60 @patch | |
61 factory Random([int seed]) => | |
62 (seed == null) ? const _JSRandom() : new _Random(seed); | |
63 } | |
64 | |
65 class _JSRandom implements Random { | |
66 // The Dart2JS implementation of Random doesn't use a seed. | |
67 const _JSRandom(); | |
68 | |
69 int nextInt(int max) { | |
70 if (max <= 0 || max > _POW2_32) { | |
71 throw new RangeError("max must be in range 0 < max ≤ 2^32, was $max"); | |
72 } | |
73 return JS("int", "(Math.random() * #) >>> 0", max); | |
74 } | |
75 | |
76 /** | |
77 * Generates a positive random floating point value uniformly distributed on | |
78 * the range from 0.0, inclusive, to 1.0, exclusive. | |
79 */ | |
80 double nextDouble() => JS("double", "Math.random()"); | |
81 | |
82 /** | |
83 * Generates a random boolean value. | |
84 */ | |
85 bool nextBool() => JS("bool", "Math.random() < 0.5"); | |
86 } | |
87 | |
88 | |
89 class _Random implements Random { | |
90 // Constants used by the algorithm or masking. | |
91 static const double _POW2_53_D = 1.0 * (0x20000000000000); | |
92 static const double _POW2_27_D = 1.0 * (1 << 27); | |
93 static const int _MASK32 = 0xFFFFFFFF; | |
94 | |
95 // State comprised of two unsigned 32 bit integers. | |
96 int _lo = 0; | |
97 int _hi = 0; | |
98 | |
99 // Implements: | |
100 // uint64_t hash = 0; | |
101 // do { | |
102 // hash = hash * 1037 ^ mix64((uint64_t)seed); | |
103 // seed >>= 64; | |
104 // } while (seed != 0 && seed != -1); // Limits for pos/neg seed. | |
105 // if (hash == 0) { | |
106 // hash = 0x5A17; | |
107 // } | |
108 // _lo = hash & _MASK_32; | |
109 // _hi = hash >> 32; | |
110 // and then does four _nextState calls to shuffle bits around. | |
111 _Random(int seed) { | |
112 int empty_seed = 0; | |
113 if (seed < 0) { | |
114 empty_seed = -1; | |
115 } | |
116 do { | |
117 int low = seed & _MASK32; | |
118 seed = (seed - low) ~/ _POW2_32; | |
119 int high = seed & _MASK32; | |
120 seed = (seed - high) ~/ _POW2_32; | |
121 | |
122 // Thomas Wang's 64-bit mix function. | |
123 // http://www.concentric.net/~Ttwang/tech/inthash.htm | |
124 // via. http://web.archive.org/web/20071223173210/http://www.concentric.ne
t/~Ttwang/tech/inthash.htm | |
125 | |
126 // key = ~key + (key << 21); | |
127 int tmplow = low << 21; | |
128 int tmphigh = (high << 21) | (low >> 11); | |
129 tmplow = (~low & _MASK32) + tmplow; | |
130 low = tmplow & _MASK32; | |
131 high = (~high + tmphigh + ((tmplow - low) ~/ 0x100000000)) & _MASK32; | |
132 // key = key ^ (key >> 24). | |
133 tmphigh = high >> 24; | |
134 tmplow = (low >> 24) | (high << 8); | |
135 low ^= tmplow; | |
136 high ^= tmphigh; | |
137 // key = key * 265 | |
138 tmplow = low * 265; | |
139 low = tmplow & _MASK32; | |
140 high = (high * 265 + (tmplow - low) ~/ 0x100000000) & _MASK32; | |
141 // key = key ^ (key >> 14); | |
142 tmphigh = high >> 14; | |
143 tmplow = (low >> 14) | (high << 18); | |
144 low ^= tmplow; | |
145 high ^= tmphigh; | |
146 // key = key * 21 | |
147 tmplow = low * 21; | |
148 low = tmplow & _MASK32; | |
149 high = (high * 21 + (tmplow - low) ~/ 0x100000000) & _MASK32; | |
150 // key = key ^ (key >> 28). | |
151 tmphigh = high >> 28; | |
152 tmplow = (low >> 28) | (high << 4); | |
153 low ^= tmplow; | |
154 high ^= tmphigh; | |
155 // key = key + (key << 31); | |
156 tmplow = low << 31; | |
157 tmphigh = (high << 31) | (low >> 1); | |
158 tmplow += low; | |
159 low = tmplow & _MASK32; | |
160 high = (high + tmphigh + (tmplow - low) ~/ 0x100000000) & _MASK32; | |
161 // Mix end. | |
162 | |
163 // seed = seed * 1037 ^ key; | |
164 tmplow = _lo * 1037; | |
165 _lo = tmplow & _MASK32; | |
166 _hi = (_hi * 1037 + (tmplow - _lo) ~/ 0x100000000) & _MASK32; | |
167 _lo ^= low; | |
168 _hi ^= high; | |
169 } while (seed != empty_seed); | |
170 | |
171 if (_hi == 0 && _lo == 0) { | |
172 _lo = 0x5A17; | |
173 } | |
174 _nextState(); | |
175 _nextState(); | |
176 _nextState(); | |
177 _nextState(); | |
178 } | |
179 | |
180 // The algorithm used here is Multiply with Carry (MWC) with a Base b = 2^32. | |
181 // http://en.wikipedia.org/wiki/Multiply-with-carry | |
182 // The constant A (0xFFFFDA61) is selected from "Numerical Recipes 3rd | |
183 // Edition" p.348 B1. | |
184 | |
185 // Implements: | |
186 // var state = (A * _lo + _hi) & _MASK_64; | |
187 // _lo = state & _MASK_32; | |
188 // _hi = state >> 32; | |
189 void _nextState() { | |
190 // Simulate (0xFFFFDA61 * lo + hi) without overflowing 53 bits. | |
191 int tmpHi = 0xFFFF0000 * _lo; // At most 48 bits of significant result. | |
192 int tmpHiLo = tmpHi & _MASK32; // Get the lower 32 bits. | |
193 int tmpHiHi = tmpHi - tmpHiLo; // And just the upper 32 bits. | |
194 int tmpLo = 0xDA61 * _lo; | |
195 int tmpLoLo = tmpLo & _MASK32; | |
196 int tmpLoHi = tmpLo - tmpLoLo; | |
197 | |
198 int newLo = tmpLoLo + tmpHiLo + _hi; | |
199 _lo = newLo & _MASK32; | |
200 int newLoHi = newLo - _lo; | |
201 _hi = ((tmpLoHi + tmpHiHi + newLoHi) ~/ _POW2_32) & _MASK32; | |
202 assert(_lo < _POW2_32); | |
203 assert(_hi < _POW2_32); | |
204 } | |
205 | |
206 int nextInt(int max) { | |
207 if (max <= 0 || max > _POW2_32) { | |
208 throw new RangeError("max must be in range 0 < max ≤ 2^32, was $max"); | |
209 } | |
210 if ((max & (max - 1)) == 0) { | |
211 // Fast case for powers of two. | |
212 _nextState(); | |
213 return _lo & (max - 1); | |
214 } | |
215 | |
216 int rnd32; | |
217 int result; | |
218 do { | |
219 _nextState(); | |
220 rnd32 = _lo; | |
221 result = rnd32.remainder(max); // % max; | |
222 } while ((rnd32 - result + max) >= _POW2_32); | |
223 return result; | |
224 } | |
225 | |
226 double nextDouble() { | |
227 _nextState(); | |
228 int bits26 = _lo & ((1 << 26) - 1); | |
229 _nextState(); | |
230 int bits27 = _lo & ((1 << 27) - 1); | |
231 return (bits26 * _POW2_27_D + bits27) / _POW2_53_D; | |
232 } | |
233 | |
234 bool nextBool() { | |
235 _nextState(); | |
236 return (_lo & 1) == 0; | |
237 } | |
238 } | |
OLD | NEW |