### ----------------------------------------------------
### -- Arithmetic::PaperAndPencil
### -- Licenses: Artistic-2.0
### -- Authors: Jean Forget
### -- File: lib/Arithmetic/PaperAndPencil.rakumod
### ----------------------------------------------------
### -- Chunk 3 of 5
 my @total;
        for $result.value.flip.comb.kv -> $i, $digit {
          @added[$i][0] = %( lin => $line - 1, col => - $i, val => $digit);
          @total[$i]    = %( lin => $line + 1, col => - $i);
        }
        for $added.value.flip.comb.kv -> $i, $digit {
          @added[$i][1] = %( lin => $line    , col => - $i, val => $digit);
          @total[$i]    = %( lin => $line + 1, col => - $i);
        }
        $result .= new(radix => $radix, value => self!adding(@added, @total, 2, $radix));
        $line++;
      }
      self.action[* - 1].level = 3;
      # next step
      $op++;
      if $op == $nb-op && $op1 != $number.chars - 2 {
        # testing - 2 because of (a) the substr(1) method which has shortened the number, and (b) zero-based numbering in the .kv method
        self.action[* - 1].level = 1;
        $action .= new(level => 9, label => 'NXP01');
        self.action.push($action);
        $action .= new(level => 9, label => 'CNV03', val1 => $result.value, val2 => $number.value.substr($op1 + 2)
                              , w1l => 1, w1c => 0, w1val => $result.value);
        self.action.push($action);
        $op = 0;
        $line = 1;
      }
      if $width ≤ $result.chars {
        $width = $result.chars;
      }
    }
  }
  else {
    my Int $op   = 0;
    my Int $l-dd = 1;
    my Int $c-dd = 0;
    my Str $res  = '';
    $action .= new(level => 9, label => 'WRI00', w1l => $l-dd, w1c => $c-dd, w1val => $number.value);
    self.action.push($action);
    my Arithmetic::PaperAndPencil::Number $x;
    my Arithmetic::PaperAndPencil::Number $y;
    while $new-radix ☈≤ $number {
      $action .= new(level => 9, label => 'DRA02', w1l => $l-dd, w1c => $c-dd + 1
                                                 , w2l => $l-dd, w2c => $c-dd + $new-radix.chars);
      self.action.push($action);
      ($x, $y) = self!embedded-div(l-dd => $l-dd    , c-dd => $c-dd                   , dividend => $number
                                 , l-dr => $l-dd    , c-dr => $c-dd + $new-radix.chars, divisor  => $new-radix
                                 , l-qu => $l-dd + 1, c-qu => $c-dd + 1
                                 , basic-level => 3, type => $div-type, mult-and-sub => $mult-and-sub
                                 , mult-cache => %mult-cache);
      self.action[* - 1].level = 3;
      $res = %conv-cache{$y.value} ~ $res;
      $number = $x;
      $op++;
      $l-dd++;
      $c-dd += $number.chars;
      my Str $rewrite-dd = '';
      if $op == $nb-op && $new-radix ☈≤ $number {
        self.action[* - 1].level = 1;
        $action .= new(level => 9, label => 'NXP01');
        self.action.push($action);
        $op   = 0;
        $l-dd = 1;
        $c-dd = 0;
        $rewrite-dd = $number.value;
      }
      if $new-radix ☈≤ $number {
        $action .= new(level => 9, label => 'CNV03', val1 => $res, val2 => $number.value, w1l => $l-dd, w1c => $c-dd, w1val => $rewrite-dd);
        self.action.push($action);
      }
    }
    $res = %conv-cache{$number.value} ~ $res;
    $action .= new(level => 0, label => 'CNV03', val1 => $res, val2 => '0');
    self.action.push($action);
    $result .= new(value => $res, radix => $radix);
  }

  self.action[* - 1].level = 0;
  return $result;
}

