yinspire 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +24 -0
- data/bench/pq/Makefile +5 -0
- data/bench/pq/bench.cc +321 -0
- data/bench/pq/bench.rb +125 -0
- data/bench/pq/bench_binaryheap.h +46 -0
- data/bench/pq/bench_calendarqueue.h +58 -0
- data/bench/pq/bench_pairingheap.h +61 -0
- data/bench/pq/bench_stlpq.h +46 -0
- data/bench/pq/benchmark.h +225 -0
- data/bench/pq/distribution.h +93 -0
- data/bench/pq/make.rb +24 -0
- data/bin/yinspire +186 -0
- data/examples/nets/gereon2005.c.json +93723 -0
- data/examples/nets/gereon2005.yin +232650 -0
- data/examples/nets/skorpion.graphml +396 -0
- data/examples/nets/spiketrains_angle_180.txt +8 -0
- data/lib/Algorithms/Array.h +52 -0
- data/lib/Algorithms/BinaryHeap.h +265 -0
- data/lib/Algorithms/CalendarQueue.h +257 -0
- data/lib/Algorithms/IndexedBinaryHeap.h +90 -0
- data/lib/Algorithms/PairingHeap.h +169 -0
- data/lib/Allocators/ChunkedFreelistAllocator.h +96 -0
- data/lib/Allocators/MemoryAllocator.h +45 -0
- data/lib/Allocators/RubyMemoryAllocator.h +37 -0
- data/lib/Yinspire.rb +69 -0
- data/lib/Yinspire/All.rb +10 -0
- data/lib/Yinspire/Core/NeuralEntity.rb +133 -0
- data/lib/Yinspire/Core/Neuron.rb +162 -0
- data/lib/Yinspire/Core/Scheduling/NeuralEntity.rb +123 -0
- data/lib/Yinspire/Core/Scheduling/Simulator.rb +94 -0
- data/lib/Yinspire/Core/Simulator.rb +36 -0
- data/lib/Yinspire/Core/StimuliMixin.rb +103 -0
- data/lib/Yinspire/Core/Stimulus.rb +25 -0
- data/lib/Yinspire/Core/Synapse.rb +64 -0
- data/lib/Yinspire/Dumpers/Dumper.rb +19 -0
- data/lib/Yinspire/Dumpers/Dumper_Dot.rb +28 -0
- data/lib/Yinspire/Loaders/GraphML.rb +84 -0
- data/lib/Yinspire/Loaders/Loader.rb +31 -0
- data/lib/Yinspire/Loaders/Loader_GraphML.rb +97 -0
- data/lib/Yinspire/Loaders/Loader_JSON.rb +181 -0
- data/lib/Yinspire/Loaders/Loader_Spike.rb +42 -0
- data/lib/Yinspire/Loaders/Loader_Yin.rb +62 -0
- data/lib/Yinspire/Loaders/YinScanner.rb +247 -0
- data/lib/Yinspire/Models/Neuron_Base.rb +38 -0
- data/lib/Yinspire/Models/Neuron_Input.rb +12 -0
- data/lib/Yinspire/Models/Neuron_InputOutput.rb +39 -0
- data/lib/Yinspire/Models/Neuron_Output.rb +15 -0
- data/lib/Yinspire/Models/Neuron_SRM01.rb +50 -0
- data/lib/Yinspire/Models/Neuron_SRM02.rb +64 -0
- data/lib/Yinspire/Models/Synapse_Hebb.rb +67 -0
- data/pure_cpp/Makefile +22 -0
- data/pure_cpp/README +2 -0
- data/pure_cpp/src/algo/binary_heap.h +277 -0
- data/pure_cpp/src/algo/indexed_binary_heap.h +90 -0
- data/pure_cpp/src/json/json.cc +542 -0
- data/pure_cpp/src/json/json.h +182 -0
- data/pure_cpp/src/json/json_parser.cc +685 -0
- data/pure_cpp/src/json/json_parser.h +15 -0
- data/pure_cpp/src/json/json_parser.rl +213 -0
- data/pure_cpp/src/main.cc +49 -0
- data/pure_cpp/src/memory_allocator.h +45 -0
- data/pure_cpp/src/neural_entity.cc +208 -0
- data/pure_cpp/src/neural_entity.h +243 -0
- data/pure_cpp/src/neuron.cc +136 -0
- data/pure_cpp/src/neuron.h +70 -0
- data/pure_cpp/src/neuron_srm_01.cc +77 -0
- data/pure_cpp/src/neuron_srm_01.h +36 -0
- data/pure_cpp/src/simulator.cc +151 -0
- data/pure_cpp/src/simulator.h +116 -0
- data/pure_cpp/src/synapse.cc +117 -0
- data/pure_cpp/src/synapse.h +60 -0
- data/pure_cpp/src/types.h +18 -0
- data/run.rb +68 -0
- data/tools/conv_jsonc_to_yin.rb +165 -0
- data/tools/converter.rb +93 -0
- data/tools/json_writer.rb +122 -0
- data/yinspire.gemspec +20 -0
- metadata +156 -0
@@ -0,0 +1,265 @@
|
|
1
|
+
/*
|
2
|
+
* An implicit Binary Heap.
|
3
|
+
*
|
4
|
+
* Copyright (c) 2007, 2008 by Michael Neumann (mneumann@ntecs.de)
|
5
|
+
*
|
6
|
+
* NOTE: We start counting from 1 in the elements array!
|
7
|
+
*
|
8
|
+
* Template parameters:
|
9
|
+
*
|
10
|
+
* E: Element type
|
11
|
+
* Alloc: Allocator
|
12
|
+
* Acc: Accessor struct. Defines ordering relation (less).
|
13
|
+
* MIN_CAPA: minimum number of elements
|
14
|
+
*
|
15
|
+
* Example:
|
16
|
+
*
|
17
|
+
* struct Acc
|
18
|
+
* {
|
19
|
+
* static inline bool less(const int& a, const int& b)
|
20
|
+
* {
|
21
|
+
* return a < b;
|
22
|
+
* }
|
23
|
+
* };
|
24
|
+
*
|
25
|
+
* BinaryHeap<int, MemoryAllocator, Acc> heap;
|
26
|
+
* heap.push(4);
|
27
|
+
* heap.pop();
|
28
|
+
* ...
|
29
|
+
*
|
30
|
+
*/
|
31
|
+
|
32
|
+
#ifndef __YINSPIRE__BINARY_HEAP__
|
33
|
+
#define __YINSPIRE__BINARY_HEAP__
|
34
|
+
|
35
|
+
#include <assert.h>
|
36
|
+
|
37
|
+
/*
|
38
|
+
* This is used to be able to keep track of
|
39
|
+
* an elements index in the IndexedBinaryHeap subclass.
|
40
|
+
* Unused in this class.
|
41
|
+
*/
|
42
|
+
template <typename E>
|
43
|
+
struct BinaryHeapDummyIndexer
|
44
|
+
{
|
45
|
+
static inline void index_changed(E& e, unsigned int i)
|
46
|
+
{
|
47
|
+
/* DUMMY */
|
48
|
+
}
|
49
|
+
};
|
50
|
+
|
51
|
+
template <typename E, class Alloc, class Acc=E, class Idx=BinaryHeapDummyIndexer<E>, unsigned int MIN_CAPA=1024>
|
52
|
+
class BinaryHeap
|
53
|
+
{
|
54
|
+
typedef unsigned int I; // index type
|
55
|
+
|
56
|
+
public:
|
57
|
+
|
58
|
+
BinaryHeap()
|
59
|
+
{
|
60
|
+
this->capacity = 0;
|
61
|
+
this->size_ = 0;
|
62
|
+
this->elements = NULL; // we do lazy allocation!
|
63
|
+
}
|
64
|
+
|
65
|
+
~BinaryHeap()
|
66
|
+
{
|
67
|
+
if (this->elements != NULL)
|
68
|
+
{
|
69
|
+
Alloc::free(this->elements+1);
|
70
|
+
}
|
71
|
+
this->elements = NULL;
|
72
|
+
}
|
73
|
+
|
74
|
+
inline E&
|
75
|
+
top() const
|
76
|
+
{
|
77
|
+
assert(this->size > 0);
|
78
|
+
return this->elements[1];
|
79
|
+
}
|
80
|
+
|
81
|
+
void
|
82
|
+
pop()
|
83
|
+
{
|
84
|
+
remove(1);
|
85
|
+
}
|
86
|
+
|
87
|
+
inline void
|
88
|
+
remove(I i)
|
89
|
+
{
|
90
|
+
assert(i <= this->size_);
|
91
|
+
|
92
|
+
//
|
93
|
+
// Element i is removed from the heap and as such becomes
|
94
|
+
// a "bubble" (free element). Move the bubble until
|
95
|
+
// the bubble becomes a leaf element.
|
96
|
+
//
|
97
|
+
Idx::index_changed(this->elements[i], 0); // detach from heap
|
98
|
+
I bubble = move_bubble_down(i);
|
99
|
+
|
100
|
+
//
|
101
|
+
// Now take the last element and insert it at the position of
|
102
|
+
// the bubble. In case the bubble is already the last element we
|
103
|
+
// are done.
|
104
|
+
//
|
105
|
+
if (bubble != this->size_)
|
106
|
+
{
|
107
|
+
insert_and_bubble_up(bubble, this->elements[this->size_]);
|
108
|
+
}
|
109
|
+
--this->size_;
|
110
|
+
}
|
111
|
+
|
112
|
+
void
|
113
|
+
push(const E& element)
|
114
|
+
{
|
115
|
+
if (this->size_ >= this->capacity) resize(2*this->capacity);
|
116
|
+
insert_and_bubble_up(++this->size_, element);
|
117
|
+
}
|
118
|
+
|
119
|
+
inline I
|
120
|
+
size() const
|
121
|
+
{
|
122
|
+
return this->size_;
|
123
|
+
}
|
124
|
+
|
125
|
+
inline bool
|
126
|
+
empty() const
|
127
|
+
{
|
128
|
+
return (this->size_ == 0);
|
129
|
+
}
|
130
|
+
|
131
|
+
/*
|
132
|
+
* Returns NULL or a pointer to the parent of +element+.
|
133
|
+
*/
|
134
|
+
E*
|
135
|
+
find_parent(const E& element)
|
136
|
+
{
|
137
|
+
I i;
|
138
|
+
|
139
|
+
//
|
140
|
+
// Find the position of the first element that is less than +element+.
|
141
|
+
//
|
142
|
+
for (i = this->size_; i != 0 && Acc::less(element, this->elements[i]); i /= 2);
|
143
|
+
|
144
|
+
return (i == 0 ? NULL : &this->elements[i]);
|
145
|
+
}
|
146
|
+
|
147
|
+
/*
|
148
|
+
* Iterate over all elements (non-destructive)
|
149
|
+
*/
|
150
|
+
void
|
151
|
+
each(void (*yield)(const E&, void*), void *data)
|
152
|
+
{
|
153
|
+
for (I i=1; i <= this->size_; i++)
|
154
|
+
{
|
155
|
+
yield(this->elements[i], data);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
protected:
|
160
|
+
|
161
|
+
/*
|
162
|
+
* Insert +element+ into the heap beginning from
|
163
|
+
* +i+ and searching upwards to the root for the
|
164
|
+
* right position (heap ordered) to insert.
|
165
|
+
*
|
166
|
+
* Element at index +i+ MUST be empty, i.e. unused!
|
167
|
+
*/
|
168
|
+
inline void
|
169
|
+
insert_and_bubble_up(I i, const E& element)
|
170
|
+
{
|
171
|
+
for (;i >= 2 && Acc::less(element, this->elements[i/2]); i /= 2)
|
172
|
+
{
|
173
|
+
store_element(i, this->elements[i/2]);
|
174
|
+
}
|
175
|
+
|
176
|
+
// finally store it into the determined hole
|
177
|
+
store_element(i, element);
|
178
|
+
}
|
179
|
+
|
180
|
+
/*
|
181
|
+
* Move the bubble (empty element) at +i+ down in direction
|
182
|
+
* to the leaves. When the bubble reaches a leaf, stop and
|
183
|
+
* return the index of the leaf element which is now empty.
|
184
|
+
*/
|
185
|
+
inline I
|
186
|
+
move_bubble_down(I i)
|
187
|
+
{
|
188
|
+
const I sz = this->size_;
|
189
|
+
I right_child = i * 2 + 1;
|
190
|
+
|
191
|
+
while (right_child <= sz)
|
192
|
+
{
|
193
|
+
if (Acc::less(this->elements[right_child-1], this->elements[right_child]))
|
194
|
+
{
|
195
|
+
--right_child; // minimum child is left child
|
196
|
+
}
|
197
|
+
|
198
|
+
store_element(i, this->elements[right_child]);
|
199
|
+
i = right_child;
|
200
|
+
right_child = i * 2 + 1;
|
201
|
+
}
|
202
|
+
|
203
|
+
//
|
204
|
+
// Edge case (comparison with the last element)
|
205
|
+
//
|
206
|
+
if (right_child-1 == sz)
|
207
|
+
{
|
208
|
+
store_element(i, this->elements[right_child-1]);
|
209
|
+
i = right_child-1;
|
210
|
+
}
|
211
|
+
|
212
|
+
return i;
|
213
|
+
}
|
214
|
+
|
215
|
+
/*
|
216
|
+
* The 0'th element is never used (accessed), so
|
217
|
+
* we allocate only "capacity" elements (instead of capacity+1)
|
218
|
+
* and move the pointer one element before the begin of the
|
219
|
+
* allocated memory.
|
220
|
+
*/
|
221
|
+
void
|
222
|
+
resize(I new_capacity)
|
223
|
+
{
|
224
|
+
E *new_elements;
|
225
|
+
|
226
|
+
if (new_capacity < MIN_CAPA) this->capacity = MIN_CAPA;
|
227
|
+
else this->capacity = new_capacity;
|
228
|
+
|
229
|
+
//
|
230
|
+
// We do lazy allocation!
|
231
|
+
//
|
232
|
+
if (this->elements != NULL)
|
233
|
+
{
|
234
|
+
new_elements = Alloc::realloc_n(this->elements+1, this->capacity);
|
235
|
+
}
|
236
|
+
else
|
237
|
+
{
|
238
|
+
new_elements = Alloc::alloc_n(this->capacity);
|
239
|
+
}
|
240
|
+
|
241
|
+
assert(new_elements != NULL);
|
242
|
+
assert(this->capacity >= this->size);
|
243
|
+
|
244
|
+
//
|
245
|
+
// move pointer so that we "introduce" a zero'th
|
246
|
+
// element.
|
247
|
+
//
|
248
|
+
this->elements = new_elements-1;
|
249
|
+
}
|
250
|
+
|
251
|
+
inline void
|
252
|
+
store_element(I i, const E& element)
|
253
|
+
{
|
254
|
+
this->elements[i] = element;
|
255
|
+
Idx::index_changed(this->elements[i], i);
|
256
|
+
}
|
257
|
+
|
258
|
+
protected:
|
259
|
+
|
260
|
+
I size_;
|
261
|
+
E *elements;
|
262
|
+
I capacity;
|
263
|
+
};
|
264
|
+
|
265
|
+
#endif
|
@@ -0,0 +1,257 @@
|
|
1
|
+
/*
|
2
|
+
* A Calendar Queue implementation.
|
3
|
+
*
|
4
|
+
* Copyright (c) 2007, 2008 by Michael Neumann (mneumann@ntecs.de)
|
5
|
+
*
|
6
|
+
* Template parameters:
|
7
|
+
*
|
8
|
+
* E: Element type
|
9
|
+
* ACC: Accessor
|
10
|
+
* priority -> real
|
11
|
+
* next -> E*&
|
12
|
+
* real: precision type
|
13
|
+
*
|
14
|
+
*/
|
15
|
+
|
16
|
+
#ifndef __YINSPIRE__CALENDAR_QUEUE__
|
17
|
+
#define __YINSPIRE__CALENDAR_QUEUE__
|
18
|
+
|
19
|
+
#include <assert.h>
|
20
|
+
|
21
|
+
template <typename E, class ACC = E, typename real=float>
|
22
|
+
class CalendarQueue
|
23
|
+
{
|
24
|
+
typedef unsigned int I; // index type
|
25
|
+
|
26
|
+
public:
|
27
|
+
|
28
|
+
CalendarQueue(real year_width=1.0)
|
29
|
+
{
|
30
|
+
this->size_ = 0;
|
31
|
+
this->year_width = year_width;
|
32
|
+
this->day_width = year_width;
|
33
|
+
|
34
|
+
this->current_year = 0;
|
35
|
+
this->current_day = 0;
|
36
|
+
|
37
|
+
this->num_days = 1;
|
38
|
+
this->days = new E*[1];
|
39
|
+
this->days[0] = NULL;
|
40
|
+
}
|
41
|
+
|
42
|
+
inline I
|
43
|
+
size() const
|
44
|
+
{
|
45
|
+
return this->size_;
|
46
|
+
}
|
47
|
+
|
48
|
+
inline bool
|
49
|
+
empty() const
|
50
|
+
{
|
51
|
+
return (this->size_ == 0);
|
52
|
+
}
|
53
|
+
|
54
|
+
void
|
55
|
+
push(E *element)
|
56
|
+
{
|
57
|
+
const real priority = ACC::priority(element);
|
58
|
+
|
59
|
+
assert(priority >= 0.0);
|
60
|
+
|
61
|
+
if (++this->size_ > 2*this->num_days) resize_double();
|
62
|
+
|
63
|
+
// map priority to a day
|
64
|
+
I day = ((I)(priority / this->day_width)) % this->num_days;
|
65
|
+
|
66
|
+
// and sort element into that day
|
67
|
+
insert_sorted(day, element);
|
68
|
+
|
69
|
+
//
|
70
|
+
// in case that the newly inserted element is smaller than the
|
71
|
+
// currently smallest value we have to change the current year
|
72
|
+
// and day.
|
73
|
+
//
|
74
|
+
if (priority < min_start())
|
75
|
+
{
|
76
|
+
this->current_day = day;
|
77
|
+
this->current_year = (I)(priority / this->year_width);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
inline real min_start() const { return day_start() + year_start(); }
|
82
|
+
inline real day_start() const { return this->current_day * this->day_width; }
|
83
|
+
inline real year_start() const { return this->current_year * this->year_width; }
|
84
|
+
|
85
|
+
E*
|
86
|
+
pop()
|
87
|
+
{
|
88
|
+
assert(this->size_ > 0);
|
89
|
+
|
90
|
+
if (--this->size_ < this->num_days/2 && this->num_days > 1) resize_half();
|
91
|
+
|
92
|
+
real priority;
|
93
|
+
real min_priority = INFINITY;
|
94
|
+
real max_value_this_year = (this->current_year+1)*this->year_width;
|
95
|
+
E *top;
|
96
|
+
I i;
|
97
|
+
|
98
|
+
for (i = this->current_day; i < this->num_days; i++)
|
99
|
+
{
|
100
|
+
top = this->days[i];
|
101
|
+
if (top != NULL)
|
102
|
+
{
|
103
|
+
priority = ACC::priority(top);
|
104
|
+
|
105
|
+
if (priority < max_value_this_year)
|
106
|
+
{
|
107
|
+
// remove top element
|
108
|
+
this->days[i] = ACC::next(top);
|
109
|
+
this->current_day = i;
|
110
|
+
ACC::next(top) = NULL;
|
111
|
+
return top;
|
112
|
+
}
|
113
|
+
if (priority < min_priority) min_priority = priority;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
//
|
118
|
+
// continue with the first element up to this->current_day
|
119
|
+
//
|
120
|
+
for (i = 0; i < this->current_day; i++)
|
121
|
+
{
|
122
|
+
top = this->days[i];
|
123
|
+
if (top != NULL)
|
124
|
+
{
|
125
|
+
priority = ACC::priority(top);
|
126
|
+
if (priority < min_priority) min_priority = priority;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
this->current_year = (I)(min_priority / this->year_width);
|
131
|
+
this->current_day = (I)(min_priority / this->day_width) % this->num_days;
|
132
|
+
|
133
|
+
top = this->days[this->current_day];
|
134
|
+
this->days[this->current_day] = ACC::next(top);
|
135
|
+
ACC::next(top) = NULL;
|
136
|
+
|
137
|
+
return top;
|
138
|
+
}
|
139
|
+
|
140
|
+
protected:
|
141
|
+
|
142
|
+
void
|
143
|
+
insert_sorted(I day, E *element)
|
144
|
+
{
|
145
|
+
E *curr = this->days[day];
|
146
|
+
E *prev = NULL;
|
147
|
+
const real priority = ACC::priority(element);
|
148
|
+
|
149
|
+
//
|
150
|
+
// Find the first element that is >= +element+.
|
151
|
+
// Insert +element+ *before* that element.
|
152
|
+
//
|
153
|
+
while (curr != NULL && ACC::priority(curr) < priority)
|
154
|
+
{
|
155
|
+
prev = curr;
|
156
|
+
curr = ACC::next(curr);
|
157
|
+
}
|
158
|
+
|
159
|
+
ACC::next(element) = curr;
|
160
|
+
|
161
|
+
if (prev != NULL) ACC::next(prev) = element;
|
162
|
+
else this->days[day] = element;
|
163
|
+
}
|
164
|
+
|
165
|
+
/*
|
166
|
+
* Each day is split into two days.
|
167
|
+
*/
|
168
|
+
void
|
169
|
+
resize_double()
|
170
|
+
{
|
171
|
+
E **new_days = new E*[2*this->num_days];
|
172
|
+
|
173
|
+
const real dw = this->day_width / 2.0;
|
174
|
+
E* c[2];
|
175
|
+
|
176
|
+
for (I i = 0; i < this->num_days; i++)
|
177
|
+
{
|
178
|
+
c[0] = new_days[i*2] = NULL;
|
179
|
+
c[1] = new_days[i*2+1] = NULL;
|
180
|
+
for (E *curr = this->days[i]; curr != NULL; curr = ACC::next(curr))
|
181
|
+
{
|
182
|
+
const I day = (I)(ACC::priority(curr) / dw) % 2;
|
183
|
+
if (c[day] != NULL)
|
184
|
+
{
|
185
|
+
ACC::next(c[day]) = curr;
|
186
|
+
}
|
187
|
+
else
|
188
|
+
{
|
189
|
+
new_days[i*2+day] = curr;
|
190
|
+
}
|
191
|
+
c[day] = curr;
|
192
|
+
}
|
193
|
+
|
194
|
+
if (c[0] != NULL) ACC::next(c[0]) = NULL;
|
195
|
+
if (c[1] != NULL) ACC::next(c[1]) = NULL;
|
196
|
+
}
|
197
|
+
|
198
|
+
delete [] this->days;
|
199
|
+
|
200
|
+
this->days = new_days;
|
201
|
+
this->num_days *= 2;
|
202
|
+
this->day_width /= 2.0;
|
203
|
+
this->current_year = 0;
|
204
|
+
this->current_day = 0;
|
205
|
+
}
|
206
|
+
|
207
|
+
// TODO: merge
|
208
|
+
void
|
209
|
+
resize_half()
|
210
|
+
{
|
211
|
+
resize(this->num_days/2, this->day_width*2.0);
|
212
|
+
}
|
213
|
+
|
214
|
+
void
|
215
|
+
resize(I new_num_days, real new_day_width)
|
216
|
+
{
|
217
|
+
E **old_days = this->days;
|
218
|
+
this->days = new E*[new_num_days];
|
219
|
+
E *element;
|
220
|
+
|
221
|
+
// initialize this->days to NULL
|
222
|
+
for (I i = 0; i < new_num_days; i++) this->days[i] = NULL;
|
223
|
+
|
224
|
+
for (I i = 0; i < this->num_days; i++)
|
225
|
+
{
|
226
|
+
for (E *curr = old_days[i]; curr != NULL; )
|
227
|
+
{
|
228
|
+
const I day = ((I)(ACC::priority(curr) / new_day_width)) % new_num_days;
|
229
|
+
element = curr;
|
230
|
+
curr = ACC::next(curr);
|
231
|
+
insert_sorted(day, element);
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
delete[] old_days;
|
236
|
+
|
237
|
+
this->num_days = new_num_days;
|
238
|
+
this->day_width = new_day_width;
|
239
|
+
this->current_year = 0;
|
240
|
+
this->current_day = 0;
|
241
|
+
}
|
242
|
+
|
243
|
+
private:
|
244
|
+
|
245
|
+
I size_;
|
246
|
+
|
247
|
+
I num_days;
|
248
|
+
E** days;
|
249
|
+
|
250
|
+
real day_width;
|
251
|
+
real year_width;
|
252
|
+
|
253
|
+
I current_year;
|
254
|
+
I current_day;
|
255
|
+
};
|
256
|
+
|
257
|
+
#endif
|