This commit is contained in:
Ingy döt Net 2013-04-10 16:57:12 -07:00
parent 518da4a923
commit 764da6cbbb
6144 changed files with 83610 additions and 11 deletions

View file

@ -0,0 +1,101 @@
#include <iostream>
#include <stddef.h>
#include <assert.h>
using std::cout;
using std::endl;
class SMA {
public:
SMA(unsigned int period) :
period(period), window(new double[period]), head(NULL), tail(NULL),
total(0) {
assert(period >= 1);
}
~SMA() {
delete[] window;
}
// Adds a value to the average, pushing one out if nescessary
void add(double val) {
// Special case: Initialization
if (head == NULL) {
head = window;
*head = val;
tail = head;
inc(tail);
total = val;
return;
}
// Were we already full?
if (head == tail) {
// Fix total-cache
total -= *head;
// Make room
inc(head);
}
// Write the value in the next spot.
*tail = val;
inc(tail);
// Update our total-cache
total += val;
}
// Returns the average of the last P elements added to this SMA.
// If no elements have been added yet, returns 0.0
double avg() const {
ptrdiff_t size = this->size();
if (size == 0) {
return 0; // No entries => 0 average
}
return total / (double) size; // Cast to double for floating point arithmetic
}
private:
unsigned int period;
double * window; // Holds the values to calculate the average of.
// Logically, head is before tail
double * head; // Points at the oldest element we've stored.
double * tail; // Points at the newest element we've stored.
double total; // Cache the total so we don't sum everything each time.
// Bumps the given pointer up by one.
// Wraps to the start of the array if needed.
void inc(double * & p) {
if (++p >= window + period) {
p = window;
}
}
// Returns how many numbers we have stored.
ptrdiff_t size() const {
if (head == NULL)
return 0;
if (head == tail)
return period;
return (period + tail - head) % period;
}
};
int main(int argc, char * * argv) {
SMA foo(3);
SMA bar(5);
int data[] = { 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 };
for (int * itr = data; itr < data + 10; itr++) {
foo.add(*itr);
cout << "Added " << *itr << " avg: " << foo.avg() << endl;
}
cout << endl;
for (int * itr = data; itr < data + 10; itr++) {
bar.add(*itr);
cout << "Added " << *itr << " avg: " << bar.avg() << endl;
}
return 0;
}

View file

@ -0,0 +1,11 @@
(defun simple-moving-average (period &aux
(sum 0) (count 0) (values (make-list period)) (pointer values))
(setf (rest (last values)) values) ; construct circularity
(lambda (n)
(when (first pointer)
(decf sum (first pointer))) ; subtract old value
(incf sum n) ; add new value
(incf count)
(setf (first pointer) n)
(setf pointer (rest pointer)) ; advance pointer
(/ sum (min count period))))

View file

@ -0,0 +1,25 @@
import std.stdio, std.traits, std.algorithm;
auto sma(T, int period)() {
T[period] data = 0; // D FP are default-initialized to NaN
T sum = 0;
int index, nfilled;
// return (in T v) nothrow {
return delegate (in T v) nothrow {
sum += -data[index] + v;
data[index] = v;
index = (index + 1) % period;
nfilled = min(period, nfilled + 1);
return cast(CommonType!(T, float))sum / nfilled;
};
}
void main() {
auto s3 = sma!(int, 3)();
auto s5 = sma!(double, 5)();
foreach (e; [1, 2, 3, 4, 5, 5, 4, 3, 2, 1])
writefln("Added %d, sma(3) = %f, sma(5) = %f",
e, s3(e), s5(e));
}

View file

@ -0,0 +1,24 @@
import std.stdio, std.traits, std.algorithm;
struct SMA(T, int period) {
T[period] data = 0;
T sum = 0;
int index, nfilled;
auto opCall(in T v) pure nothrow {
sum += -data[index] + v;
data[index] = v;
index = (index + 1) % period;
nfilled = min(period, nfilled + 1);
return cast(CommonType!(T, float))sum / nfilled;
}
}
void main() {
SMA!(int, 3) s3;
SMA!(double, 5) s5;
foreach (e; [1, 2, 3, 4, 5, 5, 4, 3, 2, 1])
writefln("Added %d, sma(3) = %f, sma(5) = %f",
e, s3(e), s5(e));
}

View file

@ -0,0 +1,22 @@
pragma.enable("accumulator")
def makeMovingAverage(period) {
def values := ([null] * period).diverge()
var index := 0
var count := 0
def insert(v) {
values[index] := v
index := (index + 1) %% period
count += 1
}
/** Returns the simple moving average of the inputs so far, or null if there
have been no inputs. */
def average() {
if (count > 0) {
return accum 0 for x :notNull in values { _ + x } / count.min(period)
}
}
return [insert, average]
}

View file

@ -0,0 +1,33 @@
? for period in [3, 5] {
> def [insert, average] := makeMovingAverage(period)
> println(`Period $period:`)
> for value in [1,2,3,4,5,5,4,3,2,1] {
> insert(value)
> println(value, "\t", average())
> }
> println()
> }
Period 3:
1 1.0
2 1.5
3 2.0
4 3.0
5 4.0
5 4.666666666666667
4 4.666666666666667
3 4.0
2 3.0
1 2.0
Period 5:
1 1.0
2 1.5
3 2.0
4 2.5
5 3.0
5 3.8
4 4.2
3 4.2
2 3.8
1 3.0

View file

@ -0,0 +1,54 @@
#define std'dictionary'*.
#define std'basic'*.
#define std'collections'*.
#define std'patterns'*.
#class ESMARole
{
#field thePeriod.
#initializer : aPeriod
[
thePeriod := aPeriod.
]
#method + aNumber
[
self += NewInt32Value::aNumber.
#if (self count > thePeriod)?
[
self first_item'reduce.
].
#var aCount := self count.
#if (aCount == 0)?
[ ^ 0. ].
#var aSum := Summing::Real::0 start:Scan::self.
^ aSum / aCount.
]
}
#symbol SMA : aPeriod = __wrap(ESMARole::aPeriod, List).
// --- Program ---
#symbol Program =
[
#var SMA3 := SMA::3.
#var SMA5 := SMA::5.
loop &&from:1 &to:5 run: i =
[
'program'output << "sma3 + " << i << " = " << SMA3 + i.
'program'output << ",sma5 + " << i << " = " << SMA5 + i << "%n".
].
loop &&from:5 &to:1 &step:-1 run: i =
[
'program'output << "sma3 + " << i << " = " << SMA3 + i.
'program'output << ",sma5 + " << i << " = " << SMA5 + i << "%n".
].
].

View file

@ -0,0 +1,3 @@
>n=1000; m=100; x=random(1,n);
>x10=fold(x,ones(1,m)/m);
>x10=fftfold(x,ones(1,m)/m)[m:n]; // more efficient

View file

@ -0,0 +1,30 @@
>function store (x:number, v:vector, n:index) ...
$if cols(v)<n then return v|x;
$else
$ v=rotleft(v); v[-1]=x;
$ return v;
$endif;
$endfunction
>v=zeros(1,0); for k=1:20; v=store(k,v,10); mean(v), end;
1
1.5
2
2.5
3
3.5
4
4.5
5
5.5
6.5
7.5
8.5
9.5
10.5
11.5
12.5
13.5
14.5
15.5
>v
[ 11 12 13 14 15 16 17 18 19 20 ]