1 """
2 Response functions (see basic.py) and CFProjection response functions
3 (see projfn.py) written in C to optimize performance.
4
5 Requires the weave package; without it unoptimized versions are used.
6
7 $Id: optimized.py 11088 2010-06-17 17:23:59Z ceball $
8 """
9 __version__='$Revision: 11088 $'
10
11 import param
12
13 from topo.base.functionfamily import ResponseFn,DotProduct
14 from topo.base.cf import CFPResponseFn, CFPRF_Plugin
15 from topo.misc.inlinec import inline,provide_unoptimized_equivalent,c_header
16 from topo.responsefn.projfn import CFPRF_EuclideanDistance
17
18
19
20
21
22
23
25 """
26 Dot-product response function.
27
28 Written in C for a manyfold speedup; see CFPRF_DotProduct for an
29 easier-to-read version in Python. The unoptimized Python version
30 is equivalent to this one, but it also works for 1D arrays.
31 """
32
33 single_cf_fn = param.ClassSelector(ResponseFn,DotProduct(),readonly=True)
34
35 - def __call__(self, iterator, input_activity, activity, strength, **params):
36
37 temp_act = activity
38 irows,icols = input_activity.shape
39 X = input_activity.ravel()
40 cfs = iterator.flatcfs
41 num_cfs = len(cfs)
42 mask = iterator.mask.data
43
44 cf_type = iterator.cf_type
45
46 code = c_header + """
47 DECLARE_SLOT_OFFSET(weights,cf_type);
48 DECLARE_SLOT_OFFSET(input_sheet_slice,cf_type);
49
50 npfloat *tact = temp_act;
51
52 for (int r=0; r<num_cfs; ++r) {
53 if((*mask++) == 0.0)
54 *tact = 0;
55 else {
56 PyObject *cf = PyList_GetItem(cfs,r);
57
58 CONTIGUOUS_ARRAY_FROM_SLOT_OFFSET(float,weights,cf)
59 LOOKUP_FROM_SLOT_OFFSET(int,input_sheet_slice,cf);
60
61 UNPACK_FOUR_TUPLE(int,rr1,rr2,cc1,cc2,input_sheet_slice);
62
63 double tot = 0.0;
64 npfloat *xj = X+icols*rr1+cc1;
65
66 // computes the dot product
67 for (int i=rr1; i<rr2; ++i) {
68 npfloat *xi = xj;
69 float *wi = weights;
70 for (int j=cc1; j<cc2; ++j) {
71 tot += *wi * *xi;
72 ++wi;
73 ++xi;
74 }
75 xj += icols;
76 weights += cc2-cc1;
77 }
78 *tact = tot*strength;
79
80 DECREF_CONTIGUOUS_ARRAY(weights);
81 }
82 ++tact;
83 }
84 """
85 inline(code, ['mask','X', 'strength', 'icols', 'temp_act','cfs','num_cfs','cf_type'],
86 local_dict=locals(), headers=['<structmember.h>'])
87
89 """
90 Wrapper written to allow transparent non-optimized fallback;
91 equivalent to CFPRF_Plugin(single_cf_fn=DotProduct()).
92 """
93
96
97 provide_unoptimized_equivalent("CFPRF_DotProduct_opt","CFPRF_DotProduct",locals())
98
99
100
102 """
103 Euclidean-distance response function.
104
105 Written in C for a several-hundred-times speedup; see
106 CFPRF_EuclideanDistance for an easier-to-read (but otherwise
107 equivalent) version in Python.
108 """
109 - def __call__(self, iterator, input_activity, activity, strength, **params):
110 temp_act = activity
111 rows,cols = activity.shape
112 irows,icols = input_activity.shape
113 X = input_activity.ravel()
114 cfs = iterator.flatcfs
115 num_cfs = len(cfs)
116
117 code = c_header + """
118 #include <math.h>
119 npfloat *tact = temp_act;
120 double max_dist=0.0;
121
122 for (int r=0; r<num_cfs; ++r) {
123 PyObject *cf = PyList_GetItem(cfs,r);
124
125 PyObject *weights_obj = PyObject_GetAttrString(cf,"weights");
126 PyObject *slice_obj = PyObject_GetAttrString(cf,"input_sheet_slice");
127
128 float *wj = (float *)(((PyArrayObject*)weights_obj)->data);
129 int *slice = (int *)(((PyArrayObject*)slice_obj)->data);
130
131 int rr1 = *slice++;
132 int rr2 = *slice++;
133 int cc1 = *slice++;
134 int cc2 = *slice;
135
136 npfloat *xj = X+icols*rr1+cc1;
137
138 // computes the dot product
139 double tot = 0.0;
140 for (int i=rr1; i<rr2; ++i) {
141 npfloat *xi = xj;
142 float *wi = wj;
143 for (int j=cc1; j<cc2; ++j) {
144 double diff = *wi - *xi;
145 tot += diff*diff;
146 ++wi;
147 ++xi;
148 }
149 xj += icols;
150 wj += cc2-cc1;
151 }
152
153 double euclidean_distance = sqrt(tot);
154 if (euclidean_distance>max_dist)
155 max_dist = euclidean_distance;
156
157 *tact = euclidean_distance;
158 ++tact;
159
160 // Anything obtained with PyObject_GetAttrString must be explicitly freed
161 Py_DECREF(weights_obj);
162 Py_DECREF(slice_obj);
163 }
164 tact = temp_act;
165 for (int r=0; r<num_cfs; ++r) {
166 *tact = strength*(max_dist - *tact);
167 ++tact;
168 }
169 """
170 inline(code, ['X', 'strength', 'icols', 'temp_act','cfs','num_cfs'],
171 local_dict=locals())
172
173 provide_unoptimized_equivalent("CFPRF_EuclideanDistance_opt","CFPRF_EuclideanDistance",locals())
174