Mercurial > forge
view main/combinatorics/src/partint.cc @ 5662:b05917e0f0bb octave-forge
explicit inclusion of lo-ieee.h is needed in 3.1.x
author | adb014 |
---|---|
date | Mon, 18 May 2009 20:13:16 +0000 |
parents | 2de537641f94 |
children | 889acd3ffe23 |
line wrap: on
line source
/* ## Copyright (C) 2006 Torsten Finke <fi@igh-essen.com> ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; If not, see <http://www.gnu.org/licenses/>. $Revision$ $Date$ $RCSfile$ */ #include <octave/oct.h> #include <octave/lo-ieee.h> #include "partint.h" unsigned long * pcnt(unsigned long n) { unsigned long *s = new unsigned long[n]; unsigned long *x = new unsigned long[n*n]; unsigned long **p = new unsigned long*[n]; for (unsigned long k=0; k<n; ++k) { p[k] = x + (k*n); s[k] = 0; } for (unsigned long k=0; k<n*n; ++k) x[k] = 0; p[0][0] = 1; for (unsigned long k=1; k<n; ++k) { // p[N][j] == numpart of N with max summand j for (unsigned long j=1; j<=k; ++j) { p[k][j] = p[k-1][j-1] + p[k-j][j]; } for (unsigned long j=1; j<=k; ++j) { s[k] += p[k][j]; // S(k) = numpart(n) } } return s; } DEFUN_DLD (partcnt, args, , "-*- texinfo -*-\n\ @deftypefn{Loadable Function} {@var{p} =} partcnt(@var{n})\n\ \n\ @cindex partition count\n\ \n\ Calculate integer partition count. Argument @var{n} be scalar, vector\n\ or matrix of non-negative numbers. A partition is the sum decomposition \n\ of integers. \n\ \n\ Example:\n\ @example \n\ partcnt([1, 5; 17 -3])\n\ @end example\n\ @noindent\n\ returns\n\ @example\n\ ans =\n\ 1 7\n\ 297 NaN\n\ @end example\n\ \n\ Reference:\n\ Joerg Arndt: Algorithms for programmers (http://www.jjj.de), 2006.\n\n\ @end deftypefn\n\ @seealso{partint}\n\ ") { octave_value r; int nargin = args.length (); if (nargin != 1) { error("partcnt accepts exactly one argument"); return r; } if ( ! args(0).is_numeric_type()) { error("partcnt only accepts a numeric argument"); return r; } NDArray f(args(0).matrix_value()); RowVector m(f.max()); double mmax = m.max(); if ( mmax < 1 ) { error("partcnt is only defined for non-negative arguments"); return r; } unsigned long n = (unsigned long) mmax + 1; unsigned long *s = pcnt(n); unsigned long fr = (unsigned long) f.rows(); unsigned long fc = (unsigned long) f.columns(); for (unsigned long i=0; i<fr; i++) { for (unsigned long k=0; k<fc; k++) { unsigned long idx = (unsigned long) f(i, k); if (0 < idx && idx < n) { f(i, k) = s[idx]; } else { f(i, k) = lo_ieee_nan_value(); } } } r = f; return r; } /* %!assert(partcnt(1), 1); %!assert(partcnt(17), 297); %!fail("partcnt()", "partcnt"); %!fail("partcnt(1,2)", "partcnt"); %!fail("partcnt('xyz')", "partcnt"); %!demo %! p = partcnt([1, 5; 17 -5]) */ DEFUN_DLD (partint, args, , "-*- texinfo -*-\n\ @deftypefn{Loadable Function} {@var{p} =} partint(@var{n})\n\ \n\ @cindex partition\n\ \n\ Calculate all integer partitions. Argument @var{n} be \n\ a positive number. A partition is the sum decomposition \n\ of integers. \n\ \n\ Example:\n\ @example \n\ partint(4)\n\ @end example\n\ @noindent\n\ returns\n\ @example\n\ ans =\n\ 4 0 0 0\n\ 2 1 0 0\n\ 0 2 0 0\n\ 1 0 1 0\n\ 0 0 0 1\n\ @end example\n\ \n\ This means\n\n\ @iftex\n\ @tex\n\ $$\eqalign{4 & = 4 \\cdot 1 \\cr\n\ & = 2 \\cdot 1 + 1 \\cdot 2 \\cr\n\ & = 2 \\cdot 2 \\cr\n\ & = 1 \\cdot 1 + 1 \\cdot 3 \\cr\n\ & = 1 \\cdot 1 \\cr\n\ \\cr}$$\n\ @end tex\n\ @end iftex\n\ @ifinfo\n\ @example\n\ 4 = 4 * 1\n\ = 2 * 1 + 1 * 2\n\ = 2 * 2\n\ = 1 * 1 + 1 * 3\n\ = 1 * 4\n\ @end example\n\ @end ifinfo\n\ \n\ Note:\n\ \n\ partint(n) * [1:n]' == n\n\ \n\ Reference:\n\ Joerg Arndt: Algorithms for programmers (http://www.jjj.de), 2006.\n\n\ @end deftypefn\n\ @seealso{partcnt}\n\ ") { octave_value r; int nargin = args.length (); if (nargin != 1 || ! args(0).is_scalar_type() || ! args(0).is_numeric_type() ) { error("partint only accepts one scalar positive integer argument"); return r; } double arg0 = args(0).double_value(); if ( arg0 < 1 ) { error("partint is only defined for positive integer arguments"); return r; } unsigned long n = (unsigned long) arg0; unsigned long *s = pcnt(n+1); unsigned long k = s[n]; Matrix pa(k, n, 0); int_partition p(n); unsigned long i = 0; do { const unsigned long *d = p.data(); for (unsigned long j=0; j<n; j++) { pa(i, j) = (unsigned long)d[j+1]; } i ++; } while (p.next()); r = pa; return r; } /* %!assert(partint(1), 1); %!assert(all(partint(n=17) * [1:n]' == n) - 1, 0); %!fail("partint()", "partint"); %!fail("partint(1,2)", "partint"); %!fail("partint('xyz')", "partint"); %!demo %! p = partint(4) */ /* ;;; Local Variables: *** ;;; mode: C++ *** ;;; End: *** */