# HG changeset patch
# User Fredrik Johansson <fredrik.johansson@gmail.com>
# Date 1341411582 -7200
# Node ID 24770e05d76f74e91e21cfde00b36f2719b7be91
# Parent 014ea68136b9bbe602cd584f8861915d24fb95fa
trac #13199 use FLINT to compute the partition function
diff --git a/module_list.py b/module_list.py
a
|
b
|
ext_modules = [ |
623 | 623 | Extension('sage.libs.flint.flint', |
624 | 624 | sources = ["sage/libs/flint/flint.pyx"], |
625 | 625 | libraries = ["csage", "flint", "gmp", "gmpxx", "m", "stdc++"], |
626 | | extra_compile_args=["-std=c99", "-D_XPG6"], |
| 626 | extra_compile_args = ["-std=c99", "-D_XPG6"], |
627 | 627 | depends = flint_depends), |
628 | 628 | |
629 | 629 | Extension('sage.libs.flint.fmpz_poly', |
630 | 630 | sources = ["sage/libs/flint/fmpz_poly.pyx"], |
631 | 631 | libraries = ["csage", "flint", "gmp", "gmpxx", "m", "stdc++"], |
632 | | extra_compile_args=["-std=c99", "-D_XPG6"], |
| 632 | extra_compile_args = ["-std=c99", "-D_XPG6"], |
| 633 | depends = flint_depends), |
| 634 | |
| 635 | Extension('sage.libs.flint.arith', |
| 636 | sources = ["sage/libs/flint/arith.pyx"], |
| 637 | libraries = ["csage", "flint", "gmp", "gmpxx", "m", "stdc++"], |
| 638 | include_dirs = [SAGE_INC + 'flint/'], |
| 639 | extra_compile_args = ["-std=c99", "-D_XPG6"], |
633 | 640 | depends = flint_depends), |
634 | 641 | |
635 | 642 | Extension('sage.libs.fplll.fplll', |
diff --git a/sage/combinat/partition.py b/sage/combinat/partition.py
a
|
b
|
For display options, see :obj:`Partition |
26 | 26 | - If given coordinates of the form ``(r, c)``, then use Python's |
27 | 27 | \*-operator. |
28 | 28 | |
| 29 | |
29 | 30 | - Throughout this documentation, for a partition `\lambda` we will denote |
30 | 31 | its conjugate partition by `\lambda^{\prime}`. For more on conjugate |
31 | 32 | partitions, see :meth:`Partition.conjugate()`. |
… |
… |
We use the lexicographic ordering:: |
272 | 273 | |
273 | 274 | from sage.interfaces.all import gap |
274 | 275 | from sage.libs.all import pari |
| 276 | from sage.libs.flint.arith import number_of_partitions as flint_number_of_partitions |
275 | 277 | |
276 | 278 | from sage.structure.global_options import GlobalOptions |
277 | 279 | from sage.structure.parent import Parent |
… |
… |
class Partitions_n(Partitions): |
4499 | 4501 | lst = [self.n-1, 1] |
4500 | 4502 | return self.element_class(self, lst) |
4501 | 4503 | |
4502 | | def cardinality(self, algorithm='bober'): |
| 4504 | def cardinality(self, algorithm='flint'): |
4503 | 4505 | r""" |
4504 | 4506 | Returns the number of partitions of the specified size. |
4505 | 4507 | |
… |
… |
class Partitions_n(Partitions): |
4508 | 4510 | - ``algorithm`` - (default: ``'bober'``) |
4509 | 4511 | |
4510 | 4512 | - ``'bober'`` -- Use Jonathan Bober's implementation (*very* fast). |
| 4513 | - ``'flint'`` -- use FLINT. |
4511 | 4514 | - ``'gap'`` -- use GAP (VERY *slow*) |
4512 | 4515 | - ``'pari'`` -- use PARI. Speed seems the same as GAP until |
4513 | 4516 | `n` is in the thousands, in which case PARI is faster. |
… |
… |
class Partitions_n(Partitions): |
4532 | 4535 | 7 |
4533 | 4536 | sage: Partitions(5).cardinality(algorithm='bober') |
4534 | 4537 | 7 |
| 4538 | sage: number_of_partitions(5, algorithm='flint') |
| 4539 | 7 |
4535 | 4540 | |
4536 | 4541 | The input must be a nonnegative integer or a ``ValueError`` is raised. |
4537 | 4542 | |
… |
… |
class Partitions_n(Partitions): |
4575 | 4580 | if algorithm == 'bober': |
4576 | 4581 | return cached_number_of_partitions(self.n) |
4577 | 4582 | |
| 4583 | elif algorithm == 'flint': |
| 4584 | return flint_number_of_partitions(self.n) |
| 4585 | |
4578 | 4586 | elif algorithm == 'gap': |
4579 | | return ZZ( gap.eval("NrPartitions(%s)"%(ZZ(self.n))) ) |
| 4587 | return ZZ(gap.eval("NrPartitions(%s)" % (ZZ(self.n)))) |
4580 | 4588 | |
4581 | 4589 | elif algorithm == 'pari': |
4582 | 4590 | return ZZ(pari(ZZ(self.n)).numbpart()) |
4583 | 4591 | |
4584 | | raise ValueError("unknown algorithm '%s'"%algorithm) |
| 4592 | raise ValueError("unknown algorithm '%s'" % algorithm) |
4585 | 4593 | |
4586 | 4594 | def random_element(self, measure = 'uniform'): |
4587 | 4595 | """ |
… |
… |
def number_of_partitions_set(S,k): |
5913 | 5921 | deprecation(13072,'number_of_partitions_set is deprecated. Use SetPartitions().cardinality() instead.') |
5914 | 5922 | return sage.combinat.set_partition.SetPartitions(S,k).cardinality() |
5915 | 5923 | |
5916 | | def number_of_partitions(n,k=None, algorithm='default'): |
| 5924 | def number_of_partitions(n, k=None, algorithm='default'): |
5917 | 5925 | r""" |
5918 | 5926 | Returns the number of partitions of `n` with, optionally, at most `k` |
5919 | 5927 | parts. |
… |
… |
def number_of_partitions(n,k=None, algor |
6064 | 6072 | |
6065 | 6073 | if algorithm == 'default': |
6066 | 6074 | if k is None: |
6067 | | algorithm = 'bober' |
| 6075 | algorithm = 'flint' |
6068 | 6076 | else: |
6069 | 6077 | algorithm = 'gap' |
6070 | 6078 | |
… |
… |
def number_of_partitions(n,k=None, algor |
6083 | 6091 | if algorithm == 'bober': |
6084 | 6092 | return cached_number_of_partitions(n) |
6085 | 6093 | |
| 6094 | elif algorithm == 'flint': |
| 6095 | return flint_number_of_partitions(n) |
| 6096 | |
6086 | 6097 | elif algorithm == 'pari': |
6087 | 6098 | deprecation(13072,"sage.combinat.number_of_partitions is deprecated. Use Partitions().cardinality(algorithm='pari')") |
6088 | 6099 | return ZZ(pari(ZZ(n)).numbpart()) |
diff --git a/sage/libs/flint/arith.pyx b/sage/libs/flint/arith.pyx
new file mode 100644
-
|
+
|
|
| 1 | include "../../ext/interrupt.pxi" |
| 2 | include "fmpz.pxi" |
| 3 | |
| 4 | cdef extern from "flint/arith.h": |
| 5 | void arith_number_of_partitions(fmpz_t x, unsigned long n) |
| 6 | |
| 7 | from sage.rings.integer cimport Integer |
| 8 | |
| 9 | |
| 10 | def number_of_partitions(unsigned long n): |
| 11 | """ |
| 12 | Returns the number of partitions of the integer n. |
| 13 | |
| 14 | EXAMPLES:: |
| 15 | |
| 16 | sage: from sage.libs.flint.arith import number_of_partitions |
| 17 | sage: number_of_partitions(10) |
| 18 | 42 |
| 19 | """ |
| 20 | cdef fmpz_t ans_fmpz |
| 21 | cdef Integer ans |
| 22 | |
| 23 | fmpz_init(ans_fmpz) |
| 24 | |
| 25 | if n > 1000: |
| 26 | sig_on() |
| 27 | |
| 28 | arith_number_of_partitions(ans_fmpz, n) |
| 29 | |
| 30 | if n > 1000: |
| 31 | sig_off() |
| 32 | |
| 33 | ans = Integer(0) |
| 34 | fmpz_get_mpz(ans.value, ans_fmpz) |
| 35 | fmpz_clear(ans_fmpz) |
| 36 | return ans |
| 37 | |