in lattices/lattice_Zn.cpp [355:416]
void ZnSphereCodecRec::decode(uint64_t code, float *c) const
{
uint64_t codes[dim];
int norm2s[dim];
codes[0] = code;
norm2s[0] = r2;
int dim2 = 1;
for(int ld = log2_dim; ld > decode_cache_ld; ld--) {
for (int i = dim2 - 1; i >= 0; i--) {
int r2sub = norm2s[i];
int i0 = 0, i1 = r2sub + 1;
uint64_t codei = codes[i];
const uint64_t *cum =
&all_nv_cum[(ld * (r2 + 1) + r2sub) * (r2 + 1)];
while (i1 > i0 + 1) {
int imed = (i0 + i1) / 2;
if (cum[imed] <= codei)
i0 = imed;
else
i1 = imed;
}
int r2a = i0, r2b = r2sub - i0;
codei -= cum[r2a];
norm2s[2 * i] = r2a;
norm2s[2 * i + 1] = r2b;
uint64_t code_a = codei / get_nv(ld - 1, r2b);
uint64_t code_b = codei % get_nv(ld - 1, r2b);
codes[2 * i] = code_a;
codes[2 * i + 1] = code_b;
}
dim2 *= 2;
}
if (decode_cache_ld == 0) {
for(int i = 0; i < dim; i++) {
if (norm2s[i] == 0) {
c[i] = 0;
} else {
float r = sqrt(norm2s[i]);
assert(r * r == norm2s[i]);
c[i] = codes[i] == 0 ? r : -r;
}
}
} else {
int subdim = 1 << decode_cache_ld;
assert ((dim2 * subdim) == dim);
for(int i = 0; i < dim2; i++) {
const std::vector<float> & cache =
decode_cache[norm2s[i]];
assert(codes[i] < cache.size());
memcpy(c + i * subdim,
&cache[codes[i] * subdim],
sizeof(*c)* subdim);
}
}
}