r987 - in packages: . libmath-combinatorics-perl libmath-combinatorics-perl/branches libmath-combinatorics-perl/branches/upstream libmath-combinatorics-perl/branches/upstream/current libmath-combinatorics-perl/branches/upstream/current/lib libmath-combinatorics-perl/branches/upstream/current/lib/Math libmath-combinatorics-perl/branches/upstream/current/t
Carlo Segre
segre-guest@costa.debian.org
Sat, 14 May 2005 23:36:08 +0000
Author: segre-guest
Date: 2005-05-14 23:36:08 +0000 (Sat, 14 May 2005)
New Revision: 987
Added:
packages/libmath-combinatorics-perl/
packages/libmath-combinatorics-perl/branches/
packages/libmath-combinatorics-perl/branches/upstream/
packages/libmath-combinatorics-perl/branches/upstream/current/
packages/libmath-combinatorics-perl/branches/upstream/current/Changes
packages/libmath-combinatorics-perl/branches/upstream/current/MANIFEST
packages/libmath-combinatorics-perl/branches/upstream/current/Makefile.PL
packages/libmath-combinatorics-perl/branches/upstream/current/README
packages/libmath-combinatorics-perl/branches/upstream/current/lib/
packages/libmath-combinatorics-perl/branches/upstream/current/lib/Math/
packages/libmath-combinatorics-perl/branches/upstream/current/lib/Math/Combinatorics.pm
packages/libmath-combinatorics-perl/branches/upstream/current/t/
packages/libmath-combinatorics-perl/branches/upstream/current/t/01.t
packages/libmath-combinatorics-perl/branches/upstream/current/t/02.t
packages/libmath-combinatorics-perl/tags/
Log:
[svn-inject] Installing original source of libmath-combinatorics-perl
Added: packages/libmath-combinatorics-perl/branches/upstream/current/Changes
===================================================================
--- packages/libmath-combinatorics-perl/branches/upstream/current/Changes 2005-05-14 23:08:48 UTC (rev 986)
+++ packages/libmath-combinatorics-perl/branches/upstream/current/Changes 2005-05-14 23:36:08 UTC (rev 987)
@@ -0,0 +1,18 @@
+Revision history for Perl extension Math::Combinatorics.
+
+0.01 Tue Sep 21 19:06:32 2004
+ - original version; created by h2xs 1.21 with options
+ -AXn Math::Combinatorics
+
+0.02 o Bugfix to permute() method, reported by Marc Logghe.
+ o Combinations/Permutations now calculated using iterator.
+ Uses less memory for very large sets (David Coppit, Tye,
+ Christopher Eltschka).
+
+0.03 o Added reference to Set::Scalar, Set::Bag
+ o new() accepts a 'compare' option.
+ o new() presorts the set by this ('compare' value is a sorting
+ subroutine code reference). this addresses a combine/permute
+ bug when using a set of references, identified by Ying Yang
+ <yyang@emba.uvm.edu>.
+
Added: packages/libmath-combinatorics-perl/branches/upstream/current/MANIFEST
===================================================================
--- packages/libmath-combinatorics-perl/branches/upstream/current/MANIFEST 2005-05-14 23:08:48 UTC (rev 986)
+++ packages/libmath-combinatorics-perl/branches/upstream/current/MANIFEST 2005-05-14 23:36:08 UTC (rev 987)
@@ -0,0 +1,7 @@
+Changes
+MANIFEST
+Makefile.PL
+README
+lib/Math/Combinatorics.pm
+t/01.t
+t/02.t
Added: packages/libmath-combinatorics-perl/branches/upstream/current/Makefile.PL
===================================================================
--- packages/libmath-combinatorics-perl/branches/upstream/current/Makefile.PL 2005-05-14 23:08:48 UTC (rev 986)
+++ packages/libmath-combinatorics-perl/branches/upstream/current/Makefile.PL 2005-05-14 23:36:08 UTC (rev 987)
@@ -0,0 +1,11 @@
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+ 'NAME' => 'Math::Combinatorics',
+ 'VERSION_FROM' => 'lib/Math/Combinatorics.pm', # finds $VERSION
+ 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1
+ ($] >= 5.005 ? ## Add these new keywords supported since 5.005
+ (ABSTRACT_FROM => 'lib/Math/Combinatorics.pm', # retrieve abstract from module
+ AUTHOR => 'Allen Day <allenday@ucla.edu>') : ()),
+);
Added: packages/libmath-combinatorics-perl/branches/upstream/current/README
===================================================================
--- packages/libmath-combinatorics-perl/branches/upstream/current/README 2005-05-14 23:08:48 UTC (rev 986)
+++ packages/libmath-combinatorics-perl/branches/upstream/current/README 2005-05-14 23:36:08 UTC (rev 987)
@@ -0,0 +1,106 @@
+NAME
+ Math::Combinatorics - Perform combinations and permutations on lists
+
+SYNOPSIS
+ Available as an object oriented API.
+
+ use Math::Combinatorics;
+
+ my @n = qw(a b c);
+ my $combinat = Math::Combinatorics->new(count => 2,
+ data => [@n],
+ );
+
+ print "combinations of 2 from: ".join(" ",@n)."\n";
+ print "------------------------".("--" x scalar(@n))."\n";
+ while(my @combo = $combinat->next_combination){
+ print join(' ', @combo)."\n";
+ }
+
+ print "\n";
+
+ print "combinations of 2 from: ".join(" ",@n)."\n";
+ print "------------------------".("--" x scalar(@n))."\n";
+ while(my @permu = $combinat->next_permutation){
+ print join(' ', @permu)."\n";
+ }
+
+ output:
+
+ Or available via exported functions 'permute', 'combine', and
+ 'factorial'.
+
+ use Math::Combinatorics;
+
+ my @n = qw(a b c);
+ print "combinations of 2 from: ".join(" ",@n)."\n";
+ print "------------------------".("--" x scalar(@n))."\n";
+ print join("\n", map { join " ", @$_ } combine(2,@n)),"\n";
+ print "\n";
+ print "permutations of 3 from: ".join(" ",@n)."\n";
+ print "------------------------".("--" x scalar(@n))."\n";
+ print join("\n", map { join " ", @$_ } permute(@n)),"\n";
+
+ Output:
+
+ combinations of 2 from: a b c
+ ------------------------------
+ a b
+ a c
+ b c
+
+ combinations of 2 from: a b c
+ ------------------------------
+ a b c
+ a c b
+ b a c
+ b c a
+ c a b
+ c b a
+
+ Output from both types of calls is the same, but the object-oriented
+ approach consumes much less memory for large sets.
+
+DESCRIPTION
+ Combinatorics is the branch of mathematics studying the enumeration,
+ combination, and permutation of sets of elements and the mathematical
+ relations that characterize their properties. As a jumping off point,
+ refer to:
+
+ http://mathworld.wolfram.com/Combinatorics.html
+
+ This module provides a pure-perl implementation of nCk, nPk, and n!
+ (combination, permutation, and factorial, respectively). Functional and
+ object-oriented usages allow problems such as the following to be
+ solved:
+
+ nCk "Fun questions to ask the pizza parlor wait staff: how many possible
+ combinations of 2 toppings can I get on my pizza?".
+
+ nPk "Master Mind Game: ways to arrange pieces of different colors in a
+ certain number of positions, without repetition of a color".
+
+ Object-oriented usage additionally allows solving these problems by
+ calling the new() entry elsewhere in this document with a frequency
+ vector:
+
+ nPRk "morse signals: diferent signals of 3 positions using the 2 two
+ symbol - and .".
+
+ nCRk "ways to extract 3 balls at once of a bag with black and white
+ balls".
+
+ nPRk "different words obtained permuting the letters of the word
+ PARROT".
+
+AUTHOR
+ Allen Day <allenday@ucla.edu>, with algorithmic contributions from
+ Christopher Eltschka and Tye.
+
+ACKNOWLEDGEMENTS
+ Thanks to everyone for helping to make this a better module.
+
+ For adding new features: Carlos Rica, David Coppit
+
+ For bug reports: Ying Yang, Joerg Beyer, Marc Logghe
+
Added: packages/libmath-combinatorics-perl/branches/upstream/current/lib/Math/Combinatorics.pm
===================================================================
--- packages/libmath-combinatorics-perl/branches/upstream/current/lib/Math/Combinatorics.pm 2005-05-14 23:08:48 UTC (rev 986)
+++ packages/libmath-combinatorics-perl/branches/upstream/current/lib/Math/Combinatorics.pm 2005-05-14 23:36:08 UTC (rev 987)
@@ -0,0 +1,693 @@
+=head1 NAME
+
+Math::Combinatorics - Perform combinations and permutations on lists
+
+=head1 SYNOPSIS
+
+Available as an object oriented API.
+
+ use Math::Combinatorics;
+
+ my @n = qw(a b c);
+ my $combinat = Math::Combinatorics->new(count => 2,
+ data => [@n],
+ );
+
+ print "combinations of 2 from: ".join(" ",@n)."\n";
+ print "------------------------".("--" x scalar(@n))."\n";
+ while(my @combo = $combinat->next_combination){
+ print join(' ', @combo)."\n";
+ }
+
+ print "\n";
+
+ print "combinations of 2 from: ".join(" ",@n)."\n";
+ print "------------------------".("--" x scalar(@n))."\n";
+ while(my @permu = $combinat->next_permutation){
+ print join(' ', @permu)."\n";
+ }
+
+ output:
+
+Or available via exported functions 'permute', 'combine', and 'factorial'.
+
+ use Math::Combinatorics;
+
+ my @n = qw(a b c);
+ print "combinations of 2 from: ".join(" ",@n)."\n";
+ print "------------------------".("--" x scalar(@n))."\n";
+ print join("\n", map { join " ", @$_ } combine(2,@n)),"\n";
+ print "\n";
+ print "permutations of 3 from: ".join(" ",@n)."\n";
+ print "------------------------".("--" x scalar(@n))."\n";
+ print join("\n", map { join " ", @$_ } permute(@n)),"\n";
+
+
+Output:
+
+ combinations of 2 from: a b c
+ ------------------------------
+ a b
+ a c
+ b c
+
+ combinations of 2 from: a b c
+ ------------------------------
+ a b c
+ a c b
+ b a c
+ b c a
+ c a b
+ c b a
+
+Output from both types of calls is the same, but the object-oriented approach consumes
+much less memory for large sets.
+
+=head1 DESCRIPTION
+
+Combinatorics is the branch of mathematics studying the enumeration, combination,
+and permutation of sets of elements and the mathematical relations that characterize
+their properties. As a jumping off point, refer to:
+
+http://mathworld.wolfram.com/Combinatorics.html
+
+This module provides a pure-perl implementation of nCk, nPk, and n! (combination,
+permutation, and factorial, respectively). Functional and object-oriented usages allow
+problems such as the following to be solved:
+
+nCk "Fun questions to ask the pizza parlor wait staff: how many possible combinations
+of 2 toppings can I get on my pizza?".
+
+nPk "Master Mind Game: ways to arrange pieces of different colors in a
+certain number of positions, without repetition of a color".
+
+Object-oriented usage additionally allows solving these problems by calling L</new()>
+with a B<frequency> vector:
+
+nPRk "morse signals: diferent signals of 3 positions using the 2 two symbol - and .".
+
+nCRk "ways to extract 3 balls at once of a bag with black and white balls".
+
+nPRk "different words obtained permuting the letters of the word PARROT".
+
+=head2 EXPORT
+
+the following export tags will bring a single method into the caller's
+namespace. no symbols are exported by default. see pod documentation below for
+method descriptions.
+
+ combine
+ permute
+ factorial
+
+=head1 AUTHOR
+
+Allen Day <allenday@ucla.edu>, with algorithmic contributions from Christopher Eltschka and
+Tye.
+
+=head1 ACKNOWLEDGEMENTS
+
+Thanks to everyone for helping to make this a better module.
+
+For adding new features: Carlos Rica, David Coppit
+
+For bug reports: Ying Yang, Joerg Beyer, Marc Logghe
+
+=head1 BUGS
+
+report them to the author. a known bug (partial implementation bug) does not allow
+parameterization of k for nPk in permute(). it is assumed k == n. L</permute()> for
+details.
+
+=head1 SEE ALSO
+
+L<Set::Scalar>
+
+L<Set::Bag>
+
+L<String::Combination> (misnamed, it actually returns permutations on a string).
+
+http://perlmonks.thepen.com/29374.html
+
+http://groups.google.com/groups?selm=38568F79.13680B86%40physik.tu-muenchen.de&output=gplain
+
+=cut
+
+package Math::Combinatorics;
+
+use strict;
+require Exporter;
+
+our @ISA = qw(Exporter);
+our @EXPORT = qw( combine permute factorial);
+our $VERSION = '0.04';
+
+=head1 EXPORTED FUNCTIONS
+
+=head2 combine()
+
+ Usage : my @combinations = combine($k,@n);
+ Function: implements nCk (n choose k), or n!/(k!*(n-k!)).
+ returns all unique unorderd combinations of k items from set n.
+ items in n are assumed to be character data, and are
+ copied into the return data structure (see "Returns" below).
+ Example : my @n = qw(a b c);
+ my @c = combine(2,@n);
+ print join "\n", map { join " ", @$_ } @c;
+ # prints:
+ # b c
+ # a c
+ # a b
+ Returns : a list of arrays, where each array contains a unique combination
+ of k items from n
+ Args : a list of items to be combined
+ Notes : data is internally assumed to be alphanumeric. this is necessary
+ to efficiently generate combinations of large sets. if you need
+ combinations of non-alphanumeric data, or on data
+ C<sort {$a cmp $b}> would not be appropriate, use the
+ object-oriented API. See L</new()> and the B<compare> option.
+
+=cut
+
+sub combine {
+ my($k,@n) = @_;
+
+ my @result = ();
+
+ my $c = __PACKAGE__->new(data => [@n], count => $k);
+ while(my(@combo) = $c->next_combination){
+ push @result, [@combo];
+ }
+
+ return @result;
+}
+
+=head2 permute()
+
+ Usage : my @permutations = permute(@n);
+ Function: implements nPk (n permute k) (where k == n), or n!/(n-k)!
+ returns all unique permutations of k items from set n
+ (where n == k, see "Note" below). items in n are assumed to
+ be character data, and are copied into the return data
+ structure.
+ Example : my @n = qw(a b c);
+ my @p = permute(@n);
+ print join "\n", map { join " ", @$_ } @p;
+ # prints:
+ # b a c
+ # b c a
+ # c b a
+ # c a b
+ # a c b
+ # a b c
+ Returns : a list of arrays, where each array contains a permutation of
+ k items from n (where k == n).
+ Args : a list of items to be permuted.
+ Note : k should really be parameterizable. this will happen
+ in a later version of the module. send me a patch to
+ make that version come out sooner.
+ Notes : data is internally assumed to be alphanumeric. this is necessary
+ to efficiently generate combinations of large sets. if you need
+ combinations of non-alphanumeric data, or on data
+ C<sort {$a cmp $b}> would not be appropriate, use the
+ object-oriented API. See L</new()>, and the B<compare> option.
+
+=cut
+
+sub permute {
+ my(@n) = @_;
+
+ my @result = ();
+
+ my $c = __PACKAGE__->new(data => [@n]);
+ while(my(@combo) = $c->next_permutation){
+ push @result, [@combo];
+ }
+
+ return @result;
+}
+
+=head2 factorial()
+
+ Usage : my $f = factorial(4); #returns 24, or 4*3*2*1
+ Function: calculates n! (n factorial).
+ Returns : undef if n is non-integer or n < 0
+ Args : a positive, non-zero integer
+ Note : this function is used internally by combine() and permute()
+
+=cut
+
+sub factorial {
+ my $n = shift;
+ return undef unless $n >= 0 and $n == int($n);
+
+ my $f;
+
+ for($f = 1 ; $n > 0 ; $n--){
+ $f *= $n
+ }
+
+ return $f;
+}
+
+=head1 CONSTRUCTOR
+
+=cut
+
+=head2 new()
+
+ Usage : my $c = Math::Combinatorics->new( count => 2, #treated as int
+ data => [1,2,3,4] #arrayref or anonymous array
+ );
+ Function: build a new Math::Combinatorics object.
+ Returns : a Math::Combinatorics object
+ Args : count - required for combinatoric functions/methods. number of elements to be
+ present in returned set(s).
+ data - required for combinatoric B<AND> permutagenic functions/methods. this is the
+ set elements are chosen from. B<NOTE>: this array is modified in place; make
+ a copy of your array if the order matters in the caller's space.
+ frequency - optional vector of data frequencies. must be the same length as the B<data>
+ constructor argument. These two constructor calls here are equivalent:
+
+ $a = 'a';
+ $b = 'b';
+
+ Math::Combinatorics->new( count=>2, data=>[\$a,\$a,\$a,\$a,\$a,\$b,\$b] );
+ Math::Combinatorics->new( count=>2, data=>[\$a,\$b], frequency=>[5,2] );
+
+ so why use this? sometimes it's useful to have multiple identical entities in
+ a set (in set theory jargon, this is called a "bag", See L<Set::Bag>).
+ compare - optional subroutine reference used in sorting elements of the set. examples:
+
+ #appropriate for character elements
+ compare => sub { $_[0] cmp $_[1] }
+ #appropriate for numeric elements
+ compare => sub { $_[0] <=> $_[1] }
+ #appropriate for object elements, perhaps
+ compare => sub { $_[0]->value <=> $_[1]->value }
+
+ defaults to "sub { $_[0] cmp $_[1] }"
+
+=cut
+
+sub new {
+ my($class,%arg) = @_;
+ my $self = bless {}, $class;
+ $self->{compare} = $arg{compare} || sub { $_[0] cmp $_[1] };
+ $self->{count} = $arg{count};
+
+ #convert bag to set
+ my $freq = $arg{frequency};
+ if(ref($freq) eq 'ARRAY' and scalar(@$freq) == scalar(@{$arg{data}})){
+ my @bag = @{$arg{data}};
+ my @set = ();
+
+ while(my $type = shift @bag){
+ my $f = shift @$freq;
+ next if $f < 1;
+ for(1..$f){
+ push @set, $type;
+ }
+ }
+ $arg{data} = \@set;
+ }
+
+ my $compare = $self->{compare};
+
+ $self->{data} = [sort {&$compare($a,$b)} @{$arg{data}}];
+
+ $self->{cin} = 1;
+ $self->{pin} = 1;
+
+ return $self;
+}
+
+=head1 OBJECT METHODS
+
+=cut
+
+=head2 next_combination()
+
+ Usage : my @combo = $c->next_combination();
+ Function: get combinations of size $count from @data.
+ Returns : returns a combination of $count items from @data (see L</new()>).
+ repeated calls retrieve all unique combinations of $count elements.
+ a returned empty list signifies all combinations have been iterated.
+ Args : none.
+
+=cut
+
+sub next_combination {
+ my $self = shift;
+ my $data = $self->data();
+ my $combo_end = $self->count();
+
+ my $begin = 0;
+ my $end = $#{$data} + 1;
+
+ my @result;
+
+ if($self->{cin}){
+ $self->{cin} = 0;
+
+ for(0..$self->count-1){
+ push @result, $data->[$_];
+ }
+ return @result;
+ }
+
+ if ($combo_end == $begin || $combo_end == $end) {
+ return ();
+ }
+
+ my $combo = $combo_end;
+ my $total_set;
+
+ --$combo;
+ $total_set = $self->upper_bound($combo_end,$end,$data->[$combo]);
+ if ($total_set != $end) {
+ $self->swap($combo,$total_set);
+
+ for(0..$self->count-1){
+ push @result, $data->[$_];
+ }
+ return @result;
+ }
+
+ --$total_set;
+ $combo = $self->lower_bound($begin, $combo_end, $data->[$total_set]);
+
+ if ($combo == $begin) {
+ $self->rotate($begin, $combo_end, $end);
+ return ();
+ }
+
+ my $combo_next = $combo;
+ --$combo;
+ $total_set = $self->upper_bound($combo_end, $end, $data->[$combo]);
+
+ my $sort_pos = $end;
+ $sort_pos += $combo_end - $total_set - 1;
+
+ $self->rotate($combo_next, $total_set, $end);
+ $self->rotate($combo, $combo_next, $end);
+ $self->rotate($combo_end, $sort_pos, $end);
+
+#warn @$data;
+
+ for(0..$self->count-1){
+ push @result, $data->[$_];
+ }
+ return @result;
+}
+
+=head2 next_permutation()
+
+ Usage : my @permu = $c->next_permutation();
+ Function: get permutations of elements in @data.
+ Returns : returns a permutation of items from @data (see L</new()>).
+ repeated calls retrieve all unique permutations of @data elements.
+ a returned empty list signifies all permutations have been iterated.
+ Args : none.
+
+=cut
+
+sub next_permutation {
+ my $self = shift;
+ my $data = $self->data();
+
+ if($self->{pin}){
+ $self->{pin} = 0;
+ return @$data;
+ }
+
+ my $cursor = $self->_permutation_cursor();
+
+ my $last= $#{$cursor};
+
+ if($last < 1){
+ return ();
+ }
+
+ # Find last item not in reverse-sorted order:
+ my $i = $last - 1;
+ $i-- while 0 <= $i && $cursor->[$i] >= $cursor->[$i+1];
+
+ if($i == -1){
+ return ();
+ }
+
+
+ # Re-sort the reversely-sorted tail of the list:
+ @{$cursor}[$i+1..$last] = reverse @{$cursor}[$i+1..$last]
+ if $cursor->[$i+1] > $cursor->[$last];
+
+ # Find next item that will make us "greater":
+ my $j = $i+1;
+ $j++ while $cursor->[$i] >= $cursor->[$j];
+
+ # Swap:
+ @{$cursor}[$i,$j] = @{$cursor}[$j,$i];
+
+ # map cursor to data array
+ my @result;
+ foreach my $c (@$cursor){
+ push @result, $data->[$c];
+ }
+ return @result;
+}
+
+=head1 INTERNAL FUNCTIONS AND METHODS
+
+=head2 sum()
+
+ Usage : my $sum = sum(1,2,3); # returns 6
+ Function: sums a list of integers. non-integer list elements are ignored
+ Returns : sum of integer items in arguments passed in
+ Args : a list of integers
+ Note : this function is used internally by combine()
+
+=cut
+
+sub sum {
+ my $sum = 0;
+ foreach my $i (@_){
+ $sum += $i if $i == int($i);
+ }
+ return $sum;
+}
+
+=head2 compare()
+
+ Usage : $obj->compare()
+ Function: internal, undocumented. holds a comparison coderef.
+ Returns : value of compare (a coderef)
+
+
+=cut
+
+sub compare {
+ my($self,$val) = @_;
+ return $self->{'compare'};
+}
+
+
+=head2 count()
+
+ Usage : $obj->count()
+ Function: internal, undocumented. holds the "k" in nCk or nPk.
+ Returns : value of count (an int)
+
+=cut
+
+sub count {
+ my($self) = @_;
+ return $self->{'count'};
+}
+
+
+=head2 data()
+
+ Usage : $obj->data()
+ Function: internal, undocumented. holds the set "n" in nCk or nPk.
+ Returns : value of data (an arrayref)
+
+=cut
+
+sub data {
+ my($self) = @_;
+ return $self->{'data'};
+}
+
+
+=head2 swap()
+
+internal, undocumented.
+
+=cut
+
+sub swap {
+ my $self = shift;
+ my $first = shift;
+ my $second = shift;
+ my $data = $self->data();
+
+ my $temp = $data->[$first];
+ $data->[$first] = $data->[$second];
+ $data->[$second] = $temp;
+}
+
+=head2 reverse()
+
+internal, undocumented.
+
+=cut
+
+sub reverse {
+ my $self = shift;
+ my $first = shift;
+ my $last = shift;
+ my $data = $self->data();
+
+ while (1) {
+ if ($first == $last || $first == --$last) {
+ return;
+ } else {
+ $self->swap($first++, $last);
+ }
+ }
+}
+
+=head2 rotate()
+
+internal, undocumented.
+
+=cut
+
+sub rotate {
+ my $self = shift;
+ my $first = shift;
+ my $middle = shift;
+ my $last = shift;
+ my $data = $self->data();
+
+ if ($first == $middle || $last == $middle) {
+ return;
+ }
+
+ my $first2 = $middle;
+
+ do {
+ $self->swap($first++, $first2++);
+
+ if ($first == $middle) {
+ $middle = $first2;
+ }
+ } while ($first2 != $last);
+
+ $first2 = $middle;
+
+ while ($first2 != $last) {
+ $self->swap($first++, $first2++);
+ if ($first == $middle) {
+ $middle = $first2;
+ } elsif ($first2 == $last) {
+ $first2 = $middle;
+ }
+ }
+}
+
+=head2 upper_bound()
+
+internal, undocumented.
+
+=cut
+
+sub upper_bound {
+ my $self = shift;
+ my $first = shift;
+ my $last = shift;
+ my $value = shift;
+ my $compare = $self->compare();
+ my $data = $self->data();
+
+ my $len = $last - $first;
+ my $half;
+ my $middle;
+
+ while ($len > 0) {
+ $half = $len >> 1;
+ $middle = $first;
+ $middle += $half;
+
+ if (&$compare($value,$data->[$middle]) == -1) {
+ $len = $half;
+ } else {
+ $first = $middle;
+ ++$first;
+ $len = $len - $half - 1;
+ }
+ }
+
+ return $first;
+}
+
+=head2 lower_bound()
+
+internal, undocumented.
+
+=cut
+
+sub lower_bound {
+ my $self = shift;
+ my $first = shift;
+ my $last = shift;
+ my $value = shift;
+ my $compare = $self->compare();
+ my $data = $self->data();
+
+ my $len = $last - $first;
+ my $half;
+ my $middle;
+
+ while ($len > 0) {
+ $half = $len >> 1;
+ $middle = $first;
+ $middle += $half;
+
+ if (&$compare($data->[$middle],$value) == -1) {
+ $first = $middle;
+ ++$first;
+ $len = $len - $half - 1;
+ } else {
+ $len = $half;
+ }
+ }
+
+ return $first;
+}
+
+=head2 _permutation_cursor()
+
+ Usage : $obj->_permutation_cursor()
+ Function: internal method. cursor on permutation iterator order.
+ Returns : value of _permutation_cursor (an arrayref)
+ Args : none
+
+=cut
+
+sub _permutation_cursor {
+ my($self,$val) = @_;
+
+ if(!$self->{'_permutation_cursor'}){
+ my $data = $self->data();
+ my @tmp = ();
+ my $i = 0;
+ push @tmp, $i++ foreach @$data;
+ $self->{'_permutation_cursor'} = \@tmp;
+ }
+
+ return $self->{'_permutation_cursor'};
+}
+
+1;
Added: packages/libmath-combinatorics-perl/branches/upstream/current/t/01.t
===================================================================
--- packages/libmath-combinatorics-perl/branches/upstream/current/t/01.t 2005-05-14 23:08:48 UTC (rev 986)
+++ packages/libmath-combinatorics-perl/branches/upstream/current/t/01.t 2005-05-14 23:36:08 UTC (rev 987)
@@ -0,0 +1,64 @@
+BEGIN {
+ use lib 'lib';
+ use strict;
+ use Test::More;
+
+ plan tests => 8;
+
+ use_ok('Data::Dumper');
+ use_ok('Math::Combinatorics');
+}
+
+my @data = qw( a b c d );
+
+my $f = 0;
+my @r;
+my $c;
+
+$c = Math::Combinatorics->new(
+ data => \@data,
+ count => 2,
+ );
+
+$f = 0;
+while(my(@combo) = $c->next_combination){
+ $f++;
+}
+ok($f == 6);
+
+$c = Math::Combinatorics->new(
+ data => \@data,
+ count => 3,
+ );
+$f = 0;
+while(my(@combo) = $c->next_combination){
+ $f++;
+}
+ok($f == 4);
+
+@r = combine(2,@data);
+ok(scalar(@r) == 6);
+
+@r = combine(3,@data);
+ok(scalar(@r) == 4);
+
+#####################
+
+$c = Math::Combinatorics->new(
+ data => \@data,
+ count => 2,
+ );
+
+$f = 0;
+while(my(@combo) = $c->next_permutation){
+ $f++;
+}
+ok($f == 24);
+
+@r = permute(@data);
+ok(scalar(@r) == 24);
+
+#my @c = permute(@data);
+##print join "\n", sort { $a cmp $b } map { join " ", @$_ } @c;
+#print join "\n", map { join " ", @$_ } @c;
+#print "\n";
Added: packages/libmath-combinatorics-perl/branches/upstream/current/t/02.t
===================================================================
--- packages/libmath-combinatorics-perl/branches/upstream/current/t/02.t 2005-05-14 23:08:48 UTC (rev 986)
+++ packages/libmath-combinatorics-perl/branches/upstream/current/t/02.t 2005-05-14 23:36:08 UTC (rev 987)
@@ -0,0 +1,49 @@
+BEGIN {
+ use lib 'lib';
+ use strict;
+ use Test::More;
+
+ plan tests => 5;
+
+ use_ok('Data::Dumper');
+ use_ok('Math::Combinatorics');
+}
+
+my $c;
+my $f = 0;
+my @r;
+my @data;
+
+@data = ( 'a', [], 'b', [] );
+$c = Math::Combinatorics->new(
+ data => \@data,
+ count => 2,
+ );
+$f = 0;
+while(my(@combo) = $c->next_combination){
+ $f++;
+}
+ok($f == 6);
+
+@data = ([],[],[],[]);
+$c = Math::Combinatorics->new(
+ data => \@data,
+ count => 2,
+ );
+$f = 0;
+while(my(@combo) = $c->next_combination){
+ $f++;
+}
+ok($f == 6);
+
+@data = (1..10);
+$c = Math::Combinatorics->new(
+ data => \@data,
+ count => 2,
+ );
+$f = 0;
+while(my(@combo) = $c->next_combination){
+ $f++;
+}
+ok($f == 45);
+