UNPKG

2.48 kBtext/coffeescriptView Raw
1
2
3
4factorial = ->
5 n = 0
6 save()
7 p1 = pop()
8 push(p1)
9 n = pop_integer()
10 if (n < 0 || isNaN(n))
11 push_symbol(FACTORIAL)
12 push(p1)
13 list(2)
14 restore()
15 return
16 bignum_factorial(n)
17 restore()
18
19
20# simplification rules for factorials (m < n)
21#
22# (e + 1) * factorial(e) -> factorial(e + 1)
23#
24# factorial(e) / e -> factorial(e - 1)
25#
26# e / factorial(e) -> 1 / factorial(e - 1)
27#
28# factorial(e + n)
29# ---------------- -> (e + m + 1)(e + m + 2)...(e + n)
30# factorial(e + m)
31#
32# factorial(e + m) 1
33# ---------------- -> --------------------------------
34# factorial(e + n) (e + m + 1)(e + m + 2)...(e + n)
35
36# this function is not actually used, but
37# all these simplifications
38# do happen automatically via simplify
39simplifyfactorials = ->
40 x = 0
41
42 save()
43
44 x = expanding
45 expanding = 0
46
47 p1 = pop()
48
49 if (car(p1) == symbol(ADD))
50 push(zero)
51 p1 = cdr(p1)
52 while (iscons(p1))
53 push(car(p1))
54 simplifyfactorials()
55 add()
56 p1 = cdr(p1)
57 expanding = x
58 restore()
59 return
60
61 if (car(p1) == symbol(MULTIPLY))
62 sfac_product()
63 expanding = x
64 restore()
65 return
66
67 push(p1)
68
69 expanding = x
70 restore()
71
72sfac_product = ->
73 i = 0
74 j = 0
75 n = 0
76
77 s = tos
78
79 p1 = cdr(p1)
80 n = 0
81 while (iscons(p1))
82 push(car(p1))
83 p1 = cdr(p1)
84 n++
85
86 for i in [0...(n - 1)]
87 if (stack[s + i] == symbol(NIL))
88 continue
89 for j in [(i + 1)...n]
90 if (stack[s + j] == symbol(NIL))
91 continue
92 sfac_product_f(s, i, j)
93
94 push(one)
95
96 for i in [0...n]
97 if (stack[s+i] == symbol(NIL))
98 continue
99 push(stack[s+i])
100 multiply()
101
102 p1 = pop()
103
104 moveTos tos - n
105
106 push(p1)
107
108sfac_product_f = (s,a,b) ->
109 i = 0
110 n = 0
111
112 p1 = stack[s + a]
113 p2 = stack[s + b]
114
115 if (ispower(p1))
116 p3 = caddr(p1)
117 p1 = cadr(p1)
118 else
119 p3 = one
120
121 if (ispower(p2))
122 p4 = caddr(p2)
123 p2 = cadr(p2)
124 else
125 p4 = one
126
127 if (isfactorial(p1) && isfactorial(p2))
128
129 # Determine if the powers cancel.
130
131 push(p3)
132 push(p4)
133 add()
134 yyexpand()
135 n = pop_integer()
136 if (n != 0)
137 return
138
139 # Find the difference between the two factorial args.
140
141 # For example, the difference between (a + 2)! and a! is 2.
142
143 push(cadr(p1))
144 push(cadr(p2))
145 subtract()
146 yyexpand(); # to simplify
147
148 n = pop_integer()
149 if (n == 0 || isNaN(n))
150 return
151 if (n < 0)
152 n = -n
153 p5 = p1
154 p1 = p2
155 p2 = p5
156 p5 = p3
157 p3 = p4
158 p4 = p5
159
160 push(one)
161
162 for i in [1..n]
163 push(cadr(p2))
164 push_integer(i)
165 add()
166 push(p3)
167 power()
168 multiply()
169 stack[s+a] = pop()
170 stack[s+b] = symbol(NIL)