Math::BaseArith - Perl extension for mixed-base number representation (like APL encode/decode)

- NAME
- SYNOPSIS
- DESCRIPTION
- FUNCTIONS
  - encode_base
  - decode_base
- DEPRECATED FUNCTIONS
- COMPATIBILITY
- EXPORT
- DEBUGGING
- LIMITATIONS
- SEE ALSO
- AUTHOR
- COPYRIGHT
- LICENSE

# NAME

Math::BaseArith - Perl extension for mixed-base number representation (like APL encode/decode)

# SYNOPSIS

      use Math::BaseArith qw( :all );

      encode_base( value, base_listref );

      decode_base( representation_listref, base_listref );

# DESCRIPTION

The inspiration for this module is a pair of functions in the APL programming language called encode (a.k.a. "represent" or "antibase)" and decode (a.k.a. base). Their principal use is to convert numbers from one number base to another. Mixed number bases are permitted.

In this perl implementation, the representation of a number in a particular number base consists of a list refence (listref) whose elements are the digit values in that base. For example, the decimal number 31 would be expressed in binary as a list of five ones with any number of leading zeros: [0, 0, 0, 1, 1, 1, 1, 1]. The same number expressed as three hexadecimal (base 16) digits would be [0, 1, 15], while in base 10 it would be [0, 3, 1]. Fifty-one inches would be expressed in yards, feet, inches as [1, 1, 3], an example of a mixed number base.

In the following description of encode_base and decode_base, Q will mean an abstract value or quantity, R will be its representation and B will define the number base. Q will be a perl scalar; R and B are perl lists. The values in R correspond to the radix values in B.

In the examples below, assume the output of print has been altered by setting $, = ' ' and that `=>` is your shell prompt.

# FUNCTIONS

## encode_base

Encode_base is used to represent a number in one or more number bases. The first argument is the number to be converted, and the second argument defines the base (or bases) to be used for the representation. Consider first the representation of a scalar in a single uniform number base:

        print encode_base( 2, [2, 2, 2, 2] )
        => 0 0 1 0

        print encode_base( 5, [2, 2, 2, 2] )
        => 0 1 0 1

        print encode_base( 13, [2, 2, 2, 2] )
        => 1 1 0 1

        print encode_base( 62, [16, 16, 16] )
        => 0 3 14

The second argument is called the base list. The length of the base list determines the number of digits in the representation of the first argument. No error occurs if the length is insufficient to give a proper representation of the number. Exploring this situation will suggest other uses of encode_base, and may clarify the use of encode_base with mixed number bases.

        # The representation of 75 in base 4
        print encode_base( 75, [4, 4, 4, 4] )
        => 1 0 2 3

        # At least four digits are needed for the full representation
        print encode_base( 75, [4, 4, 4] )
        => 0 2 3

        # If fewer elements are in the second argument,
        # leading digits do not appear in the representation.
        print encode_base( 75, [4, 4] )
        => 2 3

        # If the second argument is a one-element listref, encode_base is identical
        # to modulus (%)
        print encode_base( 75, [4] )
        => 3
        print encode_base( 76, [4] )
        => 0

        # The expression encode_base( Q, [0] ) always yields Q as the result
        print encode_base ( 75, [0] )
        => 75

        # This usage returns quotient and remainder
        print encode_base( 75, [0, 4] )
        => 18 3

        # The first quotient (18) is again divided by 4,
        # yielding a second quotient and remainder
        print encode_base( 75, [0, 4, 4] )
        => 4 2 3

        # The process is repeated again. Since the last quotient
        # is less than 4, the result is the same as encode_base(75,[4,4,4,4])
        print encode_base( 75, [0, 4, 4, 4] )
        => 1 0 2 3

Now consider a mixed number base: convert 175 inches into yards, feet, inches.

        # 175 inches is 14 feet, 7 inches (quotient and remainder).
        print encode_base( 175, [0, 12] )
        => 14 7

        # 14 feet is 4 yards, 2 feet,
        print encode_base( 14, [0, 3] )
        => 4 2

        # so 175 inches is 4 yards, 2 feet, 7 inches.
        print encode_base( 175, [0, 3, 12] )
        => 4 2 7

## decode_base

decode_base is used to determine the value of the representation of a quantity in some number base. If R is a list representation (perhaps produced by the encode_base function described above) of some quantity Q in a number base defined by the radix list B (i.e., `@R = encode_base($Q,@B)`, then the expression `decode_base(@R,@B)` yields `$Q`:

        print decode_base( [0, 0, 1, 0], [2, 2, 2, 2] )
        => 2

        print decode_base( [0, 1, 0, 1], [2, 2, 2, 2] )
        => 5

        print decode_base( [0, 3, 14], [16, 16, 16]
        => 62

The length of the representation list must be less than or equal to that of the base list.

        print decode_base( [1, 1, 1, 1], [2, 2, 2, 2] )
        => 15

        print decode_base( [1, 1, 1, 1], [2] )
        => 15

        print decode_base( [1], [2, 2, 2, 2] )
        => 15

        print decode_base( [1, 1, 1, 1], [2, 2, 2] )
        => (void)
        raises a LENGTH ERROR

As with the encode_base function, mixed number bases can be used:

        # Convert 4 yards, 2 feet, 7 inches to inches.
        print decode_base( [4, 2, 7], [0, 3, 12] )
        => 175

        # Convert 2 days, 3 hours, 5 minutes, and 27 seconds to seconds
        print decode_base( [2, 3, 5, 27], [0, 24, 60, 60] )
        => 183927

        # or to minutes.
        print decode_base( [2, 3, 5, 27], [0, 24, 60, 60] ) / 60
        => 3065.45

The first element of the radix list (second argument) is not used; it is required only to make the lengths match and so can be any value.

# DEPRECATED FUNCTIONS

encode
decode

Synonmous with encode_base/decode_base. Imported by default. See COMPATIBILITY for details.

# COMPATIBILITY

When this module was originally released on CPAN in 2002, it exported the functions encode and decode by default. These function names, however, are fairly common and so have a high probability of colliding in the global namespace with those from other modules. As of version 1.02, the functions were renamed encode_base and decode_base in order to better distinguish them.

For upward compatibility, encode/decode are provided as aliases for encode_base/decode_base and are still exported by default so scripts that include the module by:

        use Math::BaseArith;

will continue to work unchanged. See the EXPORT section for the preferred way to include the module from version 1.02 ownward.

Note the the keyword :old can be used to specify the old function names (encode/decode). The most likely use of this is to exclude them from the namespace so you can then include just one of them. For example, to get decode without encode you can do this:

        use Math::BaseArith qw( !:old decode );

But, rather than this approach, consider altering your code to use the new and preferred function names.

# EXPORT

As of version 1.02 and above, the preferred way to include this module is by using :all, or specifying you want either encode_base or decode_base:

        use Math::BaseArith ':all';
    or
        use Math::BaseArith 'encode_base';
    or
        use Math::BaseArith 'decode_base';

Do NOT include it without parameters, as that will automatically import the old function names encode/decode.

# DEBUGGING

Set the global variable $Math::BaseArith::DEBUG to print debugging information to STDERR.

If set to 1, function names and parameters are printed.

If set to 2, intermediate results are also printed.

# LIMITATIONS

The APL encode function allows both arguments to be a list, in which case the function evaluates in dot-product fashion, generating a matrix whose columns are the representation vectors for each value in the value list; i.e. a call such as encode_base([15,31,32,33,75],[4,4,4,4]) would generate the following matrix;

            0 0 0 0 1
            0 1 2 2 0
            3 3 0 0 2
            3 3 0 1 3

This version of encode_base supports only a scalar value as the first argument.

The APL version of decode support non-integer values. This version doesn't.

# SEE ALSO

https://aplwiki.com/wiki/Encode

https://aplwiki.com/wiki/Decode

# AUTHOR

Gary Puckering <jgpuckering@rogers.com>

# COPYRIGHT

Copyright (c) 2002, Gary Puckering. All rights reserved.

# LICENSE

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See:

http://www.gnu.org/copyleft/gpl.html

http://www.perl.com/language/misc/Artistic.html