1 // Written in the D programming language. 2 /* 3 NYSL Version 0.9982 4 5 A. This software is "Everyone'sWare". It means: 6 Anybody who has this software can use it as if he/she is 7 the author. 8 9 A-1. Freeware. No fee is required. 10 A-2. You can freely redistribute this software. 11 A-3. You can freely modify this software. And the source 12 may be used in any software with no limitation. 13 A-4. When you release a modified version to public, you 14 must publish it with your name. 15 16 B. The author is not responsible for any kind of damages or loss 17 while using or misusing this software, which is distributed 18 "AS IS". No warranty of any kind is expressed or implied. 19 You use AT YOUR OWN RISK. 20 21 C. Copyrighted to Kazuki KOMATSU 22 23 D. Above three clauses are applied both to source and binary 24 form of this software. 25 */ 26 27 /** 28 このモジュールは、標準ライブラリstd.mathの拡張です。 29 */ 30 module carbon.math; 31 32 import std.math; 33 import std.traits; 34 import std.array; 35 import std.range; 36 import std.typecons; 37 38 import core.bitop; 39 40 41 real toDeg(real rad) pure nothrow @safe 42 { 43 return rad / PI * 180; 44 } 45 46 47 real toRad(real deg) pure nothrow @safe 48 { 49 return deg / 180 * PI; 50 } 51 52 53 bool isPowOf2(I)(I n) 54 if(is(typeof(n && (n & (n-1)) == 0 ))) 55 { 56 return n && (n & (n-1)) == 0; 57 } 58 59 unittest{ 60 assert(!0.isPowOf2); 61 assert( 1.isPowOf2); 62 assert( 2.isPowOf2); 63 assert( 4.isPowOf2); 64 assert(!6.isPowOf2); 65 assert( 8.isPowOf2); 66 assert(!9.isPowOf2); 67 assert(!10.isPowOf2); 68 } 69 70 71 /** 72 nextが1である場合に、next2Pow(num)はnumより大きく、かつ、最小の2の累乗数を返します。 73 74 もし、nextが0であれば、next2Powはnumより小さく、かつ、最大の2の累乗数を返します。 75 nextがm > 1の場合には、next2Pow(num, m)は、next2Pow(num) << (m - 1)を返します。 76 */ 77 size_t nextPowOf2(T)(T num, size_t next = 1) 78 if(isIntegral!T) 79 in{ 80 assert(num >= 1); 81 } 82 body{ 83 static size_t castToSize_t(X)(X value) 84 { 85 static if(is(X : size_t)) 86 return value; 87 else 88 return value.to!size_t(); 89 } 90 91 return (cast(size_t)1) << (bsr(castToSize_t(num)) + next); 92 } 93 94 /// 95 pure nothrow @safe unittest{ 96 assert(nextPowOf2(10) == 16); // デフォルトではnext = 1なので、次の2の累乗数を返す 97 assert(nextPowOf2(10, 0) == 8); // next = 0だと、前の2の累乗数を返す 98 assert(nextPowOf2(10, 2) == 32); // next = 2なので、next2Pow(10) << 1を返す。 99 } 100 101 102 /// ditto 103 F nextPowOf2(F)(F num, size_t next = 1) 104 if(isFloatingPoint!F) 105 in{ 106 assert(num >= 1); 107 } 108 body{ 109 int n = void; 110 frexp(num, n); 111 return (cast(F)2.0) ^^ (n + next - 1); 112 } 113 114 /// 115 pure nothrow @safe unittest{ 116 assert(nextPowOf2(10.0) == 16.0); 117 assert(nextPowOf2(10.0, 0) == 8.0); 118 assert(nextPowOf2(10.0, 2) == 32.0); 119 } 120 121 122 /** 123 numより小さく、かつ最大の2の累乗を返します。 124 125 nextPowOf2(num, 0)に等価です 126 */ 127 auto previousPowOf2(T)(T num) 128 { 129 return nextPowOf2(num, 0); 130 } 131 132 133 T sqrtFloor(T, F)(F x) 134 if(isFloatingPoint!F) 135 { 136 return cast(T)(sqrt(x)); 137 } 138 139 140 T sqrtCeil(T, F)(F x) 141 if(isFloatingPoint!F) 142 { 143 return cast(T)(sqrt(x).ceil()); 144 } 145 146 147 T lcm(T)(T x, T y) 148 { 149 return x * (y / gcd(x, y)); 150 } 151 152 153 pure bool isPrime(T)(T src)if(__traits(isIntegral,T)){ 154 if(src <= 1)return false; 155 else if(src < 4)return true; 156 else if(!(src&1))return false; 157 else if(((src+1)%6) && ((src-1)%6))return false; 158 159 T root = cast(T)sqrt(cast(real)src) + 1; 160 161 for(T i = 5; i < root; i += 6) 162 if(!((src%i) && ((src)%(i+2)))) 163 return false; 164 165 return true; 166 } 167 168 169 void primeFactors(T, R)(T n, ref R or) 170 if(isOutputRange!(R, Tuple!(T, uint))) 171 { 172 alias E = Tuple!(T, uint); 173 174 if(n < 0){ 175 primeFactors(-n, or); 176 return; 177 } 178 179 if(n <= 1){ 180 return; 181 } 182 183 import core.bitop; 184 185 static if(is(T == long) || is(T == ulong)) 186 { 187 { 188 uint cnt; 189 immutable uint lns = n & uint.max; 190 if(auto c = bsf(lns)) 191 cnt = c; 192 else if(lns == 0) 193 cnt = bsf(cast(uint)(n >> 32)) + 32; 194 195 if(cnt){ 196 put(or, E(2, cnt)); 197 n >>= cnt; 198 } 199 } 200 } 201 else 202 { 203 if(auto cnt = bsf(n)){ 204 put(or, E(2, cnt)); 205 n >>= cnt; 206 } 207 } 208 209 if(isPrime(n)){ 210 put(or, E(n, 1)); 211 return; 212 } 213 214 // Fermat's method 215 { 216 T x = cast(T)sqrt(cast(real)n), 217 y = 0; 218 219 T diff = x^^2 - n; 220 { 221 T cnt = 3; 222 bool sw; 223 while(diff != 0){ 224 if(n % cnt == 0){ 225 // p = n / cnt, q = cnt 226 auto p = n / cnt; 227 x = (p + cnt) / 2; 228 y = (p - cnt) / 2; 229 diff = 0; 230 break; 231 } 232 cnt += 2; 233 234 if(diff < 0){ 235 diff += 2*x + 1; 236 ++x; 237 }else if(!sw && diff > 2*y+1){ 238 auto m = cast(T)ceil(sqrt((cast(real)y)^^2 + diff) - y); 239 diff -= m * (m + 2 * y); 240 y += m; 241 }else{ 242 sw = true; 243 diff -= 2*y + 1; 244 ++y; 245 } 246 } 247 } 248 249 T p = x + y, 250 q = x - y; 251 252 if(p == q){ 253 auto dlg = (E e){ 254 e[1] *= 2; 255 put(or, e); 256 }; 257 258 primeFactors(p, dlg); 259 return; 260 } 261 262 if(isPrime(q)){ 263 uint c = 1; 264 while(p % q == 0){ 265 p /= q; 266 ++c; 267 } 268 269 put(or, E(q, c)); 270 }else{ 271 { 272 auto dlg = (E e){ 273 while(p % e[0] == 0){ 274 p /= e[0]; 275 ++e[1]; 276 } 277 278 put(or, e); 279 }; 280 281 primeFactors(q, dlg); 282 } 283 } 284 285 primeFactors(p, or); 286 } 287 } 288 289 290 Tuple!(T, uint)[] primeFactors(T)(T n) 291 { 292 auto app = appender!(typeof(return))(); 293 primeFactors(n, app); 294 return app.data; 295 } 296 297 298 unittest 299 { 300 foreach(n; 2 .. 100000){ 301 ulong m = 1; 302 foreach(ps; primeFactors(n)) 303 m *= ps[0] ^^ ps[1]; 304 305 assert(m == n); 306 } 307 308 foreach(n; 10_000_000L .. 10_001_000L){ 309 ulong m = 1; 310 foreach(ps; primeFactors(n)) 311 m *= ps[0] ^^ ps[1]; 312 313 assert(m == n); 314 } 315 } 316 317 318 void primeFactorsSimple(T, R)(T n, ref R or) 319 if(isOutputRange!(R, Tuple!(T, uint))) 320 { 321 alias E = Tuple!(T, uint); 322 T m = 2; 323 while(n != 1){ 324 if(isPrime(n)){ 325 put(or, E(n, 1)); 326 return; 327 } 328 329 uint c; 330 while(n % m == 0){ 331 n /= m; 332 ++c; 333 } 334 335 if(c) put(or, E(m, c)); 336 ++m; 337 } 338 } 339 340 341 Tuple!(T, uint)[] primeFactorsSimple(T)(T n) 342 { 343 auto app = appender!(typeof(return))(); 344 primeFactorsSimple(n, app); 345 return app.data; 346 } 347 348 349 unittest 350 { 351 foreach(n; 2 .. 100000){ 352 ulong m = 1; 353 foreach(ps; primeFactorsSimple(n)) 354 m *= ps[0] ^^ ps[1]; 355 356 assert(m == n); 357 } 358 359 foreach(n; 10_000_000L .. 10_001_000L){ 360 ulong m = 1; 361 foreach(ps; primeFactorsSimple(n)) 362 m *= ps[0] ^^ ps[1]; 363 364 assert(m == n); 365 } 366 } 367 368 369 struct Imaginary(T) 370 { 371 E im; 372 373 E re() const @property { return 0; } 374 375 Imaginary!(CommonType!(T, U)) opBinary(string op: "+", U)(Imaginary!U rhs) const { return typeof(return)(im + rhs.im); } 376 } 377 378 379 C complexZero(C)() @property 380 { 381 static if(is(C == creal) || is(C == cdouble) || is(C == cfloat)) 382 { 383 C zero = 0+0i; 384 return zero; 385 } 386 else 387 return C(0, 0); 388 } 389 390 391 /* 392 struct Integrator(T) 393 { 394 T value; 395 size_t count; 396 397 398 U average(U = T)() @property 399 { 400 return cast(U)(value) / count; 401 } 402 403 404 Integrator!(typeof(T.init + U.init)) opBinary(string op: "+", U)(U v) 405 { 406 return typeof(return)(value + v, count+1); 407 } 408 409 410 Integrator!(typeof(T.init + U.init)) opBinary(string op: "-", U)(U v) 411 { 412 return typeof(return)(value - v, count-1); 413 } 414 415 416 void opBinaryAssign(string op: "+", U)(U v) 417 { 418 value += v; 419 ++count; 420 } 421 422 423 void opBinaryAssign(string op: "-", U)(U v) 424 { 425 value -= v; 426 --count; 427 } 428 } 429 */