## dist_cpan-ANTONOV-ML-TriesWithFrequencies.md
# Raku ML::TriesWithFrequencies

This Raku package has functions for creation and manipulation of
[Tries (Prefix trees)](https://en.wikipedia.org/wiki/Trie)
with frequencies.

The package provides Machine Learning (ML) functionalities,
not "just" a Trie data structure.

This Raku implementation closely follows the Java implementation [AAp3].

The system of function names follows the one used in the Mathematica package [AAp2].

**Remark:** Below Mathematica and Wolfram Language (WL) are used as synonyms.

**Remark:** There is a Raku package with an alternative implementation, [AAp6],
made mostly for comparison studies. (See the implementation notes below.)
The package in this repository, `ML::TriesWithFrequencies`, is my *primary*
Tries-with-frequencies package.

---

## Usage

Consider a trie (prefix tree) created over a list of words:

```
use ML::TriesWithFrequencies;
my $tr = trie-create-by-split( <bar bark bars balm cert cell> );
trie-say($tr);

```

```
# TRIEROOT => 6
# ├─b => 4
# │ └─a => 4
# │   ├─l => 1
# │   │ └─m => 1
# │   └─r => 3
# │     ├─k => 1
# │     └─s => 1
# └─c => 2
#   └─e => 2
#     ├─l => 1
#     │ └─l => 1
#     └─r => 1
#       └─t => 1

```

Here we convert the trie with frequencies above into a trie with probabilities:

```
my $ptr = trie-node-probabilities( $tr );
trie-say($ptr);

```

```
# TRIEROOT => 1
# ├─b => 0.6666666666666666
# │ └─a => 1
# │   ├─l => 0.25
# │   │ └─m => 1
# │   └─r => 0.75
# │     ├─k => 0.3333333333333333
# │     └─s => 0.3333333333333333
# └─c => 0.3333333333333333
#   └─e => 1
#     ├─l => 0.5
#     │ └─l => 1
#     └─r => 0.5
#       └─t => 1

```

Here we shrink the trie with probabilities above:

```
trie-say(trie-shrink($ptr));

```

```
# TRIEROOT => 1
# ├─ba => 0.6666666666666666
# │ ├─lm => 0.25
# │ └─r => 0.75
# │   ├─k => 0.3333333333333333
# │   └─s => 0.3333333333333333
# └─ce => 0.3333333333333333
#   ├─ll => 0.5
#   └─rt => 0.5

```

Here we retrieve a sub-trie with a key:

```
trie-say(trie-retrieve($ptr, 'bar'.comb))

```

```
# r => 0.75
# ├─k => 0.3333333333333333
# └─s => 0.3333333333333333

```

---

## Representation

Each trie is a tree of objects of the class `ML::TriesWithFrequencies::Trie`.
Such trees can be nicely represented as hash-maps. For example:

```
my $tr = trie-shrink(trie-create-by-split(<core cort>));
say $tr.gist;

```

```
# {TRIEROOT => {TRIEVALUE => 2, cor => {TRIEVALUE => 2, e => {TRIEVALUE => 1}, t => {TRIEVALUE => 1}}}}

```

The function `trie-say` uses that Hash-representation:

```
trie-say($tr)

```

```
# TRIEROOT => 2
# └─cor => 2
#   ├─e => 1
#   └─t => 1

```

### JSON

The JSON-representation follows the inherent object-tree
representation with `ML::TriesWithFrequencies::Trie`:

```
say $tr.JSON;

```

```
# {"key":"TRIEROOT", "value":2, "children":[{"key":"cor", "value":2, "children":[{"key":"t", "value":1, "children":[]}, {"key":"e", "value":1, "children":[]}]}]}

```

### XML

The XML-representation follows (resembles) the Hash-representation
(and output from `trie-say`):

```
say $tr.XML;

```

```
# <TRIEROOT>
#  <TRIEVALUE>2</TRIEVALUE>
#  <cor>
#   <TRIEVALUE>2</TRIEVALUE>
#   <t>
#    <TRIEVALUE>1</TRIEVALUE>
#   </t>
#   <e>
#    <TRIEVALUE>1</TRIEVALUE>
#   </e>
#  </cor>
# </TRIEROOT>

```

Using the XML representation allows for
[XPath](https://www.w3schools.com/xml/xml_xpath.asp)
searches, say, using the package
[`XML::XPath`](https://github.com/ufobat/p6-XML-XPath).
Here is an example:

```
use XML::XPath;
my $tr0 = trie-create-by-split(<bell best>);
trie-say($tr0);

```

```
# TRIEROOT => 2
# └─b => 2
#   └─e => 2
#     ├─l => 1
#     │ └─l => 1
#     └─s => 1
#       └─t => 1

```

Convert to XML:

```
say $tr0.XML;

```

```
# <TRIEROOT>
#  <TRIEVALUE>2</TRIEVALUE>
#  <b>
#   <TRIEVALUE>2</TRIEVALUE>
#   <e>
#    <TRIEVALUE>2</TRIEVALUE>
#    <s>
#     <TRIEVALUE>1</TRIEVALUE>
#     <t>
#      <TRIEVALUE>1</TRIEVALUE>
#     </t>
#    </s>
#    <l>
#     <TRIEVALUE>1</TRIEVALUE>
#     <l>
#      <TRIEVALUE>1</TRIEVALUE>
#     </l>
#    </l>
#   </e>
#  </b>
# </TRIEROOT>

```

Search for `<b e l>`:

```
say XML::XPath.new(xml=>$tr0.XML).find('//b/e/l');

```

```
# <l>
#     <TRIEVALUE>1</TRIEVALUE>
#     <l>
#      <TRIEVALUE>1</TRIEVALUE>
#     </l>
#    </l>

```

### WL

The Hash-representation is used in the Mathematica package [AAp2].
Hence, such WL format is provided by the Raku package:

```
say $tr.WL;

```

```
# <|$TrieRoot -> <|$TrieValue -> 2, "cor" -> <|$TrieValue -> 2, "t" -> <|$TrieValue -> 1|>, "e" -> <|$TrieValue -> 1|>|>|>|>

```

---

## Implementation notes

This package is a Raku re-implementation of the Java Trie package [AAp3].

The initial implementation was:

* ≈ 5-6 times slower than the Mathematica implementation [AAp2]
* ≈ 100 times slower than the Java implementation [AAp3]

The initial implementation used:

* General types for Trie nodes, i.e. `Str` for the key and `Numeric` for the value
* Argument type verification with `where` statements in the signatures of the `trie-*` functions

After reading [RAC1] I refactored the code to use native types (`num`, `str`)
and moved the `where` verifications inside the functions.

I also refactored the function `trie-merge` to use less copying of data and
to take into account which of the two tries has smaller number of children.

After those changes the current Raku implementation is:

* ≈ 2.5 times slower than the Mathematica implementation [AAp2]
* ≈ 40 times slower than the Java implementation [AAp3]

After the (monumental) work on
[the new MoarVM dispatch mechanism](https://6guts.wordpress.com/2021/09/29/the-new-moarvm-dispatch-mechanism-is-here/),
[JW1], was incorporated in standard Rakudo releases (September/October 2021)
additional 20% speed-up was obtained. Currently this package is:

* ≈ 2.0 times slower than the Mathematica implementation [AAp2]
* ≈ 30 times slower than the Java implementation [AAp3]

These speed improvements are definitely not satisfactory. I strongly consider:

1. Re-implementing in Raku the Mathematica package [AAp2], i.e. to move into Tries that are hashes.

   * (It turned out option 1 does not produce better results; see [AAp6].)
2. Re-implementing in C or C++ the Java package [AAp3] and hooking it up to Raku.

---

## TODO

In the following list the most important items are placed first.

* Implement "get words" and "get root-to-leaf paths" functions.

  * See `trie-words` and `trie-root-to-leaf-paths`.
* Convert most of the WL unit tests in [AAp5] into Raku tests.
* Implement Trie traversal functions.

  * The general `trie-map` function is in a separate role.

    * A concrete traversal functionality is a class that does the role
      and provides additional context.
* Implement (sub-)trie removal functions.

  * By threshold (below and above)
  * By Pareto principle adherence (top and bottom)
  * By regex over the keys
* Implement optional ULP spec argument for relevant functions:

  * `trie-root-to-leaf-paths`
  * `trie-words`
  * Membership test functions?
* Design and code refactoring so trie objects to have OOP interface.

  * Instead of just having `trie-words($tr, <c>)` we should be also able to say `$tr.trie-words(<c>)`.
* Implement `trie-prune` function.
* Implement Trie-based classification.
* Investigate faster implementations.

  * Re-implement the Trie functionalities using hash representation (instead of a tree of Trie-node objects.)

    * See [AAp6].
  * Make a C or C++ implementation and hook it up to Raku.
* Document examples of doing Trie-based text mining or data-mining.
* Program a trie-form visualization that is "wide", i.e. places the children nodes horizontally.

---

## References

### Articles

[AA1] Anton Antonov,
["Tries with frequencies for data mining"](https://mathematicaforprediction.wordpress.com/2013/12/06/tries-with-frequencies-for-data-mining/),
(2013),
[MathematicaForPrediction at WordPress](https://mathematicaforprediction.wordpress.com).

[AA2] Anton Antonov,
["Removal of sub-trees in tries"](https://mathematicaforprediction.wordpress.com/2014/10/12/removal-of-sub-trees-in-tries/),
(2013),
[MathematicaForPrediction at WordPress](https://mathematicaforprediction.wordpress.com).

[AA3] Anton Antonov,
["Tries with frequencies in Java"](https://mathematicaforprediction.wordpress.com/2017/01/31/tries-with-frequencies-in-java/),
(2017),
[MathematicaForPrediction at WordPress](https://mathematicaforprediction.wordpress.com).
[GitHub Markdown](https://github.com/antononcube/MathematicaForPrediction).

[JW1] Jonathan Worthington,
["The new MoarVM dispatch mechanism is here!"](https://6guts.wordpress.com/2021/09/29/the-new-moarvm-dispatch-mechanism-is-here/),
(2021),
[6guts at WordPress](https://6guts.wordpress.com).

[RAC1] Tib,
["Day 10: My 10 commandments for Raku performances"](https://raku-advent.blog/2020/12/10/day-10-my-10-commandments-for-raku-performances/),
(2020),
[Raku Advent Calendar](https://raku-advent.blog).

[WK1] Wikipedia entry, [Trie](https://en.wikipedia.org/wiki/Trie).

### Packages

[AAp1] Anton Antonov,
[Tries with frequencies Mathematica Version 9.0 package](https://github.com/antononcube/MathematicaForPrediction/blob/master/TriesWithFrequenciesV9.m),
(2013),
[MathematicaForPrediction at GitHub](https://github.com/antononcube/MathematicaForPrediction).

[AAp2] Anton Antonov,
[Tries with frequencies Mathematica package](https://github.com/antononcube/MathematicaForPrediction/blob/master/TriesWithFrequencies.m),
(2013-2018),
[MathematicaForPrediction at GitHub](https://github.com/antononcube/MathematicaForPrediction).

[AAp3] Anton Antonov,
[Tries with frequencies in Java](https://github.com/antononcube/MathematicaForPrediction/tree/master/Java/TriesWithFrequencies),
(2017),
[MathematicaForPrediction at GitHub](https://github.com/antononcube/MathematicaForPrediction).

[AAp4] Anton Antonov,
[Java tries with frequencies Mathematica package](https://github.com/antononcube/MathematicaForPrediction/blob/master/JavaTriesWithFrequencies.m),
(2017),
[MathematicaForPrediction at GitHub](https://github.com/antononcube/MathematicaForPrediction).

[AAp5] Anton Antonov,
[Java tries with frequencies Mathematica unit tests](https://github.com/antononcube/MathematicaForPrediction/blob/master/UnitTests/JavaTriesWithFrequencies-Unit-Tests.wlt),
(2017),
[MathematicaForPrediction at GitHub](https://github.com/antononcube/MathematicaForPrediction).

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

### Videos

[AAv1] Anton Antonov,
["Prefix Trees with Frequencies for Data Analysis and Machine Learning"](https://www.youtube.com/watch?v=MdVp7t8xQbQ),
(2017),
Wolfram Technology Conference 2017,
[Wolfram channel at YouTube](https://www.youtube.com/channel/UCJekgf6k62CQHdENWf2NgAQ).


## dist_zef-sdondley-Doc-Executable.md
[![Actions Status](https://github.com/sdondley/Doc-Executable/actions/workflows/test.yml/badge.svg)](https://github.com/sdondley/Doc-Executable/actions)

# Doc::Executable

Doc::Executable - executes a menu for selecting "executable" Raku tutorials in this distribution which are parsed and executed as Raku code.

# SYNOPSIS

From the command line:

```
docexec         # opens menu for finding executable doc and executes selection
docexec $file   # opens executable doc file and executes selection

```

# GOALS

The goal of `Doc::Executable` is to make it easy to write plain text Raku tutorials containing code snippets with accompanying explanations.

# DESCRIPTION

The `docexec` command displays a navigable menu on the command line to allow users to select a parseable text file. The text file contains example Raku code along with explanations accompanying each bit of code. Once parsed, the resultant file is run as Raku code with the output showing the results of the code along with the descriptions for how the code works.

This module is in its early development stages and admittedly has limited use, allowing only for the execution of an entire code example file at once. Also, it can only load and execute files packaged in this distribution.

## Executable docs? Why?

Anyone who has looked at code documentation has seen embedded code examples like this to illustrate how code works:

```
(1, 2, 3).shift;      # Error Cannot call 'shift' on an immutable 'List'
(1, 2, 3).unshift(0); # Error Cannot call 'unshift' on an immutable 'List'

```

Often you want to fiddle with the code so you have to break out the electronic scissors and tediously copy and paste the code into a file and then execute it.

So the idea behind a executable doc is to allow you to easily place your collection of code snippets into a single file where they can be more easily edited and to standarize how the examples are output when executed.

A single executable doc example looks like this:

```
##
say 1, 2;
say (1, 2);
#* To pass Lists to a function, be sure to use parentheses
#* Without parentheses, the two elements are treated as separate parameters to the 'say' function
# A List is passed with parentheses which gives a different output.
##

```

This plain text file is written with your favorite text editor.

After getting parsed and executed by this module, it outputs:

```
To pass Lists to a function, be sure to use parentheses:

say 1, 2;
say (1, 2);

Output:
12
(1 2)

Without parentheses, the two elements are treated as separate parameters to the 'say' function
A List is passed with parentheses which gives a different output..

```

And now this output can be exported to your favorite online tutorial.

# ROADMAP

As mentioned, the module in it's current state is rather limited and is more just a proof of concept. Future ideas for improving this distribution include:

* Adding more executable docs
* Documentation for creating new executable doc text files
* Allow users to add their own library of executable documents.
* Permit execution of on example at a time instead of the whole file.
* Templates for output (e.g. for HTML or markdown)
* Search examples by keyword
* Editing of executable documents

Other suggestion on how to make this module more useful are welcome.

# AUTHOR

Steve Dondley [s@dondley.com](mailto:s@dondley.com)

# COPYRIGHT AND LICENSE

Copyright 2022 Steve Dondley

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


## dist_zef-lizmat-L10N-TLH.md
[![Actions Status](https://github.com/lizmat/L10N-TLH/actions/workflows/test.yml/badge.svg)](https://github.com/lizmat/L10N-TLH/actions)

# NAME

L10N::TLH - Klingon localization of Raku

# SYNOPSIS

```
use L10N::TLH;
jatlh "Hello World";

```

# DESCRIPTION

L10N::TLH contains the logic to provide a Klingon localization of the Raku Programming Language.

# AUTHOR

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

Source can be located at: <https://github.com/lizmat/L10N-TLH> . 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 2023, 2024 Elizabeth Mattijsen

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


## dist_zef-FRITH-Spreadsheet-Libxlsxio.md
[![Actions Status](https://github.com/frithnanth/raku-Spreadsheet-Libxlsxio/workflows/test/badge.svg)](https://github.com/frithnanth/raku-Spreadsheet-Libxlsxio/actions)

# NAME

Spreadsheet::Libxlsxio - An interface to libxlsxio, a C library to read and write XLSX files

# SYNOPSIS

```
use Spreadsheet::Libxlsxio;
use Spreadsheet::Libxlsxio::Constants;

my @values;

my $ss = Spreadsheet::Libxlsxio::Read.new: 'mydata.xlsx';
$ss.sheet-list(-> $name {
  @values.push: "[$name]";
  $ss.process: $name,
               -> $, $, $value { @values.push: $value with $value; XLSXIOREAD_CONTINUE },
               -> $, $ { XLSXIOREAD_CONTINUE }
});

# Do something with @values

```

# DESCRIPTION

Spreadsheet::Libxlsxio is an interface to libxlsxio, a C library to read and write XLSX files

libxlsxio is a fast C library released under the terms of the MIT License. It has a nice API, which translates easily using Raku pointy blocks (or closures, or lambdas).

Please check the limitations of this library here: <https://brechtsanders.github.io/xlsxio/>.

This module exports two classes:

* Spreadsheet::Libxlsxio::Read
* Spreadsheet::Libxlsxio::Write

The Read class offers two ways to read an XLSX file:

* iterating through rows and cells;
* using callback functions for each cell and after each row.

The Write class has methods for writing one row at the time, cell after cell, with no random access to a single cell.

## Spreadsheet::Libxlsxio::Read

### new(Str $file!)

### new(Str :$file!)

### new(Buf $data!)

### new(Buf :$data!)

This **multi method** constructor requires one simple or named argument, the file name or the **Buf** variable into which the spreadsheet data has been read.

### version(--> Str)

This method returns the C library version as a **Str** or a **List**, if evaluated in a List context.

```
my $ss = Spreadsheet::Libxlsxio::Read.new: :file('mydata.xlsx');
my $version = $ss.version;
say $version;      # '0.2.29'
say $version.List; # (0 2 29)

```

**Methods to iterate through worksheets, rows, and cells**

### sheetlist-open(--> xlsxioreadersheetlist)

This method opens the worksheet list. It return the worksheet list handler.

### sheetlist-next(xlsxioreadersheetlist $sheetlisthandler --> Str)

This method accepts a worksheet list handler and returns the name of the next available worksheet.

For example:

```
my $ss = Spreadsheet::Libxlsxio::Read.new: :file('mydata.xlsx');
my $sl = $ss.sheetlist-open;
while $ss.sheetlist-next($sl) -> $sheetname { say $sheetname }
$ss.sheetlist-close($sl);

```

### sheetlist-close(xlsxioreadersheetlist $sheetlisthandler)

Closes the worksheet list handler.

### sheet-open(Str :$name, Int :$flag = XLSXIOREAD\_SKIP\_EMPTY\_ROWS --> xlsxioreadersheet)

Opens a worksheet by name. The flag values are defined in the **Spreadsheet::Libxlsxio::Constants** module:

* XLSXIOREAD\_SKIP\_NONE
* XLSXIOREAD\_SKIP\_EMPTY\_ROWS
* XLSXIOREAD\_SKIP\_EMPTY\_CELLS
* XLSXIOREAD\_SKIP\_ALL\_EMPTY
* XLSXIOREAD\_SKIP\_EXTRA\_CELLS

This method returns a handler to the specified worksheet.

### sheet-close(xlsxioreadersheet $sheet)

This method takes the worksheet handler and closes the worksheet.

### sheet-flags(xlsxioreadersheet $sheet --> UInt)

This method takes the worksheet handler and returns the flags set when opening the worksheet.

### last-row-read(xlsxioreadersheet $sheet --> UInt)

This method takes the worksheet handler and returns the index of the last row read.

### last-column-read(xlsxioreadersheet $sheet --> UInt)

This method takes the worksheet handler and returns the index of the last column read.

### next-cell(xlsxioreadersheet $sheet --> Str)

This method takes the worksheet handler and returns the value of the last cell read, or a false value if there are no more cells available in the current row.

### next-row(xlsxioreadersheet $sheet --> UInt)

This method takes the worksheet handler and gets the next row, or a false value if there are no more rows available.

This method must be called before each row.

**Methods that use callback functions for each cell and after each row**

### sheet-list(&callback)

This method sets a callback to be called on each worksheet.

The callback function receives the worksheet name. The actual processing can be done by the following method.

### process(Str $sheetname, &cell-callback, &row-callback, UInt :$flags = XLSXIOREAD\_SKIP\_EMPTY\_ROWS --> Int)

This method processes all rows and columns of a worksheet in a XLSX file.

It takes the sheet name, two callback functions and a flag and returns zero on success or non-zero on error. The first callback is called when a cell value is available; it receives three arguments: the row, the column, and the value contained in the cell. It must return one of these two values, available defined in the **Spreadsheet::Libxlsxio::Constants** module:

* XLSXIOREAD\_CONTINUE
* XLSXIOREAD\_ABORT

The second callback is called after each row; it receives two arguments: the row number (starting from 1) and the maximum column number on the row (starting from 1).

For example one might use both the previous methods to scan the entire spreadsheet:

```
my $ss = Spreadsheet::Libxlsxio::Read.new: 't/test.xlsx';

my @values;

$ss.sheet-list(-> $name {
  note "Processing worksheet [$name]";
  $ss.process: $name,
               -> $, $, $value { @values.push: $value with $value; XLSXIOREAD_CONTINUE },
               -> $, $ { XLSXIOREAD_CONTINUE }
});

dd @values;

```

**NOTE**

All the cell values are returned as **Str**. A helper sub is provided to convert a date cell to a Raku DateTime object:

### sub to-date(Str() $value --> DateTime)

## Spreadsheet::Libxlsxio::Write

```
use Spreadsheet::Libxlsxio;

my $ss = Spreadsheet::Libxlsxio::Write.new: :file('mydata.xlsx'), :sheet('Sheet1');
$ss.detection-rows(10)
   .row-height(10)
   .add-column('Col1', 16)
   .add-column('Col2', 0)
   .add-column('Col3', 0)
   .add-column('Col4', 0)
   .write-row;
my $dt = DateTime.new('2021-07-25T00:00:00').Instant.to-posix[0];
for ^10 -> $i {
  $ss.add-string("Test$i").add-int($i).add-num(π).add-datetime($dt).write-row;
}
$ss.close;

```

### new(Str $file!, Str $sheet?)

### new(Str :$file, Str :$sheet)

This **multi method** constructor requires two simple or named arguments: the file name and the worksheet name.

### close

This method closes the spreadsheet file.

### version(--> Str)

This method returns the C library version as a **Str** or a **List**, if evaluated in a List context.

```
my $ss = Spreadsheet::Libxlsxio::Write.new: :file('mydata.xlsx');
my $version = $ss.version;
say $version;      # '0.2.xx'
say $version.List; # (0 2 xx)

```

**All the following methods return their object, so they may be chained.**

### detection-rows(UInt $rows --> Spreadsheet::Libxlsxio::Write)

This method specifies how many initial rows will be buffered in memory to determine column widths.

### row-height(UInt $height --> Spreadsheet::Libxlsxio::Write)

This method specifies the row height in text lines to use for the current and next rows.

### add-column(Str $name, UInt $width --> Spreadsheet::Libxlsxio::Write)

This method adds a column label cell. It takes two arguments: the label and the column width in characters. It must be called for each column; the row is committed by calling the **write-row** method.

### write-row(--> Spreadsheet::Libxlsxio::Write)

This method marks the end of a row.

### add-string(Str() $value --> Spreadsheet::Libxlsxio::Write)

This method adds a cell containing Str data.

### add-int(Int() $value --> Spreadsheet::Libxlsxio::Write)

This method adds a cell containing Int data.

### add-num(Num() $value --> Spreadsheet::Libxlsxio::Write)

This method adds a cell containing Num data.

### add-datetime(DateTime() $value --> Spreadsheet::Libxlsxio::Write)

This method adds a cell containing DateTime data.

# Installation

To use this module one has to install the libxlsxio C library first.

The library home page is here: <https://brechtsanders.github.io/xlsxio/> and the GitHub project page is <https://github.com/brechtsanders/xlsxio>.

The C library has two dependencies: **expat** (available as libexpat1 on Ubuntu and Debian Linux systems) and one of **minizip** or **libzip** (libminizip1 and libzip5 on Ubuntu or Debian Linux systems).

Installing the library is as simple as typing:

```
sudo make install
sudo ldconfig

```

To install the Raku module using zef (a module management tool):

```
$ zef install Spreadsheet::Libxlsxio

```

# AUTHOR

Fernando Santagata [nando.santagata@gmail.com](mailto:nando.santagata@gmail.com)

# COPYRIGHT AND LICENSE

Copyright 2021 Fernando Santagata

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


## dist_zef-antononcube-ML-AssociationRuleLearning.md
# Raku ML::AssociationRuleLearning

[![SparkyCI](https://ci.sparrowhub.io/project/gh-antononcube-Raku-ML-AssociationRuleLearning/badge)](https://ci.sparrowhub.io)
[![](https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg)](https://opensource.org/licenses/Artistic-2.0)

This repository has the code of a Raku package for
[Association Rule Learning (ARL)](https://en.wikipedia.org/wiki/Association_rule_learning)
functions, [Wk1].

The ARL framework includes the algorithms
[Apriori](https://en.wikipedia.org/wiki/Apriori_algorithm)
and
[Eclat](https://en.wikipedia.org/wiki/Association_rule_learning#Eclat_algorithm),
and the measures
[confidence](https://en.wikipedia.org/wiki/Association_rule_learning#Confidence),
[lift](https://en.wikipedia.org/wiki/Association_rule_learning#Lift), and
[conviction](https://en.wikipedia.org/wiki/Association_rule_learning#Conviction),
(and others.)

For computational introduction to ARL utilization (in Mathematica) see the article
["Movie genre associations"](https://mathematicaforprediction.wordpress.com/2013/10/06/movie-genre-associations/),
[AA1].

The examples below use the packages
["Data::Generators"](https://raku.land/cpan:ANTONOV/Data::Generators),
["Data::Reshapers"](https://raku.land/cpan:ANTONOV/Data::Reshapers), and
["Data::Summarizers"](https://raku.land/cpan:ANTONOV/Data::Summarizers), described in the article
["Introduction to data wrangling with Raku"](https://rakuforprediction.wordpress.com/2021/12/31/introduction-to-data-wrangling-with-raku/),
[AA2].

---

## Installation

Via zef-ecosystem:

```
zef install ML::AssociationRuleLearning

```

From GitHub:

```
zef install https://github.com/antononcube/Raku-ML-AssociationRuleLearning

```

---

## Frequent sets finding

Here we get the Titanic dataset (from "Data::Reshapers") and summarize it:

```
use Data::Reshapers;
use Data::Summarizers;
my @dsTitanic = get-titanic-dataset();
records-summary(@dsTitanic);

```

```
# +-----------------+-------------------+----------------+---------------+----------------+
# | id              | passengerSurvival | passengerClass | passengerSex  | passengerAge   |
# +-----------------+-------------------+----------------+---------------+----------------+
# | 972     => 1    | died     => 809   | 3rd => 709     | male   => 843 | 20      => 334 |
# | 546     => 1    | survived => 500   | 1st => 323     | female => 466 | -1      => 263 |
# | 896     => 1    |                   | 2nd => 277     |               | 30      => 258 |
# | 512     => 1    |                   |                |               | 40      => 190 |
# | 802     => 1    |                   |                |               | 50      => 88  |
# | 47      => 1    |                   |                |               | 60      => 57  |
# | 1227    => 1    |                   |                |               | 0       => 56  |
# | (Other) => 1302 |                   |                |               | (Other) => 63  |
# +-----------------+-------------------+----------------+---------------+----------------+

```

**Problem:** Find all combinations of values of the variables "passengerAge", "passengerClass", "passengerSex", and
"passengerSurvival" that appear more than 200 times in the Titanic dataset.

Here is how we use the function `frequent-sets` to give an answer:

```
use ML::AssociationRuleLearning;
my @freqSets = frequent-sets(@dsTitanic, min-support => 200, min-number-of-items => 2, max-number-of-items => Inf):counts;
@freqSets.elems

```

```
# 11

```

The function `frequent-sets` returns the frequent sets together with their support.

Here we tabulate the result:

```
say to-pretty-table(@freqSets.map({ %( Frequent-set => $_.key.join(' '), Count => $_.value) }), align => 'l');

```

```
# +-------+-------------------------------------------------------------+
# | Count | Frequent-set                                                |
# +-------+-------------------------------------------------------------+
# | 208   | passengerAge:-1 passengerClass:3rd                          |
# | 206   | passengerAge:20 passengerClass:3rd                          |
# | 207   | passengerAge:20 passengerSex:male                           |
# | 207   | passengerAge:20 passengerSurvival:died                      |
# | 200   | passengerClass:1st passengerSurvival:survived               |
# | 216   | passengerClass:3rd passengerSex:female                      |
# | 493   | passengerClass:3rd passengerSex:male                        |
# | 418   | passengerClass:3rd passengerSex:male passengerSurvival:died |
# | 528   | passengerClass:3rd passengerSurvival:died                   |
# | 339   | passengerSex:female passengerSurvival:survived              |
# | 682   | passengerSex:male passengerSurvival:died                    |
# +-------+-------------------------------------------------------------+

```

We can verify the result by looking into these group counts, [AA2]:

```
my $obj = group-by( @dsTitanic, <passengerClass passengerSex>);
.say for $obj>>.elems.grep({ $_.value >= 200 });
$obj = group-by( @dsTitanic, <passengerClass passengerSurvival passengerSex>);
.say for $obj>>.elems.grep({ $_.value >= 200 });

```

```
# 3rd.female => 216
# 3rd.male => 493
# 3rd.died.male => 418

```

Or these contingency tables:

```
my $obj = group-by( @dsTitanic, "passengerClass") ;
$obj = $obj.map({ $_.key => cross-tabulate( $_.value, "passengerSex", "passengerSurvival" ) });
.say for $obj.Array;

```

```
# 3rd => {female => {died => 110, survived => 106}, male => {died => 418, survived => 75}}
# 1st => {female => {died => 5, survived => 139}, male => {died => 118, survived => 61}}
# 2nd => {female => {died => 12, survived => 94}, male => {died => 146, survived => 25}}

```

**Remark:** For datasets -- i.e. arrays of hashes -- `frequent-sets` preprocesses the data by concatenating
column names with corresponding column values. This is done in order to prevent "collisions" of same values
coming from different columns. If that concatenation is not desired then manual preprocessing like this can be used:

```
@dsTitanic.map({ $_.values.List }).Array

```

**Remark:** `frequent-sets`'s argument `min-support` can take both integers greater than 1 and frequencies between 0 and 1.
(If an integer greater than one is given, then the corresponding frequency is derived.)

**Remark:** By default `frequent-sets` uses the Eclat algorithm. The functions `apriori` and `eclat`
call `frequent-sets` with the option settings `method=>'Apriori'` and `method=>'Eclat'` respectively.

---

## Association rules finding

Here we find association rules with min support 0.3 and min confidence 0.7:

```
association-rules(@dsTitanic, min-support => 0.3, min-confidence => 0.7)
==> to-pretty-table

```

```
# +------------------------+-------+----------+----------+------------+------------+----------+-------------------------------------------+
# |       consequent       | count | leverage |   lift   | conviction | confidence | support  |                 antecedent                |
# +------------------------+-------+----------+----------+------------+------------+----------+-------------------------------------------+
# | passengerSurvival:died |  528  | 0.068615 | 1.204977 |  1.496229  |  0.744711  | 0.403361 |             passengerClass:3rd            |
# | passengerSurvival:died |  682  | 0.122996 | 1.309025 |  2.000009  |  0.809015  | 0.521008 |             passengerSex:male             |
# |   passengerSex:male    |  682  | 0.122996 | 1.309025 |  2.267729  |  0.843016  | 0.521008 |           passengerSurvival:died          |
# | passengerSurvival:died |  418  | 0.086564 | 1.371894 |  2.510823  |  0.847870  | 0.319328 |    passengerClass:3rd passengerSex:male   |
# |   passengerSex:male    |  418  | 0.059562 | 1.229290 |  1.708785  |  0.791667  | 0.319328 | passengerClass:3rd passengerSurvival:died |
# +------------------------+-------+----------+----------+------------+------------+----------+-------------------------------------------+

```

### Reusing found frequent sets

The function `frequent-sets` takes the adverb ":object" that makes `frequent-sets` return an object of type
`ML::AssociationRuleLearning::Apriori` or `ML::AssociationRuleLearning::Eclat`,
which can be "pipelined" to find association rules.

Here we find frequent sets, return the corresponding object, and retrieve the result:

```
my $eclatObj = frequent-sets(@dsTitanic.map({ $_.values.List }).Array, min-support => 0.12, min-number-of-items => 2, max-number-of-items => 6):object;
$eclatObj.result.elems

```

```
# 23

```

Here we find association rules and pretty-print them:

```
$eclatObj.find-rules(min-confidence=>0.7)
==> to-pretty-table

```

```
# +------------+------------+----------+----------+------------+-------+----------+------------+
# | antecedent | consequent | leverage | support  | conviction | count |   lift   | confidence |
# +------------+------------+----------+----------+------------+-------+----------+------------+
# |     -1     |    male    | 0.011938 | 0.141329 |  1.200349  |  185  | 1.092265 |  0.703422  |
# |    died    |    male    | 0.122996 | 0.521008 |  2.267729  |  682  | 1.309025 |  0.843016  |
# |    male    |    died    | 0.122996 | 0.521008 |  2.000009  |  682  | 1.309025 |  0.809015  |
# |  20 died   |    male    | 0.032122 | 0.134454 |  2.313980  |  176  | 1.313897 |  0.846154  |
# |  20 male   |    died    | 0.036249 | 0.134454 |  2.482811  |  176  | 1.369117 |  0.846154  |
# |  -1 died   |    male    | 0.027990 | 0.121467 |  2.181917  |  159  | 1.299438 |  0.836842  |
# |  -1 male   |    died    | 0.034121 | 0.121467 |  2.717870  |  159  | 1.390646 |  0.859459  |
# |  3rd died  |    male    | 0.059562 | 0.319328 |  1.708785  |  418  | 1.229290 |  0.791667  |
# |  3rd male  |    died    | 0.086564 | 0.319328 |  2.510823  |  418  | 1.371894 |  0.847870  |
# |   female   |  survived  | 0.122996 | 0.258976 |  2.267729  |  339  | 1.904511 |  0.727468  |
# |     -1     |    3rd     | 0.050076 | 0.158900 |  2.191819  |  208  | 1.460162 |  0.790875  |
# |     -1     |    died    | 0.020977 | 0.145149 |  1.376142  |  190  | 1.168931 |  0.722433  |
# |    3rd     |    died    | 0.068615 | 0.403361 |  1.496229  |  528  | 1.204977 |  0.744711  |
# |   -1 3rd   |    died    | 0.022498 | 0.120703 |  1.588999  |  158  | 1.229093 |  0.759615  |
# |  -1 died   |    3rd     | 0.042085 | 0.120703 |  2.721543  |  158  | 1.535313 |  0.831579  |
# +------------+------------+----------+----------+------------+-------+----------+------------+

```

**Remark:** Note that because of the specified min confidence, the number of association rules is "contained" --
a (much) larger number of rules would be produced with, say, `min-confidence=>0.2`.

---

## Implementation considerations

### UML diagram

Here is a UML diagram that shows package's structure:

![](./resources/class-diagram.png)

The
[PlantUML spec](./resources/class-diagram.puml)
and
[diagram](./resources/class-diagram.png)
were obtained with the CLI script `to-uml-spec` of the package "UML::Translators", [AAp6].

Here we get the [PlantUML spec](./resources/class-diagram.puml):

```
to-uml-spec ML::AssociationRuleLearning > ./resources/class-diagram.puml

```

```
#

```

Here get the [diagram](./resources/class-diagram.png):

```
to-uml-spec ML::AssociationRuleLearning | java -jar ~/PlantUML/plantuml-1.2022.5.jar -pipe > ./resources/class-diagram.png

```

```
#

```

**Remark:** Maybe it is a good idea to have an abstract class named, say,
`ML::AssociationRuleLearning::AbstractFinder` that is a parent of both
`ML::AssociationRuleLearning::Apriori` and `ML::AssociationRuleLearning::Eclat`,
but I have not found to be necessary. (At this point of development.)

### Eclat

We can say that Eclat uses a "vertical database representation" of the transactions.

Eclat is based on Raku's
[sets, bags, and mixes](https://docs.raku.org/language/setbagmix)
functionalities.

Eclat represents the transactions as a hash of sets:

* The keys of the hash are items
* The elements of the sets are transaction identifiers.

(In other words, for each item an inverse index is made.)

This representation allows for quick calculations of item combinations support.

### Apriori

Apriori uses the standard, horizontal database transactions representation.

We can say that Apriori:

* Generates candidates for item frequent sets using the routine
  [`combinations`](https://docs.raku.org/routine/combinations)
* Filters candidates by
  [Tries with frequencies](https://github.com/antononcube/Raku-ML-TriesWithFrequencies)
  creation and removal by threshold

Apriori is usually (much) slower than Eclat.
Historically, Apriori is the first ARL method, and its implementation in the package is didactic.

### Association rules

We can say that the association rule finding function is a general one, but that function
does require fast computation of confidence, lift, etc. Hence Eclat's transactions representation
is used.

Association rules finding with Apriori is the same as with Eclat.
The package function `assocition-rules` with the option setting `method=>'Apriori'`
simply sends frequent sets found with Apriori to the Eclat based association rule finding.

---

## References

### Articles

[Wk1] Wikipedia entry, ["Association Rule Learning"](https://en.wikipedia.org/wiki/Association_rule_learning).

[AA1] Anton Antonov,
["Movie genre associations"](https://mathematicaforprediction.wordpress.com/2013/10/06/movie-genre-associations/),
(2013),
[MathematicaForPrediction at WordPress](https://mathematicaforprediction.wordpress.com).

[AA2] Anton Antonov,
["Introduction to data wrangling with Raku"](https://rakuforprediction.wordpress.com/2021/12/31/introduction-to-data-wrangling-with-raku/),
(2021),
[RakuForPrediction at WordPress](https://rakuforprediction.wordpress.com).

### Packages

[AAp1] Anton Antonov,
[Implementation of the Apriori algorithm in Mathematica](https://github.com/antononcube/MathematicaForPrediction/blob/master/AprioriAlgorithm.m),
(2014-2016),
[MathematicaForPrediction at GitHub/antononcube](https://github.com/antononcube/MathematicaForPrediction/).

[AAp1a] Anton Antonov
[Implementation of the Apriori algorithm via Tries in Mathematica](https://github.com/antononcube/MathematicaForPrediction/blob/master/Misc/AprioriAlgorithmViaTries.m),
(2022),
[MathematicaForPrediction at GitHub/antononcube](https://github.com/antononcube/MathematicaForPrediction/).

[AAp2] Anton Antonov,
[Implementation of the Eclat algorithm in Mathematica](https://github.com/antononcube/MathematicaForPrediction/blob/master/EclatAlgorithm.m),
(2022),
[MathematicaForPrediction at GitHub/antononcube](https://github.com/antononcube/MathematicaForPrediction/).

[AAp3] Anton Antonov,
[Data::Generators Raku package](https://raku.land/cpan:ANTONOV/Data::Generators),
(2021),
[GitHub/antononcube](https://github.com/antononcube).

[AAp4] Anton Antonov,
[Data::Reshapers Raku package](https://raku.land/cpan:ANTONOV/Data::Reshapers),
(2021),
[GitHub/antononcube](https://github.com/antononcube).

[AAp5] Anton Antonov,
[Data::Summarizers Raku package](https://raku.land/cpan:ANTONOV/Data::Summarizers),
(2021),
[GitHub/antononcube](https://github.com/antononcube).

[AAp6] Anton Antonov,
[UML::Translators Raku package](https://raku.land/zef:antononcube/UML::Translators),
(2022),
[GitHub/antononcube](https://github.com/antononcube).

[AAp7] Anton Antonov,
[ML::TrieWithFrequencies Raku package](https://raku.land/cpan:ANTONOV/ML::TriesWithFrequencies),
(2021),
[GitHub/antononcube](https://github.com/antononcube).


## dist_cpan-FRITH-Math-Libgsl-BLAS.md
## Chunk 1 of 2
[![Build Status](https://travis-ci.org/frithnanth/raku-Math-Libgsl-BLAS.svg?branch=master)](https://travis-ci.org/frithnanth/raku-Math-Libgsl-BLAS)

# NAME

Math::Libgsl::BLAS - An interface to libgsl, the Gnu Scientific Library - BLAS (Basic Linear Algebra Subprograms).

# SYNOPSIS

```
use Math::Libgsl::Raw::BLAS :ALL;

use Math::Libgsl::BLAS;
use Math::Libgsl::BLAS::Num32;
use Math::Libgsl::BLAS::Complex32;
use Math::Libgsl::BLAS::Complex64;

```

# DESCRIPTION

Math::Libgsl::BLAS is an interface to the BLAS functions of the libgsl, the Gnu Scientific Library

This package provides both the low-level interface to the C library (Raw) and a more comfortable interface layer for the Raku programmer.

Throughout this package I used a naming convention corresponding to that of the C library, stripping the initial `gsl_blas_`.

The functions are divided in three levels:

* Level 1: vector operations
* Level 2: matrix-vector operations
* Level 3: matrix-matrix operations

The names of the functions specify the kind of operation, the matrix type, and the underlying data type. For more information please read the [C Library Documentation](C Library Documentation).

Since the original C library provided functions for four data types, so does this module. The Math::Libgsl::BLAS module provides functions that work on the default data type: num64. The functions working on num32 vector and matrices are in the Math::Libgsl::BLAS::Num32 module; those working on complex64 and complex32 are respectively in the Math::Libgsl::BLAS::Complex64 and Math::Libgsl::BLAS::Complex32 modules.

So for example this code will be executed using num32 data type variables:

```
use Math::Libgsl::Vector::Num32;
use Math::Libgsl::BLAS::Num32;

my $x = Math::Libgsl::Vector::Num32.new: 10;
$x.setall(.1);
my $y = Math::Libgsl::Vector::Num32.new: 10;
$y.setall(.2);
say sdsdot(.3, $x, $y); # output: 0.5

```

Here I'm following the order the functions are listed in the C Library Manual.

## Level 1

### sdsdot(Num() $α, Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Vector::Num32 $y where { $y.vector.size == $x.vector.size } --> Num)

This function computes the sum α + T(x)y, where T(x) is the transpose of x.

### sdot(Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Vector::Num32 $y where { $y.vector.size == $x.vector.size } --> Num)

### dsdot(Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Vector::Num32 $y where { $y.vector.size == $x.vector.size } --> Num)

### ddot(Math::Libgsl::Vector $x, Math::Libgsl::Vector $y where { $y.vector.size == $x.vector.size } --> Num)

### cdotu(Math::Libgsl::Vector::Complex32 $x, Math::Libgsl::Vector::Complex32 $y where { $y.vector.size == $x.vector.size } --> Complex)

### zdotu(Math::Libgsl::Vector::Complex64 $x, Math::Libgsl::Vector::Complex64 $y where { $y.vector.size == $x.vector.size } --> Complex)

These functions compute the scalar product T(x)y.

### cdotc(Math::Libgsl::Vector::Complex32 $x, Math::Libgsl::Vector::Complex32 $y where { $y.vector.size == $x.vector.size } --> Complex)

### zdotc(Math::Libgsl::Vector::Complex64 $x, Math::Libgsl::Vector::Complex64 $y where { $y.vector.size == $x.vector.size } --> Complex)

These functions compute the complex conjugate scalar product H(x)y.

### snrm2(Math::Libgsl::Vector::Num32 $x --> Num)

### dnrm2(Math::Libgsl::Vector $x --> Num)

### scnrm2(Math::Libgsl::Vector::Complex32 $x --> Num)

### dznrm2(Math::Libgsl::Vector::Complex64 $x --> Num)

These functions compute the Euclidean norm ||x||₂.

### sasum(Math::Libgsl::Vector::Num32 $x --> Num)

### dasum(Math::Libgsl::Vector $x --> Num)

### scasum(Math::Libgsl::Vector::Complex32 $x --> Num)

### dzasum(Math::Libgsl::Vector::Complex64 $x --> Num)

These functions compute the absolute sum Σ|xᵢ| of the elements of the vector x (or the sum of the magnitudes of the real and imaginary parts).

### isamax(Math::Libgsl::Vector::Num32 $x --> Int)

### idamax(Math::Libgsl::Vector $x --> Int)

### icamax(Math::Libgsl::Vector::Complex32 $x --> Int)

### izamax(Math::Libgsl::Vector::Complex64 $x --> Int)

These functions return the index of the largest element of the vector x. The largest element is determined by its absolute magnitude for real vectors and by the sum of the magnitudes of the real and imaginary parts Σ|R(xᵢ)| + |I(xᵢ)| for complex vectors. If the largest value occurs several times then the index of the first occurrence is returned.

### sswap(Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Vector::Num32 $y where { $y.vector.size == $x.vector.size } --> Int)

### dswap(Math::Libgsl::Vector $x, Math::Libgsl::Vector $y where { $y.vector.size == $x.vector.size } --> Int)

### cswap(Math::Libgsl::Vector::Complex32 $x, Math::Libgsl::Vector::Complex32 $y where { $y.vector.size == $x.vector.size } --> Int)

### zswap(Math::Libgsl::Vector::Complex64 $x, Math::Libgsl::Vector::Complex64 $y where { $y.vector.size == $x.vector.size } --> Int)

These functions exchange the elements of the vectors. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### scopy(Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Vector::Num32 $y where { $y.vector.size == $x.vector.size } --> Int)

### dcopy(Math::Libgsl::Vector $x, Math::Libgsl::Vector $y where { $y.vector.size == $x.vector.size } --> Int)

### ccopy(Math::Libgsl::Vector::Complex32 $x, Math::Libgsl::Vector::Complex32 $y where { $y.vector.size == $x.vector.size } --> Int)

### zcopy(Math::Libgsl::Vector::Complex64 $x, Math::Libgsl::Vector::Complex64 $y where { $y.vector.size == $x.vector.size } --> Int)

These functions copy the elements of the vector x into the vector y. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### saxpy(Num() $α, Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Vector::Num32 $y where { $y.vector.size == $x.vector.size } --> Int)

### daxpy(Num() $α, Math::Libgsl::Vector $x, Math::Libgsl::Vector $y where { $y.vector.size == $x.vector.size } --> Int)

### caxpy(Complex $α, Math::Libgsl::Vector::Complex32 $x, Math::Libgsl::Vector::Complex32 $y where { $y.vector.size == $x.vector.size } --> Int)

### zaxpy(Complex $α, Math::Libgsl::Vector::Complex64 $x, Math::Libgsl::Vector::Complex64 $y where { $y.vector.size == $x.vector.size } --> Int)

These functions compute the sum y = αx + y. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### sscal(Num() $α, Math::Libgsl::Vector::Num32 $x)

### dscal(Num() $α, Math::Libgsl::Vector $x)

### cscal(Complex $α, Math::Libgsl::Vector::Complex32 $x)

### zscal(Complex $α, Math::Libgsl::Vector::Complex64 $x)

### csscal(Num() $α, Math::Libgsl::Vector::Complex32 $x)

### zdscal(Num() $α, Math::Libgsl::Vector::Complex64 $x)

These functions rescale the vector x by α.

### srotg(Num() $a, Num() $b --> List)

### drotg(Num() $a, Num() $b --> List)

These functions compute a Givens rotation which zeroes the vector (a, b). They return the magnitude of the resulting vector and the coefficients (c, s) which zero the vector (a, b). In case of error a failure object is returned.

### srot(Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Vector::Num32 $y where { $y.vector.size == $x.vector.size }, Num() $c, Num() $s --> Int)

### drot(Math::Libgsl::Vector $x, Math::Libgsl::Vector $y where { $y.vector.size == $x.vector.size }, Num() $c, Num() $s --> Int)

These functions apply a Givens rotation (x ′ , y ′ ) = (cx + sy, −sx + cy) to the vectors x, y. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### srotmg(Num() $d1, Num() $d2, Num() $b1, Num() $b2 --> List)

### drotmg(Num() $d1, Num() $d2, Num() $b1, Num() $b2 --> List)

These functions compute a modified Givens transformation. They return a list of five elements (see the BLAS manual for an explanation). In case of error a failure object is returned.

### srotm(Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Vector::Num32 $y where { $y.vector.size == $x.vector.size }, @param where \*.elems == 5 --> Int)

### drotm(Math::Libgsl::Vector $x, Math::Libgsl::Vector $y where { $y.vector.size == $x.vector.size }, @param where \*.elems == 5 --> Int)

These functions apply a modified Givens transformation. These functions return GSL\_SUCCESS if successful, or one of the error codes (see the gsl-error enum in Math::Libgsl::Constants).

## Level 2

### sgemv(Int $TransA, Num() $α, Math::Libgsl::Matrix::Num32 $A, Math::Libgsl::Vector::Num32 $x, Num() $β, Math::Libgsl::Vector::Num32 $y --> Int)

### dgemv(Int $TransA, Num() $α, Math::Libgsl::Matrix $A, Math::Libgsl::Vector $x, Num() $β, Math::Libgsl::Vector $y --> Int)

### cgemv(Int $TransA, Complex $α, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Vector::Complex32 $x, Complex $β, Math::Libgsl::Vector::Complex32 $y --> Int)

### zgemv(Int $TransA, Complex $α, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Vector::Complex64 $x, Complex $β, Math::Libgsl::Vector::Complex64 $y --> Int)

These functions compute the matrix-vector product and sum y = αop(A)x + βy. "op" can be a no-op, a transpose, or a hermitian transpose (see the cblas-transpose enum in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### strmv(Int $Uplo, Int $TransA, Int $Diag, Math::Libgsl::Matrix::Num32 $A, Math::Libgsl::Vector::Num32 $x --> Int)

### dtrmv(Int $Uplo, Int $TransA, Int $Diag, Math::Libgsl::Matrix $A, Math::Libgsl::Vector $x --> Int)

### ctrmv(Int $Uplo, Int $TransA, Int $Diag, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Vector::Complex32 $x --> Int)

### ztrmv(Int $Uplo, Int $TransA, Int $Diag, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Vector::Complex64 $x --> Int)

These functions compute the matrix-vector product x = op(A)x for the triangular matrix A. "op" can be a no-op, a transpose, or a hermitian transpose (see the cblas-transpose enum in Math::Libgsl::Constants). When Uplo is CblasUpper then the upper triangle of A is used, and when Uplo is CblasLower then the lower triangle of A is used. If Diag is CblasNonUnit then the diagonal of the matrix is used, but if Diag is CblasUnit then the diagonal elements of the matrix A are taken as unity and are not referenced (see the cblas-uplo and cblas-diag enums in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### strsv(Int $Uplo, Int $TransA, Int $Diag, Math::Libgsl::Matrix::Num32 $A, Math::Libgsl::Vector::Num32 $x --> Int)

### dtrsv(Int $Uplo, Int $TransA, Int $Diag, Math::Libgsl::Matrix $A, Math::Libgsl::Vector $x --> Int)

### ctrsv(Int $Uplo, Int $TransA, Int $Diag, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Vector::Complex32 $x --> Int)

### ztrsv(Int $Uplo, Int $TransA, Int $Diag, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Vector::Complex64 $x --> Int)

These functions compute inv(op(A))x for x. "op" can be a no-op, a transpose, or a hermitian transpose (see the cblas-transpose enum in Math::Libgsl::Constants). When Uplo is CblasUpper then the upper triangle of A is used, and when Uplo is CblasLower then the lower triangle of A is used. If Diag is CblasNonUnit then the diagonal of the matrix is used, but if Diag is CblasUnit then the diagonal elements of the matrix A are taken as unity and are not referenced (see the cblas-uplo and cblas-diag enums in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### ssymv(Int $Uplo, Num() $α, Math::Libgsl::Matrix::Num32 $A, Math::Libgsl::Vector::Num32 $x, Num() $β, Math::Libgsl::Vector::Num32 $y --> Int)

### dsymv(Int $Uplo, Num() $α, Math::Libgsl::Matrix $A, Math::Libgsl::Vector $x, Num() $β, Math::Libgsl::Vector $y --> Int)

These functions compute the matrix-vector product and sum y = αAx + βy for the symmetric matrix A. Since the matrix A is symmetric only its upper half or lower half need to be stored. When Uplo is CblasUpper then the upper triangle and diagonal of A are used, and when Uplo is CblasLower then the lower triangle and diagonal of A are used (see the cblas-uplo enum in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### chemv(Int $Uplo, Complex $α, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Vector::Complex32 $x, Complex $β, Math::Libgsl::Vector::Complex32 $y --> Int)

### zhemv(Int $Uplo, Complex $α, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Vector::Complex64 $x, Complex $β, Math::Libgsl::Vector::Complex64 $y --> Int)

These functions compute the matrix-vector product and sum y = αAx + βy for the hermitian matrix A. Since the matrix A is hermitian only its upper half or lower half need to be stored. When Uplo is CblasUpper then the upper triangle and diagonal of A are used, and when Uplo is CblasLower then the lower triangle and diagonal of A are used (see the cblas-uplo enum in Math::Libgsl::Constants). The imaginary elements of the diagonal are automatically assumed to be zero and are not referenced. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### sger(Num() $α, Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Vector::Num32 $y, Math::Libgsl::Matrix::Num32 $A --> Int)

### dger(Num() $α, Math::Libgsl::Vector $x, Math::Libgsl::Vector $y, Math::Libgsl::Matrix $A --> Int)

### cgeru(Complex $α, Math::Libgsl::Vector::Complex32 $x, Math::Libgsl::Vector::Complex32 $y, Math::Libgsl::Matrix::Complex32 $A --> Int)

### zgeru(Complex $α, Math::Libgsl::Vector::Complex64 $x, Math::Libgsl::Vector::Complex64 $y, Math::Libgsl::Matrix::Complex64 $A --> Int)

These functions compute the rank-1 update A = αxy T + A of the matrix A. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### cgerc(Complex $α, Math::Libgsl::Vector::Complex32 $x, Math::Libgsl::Vector::Complex32 $y, Math::Libgsl::Matrix::Complex32 $A --> Int)

### zgerc(Complex $α, Math::Libgsl::Vector::Complex64 $x, Math::Libgsl::Vector::Complex64 $y, Math::Libgsl::Matrix::Complex64 $A --> Int)

These functions compute the conjugate rank-1 update A = αxH(y) + A of the matrix A. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### ssyr(Int $Uplo, Num() $α, Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Matrix::Num32 $A --> Int)

### dsyr(Int $Uplo, Num() $α, Math::Libgsl::Vector $x, Math::Libgsl::Matrix $A --> Int)

These functions compute the symmetric rank-1 update A = αxT(x) + A of the symmetric matrix A. Since the matrix A is symmetric only its upper half or lower half need to be stored. When Uplo is CblasUpper then the upper triangle and diagonal of A are used, and when Uplo is CblasLower then the lower triangle and diagonal of A are used (see the cblas-uplo enum in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### cher(Int $Uplo, num32 $α, Math::Libgsl::Vector::Complex32 $x, Math::Libgsl::Matrix::Complex32 $A --> Int)

### zher(Int $Uplo, num64 $α, Math::Libgsl::Vector::Complex64 $x, Math::Libgsl::Matrix::Complex64 $A --> Int)

These functions compute the hermitian rank-1 update A = αxx H + A of the hermitian matrix A. Since the matrix A is hermitian only its upper half or lower half need to be stored. When Uplo is CblasUpper then the upper triangle and diagonal of A are used, and when Uplo is CblasLower then the lower triangle and diagonal of A are used (see the cblas-uplo enum in Math::Libgsl::Constants). The imaginary elements of the diagonal are automatically set to zero. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### ssyr2(Int $Uplo, Num() $α, Math::Libgsl::Vector::Num32 $x, Math::Libgsl::Vector::Num32 $y, Math::Libgsl::Matrix::Num32 $A --> Int)

### dsyr2(Int $Uplo, Num() $α, Math::Libgsl::Vector $x, Math::Libgsl::Vector $y, Math::Libgsl::Matrix $A --> Int)

These functions compute the symmetric rank-2 update A = αxT(y) + αyT(x) + A of the symmetric matrix A. Since the matrix A is symmetric only its upper half or lower half need to be stored. When Uplo is CblasUpper then the upper triangle and diagonal of A are used, and when Uplo is CblasLower then the lower triangle and diagonal of A are used (see the cblas-uplo enum in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### cher2(Int $Uplo, Complex $α, Math::Libgsl::Vector::Complex32 $x, Math::Libgsl::Vector::Complex32 $y, Math::Libgsl::Matrix::Complex32 $A --> Int)

### zher2(Int $Uplo, Complex $α, Math::Libgsl::Vector::Complex64 $x, Math::Libgsl::Vector::Complex64 $y, Math::Libgsl::Matrix::Complex64 $A --> Int)

These functions compute the hermitian rank-2 update A = αxH(y) + α \* yH(x) + A of the hermitian matrix A. Since the matrix A is hermitian only its upper half or lower half need to be stored. When Uplo is CblasUpper then the upper triangle and diagonal of A are used, and when Uplo is CblasLower then the lower triangle and diagonal of A are used (see the cblas-uplo enum in Math::Libgsl::Constants). The imaginary elements of the diagonal are automatically set to zero. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

## Level 3

### sgemm(Int $TransA, Int $TransB, Num() $α, Math::Libgsl::Matrix::Num32 $A, Math::Libgsl::Matrix::Num32 $B, Num() $β, Math::Libgsl::Matrix::Num32 $C --> Int)

### dgemm(Int $TransA, Int $TransB, Num() $α, Math::Libgsl::Matrix $A, Math::Libgsl::Matrix $B, Num() $β, Math::Libgsl::Matrix $C --> Int)

### cgemm(Int $TransA, Int $TransB, Complex $α, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Matrix::Complex32 $B, Complex $β, Math::Libgsl::Matrix::Complex32 $C --> Int)

### zgemm(Int $TransA, Int $TransB, Complex $α, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Matrix::Complex64 $B, Complex $β, Math::Libgsl::Matrix::Complex64 $C --> Int)

These functions compute the matrix-matrix product and sum C = αop(A)op(B) + βC where op(A) = A, T(A), H(A) for TransA = CblasNoTrans, CblasTrans, CblasConjTrans and similarly for the parameter TransB (see the cblas-transpose enum in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### ssymm(Int $Side, Int $Uplo, Num() $α, Math::Libgsl::Matrix::Num32 $A, Math::Libgsl::Matrix::Num32 $B, Num() $β, Math::Libgsl::Matrix::Num32 $C --> Int)

### dsymm(Int $Side, Int $Uplo, Num() $α, Math::Libgsl::Matrix $A, Math::Libgsl::Matrix $B, Num() $β, Math::Libgsl::Matrix $C --> Int)

### csymm(Int $Side, Int $Uplo, Complex $α, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Matrix::Complex32 $B, Complex $β, Math::Libgsl::Matrix::Complex32 $C --> Int)

### zsymm(Int $Side, Int $Uplo, Complex $α, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Matrix::Complex64 $B, Complex $β, Math::Libgsl::Matrix::Complex64 $C --> Int)

These functions compute the matrix-matrix product and sum C = αAB + βC for Side is CblasLeft and C = αBA + βC for Side is CblasRight, where the matrix A is symmetric (see the cblas-side enum in Math::Libgsl::Constants). When Uplo is CblasUpper then the upper triangle and diagonal of A are used, and when Uplo is CblasLower then the lower triangle and diagonal of A are used (see the cblas-uplo enum in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### chemm(Int $Side, Int $Uplo, Complex $α, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Matrix::Complex32 $B, Complex $β, Math::Libgsl::Matrix::Complex32 $C --> Int)

### zhemm(Int $Side, Int $Uplo, Complex $α, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Matrix::Complex64 $B, Complex $β, Math::Libgsl::Matrix::Complex64 $C --> Int)

These functions compute the matrix-matrix product and sum C = αAB + βC for Side is CblasLeft and C = αBA + βC for Side is CblasRight, where the matrix A is hermitian (see the cblas-side enum in Math::Libgsl::Constants). When Uplo is CblasUpper then the upper triangle and diagonal of A are used, and when Uplo is CblasLower then the lower triangle and diagonal of A are used (see the cblas-uplo enum in Math::Libgsl::Constants). The imaginary elements of the diagonal are automatically set to zero. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### strmm(Int $Side, Int $Uplo, Int $TransA, Int $Diag, Num() $α, Math::Libgsl::Matrix::Num32 $A, Math::Libgsl::Matrix::Num32 $B --> Int)

### dtrmm(Int $Side, Int $Uplo, Int $TransA, Int $Diag, Num() $α, Math::Libgsl::Matrix $A, Math::Libgsl::Matrix $B --> Int)

### ctrmm(Int $Side, Int $Uplo, Int $TransA, Int $Diag, Complex $α, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Matrix::Complex32 $B --> Int)

### ztrmm(Int $Side, Int $Uplo, Int $TransA, Int $Diag, Complex $α, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Matrix::Complex64 $B --> Int)

These functions compute the matrix-matrix product B = αop(A)B for Side is CblasLeft and B = αBop(A) for Side is CblasRight (see the cblas-side enum in Math::Libgsl::Constants). The matrix A is triangular and op(A) = A, T(A), H(A) for TransA = CblasNoTrans, CblasTrans, CblasConjTrans (see the cblas-transpose enum in Math::Libgsl::Constants). When Uplo is CblasUpper then the upper triangle of A is used, and when Uplo is CblasLower then the lower triangle of A is used (see the cblas-uplo enum in Math::Libgsl::Constants). If Diag is CblasNonUnit then the diagonal of A is used, but if Diag is CblasUnit then the diagonal elements of the matrix A are taken as unity and are not referenced (see cblas-diag enums in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### strsm(Int $Side, Int $Uplo, Int $TransA, Int $Diag, Num() $α, Math::Libgsl::Matrix::Num32 $A, Math::Libgsl::Matrix::Num32 $B --> Int)

### dtrsm(Int $Side, Int $Uplo, Int $TransA, Int $Diag, Num() $α, Math::Libgsl::Matrix $A, Math::Libgsl::Matrix $B --> Int)

### ctrsm(Int $Side, Int $Uplo, Int $TransA, Int $Diag, Complex $α, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Matrix::Complex32 $B --> Int)

### ztrsm(Int $Side, Int $Uplo, Int $TransA, Int $Diag, Complex $α, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Matrix::Complex64 $B --> Int)

These functions compute the inverse-matrix matrix product B = αop(inv(A))B for Side is CblasLeft and B = αBop(inv(A)) for Side is CblasRight (see the cblas-side enum in Math::Libgsl::Constants). The matrix A is triangular and op(A) = A, T(A), H(A) for TransA = CblasNoTrans, CblasTrans, CblasConjTrans (see the cblas-transpose enum in Math::Libgsl::Constants). When Uplo is CblasUpper then the upper triangle of A is used, and when Uplo is CblasLower then the lower triangle of A is used (see the cblas-uplo enum in Math::Libgsl::Constants). If Diag is CblasNonUnit then the diagonal of A is used, but if Diag is CblasUnit then the diagonal elements of the matrix A are taken as unity and are not referenced (see cblas-diag enums in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### ssyrk(Int $Uplo, Int $TransA, Num() $α, Math::Libgsl::Matrix::Num32 $A, Num() $β, Math::Libgsl::Matrix::Num32 $C --> Int)

### dsyrk(Int $Uplo, Int $TransA, Num() $α, Math::Libgsl::Matrix $A, Num() $β, Math::Libgsl::Matrix $C --> Int)

### csyrk(Int $Uplo, Int $TransA, Complex $α, Math::Libgsl::Matrix::Complex32 $A, Complex $β, Math::Libgsl::Matrix::Complex32 $C --> Int)

### zsyrk(Int $Uplo, Int $TransA, Complex $α, Math::Libgsl::Matrix::Complex64 $A, Complex $β, Math::Libgsl::Matrix::Complex64 $C --> Int)

These functions compute a rank-k update of the symmetric matrix C, C = αAT(A) + βC when Trans is CblasNoTrans and C = αT(A)A + βC when Trans is CblasTrans (see the cblas-transpose enum in Math::Libgsl::Constants). Since the matrix C is symmetric only its upper half or lower half need to be stored. When Uplo is CblasUpper then the upper triangle and diagonal of C are used, and when Uplo is CblasLower then the lower triangle and diagonal of C are used (see the cblas-uplo enum in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### cherk(Int $Uplo, Int $TransA, num32 $α, Math::Libgsl::Matrix::Complex32 $A, num32 $β, Math::Libgsl::Matrix::Complex32 $C --> Int)

### zherk(Int $Uplo, Int $TransA, num64 $α, Math::Libgsl::Matrix::Complex64 $A, num64 $β, Math::Libgsl::Matrix::Complex64 $C --> Int)

These functions compute a rank-k update of the hermitian matrix C, C = αAH(A) + βC when Trans is CblasNoTrans and C = αH(A)A + βC when Trans is CblasConjTrans (see the cblas-transpose enum in Math::Libgsl::Constants). Since the matrix C is hermitian only its upper half or lower half need to be stored. When Uplo is CblasUpper then the upper triangle and diagonal of C are used, and when Uplo is CblasLower then the lower triangle and diagonal of C are used (see the cblas-uplo enum in Math::Libgsl::Constants). The imaginary elements of the diagonal are automatically set to zero. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### ssyr2k(Int $Uplo, Int $TransA, Num() $α, Math::Libgsl::Matrix::Num32 $A, Math::Libgsl::Matrix::Num32 $B, Num() $


## dist_cpan-FRITH-Math-Libgsl-BLAS.md
## Chunk 2 of 2
β, Math::Libgsl::Matrix::Num32 $C --> Int)

### dsyr2k(Int $Uplo, Int $TransA, Num() $α, Math::Libgsl::Matrix $A, Math::Libgsl::Matrix $B, Num() $β, Math::Libgsl::Matrix $C --> Int)

### csyr2k(Int $Uplo, Int $TransA, Complex $α, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Matrix::Complex32 $B, Complex $β, Math::Libgsl::Matrix::Complex32 $C --> Int)

### zsyr2k(Int $Uplo, Int $TransA, Complex $α, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Matrix::Complex64 $B, Complex $β, Math::Libgsl::Matrix::Complex64 $C --> Int)

These functions compute a rank-2k update of the symmetric matrix C, C = αAT(B) + αBT(A) + βC when Trans is CblasNoTrans and C = αT(A)B + αT(B)A + βC when Trans is CblasTrans (see the cblas-transpose enum in Math::Libgsl::Constants). Since the matrix C is symmetric only its upper half or lower half need to be stored. When Uplo is CblasUpper then the upper triangle and diagonal of C are used, and when Uplo is CblasLower then the lower triangle and diagonal of C are used (see the cblas-uplo enum in Math::Libgsl::Constants). These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

### cher2k(Int $Uplo, Int $TransA, Complex $α, Math::Libgsl::Matrix::Complex32 $A, Math::Libgsl::Matrix::Complex32 $B, num32 $β, Math::Libgsl::Matrix::Complex32 $C --> Int)

### zher2k(Int $Uplo, Int $TransA, Complex $α, Math::Libgsl::Matrix::Complex64 $A, Math::Libgsl::Matrix::Complex64 $B, num64 $β, Math::Libgsl::Matrix::Complex64 $C --> Int)

These functions compute a rank-2k update of the hermitian matrix C, C = αAH(B) + conj(α)BH(A) + βC when Trans is CblasNoTrans and C = αH(A)B + conj(α)H(B)A + βC when Trans is CblasConjTrans (see the cblas-transpose enum in Math::Libgsl::Constants). Since the matrix C is hermitian only its upper half or lower half need to be stored. When Uplo is CblasUpper then the upper triangle and diagonal of C are used, and when Uplo is CblasLower then the lower triangle and diagonal of C are used (see the cblas-uplo enum in Math::Libgsl::Constants). The imaginary elements of the diagonal are automatically set to zero. These functions return GSL\_SUCCESS if successful, or one of the error codes listed in Math::Libgsl::Constants::gsl-error.

# C Library Documentation

For more details on libgsl see <https://www.gnu.org/software/gsl/>.

The excellent C Library manual is available here <https://www.gnu.org/software/gsl/doc/html/index.html>, or here <https://www.gnu.org/software/gsl/doc/latex/gsl-ref.pdf> in PDF format.

The BLAS C Library manual is available here <https://software.intel.com/en-us/mkl-developer-reference-c-blas-routines> and here <http://netlib.org/blas/#_level_1>.

# Prerequisites

This module requires the libgsl library to be installed. Please follow the instructions below based on your platform:

## Debian Linux

```
sudo apt install libgsl23 libgsl-dev libgslcblas0

```

That command will install libgslcblas0 as well, since it's used by the GSL.

## Ubuntu 18.04

libgsl23 and libgslcblas0 have a missing symbol on Ubuntu 18.04. I solved the issue installing the Debian Buster version of those three libraries:

* <http://http.us.debian.org/debian/pool/main/g/gsl/libgslcblas0_2.5+dfsg-6_amd64.deb>
* <http://http.us.debian.org/debian/pool/main/g/gsl/libgsl23_2.5+dfsg-6_amd64.deb>
* <http://http.us.debian.org/debian/pool/main/g/gsl/libgsl-dev_2.5+dfsg-6_amd64.deb>

# Installation

To install it using zef (a module management tool):

```
$ zef install Math::Libgsl::BLAS

```

# AUTHOR

Fernando Santagata [nando.santagata@gmail.com](mailto:nando.santagata@gmail.com)

# COPYRIGHT AND LICENSE

Copyright 2020 Fernando Santagata

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


## dist_cpan-SAMGWISE-Seq-PreFetch.md
# NAME

Seq::PreFetch - Asynchronously pre-fetch the next item of a Seq

# SYNOPSIS

```
use Seq::PreFetch;

sub slow-and-lazy( --> Seq) {
  gather for 1..* {
    # a time expensive option... like sleep
    sleep 0.5;
    .take
  }
}

my $moment = now;
for slow-and-lazy.&pre-fetch {
  .say;
  say "Delta: { now - $moment }";
  $moment = now;
  sleep 1;
}

```

# DESCRIPTION

Seq::PreFetch asynchronously pre-fetches the next item of a Seq before you pull from the Seq. It provides the sub pre-fetch which wraps a Seq with a pre-fetching Seq.

This pattern allows you to consume one value from a Seq and begin concurrently calculating the next value of a Seq ready for the next time you need a value. Time efficiency gains can be made for operations where the time cost of a consuming loop is greater than the cost of starting a thread to pre-fetch.

As demonstrated in the synopsis example, The two operations do not block so the longer sleep in the loop defines the duration after the first iteration.

# AUTHOR

Sam Gillespie [samgwise@gmail.com](mailto:samgwise@gmail.com)

# COPYRIGHT AND LICENSE

Copyright 2017 Sam Gillespie

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


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

# NAME

Test::Stream - Stream test events

# SYNOPSIS

```
use Test::Stream;

```

# DESCRIPTION

This is a prototype of an event-based test framework. The goal is to produce an underlying set of modules that can be shared by all Test modules in the Raku ecosystem. Building this on top of an abstract test event system makes integrating different modules much easier. It also makes testing your test modules *much* easier, and allows for output formats besides TAP.

# AUTHOR

Dave Rolsky

# COPYRIGHT AND LICENSE

Copyright 2016 Dave Rolsky

Copyright 2020 - 2024 Raku Community

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


## dist_zef-jonathanstowe-Staticish.md
# Staticish

Make a singleton class that wraps the methods so they appear like class methods

![Build Status](https://github.com/jonathanstowe/Staticish/workflows/CI/badge.svg)

## Synopsis

```
use Staticish;

class Foo is Static {
    has Str $.bar is rw;
}

Foo.bar = "There you go";
say Foo.bar; # > "There you go";

```

## Description

This provides a mechanism whereby a class can be treated as a "singleton"
and all of its methods wrapped such that if they are called as "class"
or "static" methods they will actually be called on the single instance.
It does this by applying a role to the class itself which provides a
constructor "new()" that will always return the same instance of the
object, and by applying a role to the classes Meta class which over-rides
the "add\_method" method in order to wrap the programmer supplied methods
such that if the method is called on the type object (i.e. as a class
method) then the single instance will be obtained and the method will
be called with that as the invocant.

This might be useful for a class such as a configuration parser or
logger where a single set of parameters will be used globally within an
application and it doesn't make sense to pass a single object around.

It may not deal with every possible use case properly, but it largely
does what I need it to. Suggestions, patches etc are welcome.

## Installation

Assuming you have a working Rakudo installation you should be able to install this with *zef* :

```
# From the source directory

zef install .

# Remote installation

zef install Staticish

```

## Support

This has never worked quite as well as I'd hoped when pre-compiled into another module as it
flies too close to the wind of what will work. If you find you hit a problem with it then you
should try adding `no precompilation;` to your module before the `use Staticish;`.

Suggestions/patches are welcomed via [github](https://github.com/jonathanstowe/Staticish/issues)

## Licence

This is free software.

Please see the <LICENCE> file in the distribution

© Jonathan Stowe 2015 - 2021


## name.md
name

Combined from primary sources listed below.

# [In role Metamodel::Naming](#___top "go to top of document")[§](#(role_Metamodel::Naming)_method_name "direct link")

See primary documentation
[in context](/type/Metamodel/Naming#method_name)
for **method name**.

```raku
method name($type)
```

Returns the name of the metaobject, if any.

```raku
say 42.^name;       # OUTPUT: «Int␤»
```

# [In X::Attribute::Package](#___top "go to top of document")[§](#(X::Attribute::Package)_method_name "direct link")

See primary documentation
[in context](/type/X/Attribute/Package#method_name)
for **method name**.

```raku
method name(--> Str:D)
```

Returns the name of the attribute that triggered this error.

# [In X::IO::Symlink](#___top "go to top of document")[§](#(X::IO::Symlink)_method_name "direct link")

See primary documentation
[in context](/type/X/IO/Symlink#method_name)
for **method name**.

Returns the path that [symlink](/routine/symlink) failed to create.

# [In Thread](#___top "go to top of document")[§](#(Thread)_method_name "direct link")

See primary documentation
[in context](/type/Thread#method_name)
for **method name**.

```raku
method name(Thread:D: --> Str:D)
```

Returns the user defined string, which can optionally be set during object creation in order to identify the `Thread`, or `'<anon>'` if no such string was specified.

```raku
my $t1 = Thread.new(code => { for 1..5 -> $v { say $v }});
my $t2 = Thread.new(code => { for 1..5 -> $v { say $v }}, name => 'my thread');

say $t1.name;                 # OUTPUT: «<anon>␤»
say $t2.name;                 # OUTPUT: «my thread␤»
```

# [In role Encoding](#___top "go to top of document")[§](#(role_Encoding)_method_name "direct link")

See primary documentation
[in context](/type/Encoding#method_name)
for **method name**.

```raku
method name(--> Str)
```

Abstract method that would return the primary name of the encoding.

# [In Parameter](#___top "go to top of document")[§](#(Parameter)_method_name "direct link")

See primary documentation
[in context](/type/Parameter#method_name)
for **method name**.

```raku
method name(Parameter:D: --> Str:D)
```

Returns the parameter name, which includes all [sigils](/language/variables#Sigils) and [twigils](/language/variables#Twigils). This name is used internally when applied to code, or in a declaration to determine the declared the name. This name is not necessarily usable by a caller – if it is, it will also appear as an [alias](#method_named_names). Often, the name will be chosen descriptively as a form of self-documentation.

If the parameter is anonymous, an empty string will be returned.

**Note:** Before Rakudo version 2020.08 the return value for an anonymous parameter was [`Nil`](/type/Nil).

```raku
my Signature $sig = :(Str $x, Bool);
say $sig.params[0].name;                 # OUTPUT: «$x␤»
say $sig.params[1].name;                 # OUTPUT: «␤»

```

# [In X::Dynamic::NotFound](#___top "go to top of document")[§](#(X::Dynamic::NotFound)_method_name "direct link")

See primary documentation
[in context](/type/X/Dynamic/NotFound#method_name)
for **method name**.

```raku
method name(--> Str:D)
```

Returns the name of the variable that has not been found.

# [In Metamodel::DefiniteHOW](#___top "go to top of document")[§](#(Metamodel::DefiniteHOW)_method_name "direct link")

See primary documentation
[in context](/type/Metamodel/DefiniteHOW#method_name)
for **method name**.

```raku
method name($definite_type)
```

Returns the name of a definite type.

# [In Scalar](#___top "go to top of document")[§](#(Scalar)_method_name "direct link")

See primary documentation
[in context](/type/Scalar#method_name)
for **method name**.

```raku
method name(Scalar:D: --> Str)
```

Returns the name associated with the container.

Example:

```raku
my $x = 42;
say $x.VAR.name;                # OUTPUT: «$x␤»
```

# [In Label](#___top "go to top of document")[§](#(Label)_method_name "direct link")

See primary documentation
[in context](/type/Label#method_name)
for **method name**.

Not terribly useful, returns the name of the defined label:

```raku
A: while True {
  say A.name; # OUTPUT: «A␤»
  last A;
}
```

# [In X::Bind::NativeType](#___top "go to top of document")[§](#(X::Bind::NativeType)_method_name "direct link")

See primary documentation
[in context](/type/X/Bind/NativeType#method_name)
for **method name**.

```raku
method name(--> Str:D)
```

Returns the name of the variable.

# [In Variable](#___top "go to top of document")[§](#(Variable)_method_name "direct link")

See primary documentation
[in context](/type/Variable#method_name)
for **method name**.

```raku
method name(Variable:D: str)
```

Returns the name of the variable, including the sigil.

# [In Attribute](#___top "go to top of document")[§](#(Attribute)_method_name "direct link")

See primary documentation
[in context](/type/Attribute#method_name)
for **method name**.

```raku
method name(Attribute:D: --> Str:D)
```

Returns the name of the attribute. Note that this is always the private name, so if an attribute is declared as `has $.a`, the name returned is `$!a`.

```raku
class Foo {
    has @!bar;
}
my $a = Foo.^attributes(:local)[0];
say $a.name;            # OUTPUT: «@!bar␤»
```

# [In X::Attribute::NoPackage](#___top "go to top of document")[§](#(X::Attribute::NoPackage)_method_name "direct link")

See primary documentation
[in context](/type/X/Attribute/NoPackage#method_name)
for **method name**.

```raku
method name(--> Str:D)
```

Returns the name of the attribute

# [In Encoding::Registry](#___top "go to top of document")[§](#(Encoding::Registry)_method_name "direct link")

See primary documentation
[in context](/type/Encoding/Registry#method_name)
for **method name**.

```raku
method register(Encoding $enc --> Nil)
```

Register a new [`Encoding`](/type/Encoding).

# [In role Systemic](#___top "go to top of document")[§](#(role_Systemic)_method_name "direct link")

See primary documentation
[in context](/type/Systemic#method_name)
for **method name**.

Instance method returning the name of the object.

# [In X::IO::Link](#___top "go to top of document")[§](#(X::IO::Link)_method_name "direct link")

See primary documentation
[in context](/type/X/IO/Link#method_name)
for **method name**.

Returns the name of the link that could not be created.

# [In Pod::Block::Named](#___top "go to top of document")[§](#(Pod::Block::Named)_method_name "direct link")

See primary documentation
[in context](/type/Pod/Block/Named#method_name)
for **method name**.

```raku
method name(--> Str:D)
```

Returns the name of the block.

# [In ForeignCode](#___top "go to top of document")[§](#(ForeignCode)_method_name "direct link")

See primary documentation
[in context](/type/ForeignCode#method_name)
for **method name**.

```raku
method name()
```

Returns the name of the enclosed code, or `<anon>` if it has not received any.

# [In X::Attribute::Required](#___top "go to top of document")[§](#(X::Attribute::Required)_method_name "direct link")

See primary documentation
[in context](/type/X/Attribute/Required#method_name)
for **method name**.

```raku
method name(--> Str:D)
```

Returns the name of the attribute.

# [In Routine](#___top "go to top of document")[§](#(Routine)_method_name "direct link")

See primary documentation
[in context](/type/Routine#method_name)
for **method name**.

```raku
method name(Routine:D: --> Str:D)
```

Returns the name of the sub or method.

# [In X::Signature::NameClash](#___top "go to top of document")[§](#(X::Signature::NameClash)_method_name "direct link")

See primary documentation
[in context](/type/X/Signature/NameClash#method_name)
for **method name**.

```raku
method name(--> Str:D)
```

Returns the name that was used for more than one parameter.


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

# NAME

MacOS::NativeLib - Make native libs reachable on MacOS

# SYNOPSIS

```
use MacOS::NativeLib 'gd';  # make all versions of GD libraries accessible
use GD::Raw;                # load raw GD support

```

# DESCRIPTION

MacOS has built-in security features that disallow loading native libraries unless they are in a trusted location, or if they are symlinked from a trusted location.

The most common way to install native libraries on MacOS is by using `HomeBrew` with the `brew install` command. The location at which these libraries are installed, are however **NOT** trusted by MacOS.

This module allows one to specify one or more library names that should be made reachable in the `use` statement. A symlink will then be installed if there is none already.

Library names can be specified with or without the "lib" prefix, so `"gd"` and `"libgd"` would produce the same result. By default, **all** versions of a native library will be made available. You can limit to a specific version by specifying a more specific name, e.g. `"gd.3"` to only make version **3** of the GD library available.

You can have all libraries installed by HomeBrew linked automatically by specifying `"*"` or `*` (aka `Whatever`), although this may not be a wise decision from a security point of view.

If this module is loaded on any OS other than MacOS, it is simply a no-op.

Any errors will be shown on STDERR, but will **NOT** interrupt the further execution, so that any module actually depending on the reachability of a native library can use its own checks and error reporting.

# AS AN OPTIONAL DEPENDENCY

If a module author does not want to create a hard dependency on this module, it is quite easy to make it an optional dependency in the code, by wrapping the `use` statement in a `try` / `EVAL` combo:

```
try 'use MacOS::NativeLib <gd>'.EVAL;

```

# SCRIPTS

## ensure-symlink-for

```
$ ensure-symlink-for gd

```

This module also installs a command-line interface called `ensure-symlink-for`. It takes the same arguments as in the `use` statement, and will install the necessary symlinks if they did not exist yet.

# AUTHOR

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

Source can be located at: <https://github.com/lizmat/MacOS-NativeLib> . 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 2024, 2025 Elizabeth Mattijsen

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


## dist_cpan-FCO-RedFactory.md
[![Actions Status](https://github.com/FCO/RedFactory/workflows/test/badge.svg)](https://github.com/FCO/RedFactory/actions)

# NAME

RedFactory - A factory for testing code using Red

# SYNOPSIS

```
# Your DB schema ---------------------------------------------------------
use Red;

model Post {...}

model Person {
   has UInt    $.id          is serial;
   has Str     $.first-name  is column;
   has Str     $.last-name   is column;
   has Str     $.email       is column;
   has Instant $.disabled-at is column{ :nullable };
   has Post    @.posts       is relationship(*.author-id, :model(Post));
}

model Post {
    has UInt    $.id         is serial;
    has Str     $.title      is column;
    has Str     $.body       is column;
    has UInt    $!author-id  is referencing(*.id, :model(Person));
    has Person  $.author     is relationship(*.author-id, :model(Person));
    has Instant $.created-at is column = now;
}

# Your factory configuration ---------------------------------------------
use RedFactory;

factory "person", :model(Person), {

   .first-name = "john";
   .last-name  = "doe";
   .email      = -> $_, :$number = .counter-by-model {
     "{ .first-name }{ $number }@domain.com"
   }

   .posts      = -> :$num-of-posts = 0 {
     factory-args $num-of-posts, "post"
   }

   trait "disabled", {
      .disabled-at = now
   }
}

factory "post", :model(Post), {

    .title = {
        "Post title { .counter-by-model }"
    }
    .body  = -> $_, :$title-repetition = 3 {
        (.title ~ "\n") x $title-repetition
    }
}

# Testing your imaginary controller helper -------------------------------
use Test;

my $*RED-DB = factory-db;

my &get-recent-author's-posts'-titles =
    get-controller's-help("get-recent-author's-posts'-titles");

# Create the needed person with posts
my $author = factory-create "person", :PARS{ :10num-of-posts };

my @posts = get-recent-author's-posts'-titles $author.id, 3;

is-deeply @posts, ["Post title 10", "Post title 9", "Post title 8"];

```

# DESCRIPTION

RedFactory is a easier way of testing code that uses Red

# AUTHOR

```
<fernandocorrea@gmail.com>

```

# COPYRIGHT AND LICENSE

Copyright 2021

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


## dist_github-gfldex-META6-bin.md
# META6::bin

[![Build Status](https://travis-ci.org/gfldex/raku-meta6-bin.svg?branch=master)](https://travis-ci.org/gfldex/raku-meta6-bin)

Create and check META6.json files and module skeletons.

Depends on `git` and `curl` in `$PATH` and got a timeout of 60s for each call
to both. Those are used to setup a git and github repo.

Module skeletons include basic directories, `META6.json`, `t/meta.t`,
`.travis.yml` and a `README.md`. The latter includes a link to
[travis-ci](https://travis-ci.org/).

# SYNOPSIS

```
meta6 --create --name=<project-name-here> --force
meta6 --check
meta6 --create-cfg-dir --force
meta6 --new-module=<Module::Name::Here> --force --skip-git --skip-github
meta6 --fork-module=<Module::Name::Here>
meta6 --add-dep=<Module::Name::Here:ver<1.2.3>>
meta6 --pull-request
meta6 --issues --module=<Optional::Module::Name> --closed --one-line --url --deps --verbose
meta6 --set-license="license name or URL"
meta6 --add-author="Another T. Author <another.t.author@somewhere.place>"
meta6 --release --version=1.2.3

```

## Use as a Module

```
use v6.c;

use META6::bin :HELPER;

&META6::bin::try-to-fetch-url.wrap({
    say "checking URL: ⟨$_⟩";
    callsame;
});

META6::bin::MAIN(:check);

```

# General Options

```
--meta6-file=<path-to-META6.json> # defaults to ./META6.json

```

# Create Options

```
--name
--description
--version # defaults to 0.0.1
--perl # defaults to 6.c
--author # defaults to user/name from ~/.gitconfig
--auth # defaults to credentials/username from ~/.gitconfig

```

# New Module Options

```
--new-module=<Module::Name::Here>
--description="some text" # added both META6.json and README.md
--base-dir # the $*CWD for all local file operations

```

Will create a new module project in a new directory with a name prefixed with
`create.prefix` (default `raku-`), setup git, push it to github (See Github
below). The skeleton from the config dir `~/.meta6` will be applied (see Config
Dir below).

# Fork Module Options

```
--fork-module=<Module::Name::Here> # module name as to be found in the ecosystem

```

This will seach a module by name in the ecosystem. If it's a github repo that
repo will be forked and cloned to the local FS. If there is a `META6.info` but
no `t/meta.t`, the file and its dependancy will be added and commited to the
local git repo.

# Pull Request Options

```
--pull-request
--title=`git log|head 1` # defaults to last commit message
--message=''
--head=master # branch in your fork
--base=master # branch in upstream repo
--repo-name # defaults to repo name provided in META6.info

```

Pull request need to tell github where to create the PR at. That in turn
requires a proper `META6.json` to get the repo name from.

# Releasing a module

To create a release on github use `--release`. The optional parameter
`--version` takes a string that is used as a version and stored in the
META6.json-file. Versions can be incremented with `+`, `++`, `+++` for the
parts of a version with the form `1.2.3`. A single `+` will change the
revision, `++` the miner version and `+++` the major.

A github-tag will be created and is the base of the release. The `source-url`
field in the META6.json is set to the tarball of the release on github.

# Config Dir

The config dir resides at `~/.meta6` and holds a folder called `skeleton` for
additional files to be copied into any new project. This is where you put your
default `LICENSE` or alternate `.gitignore`.

The config dir, a default meta6.cfg and its default subdirs are created with
`--create-cfg-dir`.

Any executable under `pre-create.d`, `post-create.d` and `post-push.d` are
sorted and executed with a timeout of 60 seconds each. Files that end in `~`
are filtered out.

The config directory can hold a `github-token.txt` file that is used to help
`curl` to connect to github. The [token](https://github.com/settings/tokens)
needs the scopes `repo`, `user/read:user` and `user/email`. Please note that
`git` itself can handle a `~/.netrc`-file and github will accept a token
instead of a password.

# Github

To be able to talk to github your git-config requires a section as follows.

```
[credential]
    username = your-github-username

```


## dist_cpan-JFORGET-Date-Calendar-Hijri.md
# NAME

Date::Calendar::Hijri - Arithmetic variant of the Hijri calendar

# SYNOPSIS

Converting a Gregorian date (e.g. 7th February 2021) into Hijri

```
use Date::Calendar::Hijri;
my Date $dt-greg;
my Date::Calendar::Hijri $dt-hijri;

$dt-greg  .= new(2021, 2, 7);
$dt-hijri .= new-from-date($dt-greg);

say $dt-hijri;
# --> 1442-06-24
say $dt-hijri.strftime("%A %d %B %Y");
# --> Yaum al-Ahad 24 Jumaada al-Thaani 1442

```

Converting a Hijri date (e.g. 1 Muharram 1443) into Gregorian

```
use Date::Calendar::Hijri;
my Date::Calendar::Hijri $dt-hijri;
my Date $dt-greg;

$dt-hijri .= new(year => 1443, month => 1, day => 1);
$dt-greg   = $dt-hijri.to-date;

say $dt-greg;
# --> 2021-08-10

```

# DESCRIPTION

The real Hijri calendar is an observational calendar. That means that
calendar events, such as switching from a month to the next, depend of
the observation of some astronomical events, such as observing the
moon crescent after a new moon. But there is an unofficial arithmetic
variant, which differs from the real one by one or two days.

Date::Calendar::Hijri is a class representing dates in the arithmetic
variant of the Hijri calendar. It allows you to convert a Hijri date
into Gregorian (or possibly other) calendar and the other way.

# INSTALLATION

```
zef install Date::Calendar::Hijri

```

or

```
git clone https://github.com/jforget/raku-Date-Calendar-Hijri.git
cd raku-Date-Calendar-Hijri
zef install .

```

# AUTHOR

Jean Forget [JFORGET@cpan.org](mailto:JFORGET@cpan.org)

# COPYRIGHT AND LICENSE

Copyright (c) 2021 Jean Forget, all rights reserved.

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


## lazy.md
class X::Cannot::Lazy

Error due to inappropriate usage of a lazy list

```raku
class X::Cannot::Lazy is Exception { }
```

Error thrown (or wrapped in a [`Failure`](/type/Failure)) when inappropriately using a list that `.is-lazy`. Such a list can be infinite which would make it impossible to iterate over all values.

# [Methods](#class_X::Cannot::Lazy "go to top of document")[§](#Methods "direct link")

## [method action](#class_X::Cannot::Lazy "go to top of document")[§](#method_action "direct link")

```raku
method action()
```

Verbal description of the inappropriate action.

## [method what](#class_X::Cannot::Lazy "go to top of document")[§](#method_what "direct link")

```raku
method what()
```

Returns the type that was the target of the action, if it was not the lazy list itself.


## dist_zef-samy-App-Stouch.md
# stouch

**stouch** (**s**tock **touch**) is a program that can create files and directory trees from pre-existing templates. It is also capable of performing basic text substitution on the contents of created files.

## Installing

**stouch** should be able to run on both Unix-like and Windows operating systems, as long as your system supports the dependencies listed below.

**stouch** requires the [rakudo](https://rakudo.org/) compiler.

**stouch** depends on the following Raku modules, which can be installed via [zef](https://github.com/ugexe/zef):

* `IO::MiddleMan` (for tests)

Once the required dependencies are installed, **stouch** can be installed via zef.

```
zef install .

```

## Usage

```
stouch [options] file ...

```

This section is a rough overview of **stouch**'s capabilities, please consult the manual for more exhaustive documentation. The manual can be accessed via `rakudoc` or the `--man` option.

```
rakudoc App::Stouch
stouch --man

```

By default, **stouch** will create files using templates determined from each file's suffix. When creating a file, **stouch** will copy the file/directory tree to the desired location, and perform any specified text substitutions on the created files.

For **stouch** to work, you must first set up a template directory. The template directory can be specified by either `-d` option or the `STOUCH_TEMPLATES` environment variable. If neither of those are specified, **stouch** will default to `~/.stouch`. Each template in the template directory must be named after the file it is templating with the `.template` suffix. Here is an example template directory:

```
template-directory/
L raku.template
L rakumod.template
L c.template
L pl.template
...

```

This means we can use **stouch** to create the following files:

```
stouch test.raku test.rakumod test.c test.pl

```

When creating a file/directory, **stouch** will determine the template to use either by the desired file's suffix, or the `-t` option if it is specified.

**stouch** can do text substitutions via *substitution targets*. A substitution target is a string with alphanumeric or underscore characters enclosed in two curly brackets, like this:

```
{{this}} <-- is a substitution target

```

Substitution targets can optionally be substituted via the `-s` option, which allows you to specify the text you would like to replace a substitution target. For example, say you have this template file:

```
This is a {{type}} file!
It does {{whatever}}!

```

and you use **stouch** with `-s "type => text, whatever => stuff"`, the created file would look like this:

```
This is a text file!
It does stuff!

```

**stouch** can also perform text substitutions on file paths.

```
# This will create a file named foo.raku
stouch -s "script => foo" {{script}}.raku

```

These path substitutions can also apply to children paths of a template directory.

## Copyright

Copyright 2024-2025, Samuel Young

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