1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 /**
6  * Number theory.
7  *
8  * Copyright: Eugene Wissner 2017-2020.
9  * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
10  *                  Mozilla Public License, v. 2.0).
11  * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
12  * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/math/nbtheory.d,
13  *                 tanya/math/nbtheory.d)
14  */
15 module tanya.math.nbtheory;
16 
17 import tanya.meta.trait;
18 import tanya.meta.transform;
19 
20 import core.math : fabs;
21 import std.math : log;
22 
23 /**
24  * Calculates the absolute value of a number.
25  *
26  * Params:
27  *  T = Argument type.
28  *  x = Argument.
29  *
30  * Returns: Absolute value of $(D_PARAM x).
31  */
32 Unqual!T abs(T)(T x)
33 if (isIntegral!T)
34 {
35     static if (isSigned!T)
36     {
37         return x >= 0 ? x : -x;
38     }
39     else
40     {
41         return x;
42     }
43 }
44 
45 ///
46 @nogc nothrow pure @safe unittest
47 {
48     int i = -1;
49     assert(i.abs == 1);
50     static assert(is(typeof(i.abs) == int));
51 
52     uint u = 1;
53     assert(u.abs == 1);
54     static assert(is(typeof(u.abs) == uint));
55 }
56 
57 /// ditto
58 Unqual!T abs(T)(T x)
59 if (isFloatingPoint!T)
60 {
61     return fabs(x);
62 }
63 
64 ///
65 @nogc nothrow pure @safe unittest
66 {
67     float f = -1.64;
68     assert(f.abs == 1.64F);
69     static assert(is(typeof(f.abs) == float));
70 
71     double d = -1.64;
72     assert(d.abs == 1.64);
73     static assert(is(typeof(d.abs) == double));
74 
75     real r = -1.64;
76     assert(r.abs == 1.64L);
77     static assert(is(typeof(r.abs) == real));
78 }
79 
80 /**
81  * Calculates natural logarithm of $(D_PARAM x).
82  *
83  * Params:
84  *  T = Argument type.
85  *  x = Argument.
86  *
87  * Returns: Natural logarithm of $(D_PARAM x).
88  */
89 Unqual!T ln(T)(T x)
90 if (isFloatingPoint!T)
91 {
92     return log(x);
93 }
94 
95 ///
96 @nogc nothrow pure @safe unittest
97 {
98     import tanya.math;
99 
100     assert(isNaN(ln(-7.389f)));
101     assert(isNaN(ln(-7.389)));
102     assert(isNaN(ln(-7.389L)));
103 
104     assert(isInfinity(ln(0.0f)));
105     assert(isInfinity(ln(0.0)));
106     assert(isInfinity(ln(0.0L)));
107 
108     assert(ln(1.0f) == 0.0f);
109     assert(ln(1.0) == 0.0);
110     assert(ln(1.0L) == 0.0L);
111 }