summaryrefslogtreecommitdiff
path: root/ringbuf.h
blob: 5756153c494a13136d754202c0f8ae49e4eb24d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <math.h>

class Ringbuffer
{
	public:

	Ringbuffer(int size)
	{
		this->size = size;
		idx = 0;
		buf = new double[size];
		for (int i=0; i<size; i++)
			buf[i] = 0;
		avg = 0.0;
		avg_valid = false;
	}

	~Ringbuffer()
	{
		delete [] buf;
	}

	double get()
	{
		if (!avg_valid)
		{
			avg=0.0;
			for (int i=0; i<size; i++)
				avg += buf[i];
			avg/=size;
			avg_valid=true;
		}

		return avg;
	}

	void put(double val)
	{
		buf[idx] = val;
		idx = (idx+1) % size;
		avg_valid = false;
	}

	void set(double val)
	{
		for (int i=0; i<size; i++)
			buf[i]=val;
		avg = val;
		avg_valid=true;
	}

	void add(double val)
	{
		for (int i=0; i<size; i++)
			buf[i]+=val;
		avg += val;
	}

	private:
		double* buf;
		int idx;
		int size;
		double avg;
		bool avg_valid;
};

class ModuloRingbuffer
{
	private:
		Ringbuffer* rb;
		double low,upp,span;

	public:
	
	ModuloRingbuffer(int size, double low, double upp)
	{
		rb = new Ringbuffer(size);
		this->low=low;
		this->upp=upp;
		this->span=upp-low;
		rb->set(_fixup_range(0.0));
	}

	~ModuloRingbuffer()
	{
		delete rb;
	}

	double _fixup_range(double val)
	{
		while (val < low) val+=span;
		while (val>= upp) val-=span;
		return val;
	}

	double get()
	{
		return rb->get();
	}

	void put(double val)
	{
		val=_fixup_range(val);

		// direct way
		double dist1 = val - get();
		// over borders
		double dist2 = dist1 + span;
		double dist3 = dist1 - span;

		if (fabs(dist1) <= fabs(dist2) && fabs(dist1) <= fabs(dist3))
			rb->put(val);
		else if (fabs(dist2) <= fabs(dist3))
			rb->put(val+span);
		else
			rb->put(val-span);

		while (get() < low) rb->add(span);
		while (get()>= upp) rb->add(-span);
	}

	void set(double val)
	{
		rb->set(_fixup_range(val));
	}
};