@@ -103,6 +103,31 @@ class Fibonacci(_MPMathFunction):
103103 sympy_name = "fibonacci"
104104 mpmath_name = "fibonacci"
105105
106+ # Note: memoizing functions is a big win. For a value of n, more than
107+ # 1.3 n different values (positive and negative) occur.
108+ # Also for this function to be effective across top-level calls,
109+ # it needs to be at the module level rather than inside the class.
110+ # Finally, docs say that `maxsize` is best at a power of 2.
111+ # With 1024 we can handle reasonably values of n=900:
112+ # PartitionsP[900] = 415873681190459054784114365430
113+ @lru_cache (maxsize = 1024 )
114+ def number_of_partitions (n : int ) -> int :
115+ """Algorithm NumberOfPartitions from Page 67 of Skiena: Implementing
116+ Discrete Mathematics, using Euler's recurrence"""
117+ if n < 0 :
118+ return 0
119+ elif n == 0 :
120+ return 1
121+ sum = 0
122+ for m in range (math .ceil ((1 + math .sqrt (1.0 + 24 * n )) / 6 ), 0 , - 1 ):
123+ mx3 = m * 3
124+ j = n - m * (mx3 - 1 ) / 2
125+ k = n - m * (mx3 + 1 ) / 2
126+ if m % 2 :
127+ sum += number_of_partitions (j ) + number_of_partitions (k )
128+ else :
129+ sum += - number_of_partitions (j ) - number_of_partitions (k )
130+ return sum
106131
107132class PartitionsP (Builtin ):
108133 """
@@ -120,25 +145,6 @@ class PartitionsP(Builtin):
120145 def apply (self , n , evaluation ):
121146 "PartitionsP[n_Integer]"
122147
123- @lru_cache
124- def number_of_partitions (n : int ) -> int :
125- """Algorithm NumberOfPartitions from Page 67 of Skiena: Implementing
126- Discrete Mathematics, using Euler's recurrence"""
127- if n < 0 :
128- return 0
129- elif n == 0 :
130- return 1
131- sum = 0
132- for m in range (math .ceil ((1 + math .sqrt (1.0 + 24 * n )) / 6 ), 0 , - 1 ):
133- mx3 = m * 3
134- j = n - m * (mx3 - 1 ) / 2
135- k = n - m * (mx3 + 1 ) / 2
136- if m % 2 :
137- sum += number_of_partitions (j ) + number_of_partitions (k )
138- else :
139- sum += - number_of_partitions (j ) - number_of_partitions (k )
140- return sum
141-
142148 return Integer (number_of_partitions (n .get_int_value ()))
143149
144150 # Simpler but inefficient.
0 commit comments