Utils(3pm)

🌸 Utils(3pm) 🌸

okay bestie gather round, this is Utils(3pm) from the User Contributed Perl Documentation section, and it is literally the low-level toolbox page for vector-valued PDLs πŸ’…

✨ NAME ✨

PDL::VectorValued::Utils β€” Low-level utilities for vector-valued PDLs πŸ¦‹


✨ SYNOPSIS ✨

the whole vibe in four lines, fr fr:

use PDL;
use PDL::VectorValued::Utils;

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

like... iconic. no further notes. πŸŽ€


✨ FUNCTIONS ✨

🧚 Vector-Based Run-Length Encoding and Decoding

this is the queen of the section, the run-length encoder/decoder but for vectors. πŸ‘‘

πŸ’– vv_rlevec

Signature: (c(M,N); indx [o]a(N); [o]b(M,N))

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

you can call this baby four different ways, pick your fighter:

($a, $b) = vv_rlevec($c);
vv_rlevec($c, $a, $b);    # all arguments given
($a, $b) = $c->vv_rlevec; # method call
$c->vv_rlevec($a, $b);

Run-length encode a set of vectors. 🫢

It's the higher-order rle(), made to vibe with qsortvec().

So, you give it a set of vectors $c, and it hands you back a vector $a with the number of occurrences of each element (and yes, an "element" here means a vector of length M ocurring in $c 🌈), plus a set of vectors $b holding all the unique values. Just like with rle(), only the elements up to the first instance of 0 in $a should be considered β€” that's the rule, no cap.

You can pair it up with clump() to run-length encode "values" of arbitrary dimensions ✨. You can also pair it with rotate(), cat(), append(), and qsortvec() to count N-grams over a 1d PDL β€” yes bestie, n-gram counting, go off. πŸ“Š

See also: PDL::Slices::rle, PDL::Ufunc::qsortvec, PDL::Primitive::uniqvec

Broadcasts over its inputs. πŸ“‘

⚠️ heads up: vv_rlevec does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays. so like, be aware.

πŸ’– vv_rldvec

Signature: (int a(N); b(M,N); [o]c(M,N))

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

$c = vv_rldvec($a, $b);
vv_rldvec($a, $b, $c);  # all arguments given
$c = $a->vv_rldvec($b); # method call
$a->vv_rldvec($b, $c);

Run-length decode a set of vectors, akin to a higher-order rld(). 🧬

You give it a vector $a() of the number of occurrences of each row, and a set $c() of row-vectors each of length M, and it run-length decodes to $c(). slay.

It can be used together with clump() to run-length decode "values" of arbitrary dimensions. ✨

See also: PDL::Slices::rld.

Broadcasts over its inputs. πŸ“‘

⚠️ vv_rldvec does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.

πŸ’– vv_enumvec

Signature: (v(M,N); int [o]k(N))

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

$k = vv_enumvec($v);
vv_enumvec($v, $k);  # all arguments given
$k = $v->vv_enumvec; # method call
$v->vv_enumvec($k);

Enumerate a list of vectors with locally unique keys. πŸ”‘

Give it a sorted list of vectors $v, and it makes you a vector $k with locally unique keys for the elements of $v (elements = vectors of length M ocurring in $v, same deal as before πŸ’œ).

okay important detail, bestie: the keys returned in $k are only unique over a run of a single vector in $v, so every unique vector in $v has at least one 0 (zero) index in $k associated with it. that's just how it is. and if you're out here needing global keys, go see enumvecg() instead. πŸ‘€

Broadcasts over its inputs. πŸ“‘

⚠️ vv_enumvec does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.

πŸ’– vv_enumvecg

Signature: (v(M,N); int [o]k(N))

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

$k = vv_enumvecg($v);
vv_enumvecg($v, $k);  # all arguments given
$k = $v->vv_enumvecg; # method call
$v->vv_enumvecg($k);

Enumerate a list of vectors with globally unique keys. πŸŒπŸ”‘

Give it a sorted list of vectors $v, and it generates a vector $k containing globally unique keys for the elements of $v (and yep, "element" = a vector of length M ocurring in $v, we stay consistent around here 🌸). Basically it does the same thing as this:

