PDL

 view release on metacpan or  search on metacpan

lib/PDL/PP.pm  view on Meta::CPAN

        my @inputdecls = map "PDL_Indx ${_}_count=0;", grep $other{$_} && $optypes->{$_}->is_array, @inargs;
        foreach my $x (@inargs) {
          if (!$argorder && ($out{$x} || $other_out{$x} || exists $otherdefaults->{$x})) {
            last if @xsargs + keys(%out) + $noutca != $ntot;
            $argorder = 1; # remaining all output ndarrays, engage
          }
          $cnt++;
          $name2cnts{$x} = [$cnt, $cnt];
          $already_read{$x} = 1;
          push @xsargs, $x.(!$argorder ? '' :
            exists $otherdefaults->{$x} ? "=$otherdefaults->{$x}" :
            !$out{$x} ? '' :
            $inplace && $x eq $inplace->[1] ? "=$x" :
            "=".callPerlInit($x."_SV")
            );
          push @inputdecls, "$ptypes{$x}$x".($inplace && $x eq $inplace->[1] ? "=NO_INIT" : '');
        }
        my $shortcnt = my $xs_arg_cnt = $cnt;
        foreach my $x (@inargs[$cnt+1..$nmaxonstack-1]) {
          $cnt++;
          $name2cnts{$x} = [$cnt, undef];
          $name2cnts{$x}[1] = ++$shortcnt if !($out{$x} || $other_out{$x});
          push @xsargs, "$x=$x";
          push @inputdecls, "$ptypes{$x}$x".($other{$x} && !exists $otherdefaults->{$x} ? "; { ".callTypemap($x, $ptypes{$x}, $name)."; }" : "=NO_INIT");
        }
        push @inputdecls, map "$ptypes{$_}$_=".callPerlInit($_."_SV").";", grep $outca{$_}, @args;
        my $defaults_rawcond = $ndefault ? "items == $nin_minus_default" : '';
        my $svdecls = join '', map "\n  $_",
          (map "SV *${_}_SV = ".(
            !$name2cnts{$_} ? 'NULL' :
            ($argorder || (defined $otherdefaults->{$_} && !$nout)) ? "items > $name2cnts{$_}[1] ? ST($name2cnts{$_}[1]) : ".($other_out{$_} ? "sv_newmortal()" : "NULL") :
            $name2cnts{$_}[0] == ($name2cnts{$_}[1]//-1) ? "ST($name2cnts{$_}[0])" :
            "(items == $nmaxonstack) ? ST($name2cnts{$_}[0]) : ".
            (!defined $name2cnts{$_}[1] ? ($other_out{$_} ? "sv_newmortal()" : "NULL") :
              defined $otherdefaults->{$_} ? "!($defaults_rawcond) ? ST($name2cnts{$_}[1]) : ".($other_out{$_} ? "sv_newmortal()" : "NULL") :
              "ST($name2cnts{$_}[1])"
            )
          ).";", (grep !$already_read{$_}, $sig->names_in), $sig->names_out, @{$sig->othernames(1, 1, \%already_read)}),
          ;
        my $argcode =
          indent(2, join '',
            (map
              "if (!${_}_SV) { $_ = ($otherdefaults->{$_}); } else ".
              "{ ".callTypemap($_, $ptypes{$_}, $name)."; }\n",
              grep !$argorder && exists $otherdefaults->{$_}, @{$sig->othernames(1, 1)}),
            (map callTypemap($_, $ptypes{$_}, $name).";\n", grep !$already_read{$_}, $sig->names_in),
            (map +("if (${_}_SV) { ".($argorder ? '' : callTypemap($_, $ptypes{$_}, $name))."; } else ")."$_ = ".callPerlInit($_."_SV").";\n", grep $out{$_} && !$already_read{$_} && !($inplace && $_ eq $inplace->[1]), @args)
          );
        push @preinit, qq[PDL_XS_PREAMBLE($nretval);] if $nallout;
        push @preinit, qq{if (!(@{[join ' || ', map "(items == $_)", sort keys %valid_itemcounts]}))
    croak("Usage: ${main::PDLOBJ}::$name(@{[
        join ",", map exists $otherdefaults->{$_} ? "$_=$otherdefaults->{$_}" :
             $out{$_} || $other_out{$_} ? "[$_]" : $_, @inargs
    ]}) (you may leave [outputs] and values with =defaults out of list)");}
          unless $only_one || $argorder || ($nmaxonstack == keys(%valid_itemcounts) + $xs_arg_cnt);
        my $preamble = @preinit ? qq[\n PREINIT:@{[join "\n  ", "", @preinit]}\n INPUT:\n] : '';
        join '', qq[
\nvoid
pdl_run_$name(@{[join ', ', @xsargs]})$svdecls
$preamble@{[join "\n  ", "", @inputdecls]}
 PPCODE:
], map "$_\n", $argcode;
      }),

   # globalnew implies internal usage, not XS
   PDL::PP::Rule::Returns->new("VarArgsXSReturn","GlobalNew",undef),
   PDL::PP::Rule->new("FixArgsXSOtherOutDeclSV",
      ["SignatureObj"],
      "Generate XS to declare SVs for output OtherPars",
      sub {
        my ($sig) = @_;
        my $optypes = $sig->otherobjs;
        my @args = @{ $sig->allnames(1, 1) };
        my %outca = map +($_=>1), $sig->names_oca;
        my %other_output = map +($_=>1), my @other_output = ($sig->other_io, $sig->other_out);
        my $ci = 2;
        my $cnt = 0; my %outother2cnt;
        foreach my $x (grep !$outca{$_}, @args) {
            $outother2cnt{$x} = $cnt if $other_output{$x};
            $cnt++;
        }
        join "\n", map indent($ci,qq{SV *${_}_SV = ST($outother2cnt{$_});}), @other_output;
      }),
   PDL::PP::Rule->new("XSOtherOutSet",
      [qw(Name SignatureObj)],
      "Generate XS to set SVs to output values for OtherPars",
      sub {
        my ($name, $sig) = @_;
        my $clause1 = '';
        my @other_output = ($sig->other_io, $sig->other_out);
        my $optypes = $sig->otherobjs;
        my %ptypes = map +($_=>$$optypes{$_}->get_decl('', {VarArrays2Ptrs=>1})), @other_output;
        for my $x (@other_output) {
          my ($setter, $type) = typemap($ptypes{$x}, 'get_outputmap');
          $setter = typemap_eval($setter, {var=>$x, type=>$type, arg=>"tsv",
              pname=>$name});
          $clause1 .= <<EOF;
if (!${x}_SV)
  PDL->pdl_barf("Internal error in $name: tried to output to NULL ${x}_SV");
{\n  SV *tsv = sv_newmortal();
$setter
  sv_setsv(${x}_SV, tsv);\n}
EOF
        }
        indent(2, $clause1);
      }),
   PDL::PP::Rule->new("VarArgsXSReturn",
      ["SignatureObj"],
      "Generate XS trailer to return output variables or leave them as modified input variables",
      sub {
        my ($sig) = @_;
        my $oc = my @outs = $sig->names_out; # output ndarrays in calling order
        my @other_outputs = ($sig->other_io, $sig->other_out); # output OtherPars
        my $clause1 = join ';', (map "ST($_) = $outs[$_]_SV", 0 .. $#outs),
          (map "ST(@{[$_+$oc]}) = $other_outputs[$_]_SV", 0 .. $#other_outputs);
        $clause1 ? indent(2,"PDL_XS_RETURN($clause1)\n") : '';
      }),

   PDL::PP::Rule->new("NewXSHdr", ["NewXSName","SignatureObj"],
      sub {
        my($name,$sig) = @_;



( run in 1.448 second using v1.01-cache-2.11-cpan-5511b514fd6 )