method gcd(Arithmetic::PaperAndPencil::Number :$first  is copy
         , Arithmetic::PaperAndPencil::Number :$second is copy
         , Str :$div-type = 'std'
         --> Arithmetic::PaperAndPencil::Number
                 ) {
  my Arithmetic::PaperAndPencil::Action $action;
  my Int $radix = $first.radix;
  if $second.radix != $radix {
    die "The two numbers have different bases: $radix != {$second.radix}";
  }
  if @.action {
    self.action[* - 1].level = 0;
  }
  if $first ☈< $second {
    ($first, $second) = ($second, $first);
  }
  my Str $title = '';
  given $div-type {
    when 'std'      { $title = 'TIT17' ; }
    when 'cheating' { $title = 'TIT18' ; }
  }
  if $title eq '' {
    die "Division type '$div-type' unknown";
  }
  $action .= new(level => 9
               , label => $title
               , val1  => $first.value
               , val2  => $second.value
               , val3  => $radix.Str
               );
  self.action.push($action);
  my Arithmetic::PaperAndPencil::Number $quo;
  my Arithmetic::PaperAndPencil::Number $rem;
  my %mult-cache;

  # set-up
  my Int $len2 = $second.chars;
  my Int $l-dd = 0;
  my Int $c-dd = 0;
  my Int $l-dr = 0;
  my Int $c-dr = $len2;
  my Int $l-qu = -1;
  my Int $c-qu =  1;
  $action .= new(level => 9, label => 'WRI00', w1l => $l-dd, w1c => $c-dd, w1val => $first.value);
  self.action.push($action);

  # computation
  while $second.value ne '0' {
    if $div-type eq 'cheating' {
      my Arithmetic::PaperAndPencil $dummy .= new;
      $dummy!preparation(factor => $second, limit => 'Z', cache => %mult-cache);
    }
    $action .= new(level => 9, label => 'DRA02', w1l => $l-qu, w1c => $c-dr - $len2 + 1
                                               , w2l => $l-qu, w2c => $c-dr);
    self.action.push($action);
    ($quo, $rem) = self!embedded-div(l-dd => $l-dd, c-dd => $c-dd, dividend => $first
                                   , l-dr => $l-dr, c-dr => $c-dr, divisor  => $second
                                   , l-qu => $l-qu, c-qu => $c-qu
                                   , basic-level => 3, type => $div-type, mult-and-sub => 'combined'
                                   , mult-cache => %mult-cache);
    self.action[* - 1].level = 3;
    $first  = $second;
    $second = $rem;
    $len2   = $rem.chars;
    $c-dd   = $c-dr;
    $c-qu  += max($quo.chars, $first.chars);
    $c-dr   = $c-qu + $len2 - 1;
  }
  self.action[* - 1].level = 0;
  return $first;
}

