-
Notifications
You must be signed in to change notification settings - Fork 0
/
math.el
107 lines (81 loc) · 2.76 KB
/
math.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
(require 'list)
(defconst math/pi 3.141592653589793)
(defconst math/-pi (- 0 math/pi))
(defconst math/exp 2.718281828459045)
(defun math/abs (number)
"Return absolute value of the NUMBER.
If NUMBER is greater than zero, then the function returns NUMBER,
Else, the function return the converted -NUMBER to `float'"
(if (>= number 0)
number
(- 0.0 number)))
(defvar math/sqrt-tolerance 1e-4
"Fix the maximal aboslute gap between two computations of `math/sqrt-recursive-lisp'")
(defun math/sqrt-recursive-lisp (number &optional tolerance current)
"Return the square root of the NUMBER.
Pure Lisp implementation, using recursively a fixed-point algorithm to solve: x^2=number,
i.e., recursively updates by (/ (+ current number) (+ current 1.0))
until the reached TOLERANCE.
The optionnal parameter TOLERANCE is set by default to `math/sqrt-tolerance'.
CURRENT is by default set to NUMBER.
WARNING:
(see `max-lisp-eval-depth' and `max-specpdl-size')
The number of loop-recursion is limited (see elisp specifications).
Therefore, this function cannot evaluate the square root of number greater
than approximatively (/ max-specpdl-size 3).
It is then recommended to use `math/sqrt' instead."
(let ((cur current)
(tol tolerance)
update)
(when (eq current nil)
(setq cur number))
(when (eq tolerance nil)
(setq tol math/sqrt-tolerance))
(setq update (/ (+ cur number) (+ cur 1.0)))
(if (< (math/abs (- update cur)) tol)
update
(math/sqrt-recursive-lisp number tol update))
))
(defun math/sqrt (number &optional built-in)
"Return the square root of the NUMBER
If NUMBER is greater than (/ max-specpdl-size 3),
then it applies the built-in C function `sqrt',
else it uses the pure lisp implementation `math/sqrt-recursive-lisp'.
If BUILT-IN is not `nil', then `sqrt' is applied for any NUMBER."
(let ((val 0))
(when (eq built-in nil)
(setq val (/ max-specpdl-size 3)))
(if (> number val)
(sqrt number)
(math/sqrt-recursive-lisp number))
))
(defun math/pow (number power &optional accumulate)
(let ((acc accumulate))
(when (eq accumulate nil)
(setq acc 1.0))
(if (<= power 0)
acc
(math/pow number (- power 1) (* number acc)))
))
(defun math/fac (number &optional initial)
(let ((prev initial))
(when (eq initial nil)
(setq prev 1))
(if (<= number 0)
prev
(math/fac (- number 1) (* number prev)))
))
(defun apply-n-times (function n list-args initial)
(if (<= n 0)
initial
(apply-n-times function (- n 1) list-args
(apply function (push<- list-args initial)))
))
(defun math/poww (number power)
(apply-n-times
'(lambda (x y) (* x y))
power
(list number)
1.0
))
(provide 'math)