Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/combinat/expnums.pyx
4058 views
1
r"""
2
Compute Bell and Uppuluri-Carpenter numbers
3
4
AUTHORS:
5
6
- Nick Alexander
7
"""
8
9
include "../ext/interrupt.pxi"
10
include "../ext/stdsage.pxi"
11
include "../ext/cdefs.pxi"
12
include "../ext/gmp.pxi"
13
14
from sage.rings.integer cimport Integer
15
16
from sage.rings.integer_ring import ZZ
17
18
def expnums(int n, int aa):
19
r"""
20
Compute the first `n` exponential numbers around
21
`aa`, starting with the zero-th.
22
23
INPUT:
24
25
26
- ``n`` - C machine int
27
28
- ``aa`` - C machine int
29
30
31
OUTPUT: A list of length `n`.
32
33
ALGORITHM: We use the same integer addition algorithm as GAP. This
34
is an extension of Bell's triangle to the general case of
35
exponential numbers. The recursion performs `O(n^2)`
36
additions, but the running time is dominated by the cost of the
37
last integer addition, because the growth of the integer results of
38
partial computations is exponential in `n`. The algorithm
39
stores `O(n)` integers, but each is exponential in
40
`n`.
41
42
EXAMPLES::
43
44
sage: expnums(10, 1)
45
[1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147]
46
47
::
48
49
sage: expnums(10, -1)
50
[1, -1, 0, 1, 1, -2, -9, -9, 50, 267]
51
52
::
53
54
sage: expnums(1, 1)
55
[1]
56
sage: expnums(0, 1)
57
[]
58
sage: expnums(-1, 0)
59
[]
60
61
AUTHORS:
62
63
- Nick Alexander
64
"""
65
if n < 1:
66
return []
67
68
cdef Integer z
69
if n == 1:
70
z = Integer.__new__(Integer)
71
mpz_set_si(z.value, 1)
72
return [z]
73
74
n = n - 1
75
76
r = []
77
z = Integer.__new__(Integer)
78
mpz_set_si(z.value, 1)
79
r.append(z)
80
81
z = Integer.__new__(Integer)
82
mpz_set_si(z.value, aa)
83
r.append(z)
84
85
cdef mpz_t *bell
86
bell = <mpz_t *>sage_malloc(sizeof(mpz_t) * (n+1))
87
if bell == NULL:
88
raise MemoryError, "out of memory allocating temporary storage in expnums"
89
cdef mpz_t a
90
mpz_init_set_si(a, aa)
91
mpz_init_set_si(bell[1], aa)
92
cdef int i
93
cdef int k
94
for i from 1 <= i < n:
95
mpz_init(bell[i+1])
96
mpz_mul(bell[i+1], a, bell[1])
97
for k from 0 <= k < i:
98
mpz_add(bell[i-k], bell[i-k], bell[i-k+1])
99
100
z = Integer.__new__(Integer)
101
mpz_set(z.value, bell[1])
102
r.append(z)
103
104
for i from 1 <= i <= n:
105
mpz_clear(bell[i])
106
sage_free(bell)
107
108
return r
109
110
# The following code is from GAP 4.4.9.
111
###################################################
112
# InstallGlobalFunction(Bell,function ( n )
113
# local bell, k, i;
114
# bell := [ 1 ];
115
# for i in [1..n-1] do
116
# bell[i+1] := bell[1];
117
# for k in [0..i-1] do
118
# bell[i-k] := bell[i-k] + bell[i-k+1];
119
# od;
120
# od;
121
# return bell[1];
122
# end);
123
124
def expnums2(n, aa):
125
r"""
126
A vanilla python (but compiled via Cython) implementation of
127
expnums.
128
129
We Compute the first `n` exponential numbers around
130
`aa`, starting with the zero-th.
131
132
EXAMPLES::
133
134
sage: from sage.combinat.expnums import expnums2
135
sage: expnums2(10, 1)
136
[1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147]
137
"""
138
if n < 1:
139
return []
140
if n == 1:
141
return [Integer(1)]
142
143
n = n - 1
144
r = [Integer(1), Integer(aa)]
145
146
bell = [Integer(0)] * (n+1)
147
a = aa
148
bell[1] = aa
149
for i in range(1, n):
150
bell[i+1] = a * bell[1]
151
for k in range(i):
152
bell[i-k] = bell[i-k] + bell[i-k+1]
153
r.append(bell[1])
154
return r
155
156