function base_convert()

in src/math/compute.php [38:89]


function base_convert(string $value, int $from_base, int $to_base): string {
  invariant(
    $value !== '',
    'Unexpected empty string, expected number in base %d',
    $from_base,
  );

  invariant(
    $from_base >= 2 && $from_base <= 36,
    'Expected $from_base to be between 2 and 36, got %d',
    $from_base,
  );

  invariant(
    $to_base >= 2 && $to_base <= 36,
    'Expected $to_base to be between 2 and 36, got %d',
    $to_base,
  );

  invariant(\bcscale(0) === true, 'Unexpected bcscale failure');

  $from_alphabet = Str\slice(ALPHABET_ALPHANUMERIC, 0, $from_base);
  $result_decimal = '0';
  $place_value = \bcpow((string)$from_base, (string)(Str\length($value) - 1));
  foreach (Str\chunk($value) as $digit) {
    $digit_numeric = Str\search_ci($from_alphabet, $digit);
    invariant(
      $digit_numeric !== null,
      'Invalid digit %s in base %d',
      $digit,
      $from_base,
    );
    $result_decimal = \bcadd(
      $result_decimal,
      \bcmul((string)$digit_numeric, $place_value),
    );
    $place_value = \bcdiv((string)$place_value, (string)$from_base);
  }

  if ($to_base === 10) {
    return $result_decimal;
  }

  $to_alphabet = Str\slice(ALPHABET_ALPHANUMERIC, 0, $to_base);
  $result = '';
  do {
    $result = $to_alphabet[\bcmod($result_decimal, (string)$to_base)].$result;
    $result_decimal = \bcdiv((string)$result_decimal, (string)$to_base);
    } while (\bccomp($result_decimal, '0') > 0);

  return $result;
}