0xDEADBEEF

RSS odkazy

IntArray.php

6. 6. 2013, aktualizováno: 29. 9. 2021 #kód

Unboxed int array in PHP

// advanced bit-twiddling

abstract class AbstractIntArray {
  protected int $length;
  protected string $data;
  protected int $typeSize;

  function __construct(int $length) {
    $this->length = $length;
    $this->data = str_repeat("\0", $length * $this->typeSize);
  }

  protected function checkIndex(int $idx) {
    if ($idx < 0 || $idx >= $this->length)
      throw new \OutOfRangeException("index out of range");
  }

  function getData() {
    return $this->data;
  }
}


/** store unsigned bytes */
final class ByteArray extends AbstractIntArray {
  protected int $typeSize = 1;

  function get(int $idx) {
    $this->checkIndex($idx);
    return ord($this->data[$idx]);
  }

  function put(int $idx, int $val) {
    $this->checkIndex($idx);

    if ($val < 0 || $val > 255)
      throw new \OutOfRangeException();

    $this->data[$idx] = chr($val);
  }
}

final class BitSet extends AbstractIntArray {
  protected int $length;
  private ByteArray $byteArray;

  function __construct(int $length) {
    $this->length = $length;
    $this->byteArray = new ByteArray(ceil($length / 8));
  }

  function get(int $idx) {
    $this->checkIndex($idx);

    $byteIdx = intdiv($idx, 8);
    $bitIdx  = $idx % 8;
    $byte = $this->byteArray->get($byteIdx);
    return (($byte >> $bitIdx) & 1) === 1;
  }

  function put(int $idx, bool $val) {
    $this->checkIndex($idx);

    $byteIdx = intdiv($idx, 8);
    $bitIdx  = $idx % 8;

    $byte = $this->byteArray->get($byteIdx);
    if ($val) {
      $byte |= (1 << $bitIdx);
    } else {
      $byte &= ~(1 << $bitIdx);
    }

    $this->byteArray->put($byteIdx, $byte & 0xff);
  }

  function getData() {
    return $this->byteArray->getData();
  }
}

final class Int32Array extends AbstractIntArray {
  protected int $typeSize = 4;

  function get(int $idx) {
    $this->checkIndex($idx);
    return unpack('V', $this->data, $idx * 4)[1];
  }

  function put(int $idx, int $val) {
    $this->checkIndex($idx);

    $bytes = pack('V', $val);
    $base = $idx * 4;
    for ($i = 0; $i < 4; $i++) {
      $this->data[$base + $i] = $bytes[$i];
    }
  }
}

final class Int64Array extends AbstractIntArray {
  protected int $typeSize = 8;

  function get(int $idx) {
    $this->checkIndex($idx);
    return unpack('P', $this->data, $idx * 4)[1];
  }

  function put(int $idx, int $val) {
    $this->checkIndex($idx);

    $bytes = pack('P', $val);
    $base = $idx * 8;
    for ($i = 0; $i < 8; $i++) {
      $this->data[$base + $i] = $bytes[$i];
    }
  }
}

Array with 1000000 integers:

píše k47 (@kaja47, k47)