55#ifndef DT_IOP_PERMUTOHEDRAL_H
56#define DT_IOP_PERMUTOHEDRAL_H
88 Key(
const Key &origin,
int dim,
int direction)
90 for(
int i = 0;
i < KD;
i++)
key[
i] = origin.
key[
i] + direction;
91 key[dim] = origin.
key[dim] - direction * KD;
107 for(
int i = 0;
i < KD;
i++)
117 if(
hash != other.
hash)
return false;
118 for(
int i = 0;
i < KD;
i++)
120 if(
key[
i] != other.
key[
i])
return false;
137 for(
int i = 0;
i < VD;
i++)
149 for(
int i = 0;
i < VD;
i++) val[
i] = 0;
164 for(
int i = 0;
i < VD;
i++)
172 for(
int i = 0;
i < VD;
i++)
180 for(
int i = 0;
i < VD;
i++)
188 for(
int i = 0;
i < VD;
i++)
196 for(
int i = 0;
i < VD;
i++)
270 if(!create)
return -1;
297 return (offset < 0) ? nullptr :
values + offset;
325 for(
size_t i = 0;
i < oldCapacity;
i++)
327 if(
entries[
i].keyIdx == -1)
continue;
329 while(newEntries[h].keyIdx != -1)
382 float *scaleFactorTmp =
new float[D];
383 int *canonicalTmp =
new int[(D + 1) * (D + 1)];
390 for(
int i = 0;
i <= D;
i++)
392 for(
int j = 0; j <= D -
i; j++) canonicalTmp[
i * (D + 1) + j] =
i;
393 for(
int j = D -
i + 1; j <= D; j++) canonicalTmp[
i * (D + 1) + j] =
i - (D + 1);
398 for(
int i = 0;
i < D;
i++)
401 scaleFactorTmp[
i] = 1.0f / (sqrtf((
float)(
i + 1) * (
i + 2)));
415 scaleFactorTmp[
i] *= (D + 1) * sqrtf(2.0 / 3);
466 float elevated[D + 1];
469 float barycentric[D + 2];
474 for(
int i = D - 1;
i > 0;
i--)
480 constexpr float scale = 1.0f / (D + 1);
484 for(
int i = 0;
i <= D;
i++)
486 float v = elevated[
i] * scale;
487 float up = ceilf(
v) * (D + 1);
488 float down = floorf(
v) * (D + 1);
490 if(up - elevated[
i] < elevated[
i] - down)
501 memset(rank, 0,
sizeof rank);
502 for(
int i = 0;
i < D;
i++)
503 for(
int j =
i + 1; j <= D; j++)
504 if(elevated[
i] - greedy[
i] < elevated[j] - greedy[j])
513 for(
int i = 0;
i <= D;
i++)
515 if(rank[
i] >= D + 1 - sum)
518 rank[
i] += sum - (D + 1);
528 for(
int i = 0;
i <= D;
i++)
533 rank[
i] += (D + 1) + sum;
541 memset(barycentric, 0,
sizeof barycentric);
542 for(
int i = 0;
i <= D;
i++)
544 barycentric[D - rank[
i]] += (elevated[
i] - greedy[
i]) * scale;
545 barycentric[D + 1 - rank[
i]] -= (elevated[
i] - greedy[
i]) * scale;
547 barycentric[0] += 1.0f + barycentric[D + 1];
551 for(
int remainder = 0; remainder <= D; remainder++)
555 for(
int i = 0;
i < D;
i++)
key.key[
i] = greedy[
i] +
canonical[remainder * (D + 1) + rank[
i]];
562 val->
add(
value, barycentric[remainder]);
566 replay[replay_index].
weight[remainder] = barycentric[remainder];
583 while(total_entries >
hashTables[0].maxFill())
590 int **offset_remap =
new int *[
nThreads];
596 offset_remap[
i] =
new int[filled];
597 for(
int j = 0; j < filled; j++)
600 val->
add(oldVals[j]);
610 for(
int dim = 0; dim <= D; dim++)
615 for(
int i = 1;
i <
nThreads;
i++)
delete[] offset_remap[
i];
616 delete[] offset_remap;
623 void slice(
float *col,
size_t replay_index)
const
628 for(
int i = 0;
i <= D;
i++)
630 base[
r.offset[
i]].
addTo(col,
r.weight[
i]);
640 const Value *hashTableBase = oldValue;
642 const Value zero{ 0 };
645 for(
int j = 0; j <= D; j++)
653 Key neighbor1(
key, j, +1);
654 Key neighbor2(
key, j, -1);
656 const Value *oldVal = oldValue +
i;
659 vm1 = vm1 ? vm1 - hashTableBase + oldValue : &zero;
662 vp1 = vp1 ? vp1 - hashTableBase + oldValue : &zero;
665 newValue[
i].
mix(vm1, oldVal, vp1);
667 std::swap(newValue, oldValue);
672 if(oldValue != hashTableBase)
void init(dt_imageio_module_format_t *self)
HashTablePermutohedral(const HashTablePermutohedral &)=delete
const Key * getKeys() const
unsigned long capacity_bits
HashTablePermutohedral & operator=(const HashTablePermutohedral &)=delete
~HashTablePermutohedral()
Value * lookup(const Key &k, bool create=true)
Value * getValues() const
int lookupOffset(const Key &key, bool create=true)
void slice(float *col, size_t replay_index) const
struct PermutohedralLattice::ReplayEntry * replay
const float * scaleFactor
PermutohedralLattice(size_t nData_, int nThreads_=1)
PermutohedralLattice(const PermutohedralLattice &)=delete
void merge_splat_threads()
PermutohedralLattice & operator=(const PermutohedralLattice &)=delete
HashTablePermutohedral< D, VD > HashTable
void splat(float *position, float *value, size_t replay_index, int thread_index=0) const
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
float *const restrict const size_t k
#define __OMP_PARALLEL_FOR__(...)
static const dt_aligned_pixel_simd_t value
Key & operator=(const Key &)=default
Key(const Key &origin, int dim, int direction)
bool operator==(const Key &other) const
void setKey(int idx, short val)
void setValue(int idx, short val)
Value & operator+=(const Value &other)
void add(const Value &other)
Value(const Value &)=default
Value & operator=(const Value &)=default
static void clear(float *val)
void mix(const Value *left, const Value *center, const Value *right)
void addTo(float *dest, float weight) const
void addValue(int idx, short val)
void add(const float *other, float weight)