### ----------------------------------------------------
### -- Arithmetic::PaperAndPencil
### -- Licenses: Artistic-2.0
### -- Authors: Jean Forget
### -- File: lib/Arithmetic/PaperAndPencil.rakumod
### ----------------------------------------------------
### -- Chunk 5 of 5
[l2p-lin($action.r2l); l2p-col($action.r2c - $action.r2val.chars + $i + 1)] {
           $_.read = True;
           if $action.r2str {
             $_.strike = True;
           }
         }
      }
    }

    # Writing some digits (or other characters)
    if $action.w1val ne '' {
      # checking the line and column minimum numbers
      check-l-min($action.w1l);
      check-c-min($action.w1c - $action.w1val.chars + 1);
      # putting spaces into all uninitialised boxes
      filling-spaces($action.w1l, $action.w1c);
      # putting each char separately into its designated box
      for $action.w1val.comb('').kv -> $i, $str {
         with @sheet[l2p-lin($action.w1l); l2p-col($action.w1c - $action.w1val.chars + $i + 1)] {
           $_.char  = $str;
           $_.write = True;
         }
      }
    }
    if $action.w2val ne '' {
      # checking the line and column minimum numbers
      check-l-min($action.w2l);
      check-c-min($action.w2c - $action.w2val.chars + 1);
      # putting spaces into all uninitialised boxes
      filling-spaces($action.w2l, $action.w2c);
      # putting each char separately into its designated box
      for $action.w2val.comb('').kv -> $i, $str {
         with @sheet[l2p-lin($action.w2l); l2p-col($action.w2c - $action.w2val.chars + $i + 1)] {
           $_.char  = $str;
           $_.write = True;
         }
      }
    }

    # Erasing characters
    if $action.label eq 'ERA01' {
      if  $action.w1l != $action.w2l {
        die "The chars are not horizontally aligned, starting at line {$action.w1l} and ending at line {$action.w2l}";
      }
      # checking the line and column minimum numbers
      check-l-min($action.w1l);
      check-c-min($action.w1c);
      check-c-min($action.w2c);
      # begin and end
      my ($c-beg, $c-end);
      if $action.w1c > $action.w2c {
        $c-beg = l2p-col($action.w2c);
        $c-end = l2p-col($action.w1c);
        filling-spaces($action.w1l, $action.w1c);
      }
      else {
        $c-beg = l2p-col($action.w1c);
        $c-end = l2p-col($action.w2c);
        filling-spaces($action.w1l, $action.w2c);
      }
      for $c-beg .. $c-end -> $i {
        @sheet[l2p-lin($action.w1l); $i].char = ' ';
      }
    }

    # Talking
    if $talkative or $action.label.starts-with('TIT') {
      my $line = full-label($action.label, $action.val1, $action.val2, $action.val3, $lang);
      if $line {
        if  $action.label.starts-with('TIT') {
          $line = "<operation>{$line}</operation>\n";
        }
        else {
          $line = "<talk>{$line}</talk>\n";
        }
        $result ~= $line;
      }
    }

    # Showing the operation
    if $action.level ≤ $level {
      my Str $op = '';
      for @sheet.kv -> $l, $line {
        my $line1 = $line.map({ $_.html }).join('');
        $op ~= $line1 ~ "\n";
      }
      if $op ne '' {
        $result ~= "<pre>\n{$op}</pre>\n";
      }
      # untagging written and read chars
      for @sheet -> $line {
        for @$line -> $char {
          $char.read  = False;
          $char.write = False;
        }
      }
    }
  }

  # simplyfing pseudo-HTML
  $result ~~ s:g/ "</underline><underline>" //;
  $result ~~ s:g/ "</strike><strike>" //;
  $result ~~ s:g/ "</write>" (\h*) "<write>" /$0/;
  $result ~~ s:g/ "</read>"  (\h*) "<read>"  /$0/;

  # changing pseudo-HTML into proper HTML
  $result ~~ s:g/"operation>"/h1>/;
  if %css<talk> {
    $result ~~ s:g! "</talk>" !</p>!;
    $result ~~ s:g! "<talk>"  !<p class='%css<talk>'>!;
  }
  else {
    $result ~~ s:g/"talk>"/p>/;
  }
  if %css<underline> {
    $result ~~ s:g! "</underline>" !</span>!;
    $result ~~ s:g! "<underline>"  !<span class='%css<underline>'>!;
  }
  else {
    $result ~~ s:g/"underline>"/u>/;
  }
  # maybe I should replace all "strike" tags by "del"? or by "s"?
  # see https://www.w3schools.com/tags/tag_strike.asp : <strike> is not supported in HTML5
  if %css<strike> {
    $result ~~ s:g! "</strike>" !</span>!;
    $result ~~ s:g! "<strike>"  !<span class='%css<strike>'>!;
  }
  if %css<read> {
    $result ~~ s:g! "</read>" !</span>!;
    $result ~~ s:g! "<read>"  !<span class='%css<read>'>!;
  }
  else {
    $result ~~ s:g/"read>"/em>/;
  }
  if %css<write> {
    $result ~~ s:g! "</write>" !</span>!;
    $result ~~ s:g! "<write>"  !<span class='%css<write>'>!;
  }
  else {
    $result ~~ s:g/"write>"/strong>/;
  }
  $result ~~ s:g/ \h+ $$//;

  return $result;
}

