aboutsummaryrefslogtreecommitdiff
path: root/externals/gridflow/base/flow_objects2.c
blob: a0bbfe78bed816ae9140df146020b5f831b96949 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
	$Id: flow_objects.c 4097 2008-10-03 19:49:03Z matju $

	GridFlow
	Copyright (c) 2001-2008 by Mathieu Bouchard

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	See file ../COPYING for further informations on licensing terms.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "../gridflow.h.fcs"
#define OP(x) op_dict[string(#x)]

static void expect_min_one_dim (P<Dim> d) {
	if (d->n<1) RAISE("expecting at least one dimension, got %s",d->to_s());}

// obviously unfinished
\class GridExpr : FObject {
	\constructor (...) {
		std::ostringstream os;
		for (int i=0; i<argc; i++) os << " " << argv[i];
		string s = os.str();
		post("expr = '%s'",s.data());
	}
};
\end class {install("#expr",1,1);}

\class GridClusterAvg : FObject {
	\attr int numClusters;
	\attr PtrGrid r;
	\attr PtrGrid sums;
	\attr PtrGrid counts;
	\constructor (int v) {_1_float(0,0,v); r.constrain(expect_min_one_dim);}
	\decl 1 float (int v);
	\grin 0 int32
	\grin 2
	template <class T> void make_stats (long n, int32 *ldata, T *rdata) {
		int32 chans = r->dim->v[r->dim->n-1];
		T     *sdata = (T     *)*sums;
		int32 *cdata = (int32 *)*counts;
		for (int i=0; i<n; i++, ldata++, rdata+=chans) {
			if (*ldata<0 || *ldata>=numClusters) RAISE("value out of range in left grid");
			OP(+)->zip(chans,sdata+(*ldata)*chans,rdata);
			cdata[*ldata]++;
		}
		for (int i=0; i<numClusters; i++) OP(/)->map(chans,sdata+i*chans,(T)cdata[i]);
		out = new GridOutlet(this,1,counts->dim,counts->nt);
		out->send(counts->dim->prod(),(int32 *)*counts);
		out = new GridOutlet(this,0,sums->dim,sums->nt);
		out->send(sums->dim->prod(),(T *)*sums);
	}
};

GRID_INLET(0) {
	NOTEMPTY(r);
	int32 v[r->dim->n];
	COPY(v,r->dim->v,r->dim->n-1);
	v[r->dim->n-1]=1;
	P<Dim> t = new Dim(r->dim->n,v);
	if (!t->equal(in->dim)) RAISE("left %s must be equal to right %s except last dimension should be 1",in->dim->to_s(),r->dim->to_s());
	in->set_chunk(0);
	int32 w[2] = {numClusters,r->dim->v[r->dim->n-1]};
	sums   = new Grid(new Dim(2,w),r->nt,  true);
	counts = new Grid(new Dim(1,w),int32_e,true);
} GRID_FLOW {
	#define FOO(U) make_stats(n,data,(U *)*r);
	TYPESWITCH(r->nt,FOO,)
	#undef FOO
} GRID_END
\def 1 float (int v) {numClusters = v;}
GRID_INPUT(2,r) {
} GRID_END

\end class {install("#cluster_avg",3,2);}

void startup_flow_objects2 () {
	\startall
}