# base($number, $inbase, $outbase) transforms a number from one
#      base to another.
#
# Examples:
#        base(17, 9, 2)     converts 17  (base 9)  to base 2:  10000.
#        base("fff", 16, 3) converts fff (base 16) to base 3:  12121200.
#        base("g", 17, 10)  converts g   (base 17) to base 10: 16.
#
# Uses the logbase() function defined below.
#
# Returns undef on error.
#
sub base {
    my ($number, $inbase, $outbase) = @_;
    my ($realnum, $output, $i, $digit);

    # Convert the number (which might have letters) to lowercase.
    $number = lc($number);

    # Return undef (or an empty list) if the base is too weird.
    return if $inbase > 36 or $outbase > 36 or
              $inbase < 2  or $outbase < 2;

    # Convert $number from base $inbase to base 10.
    for $digit (reverse split(//, $number)) {
        $digit = ord($digit) - 87 if ord($digit) > 96;
        return if $digit >= $inbase;
        $realnum += $digit * ($inbase ** $i++);
    }

    # Convert the number from base 10 to $outbase.
    # logbase() is defined below.
    for ($i = int(logbase($realnum, $outbase)); $i >= 0; $i--) {
        $digit = int($realnum / ($outbase ** $i));
        $realnum -= $digit * ($outbase ** $i);
        $digit = ord($digit + 49) if ord($digit) > 57;
        $output .= $digit;
    }

    return $output;
}

#        base(17, 9, 2)     converts 17  (base 9)  to base 2:  10000.
print base(17, 9, 2), "\n";
#        base("fff", 16, 3) converts fff (base 16) to base 3:  12121200.
print base("fff", 16, 3), "\n";
#        base("g", 17, 10)  converts g   (base 17) to base 10: 16.
print base("g", 17, 10), "\n";


# logbase($number, $base) computes the logarithm of number in base $base.
#
# Example: logbase(243, 3) is 5, because 3 ** 5 is 243.
#
sub logbase {
    my ($number, $base) = @_;
    return if $number <= 0 or $base <= 0 or $base == 1;
    return log($number) / log($base);
}

