Functions(3pm)

πŸ“¦
version 1.24.1 Β· 5 versions
, in debian trixie, ubuntu resolute

πŸ’– Functions(3pm) πŸ’–

okay bestie, so this is PDL::CCS::Functions β€” Useful perl-level functions for PDL::CCS β€” and it lives in the User Contributed Perl Documentation section, which is basically the group chat of the manual pages. pull up a chair, we're decoding sparse matrices together πŸ¦‹


✨ SYNOPSIS ✨

use PDL;
use PDL::CCS::Functions;

##---------------------------------------------------------------------
## ... stuff happens

yep. that's the whole synopsis. "stuff happens" is doing a LOT of heavy lifting here and honestly? respect πŸ’…


πŸŽ€ Decoding πŸŽ€

ccs_decode

Signature: (indx whichnd(Ndims,Nnz); nzvals(Nnz); missing(); \@Dims; [o]a(@Dims))

this one decodes a CCS-encoded matrix. and heads up bestie β€” no dataflow. none. zero. don't come for it. 🫢


🧚 Scalar Operations 🧚

okay so the vibe here is that you can do scalar ops in parallel directly on $nzvals (and, if it applies, on $missing too). look at her go:

$c = 42;

$nzvals2 = $nzvals  + $c;        $missing2 = $missing  + $c;
$nzvals2 = $nzvals  - $c;        $missing2 = $missing  - $c;
$nzvals2 = $nzvals  * $c;        $missing2 = $missing  * $c;
$nzvals2 = $nzvals  / $c;        $missing2 = $missing  / $c;

$nzvals2 = $nzvals ** $c;        $missing2 = $missing ** $c;
$nzvals2 = log($nzvals);         $missing2 = log($missing);
$nzvals2 = exp($nzvals);         $missing2 = exp(missing);

$nzvals2 = $nzvals->and2($c,0);  $missing2 = $missing->and($c,0);
$nzvals2 = $nzvals->or2($c,0);   $missing2 = $missing->or2($c,0);
$nzvals2 = $nzvals->not();       $missing2 = $missing->not();
⚠️ warning bestie ⚠️ nothing is stopping these scalar operations from cooking up brand new "missing" values (looking at you, $nzvals*0 πŸ‘€), so you might wanna re-encode your compressed data after you apply the operation. no cap.

🌈 Vector Operations 🌈

ccs_OP_vector_mia

Signature: (indx whichDimV(Nnz); nzvals(Nnz); vec(V); [o]nzvals_out(Nnz))

so a bunch of row- and column-vector operations can go directly on encoded Nd-PDLs, which means no decoding to a potentially HUGE dense temporary. we love to see it. πŸŽ€

these operations assume that "missing" values are annihilators with respect to whatever operation we're doing β€” i.e. it holds for all $x in $vec that:

($missing __OP__ $x) == $missing

and that's in line with the usual PDL semantics if your $missing value is "BAD". but it may produce unexpected results when you're e.g. adding a vector to a sparse PDL with $missing==0. 😭 if you really need to do something like the latter, then honestly bestie you're probably better off decoding to a dense PDL anyway. it's giving "just use the dense one." πŸ’€

the predefined function names for encoded-PDL vector operations are all of the form "ccs_${OPNAME}_ma", where ${OPNAME} is the base name of the operation:

plus       ##-- addition
minus      ##-- subtraction
mult       ##-- multiplication (NOT matrix-multiplication)
divide     ##-- division
modulo     ##-- modulo
power      ##-- potentiation

gt         ##-- greater-than
ge         ##-- greater-than-or-equal
lt         ##-- less-than
le         ##-- less-than-or-equal
eq         ##-- equality
ne         ##-- inequality
spaceship  ##-- 3-way comparison

and2       ##-- binary AND
or2        ##-- binary OR
xor        ##-- binary XOR
shiftleft  ##-- left-shift
shiftright ##-- right-shift
note the shouty mult ##-- multiplication (NOT matrix-multiplication) β€” read it. internalize it. it's not matrix multiplication. periodt. πŸ’…

\&CODE = ccs_binop_vector_mia($opName, \&PDLCODE);

this one returns a generic vector-operation subroutine that reports errors as $opName and uses \&PDLCODE to do the underlying computation. she's the template, the blueprint, the blueprint-iest πŸ¦‹


🌸 Sorting 🌸

ccs_qsort

Signature: (indx which(Ndims,Nnz); nzvals(Nnz); missing(); Dim0(); indx [o]nzix(Nnz); indx [o]nzenum(Nnz))

this is the underlying guts for PDL::CCS::Nd::qsort() and PDL::CCS::Nd::qsorti(). let's break it down, bestie, because there's a lot going on and it's actually iconic once it clicks:

given a set of $Nnz items $i, each one associated with a vector-key "$which(:,$i)" and a value $nzvals($i), it returns a vector of $Nnz item indices $nzix() such that:

  • "$which(:,$nzix)" is vector-sorted in ascending order
  • "$nzvals(:,$nzix)" is sorted in ascending order for each unique key-vector in $which()

and it also returns an enumeration $nzenum() of items for each unique key-vector in terms of the sorted data β€” specifically, $nzenum($j) is the logical position of the item $nzix($j). slay. ✨

now, the tea: if $missing and $Dim0 are defined, then items "$i=$nzix($j)" with values "$nzvals($i) > $missing" will be logically enumerated at the end of the range [0,$Dim0-1], and there will be a gap between $nzenum() values for a $which()-key with fewer than $Dim0 instances. otherwise, $nzenum() values get enumerated in ascending order starting from 0. iykyk 🧚

for an unsorted index+value dataset "($which0,$nzvals0)" with:

($nzix,$nzenum) = ccs_qsort($which0("1:-1,"),$nzvals0,$missing,$which0("0,")->max+1)

qsort() can be implemented as:

$which  = $nzenum("*1,")->glue(0,$which0("1:-1,")->dice_axis(1,$nzix));
$nzvals = $nzvals0->index($nzix);

and qsorti() as:

$which  = $nzenum("*1,")->glue(0,$which0("1:-1,")->dice_axis(1,$nzix));
$nzvals = $which0("(0),")->index($nzix);

see? iconic. the way that qsort() and qsorti() differ by literally one line of vibes. πŸ’œ


πŸ’œ ACKNOWLEDGEMENTS πŸ’œ

  • Perl by Larry Wall. πŸ‘‘
  • PDL by Karl Glazebrook</>, Tuomas J. Lukka</>, Christian Soeller</>, and others. 🌈

🫢 AUTHOR 🫢

Bryan Jurish <moocow@cpan.org> πŸ’–

Copyright (C) 2007-2024, Bryan Jurish. All rights reserved.

This package is free software, and entirely without warranty β€” no cap, zero warranty, she said what she said. You may redistribute it and/or modify it under the same terms as Perl itself. periodt. πŸ’…


πŸ”₯ SEE ALSO πŸ”₯

  • perl(1)
  • PDL(3perl)
  • PDL::CCS::Nd(3perl)

and that's the whole page bestie πŸŽ€ this was documented in perl v5.40.0, dated 2025-01-04, and it's the Functions(3pm) page β€” go forth and encode, decode, and slay πŸ’–βœ¨πŸ¦‹

πŸ“¦ where this page comes from