method !adv-mult(Int :$basic-level, Str :$type = 'std'
               , Int :$l-md, Int :$c-md # coordinates of the multiplicand
               , Int :$l-mr, Int :$c-mr # coordinates of the multiplier
               , Int :$l-pd, Int :$c-pd # coordinates of the product
               , Arithmetic::PaperAndPencil::Number :$multiplicand
               , Arithmetic::PaperAndPencil::Number :$multiplier
               , :%cache
               --> Arithmetic::PaperAndPencil::Number) {
  my Arithmetic::PaperAndPencil::Action $action;
  my Str $result = '';
  my Int $radix = $multiplier.radix;
  my Int $line  = $l-pd;
  my Int $pos   = $multiplier.chars - 1;
  my Int $shift = 0;
  my Str $shift-char = '0';
  my     @partial; # storing the partial products' digits
  my     @final  ; # storing the final product's digit positions

  while $pos ≥ 0 {
    # shifting the current simple multiplication because of embedded zeroes
    if $multiplier.value.substr(0, $pos + 1) ~~ / ( '0' + ) $ / {
      $shift += $0.chars;
      $pos   -= $0.chars;
    }
    if $shift != 0 {
      $action .= new(level => $basic-level + 5, label => 'WRI00', w1l => $line, w1c => $c-pd, w1val => $shift-char x $shift);
      self.action.push($action);
      if $shift-char eq '0' {
        for 0 ..^ $shift -> $i {
          push @partial[$i], %( lin => $line, col => $c-pd - $i, val => '0');
        }
      }
    }
    # computing the simple multiplication
    my Arithmetic::PaperAndPencil::Number $mul .= new(radix => $radix, value => $multiplier.value.substr($pos, 1));
    my Arithmetic::PaperAndPencil::Number $pdt;
    if $type ne 'std' && %cache{$mul.value} {
      $pdt = %cache{$mul.value};
      $action .= new(level => $basic-level + 3, label => 'WRI05', val1 => $pdt.value
                   , w1l => $line, w1c => $c-pd - $shift, w1val => $pdt.value
                   );
      self.action.push($action);

    }
    else {
      $pdt = self!simple-mult(basic-level => $basic-level
                            , l-md => $l-md, c-md => $c-md         , multiplicand => $multiplicand
                            , l-mr => $l-mr, c-mr => $c-mr - $shift, multiplier   => $mul
                            , l-pd => $line, c-pd => $c-pd - $shift);
      # filling the cache
      %cache{$mul.value} = $pdt;
    }
    # storing the digits of $pdt
    for $pdt.value.comb.reverse.kv -> $i, $x {
      push @partial[$i + $shift], %( lin => $line, col => $c-pd - $shift - $i, val => $x);
    }
    # shifting the next simple multiplication
    $pos--;
    $shift++;
    $shift-char = '.';
    $line++;
  }
  $action .= new(level => $basic-level + 2, label => 'DRA02'
               , w1l => $line - 1, w1c => $c-pd + 1 - $multiplicand.chars - $multiplier.chars
               , w2l => $line - 1, w2c => $c-pd);
  self.action.push($action);
  for (0 .. $multiplicand.chars + $multiplier.chars) -> $i {
    @final[$i] = %( lin => $line, col => $c-pd - $i );
  }
  $result = self!adding(@partial, @final, $basic-level, $radix);
  return  Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value($result));
}

method !simple-mult(Int :$basic-level
                  , Int :$l-md, Int :$c-md # coordinates of the multiplicand
                  , Int :$l-mr, Int :$c-mr # coordinates of the multiplier (single-digit)
                  , Int :$l-pd, Int :$c-pd # coordinates of the product
                  , Arithmetic::PaperAndPencil::Number :$multiplicand
                  , Arithmetic::PaperAndPencil::Number :$multiplier
                --> Arithmetic::PaperAndPencil::Number) {
  my Str $result = '';
  my Int $radix  = $multiplier.radix;
  my     $carry  = '0';
  my Int $len1   = $multiplicand.chars;
  my Arithmetic::PaperAndPencil::Action $action;
  my Arithmetic::PaperAndPencil::Number $pdt;
  for (0 ..^ $len1) -> $i {
    my Arithmetic::PaperAndPencil::Number $mul .= new(:radix($radix), :value($multiplicand.value.substr($len1 - $i - 1, 1)));
    $pdt   = $multiplier ☈× $mul;
    $action .= new(level => $basic-level + 6, label => 'MUL01'                , val3 => $pdt.value
                 , r1l => $l-mr, r1c => $c-mr     , r1val => $multiplier.value, val1 => $multiplier.value
                 , r2l => $l-md, r2c => $c-md - $i, r2val => $mul.value       , val2 => $mul.value
                 );
    self.action.push($action);
    if $carry ne '0' {
      $pdt ☈+= Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value($carry));
      $action .= new(level => $basic-level + 6, label => 'ADD02', val1 => $carry, val2 => $pdt.value);
      self.action.push($action);
    }
    my Str $unit  = $pdt.unit.value;
    $carry        = $pdt.carry.value;
    my Str $code = 'WRI02';
    if $carry eq '0' {
      $code = 'WRI03';
    }
    if $i < $len1 - 1 {
      $action .= new(level => $basic-level + 5, label => $code, val1 => $unit, val2 => $carry
                   , w1l => $l-pd, w1c => $c-pd - $i, w1val => $unit
                     );
      self.action.push($action);
      $result = $unit ~ $result;
    }
  }
  $action .= new(level => $basic-level + 3, label => 'WRI00'
               , w1l => $l-pd, w1c => $c-pd + 1 - $len1, w1val => $pdt.value
                 );
  self.action.push($action);
  return  Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value($pdt.value ~ $result));
}

