run_regularly() with large dt in standalone mode
I'm running into an issue with using run_regularly() in standalone mode that I believe could possibly be a bug. 

Below is the network that reproduces the issue. The simulation segment 'T2', although very long, is completely skipped. For example I get an output of 

> Starting simulation at t=0 s for duration 1 s
> 1 s (100%) simulated in 0.23194 s
> Starting simulation at t=1 s for duration 100000 s
> 100000 s (100%) simulated in 1.35702e-94 s
> Starting simulation at t=100001 s for duration 1 s
> 1 s (100%) simulated in 0.228624 s

Two things fix the problem: 

1.  using a shorter simluation time, for example t2=100*second, or,
2. disabling the run_regularly() step

Brian2 version '2.2.1'.  Can anyone reproduce this? Thanks!


``` python

import numpy as np
from brian2 import *

N_e, N_i = 50, 50

tau = 20*ms               
tau_e = 3*ms              
tau_i = 5*ms              
El = -60*mV               
Ee = 0*mV                 
Ei = -80*mV               
mu_e = 9.0*mV
mu_i = 8.5*mV
sigma_e = 0.5**0.5 *mV    
sigma_i = 0.5**0.5 *mV

Vr_e = -60*mV
Vr_i = -60*mV
Vt_e = -57.5*mV
Vt_i = -58*mV

a_ee = 0.002

taupre = 15*ms
taupost = 30*ms
Aplus = 0.0015/10
Aminus = -0.00075/10
amax = 0.8
ATotalMax = 0.15

T1 = 1*second
T2 = 100000*second
T3 = 1*second

insert_P = 0.001
p_inactivate = 0.25
p_ee = 0.1


condlif_memnoise = '''
              dV/dt = (El-V + (gfwd+ge)*(Ee-V) + gi*(Ei-V))/tau +  mu/tau + (sigma * xi) / (tau **.5) : volt
              Vt : volt 
              dge /dt = -ge/tau_e : 1
              dgfwd /dt = -gfwd/tau_e : 1
              dgi /dt = -gi/tau_i : 1

              Asum : 1
              
              sigma: volt (constant)
              mu : volt (constant)
              '''

nrnEE_thrshld = 'V > Vt'

nrnEE_reset = 'V = Vr_e'

synEE_mod = '''
            a : 1
            syn_active : integer

            dApre  /dt = -Apre/taupre  : 1 (event-driven)
            dApost /dt = -Apost/taupost : 1 (event-driven)

            Asum_post = a : 1 (summed)         
            insert_P : 1 (shared) 
            p_inactivate : 1 (shared)
            '''

synEE_p_activate = '''
                   r = rand()
                   syn_active = int(r < p_ee)
                   a = syn_active*a
                   '''

synEE_pre = '''
            ge_post += syn_active*a
            Apre += syn_active*Aplus
            '''

synEE_post = '''
             Apost+= syn_active*Aminus
             '''


        
set_device('cpp_standalone', directory='./builds/0000',
           build_on_run=False)



T = T1 + T2 + T3


neuron_model = condlif_memnoise

GExc = NeuronGroup(N=N_e, model=neuron_model,
                   threshold=nrnEE_thrshld,
                   reset=nrnEE_reset)
GInh = NeuronGroup(N=N_i, model=neuron_model,
                   threshold ='V > Vt',
                   reset='V=Vr_i')

GExc.mu, GInh.mu = mu_e, mu_i
GExc.sigma, GInh.sigma = sigma_e, sigma_i

GExc.Vt, GInh.Vt = Vt_e, Vt_i
GExc.V , GInh.V  = np.random.uniform(Vr_e/mV, Vt_e/mV,
                                     size=N_e)*mV, \
                   np.random.uniform(Vr_i/mV, Vt_i/mV,
                                     size=N_i)*mV


synEE_pre_mod = synEE_pre
synEE_post_mod = synEE_post


SynEE = Synapses(target=GExc, source=GExc, model=synEE_mod,
                 on_pre=synEE_pre_mod, on_post=synEE_post_mod)


SynEE.connect(p=1)


SynEE.a = a_ee        
SynEE.insert_P = insert_P
SynEE.p_inactivate = p_inactivate

# this causes problems when T2 is large!
# compare T2 = 100000*second with T2= 100*second
SynEE.run_regularly(synEE_p_activate, dt=T, when='start',
                    order=-100)


net = Network(GExc, GInh, SynEE)


net.run(T1, report='text')

net.run(T2, report='text')

net.run(T3, report='text')


device.build(directory='builds/0000', clean=True,
             compile=True, run=True, debug=False)
   
```
    
        




