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