This page describes the format of digital nets on this website. Let s, n, m be the dimension over R, the number of binary digits, and the dimension over F2 of P. The digital net P ⊂ F2s×n is formatted in one-line ASCII text which consists of (3 + ms) integers separated by spaces.
The first three integers are n, m and s in this order. The following ms n-bit nonnegative integers are the components phi (h ∈ m; i ∈ s) of a basis of P, ordered lexicographically by (h, i). To simplify the conversion to real numbers, the most significant bit corresponds to 2−1.
The code below (written in D) reads the string line and set s, n, m and p:
import std.string, std.array, std.conv; // std.string for strip, std.array for split, std.conv for to
auto buf = line.strip().split();
immutable n = buf.front.to!size_t(); buf.popFront();
immutable m = buf.front.to!size_t(); buf.popFront();
immutable s = buf.front.to!size_t(); buf.popFront();
auto p = new U[][](m, s);
foreach (h; 0..m)
foreach (i; 0..s)
{
p[h][i] = buf.front.to!U();
buf.popFront();
}
The type U is the unsigned integer which can store at least n bits.
Use ubyte
for n ≤ 8, ushort
for n ≤ 16, uint
for n ≤ 32, and ulong
for n ≤ 64.
Almost all generating matrices on this website uses n = 32 and U = uint
.
To generate each point, simply XOR the elements p[h][i]
and divide by 2n:
auto xi = new U[](s);
foreach (h; H)
foreach (i; 0..s)
xi[i] ^= p[h][i];
auto x = new F[](s);
foreach (i; 0..s)
x[i] = xi[i] * 0.5 ^^ n;
for each subset H
⊂ m.
To iterate over P you may use gray-code implementation for efficiency.
Additionally, to reduce the discretization error in QMC integration or to avoid the divergence around the boundary of the hypercube you can place each point center of the hypercube by modifying the last two lines:
foreach (i; 0..s)
x[i] = (xi[i] + 0.5) * 0.5 ^^ n;
Dirk Nuyens' Magic point shop uses a different format, and I provide a converter from his to mine here:
import std.stdio;
import std.functional : pipe;
import std.string : strip;
import std.array : split;
import std.algorithm : map;
import std.conv : to;
import std.array : array;
import core.bitop : bitswap;
void main()
{
size_t precision = 32, dimensionF2, dimensionR;
uint[][] vectors;
foreach (line; stdin.byLine().map!(pipe!(strip, split, map!(pipe!(to!uint, bitswap)), array)))
{
if (dimensionR == 0)
{
dimensionF2 = line.length;
vectors = line.map!(a => [a])().array();
}
else
{
assert (dimensionF2 == line.length);
foreach (i, ref vector; vectors)
vector ~= line[i];
}
dimensionR += 1;
}
"%d %d %d%(%( %d%)%)".writefln(precision, dimensionF2, dimensionR, vectors);
}
Note that this code depends on uint bitswap(uint)
so that it doesn't work for precision > 32 without modification.
The line which describes a digital net P may contain additional information.
If the number of space-separated integers is (3 + ms + m) rather than default (3 + ms), the additional m are interpreted as the components of a digital shift σ ∈ F2s×n applied to P, in the same manner as the components of the basis.
With the exception above, additional information must be separated by a comma (',
') and then follow.
Some typical usages are WAFOM value, QMC integration, QMC error, etc.