Files
michaelschiemer/src/Domain/QrCode/ValueObject/GaloisField.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;
}
}