BitSet 
Drop in replacement for bitset extension.
Also try to reproduce the implementation details of the extension.
API
The API is the same as in the extension, with the addition of a Factory to use the best available implementation.
Factory:
Factory::create($bits = 64): BitSet
Factory::fromArray(array $array): BitSet
Factory::fromRawValue(string $raw): BitSet
Factory::fromString(string $str): BitSet
BitSet adapters:
BitSet::set($from = -1, $to = 0): void
BitSet::get($index): boolean
BitSet::clear($from = -1, $to = 0): void
BitSet::size(): int
BitSet::cardinality(): int
BitSet::isEmpty(): boolean
BitSet::length(): int
BitSet::andNotOp(BitSet $set): void
BitSet::andOp(BitSet $set): void
BitSet::orOp(BitSet $set): void
BitSet::xorOp(BitSet $set): void
BitSet::nextClearBit($index): int|false
BitSet::nextSetBit($index): int|false
BitSet::previousClearBit($index): int|false
BitSet::previousSetBit($index): int|false
BitSet::getRawValue(): string
BitSet::toArray(): array
Usage
Factory:
<?php
use Adagio\BitSet\Factory;
$b = Factory::create();
var_dump($b->__toString());
$b = Factory::create(8);
var_dump($b->__toString());
$b = Factory::fromArray([1, 6, 17, 2]);
var_dump($b->__toString());
var_dump($b->toArray());
$b = Factory::fromRawValue(base64_decode('IA=='));
var_dump($b->__toString());
var_dump(base64_encode($b->getRawValue()));
$b = Factory::fromString('0110');
var_dump($b->__toString());
Adapters:
<?php
use Adagio\BitSet\Factory;
$b = Factory::create();
$b->set(5);
var_dump($b->get(5));
var_dump($b->get(20));
$b->set(20);
var_dump($b->get(20));
$b = Factory::create(8);
var_dump($b->__toString());
$b->set(2);
$b->set(2, 4);
$b->set(0);
var_dump($b->__toString());
$b->set();
var_dump($b->__toString());
$b = Factory::create();
$b->set(50);
$b->set(63);
var_dump($b->get(50));
$b->clear(50);
var_dump($b->get(50));
$b = Factory::create();
$b->set(5);
$b->set(33);
$b->set(63);
var_dump($b->cardinality());
$b = Factory::create();
var_dump($b->size());
$b = Factory::create(8);
$b->set(2, 4);
$b->clear(3);
var_dump($b->size());
$b = Factory::create();
var_dump($b->isEmpty());
$b->set(32);
var_dump($b->isEmpty());
$b = Factory::create();
$b->set(33);
var_dump($b->length());
$b = Factory::create();
$c = Factory::create();
$b->set(2);
$b->set(6);
$c->set(2);
$b->andNotOp($c);
var_dump($b->__toString());
$b = Factory::create();
$b->set(2);
$b->set(6);
$c = Factory::create();
$c->set(2);
$c->set(50);
$b->andOp($c);
var_dump($b->__toString());
$b = Factory::create();
$c = Factory::create();
$b->set(2);
$b->set(6);
$c->set(2);
$b->xorOp($c);
var_dump($b->__toString());
$b = Factory::create();
$b->set(20);
var_dump($b->nextClearBit(20));
var_dump($b->nextClearBit(18));
$b = Factory::create();
$b->set(20);
var_dump($b->nextSetBit(20));
var_dump($b->nextSetBit(18));
$b = Factory::create();
$c = Factory::create();
$b->set(2);
$b->set(6);
$c->set(2);
$c->set(9);
$b->orOp($c);
var_dump($b->__toString());
$b = Factory::create();
$b->set(20);
$b->set(18);
var_dump($b->previousClearBit(20));
var_dump($b->previousClearBit(18));
$b = Factory::create();
$b->set(20);
$b->set(18);
var_dump($b->previousSetBit(20));
var_dump($b->previousSetBit(18));
$b->set(1);
var_dump($b->previousSetBit(5));
$b = Factory::create();
$b->set(5);
$b->set(22);
var_dump($b->toArray());
$b = Factory::create(8);
$b->set(5);
var_dump(base64_encode($b->getRawValue()));
var_dump(bin2hex($b->getRawValue()));