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 enum real eulersGamma = 0.57721566490153286060651L; 393 394 395 real sinc(real x) 396 { 397 if(abs(x) < 1E-2){ 398 // From pade approximation of sin(x) 399 // See also: https://en.wikipedia.org/wiki/Pad%C3%A9_approximant 400 401 immutable real[3] numCoefs = [ 402 +1.0L, 403 -2363 / 18183.0L, 404 +12671 / 4363920.0L, 405 ]; 406 407 immutable real[4] denCoefs = [ 408 +1.0L, 409 +445 / 12122.0L, 410 +601 / 872784.0L, 411 +121 / 16662240.0L 412 ]; 413 414 immutable x2 = x^^2; 415 return poly(x2, numCoefs) / poly(x2, denCoefs); 416 } 417 418 return sin(x)/x; 419 } 420 421 422 /** 423 See also: https://en.wikipedia.org/wiki/Trigonometric_integral 424 */ 425 real triIntSi(real x) 426 { 427 if(x < 0){ 428 return triIntSi(-x)*-1; 429 } 430 431 if(x <= 4){ 432 immutable real[8] numCoefs = [ 433 +1, 434 -4.54393409816329991e-2L, 435 +1.15457225751016682e-3L, 436 -1.41018536821330254e-5L, 437 +9.43280809438713025e-8L, 438 -3.53201978997168357e-10L, 439 +7.08240282274875911e-13L, 440 -6.05338212010422477e-16L 441 ]; 442 443 immutable real[7] denCoefs = [ 444 +1, 445 +1.01162145739225565e-2L, 446 +4.99175116169755106e-5L, 447 +1.55654986308745614e-7L, 448 +3.28067571055789734e-10L, 449 +4.5049097575386581e-13L, 450 +3.21107051193712168e-16L, 451 ]; 452 453 immutable real x2 = x^^2; 454 455 return x * (poly(x2, numCoefs) / poly(x2, denCoefs)); 456 }else{ 457 // For x > 4, 458 immutable fg = fgForTriIntSiCiLargeX(x); 459 460 return PI_2 - fg[0] * cos(x) - fg[1] * sin(x); 461 } 462 } 463 464 465 /// 466 real triIntCi(real x) 467 { 468 if(x < 0){ 469 return triIntCi(-x); 470 } 471 472 473 if(x <= 4){ 474 immutable real[7] numCoefs = [ 475 -0.25L, 476 +7.51851524438898291e-3L, 477 -1.27528342240267686e-4L, 478 +1.05297363846239184e-6L, 479 -4.68889508144848019e-9L, 480 +1.06480802891189243e-11L, 481 -9.93728488857585407e-15L, 482 ]; 483 484 immutable real[8] denCoefs = [ 485 +1, 486 +1.1592605689110735e-2L, 487 +6.72126800814254432e-5L, 488 +2.55533277086129636e-7L, 489 +6.97071295760958946e-10L, 490 +1.38536352772778619e-12L, 491 +1.89106054713059759e-15L, 492 +1.39759616731376855e-18L, 493 ]; 494 495 immutable real x2 = x^^2; 496 497 return eulersGamma + log(x) + x2 * (poly(x2, numCoefs) / poly(x2, denCoefs)); 498 }else{ 499 // For x > 4: 500 501 immutable fg = fgForTriIntSiCiLargeX(x); 502 return fg[0] * sin(x) - fg[1] * cos(x); 503 } 504 } 505 506 507 private 508 real[2] fgForTriIntSiCiLargeX(real x) 509 { 510 immutable real xm1 = 1/x; 511 immutable real xm2 = xm1^^2; 512 513 immutable real[11] numFCoefs = [ 514 +1, 515 +7.44437068161936700618e2L, 516 +1.96396372895146869801e5L, 517 +2.37750310125431834034e7L, 518 +1.43073403821274636888e9L, 519 +4.33736238870432522765e10L, 520 +6.40533830574022022911e11L, 521 +4.20968180571076940208e12L, 522 +1.00795182980368574617e13L, 523 +4.94816688199951963482e12L, 524 -4.94701168645415959931e11L, 525 ]; 526 527 immutable real[10] denFCoefs = [ 528 +1, 529 +7.46437068161927678031e2L, 530 +1.97865247031583951450e5L, 531 +2.41535670165126845144e7L, 532 +1.47478952192985464958e9L, 533 +4.58595115847765779830e10L, 534 +7.08501308149515401563e11L, 535 +5.06084464593475076774e12L, 536 +1.43468549171581016479e13L, 537 +1.11535493509914254097e13L 538 ]; 539 540 immutable real[11] numGCoefs = [ 541 +1, 542 +8.1359520115168615e2L, 543 +2.35239181626478200e5L, 544 +3.12557570795778731e7L, 545 +2.06297595146763354e9L, 546 +6.83052205423625007e10L, 547 +1.09049528450362786e12L, 548 +7.57664583257834349e12L, 549 +1.81004487464664575e13L, 550 +6.43291613143049485e12L, 551 -1.36517137670871689e12L, 552 ]; 553 554 immutable real[10] denGCoefs = [ 555 +1, 556 +8.19595201151451564e2L, 557 +2.40036752835578777e5L, 558 +3.26026661647090822e7L, 559 +2.23355543278099360e9L, 560 +7.87465017341829930e10L, 561 +1.39866710696414565e12L, 562 +1.17164723371736605e13L, 563 +4.01839087307656620e13L, 564 +3.99653257887490811e13L, 565 ]; 566 567 return [ 568 xm1 * poly(xm2, numFCoefs) / poly(xm2, denFCoefs), 569 xm2 * poly(xm2, numGCoefs) / poly(xm2, denGCoefs) 570 ]; 571 } 572 573 574 /* 575 struct Integrator(T) 576 { 577 T value; 578 size_t count; 579 580 581 U average(U = T)() @property 582 { 583 return cast(U)(value) / count; 584 } 585 586 587 Integrator!(typeof(T.init + U.init)) opBinary(string op: "+", U)(U v) 588 { 589 return typeof(return)(value + v, count+1); 590 } 591 592 593 Integrator!(typeof(T.init + U.init)) opBinary(string op: "-", U)(U v) 594 { 595 return typeof(return)(value - v, count-1); 596 } 597 598 599 void opBinaryAssign(string op: "+", U)(U v) 600 { 601 value += v; 602 ++count; 603 } 604 605 606 void opBinaryAssign(string op: "-", U)(U v) 607 { 608 value -= v; 609 --count; 610 } 611 } 612 */