Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What's wrong? #18

Open
EthraZa opened this issue Jul 7, 2016 · 17 comments
Open

What's wrong? #18

EthraZa opened this issue Jul 7, 2016 · 17 comments

Comments

@EthraZa
Copy link

EthraZa commented Jul 7, 2016

Hi.
Using the example numbers:

$optimus = new Jenssegers\Optimus\Optimus(1580030173, 59260789, 1163945558);

$id = "1000000000"; //10 digits
$encoded = $optimus->encode($id);
$original = $optimus->decode($encoded);
print_r(array($id, $encoded, $original), true); 
// ["1000000000", 1768948822, 1000000000]

$id = "10000000000"; //11 digits
$encoded = $optimus->encode($id);
$original = $optimus->decode($encoded);
print_r(array($id, $encoded, $original), true); 
// ["10000000000", 2109978198, 856559616]


$id = "100000000000"; //12 digits
$encoded = $optimus->encode($id);
$original = $optimus->decode($encoded);
print_r(array($id, $encoded, $original), true); 
// ["100000000000", 1163945558, 0]

My IDs are MySQL's bigint that can be 20 digits long! Optimus is not for me?
What am I missing? There is a length limit?


php -v
PHP 5.3.2-1ubuntu4.30 with Suhosin-Patch (cli) (built: Apr 17 2015 15:01:29)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies

uname -a
Linux picard 2.6.32-74-server #142-Ubuntu SMP Tue Apr 28 10:12:19 UTC 2015 x86_64 GNU/Linux


I had to change line 108 at src/Optimus.php to get it working:

if (! in_array($mode, [static::MODE_GMP, static::MODE_NATIVE])) {

to

if (! in_array($mode, array(static::MODE_GMP, static::MODE_NATIVE)) ) {

Thanks in advance.

@fabiandev
Copy link

You are using PHP 5.3 which was released in 2009 and where support ended for in 2014.
Short array syntax ([] instead of array()) was introduced in PHP 5.4.

This package requires PHP >= 5.4 if you have a look at the composer.json file.

Anyway, support for PHP 5.4 ended in 2015, and 5.5 was actually supported until yesterday, so I'd recommend you to upgrade to 5.6 if you can.

@EthraZa
Copy link
Author

EthraZa commented Jul 11, 2016

Yes I noticed the sintaxe, because of that I have to change line 108.
So are you saying that even changing this line and it seeming as it's working, it will not work properly because of the PHP version?

@fabiandev
Copy link

I'm not the author of this package, but as it requires PHP >= 5.4 you may experience unexpected behavior with a lower version. What you can do is to run the tests and check if they pass.

@pjebs
Copy link

pjebs commented Jul 22, 2016

Optimus only works if the id is less than max int. it is designed that way. If you want, you can fork the library and increase MAX_INT not 9223372036854775807.
#17

@jenssegers
Copy link
Owner

We could add a method to override the internal max integer value.

@tamhv
Copy link

tamhv commented Feb 8, 2017

@jenssegers @pjebs i did try to increase MAX_INT in Optimus.php but it doesn't work

#uname -a
Linux web2 2.6.32-573.8.1.el6.x86_64 #1 SMP Tue Nov 10 18:01:38 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
...
const MAX_INT = 100000000000; //12 digits
...
$ob = new Jenssegers\Optimus\Optimus(615006283, 1261799779, 332484960);
$id = "10000000000"; //11 digits
$encoded = $ob->encode($id);
$original = $ob->decode($encoded);
print_r(array($id, $encoded, $original));

Result:

Array
(
    [0] => 10000000000
    [1] => 30528477536
    [2] => 73155108864
)

@pjebs
Copy link

pjebs commented Feb 8, 2017

are you sure const MAX_INT = 100000000000; //12 digits is within the class. I thikn jensegers added a method to override the default in new version.

@tamhv
Copy link

tamhv commented Feb 8, 2017

@pjebs I'm very sure. I also checked over the source but no method to override default MAX_INT. I saw your comments on repo optimus-go, it seems very easy to change, but i have no idea why it doesn't work on my test. Thank you!

v0.2.2

php -v
PHP 5.6.30 (cli) (built: Jan 19 2017 10:06:11) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
...
<?php namespace Jenssegers\Optimus;

use InvalidArgumentException;

class Optimus
{
    /**
     * @var int
     */
    const MAX_INT = 100000000000;

    /**
     * @var string
     */
    private static $mode;

    /**
     * Use GMP extension functions.
     */
    const MODE_GMP = 'gmp';

    /**
     * Use native PHP implementation.
     */
    const MODE_NATIVE = 'native';

    /**
     * @var int
     */
    private $prime;

    /**
     * @var int
     */
    private $inverse;

    /**
     * @var int
     */
    private $xor;

    /**
     * @param int $prime
     * @param int $xor
     * @param int $inverse
     */
    public function __construct($prime, $inverse, $xor = 0)
    {
        $this->prime = (int) $prime;
        $this->inverse = (int) $inverse;
        $this->xor = (int) $xor;

        // Check which calculation mode should be used.
        if (static::$mode === null) {
            static::$mode = PHP_INT_SIZE === 4 ? static::MODE_GMP : static::MODE_NATIVE;
        }
    }

    /**
     * Encode an integer.
     *
     * @param  int $value
     * @return int
     */
    public function encode($value)
    {
        if (! is_numeric($value)) {
            throw new InvalidArgumentException('Argument should be an integer');
        }

        switch (static::$mode) {
            case self::MODE_GMP:
                return (gmp_intval(gmp_mul($value, $this->prime)) & static::MAX_INT) ^ $this->xor;

            default:
                return (((int) $value * $this->prime) & static::MAX_INT) ^ $this->xor;
        }
    }

    /**
     * Decode an integer.
     *
     * @param  int $value
     * @return int
     */
    public function decode($value)
    {
        if (! is_numeric($value)) {
            throw new InvalidArgumentException('Argument should be an integer');
        }

        switch (static::$mode) {
            case static::MODE_GMP:
                return gmp_intval(gmp_mul((int) $value ^ $this->xor, $this->inverse)) & static::MAX_INT;

            default:
                return (((int) $value ^ $this->xor) * $this->inverse) & static::MAX_INT;
        }
    }

    /**
     * Set the internal calculation mode (mainly used for testing).
     *
     * @param string $mode
     */
    public function setMode($mode)
    {
        if (! in_array($mode, [static::MODE_GMP, static::MODE_NATIVE])) {
            throw new InvalidArgumentException('Unkown mode: ' . $mode);
        }

        static::$mode = $mode;
    }
}

@pjebs
Copy link

pjebs commented Feb 8, 2017

Try essentially creating your own Optimus class that is exactly the same as the official one and then a) test if your test works and b) if your changed MAX_INT is reflected inside the class

