Daily Archives: September 30, 2015

A Mersenne_Twister Implementation in PHP

I am confused. I found this great Mersenne_Twister implementation to compensate for the fact the at mt_srand() and mt_rand() don’t generate predictable sequences since PHP 5.2.1. From www.php.net:

The Mersenne Twister implementation in PHP now uses a new seeding algorithm by Richard Wagner. Identical seeds no longer produce the same sequence of values they did in previous versions. This behavior is not expected to change again, but it is considered unsafe to rely upon it nonetheless.

What confuses me is that I cannot figure out where I found this code. In my notes have it at www.php.net in the comments – but I cannot re-find that comment on mt_srand() entry – perhaps it was deleted.

So that it is not lost, I reproduce it here.


class Mersenne_Twister
{
  private $state = array ();
  private $index = 0;

  public function __construct($seed = null) {
    if ($seed === null)
      $seed = mt_rand();

    $this->setSeed($seed);
  }

  public function setSeed($seed) {
    $this->state[0] = $seed & 0xffffffff;

    for ($i = 1; $i < 624; $i++) {
      $this->state[$i] = (((0x6c078965 * ($this->state[$i - 1] ^ ($this->state[$i - 1] >> 30))) + $i)) & 0xffffffff;
    }

    $this->index = 0;
  }

  private function generateTwister() {
    for ($i = 0; $i < 624; $i++) {
      $y = (($this->state[$i] & 0x1) + ($this->state[$i] & 0x7fffffff)) & 0xffffffff;
      $this->state[$i] = ($this->state[($i + 397) % 624] ^ ($y >> 1)) & 0xffffffff;

      if (($y % 2) == 1) {
        $this->state[$i] = ($this->state[$i] ^ 0x9908b0df) & 0xffffffff;
      }
    }
  }

  public function getNext($min = null, $max = null) {
    if (($min === null && $max !== null) || ($min !== null && $max === null))
      throw new Exception('Invalid arguments');

    if ($this->index === 0) {
      $this->generateTwister();
    }

    $y = $this->state[$this->index];
    $y = ($y ^ ($y >> 11)) & 0xffffffff;
    $y = ($y ^ (($y << 7) & 0x9d2c5680)) & 0xffffffff;
    $y = ($y ^ (($y << 15) & 0xefc60000)) & 0xffffffff;
    $y = ($y ^ ($y >> 18)) & 0xffffffff;

    $this->index = ($this->index + 1) % 624;

    if ($min === null && $max === null)
      return $y;

    $range = abs($max - $min);

    return min($min, $max) + ($y % ($range + 1));
  }
}

I also wrote a PHP Mersenne_Shuffle() function called that produces a predictable shuffle using the Mersenne_Twister().


// http://stackoverflow.com/questions/6557805/randomize-a-php-array-with-a-seed
// http://bost.ocks.org/mike/algorithms/#shuffling
function Mersenne_Shuffle($arr, $seed=-1)
{
    if ( $seed == -1 ) return $arr;
    $mt = new Mersenne_Twister($seed);
    $new = $arr;
    for ($i = count($new) - 1; $i > 0; $i--)
    {
        $j = $mt->getNext(0,$i);
        $tmp = $new[$i];
        $new[$i] = $new[$j];
        $new[$j] = $tmp;
    }
    return $new;
}

Why PHP chose to break this in the name of progress I don’t understand. Ah well. Here is the workaround. If I need to acknowledge someone – let me know.

Using git subtrees in Tsugi

I am starting to build PHP and Java implementations of my Tsugi libraries and I want to share the static content (JavaScript, CSS, etc) between them all so they all are effectively testing the same core code as much as possible and I don’t want to change things two places. Here are my repos:

I toyed with submodules – but adding “–recursive” to all “git clones” seemes icky and it seemed ike “git pull” in the world of submodules was clunky – I did not even bother to figure it out before I gave up on submodules.

Goodbye git submodules hello git subtrees.

I read these blog posts to learn up:

Conviently in the modern version of git – it knows how to blast submodules so undoing my use of sub modules was a simple matter of:

git rm static
git push

Of course my repo was broken at this point so I quickly needed to add the static folder back as a subtree in with these commands. Note that I did not do the “remote-add” and just put hte full URL if the repo in place of the remote on the subtree commands. I will add the remote if I start pushing from tsugi to tsugi-static.

$ git subtree add --prefix=static/ https://github.com/csev/tsugi-static master
git fetch tsugi-static master
warning: no common commits
remote: Counting objects: 159, done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 159 (delta 3), reused 0 (delta 0), pack-reused 150
Receiving objects: 100% (159/159), 1.14 MiB | 0 bytes/s, done.
Resolving deltas: 100% (31/31), done.
From https://github.com/csev/tsugi-static
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> tsugi-static/master
Added dir 'static'

$ git push
Counting objects: 160, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (125/125), done.
Writing objects: 100% (160/160), 1.20 MiB | 0 bytes/s, done.
Total 160 (delta 32), reused 149 (delta 30)
To https://github.com/csev/tsugi.git
   55ec2c7..87c5f1d  master -> master
0587388153:tsugi csev$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Just to be sure I putched my clone and re-cloned tsugi and poof! My static content was there in a folder just like I like it – no –recursive required.

On to the git pull when the subtree repo is updated..

In general I will make changes in a separately checked out version of tsugi-static, push them up there and then do a pull into tsugi using these commands. It is a merge – but as long as you keep your local copy of the subtree clean – it is a trivial merge. Of course then you need to push to origin master since subtrees have a full copy of the subtree in the repo:

$ git subtree pull --prefix=static https://github.com/csev/tsugi-static master
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 2), reused 3 (delta 2), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/csev/tsugi-static
 * branch            master     -> FETCH_HEAD
Merge made by the 'recursive' strategy.
 static/README.md | 8 --------
 1 file changed, 8 deletions(-)

$ git push origin master
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 858 bytes | 0 bytes/s, done.
Total 5 (delta 2), reused 0 (delta 0)
To https://github.com/csev/tsugi.git
   87c5f1d..6397cb5  master -> master

And that is all there is to it.

This tricky subtree pull is only for the repo that pulled in the subtree initially. Any forks of that repo are unaware that the “static” folder is a subtree and for them “git pull” updates both the repo and the subtree automatically.