Skip to content

Commit 2fc55f1

Browse files
authored
Merge pull request #1396 from brian-team/long_runs_cpp_standalone
Avoid casting timesteps to 32bit in C++ standalone
2 parents c2b155f + aff91cb commit 2fc55f1

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

brian2/devices/cpp_standalone/brianlib/clocks.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
#include<math.h>
77

88
namespace {
9-
inline int fround(double x)
9+
inline int64_t fround(double x)
1010
{
11-
return (int)(x+0.5);
11+
return (int64_t)(x+0.5);
1212
};
1313
};
1414

@@ -28,20 +28,20 @@ class Clock
2828
inline bool running() { return timestep[0]<i_end; };
2929
void set_interval(double start, double end)
3030
{
31-
int i_start = fround(start/dt[0]);
31+
int64_t i_start = fround(start/dt[0]);
3232
double t_start = i_start*dt[0];
3333
if(t_start==start || fabs(t_start-start)<=epsilon*fabs(t_start))
3434
{
3535
timestep[0] = i_start;
3636
} else
3737
{
38-
timestep[0] = (int)ceil(start/dt[0]);
38+
timestep[0] = (int64_t)ceil(start/dt[0]);
3939
}
4040
i_end = fround(end/dt[0]);
4141
double t_end = i_end*dt[0];
4242
if(!(t_end==end || fabs(t_end-end)<=epsilon*fabs(t_end)))
4343
{
44-
i_end = (int)ceil(end/dt[0]);
44+
i_end = (int64_t)ceil(end/dt[0]);
4545
}
4646
}
4747
private:

brian2/tests/test_network.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,23 @@ def test_both_equal():
15351535

15361536
assert (M1.v == M2.v).all()
15371537

1538+
@pytest.mark.standalone_compatible
1539+
def test_long_run():
1540+
defaultclock.dt = 0.1 * ms
1541+
group = NeuronGroup(1, 'x : 1')
1542+
group.run_regularly('x += 1')
1543+
# Timesteps are internally stored as 64bit integers, but previous versions
1544+
# converted them into 32bit integers along the way. We'll make sure that
1545+
# this is not the case and everything runs fine. To not actually run such a
1546+
# long simulation we manually advance the clock.
1547+
net = Network(group, name='network')
1548+
start_step = 2**31-5
1549+
start_time = start_step*defaultclock.dt_
1550+
with catch_logs() as l:
1551+
net.t_ = start_time # for runtime
1552+
device.insert_code('main', 'network.t = {};'.format(start_time)) # for standalone
1553+
net.run(6 * defaultclock.dt)
1554+
assert group.x == 6
15381555

15391556
@pytest.mark.codegen_independent
15401557
def test_long_run_dt_change():
@@ -1571,6 +1588,7 @@ def test_multiple_runs_function_change():
15711588
device.build(direct_call=False, **device.build_options)
15721589
assert_equal(mon.v[0], [1, 2, 3, 4])
15731590

1591+
15741592
if __name__ == '__main__':
15751593
BrianLogger.log_level_warn()
15761594
for t in [
@@ -1635,6 +1653,7 @@ def test_multiple_runs_function_change():
16351653
test_runtime_rounding,
16361654
test_small_runs,
16371655
test_both_equal,
1656+
test_long_run,
16381657
test_long_run_dt_change,
16391658
test_multiple_runs_constant_change,
16401659
test_multiple_runs_function_change

0 commit comments

Comments
 (0)