Deconvolution/2D+: Difference between revisions

Formatted D entry, not improved
(Formatted D entry, not improved)
Line 320:
 
=={{header|D}}==
<lang d>import std.stdio, std.conv, ;std.array, std.algorithm, std.numeric,
import std.array, std.algorithm, std.numeric, std.range ;
 
class M(T) {
private size_t[] dim ;
private size_t[] subsize ;
private T[] d ;
 
this(size_t[] dimension ...) {
setDimension(dimension) ;
d[] = 0 ; // init each entry to zero ;
}
 
M!T dup() {
M!T m = new M!T(dim) ;
return m.set1DArray(d) ;
}
 
M!T setDimension(size_t[] dimension ...) {
foreach (e ; dimension)
assert(e > 0, "no zero dimension") ;
dim = dimension.dup ;
subsize = dim.dup ;
foreach (i; 0 .. dim.length)
subsize[i] = reduce!"a*b"(1, dim[i + 1 .. $]) ;
auto dlength = dim[0] * subsize[0] ;
if (d.length != dlength)
d = new T[](dlength) ];
return this ;
}
 
M!T set1DArray(T[] t ...) {
auto minLen = min(t.length, d.length) ;
d[] = 0 ;
d[0 .. minLen] = t[0 .. minLen] ;
return this ;
}
 
size_t[] seq2idx(size_t seq) {
size_t acc = seq, tmp ;
size_t[] idx ;
foreach (e ; subsize) {
idx ~= tmp = acc / e ;
acc = acc - tmp *e e; // same as % (mod) e ;
}
return idx ;
}
 
size_t size() const @property { return d.length ; }
 
size_t rank() const @property { return dim.length ; }
size_t[] shaperank() const @property { return dim.dup length; }
 
T[] raw() const @property { return d.dup ; }
size_t[] rankshape() const @property { return dim.length dup; }
 
T[] raw() const @property { return d.dup ; }
 
bool checkBound(size_t[] idx ...) const {
if (idx.length > dim.length) return false ;
foreach(i, dm ; idx) return false;
foreach (i, if(dm; >= dim[i]idx) return false ;
return true ; if (dm >= dim[i])
return false;
return true;
}
 
T opIndex(size_t[] idx ...) {
assert(checkBound(idx), "OOPS") ;
return d[dotProduct(idx, subsize)] ;
}
 
T opIndexAssign(T v, size_t[] idx ...) {
assert(checkBound(idx), "OOPS") ;
d[dotProduct(idx, subsize)] = v ;
return v ;
}
 
override bool opEquals(Object o) {
auto rhs = to!(M!T)(o) ;
return dim ==auto rhs.dim && d == rhs.d to!(M!T)(o);
dm[]return dim -== (rhs.dim[] -&& 1)d == rhs.d;
}
 
int opApply(int delegate(ref size_t[]) dg) {
size_t[] yieldIdx ;
foreach (i; 0 .. d.length) {
yieldIdx = seq2idx(i) ;
if (dg(yieldIdx))
break ;
}
return 0 ;
}
 
int opApply(int delegate(ref size_t[], ref T) dg) {
size_t idx1d = 0 ;
foreach (size_t[] idx ; this) {
if (dg(idx, d[idx1d++]))
break ;
}
return 0 ;
}
 
M!T convolute(M!T rhs) { // _this_ is h, rhs is f, output g
auto dm = dim.dup ;
dm[] += (rhs.dim[] - 1) ;
M!T m = new M!T(dm) ; // dm will be reused as m's idx
auto bound = m.size ;
foreach (i; 0 .. d.length) {
auto thisIdx = seq2idx(i) ;
foreach (j; 0 .. rhs.d.length) {
dm[] = thisIdx[] + rhs.seq2idx(j)[] ;
auto midx1d = dotProduct(dm, m.subsize) ;
if ( midx1d < bound)
m.d[midx1d] += d[i] * rhs.d[j] ;
else
break ; // bound reach, ok to break
}
}
return m ;
}
 
M!T deconvolute(M!T rhs) { // _this_ is g, rhs is f, output is h
auto dm = dim.dup ;
foreach (i, e ; dm)
assert(e + 1 > rhs.dim[i], "deconv : dimensions is zero or negative") ;
"deconv : dimensions is zero or negative");
dm[] -= (rhs.dim[] - 1) ;
dm[] -= (rhs.dim[] - 1);
M!T m = new M!T(dm) ; // dm will be reused as rhs' idx
 
foreach (i; 0 .. m.size) {
auto idx = m.seq2idx(i) ;
m.d[i] = this[idx] ;
foreach (j; 0 .. i) {
auto jdx = m.seq2idx(j) ;
dm[] = idx[] - jdx[];
if (rhs.checkBound(dm))
m.d[i] -= m.d[j] * rhs[dm] ;
}
m.d[i] /= rhs.d[0] ;
}
return m ;
}
 
override string toString() { return to!string(d) ; }
}
 
auto fold(T)(T[] arr, ref size_t[] d) {
if (d.length == 0) d ~= arr.length ;
static if(is(T U : U[]))d {// is~= arr an array of arrays?.length;
static if (is(T U : U[])) { // is arr an array of arrays?
assert(arr.length > 0, "no empty dimension") ;
d ~= assert(arr[0].length > 0, "no empty dimension");
foreach(ed ;~= arr)[0].length;
foreach assert(e.length ==; arr[0].length, "not rectangular") ;
return fold(reduce!"a~b" assert(e.length == arr)[0].length, d)"not rectangular");
return fold(reduce!q{a ~ b}(arr), d);
} else {
assert(arr.length == reduce!"q{a * b"}(d), "not same size") ;
return arr ;
}
}
 
auto arr2M(T)(T a) {
size_t[] dm ;
auto d = fold(a, dm) ;
alias ElementType!(typeof(d)) E ;
auto m = new M!E(dm) ;
m.set1DArray(d) ;
return m ;
}
 
void main() {
alias M!int Mi ;
auto hh = [[[-6, -8, -5, 9], [-7, 9, -6, -8], [2, -7, 9, 8]],
[[7, 4, 4, -6], [9, 9, 4, -4], [-3, 7, -2, -3]]] ;
auto ff = [[[-9, 5, -8], [3, 5, 1]],[[-1, -7, 2], [-5, -6, 6]],
[[8, 5, 8],[-2, -6, -4]]] ;
auto h = arr2M(hh) ;
auto f = arr2M(ff) ;
 
auto g = h.convolute(f) ;
 
writeln("g == f convolute h ? ", g == f.convolute(h)) ;
writeln("h == g deconv f ? ", h == g.deconvolute(f)) ;
writeln("f == g deconv h ? ", f == g.deconvolute(h)) ;
writeln(" f = ", f) ;
writeln("g deconv h = ", g.deconvolute(h)) ;
}</lang>
''todo(may be not :): pretty print & convert to normal D array''