diff --git a/brian2/core/clocks.py b/brian2/core/clocks.py
index d2f051de..d6ecdf73 100644
--- a/brian2/core/clocks.py
+++ b/brian2/core/clocks.py
@@ -36,8 +36,7 @@ def check_dt(new_dt, old_dt, target_t):
     ------
     ValueError
         If using the new dt value would lead to a difference in the target
-        time of more than `Clock.epsilon_dt` times ``new_dt`` (by default,
-        0.01% of the new dt).
+        time of more than `Clock.epsilon_dt` (by default, 10ns).
 
     Examples
     --------
@@ -52,7 +51,7 @@ def check_dt(new_dt, old_dt, target_t):
     old_t = np.int64(np.round(target_t / old_dt)) * old_dt
     new_t = np.int64(np.round(target_t / new_dt)) * new_dt
     error_t = target_t
-    if abs(new_t - old_t)/new_dt > Clock.epsilon_dt:
+    if abs(new_t - old_t) > Clock.epsilon_dt:
         raise ValueError(('Cannot set dt from {old} to {new}, the '
                           'time {t} is not a multiple of '
                           '{new}').format(old=str(old_dt * second),
@@ -74,10 +73,8 @@ class Clock(VariableOwner):
     Notes
     -----
     Clocks are run in the same `Network.run` iteration if `~Clock.t` is the
-    same. The condition for two
-    clocks to be considered as having the same time is
-    ``abs(t1-t2)<epsilon*abs(t1)``, a standard test for equality of floating
-    point values. The value of ``epsilon`` is ``1e-14``.
+    same. The condition for two clocks to be considered as having the same time
+    is ``abs(t1-t2)<10*ns``.
     '''
 
     def __init__(self, dt, name='clock*'):
@@ -121,7 +118,7 @@ def _set_t_update_dt(self, target_t=0*second):
     def _calc_timestep(self, target_t):
         '''
         Calculate the integer time step for the target time. If it cannot be
-        exactly represented (up to 0.01% of dt), round up.
+        exactly represented (up to 10ns), round up.
 
         Parameters
         ----------
@@ -136,7 +133,7 @@ def _calc_timestep(self, target_t):
         new_i = np.int64(np.round(target_t / self.dt_))
         new_t = new_i * self.dt_
         if (new_t == target_t or
-                        np.abs(new_t - target_t)/self.dt_ <= Clock.epsilon_dt):
+                        np.abs(new_t - target_t) <= Clock.epsilon_dt):
             new_timestep = new_i
         else:
             new_timestep = np.int64(np.ceil(target_t / self.dt_))
@@ -189,9 +186,9 @@ def set_interval(self, start, end):
                                      self._i_end),
                         'many_timesteps')
 
-    #: The relative difference for times (in terms of dt) so that they are
+    #: The absolute difference for times (in seconds) so that clocks are
     #: considered identical.
-    epsilon_dt = 1e-4
+    epsilon_dt = 1e-8
 
 
 class DefaultClockProxy(object):