=begin pod

=head1 NAME

Arithmetic::PaperAndPencil - simulating paper and pencil techniques for basic arithmetic operations

=head1 SYNOPSIS

=begin code :lang<raku>

use Arithmetic::PaperAndPencil;

my Arithmetic::PaperAndPencil $operation .= new;
my Arithmetic::PaperAndPencil::Number $x .= new(value => '355000000');
my Arithmetic::PaperAndPencil::Number $y .= new(value => '113');

$operation.division(dividend => $x, divisor => $y);
my Str $html = $operation.html(lang => 'fr', silent => False, level => 3);
'division.html'.IO.spurt($html);

$operation .= new; # emptying previous content
my Arithmetic::PaperAndPencil::Number $dead .= new(value => 'DEAD', radix => 16);
my Arithmetic::PaperAndPencil::Number $beef .= new(value => 'BEEF', radix => 16);

$operation.addition($dead, $beef);
$html = $operation.html(lang => 'fr', silent => False, level => 3);
'addition.html'.IO.spurt($html);

=end code

The first HTML file ends with

=begin code
 355000000|113
 0160     |---
  0470    |3141592
   0180   |
    0670  |
     1050 |
      0330|
       104|
=end code

and the second one with

=begin code
  DEAD
  BEEF
 -----
 19D9C
=end code

=head1 DESCRIPTION

Arithmetic::PaperAndPencil  is a  module which  allows simulating  the
paper  and  pencil  techniques  for  basic  arithmetic  operations  on
integers: addition, subtraction, multiplication and division, but also
square root extraction and conversion from a radix to another.

An  object  from  the C<Arithmetic::PaperAndPencil>  class  is  called
"paper  sheet", because  it  represents  a paper  sheet  on which  the
simulated human scribbles  his computations. In some  cases, the human
would use a wad of sheets instead of a single sheet. This is simulated
in the module, but we still called an object "paper sheet".

=head2 Problems, known bugs and acceptable breaks from reality

Most  humans  can only  compute  in  radix  10.  Some persons  have  a
theoretical knowledge  of numeric bases  other than 10, and  a limited
practical skill  of using radix  2, radix 8  and radix 16.  The module
uses any radix from 2 to 36, without difference.

The module  can use numbers  of any length.  Human beings will  not be
able to  multiply two  100-digit numbers.  Or if  they try,  they will
spend much effort  and the result may be wrong.  The module can easily
multiply two 100-digit numbers. The  output may be lengthy and boring,
but it will be correct.

Humans can  detect situations where  the computation procedure  can be
amended,  such as  a  multiplication where  the  multiplicand and  the
multiplier contain many  "0" digits. The module does  not detect these
cases and still uses the unaltered computation procedure.

Human beings write their calculations on A4 paper (21 cm × 29,7 cm) or
letter paper (21,6  cm × 27,9 cm). The module  writes its calculations
on unlimited  sheets of paper. If  you want to compute  the product of
two 1000-digit numbers, the multiplication will have a 2000-char width
and a 1000-line height and still be on a single sheet of paper.

If you  ask for the  operations with  the "talking" formulas,  most of
these  formulas are  the traditional  sentences which  accompanies the
writing of the  computation. But in some cases, the  module displays a
non-standard sentence, to explain better what is happening.

=head1 UTILITY METHODS

=head2 new

Without  parameters, creates  an  empty paper  sheet.  Or removes  the
content of an already existing paper sheet.

With a C<csv> keyword parameter, reads  a CSV file and creates a paper
sheet containing the operations listed in this CSV file. The parameter
is the CSV filename.

=head2 csv

Generates a string with a CSV format and listing all operations stored
in the sheet object. Storing this string into a file allows you to use
the C<< .new(csv => $filename) >> method to recreate a prior sheet.

=head2 html

Generates a string using the HTML format.

For a properly formatted HTML file, the module user should provide the
beginning of the file, from the C<< <html> >> tag until the C<< <body>
>> tag, and then  the end of the file, with  the C<< </body></html> >>
tags.

The parameters are the following:

=begin item

C<lang>

The  language for  the titles  and messages.  The C<"fr">  language is
fully specified, and the C<"en"> language is still incomplete. For the
moment, there are no other languages.

=end item

=begin item

C<silent>

Boolean parameter controlling the display of the "spoken" messages. If
C<True>, only the titles are  displayed. It C<False>, all messages are
displayed.

=end item

=begin item

C<level>

Integer parameter  controlling the  display of partial  operations. If
C<0>, only the final complete operation  is shown. If C<1>, each sheet
is displayed  upon switching  to another  sheet (when  using a  wad of
sheets). If C<2> or more, partial operations are displayed. The higher
the parameter, the more often the partial operations are displayed.

=end item

=begin item

C<css>

Overrides  the default  HTML formatting.  This is  a hash  table, with
entries among C<underline>, C<strike>,  C<write>, C<read> and C<talk>.
If  an entry  exists,  the default  format is  replaced  by C<<  <span
style='xxx'> >>. Exception: if the  C<talk> entry exists, the "spoken"
messages are formatted with C<< <p style='xxx'> >>.

=end item

=head1 ARITHMETIC METHODS

All  these  methods   return  a  C<Arithmetic::PaperAndPencil::Number>
instance,  equal to  the  result of  the  operation. Unless  specified
otherwise,  all input  C<Arithmetic::PaperAndPencil::Number> instances
must have the same numeric radix.

=head2 addition

Simulates the addition  of two or more numbers. The  numbers are given
as a  list variable  C<@list> or  a list  of scalar  variables C<$nb1,
$nb2,  $nb3>.  This is  a  positional  parameter.  Each number  is  an
instance of the C<Arithmetic::PaperAndPencil::Number> class.

=head2 subtraction

Simulates   the  subtraction   of  two   numbers,  instances   of  the
C<Arithmetic::PaperAndPencil::Number> class. The  keywords are C<high>
and C<low>.  The C<high> number must  be greater than or  equal to the
C<low> number. Negative results are not allowed.

A third  keyword parameter  is C<type>. With  this parameter,  you can
choose between a standard subtraction (parameter value C<std>, default
value) and a subtraction using  the radix-complement of the low number
(parameter value C<compl>).

Acceptable break  from reality. When  using the C<compl>  variant, the
module will write the extra digit  and then strike it, while the human
computer will stop before writing  this extra digit, especially in the
context of assembly programming, where  for example the registers hold
32 bits, not 33.

=head2 multiplication

Simulates the  multiplication of  two numbers. The  keyword parameters
are:

=begin item
C<multiplicand>, C<multiplier>

The two numbers to be multiplied, instances of C<Arithmetic::PaperAndPencil::Number>.
=end item

=begin item
C<type>

Specifies the variant technique. This parameter is a C<Str> value. The
default  variant  is  C<'std'>.   Other  values  are  C<'jalousie-A'>,
C<'jalousie-B'>, or C<'boat'> (see below).
=end item

=begin item
C<direction>

This  parameter  is  used  with the  C<'boat'>  type.  Value  C<'ltr'>
(default value)  specifies that the elementary  products are processed
left-to-right,  value  C<'rtl'>  specifies  that  these  products  are
processed  right-to-left.   This  applies   only  to   processing  the
multiplier's   digits.  Whatever   the  value,   the  digits   of  the
multiplicand are processed left-to-right.

This  parameter   has  no  use  with   C<'std'>,  C<'jalousie-A'>  and
C<jalousie-B'> types.
=end item

=begin item
C<mult-and-add>

This parameter  is used with  the C<'boat'> type.  Value C<'separate'>
(default value) means that in a first phase, the digits resulting from
the elementary multiplications are written  and that in a second phase
these  digits are  added together  to obtain  the final  result. Value
C<'combined'> means that as soon  as a elementary product is computed,
its digits  are added to the  running sum which will  become the final
full product at the end.

This  parameter   has  no  use  with   C<'std'>,  C<'jalousie-A'>  and
C<jalousie-B'> types.
=end item

=begin item
C<product>

