### ----------------------------------------------------
### -- Arithmetic::PaperAndPencil
### -- Licenses: Artistic-2.0
### -- Authors: Jean Forget
### -- File: lib/Arithmetic/PaperAndPencil.rakumod
### ----------------------------------------------------
### -- Chunk 2 of 5
paration(factor => $divisor, limit => 'Z', cache => %div-cache);
    # the actual limit will be '9' for radix 10, 'F' for radix 16, etc. But 'Z' will give the same result
  }
  if $type eq 'cheating' | 'boat' {
    my Arithmetic::PaperAndPencil $dummy .= new;
    $dummy!preparation(factor => $divisor, limit => 'Z', cache => %div-cache);
  }

  # setup
  my Int $delta = $len2 - 1; # how long we must shorten the divisor and the partial dividend to compute the quotient first candidate
  my Int $lin-d = 0;         # line   for the successive partial dividends
  my Int $col-q = $len1 + 1; # column for the successive single-digit partial quotients
  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 {
    $col-r++;
    $len-dvd1++;
  }

  # computation
  if $type eq 'std' | 'cheating' | 'prepared' {
    $action .= new(level => 5, label => 'WRI00', w1l => 0, w1c => $len1        , w1val => $dividend.value);
    self.action.push($action);
    $action .= new(level => 5, label => 'DRA02', w1l => 0, w1c => $len1 + 1
                                               , w2l => 0, w2c => $len1 + $len2);
    self.action.push($action);
    my Arithmetic::PaperAndPencil::Number $quotient;
    my Arithmetic::PaperAndPencil::Number $rem;
    ($quotient, $rem) = self!embedded-div(l-dd => 0, c-dd => $len1        , dividend => $dividend
                                        , l-dr => 0, c-dr => $len1 + $len2, divisor  => $divisor
                                        , l-qu => 1, c-qu => $len1 + 1
                                        , basic-level => 0, type => $type, mult-and-sub => $mult-and-sub, mult-cache => %div-cache
                                        , stand-alone => True
                                        );
    self.action[* - 1].level = 0;
    given $result {
      when 'quotient'  { return   $quotient; }
      when 'remainder' { return   $rem; }
      when 'both'      { return ( $quotient, $rem); }
    }
  }
  if $type eq 'boat' {
    $action .= new(level => 6, label => 'WRI00', w1l => 0, w1c => $len1 + 1, w1val => $dividend.value ~ '{');
    self.action.push($action);
    $action .= new(level => 6, label => 'DRA02', w1l => 0, w1c => 1
                                               , w2l => 0, w2c => $len1);
    self.action.push($action);

    # arrays of line numbers per column
    my @lines-below = ( 1) xx ($len1 + 1);
    my @lines-above = (-1) xx ($len1 + 1);
    self!push-below($divisor, $col-r, @lines-below);

    $col-q++;
    my Str $quotient = '';
    my Str $rem      = '';
    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($radix), :value($dividend.value.substr(0, $col-r)));

    while $col-r ≤ $len1 {
      my Arithmetic::PaperAndPencil::Number $part-dvd1 = $part-dvd.carry($delta);  # single-digit dividend or 2-digit dividend to compute the quotient first candidate
      my Arithmetic::PaperAndPencil::Number $theo-quo  = $part-dvd1 ☈÷ $part-dvr1; # theoretical quotient first candidate
      my Arithmetic::PaperAndPencil::Number $act-quo;                              # actual quotient first candidate
      $rem = '';
      my Str $label;
      if $part-dvd ☈< $divisor {
        $theo-quo = $zero;
        $act-quo  = $zero;
      }
      else {
        $act-quo .= new(radix => $radix, value => %div-cache.keys.grep(-> $x { %div-cache{$x} ☈≤ $part-dvd }).max);
        $label = 'DIV03';
      }
      if $theo-quo.value eq '0' {
        # cannot flag $part-dvd and $divisor as read, because there are not on a single line.
        $action .= new(level => 5, label => 'DIV01', val1 => $part-dvd.value
                                                   , val2 => $divisor .value
                                                   , val3 => '0', w1l => 0, w1c => $col-q, w1val => '0');
        self.action.push($action);
        # striking the useless divisor
        for 0 ..^ $len2 -> $i {
          $action .= new(level => 6, label => 'WRI00', r1l => @lines-below[$col-r - $i] - 1, r1c => $col-r - $i, r1val => $divisor.value.substr(* -$i - 1, 1), r1str => True);
          self.action.push($action);
        }
        $rem = $part-dvd.value;
        $quotient ~= '0';
        ++$col-q;
        ++$col-r;
        if  $col-r ≤ $len1 {
          self!push-below($divisor, $col-r, @lines-below);
        }
        $part-dvd = Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value($rem ~ $dividend.value.substr($col-r - 1, 1)));
        next;
      }
      elsif $theo-quo.value eq $act-quo.value {
        # cannot flag $part-dvd and $divisor as read, because there are not on a single line.
        $action .= new(level => 5, label => 'DIV01', val1 => $part-dvd1.value
                                                   , val2 => $part-dvr1.value
                                                   , val3 => $theo-quo .value, w1l => 0, w1c => $col-q, w1val => $act-quo.value);
        self.action.push($action);
      }
      else {
        # cannot flag $part-dvd and $divisor as read, because there are not on a single line.
        $action .= new(level => 6, label => 'DIV01', val1 => $part-dvd1.value, val2 => $part-dvr1.value, val3 => $theo-quo.value);
        self.action.push($action);
        $action .= new(level => 5, label => $label, val1 => $act-quo.value, w1l => 0, w1c => $col-q, w1val => $act-quo.value);
        self.action.push($action);
      }
      my Str $carry = '0';
      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 ☈×= $act-quo;
        $action .= new(level => 6                            , label => 'MUL01'                                            , val3 => $temp.value
                     , r1l   => 1                            , r1c   => $col-q     , r1val => $act-quo.value               , val1 => $act-quo.value
                     , r2l   => @lines-below[$col-r - $i] - 1, r2c   => $col-r - $i, r2val => $divisor-digit, r2str => True, val2 => $divisor-digit
                     );
        self.action.push($action);
        if $carry ne '0' {
          $temp ☈+= Arithmetic::PaperAndPencil::Number.new(radix => $radix, value => $carry);
          $action .= new(level => 6, label => 'ADD02', val1 => $carry, val2 => $temp.value);
          self.action.push($action);
        }
        my Arithmetic::PaperAndPencil::Number $dividend-digit .= new(radix => $radix, value => $part-dvd.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 {
          $action .= new(level => 6, label => 'SUB02', val1  => $rem-digit.value, val2 => $adjusted-dividend.value
                     , r1l => @lines-above[$col-r - $i] + 1, r1c => $col-r - $i, r1val => $adjusted-dividend.value, r1str => True
                     );
          self.action.push($action);
          $action .= new(level => 6, label => 'WRI04'                            , val1  => $rem-digit.value
                       , w1l   => @lines-above[$col-r - $i]--, w1c => $col-r - $i, w1val => $rem-digit.value
                       );
          self.action.push($action);
          $rem   = $rem-digit.value ~ $rem;
        }
        else {
          $action .= new(level => 6, label => 'SUB02', val1  => $rem-digit.value   , val2  => $adjusted-dividend.value
                       , r1l   => @lines-above[$col-r - $i] + 1, r1c => $col-r - $i, r1val => $adjusted-dividend.value, r1str => True
                       );
          self.action.push($action);
          my Str $label = 'WRI02';
          if $adjusted-dividend.carry.value eq '0' {
            $label = 'WRI03';
          }
          $action .= new(level => 6, label => $label                             , val1  => $rem-digit.value, val2 => $adjusted-dividend.carry.value
                       , w1l   => @lines-above[$col-r - $i]--, w1c => $col-r - $i, w1val => $rem-digit.value
                       );
          self.action.push($action);
          $rem   = $rem-digit.value ~ $rem;
          $carry = $adjusted-dividend.carry.value;
        }
      }
      self.action[* - 1].level = 4;
      $quotient ~= $act-quo.value;
      ++$col-q;
      ++$col-r;
      if  $col-r ≤ $len1 {
        self!push-below($divisor, $col-r, @lines-below);
      }
      $part-dvd = Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value($rem ~ $dividend.value.substr($col-r - 1, 1)));
    }

    self.action[* - 1].level = 0;
    given $result {
      when 'quotient'  { return   Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value($quotient)); }
      when 'remainder' { return   Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value($rem)); }
      when 'both'      { return ( Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value($quotient))
                                , Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value($rem))); }
    }
  }

}

method square-root(Arithmetic::PaperAndPencil::Number $number
                 , Str :$mult-and-sub is copy = 'combined'
                 --> Arithmetic::PaperAndPencil::Number
                   ) {
  my Arithmetic::PaperAndPencil::Action $action;
  my Int $radix = $number.radix;

  $action .= new(level => 9, label => "TIT13", val1 => $number.value, val2 => $radix.Str);
  self.action.push($action);

  # set-up
  my Int $nb-dig = ($number.chars / 2).ceiling; # number of digits of the square root
  $action .= new(level => 6, label => 'WRI00', w1l => 0, w1c => 0, w1val => $number.value);
  self.action.push($action);
  $action .= new(level => 6, label => 'DRA01', w1l => 0, w1c => 0, w2l => 2, w2c => 0);
  self.action.push($action);
  $action .= new(level => 6, label => 'DRA02', w1l => 0, w1c => 1, w2l => 0, w2c => $nb-dig);
  self.action.push($action);
  $action .= new(level => 2, label => 'WRI00', w1l => 0, w1c => $nb-dig, w1val => '.' x $nb-dig);
  self.action.push($action);

  # first phase, square root proper
  my Int $col-first;
  my Str $remainder = '';
  my Arithmetic::PaperAndPencil::Number $partial-number = $number.carry(2 × ($nb-dig - 1));
  my Arithmetic::PaperAndPencil::Number $partial-root   = $partial-number.square-root;
  my Str $root = $partial-root.value;
  $action .= new(level => 5, label => 'SQR01'        , val1  => $partial-number.value, val2 => $root
                , r1l => 0, r1c => -2 × ($nb-dig - 1), r1val => $partial-number.value
                , w1l => 0, w1c => 1                 , w1val => $root
                );
  self.action.push($action);
  my Arithmetic::PaperAndPencil::Number $partial-square = $partial-root ☈× $partial-root;
  if $mult-and-sub eq 'combined' {
    $action .= new(level => 5, label => 'MUL01', val1 => $root, val2 => $root, val3 => $partial-square.value);
    self.action.push($action);
    my ($x, $y) = adjust-sub($partial-number.unit, $partial-square);
    $action .= new(level => 5, label => 'SUB02', val1 => $y.value
                                               , val2 => $x.value
                  );
    self.action.push($action);
    if $x.carry.value eq '0' {
      $action .= new(level => 5, label => 'WRI03'           , val1  => $y.value
                   , w1l   => 1, w1c   => -2 × ($nb-dig - 1), w1val => $y.value
                    );
      self.action.push($action);
      $remainder = $y.value;
    }
    else {
      $action .= new(level => 5, label => 'WRI02'           , val1  => $y.value, val2 => $x.carry.value
                   , w1l   => 1, w1c   => -2 × ($nb-dig - 1), w1val => $y.value
                    );
      self.action.push($action);
      my ($z, $t) = adjust-sub($partial-number.carry, $x.carry);
      $action .= new(level => 5, label => 'SUB01', val1 => $x.carry.value, val2 => $t.value, val3 => $z.value
                   , w1l   => 1, w1c   => -2 × $nb-dig + 1              , w1val => $t.value
                    );
      self.action.push($action);
      $remainder = $t.value ~ $y.value;
    }
  }
  else {
    $action .= new(level => 5, label => 'MUL01', val1 => $root, val2 => $root, val3 => $partial-square.value, w1l => 1, w1c => -2 × ($nb-dig - 1), w1val => $partial-square.value);
    self.action.push($action);
    $remainder = self!embedded-sub(basic-level => 0, l-hi => 0, c-hi => -2 × ($nb-dig - 1), high => $partial-number
                                                   , l-lo => 1, c-lo => -2 × ($nb-dig - 1), low  => $partial-square
                                                   , l-re => 2, c-re => -2 × ($nb-dig - 1));
  }
  my Arithmetic::PaperAndPencil::Number $divisor = $partial-root ☈+ $partial-root;
  $col-first = $divisor.chars;
  $action .= new(level => 3, label => 'ADD01'   , val1  => $partial-root.value, val2 => $partial-root.value, val3 => $divisor.value
                , r1l  => 0, r1c   => 1         , r1val => $partial-root.value
                , w1l  => 1, w1c   => $col-first, w1val => $divisor.value
                );
  self.action.push($action);

  my Arithmetic::PaperAndPencil::Number $zero     .= new(:radix($radix), :value<0>);
  my Arithmetic::PaperAndPencil::Number $one      .= new(:radix($radix), :value<1>);
  my Arithmetic::PaperAndPencil::Number $divisor1;

  # next phase, division
  my Int $bot      = 2; # bottom line number of the vertical line
  my Int $line-rem = 1; # line number of the partial remainder or partial dividend
  my Int $line-div = 1; # line number of the divisor
  if $mult-and-sub eq 'separate' {
    $line-rem = 2;
  }
  for 1 ..^ $nb-dig -> $i {
    my Int $pos = 2 × ($nb-dig - $i);
    my Str $two-digits = $number.value.substr(* - $pos, 2);
    $action .= new(level => 3        , label => 'DIV04'   , val1  => $two-digits
                  , r1l  => 0        , r1c   => 2 - $pos  , r1val => $two-digits
                  , w1l  => $line-rem, w1c   => 2 - $pos  , w1val => $two-digits
                  );
    self.action.push($action);
    $remainder ~= $two-digits;

    $partial-number .= new(radix => $radix, value => $remainder);
    my Arithmetic::PaperAndPencil::Number $part-dvr1 = $divisor.carry($divisor.chars - 1); # single-digit divisor to compute the quotient first candidate
    my Arithmetic::PaperAndPencil::Number $part-dvd1 = $partial-number.carry($i + $col-first - 1); # single-digit dividend or 2-digit dividend to compute the quotient first candidate
    my Arithmetic::PaperAndPencil::Number $theo-quo = $part-dvd1 ☈÷ $part-dvr1; # theoretical quotient first candidate
    my Arithmetic::PaperAndPencil::Number $act-quo;                             # actual quotient first candidate and then all successive candidates
    my Str $label;
    if $partial-number ☈≤ $divisor {
      $theo-quo = $zero;
      $act-quo  = $zero;
      $divisor1 .= new(radix => $radix, value => $divisor.value ~ '0');
    }
    elsif $theo-quo.chars == 2 {
      $act-quo  = max-unit($radix);
      $label = 'DIV02';
    }
    else {
      $act-quo  = $theo-quo;
    }
    my Bool $too-much = True; # we must loop with the next lower candidate
    if $theo-quo.value eq '0' {
      $action .= new(level => 5, label => 'DIV01', val1 => $part-dvd1.value, r1l => $line-rem, r1c => - $pos         , r1val => $part-dvd1.value
                                                 , val2 => $part-dvr1.value, r2l => $line-div, r2c => 0              , r2val => $part-dvr1.value
                                                 , val3 => '0'             , w1l => $line-div, w1c => $i + $col-first, w1val => '0');
      self.action.push($action);
      $too-much = False; # no need to loop on candidate values, no need to execute the mult-and-sub routine
      $remainder = $partial-number.value;
    }
    elsif $theo-quo.value eq $act-quo.value {
      $action .= new(level => 5, label => 'DIV01', val1 => $part-dvd1.value, r1l => $line-rem    , r1c => - $pos         , r1val => $part-dvd1.value
                                                 , val2 => $part-dvr1.value, r2l => $line-div    , r2c => 0              , r2val => $part-dvr1.value
                                                 , val3 => $theo-quo .value, w1l => $line-div    , w1c => $i + $col-first, w1val => $act-quo.value
                                                                           , w2l => $line-div + 1, w2c => $i + $col-first, w2val => $act-quo.value);
      self.action.push($action);
    }
    else {
      $action .= new(level => 6, label => 'DIV01', val1 => $part-dvd1.value, val2 => $part-dvr1.value, val3  => $theo-quo.value
                                                 , r1l  => $line-rem       , r1c  => - $pos          , r1val => $part-dvd1.value
                                                 , r2l  => $line-div       , r2c  => 0               , r2val => $part-dvr1.value);
      self.action.push($action);
      $action .= new(level => 5, label => $label, val1 => $act-quo.value, w1l => $line-div    , w1c => $i + $col-first, w1val => $act-quo.value
                                                                        , w2l => $line-div + 1, w2c => $i + $col-first, w2val => $act-quo.value);
      self.action.push($action);
    }
    my Str $rem;
    my Int $l-re;
    while $too-much {
      if $mult-and-sub eq 'separate' {
        $l-re = $line-rem + 2;
      }
      else {
        $l-re = $line-rem + 1;
      }
      if $bot < $l-re {
        $bot = $l-re;
        $action .= new(level => 5, label => 'DRA01', w1l => 0   , w1c => 0
                                                   , w2l => $bot, w2c => 0);
        self.action.push($action);
      }
      $divisor1 .= new(radix => $radix, value => $divisor.value ~ $act-quo.value);
      ($too-much, $rem) = self!mult-and-sub(l-dd => $line-rem    , c-dd => 2 - 2 × ($nb-dig - $i), dividend => $partial-number
                                          , l-dr => $line-div    , c-dr => $i + $col-first       , divisor  => $divisor1
                                          , l-qu => $line-div + 1, c-qu => $i + $col-first       , quotient => $act-quo
                                          , l-re => $l-re        , c-re => 2 - 2 × ($nb-dig - $i), basic-level => 0
                                          , l-pr => $line-rem + 1, c-pr => 2 - 2 × ($nb-dig - $i), mult-and-sub => $mult-and-sub);
      if $too-much {
        self.action[* - 1].level = 4;
        $act-quo ☈-= $one;
        $action .= new(level => 5, label => 'ERA01', w1l => $line-rem + 1, w1c => 0, w2l => $line-rem + 1, w2c => 1 - $number.chars);
        self.action.push($action);
        $action .= new(level => 4, label => 'DIV02', val1 => $act-quo.value, w1l => $line-div    , w1c => $i + $col-first, w1val => $act-quo.value
                                                                           , w2l => $line-div + 1, w2c => $i + $col-first, w2val => $act-quo.value);
        self.action.push($action);
      }
    }
    self.action[* - 1].level = 4;

    $action .= new(level => 5, label => 'WRI04', val1 => $act-quo.value, w1l => 0, w1c => $i + 1, w1val => $act-quo.value);
    self.action.push($action);
    $root ~= $act-quo.value;

    $divisor = $divisor1 ☈+ $act-quo;
    if $act-quo.value eq '0' {
      $action .= new(level => 3, label => 'ERA01', w1l => $line-div + 1, w1c => $i + $col-first, w2l => $line-div + 1, w2c => $i + $col-first);
      self.action.push($action);
    }
    elsif $i < $nb-dig - 1 {
      $remainder = $rem;
      $line-rem = $l-re;
      if $bot < $line-div + 3 {
        $bot = $line-div + 3;
      }
      $action .= new(level => 6, label => 'DRA01', w1l => 0, w1c => 0, w2l => $bot, w2c => 0);
      self.action.push($action);
      $action .= new(level => 6, label => 'DRA02', w1l => $line-div + 1, w1c => 1, w2l => $line-div + 1, w2c => $divisor.chars);
      self.action.push($action);
      $action .= new(level => 3, label => 'ADD01', r1l => $line-div    , r1c => $i + $col-first, r1val => $divisor1.value, val1 => $divisor1.value
                                                 , r2l => $line-div + 1, r2c => $i + $col-first, r2val => $act-quo.value , val2 => $act-quo.value
                                                 , w1l => $line-div + 2, w1c => $i + $col-first, w1val => $divisor.value , val3 => $divisor.value);
      self.action.push($action);
      $line-div += 2;
    }
  }

  self.action[* - 1].level = 0;
  return Arithmetic::PaperAndPencil::Number.new(:radix($radix), :value($root));
}

method conversion(Arithmetic::PaperAndPencil::Number :$number is copy
                , Int :$radix
                , Int :$nb-op    = 0
                , Str :$type     = 'mult'
                , Str :$div-type = 'std'
                , Str :$mult-and-sub is copy = 'combined'
                --> Arithmetic::PaperAndPencil::Number
                ) {
  unless 2 ≤ $radix ≤ 36 {
    die "Radix should be between 2 and 36, instead of $radix";
  }
  my Str $title = '';
  given $type {
    when 'mult'   { $title = 'TIT14' ; }
    when 'Horner' { $title = 'TIT14' ; }
    when 'div'    { $title = 'TIT16' ; }
    default       { die "Conversion type '$type' unknown, should be 'mult', 'Horner' or 'div'"; }
  }
  if $type eq 'div' and $div-type ne 'std' | 'cheating' | 'prepared' {
    die "Division type '$div-type' unknown, should be 'std', 'cheating' or 'prepared'";
  }
  if $type eq 'div' and $mult-and-sub ne 'combined' | 'separate' {
    die "Mult and sub type '$mult-and-sub' unknown, should be 'combined' or 'separate'";
  }
  if $type eq 'div' and $div-type eq 'std' {
    $mult-and-sub = 'combined';
  }
  if $type eq 'div' and $div-type eq 'prepared' {
    $mult-and-sub = 'separate';
  }
  my Arithmetic::PaperAndPencil::Action $action;
  my Int $old-radix = $number.radix;

  $action .= new(level => 9, label => $title, val1 => $number.value, val2 => $old-radix.Str, val3 => $radix.Str);
  self.action.push($action);

  if $radix == $old-radix or ($number.chars == 1 && $old-radix ≤ $radix) {
    $action .= new(level => 0, label => "CNV01", val1 => $number.value, val2 => $old-radix.Str, val3 => $radix.Str);
    self.action.push($action);
    return $number;
  }
  my %conv-cache;
  my Arithmetic::PaperAndPencil::Number $new-radix;
  my Arithmetic::PaperAndPencil::Number $zero .= new(:radix($old-radix), :value<0>);
  my %mult-cache;
  if $type eq 'mult' | 'Horner' {
    self!prep-conv($old-radix, $radix, %conv-cache, basic-level => 2);
  }
  else {
    %mult-cache = 0 => $zero, 1 => $new-radix;
    my %tmp-cache;
    self!prep-conv($radix, $old-radix, %tmp-cache, basic-level => 2);
    $new-radix = %tmp-cache<10>;
    for %tmp-cache.kv -> $new, $old {
      %conv-cache{$old.value} = $new;
    }
    if $div-type eq 'prepared' {
      my %tmp-cache;
      self!preparation(factor => $new-radix, limit => 'Z', cache => %mult-cache, basic-level => 2);
      self.action[* - 2].level = 1; # * - 2 to update the action **before** action NXP01
      # the actual limit will be '9' for radix 10, 'F' for radix 16, etc. But 'Z' will give the same result
    }
    if $div-type eq 'cheating' {
      my Arithmetic::PaperAndPencil $dummy .= new;
      $dummy!preparation(factor => $new-radix, limit => 'Z', cache => %mult-cache);
    }
  }

  my Arithmetic::PaperAndPencil::Number $result;
  if $type eq 'mult' | 'Horner' {
    my Str $old-digit = $number.value.substr(0,1);
    $result = %conv-cache{$old-digit};
    my Int $line   = 1;
    my Int $op     = 0;
    my Int $width  = %conv-cache<10>.chars;
    $action .= new(level => 3, label => "CNV02", val1 => $old-digit, val2 => $result.value
                                          , w1l => $line, w1c => 0, w1val => $result.value);
    self.action.push($action);
    for $number.value.substr(1).comb.kv -> $op1, $old-digit {
      # multiplication
      my Int $pos-sign =  %conv-cache<10>.chars max $result.chars;
      ++$line;
      $action .= new(level => 9, label => 'WRI00', w1l => $line, w1c => 0              , w1val => %conv-cache<10>.value
                                                 , w2l => $line, w2c => - $pos-sign - 1, w2val => '×');
      self.action.push($action);
      $action .= new(level => 5, label => 'DRA02', w1l => $line, w1c => 0, w2l => $line, w2c => - $width);
      self.action.push($action);
      if %conv-cache<10>.chars == 1 {
        $result = self!simple-mult(basic-level => 2
                                , l-md => $line - 1, c-md => 0, multiplicand => $result
                                , l-mr => $line    , c-mr => 0, multiplier   => %conv-cache<10>
                                , l-pd => $line + 1, c-pd => 0);
        $line++;
      }
      else {
        my %dummy-cache;
        $result = self!adv-mult(basic-level => 2
                                , l-md => $line - 1, c-md => 0, multiplicand => $result
                                , l-mr => $line    , c-mr => 0, multiplier   => %conv-cache<10>
                                , l-pd => $line + 1, c-pd => 0, cache        => %dummy-cache);
        $line += %conv-cache<10>.chars + 1;
      }
      if $width ≤ $result.chars {
        $width = $result.chars;
      }
      # addition
      my $added = %conv-cache{$old-digit};
      if $added.value eq '0' {
        $action .= new(level => 9, label => "CNV02", val1 => '0', val2  => '0');
        self.action.push($action);
      }
      else {
        $pos-sign =  %conv-cache<10>.chars max $width;
        ++$line;
        $action .= new(level => 9, label => "CNV02"       , val1 => $old-digit    , val2  => $added.value
                                            , w1l => $line, w1c => 0              , w1val => $added.value
                                            , w2l => $line, w2c => - $pos-sign - 1, w2val => '+');
        self.action.push($action);
        $action .= new(level => 5, label => 'DRA02', w1l =>   $line, w1c => 0, w2l => $line, w2c => - $width);
        self.action.push($action);
        my @added;
       