method !adding(@digits, @pos, $basic-level, $radix, :$striking = False --> Str) {
  my Arithmetic::PaperAndPencil::Action $action;
  my Arithmetic::PaperAndPencil::Number $sum;
  my Str $result = '';
  my Str $carry  = '0';
  for @digits.kv -> $i, $l {
    my @l = $l.grep({ $_ }); # to remove the Nil entries
    if @l.elems == 0 {
        $action .= new(level => $basic-level + 3, label => 'WRI04'           , val1  => $carry
                                 , w1l => @pos[$i]<lin>, w1c => @pos[$i]<col>, w1val => $carry
                                 );
        self.action.push($action);
        $result = $carry ~ $result;
    }
    elsif @l.elems == 1 && $carry eq '0' {
        $action .= new(level => $basic-level + 3, label => 'WRI04'           , val1  => @l[0]<val>
                                 , r1l => @l[ 0  ]<lin>, r1c => @l[ 0  ]<col>, r1val => @l[0]<val>, r1str => $striking
                                 , w1l => @pos[$i]<lin>, w1c => @pos[$i]<col>, w1val => @l[0]<val>
                                 );
        self.action.push($action);
        $result = @l[0]<val> ~ $result;
    }
    else {
      my Int $first;
      $sum .= new(radix => $radix, value => @l[0]<val>);
      if $carry eq '0' {
        $sum ☈+= Arithmetic::PaperAndPencil::Number.new(radix => $radix, value => @l[1]<val>);
        $action .= new(level => $basic-level + 6, label => 'ADD01', val1  => @l[0]<val>, val2 => @l[1]<val>, val3 => $sum.value
                            , r1l => @l[0]<lin>, r1c => @l[0]<col>, r1val => @l[0]<val>, r1str => $striking
                            , r2l => @l[1]<lin>, r2c => @l[1]<col>, r2val => @l[1]<val>, r2str => $striking
                            );
        $first = 2;
      }
      else {
        $sum ☈+= Arithmetic::PaperAndPencil::Number.new(radix => $radix, value => $carry);
        $action .= new(level => $basic-level + 6, label => 'ADD01', val1  => @l[0]<val>, val2 => $carry, val3 => $sum.value
                            , r1l => @l[0]<lin>, r1c => @l[0]<col>, r1val => @l[0]<val>, r1str => $striking
                            );
        $first = 1;
      }
      self.action.push($action);
      for $first ..^ @l.elems -> $j {
        $sum ☈+= Arithmetic::PaperAndPencil::Number.new(radix => $radix, value => @l[$j]<val>);
        $action .= new(level => $basic-level + 6, label => 'ADD02', val1  => @l[$j]<val>, val2 => $sum.value
                          , r1l => @l[$j]<lin>, r1c => @l[$j]<col>, r1val => @l[$j]<val>, r1str => $striking
                          );
        self.action.push($action);
      }
      if $i == @digits.elems - 1 {
        my Arithmetic::PaperAndPencil::Action $last-action = self.action[* - 1];
        self.action[* - 1] .= new(level => $basic-level + 2, label => $last-action.label, val1  => $last-action.val1, val2 => $last-action.val2, val3 => $last-action.val3
                          , r1l => $last-action.r1l, r1c => $last-action.r1c, r1val => $last-action.r1val, r1str => $striking
                          , r2l => $last-action.r2l, r2c => $last-action.r2c, r2val => $last-action.r2val, r2str => $striking
                          , w1l => @pos[$i]<lin>   , w1c => @pos[$i]<col> ,   w1val => $sum.value
                          );
        $result = $sum.value ~ $result;
      }
      else {
        my Str $digit = $sum.unit.value;
        $carry        = $sum.carry.value;
        my Int $lin;
        my Int $col;
        my Str $code = 'WRI02';
        if $carry eq '0' {
          $code = 'WRI03';
        }
        $action .= new(level => $basic-level + 3, label => $code, val1 => $digit, val2 => $carry
                   , w1l => @pos[$i]<lin>, w1c => @pos[$i]<col>, w1val => $digit
                   );
        self.action.push($action);
        $result = $digit ~ $result;
      }
    }
  }
  return $result;
}