This  parameter   is  used  with  the   C<"jalousie-*">  types.  Value
C<"L-shaped"> (default value) means that the product is written in two
parts,  an horizontal  one  at  the bottom  of  the  operation and  an
vertical one, on the left side of the operation for C<"jalousie-A"> or
on the right side for  C<"jalousie-B">. Value C<"straight"> means than
the product  is written horizontaly  on the  bottom line, even  if the
bottom line is wider than the rectangle of the operation.
=end item

The various types are

=begin item
C<std>

The standard multiplication.

Acceptable break  from reality:  remember that the  successive partial
products  shifts by  one column.  These shifts  are materialised  with
dots. When  the multiplier contains  a digit  C<0>, the line  with all
zeroes is not printed and the shift  is more than one column, with the
corresponding number of dots. Example:

  .      628
  .      203
  .      ---
  .     1884
  .   1256..
  .   ------
  .   127484

The actual acceptable  break from reality happens  when the multiplier
contains zeroes at the right. In this case, are there dots in the very
first line? Or do we write zeroes? See below both cases.

  .      628          628
  .      230          230
  .      ---          ---
  .    1884.        18840
  .   1256..       1256..
  .   ------       ------
  .   144440       144440

The module uses the second possibility, writing zeroes on the first line.
=end item

=begin item
C<shortcut>

The standard multiplication, but  if the multiplier  contains repeated
digits, the  partial products  are computed only  once. When  the same
digit appears a second time in the multiplier, the  partial product is
copied from the first occurrence instead of being recomputed.
=end item

=begin item
C<prepared>

This  variant  is  inspired  from  the  C<prepared>  variant  for  the
division.  Before  starting  the multiplication  proper,  all  partial
products are  preemptively computed. Then, when  the multiplication is
computed, all partial products are  simply copied from the preparation
step.

Acceptable  break  from  reality:  there  is  no  evidence  that  this
technique  is taught  or used.  It is  just an  possible extension  to
multiplication of the prepared division technique.
=end item

=begin item
C<jalousie-A>

The partial products are written in rectangular form. The multiplicand
is  written  left-to-right on  the  top  side  of the  rectangle,  the
multiplier  is  written  top-to-bottom  on   the  right  side  of  the
rectangle, the  final product is  written first, top-to-bottom  on the
left side  of the  rectangle and second,  left-to-right on  the bottom
side of  the rectangle. For example,  the multiplication C<15 ×  823 =
12345>  gives  the following  result  (omitting  the interior  of  the
rectangle):

  .     823
  .    1   1
  .    2   5
  .     345

If the C<product> parameter is C<"straight">, then the operation final
aspect is:

  .     823
  .        1
  .        5
  .   12345

Acceptable break from reality: the  outlying digits should be centered
with respect  to the inner  grid. The module  writes them in  a skewed
fashion. In addition, the inner  vertical and horizontal lines are not
drawn. Below left, the theoretical  output, below right the simplified
output:

  .     8   2   3         8 2 3
  .   -------------      --------
  .   |0 /|0 /|0 /|      |0/0/0/|
  .  1| / | / | / |1    1|/8/2/3|1
  .   |/ 8|/ 2|/ 3|      |4/1/1/|
  .   -------------     2|/0/0/5|5
  .   |4 /|1 /|1 /|      --------
  .  2| / | / | / |5      3 4 5
  .   |/ 0|/ 0|/ 5|
  .   -------------
  .     3   4   5

=end item

=begin item
C<jalousie-B>

The partial products are written in rectangular form. The multiplicand
is  written  left-to-right on  the  top  side  of the  rectangle,  the
multiplier is written bottom-to-top on the left side of the rectangle,
the final product  is written first, left-to-right on  the bottom side
of the  rectangle and second, bottom-to-top  on the right side  of the
rectangle. For  example, the multiplication C<15 × 823 =  12345> gives
the following result (omitting the interior of the rectangle):

  .  823
  . 5   5
  . 1   4
  .  123

If the C<product> parameter is C<"straight">, then the operation final
aspect is:

  .  823
  . 5
  . 1
  .  12345

Acceptable break from reality: same as for C<'jalousie-A'>.
=end item

=begin item
C<boat>

The  multiplicand  is  written   between  two  horizontal  lines.  The
multiplier is written below the bottom line and stricken and rewritten
as  the multiplication  progresses. The  partial products  are written
above the  top line.  When the  partial products  are added,  they are
stricken and the final product is written above the partial products.

