Active object: Difference between revisions

m
Alphabetize; try this again
(Undo revision 277235 by Thundergnat (talk) Wow, I completely screwed that up)
m (Alphabetize; try this again)
Line 1,260:
v2 = it.runningsum
println("After 2.5 seconds, integrator value was $v2")</lang>
 
=={{header|Lingo}}==
Parent script "Integrator":
<lang Lingo>property _sum
property _func
property _timeLast
property _valueLast
property _ms0
property _updateTimer
 
on new (me, func)
if voidP(func) then func = "0.0"
me._sum = 0.0
-- update frequency: 100/sec (arbitrary)
me._updateTimer = timeout().new("update", 10, #_update, me)
me.input(func)
return me
end
 
on stop (me)
me._updateTimer.period = 0 -- deactivates timer
end
 
-- func is a term (as string) that might contain "t" and is evaluated at runtime
on input (me, func)
me._func = func
me._ms0 = _system.milliseconds
me._timeLast = 0.0
t = 0.0
me._valueLast = value(me._func)
end
 
on output (me)
return me._sum
end
 
on _update (me)
now = _system.milliseconds - me._ms0
t = now/1000.0
val = value(me._func)
me._sum = me._sum + (me._valueLast+val)*(t - me._timeLast)/2
me._timeLast = t
me._valueLast = val
end</lang>
 
In some movie script:
<lang Lingo>global gIntegrator
 
-- entry point
on startMovie
gIntegrator = script("Integrator").new("sin(PI * t)")
timeout().new("timer", 2000, #step1)
end
 
on step1 (_, timer)
gIntegrator.input("0.0")
timer.timeoutHandler = #step2
timer.period = 500
end
 
on step2 (_, timer)
gIntegrator.stop()
put gIntegrator.output()
timer.forget()
end</lang>
 
{{out}}
<pre>-- 0.0004</pre>
 
=={{header|Kotlin}}==
Line 1,407 ⟶ 1,339:
</pre>
 
=={{header|MathematicaLingo}}==
Parent script "Integrator":
<lang Mathematica>Block[{start = SessionTime[], K, t0 = 0, t1, kt0, S = 0},
<lang Lingo>property _sum
K[t_] = Sin[2 Pi f t] /. f -> 0.5; kt0 = K[t0];
property _func
While[True, t1 = SessionTime[] - start;
property _timeLast
S += (kt0 + (kt0 = K[t1])) (t1 - t0)/2; t0 = t1;
property _valueLast
If[t1 > 2, K[t_] = 0; If[t1 > 2.5, Break[]]]]; S]</lang>
property _ms0
property _updateTimer
 
on new (me, func)
1.1309*10^-6
if voidP(func) then func = "0.0"
me._sum = 0.0
-- update frequency: 100/sec (arbitrary)
me._updateTimer = timeout().new("update", 10, #_update, me)
me.input(func)
return me
end
 
on stop (me)
Curiously, this value never changes; it is always exactly the same (at 1.1309E-6). Note that closer answers could be achieved by using Mathematica's better interpolation methods, but it would require collecting the data (in a list), which would have a speed penalty large enough to negate the improved estimation.
me._updateTimer.period = 0 -- deactivates timer
end
 
-- func is a term (as string) that might contain "t" and is evaluated at runtime
=={{header|Oz}}==
on input (me, func)
<lang oz>declare
me._func = func
fun {Const X}
me._ms0 = _system.milliseconds
fun {$ _} X end
me._timeLast = 0.0
end
t = 0.0
me._valueLast = value(me._func)
end
 
on output (me)
fun {Now}
return me._sum
{Int.toFloat {Property.get 'time.total'}} / 1000.0
end
 
on _update (me)
class Integrator from Time.repeat
now = _system.milliseconds - me._ms0
attr
t = k:{Const 0now/1000.0}
val = s:0value(me.0_func)
me._sum = me._sum + (me._valueLast+val)*(t - me._timeLast)/2
t1 k_t1
me._timeLast = t2 k_t2t
me._valueLast = val
end</lang>
meth init(SampleIntervalMS)
t1 := {Now}
k_t1 := {@k @t1}
{self setRepAll(action:Update
delay:SampleIntervalMS)}
thread
{self go}
end
end
 
In some movie script:
meth input(K)
<lang Lingo>global gIntegrator
k := K
end
 
-- entry point
meth output($)
on startMovie
@s
gIntegrator = script("Integrator").new("sin(PI * t)")
end
timeout().new("timer", 2000, #step1)
end
 
on step1 (_, timer)
meth Update
gIntegrator.input("0.0")
t2 := {Now}
timer.timeoutHandler = #step2
k_t2 := {@k @t2}
timer.period = 500
s := @s + (@k_t1 + @k_t2) * (@t2 - @t1) / 2.0
end
t1 := @t2
k_t1 := @k_t2
end
end
 
on step2 (_, timer)
Pi = 3.14159265
F = 0gIntegrator.5stop()
put gIntegrator.output()
timer.forget()
end</lang>
 
{{out}}
I = {New Integrator init(10)}
<pre>-- 0.0004</pre>
in
{I input(fun {$ T}
{Sin 2.0 * Pi * F * T}
end)}
 
=={{header|Mathematica}}==
{Delay 2000} %% ms
<lang Mathematica>Block[{start = SessionTime[], K, t0 = 0, t1, kt0, S = 0},
K[t_] = Sin[2 Pi f t] /. f -> 0.5; kt0 = K[t0];
While[True, t1 = SessionTime[] - start;
S += (kt0 + (kt0 = K[t1])) (t1 - t0)/2; t0 = t1;
If[t1 > 2, K[t_] = 0; If[t1 > 2.5, Break[]]]]; S]</lang>
 
1.1309*10^-6
{I input({Const 0.0})}
 
Curiously, this value never changes; it is always exactly the same (at 1.1309E-6). Note that closer answers could be achieved by using Mathematica's better interpolation methods, but it would require collecting the data (in a list), which would have a speed penalty large enough to negate the improved estimation.
{Delay 500} %% ms
 
{Show {I output($)}}
{I stop}</lang>
 
=={{header|ooRexx}}==
Line 1,560 ⟶ 1,498:
 
</lang>
 
=={{header|Perl}}==
<lang perl>#!/usr/bin/perl
 
use strict;
use 5.10.0;
 
package Integrator;
use threads;
use threads::shared;
 
sub new {
my $cls = shift;
my $obj = bless { t => 0,
sum => 0,
ref $cls ? %$cls : (),
stop => 0,
tid => 0,
func => shift,
}, ref $cls || $cls;
 
share($obj->{sum});
share($obj->{stop});
 
$obj->{tid} = async {
my $upd = 0.1; # update every 0.1 second
while (!$obj->{stop}) {
{
my $f = $obj->{func};
my $t = $obj->{t};
 
$obj->{sum} += ($f->($t) + $f->($t + $upd))* $upd/ 2;
$obj->{t} += $upd;
}
select(undef, undef, undef, $upd);
}
# say "stopping $obj";
};
$obj
}
 
sub output { shift->{sum} }
 
sub delete {
my $obj = shift;
$obj->{stop} = 1;
$obj->{tid}->join;
}
 
sub setinput {
# This is surprisingly difficult because of the perl sharing model.
# Func refs can't be shared, thus can't be replaced by another thread.
# Have to create a whole new object... there must be a better way.
my $obj = shift;
$obj->delete;
$obj->new(shift);
}
 
package main;
 
my $x = Integrator->new(sub { sin(atan2(1, 1) * 8 * .5 * shift) });
 
sleep(2);
say "sin after 2 seconds: ", $x->output;
 
$x = $x->setinput(sub {0});
 
select(undef, undef, undef, .5);
say "0 after .5 seconds: ", $x->output;
 
$x->delete;</lang>
 
=={{header|Perl 6}}==
{{works with|Rakudo|2018.12}}
There is some jitter in the timer, but it is typically accurate to within a few thousandths of a second.
 
<lang perl6>class Integrator {
has $.f is rw = sub ($t) { 0 };
has $.now is rw;
has $.value is rw = 0;
has $.integrator is rw;
 
method init() {
self.value = &(self.f)(0);
self.integrator = Thread.new(
:code({
loop {
my $t1 = now;
self.value += (&(self.f)(self.now) + &(self.f)($t1)) * ($t1 - self.now) / 2;
self.now = $t1;
sleep .001;
}
}),
:app_lifetime(True)
).run
}
 
method Input (&f-of-t) {
self.f = &f-of-t;
self.init;
self.now = now;
}
 
method Output { self.value }
}
 
my $a = Integrator.new;
 
$a.Input( sub ($t) { sin(2 * π * .5 * $t) } );
 
say "Initial value: ", $a.Output;
 
sleep 2;
 
say "After 2 seconds: ", $a.Output;
 
$a.Input( sub ($t) { 0 } );
 
sleep .5;
 
say "f(0): ", $a.Output;</lang>
 
{{out|Typical output}}
<pre>Initial value: 0
After 2 seconds: -0.0005555887464620366
f(0): 0</pre>
 
=={{header|OxygenBasic}}==
Line 1,865 ⟶ 1,677:
 
Rudolpho.clear</lang>
 
=={{header|Oz}}==
<lang oz>declare
fun {Const X}
fun {$ _} X end
end
 
fun {Now}
{Int.toFloat {Property.get 'time.total'}} / 1000.0
end
 
class Integrator from Time.repeat
attr
k:{Const 0.0}
s:0.0
t1 k_t1
t2 k_t2
meth init(SampleIntervalMS)
t1 := {Now}
k_t1 := {@k @t1}
{self setRepAll(action:Update
delay:SampleIntervalMS)}
thread
{self go}
end
end
 
meth input(K)
k := K
end
 
meth output($)
@s
end
 
meth Update
t2 := {Now}
k_t2 := {@k @t2}
s := @s + (@k_t1 + @k_t2) * (@t2 - @t1) / 2.0
t1 := @t2
k_t1 := @k_t2
end
end
 
Pi = 3.14159265
F = 0.5
 
I = {New Integrator init(10)}
in
{I input(fun {$ T}
{Sin 2.0 * Pi * F * T}
end)}
 
{Delay 2000} %% ms
 
{I input({Const 0.0})}
 
{Delay 500} %% ms
 
{Show {I output($)}}
{I stop}</lang>
 
=={{header|Perl}}==
<lang perl>#!/usr/bin/perl
 
use strict;
use 5.10.0;
 
package Integrator;
use threads;
use threads::shared;
 
sub new {
my $cls = shift;
my $obj = bless { t => 0,
sum => 0,
ref $cls ? %$cls : (),
stop => 0,
tid => 0,
func => shift,
}, ref $cls || $cls;
 
share($obj->{sum});
share($obj->{stop});
 
$obj->{tid} = async {
my $upd = 0.1; # update every 0.1 second
while (!$obj->{stop}) {
{
my $f = $obj->{func};
my $t = $obj->{t};
 
$obj->{sum} += ($f->($t) + $f->($t + $upd))* $upd/ 2;
$obj->{t} += $upd;
}
select(undef, undef, undef, $upd);
}
# say "stopping $obj";
};
$obj
}
 
sub output { shift->{sum} }
 
sub delete {
my $obj = shift;
$obj->{stop} = 1;
$obj->{tid}->join;
}
 
sub setinput {
# This is surprisingly difficult because of the perl sharing model.
# Func refs can't be shared, thus can't be replaced by another thread.
# Have to create a whole new object... there must be a better way.
my $obj = shift;
$obj->delete;
$obj->new(shift);
}
 
package main;
 
my $x = Integrator->new(sub { sin(atan2(1, 1) * 8 * .5 * shift) });
 
sleep(2);
say "sin after 2 seconds: ", $x->output;
 
$x = $x->setinput(sub {0});
 
select(undef, undef, undef, .5);
say "0 after .5 seconds: ", $x->output;
 
$x->delete;</lang>
 
=={{header|Perl 6}}==
{{works with|Rakudo|2018.12}}
There is some jitter in the timer, but it is typically accurate to within a few thousandths of a second.
 
<lang perl6>class Integrator {
has $.f is rw = sub ($t) { 0 };
has $.now is rw;
has $.value is rw = 0;
has $.integrator is rw;
 
method init() {
self.value = &(self.f)(0);
self.integrator = Thread.new(
:code({
loop {
my $t1 = now;
self.value += (&(self.f)(self.now) + &(self.f)($t1)) * ($t1 - self.now) / 2;
self.now = $t1;
sleep .001;
}
}),
:app_lifetime(True)
).run
}
 
method Input (&f-of-t) {
self.f = &f-of-t;
self.init;
self.now = now;
}
 
method Output { self.value }
}
 
my $a = Integrator.new;
 
$a.Input( sub ($t) { sin(2 * π * .5 * $t) } );
 
say "Initial value: ", $a.Output;
 
sleep 2;
 
say "After 2 seconds: ", $a.Output;
 
$a.Input( sub ($t) { 0 } );
 
sleep .5;
 
say "f(0): ", $a.Output;</lang>
 
{{out|Typical output}}
<pre>Initial value: 0
After 2 seconds: -0.0005555887464620366
f(0): 0</pre>
 
=={{header|PicoLisp}}==
10,333

edits