Skip to content

Instantly share code, notes, and snippets.

Created December 14, 2012 06:44
Show Gist options
  • Save anonymous/4283220 to your computer and use it in GitHub Desktop.
Save anonymous/4283220 to your computer and use it in GitHub Desktop.
module newmetafint;
import std.stdio : write, writeln, writef, writefln;
import std.conv : to;
import std.array : replace, replicate;
debug import std.random;
version = demo;
debug = trace;
debug
{
mixin DefineBinaryField!(ubyte, 2, (1 << 1) + (1 << 0)) BF2;
mixin DefineBinaryField!(ubyte, 3, (1 << 1) + (1 << 0)) BF3;
mixin DefineBinaryField!(ubyte, 4, (1 << 1) + (1 << 0)) BF4;
mixin DefineBinaryField!(ubyte, 6, (1 << 1) + (1 << 0)) BF6;
mixin DefineBinaryField!(ubyte, 8, (1 << 7) + (1 << 2) + (1 << 1) + (1 << 0)) BF8;
mixin DefineBinaryField!(ushort, 12, (1 << 10) + (1 << 2) + (1 << 1) + (1 << 0)) BF12;
mixin DefineBinaryField!(ushort, 16, (1 << 12) + (1 << 3) + (1 << 1) + (1 << 0)) BF16;
mixin DefineBinaryField!(uint, 24, (1 << 7) + (1 << 2) + (1 << 1) + (1 << 0)) BF24;
mixin DefineBinaryField!(uint, 32, (1 << 22) + (1 << 2) + (1 << 1) + (1 << 0)) BF32;
mixin DefineBinaryField!(ulong, 64, (1UL << 61) + (1UL << 34) + (1UL << 9) + (1UL << 0)) BF64;
void main()
{
}
}
mixin template DefineBinaryField(U, U n, U p)
{
struct F
{
private static bool has_cantor_basis ()
{
U e = n;
while (e)
{
if (e & 1) return e == 1;
e >>= 1;
}
assert (false);
}
private static U left(U cur)
{
U top_bit = cur;
top_bit >>= n - 1;
cur <<= 1;
if (top_bit)
{
static if (n >> 3 != U.sizeof)
return cur ^ p ^ (cast(U)1 << n);
else
return cur ^ p;
}
else
{
return cur;
}
}
private static U[n] gen_square_p()
{
U[n] ret;
U cur = 1;
foreach (i; 0..cast(size_t)n)
{
ret[i] = cur;
cur = left(left(cur));
}
return ret;
}
private static square_p = gen_square_p();
unittest
{
debug "square_p = ".writeln(square_p);
}
private U squar(U a)
{
U ret;
foreach (i, c; square_p)
{
if (a >> i & 1)
{
ret ^= c;
}
}
return ret;
}
private static U[n - 1] gen_prod_p()
{
U[n - 1] ret;
U cur = p;
foreach (i; 0..cast(size_t)(n - 1))
{
ret[i] = cur;
cur = left(cur);
}
return ret;
}
private static prod_p = gen_prod_p();
private U prod(U a, U b)
{
U ret, higher;
if (a & 1)
{
ret = b;
}
foreach (i; 1..n)
{
if (a >> i & 1)
{
ret ^= b << i;
higher ^= b >> (n - i);
}
}
static if (n >> 3 != U.sizeof)
{
ret &= (1 << n) - 1;
}
foreach (i, c; prod_p)
{
if (higher >> i & 1)
{
ret ^= c;
}
}
return ret;
}
U v;
this (U v) /// trivial constructor (necessary for implicit conversion from U.)
{
this.v = v;
}
T opCast(T)() /// cast to other types (typically bool and U)
{
return cast(T)this.v;
}
version (binary) string toString() /// toString: binary version
{
string ret;
foreach_reverse (i; 0..n)
{
ret ~= ((this.v >> i) & 1).to!string;
}
return ret;
}
else string toString() /// toString: decimal version
{
return this.v.to!string;
}
bool opEquals(F other) /// equality
{
return this.v == other.v;
}
F opBinary(string op)(F other) /// binary operators with same type
{
static if (op == "+" || op == "-")
{
return F(this.v ^ other.v);
}
static if (op == "*")
{
return F(prod(this.v, other.v));
}
static if (op == "/")
{
return this * other.inverse();
}
}
F opOpAssign(string op)(F other) /// ditto
{
static if (op == "+" || op == "-")
{
this.v ^= other.v;
return this;
}
static if (op == "*")
{
this.v = prod(this.v, other.v);
return this;
}
}
F inverse() /// inverse
{
auto v = squar(this.v);
auto sq = v;
foreach (i; 1..(n - 1))
{
sq = squar(sq);
v = prod(v, sq);
}
return F(v);
}
F opBinary(string op)(ulong e) /// power operator
{
static if (op == "^^")
{
static if (n < 64)
{
static immutable mask = (1UL << n) - 1;
while (e >> n)
{
e = (e >> n) + (e & mask);
}
}
U v = 1;
U sq = this.v;
while (e)
{
if (e & 1)
{
v = prod(v, sq);
}
sq = squar(sq);
e >>= 1;
}
return F(v);
}
}
F square()
{
return F(squar(this.v));
}
alias square frobenius;
bool trace() /// field trace
{
debug (trace) " %s.field_trace = ".writefln(this);
F ret;
F tmp = this;
foreach (i; 0..n)
{
debug (trace) " %s^2^%d = %s".writefln(this, i, tmp);
ret += tmp;
tmp = tmp.square();
}
debug (trace) " ".writeln(ret.v ? 1 : 0);
return ret.v != 0;
}
debug
{
private bool another_trace() /// field trace: definition by linear algebra.
{
debug (trace) " %s.linear_trace = ".writefln(this);
bool tr;
U before = 1;
foreach (i; 0..n)
{
debug (trace) " *%s: %d -> %d (%d)".writefln(this, before, prod(this.v, before), prod(this.v, before) & before ? 1 : 0);
if (prod(this.v, before) & before)
{
tr = !tr;
}
before <<= 1;
}
debug (trace) " ".writeln(tr ? 1 : 0);
return tr;
}
unittest
{
debug "standard_basis = %s".writefln(standard_basis());
}
unittest
{
version (demo) "checking two definition of trace for x^i: 0 <= x < %d ...".writefln(n);
foreach (y; F.standard_basis())
{
assert (y.trace == y.another_trace);
}
version (demo) " OK".writeln();
}
}
bool norm() /// field norm
{
return this.v != 0;
}
static F[] standard_basis() /// basis for F as a vector space over B
{
F[] ret;
U v = 1;
foreach (i; 0..n)
{
ret ~= F(v);
v <<= 1;
}
return ret;
}
static F trace_one() /// smallest (as ordinal number) element which is of trace one.
{
foreach (y; F.standard_basis())
{
if (y.trace) return y;
}
assert (false);
}
version (demo) unittest
{
"first element with trace 1 in F_{2^%d} is %d".writefln(n, F.trace_one());
}
static if (has_cantor_basis()) static F[n] cantor_basis()
out (result)
{
U[n] check;
foreach (i; 0..cast(size_t)n)
{
check[i] = result[i].v;
}
assert_linear_independency(check);
}
body
{
auto theta = trace_one();
F next_elem(F prev)
out (ret)
{
auto r = F(ret.v);
assert (prev == r * r + r);
}
body
{
F ret;
// [0 <= j < i < n] this^2^j theta^2^i
U one = 1;
F thetasq = theta;
foreach (U i; 0..n)
{
F thissq = prev;
foreach (U j; 0..i)
{
ret += thissq * thetasq;
thissq = thissq.frobenius();
}
thetasq = thetasq.frobenius();
}
return ret;
}
F[n] ret;
ret[0] = F(1);
foreach (i; 1..cast(size_t)n)
{
ret[i] = next_elem(ret[i - 1]);
}
return ret;
}
private static void assert_linear_independency(U[n] result)
{
outer:
foreach (i; 0..cast(size_t)n)
{
foreach (j; 0..cast(size_t)n)
{
if (result[j] >> i & 1)
{
foreach (k; (j+1)..cast(size_t)n)
{
if (result[k] >> i & 1)
{
result[k] ^= result[j];
}
}
continue outer;
}
}
assert (false);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment