Algorithm-Permute
view release on metacpan or search on metacpan
/*
Permute.xs
Copyright (c) 1999 - 2008 Edwin Pratomo
You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file,
with the exception that it cannot be placed on a CD-ROM or similar media
for commercial distribution without the prior approval of the author.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <stdio.h>
#include "coollex.h"
#include "multicall.h"
#include "ppport.h"
#ifdef __cplusplus
}
#endif
/* (Robin) This hack is stolen from Graham Barr's Scalar-List-Utils package.
The comment therein runs:
Some platforms have strict exports. And before 5.7.3 cxinc (or Perl_cxinc)
was not exported. Therefore platforms like win32, VMS etc have problems
so we redefine it here -- GMB
With any luck, it will enable us to build under ActiveState Perl.
*/
#if PERL_VERSION < 7/* Not in 5.6.1. */
# ifdef cxinc
# undef cxinc
# endif
# define cxinc() my_cxinc(aTHX)
static I32
my_cxinc(pTHX)
{
cxstack_max = cxstack_max * 3 / 2;
Renew(cxstack, cxstack_max + 1, struct context); /* XXX should fix CXINC macro */
return cxstack_ix + 1;
}
#endif
/* (Robin) Assigning to AvARRAY(array) expands to an assignment which has a typecast on the left-hand side.
* So it was technically illegal, but GCC is decent enough to accept it
* anyway. Unfortunately other compilers are not usually so forgiving...
*/
#if PERL_VERSION >= 9
# define AvARRAY_set(av, val) ((av)->sv_u.svu_array) = val
#else
# define AvARRAY_set(av, val) ((XPVAV*) SvANY(av))->xav_array = (char*) val
#endif
typedef unsigned int UINT;
typedef unsigned long ULONG;
#ifdef USE_LINKEDLIST
typedef struct record {
int info;
struct record *link;
} listrecord;
#endif
typedef struct {
bool is_done;
SV **items;
SV* aryref;
UV num;
#ifdef USE_LINKEDLIST
listrecord *ptr_head, **ptr, **pred;
#else
UINT *loc; /* location of n in p[] */
UINT *p;
#endif
COMBINATION *c;
} Permute;
/* private _next */
#ifdef USE_LINKEDLIST
static bool _next(UV n, listrecord *ptr_head, listrecord **ptr, listrecord **pred)
#else
static bool _next(UV n, UINT *p, UINT *loc)
#endif
{
#ifndef USE_LINKEDLIST
int i;
#endif
bool is_done = FALSE;
if (n <= 1) /* termination condition */
return TRUE;
#ifdef USE_LINKEDLIST
/* less arithmetic */
if (ptr[n]->link != NULL) {
pred[n]->link = ptr[n]->link;
pred[n] = pred[n]->link;
ptr[n]->link = pred[n]->link;
pred[n]->link = ptr[n];
} else {
pred[n]->link = NULL;
is_done = _next(n - 1, ptr_head, ptr, pred);
ptr[n]->link = ptr_head->link;
ptr_head->link = ptr[n]; /* change head of list */
( run in 0.821 second using v1.01-cache-2.11-cpan-5b529ec07f3 )