Acceptable  break from  reality: I  am not  sure the  explanation from
I<Number Words and  Number Symbols> is authoritative. So  I have added
two parameters, C<direction> and  C<mult-and-add>, to allow the module
user to choose which subvariant he prefers.
=end item

=head2 division

Simulates the division of two numbers. The keyword parameters are:

=begin item
C<dividend>, C<divisor>

The two numbers to be divided, instances of C<Arithmetic::PaperAndPencil::Number>.
=end item

=begin item
C<type>

Specifies the variant technique. This parameter is a C<Str> value. The
default variant is C<"std">.
=end item

=begin item
C<result>

This C<Str> parameter  can be either C<"quotient">  (default value) or
C<"remainder">,  or  C<"both">.  It  controls  which  value  is  (are)
returned by the method to the main programme.
=end item


=begin item
C<mult-and-sub>

This C<Str> parameter  can be either C<"combined">  (default value) or
C<"separate">. It  controls the computation of  the successive partial
remainders with  a multiplication (quotient digit  times full divisor)
and a subtraction  (from the partial dividend).  If C<"combined">, the
multiplication and  the subtraction are  done at the same  time, digit
per digit. If C<"separate">, the multiplication is done first in full,
then the subtraction is done.
=end item

The various types are

=begin item
C<std>

The standard division.
=end item

=begin item
C<cheating>

This is the  standard division with a twist. The  standard division is
usually a  trial-and-error process  in which several  candidate digits
are  tried  for   each  quotient  digit.  With   this  technique,  the
trial-and-error process is cut short  and only the successful digit is
tried.

Acceptable break  from reality: This is  not a real method,  this is a
convenience  method  which gives  shorter  HTML  files than  what  the
C<"std"> type generates.
=end item

=begin item
C<prepared>

Before starting the division, the module computes the partial products
of the divisor with any  single-digit number. These when computing the
intermediate  remainders,   instead  of   doing  a   multiplication  -
subtraction combination,  the already known partial  product is simply
copied from  the preparation  list then  subtracted from  the previous
intermediate  remainder.  The  C<mult-and-sub> parameter  defaults  to
C<"separate"> for this division type.
=end item

=begin item
C<boat>

The  dividend is  written above  an  horizontal line.  The divisor  is
written below this  line. As the first partial  remainder is computed,
the  used digits  of the  dividend and  divisor are  stricken and  the
digits of  the partial remainder are  written above the digits  of the
dividend. When computing the next digits, the divisor is rewritten and
the computation of the next partial remainder again strikes the digits
of the  first partial remainder  and of  the second occurrence  of the
divider.

Acceptable  break  from   reality:  I  have  not   found  anywhere  an
explanation for this technique. The way it is implemented is just some
guesswork after some  reverse engineering attempt. A  special point is
that  it  seems  to  require  something  similar  to  the  C<cheating>
technique above, because I do not see how we can "unstrike" the digits
that were stricken with the previous digit candidate.
=end item

=head2 square-root

Simulates the  extraction of the square  root of a number.  There is a
single     positional     parameter,     an    instance     of     the
C<Arithmetic::PaperAndPencil::Number> class.

There is  an optional keyword parameter,  C<mult-and-sub>. Its purpose
is the same as for division. If set to C<'combioned'> (default value),
the  computing  of the  product  (candidate  digit times  divisor)  is
combined with  the subtraction  from the partial  dividend. If  set to
C<'separate'>, the multiplication and  the subtraction are executed in
separate and successive phases.

=head2 conversion

Simulates the conversion  of a number from its current  radix to a new
radix.

The parameters are:

=begin item
C<number>

The number to convert, instance of C<Arithmetic::PaperAndPencil::Number>.
=end item

=begin item
C<radix>

The  destination radix  for the  conversion. This  is a  native C<Int>
number, not an instance of C<Arithmetic::PaperAndPencil::Number>.
=end item

=begin item
C<nb-op>

The  number of  operations  on a  single page.  After  this number  is
reached, a  new page  is generated. This  allows keeping  the complete
operation  sufficiently  short.  This  parameter is  a  native  C<Int>
number. If zero (default value), no new pages are generated.
=end item

=begin item
C<type>

A string  parameter specifying  which algorithm is  used to  convert a
number. Values  C<'mult'> and C<'Horner'>  are synonymous and  use the
cascading multiplication algorithm (or  Horner scheme). Value C<'div'>
uses the cascading division algorithm.
=end item

=begin item
C<div-type>

