139 lines
3.1 KiB
PHP
139 lines
3.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Domain\QrCode\ValueObject;
|
|
|
|
/**
|
|
* Repräsentiert ein Galois-Feld GF(2^8) für Reed-Solomon-Berechnungen
|
|
*/
|
|
class GaloisField
|
|
{
|
|
// Generator-Polynom für GF(2^8)
|
|
private const PRIMITIVE_POLY = 0x11D; // x^8 + x^4 + x^3 + x^2 + 1
|
|
|
|
// Lookup-Tabellen für Multiplikation und Division
|
|
private array $expTable = [];
|
|
private array $logTable = [];
|
|
|
|
public function __construct()
|
|
{
|
|
$this->initTables();
|
|
}
|
|
|
|
/**
|
|
* Initialisiert die Lookup-Tabellen für schnelle Berechnungen
|
|
*/
|
|
private function initTables(): void
|
|
{
|
|
// Setze Tabellen-Größe
|
|
$this->expTable = array_fill(0, 256, 0);
|
|
$this->logTable = array_fill(0, 256, 0);
|
|
|
|
// Berechne die Exponentiation und Logarithmus-Tabellen
|
|
$x = 1;
|
|
for ($i = 0; $i < 255; $i++) {
|
|
$this->expTable[$i] = $x;
|
|
$this->logTable[$x] = $i;
|
|
|
|
// Multiplikation mit x in GF(2^8)
|
|
$x = ($x << 1) ^ ($x & 0x80 ? self::PRIMITIVE_POLY : 0);
|
|
$x &= 0xFF;
|
|
}
|
|
|
|
// Setze expTable[255] = expTable[0]
|
|
$this->expTable[255] = $this->expTable[0];
|
|
}
|
|
|
|
/**
|
|
* Addiert zwei Elemente im Galois-Feld
|
|
*/
|
|
public function add(int $a, int $b): int
|
|
{
|
|
return $a ^ $b; // In GF(2^8) ist Addition = XOR
|
|
}
|
|
|
|
/**
|
|
* Subtrahiert zwei Elemente im Galois-Feld
|
|
* In GF(2^8) ist Subtraktion = Addition = XOR
|
|
*/
|
|
public function subtract(int $a, int $b): int
|
|
{
|
|
return $this->add($a, $b);
|
|
}
|
|
|
|
/**
|
|
* Multipliziert zwei Elemente im Galois-Feld
|
|
*/
|
|
public function multiply(int $a, int $b): int
|
|
{
|
|
// Spezialfall: Null-Multiplikation
|
|
if ($a === 0 || $b === 0) {
|
|
return 0;
|
|
}
|
|
|
|
// Benutze Log-Tabellen für Multiplikation
|
|
$logA = $this->logTable[$a];
|
|
$logB = $this->logTable[$b];
|
|
$sumLog = ($logA + $logB) % 255;
|
|
|
|
return $this->expTable[$sumLog];
|
|
}
|
|
|
|
/**
|
|
* Dividiert zwei Elemente im Galois-Feld
|
|
*/
|
|
public function divide(int $a, int $b): int
|
|
{
|
|
if ($b === 0) {
|
|
throw new \DivisionByZeroError('Division by zero in Galois field');
|
|
}
|
|
|
|
if ($a === 0) {
|
|
return 0;
|
|
}
|
|
|
|
// Benutze Log-Tabellen für Division
|
|
$logA = $this->logTable[$a];
|
|
$logB = $this->logTable[$b];
|
|
$diffLog = ($logA - $logB + 255) % 255;
|
|
|
|
return $this->expTable[$diffLog];
|
|
}
|
|
|
|
/**
|
|
* Berechnet die Potenz eines Elements im Galois-Feld
|
|
*/
|
|
public function power(int $a, int $power): int
|
|
{
|
|
if ($a === 0) {
|
|
return 0;
|
|
}
|
|
|
|
if ($power === 0) {
|
|
return 1;
|
|
}
|
|
|
|
$logA = $this->logTable[$a];
|
|
$resultLog = ($logA * $power) % 255;
|
|
|
|
return $this->expTable[$resultLog];
|
|
}
|
|
|
|
/**
|
|
* Liefert die Logarithmus-Tabelle
|
|
*/
|
|
public function getLogTable(): array
|
|
{
|
|
return $this->logTable;
|
|
}
|
|
|
|
/**
|
|
* Liefert die Exponentiations-Tabelle
|
|
*/
|
|
public function getExpTable(): array
|
|
{
|
|
return $this->expTable;
|
|
}
|
|
}
|