Skip to content

Commit

Permalink
Add optimized min/max/minmax for native arrays
Browse files Browse the repository at this point in the history
- int/num/str arrays
- between 15x and 25x as fast as the non-native equivalent
  • Loading branch information
lizmat committed Jul 30, 2016
1 parent 1035edb commit dd0fe7f
Show file tree
Hide file tree
Showing 2 changed files with 262 additions and 6 deletions.
204 changes: 198 additions & 6 deletions src/core/native_array.pm
Expand Up @@ -34,7 +34,7 @@ my class array does Iterable is repr('VMArray') {

my role strarray[::T] does Positional[T] is array_type(T) {
#- start of generated part of strarray role -----------------------------------
#- Generated on 2016-03-26T22:25:27+01:00 by tools/build/makeNATIVE_ARRAY.pl6
#- Generated on 2016-07-30T23:24:42+02:00 by tools/build/makeNATIVE_ARRAY.pl6
#- PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE

multi method AT-POS(strarray:D: int $idx) is raw {
Expand Down Expand Up @@ -78,7 +78,7 @@ my class array does Iterable is repr('VMArray') {
my int $i = -1;
nqp::bindpos_s(self, $i,
nqp::unbox_s(@values.AT-POS($i)))
while nqp::islt_i(++$i,$elems);
while nqp::islt_i($i = nqp::add_i($i,1),$elems);
self
}

Expand Down Expand Up @@ -199,6 +199,70 @@ my class array does Iterable is repr('VMArray') {
}
}

method min(strarray:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my str $min = nqp::atpos_s(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::islt_i(nqp::cmp_s(
nqp::atpos_s(self,$i),$min),0),
($min = nqp::atpos_s(self,$i))
)
),
$min
),
Inf
)
}
method max(strarray:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my str $max = nqp::atpos_s(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::isgt_i(nqp::cmp_s(
nqp::atpos_s(self,$i),$max),0),
($max = nqp::atpos_s(self,$i))
)
),
$max
),
-Inf
)
}
method minmax(strarray:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my str $min =
my str $max = nqp::atpos_s(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::islt_i(nqp::cmp_s(
nqp::atpos_s(self,$i),$min),0),
($min = nqp::atpos_s(self,$i)),
nqp::if(
nqp::isgt_i(nqp::cmp_s(
nqp::atpos_s(self,$i),$max),0),
($max = nqp::atpos_s(self,$i))
)
)
),
Range.new($min,$max)
),
Range.new(Inf,-Inf)
)
}

method iterator(strarray:D:) {
class :: does Iterator {
has int $!i;
Expand Down Expand Up @@ -244,7 +308,7 @@ my class array does Iterable is repr('VMArray') {

my role intarray[::T] does Positional[T] is array_type(T) {
#- start of generated part of intarray role -----------------------------------
#- Generated on 2016-03-26T22:25:27+01:00 by tools/build/makeNATIVE_ARRAY.pl6
#- Generated on 2016-07-30T23:24:42+02:00 by tools/build/makeNATIVE_ARRAY.pl6
#- PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE

multi method AT-POS(intarray:D: int $idx) is raw {
Expand Down Expand Up @@ -288,7 +352,7 @@ my class array does Iterable is repr('VMArray') {
my int $i = -1;
nqp::bindpos_i(self, $i,
nqp::unbox_i(@values.AT-POS($i)))
while nqp::islt_i(++$i,$elems);
while nqp::islt_i($i = nqp::add_i($i,1),$elems);
self
}

Expand Down Expand Up @@ -409,6 +473,70 @@ my class array does Iterable is repr('VMArray') {
}
}

method min(intarray:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my int $min = nqp::atpos_i(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::islt_i(nqp::cmp_i(
nqp::atpos_i(self,$i),$min),0),
($min = nqp::atpos_i(self,$i))
)
),
$min
),
Inf
)
}
method max(intarray:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my int $max = nqp::atpos_i(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::isgt_i(nqp::cmp_i(
nqp::atpos_i(self,$i),$max),0),
($max = nqp::atpos_i(self,$i))
)
),
$max
),
-Inf
)
}
method minmax(intarray:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my int $min =
my int $max = nqp::atpos_i(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::islt_i(nqp::cmp_i(
nqp::atpos_i(self,$i),$min),0),
($min = nqp::atpos_i(self,$i)),
nqp::if(
nqp::isgt_i(nqp::cmp_i(
nqp::atpos_i(self,$i),$max),0),
($max = nqp::atpos_i(self,$i))
)
)
),
Range.new($min,$max)
),
Range.new(Inf,-Inf)
)
}

method iterator(intarray:D:) {
class :: does Iterator {
has int $!i;
Expand Down Expand Up @@ -471,7 +599,7 @@ my class array does Iterable is repr('VMArray') {

my role numarray[::T] does Positional[T] is array_type(T) {
#- start of generated part of numarray role -----------------------------------
#- Generated on 2016-03-26T22:25:27+01:00 by tools/build/makeNATIVE_ARRAY.pl6
#- Generated on 2016-07-30T23:24:42+02:00 by tools/build/makeNATIVE_ARRAY.pl6
#- PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE

multi method AT-POS(numarray:D: int $idx) is raw {
Expand Down Expand Up @@ -515,7 +643,7 @@ my class array does Iterable is repr('VMArray') {
my int $i = -1;
nqp::bindpos_n(self, $i,
nqp::unbox_n(@values.AT-POS($i)))
while nqp::islt_i(++$i,$elems);
while nqp::islt_i($i = nqp::add_i($i,1),$elems);
self
}

Expand Down Expand Up @@ -636,6 +764,70 @@ my class array does Iterable is repr('VMArray') {
}
}

method min(numarray:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my num $min = nqp::atpos_n(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::islt_i(nqp::cmp_n(
nqp::atpos_n(self,$i),$min),0),
($min = nqp::atpos_n(self,$i))
)
),
$min
),
Inf
)
}
method max(numarray:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my num $max = nqp::atpos_n(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::isgt_i(nqp::cmp_n(
nqp::atpos_n(self,$i),$max),0),
($max = nqp::atpos_n(self,$i))
)
),
$max
),
-Inf
)
}
method minmax(numarray:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my num $min =
my num $max = nqp::atpos_n(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::islt_i(nqp::cmp_n(
nqp::atpos_n(self,$i),$min),0),
($min = nqp::atpos_n(self,$i)),
nqp::if(
nqp::isgt_i(nqp::cmp_n(
nqp::atpos_n(self,$i),$max),0),
($max = nqp::atpos_n(self,$i))
)
)
),
Range.new($min,$max)
),
Range.new(Inf,-Inf)
)
}

method iterator(numarray:D:) {
class :: does Iterator {
has int $!i;
Expand Down
64 changes: 64 additions & 0 deletions tools/build/makeNATIVE_ARRAY.pl6
Expand Up @@ -203,6 +203,70 @@ for $*IN.lines -> $line {
}
}
method min(#type#array:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my #type# $min = nqp::atpos_#postfix#(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::islt_i(nqp::cmp_#postfix#(
nqp::atpos_#postfix#(self,$i),$min),0),
($min = nqp::atpos_#postfix#(self,$i))
)
),
$min
),
Inf
)
}
method max(#type#array:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my #type# $max = nqp::atpos_#postfix#(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::isgt_i(nqp::cmp_#postfix#(
nqp::atpos_#postfix#(self,$i),$max),0),
($max = nqp::atpos_#postfix#(self,$i))
)
),
$max
),
-Inf
)
}
method minmax(#type#array:D:) {
nqp::if(
(my int $elems = self.elems),
nqp::stmts(
(my int $i),
(my #type# $min =
my #type# $max = nqp::atpos_#postfix#(self,0)),
nqp::while(
nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
nqp::if(
nqp::islt_i(nqp::cmp_#postfix#(
nqp::atpos_#postfix#(self,$i),$min),0),
($min = nqp::atpos_#postfix#(self,$i)),
nqp::if(
nqp::isgt_i(nqp::cmp_#postfix#(
nqp::atpos_#postfix#(self,$i),$max),0),
($max = nqp::atpos_#postfix#(self,$i))
)
)
),
Range.new($min,$max)
),
Range.new(Inf,-Inf)
)
}
method iterator(#type#array:D:) {
class :: does Iterator {
has int $!i;
Expand Down

0 comments on commit dd0fe7f

Please sign in to comment.