A string parameter specifying which kind of division is used: C<'std'>
(default value) uses  a standard division with  a full trial-and-error
processing  for  candidate  quotient   digits,  C<'cheating'>  uses  a
standard division  in which the trial-and-error  of candidate quotient
digits is  artificially reduced  to a single  iteration, C<'prepared'>
first computes the list of multiples  for the target radix and uses it
to openly and  accountably reduce the trial-and-error  processing to a
single iteration.

This parameter is  ignored if the conversion parameter  C<type> is not
C<'div'>.

See  the  C<type>  parameter  for the  C<division>  method.  Yet,  the
C<'boat'> value available for the C<type> parameter of the C<division>
method  is   not  allowed  for   the  C<div-type>  parameter   of  the
C<conversion> method.
=end item

=begin item
C<mult-and-sub>

This parameter  is similar  to the  C<mult-and-sub> parameter  for the
C<division> method, except that it is useful only if the value of the
C<div-type> parameter is C<'cheating'>.

The  parameter  controls the  computation  of  the successive  partial
remainders with  a multiplication (quotient digit  times full divisor)
and a  subtraction (from  the partial  dividend). Possible  values are
C<'combined'> or  C<'separate'>. If C<'combined'>,  the multiplication
and the  subtraction are done  at the same  time, digit per  digit. If
C<'separate'>,  the multiplication  is done  first in  full, then  the
subtraction is done.

If  the  C<div-type> parameter  is  C<'prepared'>,  this parameter  is
ignored  and   the  multiplication   and  the  subtraction   are  done
separately.

If  the   C<div-type>  parameter  is  C<'std'>,   the  C<mult-and-sub>
parameter is  ignored and the  multiplication and the  subtraction are
combined. The  reason for  this behaviour  is to  by-pass a  bug which
would appear in cramped situations where several divisions are crammed
side by side.

=end item

=head2 gcd

Simulates the computation of the GCD (greatest common divisor) of
two numbers.

The parameters are:

=begin item
C<first>

The first number used, instance of C<Arithmetic::PaperAndPencil::Number>.
=end item

=begin item
C<second>

The second number used, instance of C<Arithmetic::PaperAndPencil::Number>.
=end item

=begin item
C<div-type>

A string parameter specifying which kind of division is used: C<"std">
(default value) uses  a standard division with  a full trial-and-error
processing  for  candidate  quotient   digits,  C<"cheating">  uses  a
standard division  in which the trial-and-error  of candidate quotient
digits is artificially reduced to a single iteration.

See  the  C<type>  parameter  for the  C<division>  method.  Yet,  the
C<"boat"> and C<"prepared"> values available for the C<type> parameter
of  the  C<division>  method  are  not  allowed  for  the  C<div-type>
parameter of the C<gcd> method.
=end item

=head1 BUGS, ISSUES AND ACCEPTABLE BREAKS FROM REALITY

For the  various arithmetical methods, not  all parameter combinations
are  used in  real life.  This includes  especially the  C<"cheating">
variants.

The  values  assigned  to  the   C<level>  attribute  are  not  always
consistent and  they may lead to  awkward listings, in which  a boring
part is  printed in whole  detail and  an interesting part  is printed
without enough detail.

=head1 SECURITY MATTERS

As said above, the numbers are not limited in length. The flip side is
that  the  user can  ask  for  the  multiplication of  two  1000-digit
numbers, which  means several millions of  basic actions (single-digit
multiplications, basic  additions, etc). This  can lead to  a DOS-like
situation: filled-up memory, clogged CPU for example.

Another issue is the initialisation of a C<Arithmetic::PaperAndPencil>
object with a  CSV file. The content  of the CSV file  is not checked.
This  can  result  is  line  and column  coordinates  ranging  in  the
thousands or  beyond. In this  case, the  C<html> method will  build a
huge string result.

=head1 SEE ALSO

The background of this module is extensively described in the Github repository. See
L<https://github.com/jforget/raku-Arithmetic-PaperAndPencil/blob/master/doc/Description-en.md>
(or L<https://github.com/jforget/raku-Arithmetic-PaperAndPencil/blob/master/doc/Description-fr.md>
if you speak French).

=head1 DEDICATION

This module is dedicated to my  primary school teachers, who taught me
the basics of arithmetics, and even  some advanced features, and to my
secondary  school math  teachers, who  taught me  other advanced  math
concepts and features.

=head1 AUTHOR

Jean Forget <J2N-FORGET@orange.fr>

=head1 COPYRIGHT AND LICENSE

Copyright 2023, 2024 Jean Forget

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

=end pod