method !embedded-sub(Int :$basic-level, Int :$l-hi, Int :$c-hi, Arithmetic::PaperAndPencil::Number :$high
                                      , Int :$l-lo, Int :$c-lo, Arithmetic::PaperAndPencil::Number :$low
                                      , Int :$l-re, Int :$c-re
                                      --> Str) {
  my Arithmetic::PaperAndPencil::Action $action;
  my Int $radix = $high.radix;
  my Int $leng  = $high.chars;
  # set-up
  $action .= new(level => $basic-level + 2, label => 'DRA02', w1l => $l-lo, w1c => $c-lo - $leng + 1
                                                            , w2l => $l-lo, w2c => $c-lo);
  self.action.push($action);

  my Str $carry  = '0';
  my Str $result = '';
  my Str $label;

  # First subphase, looping over the low number's digits
  for (0 ..^ $low.chars) -> $i {
    my Arithmetic::PaperAndPencil::Number $high1 .= new(radix => $radix, value => $high.value.substr($leng      - $i - 1, 1));
    my Arithmetic::PaperAndPencil::Number $low1  .= new(radix => $radix, value => $low .value.substr($low.chars - $i - 1, 1));
    my Arithmetic::PaperAndPencil::Number $adj1;
    my Arithmetic::PaperAndPencil::Number $res1;
    my Arithmetic::PaperAndPencil::Number $low2;
    if $carry eq '0' {
      ($adj1, $res1) = adjust-sub($high1, $low1);
      $action .= new(level => $basic-level + 6, label => 'SUB01', val1  => $low1.value, val2 => $res1.value, val3 => $adj1.value
                   , r1l => $l-hi, r1c => $c-hi - $i, r1val => $high1.value
                   , r2l => $l-lo, r2c => $c-lo - $i, r2val => $low1.value
                   );
    }
    else {
      $low2 = $low1 ☈+ Arithmetic::PaperAndPencil::Number.new(radix => $radix, value => $carry);
      $action .= new(level => $basic-level + 6, label => 'ADD01'   , val1  => $low1.value, val2 => $carry, val3 => $low2.value
                   , r1l => $l-lo, r1c => $c-lo - $i, r1val => $low1.value
                   );
      self.action.push($action);
      ($adj1, $res1) = adjust-sub($high1, $low2);
      $action .= new(level => $basic-level + 6, label => 'SUB02'   , val1  => $res1.value, val2 => $adj1.value
                   , r1l => $l-hi, r1c => $c-hi - $i, r1val => $high1.value
                   );
    }
    self.action.push($action);
    $result = $res1.unit.value ~ $result;
    $carry  = $adj1.carry.value;
    if $carry eq '0' {
      $label = 'WRI03';
    }
    else {
      $label = 'WRI02';
    }
    $action .= new(level => $basic-level + 3, label => $label    , val1  => $res1.unit.value, val2 => $carry
                 , w1l   => $l-re           , w1c   => $c-re - $i, w1val => $res1.unit.value
                 );
    self.action.push($action);
  }
  # Second subphase, dealing with the carry
  my Int $pos = $low.chars;
  while $carry ne '0' {
    my Arithmetic::PaperAndPencil::Number $high1  .= new(radix => $radix, value => $high.value.substr($leng - $pos - 1, 1));
    my Arithmetic::PaperAndPencil::Number $carry1 .= new(radix => $radix, value => $carry);
    my Arithmetic::PaperAndPencil::Number $adj1;
    my Arithmetic::PaperAndPencil::Number $res1;
    ($adj1, $res1) = adjust-sub($high1, $carry1);
    $action .= new(level => $basic-level + 6, label => 'SUB01', val1  => $carry, val2 => $res1.value, val3 => $adj1.value
                 , r1l => $l-hi, r1c => $c-hi - $pos, r1val => $high1.value
                 );
    self.action.push($action);
    $result = $res1.unit.value ~ $result;
    $carry  = $adj1.carry.value;
    if $carry eq '0' {
      $label = 'WRI03';
    }
    else {
      $label = 'WRI02';
    }
    $action .= new(level => $basic-level + 3, label => $label      , val1  => $res1.unit.value, val2 => $carry
                 , w1l   => $l-re           , w1c   => $c-re - $pos, w1val => $res1.unit.value
                 );
    # no need to write the final zero if there is no carry
    if $res1.unit.value ne '0' or $carry ne '0' or $pos < $leng - 1 {
      self.action.push($action);
    }
    $pos++;
  }
  # Third subphase, a single copy
  if $pos < $leng {
    $action .= new(level => $basic-level, label => 'WRI05'     , val1  => $high.value.substr(0, $leng - $pos)
                 , w1l   => $l-re       , w1c   => $c-re - $pos, w1val => $high.value.substr(0, $leng - $pos)
                 );
    self.action.push($action);
    $result = $high.value.substr(0, $leng - $pos) ~ $result;
  }

  return $result;
}

