Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

r""" 

Compute Bell and Uppuluri-Carpenter numbers 

  

AUTHORS: 

  

- Nick Alexander 

""" 

  

from cysignals.memory cimport check_allocarray, sig_free 

  

from sage.libs.gmp.mpz cimport * 

  

from sage.rings.integer cimport Integer 

from sage.rings.integer_ring import ZZ 

  

def expnums(int n, int aa): 

r""" 

Compute the first `n` exponential numbers around 

`aa`, starting with the zero-th. 

  

INPUT: 

  

  

- ``n`` - C machine int 

  

- ``aa`` - C machine int 

  

  

OUTPUT: A list of length `n`. 

  

ALGORITHM: We use the same integer addition algorithm as GAP. This 

is an extension of Bell's triangle to the general case of 

exponential numbers. The recursion performs `O(n^2)` 

additions, but the running time is dominated by the cost of the 

last integer addition, because the growth of the integer results of 

partial computations is exponential in `n`. The algorithm 

stores `O(n)` integers, but each is exponential in 

`n`. 

  

EXAMPLES:: 

  

sage: expnums(10, 1) 

[1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147] 

  

:: 

  

sage: expnums(10, -1) 

[1, -1, 0, 1, 1, -2, -9, -9, 50, 267] 

  

:: 

  

sage: expnums(1, 1) 

[1] 

sage: expnums(0, 1) 

[] 

sage: expnums(-1, 0) 

[] 

  

AUTHORS: 

  

- Nick Alexander 

""" 

if n < 1: 

return [] 

  

cdef Integer z 

if n == 1: 

z = Integer.__new__(Integer) 

mpz_set_si(z.value, 1) 

return [z] 

  

n = n - 1 

  

r = [] 

z = Integer.__new__(Integer) 

mpz_set_si(z.value, 1) 

r.append(z) 

  

z = Integer.__new__(Integer) 

mpz_set_si(z.value, aa) 

r.append(z) 

  

cdef mpz_t *bell 

bell = <mpz_t *>check_allocarray(n + 1, sizeof(mpz_t)) 

cdef mpz_t a 

mpz_init_set_si(a, aa) 

mpz_init_set_si(bell[1], aa) 

cdef int i 

cdef int k 

for i from 1 <= i < n: 

mpz_init(bell[i+1]) 

mpz_mul(bell[i+1], a, bell[1]) 

for k from 0 <= k < i: 

mpz_add(bell[i-k], bell[i-k], bell[i-k+1]) 

  

z = Integer.__new__(Integer) 

mpz_set(z.value, bell[1]) 

r.append(z) 

  

for i from 1 <= i <= n: 

mpz_clear(bell[i]) 

sig_free(bell) 

  

return r 

  

# The following code is from GAP 4.4.9. 

################################################### 

# InstallGlobalFunction(Bell,function ( n ) 

# local bell, k, i; 

# bell := [ 1 ]; 

# for i in [1..n-1] do 

# bell[i+1] := bell[1]; 

# for k in [0..i-1] do 

# bell[i-k] := bell[i-k] + bell[i-k+1]; 

# od; 

# od; 

# return bell[1]; 

# end); 

  

def expnums2(n, aa): 

r""" 

A vanilla python (but compiled via Cython) implementation of 

expnums. 

  

We Compute the first `n` exponential numbers around 

`aa`, starting with the zero-th. 

  

EXAMPLES:: 

  

sage: from sage.combinat.expnums import expnums2 

sage: expnums2(10, 1) 

[1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147] 

""" 

if n < 1: 

return [] 

if n == 1: 

return [Integer(1)] 

  

n = n - 1 

r = [Integer(1), Integer(aa)] 

  

bell = [Integer(0)] * (n+1) 

a = aa 

bell[1] = aa 

for i in range(1, n): 

bell[i+1] = a * bell[1] 

for k in range(i): 

bell[i-k] = bell[i-k] + bell[i-k+1] 

r.append(bell[1]) 

return r