1 /* This file is part of the Amalthea library.
2  *
3  * Copyright (C) 2019, 2021 Eugene 'Vindex' Stulin
4  *
5  * Distributed under the Boost Software License 1.0 or (at your option)
6  * the GNU Lesser General Public License 3.0 or later.
7  */
8 
9 module amalthea.math;
10 
11 unittest {
12     assert(0 == gcd(0, 0));
13     assert(gcd(4, 0) == 4 && 4 == gcd(0, 4));
14     assert(gcd(1, 1) == 1);
15     assert(gcd(1, 0) == 1 && gcd(0, 1) == 1);
16     assert(gcd(1, 2) == 1 && gcd(2, 1) == 1);
17     assert(gcd(70, 105) == 35 && gcd(105, 70) == 35);
18 }
19 /*******************************************************************************
20  * Greatest common divisor.
21  */
22 ulong gcd(ulong a, ulong b) {
23     if (a == 0) {
24         return b;
25     }
26     if (b == 0) {
27         return a;
28     }
29     while (a != b) {
30         if (a > b) {
31             a -= b;
32         } else {
33             b -= a;
34         }
35     }
36     return a;
37 }
38 
39 
40 /*******************************************************************************
41  * Least common multiple.
42  */
43 ulong lcm(ulong a, ulong b) {
44     return a*b / gcd(a, b);
45 }
46 
47 
48 /*******************************************************************************
49  * This function checks if a number is prime.
50  */
51 bool isPrimeNumber(ulong n) {
52     if (n < 2) {
53         return false;
54     }
55     for (ulong i = 2; i <= n/2; ++i) {
56         if (n%i == 0) {
57             return false;
58         }
59     }
60     return true;
61 }
62 
63 
64 /*******************************************************************************
65  * Returns generator of Fibonacci numbers.
66  */
67 FibonacciRange!T fibonacci(T=long)()
68 if (is(T : ulong)) {
69 	return FibonacciRange!T();
70 }
71 unittest {
72     import std.range : take;
73     import std.array : array;
74     auto fibSequence = array(take(fibonacci, 8));
75     assert(fibSequence == [1, 1, 2, 3, 5, 8, 13, 21]);
76 }
77 
78 
79 
80 /*******************************************************************************
81  * Range of Fibonacci numbers for the 'fibonacci' function.
82  */
83 struct FibonacciRange(T) if (is(T : ulong)) {
84 private:
85     T prevValue = 0;
86     T currValue = 1;
87 
88 public:
89     @property empty() const {
90         return false;
91     }
92 
93     T popFront() {
94         currValue += prevValue;
95         prevValue = currValue - prevValue;
96         return prevValue;
97     }
98 
99     T front() const {
100         return currValue;
101     }
102 }
103 
104 
105 /*******************************************************************************
106  * Logarithm.
107  */
108 real logarithm(real b, real n) {
109     import std.math : log;
110     return log(b)/log(n);
111 }
112 unittest {
113     assert(logarithm(1024*1024, 1024) == 2);
114 }