Skip to content

Commit a29f75d

Browse files
committed
speed up TrinaryLogic
- Split variadic arguments for and() and or(). Common case of single argument doesn't allocate an array. - Add static fields mirroring $registry to skip one level of indirection. - Numeric values chosen that & and | is the same as min and max. and()/or() optimized accordingly. - Inline trivial create() method. - Remove one unnecessary access to registry in method create(). this loop runs 1.8x faster (php 8.4.16, jit off) $t = TrinaryLogic::createYes(); for ($i = 10_000_000; $i--;) { $t = $t->and(TrinaryLogic::createYes()); } before: 1.125 s now: 0.616 s
1 parent cd5401f commit a29f75d

File tree

1 file changed

+21
-26
lines changed

1 file changed

+21
-26
lines changed

src/TrinaryLogic.php

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,35 @@
1414
*/
1515
final class TrinaryLogic
1616
{
17+
private const YES = 3;
18+
private const MAYBE = 1;
19+
private const NO = 0;
1720

18-
private const YES = 1;
19-
private const MAYBE = 0;
20-
private const NO = -1;
2121

2222
/** @var self[] */
2323
private static array $registry = [];
2424

25+
private static self $YES;
26+
private static self $MAYBE;
27+
private static self $NO;
28+
2529
private function __construct(private int $value)
2630
{
2731
}
2832

2933
public static function createYes(): self
3034
{
31-
return self::$registry[self::YES] ??= new self(self::YES);
35+
return self::$YES ??= (self::$registry[self::YES] ??= new self(self::YES));
3236
}
3337

3438
public static function createNo(): self
3539
{
36-
return self::$registry[self::NO] ??= new self(self::NO);
40+
return self::$NO ??= (self::$registry[self::NO] ??= new self(self::NO));
3741
}
3842

3943
public static function createMaybe(): self
4044
{
41-
return self::$registry[self::MAYBE] ??= new self(self::MAYBE);
45+
return self::$MAYBE ??= (self::$registry[self::MAYBE] ??= new self(self::MAYBE));
4246
}
4347

4448
public static function createFromBoolean(bool $value): self
@@ -49,8 +53,7 @@ public static function createFromBoolean(bool $value): self
4953

5054
private static function create(int $value): self
5155
{
52-
self::$registry[$value] ??= new self($value);
53-
return self::$registry[$value];
56+
return self::$registry[$value] ??= new self($value);
5457
}
5558

5659
/**
@@ -89,17 +92,13 @@ public function toBooleanType(): BooleanType
8992
return new ConstantBooleanType($this->value === self::YES);
9093
}
9194

92-
public function and(self ...$operands): self
95+
public function and(self $operand, self ...$rest): self
9396
{
94-
$min = $this->value;
95-
foreach ($operands as $operand) {
96-
if ($operand->value >= $min) {
97-
continue;
98-
}
99-
100-
$min = $operand->value;
97+
$min = $this->value & $operand->value;
98+
foreach ($rest as $operand) {
99+
$min &= $operand->value;
101100
}
102-
return self::create($min);
101+
return self::$registry[$min] ??= new self($min);
103102
}
104103

105104
/**
@@ -129,17 +128,13 @@ public function lazyAnd(
129128
return $this->and(...$results);
130129
}
131130

132-
public function or(self ...$operands): self
131+
public function or(self $operand, self ...$rest): self
133132
{
134-
$max = $this->value;
135-
foreach ($operands as $operand) {
136-
if ($operand->value < $max) {
137-
continue;
138-
}
139-
140-
$max = $operand->value;
133+
$max = $this->value | $operand->value;
134+
foreach ($rest as $operand) {
135+
$max |= $operand->value;
141136
}
142-
return self::create($max);
137+
return self::$registry[$max] ??= new self($max);
143138
}
144139

145140
/**

0 commit comments

Comments
 (0)