## dist_zef-lichtkind-Math-Matrix.md
## Chunk 2 of 3
 of a none zero value from the main [diagonal](#diagonal). A matrix that [is-diagonal](#is-diagonal) has a bandwith of 0. If there is a none zero value on an diagonal above or below the main diagonal, tha bandwith would be one.

```
my $bw = $matrix.bandwith;

```

#### [lower-bandwith](#bandwith)

In a matrix with the lower bandwith of k, every [element](#element) with row index m and column index n, for which holds m - k > n, the content has to be zero. Literally speaking: there are k [diagonal](#diagonal)s below the main diagonal, that contain none zero values.

#### [upper-bandwith](#bandwith)

Analogously, every [element](#element) with m + k < n is zero if matrix has an upper bandwith of k.

```
Example:    1  0  0
            4  2  0
            0  5  3

```

The *bidiagonal* example matrix has an upper bandwith of zero and lower bandwith of one, so the overall bandwith is one.

### [trace](#numeric-properties)

The trace of a [square](#is-square) matrix is the sum of the [element](#element)s on the main diagonal. In other words: sum of elements which row and column value is identical.

```
my $tr = $matrix.trace;

```

### [rank](#numeric-properties)

Rank is the number of independent row or column vectors or also called independent dimensions (thats why this command is sometimes calles dim)

```
my $r = $matrix.rank;

```

### [nullity](#numeric-properties)

Nullity of a matrix is the number of dependent rows or columns (rank + nullity = dim). Or number of dimensions of the kernel (vector space mapped by the matrix into zero).

```
my $n = $matrix.nullity;

```

### [determinant](#numeric-properties)

Only a [square](#is-square) matrice has a defined determinant, which tells the volume, spanned by the row or column vectors. So if the volume is just in one dimension flat, the determinant is zero, and has a kernel (not a full [rank](#rank) - thus is not [invertible](#is-invertable)).

```
my $det = $matrix.determinant;
my $d = $matrix.det;                # same thing
my $d = ❘ $matrix ❘;                # unicode operator shortcut

```

### [minor](#numeric-properties)

A Minor is the determinant of a [submatrix](#leaving-out-one) (first variant with same 2 scalar arguments a minor method). The two required positional arguments are row and column indices of an existing [element](#element).

```
my $m = $matrix.minor(1,2);

```

### [norm](#numeric-properties)

A norm is a single positive number, which is an abstraction to the concept of size. Most common form for matrices is the p-norm, where in step 1 the absolute value of every [element](#element) is taken to the power of p. The sum of these results is taken to the power of 1/p. The p-q-Norm extents this process. In his step 2 every column-sum is taken to the power of (p/q). In step 3 the sum of these are taken to the power of (1/q).

```
my $norm = $matrix.norm( );           # euclidian norm aka L2 (p = 2, q = 2)
my $norm = + $matrix;                 # context op shortcut
my $norm = ‖ $matrix ‖;               # unicode op shortcut
my $norm = $matrix.norm(1);           # p-norm aka L1 = sum of all elements absolute values (p = 1, q = 1)
my $norm = $matrix.norm(p:<4>,q:<3>); # p,q - norm, p = 4, q = 3
my $norm = $matrix.norm(p:<2>,q:<2>); # L2 aka Euclidean aka Frobenius norm
my $norm = $matrix.norm('euclidean'); # same thing, more expressive to some
my $norm = $matrix.norm('frobenius'); # same thing, more expressive to some
my $norm = $matrix.norm('max');       # maximum norm - biggest absolute value of a element
$matrix.norm('row-sum');              # row sum norm - biggest abs. value-sum of a row
$matrix.norm('column-sum');           # column sum norm - same column wise

```

### [condition](#numeric-properties)

Condition number of a matrix is L2 norm \* L2 of [inverted](#inverted) matrix.

```
my $c = $matrix.condition( );

```

### [element-type](#numeric-properties)

#### [narrowest-element-type](#numeric-properties)

#### [widest-element-type](#numeric-properties)

Matrix [element](#element)s can be (from most narrow to widest), of type (Bool), (Int), (Num), (Rat), (FatRat) or (Complex). The widest type of any element will returned as type object.

In the next example the smartmatch returns true, because no element of our default example matrix has wider type than (Int). After such a test all elements can be safely treated as Int or Bool.

```
if $matrix.widest-element-type ~~ Int { ...

```

You can also check if all elements have the same type:

```
if $matrix.widest-element-type eqv $matrix.narrowest-element-type

```

## [Derived Matrices](#methods)

Single matrices, that can be computed with only our original matrix as input.

[transposed](#transposed), [negated](#negated), [conjugated](#conjugated), [adjugated](#adjugated), [inverted](#inverted), [reduced-row-echelon-form](#reduced-row-echelon-form)

### [transposed](#derived-matrices)

Returns a new, transposed Matrix, where rows became colums and vice versa.

```
Math::Matrix.new([[1,2,3],[3,4,6]]).transposed :

[[1 2 3]     = [[1 4]
 [4 5 6]].T     [2 5]
                [3 6]]

Math::Matrix.new([[1,2,3],[3,4,6]]).T # same but shorter

```

### [negated](#derived-matrices)

Creates a matrix where every [element](#element) has the negated value of the original (invertion of sign).

```
my $new = $matrix.negated();     # invert sign of all elements
my $neg = - $matrix;             # operator alias

say $neg:  -1 -2
           -3 -4

```

### [conjugated](#derived-matrices)

Creates a matrix where every [element](#element) is the complex conjugated of the original.

```
my $c = $matrix.conjugated();    # change every value to its complex conjugated
my $c = $matrix.conj();          # short alias (official Raku shortcut for conjugation of numbers)

say Math::Matrix.new([[1+i,2],[3,4-i]]).conj :

1-1i  2
3     4+1i

my $ct = $matrix.H;              # conjugated and transposed matrix (Hermitian transpose)

```

### [adjugated](#derived-matrices)

Creates a matrix out of the properly signed [minors](#minor) of the original. It is called adjugate, classical adjoint or sometimes adjunct.

```
$matrix.adjugated.say :

 4 -3
-2  1

```

### [inverted](#derived-matrices)

Matrices that have a [square](#is-square) form and a full [rank](#rank) can be [inverted](#inverted) (see [is-invertible](#is-invertible)). Inverse matrix regarding to matrix multiplication (see [dot-product](#dot-product)). The dot product of a matrix with it's inverted results in a [identity](#is-identity) matrix (neutral element in this group).

```
my $i = $matrix.inverted();      # invert matrix
my $i = $matrix ** -1;           # operator alias

say $i:

 -2    1
1.5 -0.5

```

### [reduced-row-echelon-form](#derived-matrices)

Return the reduced row echelon form of a matrix, a.k.a. row canonical form

```
my $rref = $matrix.reduced-row-echelon-form();
my $rref = $matrix.rref();       # short alias

```

## [Decompositions](#methods)

Methods that return a list of matrices, which can be recombined into the original matrix (mostly by [dot product](#dot-product)).

[LU](#LU-decomposition), [LU-Crout](#LU-Crout-decomposition), [LDU](#LDU-decomposition), [LUP](#LUP-decomposition), [Cholesky](#Cholesky-decomposition) [LDL](#LDL-decomposition)

### [LU-decomposition](#decompositions)

Decompose an [invertible](#is-invertible), matrix into a [lower triangular](#is-lower-triangular) (called L) and an [upper triangular matrix](#is-upper-triangular) (called U). The algorithm works along the lines of what is called Gaussian elimination.

```
my ($L, $U) = $matrix.LU-decomposition();
$L dot $U eq $matrix;                # True
$U.is-triangular(:upper);             # True
$L.is-triangular(:lower, :unit);       # True

```

#### [LU-Crout-decomposition](#decompositions)

L will also be [unit triangular matrix](#unit-triangular), but not U - meaning the [diagonal](#diagonal) elements of L are all equal 1 and the diagonal elements of U might differ from 1. If you prefer this to be the other way around, use the optional, boolean parameter *:Crout*.

```
my ($L, $U) = $matrix.LU-decomposition(:Crout);
$L dot $U eq $matrix;                # True
$L.is-triangular(:lower);             # True
$U.is-triangular(:upper, :unit);       # True

```

#### [LDU-decomposition](#decompositions)

If you want the diagonal elements separated into its own matrix, use the optional, boolean parameter *:diagonal*. Note that you can not use this and *:Crout* at once.

```
my ($L, $D, $U) = $matrix.LU-decomposition( :diagonal);
$L dot $D dot $U eq $matrix;         # True
$L.is-triangular(:lower, :unit);      # True
$U.is-triangular(:upper, :unit);       # True
$D.is-diagonal();                       # True

```

#### [LUP-decomposition](#decompositions)

If you choose the optional, boolean parameter *:pivot*, you get additionally a permutation matrix, that contains the information which rows and columns were swapped, in order to achieve a decomposition. That is why the matrix no longer has to be [invertible](#is-invertable), but only [square](#is-square) to run a LU decomposition with permutation. This option might be combined with *:Crout* or *:diagonal*, but not both.

```
my ($L, $U, $P) = $matrix.LU-decomposition( :pivot );
$L dot $U eq $matrix dot $P;         # True

```

### [Cholesky-decomposition](#decompositions)

This decomposition does roughly the same as LU and is faster. But it works only on matrices that are [symmetric](#is-symmetric) and [positive-definite](#is-positive-definite). The result will be an [orthogonal](#is-orthogonal), [lower triangular matrix](#is-lower-triangular) matrix (here called G) that multiplied with its [transposed](#transposed) gives you the original matrix.

```
my $G = $matrix.Cholesky-decomposition( );          # $G is a left triangular matrix
my $G = $matrix.Cholesky-decomposition(:!diagonal); # same as before
$G dot $G.T == $matrix;                             # True

```

#### [LDL-decomposition](#decompositions)

When the optional, boolean parameter :diagonal is positive (negative by default) you get two matrices (L and D) as a result. L is then a [lower unit triangular matrix](#unit-triangular), (with ones in its main diagonal). D is a [diagonal](#diagonal) matrix ( G = L \* sqrt(D)), containing the values formerly on the diagonal of G, but squared. This output format is also known as *LDL decomposition*. You get the second L matrix easily by transposing the L you got.

```
my ($L, $D) = $matrix.Cholesky-decomposition(:diagonal);
$L dot $D dot $L.T == $matrix;                      # True

```

## [Mathematical Operations](#methods)

Math methods that work on a whole matrix or just some parts of it. The operands will not be changed but a the result matrix will be returned.

[equal](#equal), **[add](#add)**: ([matrix](#add-matrix), [vector](#add-vector), [scalar](#add-scalar)), **[multiply](#multiply)**: ([matrix](#multiply-matrix), [vector](#multiply-vector), [scalar](#multiply-scalar)), [dot-product](#dot-product), [tensor-product](#tensor-product).

### [equal](#mathematical-operations)

Checks two matrices for equality. They have to be of same [size](#size) and every [element](#element) of the first matrix on a particular position has to be numerically equal (as checked by *==*) to the element (on the same position) of the second matrix.

```
if $matrixa.equal( $matrixb ) {   # method variant
if $matrixa == $matrixb {         # operator alias
if $matrixa ~~ $matrixb {         # smart match redirects to ==

```

### [add](#mathematical-operations)

Adding a matrix, [vector](#add-vector) or [scalar](#scalar-scalar). Named arguments *:row* and *:column* are only used to add a vector (one) or scalar (both).

#### [add matrix](#add)

When adding two matrices, they have to be of the same [size](#size). Instead of a Math::Matrix object you can also provide the content of a matrix as [new []](#new--), [new ()](#new---1) or [new ""](#new---2) would accept it.

```
$matrix.add( $matrix2 );
$matrix.add( [[2,3],[4,5]] ); # data alias
$matrix + $matrix2            # operator alias

Example:    1 2  +  2 3  =  3 5
            3 4     4 5     7 9

```

#### [add vector](#add)

To add a vector you have to specify to which row or column it should be added. The other argument is a list or array (which have to fit the row or column size).

```
$matrix.add( row => 1, [2,3] );

Example:    1 2  +       =  1 2
            3 4    2 3      5 7

$matrix.add( column => 1, (2,3) );

Example:    1 2  +   2   =  1 4
            3 4      3      3 7

```

#### [add scalar](#add)

When adding a single number to the matrix (providing one argument), the number will be added to every [element](#element) of the matrix. If you additionally provide a row or column number, only in that row or column, every element gets added to. In case you provide row and column numbber (three args), only a single element of the result matrix might be different.

```
$matrix.add( $number );       # adds number to every element
$matrix + $number;            # works too

Example:    1 2  +  5    =  6 7
            3 4             8 9

$matrix.add( row => 1, 3 ):             [[1,2],[6,7]]
$matrix.add( row => 1, column=> 0, 2 ): [[1,2],[5,4]]

```

### [multiply](#mathematical-operations)

Unlike the [dot-product](#dot-product) and [tensor-product](#tensor-product), this operation is the simple, scalar multiplication applied to each ore some [element](#element)s. The second factor might come from the cells of another [matrix](#multiply-matrix), a [vector](#multiply-vector) or a [single value](#multiply-scalar). That is why this method works analogous to [add](#add).

#### [multiply matrix](#multiply)

When a matrix of same size is given, the result will be a matrix of that size again. Each element will be the product of two the two elements of the operands with the same indices (position). Instead of a Math::Matrix object you can also provide the content of a matrix as [new []](#new--), [new ()](#new---1) or [new ""](#new---2) would accept it.

```
my $product = $matrix.multiply( $matrix2 );  # element wise multiplication of same size matrices
my $p = $matrix * $matrix2;                  # works too

Example:    1 2  *  2 3  =   2  6
            3 4     4 5     12 20

```

#### [multiply vector](#multiply)

Takes a vector (list of numbers) and a Pair thst specifies an existing row or column. This row or column will than multiplied with the vector (element one by vector element one, and so on).

```
my $product = $matrix.multiply( row => 0, (2, 3) );   # multiply every element with number

Example:    1 2  *  2 3  =  2 6
            3 4             3 4

```

#### [multiply scalar](#multiply)

If you provide just one number, every matrix element will be multiplied by this number. When you additionally add a valid row or column index, only the cells in that row or column get multiplied. (This is especially useful, when doing Gaussian elimination.) If both are provided, only one cell gets multiplied.

```
my $product = $matrix.multiply( $number );   # multiply every element with number
my $p = $matrix * $number;                   # does the same

Example:    1 2  *  5    =   5 10
            3 4             15 20

$matrix.multiply( row => 0, 2);

Example:    1 2  * 2     =  2 4
            3 4             3 4

$matrix.multiply(2, column => 0 );

Example:    1 2   =  2 2
            3 4      6 4

           *2

$matrix.multiply(row => 1, column => 1, 3) : [[1,2],[3,12]]

```

### [dot-product](#mathematical-operations)

Matrix multiplication of two fitting matrices (colums left == rows right).

```
Math::Matrix.new( [[1,2],[3,4]] ).dot-product(  Math::Matrix.new([[2,3],[4,5]]) );

Example:    2  3
            4  5
         *
     1 2   10 13  =  1*2+2*4  1*3+2*5
     3 4   22 29     3*2+4*4  3*3+4*5

my $product = $matrix1.dot-product( $matrix2 )
my $c = $a dot $b;              # works too as operator alias
my $c = $a ⋅ $b;                # unicode operator alias

A shortcut for multiplication is the power - operator **
my $c = $a **  3;               # same as $a dot $a dot $a
my $c = $a ** -3;               # same as ($a dot $a dot $a).inverted
my $c = $a **  0;               # created an right sized identity matrix

```

### [tensor-product](#mathematical-operations)

The *tensor product* (a.k.a *Kronecker product*) between a matrix A of *size|#size* (m,n) and matrix B of size (p,q) is a matrix C of size (m*p,n*q). C is a concatination of matrices you get if you take every [element](#element) of A and do a [scalar multiplication](#multiply) with B as in $B.multiply($A.element(..,..)).

```
Example:    1 2  X*  2 3   =  1*[2 3] 2*[2 3]  =  2  3  4  6
            3 4      4 5        [4 5]   [4 5]     4  5  8 10
                              3*[2 3] 4*[2 3]     6  9  8 12
                                [4 5]   [4 5]     8 15 16 20

my $c = $matrixa.tensor-product( $matrixb );
my $c = $a X* $b;               # works too as operator alias
my $c = $a ⊗ $b;                # unicode operator alias

```

## [List Like Operations](#methods)

Methods (or extensions thereof) that usually are provided by Lists and Arrays, but make also sense in context of matrices: [elems](#elems), [elem](#elem), [cont](#cont), [map](#map), [map-with-index](#map-with-index), [reduce](#reduce), [reduce-rows](#reduce-rows), [reduce-columns](#reduce-columns)

### [elems](#list-like-operations)

Number (count) of [element](#element)s = rows \* columns (see [size](#size)).

```
say $matrix.elems();

```

### [elem](#list-like-operations)

Asks if all [element](#element) of Matrix (cell) values are an element of the given set or range.

```
Math::Matrix.new([[1,2],[3,4]]).elem(1..4) :   True
Math::Matrix.new([[1,2],[3,4]]).elem(2..5) :   False, 1 is not in 2..5

```

### [cont](#list-like-operations)

Asks if the matrix contains a value equal to the only argument of the method. If a range is provided as argument, at least one value has to be within this range to make the result true.

```
Math::Matrix.new([[1,2],[3,4]]).cont(1)   : True
Math::Matrix.new([[1,2],[3,4]]).cont(5)   : False
Math::Matrix.new([[1,2],[3,4]]).cont(3..7): True

MM [[1,2],[3,4]] (cont) 1                 # True too

```

### [map](#list-like-operations)

Creates a new matrix of same size by iterating over all or some [element](#element)s. For every chosen element with the indices (m,n), a provided code block (required argument) will be run once. That block will be given the elements(m,n) value as an argument. The return value of the block will be the content of the element(m,n) of the resulting matrix.

```
say $matrix.map(* + 1) :

2 3
4 5

```

By provding values (Ranges) to the named arguments *rows* and *columns* (no special order required), only a subset of rows or columns will be mapped - the rest will be just copied.

```
say $matrix.map( rows => (0..0), {$_ * 2}) :

2 4
3 4

say $matrix.map( rows => (1..*), columns => (1..1), {$_ ** 2}) :

1  2
3 16

```

### [map-with-index](#list-like-operations)

Works just like [map](#map) with the only difference that the given block can recieve one to three arguments: (row index, column index and cell value).

```
say $matrix.map-with-index: {$^m == $^n ?? $^value !! 0 } :

1 0
0 4

```

### [reduce](#list-like-operations)

Like the built in reduce method, it iterates over all [element](#element)s and joins them into one value, by applying the given operator or method to the previous result and the next element. I starts with the element [0][0] and moving from left to right in the first row and continue with the first element of the next row.

```
Math::Matrix.new([[1,2],[3,4]]).reduce(&[+]): 10 = 1 + 2 + 3 + 4
Math::Matrix.new([[1,2],[3,4]]).reduce(&[*]): 10 = 1 * 2 * 3 * 4

```

### [reduce-rows](#list-like-operations)

Reduces (as described above) every row into one value, so the overall result will be a list. In this example we calculate the sum of all elements in a row:

```
say Math::Matrix.new([[1,2],[3,4]]).reduce-rows(&[+]): (3, 7)

```

### [reduce-columns](#list-like-operations)

Similar to reduce-rows, this method reduces each column to one value in the resulting list:

```
say Math::Matrix.new([[1,2],[3,4]]).reduce-columns(&[*]): (3, 8)

```

## [Structural Operations](#methods)

Methods that reorder rows and columns, delete some or even add new. The accessor [submatrix](#submatrix) is also useful for that purpose. [move-row](#move-row), [move-column](#move-column), [swap-rows](#swap-rows), [swap-rows](#swap-columns), [splice-rows](#splice-rows), [splice-columns](#splice-columns)

### [move-row](#structural-matrix-operations)

```
Math::Matrix.new([[1,2,3],[4,5,6],[7,8,9]]).move-row(0,1);  # move row 0 to 1
Math::Matrix.new([[1,2,3],[4,5,6],[7,8,9]]).move-row(0=>1); # same

1 2 3           4 5 6
4 5 6    ==>    1 2 3
7 8 9           7 8 9

```

### [move-column](#structural-matrix-operations)

```
Math::Matrix.new([[1,2,3],[4,5,6],[7,8,9]]).move-column(2,1);
Math::Matrix.new([[1,2,3],[4,5,6],[7,8,9]]).move-column(2=>1); # same

1 2 3           1 3 2
4 5 6    ==>    4 6 5
7 8 9           7 9 8

```

### [swap-rows](#structural-matrix-operations)

```
Math::Matrix.new([[1,2,3],[4,5,6],[7,8,9]]).swap-rows(2,0);

1 2 3           7 8 9
4 5 6    ==>    4 5 6
7 8 9           1 2 3

```

### [swap-columns](#structural-matrix-operations)

```
Math::Matrix.new([[1,2,3],[4,5,6],[7,8,9]]).swap-columns(0,2);

1 2 3           3 2 1
4 5 6    ==>    6 5 4
7 8 9           9 8 7

```

### [splice-rows](#structural-matrix-operations)

Like the splice for lists: the first two parameter are position and amount (optional) of rows to be deleted. The third and alos optional parameter will be an array of arrays (line .new would accept), that fitting row lengths. These rows will be inserted before the row with the number of first parameter. The third parameter can also be a fitting Math::Matrix.

```
$matrix.splice-rows(0,0, Math::Matrix.new([[5,6],[7,8]]) ); # aka prepend
$matrix.splice-rows(0,0,                  [[5,6],[7,8]]  ); # same result

5 6
7 8
1 2
3 4

$matrix.splice-rows(1,0, Math::Matrix.new([[5,6],[7,8]]) ); # aka insert
$matrix.splice-rows(1,0,                  [[5,6],[7,8]]  ); # same result

1 2
5 6
7 8
3 4

$matrix.splice-rows(1,1, Math::Matrix.new([[5,6],[7,8]]) ); # aka replace
$matrix.splice-rows(1,1,                  [[5,6],[7,8]]  ); # same result

1 2
5 6
7 8

$matrix.splice-rows(2,0, Math::Matrix.new([[5,6],[7,8]]) ); # aka append
$matrix.splice-rows(2,0,                  [[5,6],[7,8]]  ); # same result
$matrix.splice-rows(-1,0,                 [[5,6],[7,8]]  ); # with negative index

1 2
3 4
5 6
7 8

```

### [splice-columns](#structural-matrix-operations)

Same as splice-rows, just horizontally.

```
$matrix.splice-columns(2,0, Math::Matrix.new([[5,6],[7,8]]) ); # aka append
$matrix.splice-columns(2,0,                  [[5,6],[7,8]]  ); # same result
$matrix.splice-columns(-1,0,                 [[5,6],[7,8]]  ); # same result with negative index

1 2  ~  5 6  =  1 2 5 6
3 4     7 8     3 4 7 8

```

## [Shortcuts](#methods)

Summary of all shortcut aliases (left) and their long form (right).

* T --> [transposed](#transposed)
* H --> [conjugated and transposed](#conjugated)
* conj --> [conjugated](#conjugated)
* det --> [determinant](#determinant)
* rref --> [reduced-row-echelon-form](#reduced-row-echelon-form)

## [Operator Methods](#methods)

Operators (left) with the methods they refer to (right). (Most ops are just aliases.) For more explanations of the ops (with examples) see the [next chapter](#operators):

* prefix ? --> [Bool](#bool)
* prefix + --> [Numeric](#numeric)
* prefix - --> [negated](#negated)
* prefix ~ --> [Str](#str)
* prefix | --> [list](#list)
* prefix @ --> [Array](#array)
* prefix % --> [Hash](#hash)
* prefix MM --> [new](#new--)
* infix == --> [equal](#equal)
* infix ~~ --> [equal](#equal) ACCEPTS
* infix + --> [add](#add)
* infix - --> [add](#add)
* infix \* --> [multiply](#multiply)
* infix ⋅ dot --> [dot-product](#dot-product)
* infix ÷ --> dot-product [inverted](#inverted)
* infix \*\* --> dot-product inverted
* infix ⊗ X\* --> [tensor-product](#tensor-product)
* circumfix ｜..｜ --> [determinant](#determinant)
* circumfix ‖..‖ --> [norm](#norm)
* postcircumfix [..] --> [AT-POS](#at-pos)

# [Operators](#synopsis)

The Module overloads or introduces a range of well and lesser known ops, which are almost all [aliases](#operator-methods).

==, +, \* are commutative, -, ⋅, dot, ÷, x, ⊗ and \*\* are not. All ops have same precedence as its multi method siblings - unless stated otherwise.

They are exported when using no flag (same as :DEFAULT) or :ALL, but not under :MANDATORY or :MM). The only exception is MM operator, a shortcut to create a matrix. That has to be importet explicitly with the tag :MM or :ALL. The postcircumfix [] - op will always work.

```
my $a   = +$matrix               # Num context, Euclidean norm
my $b   = ?$matrix               # Bool context, True if any element has a none zero value
my $str = ~$matrix               # String context, matrix content, space and new line separated as table
my $l   = |$matrix               # list context, list of all elements, row-wise
my $a   = @ $matrix              # same thing, but as Array
my $h   = % $matrix              # hash context, similar to .kv, so that %$matrix{0}{0} is first element

$matrixa == $matrixb             # check if both have same size and they are element wise equal
$matrixa ~~ $matrixb             # same thing

my $sum =  $matrixa + $matrixb;  # element wise sum of two same sized matrices
my $sum =  $matrix  + $number;   # add number to every element

my $dif =  $matrixa - $matrixb;  # element wise difference of two same sized matrices
my $dif =  $matrix  - $number;   # subtract number from every element
my $neg = -$matrix               # negate value of every element

my $p   =  $matrixa * $matrixb;  # element wise product of two same sized matrices
my $sp  =  $matrix  * $number;   # multiply number to every element

my $dp  =  $a dot $b;            # dot product of two fitting matrices (cols a = rows b)
my $dp  =  $a ⋅ $b;              # dot product, unicode (U+022C5)
my $dp  =  $a ÷ $b;              # alias to $a dot $b.inverted, (U+000F7)

my $c   =  $a **  3;             # $a to the power of 3, same as $a dot $a dot $a
my $c   =  $a ** -3;             # alias to ($a dot $a dot $a).inverted
my $c   =  $a **  0;             # creates an right sized identity matrix

my $tp  =  $a X* $b;             # tensor product, same precedence as infix: x (category Replication)
my $tp  =  $a ⊗ $b;              # tensor product, unicode (U+02297)

 ｜$matrix ｜                     # determinant, unicode (U+0FF5C)
 ‖ $matrix ‖                     # L2 norm (euclidean p=2 to the square), (U+02016)

   $matrix[1][2]                 # 2nd row, 3rd column element - works even under :MANDATORY tag

MM [[1]]


## dist_zef-lichtkind-Math-Matrix.md
## Chunk 3 of 3
                         # a new matrix, has higher precedence than postcircumfix:[]
MM '1'                           # string alias

```

# [Export Tags](#synopsis)

* :MANDATORY (nothing is exported)
* :DEFAULT (same as no tag, most [ops](#operators) will be exported)
* :MM (only [MM](#new--) op exported)
* :ALL

# [Authors](#synopsis)

* Pierre Vigier
* Herbert Breunung

# [Contributors](#synopsis)

* Patrick Spek
* Juan Julián Merelo Guervós

# [License](#synopsis)

Copyright 2015 - 2020 Pierre Vigier, Herbert Breunung

Copyright 2024 The Raku Community

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.

# [See Also](#synopsis)

* Math::Libgsl::Matrix


## dist_github-tokuhirom-Getopt-Tiny.md
[![Build Status](https://travis-ci.org/tokuhirom/p6-Getopt-Tiny.svg?branch=master)](https://travis-ci.org/tokuhirom/p6-Getopt-Tiny)

# NAME

Getopt::Tiny - Tiny option parser for Perl6

# SYNOPSIS

```
use v6;

use Getopt::Tiny;

my $opts = { host => '127.0.0.1', port => 5000 };

get-options($opts, <
    e=s
    I=s@
    p=i
    h|host=s
>);

```

# DESCRIPTION

Getopt::Tiny is tiny command line option parser library for Perl6.

# FEATURES

* Fluent interface
* Built-in pod2usage feature

# MOTIVATION

Perl6 has a great built-in command line option parser. But it's not flexible. It's not perfect for all cases.

# Function interface

## `get-options(Hash $opts, Array[Str] $definitions, Bool :$pass-through=False)`

Here is a synopsis code:

```
get-options($args, <
    e=s
    I=s@
    p=i
    h|host=s
>);

```

`$definitions`' grammar is here:

```
token TOP { <key> '=' <type> }
token key { <short> [ '|' <long> ]?  | <long> }

token short { <[a..z A..Z]> }
token long { <[a..z A..Z]> <[a..z A..Z 0..9]>+ }

token type {
    's'  | # str
    's@' | # array of string
    '!'  | # bool
    'i'    # int
}

```

Parse options from `@*ARGS`.

`$opts` should be Hash. This function writes result to `$opts`.

`$definitions` should be one of following style.

If you want to pass-through unknown option, you can pass `:pass-through` as a named argument like following:

```
get-options($x, $y, :pass-through);

```

This function modifies `@*ARGS` and `$PROCESS::ARGFILES`.

# OO Interface

## METHODS

### `my $opt = Getopt::Tiny.new()`

Create new instance of the parser.

### `$opt.str($opt, $callback)`

If `$opt` has 1 char, it's equivalent to `$opt.str($opt, Nil, $callback)`, `$opt.str(Nil, $opt, $callback)` otherwise.

### `$opt.str($short, $long, $callback)`

Add string option.

`$short` accepts `-Ilib` or `-I lib` form. `$long` accepts `--host=lib` or `--host lib` form.

Argument of `$callback` is `Str`.

### `$opt.int($opt, $callback)`

If `$opt` has 1 char, it's equivalent to `$opt.int($opt, Nil, $callback)`, `$opt.int(Nil, $opt, $callback)` otherwise.

### `$opt.int($short, $long, $callback)`

Add integer option.

`$short` accepts `-I3` or `-I 3` form. `$long` accepts `--port=5963` or `--port 5963` form.

Argument of `$callback` is `Int`.

### `$opt.bool($opt, $callback)`

If `$opt` has 1 char, it's equivalent to `$opt.bool($opt, Nil, $callback)`, `$opt.bool(Nil, $opt, $callback)` otherwise.

### `$opt.bool($short, $long, $callback)`

Add boolean option.

`$short` accepts `-x` form. `$long` accepts `--man-pages` or `--no-man-pages` form.

Argument of `$callback` is `Bool`.

### `$opt.parse(@args)`

Run the option parser. Return values are positional arguments.

This operation does *not* modify `@*ARGS` and `$PROCESS::ARGFILES`.

# pod2usage

This library shows POD's SYNOPSIS section in your script as help message, when it's available.

# COPYRIGHT AND LICENSE

Copyright 2015 Tokuhiro Matsuno [tokuhirom@gmail.com](mailto:tokuhirom@gmail.com)

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## async.md
role X::Proc::Async

Exception thrown by Proc::Async

```raku
role X::Proc::Async is Exception { ... }
```

All exceptions thrown by [`Proc::Async`](/type/Proc/Async) do this common role.

# [Methods](#role_X::Proc::Async "go to top of document")[§](#Methods "direct link")

## [method proc](#role_X::Proc::Async "go to top of document")[§](#method_proc "direct link")

```raku
method proc(X::Proc::Async:D --> Proc::Async)
```

Returns the object that threw the exception.


## dist_zef-thundergnat-List-Divvy.md
# NAME List::Divvy

[![test](https://github.com/thundergnat/List-Divvy/actions/workflows/test.yml/badge.svg)](https://github.com/thundergnat/List-Divvy/actions/workflows/test.yml)

Various shortcut keyword routines to divide up monotonic Positional objects based on element values.

# SYNOPSIS

```
use List::Divvy;

my $list = 1..∞; # an infinite range

# show the values in the list before a value greater than or equal to 5
put $list.&before(5); # 1 2 3 4

# show the values in the list up to and including a value equal to 5
put $list.&upto(5); # 1 2 3 4 5

# show the first 5 values in the list greater than 5
put $list.&after(5).head(5); # 6 7 8 9 10

# show the first 5 values in the list greater than or equal to 5
put $list.&from(5).head(5); # 5 6 7 8 9

# show the values between 10 and 15
put $list.&between(10, 15); # 11 12 13 14

# show the values bounded by 10 and 15
put $list.&bounded(10, 15); # 10 11 12 13 14 15

```

# DESCRIPTION

Convenience routines to "divvy" up a positional object based on the element values.

When presenting a portion of an array or list, it is simple in Raku to return a specific number or range of elements `@array[^5]`, `@array[15..20]` or some such. Often you need to find the elements whose **value** is in some range. "Show the elements with values less than 100" or "find the elements with values between 25 and 50". There are no built-in routines in Raku to directly do that. It is possible to do but often a little convoluted.

This module exposes several routines to easily partition positionals. These routines are perfectly capable of working with infinite lists and will **not** attempt to reify the whole list to return the requested values.

**Note:** there is at least one other Raku module available ([List::MoreUtils](https://modules.raku.org/dist/List::MoreUtils:zef:zef:lizmat)) that provides similar list partition functionality. [List::MoreUtils](https://modules.raku.org/dist/List::MoreUtils:zef:zef:lizmat) is a Perl 5 port though, and the routines from there are formatted `routine($threshold, @list)` rather than `routine(@list, $threshold)`, which makes it much more difficult to do routine chaining. In this module, the list out from any routine is suitable as the first input parameter to any other routine.

These routines primarily are geared to monotonically increasing numeric values. They can be used with decreasing or variable lists but may not return the results expected.

They will all accept both Real defined numeric values for thresholds, or, Callable blocks or WhateverCodes.

Exports the Subs:

* [before( )](#before)
* [after( )](#after)
* [upto( )](#upto)
* [from( )](#from)
* [between( )](#between)
* [bounded( )](#bounded)

Use `before()` and `after()` to partition out value less than or greater than some threshold **not** including the threshold value.

## before( )

Returns the list of values `before()` the given defined value or WhateverCode.

### before( Cool @array, Real $value ); or before( Cool @array, Callable $block );

* @array

  * Positional object; any array, list or list-like object
* $value

  * value; any Real number (Rat, Int, or Num)
* $block

  * callable; an expression, block or WhateverCode that returns a Truthy/Falsey value

Pass in a defined Real value to get all of the elements up to but not including that value.

```
put (1..100).&before(10);
1 2 3 4 5 6 7 8 9

```

Or a WhateverCode

```
put (1..100).&before(* %% 7);
1 2 3 4 5 6

```

## after( )

Complement to `before()`, `after()` returns the elements greater than the passed in value or code block.

### after( Cool @array, Real $value ); or after( Cool @array, Callable $block );

* @array

  * Positional object; any array, list or list-like object
* $value

  * value; any Real number (Rat, Int, or Num)
* $block

  * callable; an expression, block or WhateverCode that returns a Truthy/Falsey value

Pass in a defined Real value to get all of the elements after but not including that value.

```
put (1..10).&after(5);
6 7 8 9 10

```

Or a WhateverCode

```
put (1..10).&after(* %% 7);
8 9 10

```

Use `upto()` and `from()` to partition out value less than or greater than some threshold including the threshold value.

## upto( )

Returns the list of values `upto()` the given defined value or WhateverCode.

### upto( Cool @array, Real $value ); or upto( Cool @array, Callable $block );

* @array

  * Positional object; any array, list or list-like object
* $value

  * value; any Real number (Rat, Int, or Num)
* $block

  * callable; an expression, block or WhateverCode that returns a Truthy/Falsey value

Pass in a defined Real value to get all of the elements up to and including that value.

```
put (1..100).&upto(10);
1 2 3 4 5 6 7 8 9 10

```

Or a WhateverCode

```
put (1..100).&upto(* %% 7);
1 2 3 4 5 6 7

```

## from( )

Complement to `upto()`, `from()` returns the elements greater than or equal to the passed in value or code block.

### from( Cool @array, Real $value ); or from( Cool @array, Callable $block );

* @array

  * Positional object; any array, list or list-like object
* $value

  * value; any Real number (Rat, Int, or Num)
* $block

  * callable; an expression, block or WhateverCode that returns a Truthy/Falsey value

Pass in a defined Real value to get all of the elements greater than or equal to that value.

```
put (1..10).&from(5);
5 6 7 8 9 10

```

Or a WhateverCode

```
put (1..10).from(* %% 7);
7 8 9 10

```

Similar to the single ended partition routines, there are routines `between` and `bounded`.

## between( )

Returns the list of values `between()` the two boundary values.

### between( Cool @array, Real (or Callable) $lo, Real (or Callable) $hi );

* @array

  * Positional object; any array, list or list-like object
* $lo

  * value; lower threshold, any Real number (Rat, Int, or Num) or Callable
* $hi

  * value; upper threshold, any Real number (Rat, Int, or Num) or Callable

Gets all of the elements between but not including the threshold values.

```
put (1..100).&between(23, 29);
24 25 26 27 28

```

## bounded( )

Returns the list of values `bounded()` by the two threshold values.

### bounded( Cool @array, Real (or Callable) $lo, Real (or Callable) $hi );

* @array

  * Positional object; any array, list or list-like object
* $lo

  * value; lower threshold, any Real number (Rat, Int, or Num) or Callable
* $hi

  * value; upper threshold, any Real number (Rat, Int, or Num) or Callable

Get all of the elements bounded by, and including the threshold values.

```
put (1..100).&bounded(23, 29);
23 24 25 26 27 28 29

```

You may also combine and chain the single ended partitions in various combinations to include or exclude the upper and lower thresholds as desired.

```
put (1..20).&after(4).&upto(12);
5 6 7 8 9 10 11 12

```

Note that these examples have all used integers, but they may be **any** Real numeric value. If the threshold value does not appear in the list then the corresponding routines act the same.

Cuban primes between 1e5 and 1.2e5:

```
put (1..*).map({ ($_+1)³ - .³ }).grep( &is-prime ).&between(1e5, 1.2e5);
103231 104347 110017 112327 114661 115837

```

Random interval sequence with non-Int boundaries:

```
put (0, *+.01 * rand … *).&between(3.575, 3.6045);
3.5875642424525935 3.5922439090572023 3.6003421569736993 3.6024701972903563

```

The callable block may be a WhateverCode or may be an actual block.

Powers of 3, filtered to show the first with 5 digits, through the first with more than 7 digits:

```
put (1, 3, 9, 27 … *).&bounded( *.chars == 5, {.chars > 7} );
19683 59049 177147 531441 1594323 4782969 14348907

```

# BUGS

Mostly intended for monotonic numeric lists/sequences. May work for non-numeric or non-monotonic but not likely to give useful results.

# AUTHOR

©2022 Stephen Schulze aka thundergnat.

# LICENSE

Licensed under The Artistic 2.0; see LICENSE.


## dist_github-hankache-Imlib2.md
# Raku Imlib2 Imlib2 Logo

Raku interface to the Imlib2 image library.

| Operating System | Build Status |
| --- | --- |
| Linux | [Build Status](https://travis-ci.org/hankache/perl6-Imlib2) |

## Description

Raku binding for [Imlib2](http://docs.enlightenment.org/api/imlib2/html/ "Imlib2 Library Documentation"), a featureful and efficient image manipulation library, which produces high quality, anti-aliased output.

## Installation

Note that a recent version of [Imlib2](http://sourceforge.net/projects/enlightenment/files/imlib2-src/) library must be installed before installing this module.

To install with zef:

```
zef update
zef install Imlib2

```

## Synopsis

WARNING: This module is Work in Progress, which means: this interface is not final. This will perhaps change in the future.

Below is a sample code:

```
use Imlib2;

my $im = Imlib2.new();
# Create a new raw image.
my $rawimage = $im.create_image(200, 200);
exit() unless $rawimage;

# Sets the current image Imlib2 will be using with its function calls.
$rawimage.context_set();

# Sets the color with which text, lines and rectangles are drawn when
# being rendered onto an image.
$im.context_set_color(
	red   => 255,
	green => 127,
	blue  => 0,
	alpha => 255);

$im.image_draw_rectangle(
	location => (0, 0),
	size     => (200, 200),
	fill     => True);
$im.image_set_format("png");
unlink("images/test_imlib2.png") if "images/test_imlib2.png".IO ~~ :e;
$im.save_image("images/test_imlib2.png");

# Frees the image that is set as the current image in Imlib2's context.
$im.free_image();

exit();

```

## Author

Henrique Dias [mrhdias@gmail.com](mailto:mrhdias@gmail.com)

## See Also

* [Imlib2 Raku Module Documentation](lib/Imlib2.pod "Imlib2 Raku Module Documentation")
* [Imlib2 Library Documentation](http://docs.enlightenment.org/api/imlib2/html/ "Imlib2 Library Documentation")
* [Imlib2 Source Repository](http://sourceforge.net/projects/enlightenment/files/imlib2-src/)

## License

This library is free software; you can redistribute it and/or modify it under the same terms as Raku itself.


## dist_cpan-MARTIMM-PKCS5.md
# Public Key Cryptography Standards #5 (PKCS 5)

[![Build Status](https://travis-ci.org/MARTIMM/PKCS5.svg?branch=master)](https://travis-ci.org/MARTIMM/PKCS5)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/MARTIMM/pkcs5?branch=master&passingText=Windows%20-%20OK&failingText=Windows%20-%20FAIL&pendingText=Windows%20-%20pending&svg=true)](https://ci.appveyor.com/project/MARTIMM/pkcs5/branch/master)
[![License](http://martimm.github.io/label/License-label.svg)](http://www.perlfoundation.org/artistic_license_2_0)

This package implements part of PKCS 5 which is, according to the [wikipedia](https://en.wikipedia.org/wiki/PKCS), a Password-based Encryption Standard. The derivation algorithm PBKDF2 is implemented as a class in this package.

## Synopsis

```
  use PKCS5::PBKDF2;

  my PKCS5::PBKDF2 $p .= new;

  $spw2 = $p.derive-hex(
    Buf.new('pencil'.encode),
    Buf.new( 65, 37, 194, 71, 228, 58, 177, 233, 60, 109, 255, 118),
    4096,
  );

  is $spw2, '1d96ee3a529b5a5f9e47c01f229a2cb8a6e15f7d', '4096 iteration hex';

```

## Documentation

See documentation at

* [PKCS5::PBKDF2](https://github.com/MARTIMM/PKCS5/blob/master/doc/PBKDF2.pdf)
* [Release notes](https://github.com/MARTIMM/PKCS5/blob/master/doc/CHANGES.md)

## Versions of PERL, MOARVM and MongoDB

This project is tested with latest Rakudo built on MoarVM implementing Perl v6.c.

## AUTHORS

```
Marcel Timmerman (MARTIMM on github)

```


## dist_zef-raku-community-modules-JSON-Mask.md
[![Actions Status](https://github.com/raku-community-modules/JSON-Mask/actions/workflows/linux.yml/badge.svg)](https://github.com/raku-community-modules/JSON-Mask/actions) [![Actions Status](https://github.com/raku-community-modules/JSON-Mask/actions/workflows/macos.yml/badge.svg)](https://github.com/raku-community-modules/JSON-Mask/actions) [![Actions Status](https://github.com/raku-community-modules/JSON-Mask/actions/workflows/windows.yml/badge.svg)](https://github.com/raku-community-modules/JSON-Mask/actions)

# NAME

JSON::Mask - JSON filtering

# SYNOPSIS

```
use JSON::Mask;

# Select keys "a", "b", and "c".
mask('a,b,c', %data);

my $mask = compile-mask('a,b,c');
mask($mask, %data1);

```

# DESCRIPTION

Allows to filter JSON-like data so it's suitable for public consumption. The pattern describes the schema, and the module trims the extra data.

## Basic syntax

To select keys, list them in a comma-separated string:

```
# Select keys "a", "b", and "c".
mask('a,b,c', %data);

```

To select all keys except a few, negate them:

```
# Select all the keys that aren't "a" or "b".
mask('-a,-b', %data);

```

To select subkeys, use parentheses:

```
# Keeps only "a", and in it only its subkeys "b" and "c".
mask('a(b,c)', %data);

```

You can of course combine them:

```
# Select everything but "password", but only keep the
# "name" and "email" subkeys from "profile".
mask('-password,profile(name,email)', %data);

```

You can quote a key if it contains "special" characters:

```
# Select everything but "password" and "password-confirmation".
mask('-password,-"password-confirmation"', %data);

```

## Compilation

If you want to reuse masks, you can pre-compile them:

```
my $mask = compile-mask('a,b,c');
mask($mask, %data1);
mask($mask, %data2);
mask($mask, %data3);

```

## Array handling

The module handles arrays without you needing to do anything: a mask will be applied recursively on each element of the array.

```
my @data =
  %(id => 1, name => "First Volume"),
  %(id => 2, name => "Second Adventure"),
  %(id => 3, name => "Final Countdown")
;
mask('id', @data); # Select key "id" in each sub-hash

```

## Error handling

The module ignores missing keys. It will however throw an exception if a nested key ("a(b,c)") is not actually `Associative` (or `Positional`).

# AUTHOR

vendethiel

Source can be located at: <https://github.com/raku-community-modules/JSON-Mask> . Comments and Pull Requests are welcome.

# COPYRIGHT AND LICENSE

Copyright 2020 Edument AB

Copyright 2024 The Raku Community

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## baghash.md
class BagHash

Mutable collection of distinct objects with integer weights

```raku
class BagHash does Baggy { }
```

A `BagHash` is a mutable bag/multiset, meaning a collection of distinct items in no particular order that each have an integer weight assigned to them signifying how many copies of that element are considered "in the bag". If you do not need the mutability that a `BagHash` provides, consider using the *immutable* [`Bag`](/type/Bag) type instead.

An item may be a definite object of any type – not just a [`Str`](/type/Str). For example, you can store [`Sub`](/type/Sub)'s in a `BagHash`, and you will store the actual [`Sub`](/type/Sub) rather than a string with the same name as the [`Sub`](/type/Sub). Within a `BagHash`, items that would compare positively with the [===](/routine/===) operator are considered the same element, with the number of how many there were as its weight. Alternatively, you can use the `kxxv` method to easily get back the expanded list of items (without the order):

```raku
my $breakfast = <spam eggs spam spam bacon spam>.BagHash;

say $breakfast.elems;      # OUTPUT: «3␤»
say $breakfast.keys.sort;  # OUTPUT: «bacon eggs spam␤»

say $breakfast.total;      # OUTPUT: «6␤»
say $breakfast.kxxv.sort;  # OUTPUT: «bacon eggs spam spam spam spam␤»

```

`BagHash`es can be treated as object hashes using the [`{ }` postcircumfix operator](/language/operators#postcircumfix_{_}), or the [`< >` postcircumfix operator](/language/operators#postcircumfix_<_>) for literal string keys, which returns the corresponding integer weight for keys that are elements of the bag, and `0` for keys that aren't. These operators can also be used to modify weights (see [Updating BagHash Objects](#Updating_BagHash_Objects), below).

```raku
my $breakfast = <spam eggs spam spam bacon spam>.BagHash;
say $breakfast<bacon>;     # OUTPUT: «1␤»
say $breakfast<spam>;      # OUTPUT: «4␤»
say $breakfast<sausage>;   # OUTPUT: «0␤»

$breakfast<sausage> = 2;
$breakfast<bacon>--;
say $breakfast.kxxv.sort;  # OUTPUT: «eggs sausage sausage spam spam spam spam␤»

```

# [Creating `BagHash` objects](#class_BagHash "go to top of document")[§](#Creating_BagHash_objects "direct link")

`BagHash`es can be composed using `BagHash.new`. Any positional parameters, regardless of their type, become elements of the bag:

```raku
my $n = BagHash.new: "a", "b", "c", "c";
say $n.raku;             # OUTPUT: «("b"=>1,"a"=>1,"c"=>2).BagHash␤»
say $n.keys.raku;        # OUTPUT: «("b", "a", "c").Seq␤»
say $n.values.raku;      # OUTPUT: «(1, 1, 2).Seq␤»
```

Besides, `BagHash.new-from-pairs` can create a `BagHash` with items and their occurrences.

```raku
my $n = BagHash.new-from-pairs: "a" => 0, "b" => 1, "c" => 2, "c" => 2;
say $n.raku;             # OUTPUT: «("b"=>1,"c"=>4).BagHash␤»
say $n.keys.raku;        # OUTPUT: «("b", "c").Seq␤»
say $n.values.raku;      # OUTPUT: «(1, 4).Seq␤»
```

Alternatively, the `.BagHash` coercer (or its functional form, `BagHash()`) can be called on an existing object to coerce it to a `BagHash`. Its semantics depend on the type and contents of the object. In general it evaluates the object in list context and creates a bag with the resulting items as elements, although for Hash-like objects or Pair items, only the keys become elements of the bag, and the (cumulative) values become the associated integer weights:

```raku
my $m = ("a", "b", "c", "c").BagHash;
my $n = ("a" => 0, "b" => 1, "c" => 2, "c" => 2).BagHash;
say $m.raku;             # OUTPUT: «("b"=>1,"a"=>1,"c"=>2).BagHash␤»
say $n.raku;             # OUTPUT: «("b"=>1,"c"=>4).BagHash␤»
```

You can also create `BagHash` masquerading as a hash by using the `is` trait:

```raku
my %bh is BagHash = <a b b c c c>;
say %bh<b>;  # OUTPUT: «2␤»
say %bh<d>;  # OUTPUT: «0␤»
```

Since 6.d (2019.03 and later) it is also possible to specify the type of values you would like to allow in a `BagHash`. This can either be done when calling `.new`:

```raku
# only allow strings
my $n = BagHash[Str].new: <a b b c c c>;
```

or using the masquerading syntax:

```raku
# only allow strings
my %bh is BagHash[Str] = <a b b c c c>;
say %bh<b>;  # OUTPUT: «2␤»
say %bh<d>;  # OUTPUT: «0␤»

# only allow whole numbers
my %bh is BagHash[Int] = <a b b c c c>;
# Type check failed in binding; expected Int but got Str ("a")
```

# [Updating BagHash Objects](#class_BagHash "go to top of document")[§](#Updating_BagHash_Objects "direct link")

Once you have created a `BagHash`, you can update its values in two ways. First, you can use the `add` and `remove` methods:

```raku
my $n = BagHash.new: "a", "b", "c", "c";
say $n.raku;             # OUTPUT: «("b"=>1,"a"=>1,"c"=>2).BagHash␤»
$n.add('c');
say $n.raku;             # OUTPUT: «("b"=>1,"c"=>3,"a"=>1).BagHash␤»
$n.remove(('b', 'a'),);
say $n.raku;             # OUTPUT: «("c"=>3).BagHash␤»
$n.remove('c');
say $n.raku;             # OUTPUT: «("c"=>2).BagHash␤»
```

Note that, as shown in the final example, the `remove` method removes a *single* value from the `BagHash`; it doesn't entirely remove the key from the `BagHash`.

Alternatively, you can use assignment (including with [autoincrement operators](/language/operators#Autoincrement_precedence) such as `++` and `--`) to modify the `BagHash`'s contents.

```raku
my $n = BagHash.new: "a", "b", "c", "c";
say $n.raku;             # OUTPUT: «("b"=>1,"a"=>1,"c"=>2).BagHash␤»
$n<c>++;
say $n.raku;             # OUTPUT: «("b"=>1,"c"=>3,"a"=>1).BagHash␤»
$n<b> -= 1;
say $n.raku;             # OUTPUT: «("a"=>1,"c"=>3).BagHash␤»
$n{'a'} = 0;
say $n.raku;             # OUTPUT: «("c"=>3).BagHash␤»
```

Using either syntax, if you set the value of an item to zero or less than zero, the item will be removed from the `BagHash`.

# [Operators](#class_BagHash "go to top of document")[§](#Operators "direct link")

See [Operators with set semantics](/language/setbagmix#Operators_with_set_semantics) for a complete list of "set operators" applicable to, among other types, `BagHash`.

Examples:

```raku
my ($a, $b) = BagHash.new(2, 2, 4), BagHash.new(2, 3, 3, 4);

say $a (<) $b;   # OUTPUT: «False␤»
say $a (<=) $b;  # OUTPUT: «False␤»
say $a (^) $b;   # OUTPUT: «BagHash(3(2) 2)␤»
say $a (+) $b;   # OUTPUT: «BagHash(2(3) 4(2) 3(2))␤»

# Unicode versions:
say $a ⊂ $b;  # OUTPUT: «False␤»
say $a ⊆ $b;  # OUTPUT: «False␤»
say $a ⊖ $b;  # OUTPUT: «BagHash(3(2) 2)␤»
say $a ⊎ $b;  # OUTPUT: «BagHash(2(3) 4(2) 3(2))␤»

```

# [Note on `reverse` and ordering.](#class_BagHash "go to top of document")[§](#Note_on_reverse_and_ordering. "direct link")

BagHash inherits `reverse` from [Any](/type/Any#routine_reverse), however, [`Bag`](/type/Bag)s do not have an inherent order and you should not trust it returning a consistent output.

If you sort a BagHash, the result is a list of pairs, at which point `reverse` makes perfect sense:

```raku
my $a = BagHash.new(2, 2, 18, 3, 4);
say $a;  # OUTPUT: «BagHash(18 2(2) 3 4)␤»

say $a.sort;  # OUTPUT: «(2 => 2 3 => 1 4 => 1 18 => 1)␤»
say $a.sort.reverse;  # OUTPUT: «(18 => 1 4 => 1 3 => 1 2 => 2)␤»

```

## [method add](#class_BagHash "go to top of document")[§](#method_add "direct link")

```raku
method add(BagHash: \to-add, *%_ --> Nil)
```

When `to-add` is a single item, `add` inserts it into the `BagHash` or, if it was already present, increases its weight by 1. When `to-add` is a [`List`](/type/List), [`Array`](/type/Array), [`Seq`](/type/Seq), or any other type that `does` the [`Iterator`](/type/Iterator) Role, `add` inserts each element of the [`Iterator`](/type/Iterator) into the [`SetHash`](/type/SetHash) or increments the weight of each element by 1.

*Note:* Added in version 2020.02.

## [method remove](#class_BagHash "go to top of document")[§](#method_remove "direct link")

```raku
method remove(BagHash: \to-remove, *%_ --> Nil)
```

When `to-remove` is a single item, `remove` reduces the weight of that item by one. If this results in the item having a weight of 0, this removes the item from the `BagHash`. If the item is not present in the `BagHash`, `remove` has no effect. When `to-remove` is a [`List`](/type/List), [`Array`](/type/Array), [`Seq`](/type/Seq), or any other type that `does` the [`Iterator`](/type/Iterator) Role, `remove` reduces the weight of each element by 1 and removes any items with the resulting weight of 0.

*Note:* Added in version 2020.02.

# [See Also](#class_BagHash "go to top of document")[§](#See_Also "direct link")

[Sets, Bags, and Mixes](/language/setbagmix)

# [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")

Type relations for `BagHash`

raku-type-graph

BagHash
BagHash

Any
Any

BagHash->Any

Baggy
Baggy

BagHash->Baggy

Mu
Mu

Any->Mu

Associative
Associative

QuantHash
QuantHash

QuantHash->Associative

Baggy->QuantHash

[Expand chart above](/assets/typegraphs/BagHash.svg)


## dist_zef-lizmat-ValueMap.md
[![Actions Status](https://github.com/lizmat/ValueMap/actions/workflows/linux.yml/badge.svg)](https://github.com/lizmat/ValueMap/actions) [![Actions Status](https://github.com/lizmat/ValueMap/actions/workflows/macos.yml/badge.svg)](https://github.com/lizmat/ValueMap/actions) [![Actions Status](https://github.com/lizmat/ValueMap/actions/workflows/windows.yml/badge.svg)](https://github.com/lizmat/ValueMap/actions)

# NAME

ValueMap - Provide an immutable Map value type

# SYNOPSIS

```
use ValueMap;

my %vm is ValueMap = foo => 42, bar => 666, baz => 137;

my $vm := ValueMap.new( (foo => 42, bar => 666, baz => 137) );

my %s is Set = $vm, %vm;
say %s.elems;  # 1

```

# DESCRIPTION

Raku provides a semi-immutable Associative datatype: Map. A Map can not have any elements added or removed from it. However, since a Map can contain containers of which the value can be changed, it is **not** a value type. So you cannot use Maps in data structures such as Sets, because each Map is considered to be different from any other List, because they are not value types.

# AUTHOR

Elizabeth Mattijsen [liz@raku.rocks](mailto:liz@raku.rocks)

Source can be located at: <https://github.com/lizmat/ValueMap> . Comments and Pull Requests are welcome.

If you like this module, or what I’m doing more generally, committing to a [small sponsorship](https://github.com/sponsors/lizmat/) would mean a great deal to me!

# COPYRIGHT AND LICENSE

Copyright 2022, 2024 Elizabeth Mattijsen

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_zef-leont-Net-Postgres-Abstract.md
[![Actions Status](https://github.com/Leont/net-postgres-abstract/actions/workflows/test.yml/badge.svg)](https://github.com/Leont/net-postgres-abstract/actions)

# NAME

Net::Postgres::Abstract - Abstractly and asynchronously querying your postgresql database

# SYNOPSIS

```
use Net::Postgres::Abstract;

my $dbh = await Net::Postgres::Abstract.connect-tcp(:$host, :user, :$password);

await $dbh.transaction: {
	my $row = await $dbh.insert('table', { :user<leont>, :language<raku> }, :returning<id>);
	...
}

my $results = await $dbh.select('table', <user password country>, { :age('>' => 25) });
for $results.objects(User) -> $user {
	...
}

my $sth = await $dbh.select('table', *, { :id(delegate('id')) }, :prepare);
for @ids -> $id {
	my $row = await $sth->execute(:$id);
	...
}

```

# Description

Net::Postgres::Abstract is at its core a combination of query builder `SQL::Abstract` and postgresql client `Net::Postgres`.

## Rationale

* Abstract

It abstracts the generation of SQL queries, so you don't have to write them yourself.

* Asynchronous

All queries are performed asynchronously.

* Prepared

Full support for prepared queries, including named substitution, is offered.

# Constructors

## connect-tcp(--> Promise)

This creates a promise to a new `Net::Postgres::Abstract` client. It takes the following named arguments:

* Str :$host = 'localhost'
* Int :$port = 5432
* Str :$user = ~$\*USER
* Str :password
* Str :$database
* TypeMap :$typemap = Protocol::Postgres::TypeMap::JSON
* Bool :$tls = False
* :%tls-args = ()

## connect-local(--> Promise)

This creates a new `Net::Postgres::Abstract` client much like `connect-tcp`, but does so via a unix domain socket.

* IO(Str) :$path = '/var/run/postgresql/'.IO
* Int :$port = 5432
* Str :$user = ~$\*USER
* Str :password
* Str :$database
* TypeMap :$typemap = Protocol::Postgres::TypeMap::JSON

## connect(--> Promise)

This takes the same arguments as `connect-local` and `connect-tcp`. It will call the former if the `$host` is localhost and the `$path` exists, otherwise it will call `connect-tcp`.

# Querying methods

All these methods return a Promise. if a `:$prepared` argument is given to them the Promise will contain a `Net::Postgres::Abstract::PreparedStatement` object, otherwise it will be the usual `Net::Postgres` return type (usually a `Net::Postgres::ResultSet` if it returns rows, or a `Str` if it doesn't).

## select

```
method select(Source(Any) $source, Column::List(Any) $columns = *, Conditions(Any) $where?, Common(Any) :$common,
Distinction(Any) :$distinct, GroupBy(Any) :$group-by, Conditions(Any) :$having, Window::Clauses(Any) :$windows,
Compound(Pair) :$compound, OrderBy(Any) :$order-by, Int :$limit, Int :$offset, Locking(Any) :$locking)

```

This will generate a `SELECT` query. It will select `$columns` from `$source`, filtering by $conditions.

```
my $join = { :left<books>, :right<authors>, :using<author_id> };
my $result = $abstract.select($join, ['books.name', 'authors.name'], { :cost('<' => 10) });
# SELECT books.name, authors.name FROM books INNER JOIN authors USING (author_id) WHERE cost < 10

my $counts = $abstract.select('artists',
    [ 'name', :number(:count(*)) ],
    { :name(like => 'A%') },
    :group-by<name>, :order-by(:number<desc>));
# SELECT name, COUNT(*) as number FROM artists WHERE name LIKE 'A%' GROUP BY name ORDER BY number DESC

```

## update

```
method update(Table(Any) $target, Assigns(Any) $assigns, Conditions(Any) $where?,
Common(Any) :$common, Source(Any) :$from, Column::List(Any) :$returning)

```

This will update `$target` by assigning the columns and values from `$set` if they match `$where`, returning `$returning`.

```
$abtract.update('artists', { :name('The Artist (Formerly Known as Prince)') }, { :name<Prince> });
# UPDATE artists SET name = 'The Artist (Formerly Known as Prince)' WHERE name = 'Prince'

```

## insert

### Map insertion

```
method insert(Table(Any) $target, Assigns(Any) $values, Common(Any) :$common,
Overriding(Str) :$overriding, Conflicts(Any) :$conflicts, Column::List(Any) :$returning)

```

Inserts the values in `$values` into the table `$target`, returning the columns in `$returning`

```
$abstract.insert('artists', { :name<Metallica> }, :returning(*));
# INSERT INTO artists (name) VALUES ('Metallica') RETURNING *

```

### List insertions

```
method insert(Table(Any) $target, Identifiers(Any) $columns, Rows(List) $rows, Common(Any) :$common,
Overriding(Str) :$overriding, Conflicts(Any) :$conflicts, Column::List(Any) :$returning)

```

Insert into `$target`, assigning each of the values in Rows to a new row in the table. This way one can insert a multitude of rows into a table.

```
$abstract.insert('artists', ['name'], [ ['Metallica'], ['Motörhead'] ], :returning(*));
# INSERT INTO artists (name) VALUES ('Metallica'), ('Motörhead') RETURNING *

$abstract.insert('artists', List, [ [ 'Metallica'], ], :returning<id>);
# INSERT INTO artists VALUES ('Metallica') RETURNING id

```

### Select insertion

```
method insert(Table(Any) $target, Identifiers(Any) $columns, Select(Map) $select, Common(Any) :$common,
Overriding(Str) :$overriding, Conflicts(Any) :$conflicts, Column::List(Any) :$returning)

```

This selects from a (usually different) table, and inserts the values into the table.

```
$abstract.insert('artists', 'name', { :source<new_artists>, :columns<name> }, :returning(*));
# INSERT INTO artists (name) SELECT name FROM new_artists RETURNING *

```

## delete

```
method delete(Table:D(Any:D) $target, Conditions(Any) $where, Common(Any) :$common,
Source(Any) :$using, Column::List(Any) :$returning)

```

This deletes rows from the database, optionally returning their values.

```
$abstract.delete('artists', { :name<Madonna> });
# DELETE FROM artists WHERE name = 'Madonna'

```

## query

```
method query(Str $sql, @arguments?)
method query(SQL::Query $query)
method query(SQL::Abstract::Expression $query)

```

Perform a manual query to the database.

## prepare

```
method prepare(Str $sql)
method prepare(Str $sql, @names)

```

This prepares a raw query. If given `@names` it will take named parameters on execute, without it will take positional ones.

## transaction

To use a transaction, one can use the `transaction(&code)` method. It's code reference will act as a wrapper for the transaction. If anything throws an exception out of the callback (e.g. a failed query method), a rollback will be attempted.

# Connection methods

* listen(Str $channel-name --> Promise[Supply])

  This listens to notifications on the given channel. It returns a `Promise` to a `Supply` of `Notification`s.
* terminate(--> Nil)

  This sends a message to the server to terminate the connection
* disconnected(--> Promise)

  This returns a `Promise` that will be be kept if the connection or broken to signal the connection is lost.
* process-id(--> Int)

  This returns the process id of the backend of this connection. This is useful for debugging purposes and for notifications.
* get-parameter(Str $name --> Str)

  This returns various parameters, currently known parameters are: `server_version`, `server_encoding`, `client_encoding`, `application_name`, `default_transaction_read_only`, `in_hot_standby`, `is_superuser`, `session_authorization`, `DateStyle`, `IntervalStyle`, `TimeZone`, `integer_datetimes`, and `standard_conforming_strings`.

# PreparedStatement

This class is much like `Net::`

# Exported functions

Under the `:functions` tag it exports two helper functions

* delegate(Str $name, Any $default-value, Any:U :$type)
* value(Any $value)

# AUTHOR

Leon Timmermans [fawaka@gmail.com](mailto:fawaka@gmail.com)

# COPYRIGHT AND LICENSE

Copyright 2023 Leon Timmermans

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_zef-antononcube-LLM-Functions.md
## Chunk 1 of 2
# LLM::Functions

[![MacOS](https://github.com/antononcube/Raku-LLM-Functions/actions/workflows/macos.yml/badge.svg)](https://github.com/antononcube/Raku-LLM-Functions/actions/workflows/macos.yml)
[![Linux](https://github.com/antononcube/Raku-LLM-Functions/actions/workflows/linux.yml/badge.svg)](https://github.com/antononcube/Raku-LLM-Functions/actions/workflows/linux.yml)
[![Win64](https://github.com/antononcube/Raku-LLM-Functions/actions/workflows/windows.yml/badge.svg)](https://github.com/antononcube/Raku-LLM-Functions/actions/workflows/windows.yml)
[![](https://raku.land/zef:antononcube/LLM::Functions/badges/version)](https://raku.land/zef:antononcube/LLM::Functions)

## In brief

This Raku package provides functions and function objects to access, interact, and utilize
Large Language Models (LLMs), like
[OpenAI](https://platform.openai.com), [OAI1],
[PaLM](https://developers.generativeai.google/products/palm), [ZG1],
and
[MistralAI](https://docs.mistral.ai), [MAI1].

For more details how the concrete LLMs are accessed see the packages
["WWW::OpenAI"](https://raku.land/zef:antononcube/WWW::OpenAI), [AAp2],
["WWW::PaLM"](https://raku.land/zef:antononcube/WWW::PaLM), [AAp3],
["WWW::MistralAI"](https://raku.land/zef:antononcube/WWW::MistralAI), [AAp9], and
["WWW::Gemini"](https://raku.land/zef:antononcube/WWW::Gemini), [AAp11].

The LLM functions built by this package can have evaluators that use "sub-parsers" -- see
["Text::SubParsers"](https://raku.land/zef:antononcube/Text::SubParsers), [AAp4].

The primary motivation to have handy, configurable functions for utilizing LLMs
came from my work on the packages
["ML::FindTextualAnswer"](https://raku.land/zef:antononcube/ML::FindTextualAnswer), [AAp6], and
["ML::NLPTemplateEngine"](https://raku.land/zef:antononcube/ML::NLPTemplateEngine), [AAp7].

A very similar system of functionalities is developed by Wolfram Research Inc.;
see the paclet
["LLMFunctions"](https://resources.wolframcloud.com/PacletRepository/resources/Wolfram/LLMFunctions/), [WRIp1].

For well curated and instructive examples of LLM prompts see the
[Wolfram Prompt Repository](https://resources.wolframcloud.com/PromptRepository/).
Many of those prompts (≈220) are available in Raku and Python --
see ["LLM::Prompts"](https://raku.land/zef:antononcube/LLM::Prompts), [AAp8], and
["LLMPrompts"](https://pypi.org/project/LLMPrompts/), [AAp10], respectively.

The article
["Generating documents via templates and LLMs"](https://rakuforprediction.wordpress.com/2023/07/11/generating-documents-via-templates-and-llms/), [AA1],
shows an alternative way of streamlining LLMs usage. (Via Markdown, Org-mode, or Pod6 templates.)

---

## Installation

Package installations from both sources use [zef installer](https://github.com/ugexe/zef)
(which should be bundled with the "standard" Rakudo installation file.)

To install the package from [Zef ecosystem](https://raku.land/) use the shell command:

```
zef install LLM::Functions

```

To install the package from the GitHub repository use the shell command:

```
zef install https://github.com/antononcube/Raku-LLM-Functions.git

```

---

## Design

"Out of the box"
["LLM::Functions"](https://raku.land/zef:antononcube/LLM::Functions) uses
["WWW::OpenAI"](https://raku.land/zef:antononcube/WWW::OpenAI), [AAp2],
["WWW::PaLM"](https://raku.land/zef:antononcube/WWW::PaLM), [AAp3], and
["WWW::MistralAI"](https://raku.land/zef:antononcube/WWW::MistralAI), [AAp9].
Other LLM access packages can be utilized via appropriate LLM configurations.

Configurations:

* Are instances of the class `LLM::Functions::Configuration`
* Are used by instances of the class `LLM::Functions::Evaluator`
* Can be converted to Hash objects (i.e. have a `.Hash` method)

New LLM functions are constructed with the function `llm-function`.

The function `llm-function`:

* Has the option "llm-evaluator" that takes evaluators, configurations, or string shorthands as values
* Returns anonymous functions (that access LLMs via evaluators/configurations.)
* Gives result functions that can be applied to different types of arguments depending on the first argument
* Can take a (sub-)parser argument for post-processing of LLM results
* Takes as a first argument a prompt that can be a:
  * String
  * Function with positional arguments
  * Function with named arguments

Here is a sequence diagram that follows the steps of a typical creation procedure of
LLM configuration- and evaluator objects, and the corresponding LLM-function that utilizes them:

```
sequenceDiagram
  participant User
  participant llmfunc as llm-function
  participant llmconf as llm-configuration
  participant LLMConf as LLM configuration
  participant LLMEval as LLM evaluator
  participant AnonFunc as Anonymous function
  User ->> llmfunc: ・prompt<br>・conf spec
  llmfunc ->> llmconf: conf spec
  llmconf ->> LLMConf: conf spec
  LLMConf ->> LLMEval: wrap with
  LLMEval ->> llmfunc: evaluator object
  llmfunc ->> AnonFunc:  create with:<br>・evaluator object<br>・prompt
  AnonFunc ->> llmfunc: handle
  llmfunc ->> User: handle

```

Here is a sequence diagram for making a LLM configuration with a global (engineered) prompt,
and using that configuration to generate a chat message response:

```
sequenceDiagram
  participant WWWOpenAI as WWW::OpenAI
  participant User
  participant llmfunc as llm-function
  participant llmconf as llm-configuration
  participant LLMConf as LLM configuration
  participant LLMChatEval as LLM chat evaluator
  participant AnonFunc as Anonymous function
  User ->> llmconf: engineered prompt
  llmconf ->> User: configuration object
  User ->> llmfunc: ・prompt<br>・configuration object
  llmfunc ->> LLMChatEval: configuration object
  LLMChatEval ->> llmfunc: evaluator object
  llmfunc ->> AnonFunc: create with:<br>・evaluator object<br>・prompt
  AnonFunc ->> llmfunc: handle
  llmfunc ->> User: handle
  User ->> AnonFunc: invoke with<br>message argument
  AnonFunc ->> WWWOpenAI: ・engineered prompt<br>・message
  WWWOpenAI ->> User: LLM response

```

---

## Configurations

### OpenAI-based

Here is the default, OpenAI-based configuration:

```
use LLM::Functions;
.raku.say for llm-configuration('OpenAI').Hash;

```

```
# :evaluator(Whatever)
# :module("WWW::OpenAI")
# :function(proto sub OpenAITextCompletion ($prompt is copy, :$model is copy = Whatever, :$suffix is copy = Whatever, :$max-tokens is copy = Whatever, :$temperature is copy = Whatever, Numeric :$top-p = 1, Int :$n where { ... } = 1, Bool :$stream = Bool::False, Bool :$echo = Bool::False, :$stop = Whatever, Numeric :$presence-penalty = 0, Numeric :$frequency-penalty = 0, :$best-of is copy = Whatever, :api-key(:$auth-key) is copy = Whatever, Int :$timeout where { ... } = 10, :$format is copy = Whatever, Str :$method = "tiny", Str :$base-url = "https://api.openai.com/v1") {*})
# :max-tokens(300)
# :temperature(0.8)
# :prompts($[])
# :name("openai")
# :images($[])
# :tools($[])
# :api-key(Whatever)
# :api-user-id("user:109176182730")
# :base-url("https://api.openai.com/v1")
# :tool-prompt("")
# :tool-response-insertion-function(WhateverCode)
# :argument-renames(${:api-key("auth-key"), :stop-tokens("stop")})
# :stop-tokens($[])
# :examples($[])
# :format("values")
# :tool-request-parser(WhateverCode)
# :total-probability-cutoff(0.03)
# :model("gpt-3.5-turbo-instruct")
# :prompt-delimiter(" ")

```

Here is the ChatGPT-based configuration:

```
.say for llm-configuration('ChatGPT').Hash;

```

```
# tool-request-parser => (WhateverCode)
# total-probability-cutoff => 0.03
# model => gpt-3.5-turbo
# api-user-id => user:475496933842
# images => []
# argument-renames => {api-key => auth-key, stop-tokens => stop}
# max-tokens => 300
# module => WWW::OpenAI
# tool-prompt =>
# format => values
# stop-tokens => []
# examples => []
# temperature => 0.8
# prompts => []
# tool-response-insertion-function => (WhateverCode)
# tools => []
# function => &OpenAIChatCompletion
# prompt-delimiter =>
# api-key => (Whatever)
# base-url => https://api.openai.com/v1
# name => chatgpt
# evaluator => (my \LLM::Functions::EvaluatorChat_6288007030840 = LLM::Functions::EvaluatorChat.new(context => "", examples => Whatever, user-role => "user", assistant-role => "assistant", system-role => "system", conf => LLM::Functions::Configuration.new(name => "chatgpt", api-key => Whatever, api-user-id => "user:475496933842", module => "WWW::OpenAI", base-url => "https://api.openai.com/v1", model => "gpt-3.5-turbo", function => proto sub OpenAIChatCompletion ($prompt is copy, :$role is copy = Whatever, :$model is copy = Whatever, :$temperature is copy = Whatever, :$max-tokens is copy = Whatever, Numeric :$top-p = 1, Int :$n where { ... } = 1, Bool :$stream = Bool::False, :$stop = Whatever, Numeric :$presence-penalty = 0, Numeric :$frequency-penalty = 0, :@images is copy = Empty, :api-key(:$auth-key) is copy = Whatever, Int :$timeout where { ... } = 10, :$format is copy = Whatever, Str :$method = "tiny", Str :$base-url = "https://api.openai.com/v1") {*}, temperature => 0.8, total-probability-cutoff => 0.03, max-tokens => 300, format => "values", prompts => [], prompt-delimiter => " ", examples => [], stop-tokens => [], tools => [], tool-prompt => "", tool-request-parser => WhateverCode, tool-response-insertion-function => WhateverCode, images => [], argument-renames => {:api-key("auth-key"), :stop-tokens("stop")}, evaluator => LLM::Functions::EvaluatorChat_6288007030840), formatron => "Str"))

```

**Remark:** `llm-configuration(Whatever)` is equivalent to `llm-configuration('OpenAI')`.

**Remark:** Both the "OpenAI" and "ChatGPT" configuration use functions of the package "WWW::OpenAI", [AAp2].
The "OpenAI" configuration is for text-completions;
the "ChatGPT" configuration is for chat-completions.

### PaLM-based

Here is the default PaLM configuration:

```
.say for llm-configuration('PaLM').Hash;

```

```
# tool-request-parser => (WhateverCode)
# stop-tokens => []
# images => []
# format => values
# name => palm
# api-user-id => user:948311569993
# argument-renames => {api-key => auth-key, max-tokens => max-output-tokens, stop-tokens => stop-sequences}
# examples => []
# api-key => (Whatever)
# prompt-delimiter =>
# model => text-bison-001
# prompts => []
# temperature => 0.4
# function => &PaLMGenerateText
# tool-response-insertion-function => (WhateverCode)
# tool-prompt =>
# tools => []
# evaluator => (Whatever)
# module => WWW::PaLM
# max-tokens => 300
# total-probability-cutoff => 0
# base-url =>

```

---

## Basic usage of LLM functions

### Textual prompts

Here we make a LLM function with a simple (short, textual) prompt:

```
my &func = llm-function('Show a recipe for:');

```

```
# -> $text, *%args { #`(Block|6288098091184) ... }

```

Here we evaluate over a message:

```
say &func('greek salad');

```

```
# Ingredients:
# - 1 large cucumber, diced
# - 1 bell pepper, diced
# - 1 red onion, thinly sliced
# - 2-3 tomatoes, diced
# - 1 cup Kalamata olives, pitted
# - 1 cup feta cheese, crumbled
# - 1/4 cup extra virgin olive oil
# - 2 tablespoons red wine vinegar
# - 1 teaspoon dried oregano
# - Salt and pepper to taste
#
# Instructions:
# 1. In a large salad bowl, combine the cucumber, bell pepper, red onion, tomatoes, and olives.
# 2. In a small bowl, whisk together the olive oil, red wine vinegar, oregano, salt, and pepper.
# 3. Pour the dressing over the vegetables and toss to combine.
# 4. Add the feta cheese on top of the salad.
# 5. Serve immediately or refrigerate for 1-2 hours to allow the flavors to meld together before serving. Enjoy your delicious Greek salad!

```

### Positional arguments

Here we make a LLM function with a function-prompt and numeric interpreter of the result:

```
my &func2 = llm-function(
        {"How many $^a can fit inside one $^b?"},
        form => Numeric,
        llm-evaluator => 'palm');

```

```
# -> **@args, *%args { #`(Block|6288154113224) ... }

```

Here were we apply the function:

```
my $res2 = &func2("tennis balls", "toyota corolla 2010");

```

```
# 48

```

Here we show that we got a number:

```
$res2 ~~ Numeric

```

```
# False

```

### Named arguments

Here the first argument is a template with two named arguments:

```
my &func3 = llm-function(-> :$dish, :$cuisine {"Give a recipe for $dish in the $cuisine cuisine."}, llm-evaluator => 'palm');

```

```
# -> **@args, *%args { #`(Block|6288120035248) ... }

```

Here is an invocation:

```
&func3(dish => 'salad', cuisine => 'Russian', max-tokens => 300);

```

```
# **Ingredients:**
#
# * 1 head of cabbage (chopped)
# * 2 carrots (grated)
# * 1 cucumber (chopped)
# * 1/2 red onion (chopped)
# * 1/2 cup of mayonnaise
# * 1/4 cup of sour cream
# * Salt and pepper to taste
#
# **Instructions:**
#
# 1. In a large bowl, combine the cabbage, carrots, cucumber, and onion.
# 2. In a small bowl, whisk together the mayonnaise, sour cream, salt, and pepper.
# 3. Pour the dressing over the salad and toss to coat.
# 4. Serve immediately or chill for later.
#
# **Tips:**
#
# * For a more flavorful salad, add some chopped fresh herbs, such as dill or parsley.
# * You can also add some protein to the salad, such as shredded chicken or crumbled bacon.
# * If you don't have any sour cream on hand, you can use yogurt or even just milk to thin out the mayonnaise.
# * This salad is best served cold, so make sure to chill it for at least a few hours before serving.

```

---

## LLM example functions

The function `llm-example-function` can be given a training set of examples in order
to generating results according to the "laws" implied by that training set.

Here a LLM is asked to produce a generalization:

```
llm-example-function([ 'finger' => 'hand', 'hand' => 'arm' ])('foot')

```

```
# leg

```

Here is an array of training pairs is used:

```
'Oppenheimer' ==> (["Einstein" => "14 March 1879", "Pauli" => "April 25, 1900"] ==> llm-example-function)()

```

```
# April 22, 1904

```

Here is defined a LLM function for translating WL associations into Python dictionaries:

```
my &fea = llm-example-function( '<| A->3, 4->K1 |>' => '{ A:3, 4:K1 }');
&fea('<| 23->3, G->33, T -> R5|>');

```

```
# { 23:3, G:33, T:R5 }

```

The function `llm-example-function` takes as a first argument:

* Single `Pair` object of two scalars
* Single `Pair` object of two `Positional` objects with the same length
* A `Hash`
* A `Positional` object of pairs

**Remark:** The function `llm-example-function` is implemented with `llm-function` and suitable prompt.

Here is an example of using hints:

```
my &fec = llm-example-function(
        ["crocodile" => "grasshopper", "fox" => "cardinal"],
        hint => 'animal colors');

say &fec('raccoon');

```

```
# panda

```

---

## Using predefined prompts

Using predefined prompts of the package ["LLM::Prompts"](https://raku.land/zef:antononcube/LLM::Prompts), [AAp8],
can be very convenient in certain (many) cases.

Here is an example using "Fixed That For You" synthesis:

```
use LLM::Prompts;

llm-synthesize([llm-prompt('FTFY'), 'Wha is ther population?'])

```

```
# What is the population?

```

---

## Using chat-global prompts

The configuration objects can be given prompts that influence the LLM responses
"globally" throughout the whole chat. (See the second sequence diagram above.)

For detailed examples see the documents:

* ["Using engineered prompts"](./docs/Using-engineered-prompts_woven.md)
* ["Expand tests into documentation examples"](./docs/Expand-tests-into-doc-examples_woven.md)

---

## Chat objects

Here we create chat object that uses OpenAI's ChatGPT:

```
my $prompt = 'You are a gem expert and you give concise answers.';
my $chat = llm-chat(chat-id => 'gem-expert-talk', conf => 'ChatGPT', :$prompt);

```

```
# LLM::Functions::Chat(chat-id = gem-expert-talk, llm-evaluator.conf.name = chatgpt, messages.elems = 0)

```

```
$chat.eval('What is the most transparent gem?');

```

```
# Diamond is the most transparent gem.

```

```
$chat.eval('Ok. What are the second and third most transparent gems?');

```

```
# The second most transparent gem is sapphire, and the third most transparent gem is emerald.

```

Here are the prompt(s) and all messages of the chat object:

```
$chat.say

```

```
# Chat: gem-expert-talk
# ⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺
# Prompts: You are a gem expert and you give concise answers.
# ⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺
# role	user
# content	What is the most transparent gem?
# timestamp	2024-03-17T15:35:54.133613-04:00
# ⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺
# role	assistant
# content	Diamond is the most transparent gem.
# timestamp	2024-03-17T15:35:54.831745-04:00
# ⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺
# role	user
# content	Ok. What are the second and third most transparent gems?
# timestamp	2024-03-17T15:35:54.846413-04:00
# ⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺⸺
# role	assistant
# content	The second most transparent gem is sapphire, and the third most transparent gem is emerald.
# timestamp	2024-03-17T15:35:56.018877-04:00

```

---

## AI-vision functions

Consider [this image](https://raw.githubusercontent.com/antononcube/MathematicaForPrediction/master/MarkdownDocuments/Diagrams/AI-vision-via-WL/0iyello2xfyfo.png):

![](https://raw.githubusercontent.com/antononcube/MathematicaForPrediction/master/MarkdownDocuments/Diagrams/AI-vision-via-WL/0iyello2xfyfo.png)

Here we import the image (as a Base64 string):

```
use Image::Markup::Utilities;
my $url = 'https://raw.githubusercontent.com/antononcube/MathematicaForPrediction/master/MarkdownDocuments/Diagrams/AI-vision-via-WL/0iyello2xfyfo.png';
my $img = image-import($url);
$img.substr(^100)

```

```
# ![](data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAArwAAAK8CAIAAACC2PsUAAAA1XpUWHRSYXcgcHJvZmlsZSB0e

```

Here we apply OpenAI's AI vision model `gpt-4-vision-preview` (which is the default one) over the ***URL of the image***:

```
llm-vision-synthesize('Describe the image.', $url);

```

```
# The image is an infographic titled "Cyber Week Spending Set to Hit New Highs in 2023". It shows estimated online spending on Thanksgiving weekend in the United States for the years 2019 through 2023, with 2023 being a forecast. The data is presented in a bar chart format, with different colored bars representing each year.
#
# There are three categories on the horizontal axis: Thanksgiving Day, Black Friday, and Cyber Monday. The vertical axis represents spending in billions of dollars, ranging from $0B to $12B.
#
# The bars show an increasing trend in spending over the years for each of the three days. For Thanksgiving Day, the spending appears to have increased from just over $4B in 2019 to a forecast of around $6B in 2023. Black Friday shows a rise from approximately $7B in 2019 to a forecast of nearly $10B in 2023. Cyber Monday exhibits the highest spending, with an increase from around $9B in 2019 to a forecast of over $11B in 2023.
#
# There is an icon of a computer monitor with a shopping tag, indicating the focus on online spending. At the bottom of the image, the source of the data is credited to Adobe Analytics, and the logo of Statista is present, indicating that they have produced or distributed the infographic. There are also two icons, one resembling a Creative Commons license and the other a share or export button.

```

Here we apply Gemini's AI vision model `gemini-pro-vision` over the image:

```
llm-vision-synthesize('Describe the image.', $img, e => 'Gemini');

```

```
# The image shows the estimated online spending on Thanksgiving weekend in the United States from 2019 to 2023. The y-axis shows the spending amount in billions of dollars, while the x-axis shows the year. The data is presented in four bars, each representing a different year. The colors of the bars are blue, orange, green, and yellow, respectively. The values for each year are shown below:
#
# * 2019: $7.4 billion
# * 2020: $9.0 billion
# * 2021: $10.7 billion
# * 2022: $11.3 billion
# * 2023: $12.2 billion (estimated)
#
# The image shows that online spending on Thanksgiving weekend has increased steadily over the years. In 2023, online spending is expected to reach $12.2 billion, up from $7.4 billion in 2019.

```

**Remark:** Currently, Gemini works with (Base64) images only (and does not with URLs.) OpenAI's vision works with both URLs and images.

The function `llm-vision-function` uses the same evaluators (configurations, models) as `llm-vision-synthesize`.

---

## Potential problems

With PaLM with certain wrong configuration we get the error:

```
error => {code => 400, message => Messages must alternate between authors., status => INVALID_ARGUMENT}

```

---

## TODO

* DONE Resources
  * See ["LLM::Prompts"](https://github.com/antononcube/Raku-LLM-Prompts)
  * DONE Gather prompts
  * DONE Process prompts into a suitable database
    * Using JSON.
* TODO Implementation
  * DONE Processing and array of prompts as a first argument
  * DONE Prompt class / object / record
    * Again, see ["LLM::Prompts"](https://github.com/antononcube/Raku-LLM-Prompts)
    * For retrieval and management of prompts.
      * DONE Prompts can be both plain strings or templates / functions.
      * DONE Each prompt has associated metadata:
        * Type: persona, function, modifier
        * Tool/parser
        * Keywords
        * Contributor?
        * Topics: "Advisor bot", "AI Guidance", "For Fun", ...
          * See: <https://resources.wolframcloud.com/PromptRepository/>
    * DONE Most likely, there would be a separate package "LLM::Prompts", [AAp8].
  * MAYBE Random selection of LLM-evaluator
    * Currently, the LLM-evaluator of the LLM-functions and LLM-chats is static, assigned at creation.
    * This is easily implemented at "top-level."
  * DONE Chat class / object
    * For long conversations
  * DONE Include LLaMA
    * Just using a different `:$base-url` for "ChatGPT" for the configurations.
  * DONE Include Gemini
    * DONE Separate configuration
    * DONE Its own evaluator class
  * DONE LLM example function
    * DONE First version with the signatures:
      * `@pairs`
      * `@input => @output`
      * Hint option
    * DONE Verify works with OpenAI
    * DONE Verify works with PaLM
    * DONE Verify works with Gemini
  * DONE Interpreter argument for `llm-function`
    * See the `formatron` attribute of `LLM::Functions::Evaluator`.
  * DONE Adding `form` option to chat objects evaluator
  * DONE Implement `llm-embedding` function
    * Generic, universal function for accessing the embeddings of different providers/models.
* TODO CLI
  * TODO Based on Chat objects
  * TODO Storage and retrieval of chats
  * TODO Has as parameters all attributes of the LLM-configuration objects.
* TODO Documentation
  * TODO Detailed parameters description
    * TODO Configuration
    * TODO Evaluator
    * TODO Chat
  * DONE Using engineered prompts
  * DONE Expand tests in documentation examples
  * DONE Conversion of a test file tests into Gherkin specs
  * DONE Number game programming
    * DONE Man vs Machine
    * DONE Machine vs Machine
  * DONE Using retrieved prompts
  * TODO Longer conversations / chats

---

## References

### Articles

[AA1] Anton Antonov,
["Generating documents via templates and LLMs"](https://rakuforprediction.wordpress.com/2023/07/11/generating-documents-via-templates-and-llms/),
(2023),
[RakuForPrediction at WordPress](https://rakuforprediction.wordpress.com).

[ZG1] Zoubin Ghahramani,
["Introducing PaLM 2"](https://blog.google/technology/ai/google-palm-2-ai-large-language-model/),
(2023),
[Google Official Blog on AI](https://blog.google/technology/ai/).

### Repositories, sites

[MAI1] MistralAI team, [MistralAI platform](https://docs.mistral.ai).

[OAI1] OpenAI team, [OpenAI platform](https://platform.openai.com/).

[WRIr1] Wolfram Research, Inc.
[Wolfram Prompt Repository](https://resources.wolframcloud.com/PromptRepository/).

### Packages, paclets

[AAp1] Anton Antonov,
[LLM::Functions Raku package](https://github.com/antononcube/Raku-LLM-Functions),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp2] Anton Antonov,
[WWW::OpenAI Raku package](https://github.com/antononcube/Raku-WWW-OpenAI),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp3] Anton Antonov,
[WWW::PaLM Raku package](https://github.com/antononcube/Raku-WWW-PaLM),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp4] Anton Antonov,
[Text::SubParsers Raku package](https://github.com/antononcube/Raku-Text-SubParsers),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp5] Anton Antonov,
[Text::CodeProcessing Raku package](https://github.com/antononcube/Raku-Text-CodeProcessing),
(2021),
[GitHub/antononcube](https://github.com/antononcube).

[AAp6] Anton Antonov,
[ML::FindTextualAnswer Raku package](https://github.com/antononcube/Raku-ML-FindTextualAnswer),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp7] Anton Antonov,
[ML::NLPTemplateEngine Raku package](https://github.com/antononcube/Raku-ML-NLPTemplateEngine),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp8] Anton Antonov,
[LLM::Prompts Raku package](https://github.com/antononcube/Raku-LLM-Prompts),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp9] Anton Antonov,
[WWW::MistralAI Raku package](https://github.com/antononcube/Raku-WWW-MistralAI),
(2023),
[GitHub/antononcube](https://github.com/antononcube).

[AAp10] Anton Antonov,
[LLMPrompts Python package](https://pypi.org/project/LLMPrompts/),
(2023),
[PyPI.org/antononcube](https://pypi.org/user/antononcube/).

[AAp11] Anton Antonov,
[WWW::Gemini Raku package](https://github.com/antononcube/Raku-WWW-Gemini),
(2024),
[GitHub/antononcube](https://github.com/antononcube).

[WRIp1] Wolfram Research, Inc.
[LLMFunctions paclet](https://resources.wolframcloud.com/PacletRepository/resources/Wolfram/LLMFunctions/),
(2023),
[Wolfram Language Paclet Repository](https://resources.w


## dist_zef-antononcube-LLM-Functions.md
## Chunk 2 of 2
olframcloud.com/PacletRepository/).