method !mult-and-sub(Int :$l-dd, Int :$c-dd, Arithmetic::PaperAndPencil::Number :$dividend
                   , Int :$l-dr, Int :$c-dr, Arithmetic::PaperAndPencil::Number :$divisor
                   , Int :$l-qu, Int :$c-qu, Arithmetic::PaperAndPencil::Number :$quotient
                   , Int :$l-re, Int :$c-re, Int :$basic-level
                   , Int :$l-pr, Int :$c-pr, Str :$mult-and-sub = 'combined'
                   ) {
  my Arithmetic::PaperAndPencil::Action $action;
  my Int $radix = $dividend.radix;
  my Str $carry = '0';
  my Str $rem   = '';
  my Bool $too-much = False;

  if $mult-and-sub eq 'separate' {
    my Arithmetic::PaperAndPencil::Number $pdt;
    $pdt = self!simple-mult(basic-level => $basic-level + 1
                         , l-md => $l-dr, c-md => $c-dr, multiplicand => $divisor
                         , l-mr => $l-qu, c-mr => $c-qu, multiplier   => $quotient
                         , l-pd => $l-pr, c-pd => $c-pr);
    if $dividend ☈< $pdt {
      return (True, '');
    }
    $rem = self!embedded-sub(basic-level => $basic-level + 3
                           , l-hi => $l-dd, c-hi => $c-dd, high => $dividend
                           , l-lo => $l-pr, c-lo => $c-pr, low  => $pdt
                           , l-re => $l-re, c-re => $c-re);
    return (False, $rem);
  }
  for 0 ..^ $divisor.chars -> $i {
    my Str $divisor-digit = $divisor.value.substr(* - $i - 1, 1);
    my Arithmetic::PaperAndPencil::Number $temp .= new(radix => $radix, value => $divisor-digit);
    $temp ☈×= $quotient;
    $action .= new(level => $basic-level + 6, label => 'MUL01'              , val3 => $temp.value
                 , r1l => $l-qu, r1c => $c-qu     , r1val => $quotient.value, val1 => $quotient.value
                 , r2l => $l-dr, r2c => $c-dr - $i, r2val => $divisor-digit , val2 => $divisor-digit
                 );
    self.action.push($action);
    if $carry ne '0' {
      $temp ☈+= Arithmetic::PaperAndPencil::Number.new(radix => $radix, value => $carry);
      $action .= new(level => $basic-level + 6, label => 'ADD02', val1 => $carry, val2 => $temp.value);
      self.action.push($action);
    }
    my Arithmetic::PaperAndPencil::Number $dividend-digit .= new(radix => $radix, value => $dividend.value.substr(* - $i - 1, 1));
    my Arithmetic::PaperAndPencil::Number $adjusted-dividend;
    my Arithmetic::PaperAndPencil::Number $rem-digit;
    ($adjusted-dividend, $rem-digit) = adjust-sub($dividend-digit, $temp);
    if $i == $divisor.chars - 1 {
      if $dividend.carry($i) ☈< $adjusted-dividend {
        $too-much = True;
      }
      else {
        $action .= new(level => $basic-level + 6, label => 'SUB02', val1  => $rem-digit.value, val2 => $adjusted-dividend.value
                                                           , r1l => $l-dd, r1c => $c-dd - $i, r1val => $adjusted-dividend.value
                     );
        self.action.push($action);
        $action .= new(level => $basic-level + 6, label => 'WRI04'   , val1  => $rem-digit.value
                     , w1l   => $l-re           , w1c   => $c-re - $i, w1val => $rem-digit.value
                     );
        self.action.push($action);
        $rem   = $rem-digit.value ~ $rem;
      }
    }
    else {
      $action .= new(level => $basic-level + 6, label => 'SUB02', val1  => $rem-digit.value, val2 => $adjusted-dividend.value
                                                         , r1l => $l-dd, r1c => $c-dd - $i, r1val => $adjusted-dividend.value
                   );
      self.action.push($action);
      my Str $label = 'WRI02';
      if $adjusted-dividend.carry.value eq '0' {
        $label = 'WRI03';
      }
      $action .= new(level => $basic-level + 6, label => $label, val1  => $rem-digit.value, val2 => $adjusted-dividend.carry.value
                              , w1l => $l-re, w1c => $c-re - $i, w1val => $rem-digit.value
                              );
      self.action.push($action);
      $rem   = $rem-digit.value ~ $rem;
      $carry = $adjusted-dividend.carry.value;
    }
  }
  return ($too-much, $rem);
}