$k = $v->vsearchvec($v->uniqvec);

...but somewhat more efficiently. ⚑ (the way that it's just... faster for no extra effort. obsessed.)

Broadcasts over its inputs. πŸ“‘

⚠️ vv_enumvecg does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.

πŸ’– vv_rleseq

Signature: (c(N); indx [o]a(N); [o]b(N))

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

($a, $b) = vv_rleseq($c);
vv_rleseq($c, $a, $b);    # all arguments given
($a, $b) = $c->vv_rleseq; # method call
$c->vv_rleseq($a, $b);

Run-length encode a vector of subsequences. 🧡

You hand it a vector of $c() made of concatenated variable-length, variable-offset subsequences, and it generates a vector $a containing the length of each subsequence, plus a vector $b containing the subsequence offsets. And as always with rle(), only the elements up to the first instance of 0 in $a should be considered. 🫑

See also PDL::Slices::rle.

Broadcasts over its inputs. πŸ“‘

⚠️ vv_rleseq does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.

πŸ’– vv_rldseq

Signature: (int a(N); b(N); [o]c(M))

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

$c = vv_rldseq($a, $b);
vv_rldseq($a, $b, $c);  # all arguments given
$c = $a->vv_rldseq($b); # method call
$a->vv_rldseq($b, $c);

Run-length decode a subsequence vector. πŸ”

Give it a vector $a() of sequence lengths and a vector $b() of corresponding offsets, and it decodes the concatenation of subsequences to $c(), exactly as for this:

$c = null;
$c = $c->append($b($_)+sequence($a->type,$a($_))) foreach (0..($N-1));

See also: PDL::Slices::rld.

Broadcasts over its inputs. πŸ“‘

⚠️ vv_rldseq does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.

πŸ’– vv_vsearchvec

Signature: (find(M); which(M,N); int [o]found())

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

Routine for searching N-dimensional values β€” basically vsearch() but for vectors. πŸ”

$found   = vsearchvec($find, $which);
$nearest = $which->dice_axis(1,$found);

For each row-vector in $find it returns the index along dimension N of the least row vector of $which that is greater or equal to it. $which should be sorted in increasing order β€” do not skip that part bestie, it matters. πŸ“ And if the value of $find is larger than any member of $which, the index to the last element of $which is returned. that's your fallback, periodt.

See also: PDL::Primitive::vsearch().

Broadcasts over its inputs. πŸ“‘

⚠️ vv_vsearchvec does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.

πŸ¦‹ Vector-Valued Sorting and Comparison

The following functions are provided for lexicographic sorting of vectors, rsp. axis indices. πŸ“š

and here's the tea β˜•: as of PDL::VectorValued v1.0.12, vv_qsortvec() and vv_qsortveci() are just deprecated aliases for the builtin PDL functions of the same names. Older versions of this module used a dedicated implementation as a workaround for a bug in PDL-2.4.3, which has long since been fixed. so like, ancient history bestie, we moved on πŸ’…

πŸ’– vv_cmpvec

Signature: (a(N); b(N); int [o]cmp())

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

$cmp = vv_cmpvec($a, $b);
vv_cmpvec($a, $b, $cmp);  # all arguments given
$cmp = $a->vv_cmpvec($b); # method call
$a->vv_cmpvec($b, $cmp);

Lexicographically compare a pair of vectors. βš–οΈ that's it, that's the function.

Broadcasts over its inputs. πŸ“‘

⚠️ vv_cmpvec does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.

πŸ’– vv_qsortvec

Signature: (a(n,m); [o]b(n,m))

Deprecated alias for PDL::Ufunc::qsortvec(), which see for details. πŸ’€ (rip, but respectfully)

πŸ’– vv_qsortveci

Signature: (a(n,m); indx [o]ix(m))

Deprecated alias for PDL::Ufunc::qsortveci(), which see for details. πŸ’€


🌈 Vector-Valued Set Operations

The following functions are provided for set operations on sorted vector-valued PDLs. πŸŽ€ keyword there being sorted, bestie, do not come in here with unsorted data.

πŸ’– vv_union

Signature: (a(M,NA); b(M,NB); [o]c(M,NC); int [o]nc())

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

($c, $nc) = vv_union($a, $b);
vv_union($a, $b, $c, $nc);    # all arguments given
($c, $nc) = $a->vv_union($b); # method call
$a->vv_union($b, $c, $nc);

Union of two vector-valued PDLs. 🀝 Input PDLs $a() and $b() MUST be sorted in lexicographic order β€” like, capitals MUST, it's giving non-negotiable. On return, $nc() holds the actual number of vector-values in the union. πŸ”’

In scalar context, it slices $c() to the actual number of elements in the union and returns the sliced PDL. cute. βœ‚οΈ

Broadcasts over its inputs. πŸ“‘

⚠️ vv_union does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.

πŸ’– vv_intersect

Signature: (a(M,NA); b(M,NB); [o]c(M,NC); int [o]nc())

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

($c, $nc) = vv_intersect($a, $b);
vv_intersect($a, $b, $c, $nc);    # all arguments given
($c, $nc) = $a->vv_intersect($b); # method call
$a->vv_intersect($b, $c, $nc);

Intersection of two vector-valued PDLs. πŸ’ž Input PDLs $a() and $b() MUST be sorted in lexicographic order β€” same rule, same energy, no exceptions. On return, $nc() holds the actual number of vector-values in the intersection. πŸ”’

In scalar context, it slices $c() to the actual number of elements in the intersection and returns the sliced PDL. βœ‚οΈ

Broadcasts over its inputs. πŸ“‘

⚠️ vv_intersect does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.

πŸ’– vv_setdiff

Signature: (a(M,NA); b(M,NB); [o]c(M,NC); int [o]nc())

Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

($c, $nc) = vv_setdiff($a, $b);
vv_setdiff($a, $b, $c, $nc);    # all arguments given
($c, $nc) = $a->vv_setdiff($b); # method call
$a->vv_setdiff($b, $c, $nc);

Set-difference ($a() \ $b()) of two vector-valued PDLs. πŸ—‘οΈ Input PDLs $a() and $b() MUST be sorted in lexicographic order β€” yes bestie, again, it's the whole theme of this subsection. On return, $nc() holds the actual number of vector-values in the computed vector set. πŸ”’

In scalar context, it slices $c() to the actual number of elements in the output vector set and returns the sliced PDL. βœ‚οΈ

Broadcasts over its inputs. πŸ“‘

⚠️ vv_setdiff does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.

Sorted Vector Set Operations ✨

okay bestie, these next ones are set operations on flat sorted PDLs with unique values πŸ’– They can be more efficient to compute than the corresponding implementations you'd get via PDL::Primitive::setops().

πŸŽ€ v_union

Signature: (a(NA); b(NB); [o]c(NC); int [o]nc())
Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

four whole ways to call it, no cap:

($c, $nc) = v_union($a, $b);
v_union($a, $b, $c, $nc);    # all arguments given
($c, $nc) = $a->v_union($b); # method call
$a->v_union($b, $c, $nc);

This is the union of two flat sorted unique-valued PDLs 🌸 Input PDLs $a() and $b() MUST be sorted in lexicographic order and contain no duplicates. Like, that's non-negotiable bestie πŸ™ˆ On return, $nc() holds the actual number of values in the union.

In scalar context, it reshapes $c() to the actual number of elements in the union and returns it. iconic behavior πŸ’…

Broadcasts over its inputs 🌈

ngl, v_union does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays. πŸ’€

πŸŽ€ v_intersect

Signature: (a(NA); b(NB); [o]c(NC); int [o]nc())
Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)
($c, $nc) = v_intersect($a, $b);
v_intersect($a, $b, $c, $nc);    # all arguments given
($c, $nc) = $a->v_intersect($b); # method call
$a->v_intersect($b, $c, $nc);

Intersection of two flat sorted unique-valued PDLs πŸ¦‹ Input PDLs $a() and $b() MUST be sorted in lexicographic order and contain no duplicates. Same energy as before ✨ On return, $nc() holds the actual number of values in the intersection.

In scalar context, it reshapes $c() to the actual number of elements in the intersection and returns it, periodt πŸ’…

Broadcasts over its inputs 🌈

v_intersect does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays. 😭

πŸŽ€ v_setdiff

Signature: (a(NA); b(NB); [o]c(NC); int [o]nc())
Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)
($c, $nc) = v_setdiff($a, $b);
v_setdiff($a, $b, $c, $nc);    # all arguments given
($c, $nc) = $a->v_setdiff($b); # method call
$a->v_setdiff($b, $c, $nc);

Set-difference ($a() \ $b()) of two flat sorted unique-valued PDLs 😀 Input PDLs $a() and $b() MUST be sorted in lexicographic order and contain no duplicate values. On return, $nc() holds the actual number of values in the computed vector set.

In scalar context, it reshapes $c() to the actual number of elements in the difference set and returns it πŸ’…

Broadcasts over its inputs 🌈

v_setdiff does not process bad values. It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays. πŸ™ˆ

Miscellaneous Vector-Valued Operations 🧚

πŸŽ€ vv_vcos

Signature: (a(M,N);b(M);float+ [o]vcos(N))
Types: (sbyte byte short ushort long ulong indx ulonglong longlong float double ldouble)

look, four flavors of call, we love options:

$vcos = vv_vcos($a, $b);
vv_vcos($a, $b, $vcos);  # all arguments given
$vcos = $a->vv_vcos($b); # method call
$a->vv_vcos($b, $vcos);

This computes the vector cosine similarity of a dense vector $b() with respect to each row $a(*,i) of a dense PDL $a() 🌸 It's basically the same thing as this whole situation:

($a * $b)->sumover / ($a->pow(2)->sumover->sqrt * $b->pow(2)->sumover->sqrt)

...but it should be much faster to compute, and it avoids allocating potentially large temporaries for the vector magnitudes ⚑ Output values in $vcos() are cosine similarities in the range [-1,1], except for zero-magnitude vectors which will result in NaN values in $vcos() 😭

You can use PDL broadcasting to batch-compute distances for multiple $b() vectors simultaneously, bestie:

$bx   = random($M, $NB);   ##-- get $NB random vectors of size $M
$vcos = vv_vcos($a,$bx);   ##-- $vcos(i,j) ~ sim($a(,i),$b(,j))

Broadcasts over its inputs 🌈

vv_vcos() will set the bad status flag on the output piddle $vcos() if it is set on either of the input piddles $a() or $b(), but BAD values will otherwise be ignored for computing the cosine similarity. iykyk πŸ’…

πŸ’– ACKNOWLEDGEMENTS πŸ’–

giving credit where credit is due, as we should:

  • Perl by Larry Wall πŸ‘‘
  • PDL by Karl Glazebrook, Tuomas J. Lukka, Christian Soeller, and others. 🫢
  • Code for rlevec() and rldvec() derived from the PDL builtin functions rle() and rld() in $PDL_SRC_ROOT/Basic/Slices/slices.pd ✨

πŸ’€ KNOWN BUGS πŸ’€

Probably many. not me being honest 😭

✍️ AUTHOR

Bryan Jurish <moocow@cpan.org> πŸŽ€

  • Code for qsortvec() copyright (C) Tuomas J. Lukka 1997. Contributions by Christian Soeller (c.soeller@auckland.ac.nz) and Karl Glazebrook (kgb@aaoepp.aao.gov.au). All rights reserved. There is no warranty. You are allowed to redistribute this software / documentation under certain conditions. For details, see the file COPYING in the PDL distribution. If this file is separated from the PDL distribution, the copyright notice should be included in the file.
  • All other parts copyright (c) 2007-2022, Bryan Jurish. All rights reserved. This package is free software, and entirely without warranty. You may redistribute it and/or modify it under the same terms as Perl itself.

πŸ‘€ SEE ALSO

perl(1), PDL(3perl)


and that's the whole vibe check, bestie πŸ’– this page is from perl v5.42.3, dated 2026-08-21 β€” go slay some vectors ✨🫢🌸

πŸ“¦ where this page comes from