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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
#ifndef x9xBGzwmK2Ew29hQ89VsJgDlY3M
#define x9xBGzwmK2Ew29hQ89VsJgDlY3M
#include <boost/tuple/tuple.hpp>
#include "checkpoint.hpp"
#include "index.hpp"
#include "quant_types.hpp"
template<typename Ptr>
struct CommonSpikeIndex : CommonIndex<Ptr> {
// type- and constdefs
typedef Neuron::instance_ptr_t neuron_ptr_t;
// lift stuff from CommonIndex
typedef typename CommonIndex<Ptr>::ptr_t ptr_t;
using CommonIndex<Ptr>::nil;
using CommonIndex<Ptr>::first;
using CommonIndex<Ptr>::last;
using CommonIndex<Ptr>::time;
// using CommonIndex<Ptr>::nil;
CommonSpikeIndex(string qname);
// read operations
ptr_t last(Time t, neuron_ptr_t n); // ... of neuron n
ptr_t first(Time t, neuron_ptr_t n);
// write operations
template<typename SrcQuant>
inline ptr_t add(Time time, Time eventTime /* ignored */, SrcQuant src);
virtual void sync();
// vectors storing topological information
Vector<neuron_ptr_t::ptr_t> src;
Vector<ptr_t> prev, next; // address of the previous and next spike
// of the same sender neuron
// checkpoint to store the last known spike of every neuron (to
// implement adding a spike in a fast way)
Checkpoint<ptr_t, maxNeurons> prevCache;
};
template<typename Ptr>
CommonSpikeIndex<Ptr>::CommonSpikeIndex(string qname) :
CommonIndex<Ptr>("index_" + qname + "_time", maxSpikes),
src("index_" + qname + "_src", maxSpikes),
prev("index_" + qname + "_prev", maxSpikes),
next("index_" + qname + "_next", maxSpikes),
prevCache("index_" + qname + "_checkpoint_prev", this->nil())
{ }
template<typename Ptr>
typename CommonSpikeIndex<Ptr>::ptr_t CommonSpikeIndex<Ptr>::last(Time t, neuron_ptr_t n) {
// TODO (optimize): improve the alg to use prevCache as seed for
// proper min/max values
// get the last element before (at) time t
ptr_t id = last(t);
if (id == nil()) return nil(); // no spikes at all
// get the last known spike of neuron
Time lookup = fmin(prevCache.timeLimit(), t());
ptr_t lst = prevCache.getValue(lookup, n());
if (lst == nil()) return nil(); // n didn't fire at all
if (lst < id) return lst; // no l' with time(lst) < time(lst') <= t may exist
// do a linear search until a spike of n is found
while (src(id) != n()) {
id--;
}
return id;
}
template<typename Ptr>
typename CommonSpikeIndex<Ptr>::ptr_t CommonSpikeIndex<Ptr>::first(Time t, neuron_ptr_t n) {
// TODO (optimize): improve the alg to use prevCache as seed for
// proper min/max values
// get the first element after (at) time t
ptr_t id = first(t);
if (id == nil()) return nil(); // no spikes at all
// get the first known spike of neuron
ptr_t lst;
Time lookup = (t + prevCache.interval())();
do {
lookup = fmin(prevCache.timeLimit(), lookup());
lst = prevCache.getValue(lookup, n());
lookup += prevCache.interval();
} while (lst == nil() && lookup < prevCache.timeLimit());
if ((lst < id) || (lst == nil())) return nil(); // no spike of n after t exists
// do a linear search until a spike of n is found
while (src(id) != n()) {
id++;
}
return id;
}
template<typename Ptr> template<typename AddPtr>
typename CommonSpikeIndex<Ptr>::ptr_t CommonSpikeIndex<Ptr>::add(Time aTime, Time,
AddPtr rawSrc) {
// cast to neuron ptr (only correct type for call)
if (!boost::is_same<AddPtr, neuron_ptr_t>::value) DO_NOT_CALL;
neuron_ptr_t &aSrc(FORCE_CONV(neuron_ptr_t, rawSrc));
// check if all barriers are equal
assert(time.barrierWrite() == src.barrierWrite());
assert(time.barrierWrite() == prev.barrierWrite());
assert(time.barrierWrite() == next.barrierWrite());
// get position to write
ptr_t id = last();
if (last() == nil()) {
id = 0;
}else{
id += 1;
}
// add new record
time(id) = aTime;
src(id) = aSrc();
prev(id) = prevCache.getValue(aTime, aSrc());
if (prevCache.getValue(aTime, aSrc()) != nil())
next(prevCache.getValue(aTime, aSrc())) = id;
next(id) = nil();
prevCache.set(aTime, aSrc(), id);
// increase all write barriers
time.barrierWrite() = id + 1;
src.barrierWrite() = id + 1;
prev.barrierWrite() = id + 1;
next.barrierWrite() = id + 1;
return id;
}
template<typename Ptr>
void CommonSpikeIndex<Ptr>::sync() {
CommonIndex<Ptr>::sync();
src.sync();
prev.sync();
next.sync();
prevCache.sync();
}
#endif // x9xBGzwmK2Ew29hQ89V
|