| 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 |