diff --git a/brian2/core/network.py b/brian2/core/network.py
index 1c7084de..bf5b9fc2 100644
--- a/brian2/core/network.py
+++ b/brian2/core/network.py
@@ -877,7 +877,7 @@ def _nextclocks(self):
         minclock, min_time, minclock_dt = min(clocks_times_dt, key=lambda k: k[1])
         curclocks = set(clock for clock, time, dt in clocks_times_dt if
                         (time == min_time or
-                         abs(time - min_time)/min(minclock_dt, dt) < Clock.epsilon_dt))
+                         abs(time - min_time) < Clock.epsilon_dt))
         return minclock, curclocks
 
     @device_override('network_run')
diff --git a/brian2/devices/cpp_standalone/brianlib/clocks.h b/brian2/devices/cpp_standalone/brianlib/clocks.h
index b3316830..1617f98f 100644
--- a/brian2/devices/cpp_standalone/brianlib/clocks.h
+++ b/brian2/devices/cpp_standalone/brianlib/clocks.h
@@ -19,7 +19,7 @@ class Clock
 	double *dt;
 	int64_t *timestep;
 	double *t;
-	Clock(double _epsilon=1e-14) : epsilon(_epsilon) { i_end = 0;};
+	Clock(double _epsilon=1e-8) : epsilon(_epsilon) { i_end = 0;};
     inline void tick()
     {
         timestep[0] += 1;
@@ -30,18 +30,18 @@ class Clock
 	{
         int i_start = fround(start/dt[0]);
         double t_start = i_start*dt[0];
-        if(t_start==start || fabs(t_start-start)<=epsilon*fabs(t_start))
+        if(t_start==start || fabs(t_start-start)<=epsilon)
         {
             timestep[0] = i_start;
         } else
         {
-            timestep[0] = (int)ceil(start/dt[0]);
+            timestep[0] = (int64_t)ceil(start/dt[0]);
         }
         i_end = fround(end/dt[0]);
         double t_end = i_end*dt[0];
-        if(!(t_end==end || fabs(t_end-end)<=epsilon*fabs(t_end)))
+        if(!(t_end==end || fabs(t_end-end)<=epsilon))
         {
-            i_end = (int)ceil(end/dt[0]);
+            i_end = (int64_t)ceil(end/dt[0]);
         }
 	}
 private:
diff --git a/brian2/devices/cpp_standalone/templates/network.cpp b/brian2/devices/cpp_standalone/templates/network.cpp
index 197d8469..fad9301f 100644
--- a/brian2/devices/cpp_standalone/templates/network.cpp
+++ b/brian2/devices/cpp_standalone/templates/network.cpp
@@ -7,8 +7,6 @@
 #include<utility>
 {{ openmp_pragma('include') }}
 
-#define Clock_epsilon 1e-14
-
 double Network::_last_run_time = 0.0;
 double Network::_last_run_completed_fraction = 0.0;
 
@@ -158,7 +156,7 @@ Clock* Network::next_clocks()
     {
         Clock *clock = *i;
         double s = clock->t[0];
-        if(s==t || fabs(s-t)<=Clock_epsilon)
+        if(s==t || fabs(s-t) <= clock->epsilon)
             curclocks.insert(clock);
     }
     return minclock;
diff --git a/brian2/devices/cpp_standalone/templates/objects.cpp b/brian2/devices/cpp_standalone/templates/objects.cpp
index a6fc2d5a..c9d9f74a 100644
--- a/brian2/devices/cpp_standalone/templates/objects.cpp
+++ b/brian2/devices/cpp_standalone/templates/objects.cpp
@@ -59,7 +59,7 @@ SynapticPathway {{path.name}}(
 
 //////////////// clocks ///////////////////
 {% for clock in clocks | sort(attribute='name') %}
-Clock {{clock.name}};  // attributes will be set in run.cpp
+Clock {{clock.name}}({{clock.epsilon_dt}});  // attributes will be set in run.cpp
 {% endfor %}
 
 {% if profiled_codeobjects is defined %}
diff --git a/brian2/tests/test_clocks.py b/brian2/tests/test_clocks.py
index eba9c96b..1607123e 100644
--- a/brian2/tests/test_clocks.py
+++ b/brian2/tests/test_clocks.py
@@ -59,6 +59,31 @@ def test_set_interval_warning():
     assert logs[0][1].endswith('many_timesteps')
 
 
+@attr('codegen-independent')
+def test_very_long_dt():
+    # See github issue #1054
+    clock1 = Clock(dt=0.1*ms)
+    clock2 = Clock(dt=100000*second)
+    clock1.set_interval(0*ms, 1*ms)
+    clock2.set_interval(0*ms, 1*ms)  # The clock should advance
+    assert clock1.timestep[:] == 0
+    assert clock2.timestep[:] == 0
+    assert clock1._i_end == 10
+    assert clock2._i_end == 1
+    # Simulate advancing the clock
+    clock1.variables['timestep'].set_value(clock1._i_end)
+    clock1.variables['t'].set_value(clock1._i_end * clock1.dt)
+    clock2.variables['timestep'].set_value(clock2._i_end)
+    clock2.variables['t'].set_value(clock2._i_end * clock2.dt)
+
+    clock1.set_interval(1*ms, 2*ms)
+    clock2.set_interval(1*ms, 2*ms)  # The clock should not advance
+    assert clock1.timestep[:] == 10
+    assert clock2.timestep[:] == 1
+    assert clock1._i_end == 20
+    assert clock2._i_end == 1
+
+
 if __name__ == '__main__':
     test_clock_attributes()
     restore_initial_state()
@@ -66,3 +91,4 @@ def test_set_interval_warning():
     restore_initial_state()
     test_defaultclock()
     test_set_interval_warning()
+    test_very_long_dt()
diff --git a/brian2/tests/test_network.py b/brian2/tests/test_network.py
index 175440fe..bed2b367 100644
--- a/brian2/tests/test_network.py
+++ b/brian2/tests/test_network.py
@@ -1372,6 +1372,24 @@ def test_small_runs():
     assert_allclose(mon_1.t_[:], mon_2.t_[:])
     assert_allclose(mon_1.v_[:], mon_2.v_[:])
 
+@attr('standalone-compatible')
+@with_setup(teardown=reinit_devices)
+def test_long_run():
+    defaultclock.dt = 0.1 * ms
+    group = NeuronGroup(1, 'x : 1')
+    group.run_regularly('x += 1')
+    # Timesteps are internally stored as 64bit integers, but previous versions
+    # converted them into 32bit integers along the way. We'll make sure that
+    # this is not the case and everything runs fine. To not actually run such a
+    # long simulation we manually advance the clock.
+    net = Network(group, name='network')
+    start_step = 2**31-5
+    start_time = start_step*defaultclock.dt_
+    with catch_logs() as l:
+        net.t_ = start_time  # for runtime
+        device.insert_code('main', 'network.t = {};'.format(start_time))  # for standalone
+        net.run(6 * defaultclock.dt)
+    assert group.x == 6
 
 @attr('codegen-independent')
 @with_setup(teardown=reinit_devices)
@@ -1409,6 +1427,7 @@ def test_multiple_runs_function_change():
     device.build(direct_call=False, **device.build_options)
     assert_equal(mon.v[0], [1, 2, 3, 4])
 
+
 if __name__ == '__main__':
     BrianLogger.log_level_warn()
     for t in [
@@ -1470,6 +1489,7 @@ def test_multiple_runs_function_change():
             test_magic_scope,
             test_runtime_rounding,
             test_small_runs,
+            test_long_run,
             test_long_run_dt_change,
             test_multiple_runs_constant_change,
             test_multiple_runs_function_change
['brian2/devices/cpp_standalone/templates/objects.cpp', 'brian2/tests/test_network.py', 'brian2/devices/cpp_standalone/templates/network.cpp', 'brian2/devices/cpp_standalone/brianlib/clocks.h', 'brian2/core/clocks.py', 'brian2/tests/test_clocks.py', 'brian2/core/network.py']