@tamhv
Copy link

tamhv commented Feb 9, 2017

hi @pjebs i forked this repo, change MAX_INT,.. and made a test https://github.com/tamhv/optimus/blob/master/tests/CustomTest.php

//        const MAX_INT = 1000000000000;//13 digits
//
//        var_dump(\Jenssegers\Optimus\Energon::generatePrime());//204370143667
//        ./optimus spark 204370143667
//        Prime: 204370143667
//        Inverse: 676326779
//        Random: 1054205207
//
//        new Optimus(204370143667, 676326779, 1054205207);


        $ob = new Optimus(204370143667, 676326779, 1054205207);

        $id = 10000000000; //11 digits

        $encoded = $ob->encode($id);
        $original = $ob->decode($encoded);

        print_r([$id, $encoded, $original]);

//        Array
//        (
//            [0] => 10000000000
//            [1] => 722264515863
//            [2] => 446746066944
//        )


//         encode?
//         (((int) $value * $this->prime) & static::MAX_INT) ^ $this->xor;
//         (((int) 10000000000 * 204370143667) & 1000000000000) ^ 1054205207; //722264515863
//
//         decode?
//         (((int) $value ^ $this->xor) * $this->inverse) & static::MAX_INT;
//         (((int) 722264515863 ^ 1054205207) * 676326779) & 1000000000000; //446746066944

It still doesn't work, can you please have a look and correct me if anything wrong.
Thank you in advance.

@pjebs
Copy link

pjebs commented Feb 9, 2017

Can you try the example values in the ReadMe. See if you can recreate those results.

@pjebs
Copy link

pjebs commented Feb 9, 2017

I suspect const MAX_INT = 1000000000000;//13 digits can't just be any number. I think it has to be a power of 2 (not documented).

@tamhv
Copy link

tamhv commented Feb 9, 2017

it doesn't match (PRIME * INVERSE) & MAXID == 1, so there is some thing wrong with optimus spark . It gave me wrong PRIME and INVERSE if MAX_INT greater than 2147483647.

I did try with MAX_INT=8589934593 and ((366693263 * 620196719) & 8589934593) == 1 but still not work:

$ob = new Optimus(366693263, 620196719, 1066048704);
$id = 5; //11 digits

$encoded = $ob->encode($id);
$original = $ob->decode($encoded);

 print_r([$id, $encoded, $original]);
Array
(
    [0] => 5
    [1] => 1066048705
    [2] => 1
)

@ConnorVG
Copy link

ConnorVG commented Jun 5, 2017

@tamhv, @pjebs take a look at #29 – that should help.

@ElfSundae
Copy link
Contributor

It seems the max number can only be 2147483647? even 64bit system with PHP 7.1
I'm not sure this issue is from this package code or the limitation of hashing algorithm used.

@chinnalamahesh
Copy link

Installed optimus package and used the below code

$optimus = new Optimus(158003, 59260, 1163);

$value = "10000";
$encoded = $optimus->encode($value);
$original = $optimus->decode($encoded);
print_r(array($value, $encoded, $original), true);

i am getting this error :: Call to undefined function Jenssegers\Optimus\gmp_intval()

@pjebs
Copy link

pjebs commented Dec 18, 2017

you prob need gmt php extension installed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants