markrogoyski / math-php

Powerful modern math library for PHP: Features descriptive statistics and regressions; Continuous and discrete probability distributions; Linear algebra with matrices and vectors, Numerical analysis; special mathematical functions; Algebra
MIT License
2.32k stars 238 forks source link

Create an ArbitraryInteger from a novel alphabet. #419

Open Beakerboy opened 2 years ago

Beakerboy commented 2 years ago

In BaseEncoderDecoder::createArbitraryInteger(), I state in the description:

Create an ArbitraryInteger from a number string in novel number bases and alphabets

It looks like I may have oversold this function a little. Sure, it can create from novel alphabets, but those alphabets have to be an alphabet of successive ASCII characters. A number in RFC3548_BASE64_FILE_SAFE format can be output using the functions, but not created because the alphabet is discontinuous in its ASCII mapping. We (I) need to add a function something like this:

public function ArbitraryIntegerFromAlphabet(string $number, string $alphabet): ArbitraryInteger
{
    // Check if $number contains any characters that are not in $alphabet
    // Check if $alphabet has any duplicated characters
    // Check that $alphabet is not greater than 256 characters (if so, the check above would be violated, maybe not if unicode?)
    // Check that $alphabet is ASCII, $number too?
    $flipped_alphabet = \array_filp($alphabet);
    $chars = str_split($number);
    $zero_offset = '';
    foreach ($chars as $char) {
        $zero_offset .=  \chr($flipped_alphabet[$char]);
    }
    return self::createArbitraryInteger($zero_offset, count($alphabet), \chr(0));
}

With this, a base two number where the characters are 't' and 'f' can be created as

ArbitraryIntegerFromAlphabet('tftfttffftftft', 'ft');

All 'f' characters are converted to \chr(0) and all 't' characters to \chr(1). Then the createArbitrayInteger function can create the object. The integer representation of a Bitcoin address can be made using:

$bitcoin_base58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
$genesis_block_address = '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa';
$Integer = ArbitraryIntegerFromAlphabet($genesis_block_address, $bitcoin_base58);