method !embedded-div(Int :$l-dd, Int :$c-dd, Arithmetic::PaperAndPencil::Number :$dividend
                   , Int :$l-dr, Int :$c-dr, Arithmetic::PaperAndPencil::Number :$divisor
                   , Int :$l-qu, Int :$c-qu is copy
                   , Int :$basic-level
                   , Str :$type, Str :$mult-and-sub, :%mult-cache
                   , Bool :$stand-alone = False
                   ) {
  my Arithmetic::PaperAndPencil::Action $action;
  my Int $radix = $dividend.radix;
  my Arithmetic::PaperAndPencil::Number $zero .= new(:radix($radix), :value<0>);
  my Arithmetic::PaperAndPencil::Number $one  .= new(:radix($radix), :value<1>);
  my Int $len1  = $dividend.chars;
  my Int $len2  = $divisor .chars;
  my Int $col-r = $len2;     # column for the successive partial dividends and remainders
  my Int $len-dvd1 = 1;      # length of the part of the dividend used to compute the first candidate digit
  # yes, string comparison or left-aligned comparison, to know if we need a short hook or a long hook
  if $dividend ☈lt $divisor {
    $len-dvd1++;
    $col-r++;
  }
  my Int $bot      = $l-dd + 2;
  my Str $quotient = '';
  my Str $rem      = '';
  my Int $nb-dots  = $len1 - $col-r + 1;
  my Str $dots     = '.' x $nb-dots;
  $action .= new(level => $basic-level + 5, label => 'DRA01', w1l => $l-dr, w1c => $c-dr - $len2
                                                            , w2l => $bot , w2c => $c-dr - $len2);
  self.action.push($action);
  $action .= new(level => $basic-level + 5, label => 'WRI00'
               , w1l   => $l-dr, w1c => $c-dr               , w1val => $divisor.value
               , w2l   => $l-qu, w2c => $c-qu + $nb-dots - 1, w2val => $dots);
  self.action.push($action);
  $action .= new(level => $basic-level + 1, label => 'HOO01', w1l => $l-dd, w1c => $c-dd - $len1 + 1
                                                            , w2l => $l-dd, w2c => $c-dd - $len1 + $col-r);
  self.action.push($action);

  # computation
  if $type eq 'std' | 'cheating' {
    my Int $lin-d = $l-dd;     # line of the partial dividend
    my Int $delta = $len2 - 1; # how long we must shorten the divisor and the partial dividend to compute the quotient first candidate
    my Arithmetic::PaperAndPencil::Number $part-dvr1 = $divisor.carry($delta); # single-digit divisor to compute the quotient first candidate
    my Arithmetic::PaperAndPencil::Number $part-dvd .= new(:radix