What does gen~ phasor() do? (Translating Max/MSP gen to C++) - c++

We have two places in the same gen~ code box object with phasor:
wander = phasor(in8/dense);
...some code later...
phas = (triangle(phasor(freq), sharp)*len-rot_x/(2*pi))%1;
I understand that phasor() produces a rising sawtooth, outputting values of 0 to 1. I understand the argument of phasor() is frequency. What I don't understand is how phasor() can output a value of 0 to 1 given frequency, when you would need frequency over time to produce a value other than 0. It would seem that phasor(frequency) should always output 0 unless somehow phasor() is keeping track of time and its own phase.
If phasor is keeping track of time/phase, how can we call phasor() twice in the same gen code box? It would seem impossible that we could have two time values. Unless...
...we have one time/phase value shared between all calls to phasor() but it is the last call to phasor() that sets the final frequency before phasor() increments its phase, which happens at the end of the code block.
Am I correct?
Edit: No that can't be, then why would you ever put a frequency into phasor twice? It wouldn't change the output under my logic.

From my tests, phasor is indeed a sawtooth oscillator object where each call to phasor is a unique oscillator, so, calling phasor twice in the same code box will instantiate two objects.
class Phasor
{
public:
double getSample()
{
double ret = phase/PI_z_2;
phase = fmod(phase+phase_inc, TAU); //increment phase
return ret;
}
void setSampleRate(double v) { sampleRate = v; calculateIncrement(); }
void setFrequency(double v) { frequency = v; calculateIncrement(); }
void reset() { phase = 0.0; }
protected:
void calculateIncrement() { phase_inc = TAU * frequency / sampleRate; }
double sampleRate = 44100.0;
double frequency = 1.0;
double phase = 0.0;
double phase_inc = 0.0;
const double TAU = 2*PI;
const double PI_z_2 = PI/2.0;
};

Related

Optimize estimating Pi function C++

I've wrote a program, that approximates Pi using the Monte-Carlo method. It is working fine, but I wonder if I can make it work better and faster, because when inserting something like ~n = 100000000 and bigger from that point, it takes some time to do the calculations and print the result.
I've imagined how I could try to approximate it better by doing a median for n results, but considering how slow my algorithm is for big numbers, I decided not doing so.
Basically, the question is: How can I make this function work faster?
Here is the code that I've got so far:
double estimate_pi(double n)
{
int i;
double x,y, distance;
srand( (unsigned)time(0));
double num_point_circle = 0;
double num_point_total = 0;
double final;
for (i=0; i<n; i++)
{
x = (double)rand()/RAND_MAX;
y = (double)rand()/RAND_MAX;
distance = sqrt(x*x + y*y);
if (distance <= 1)
{
num_point_circle+=1;
}
num_point_total+=1;
}
final = ((4 * num_point_circle) / num_point_total);
return final;
}
An obvious (small) speedup is to get rid of the square root operation.
sqrt(x*x + y*y) is exactly smaller than 1, when x*x + y*y is also smaller than 1.
So you can just write:
double distance2 = x*x + y*y;
if (distance2 <= 1) {
...
}
That might gain something, as computing the square root is an expensive operation, and takes much more time (~4-20 times slower than one addition, depending on CPU, architecture, optimization level, ...).
You should also use integer values for variables where you count, like num_point_circle, n and num_point_total. Use int, long or long long for them.
The Monte Carlo algorithm is also embarrassingly parallel. So an idea to speed it up would be to run the algorithm with multiple threads, each one processes a fraction of n, and then at the end sum up the number of points that are inside the circle.
Additionally you could try to improve the speed with SIMD instructions.
And as last, there are much more efficient ways of computing Pi.
With the Monte Carlo method you can do millions of iterations, and only receive an accuracy of a couple of digits. With better algorithms its possible to compute thousands, millions or billions of digits.
E.g. you could read up on the on the website https://www.i4cy.com/pi/
First of all, you should modify the code to consider how much the estimate changes after a certain number of iterations and stop when it reached a satisfiying accuracy.
For your code as is, with a fixed number of iterations, there isnt much to optimize that the compiler cannot do better than you. One minor thing you can improve is to drop computing the square root in every iteration. You don't need it, because sqrt(x) <= 1 is true if x <= 1.
Very roughly speaking you can expect a good estimate from your Monte Carlo method once your x,y points are uniformly distributed in the quarter circle. Considering that, there is a much simpler way to get points uniformly distributed without randomness: Use a uniform grid and count how many points are inside the circle and how many are outside.
I would expect this to converge much better (when decreasing the grid spacing) than Monte Carlo. However, you can also try to use it to speed up your Monte Carlo code by starting from counts of num_point_circle and num_point_total obtained from points on a uniform grid and then incrementing the counters by continuing with randomly distributed points.
As the error decreases as the inverse of the square root of the number of samples, to gain a single digit you need one hundred times more samples. No micro-optimization will help significantly. Just consider that this method is of no use to effectively compute π.
If you insist: https://en.wikipedia.org/wiki/Variance_reduction.
A first level improvement would be to sample on a regular grid, using brute force algorithm, as suggested by 463035818_is_not_a_number.
The next level improvement would be to "draw" just a semi circle for each 'x', counting how many points must be below y = sqrt(radius*radius - x*x).
This reduces the complexity from O(N^2) to O(N).
With the grid size == radius of 10, 100, 1000, 10000, etc, one should have about one digit of each step.
One of the problems with the rand() function being, that the numbers soon begin to repeat -- with regular grid and this O(N) turned problem we can even simulate a grid of the size of 2^32 in quite a reasonable time.
With ideas from Bresenham's Circle drawing algorithm we can even quickly evaluate if the candidate (x+1, y_previous) or (x+1, y_previous-1) should be selected, as only one of those is inside the circle for the first octant. For second some other hacks are needed to avoid sqrt.
How can I make this function work faster? not more precise!
when Monte Carlo is an estimate anyway and the final multiplication is a multiple of 2,4,8 and so on you can also do bit operations. Any if statement makes it slow, so trying to get rid of it. But when we increase 1 or nothing (0) anyway you can get rid of the statement and reduce it to simple math, which should be faster. When i is initialised before the loop, and we are counting up inside the loop, it can also be a while loop.
#include <time.h>
double estimate_alt_pi(double n){
uint64_t num_point_total = 0;
double x, y;
srand( (unsigned)time(0));
uint64_t num_point_circle = 0;
while (num_point_total<n) {
x = (double)rand()/RAND_MAX;
y = (double)rand()/RAND_MAX;
num_point_circle += (sqrt(x*x + y*y) <= 1);
num_point_total++; // +1.0 we don't need 'i'
}
return ((num_point_circle << 2) / (double)num_point_total); // x<<2 == x * 4
}
Benchmarked with Xcode on a mac, looks like.
extern uint64_t dispatch_benchmark(size_t count, void (^block)(void));
int main(int argc, const char * argv[]) {
size_t count = 1000000;
double input = 1222.52764523423;
__block double resultA;
__block double resultB;
uint64_t t = dispatch_benchmark(count,^{
resultA = estimate_pi(input);
});
uint64_t t2 = dispatch_benchmark(count,^{
resultB = estimate_alt_pi(input);
});
fprintf(stderr,"estimate_____pi=%f time used=%llu\n",resultA, t);
fprintf(stderr,"estimate_alt_pi=%f time used=%llu\n",resultB, t2);
return 0;
}
~1,35 times faster, or takes ~73% of the original time
but significant less difference when the given number is lower.
And also the whole algorithm works properly only up to inputs with maximal 7 digits which is because of the used data types. Below 2 digits it is even slower. So the whole Monte Carlo algo is indeed not really worth digging deeper, when it's only about speed while keeping some kind of reliability.
Literally nothing will be faster than using a #define or static with a fixed number as Pi, but that was not your question.
Your code is very bad from performance aspect as:
x = (double)rand()/RAND_MAX;
y = (double)rand()/RAND_MAX;
is converting between int and double, also using integer division ... Why not use Random() instead? Also this:
for (i=0; i<n; i++)
is a bad idea as n is double and i is int so either store n to int variable at start or change the header to int n. Btw why are you computing num_point_total when you already got n ? Also:
num_point_circle += (sqrt(x*x + y*y) <= 1);
is a bad idea why sqrt? you know 1^2 = 1 so you can simply do:
num_point_circle += (x*x + y*y <= 1);
Why not do continuous computing? ... so what you need to implement is:
load of state at app start
computation either in timer or OnIdle event
so in each iteration/even you will do N iterations of Pi (adding to some global sum and count)
save of state at app exit
Beware Monte Carlo Pi computation converges very slowly and you will hit floating point accuracy problems once the sum grows too big
Here small example I did a long time ago doing continuous Monte Carlo...
Form cpp:
//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "Unit1.h"
#include "performance.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
int i=0,n=0,n0=0;
//---------------------------------------------------------------------------
void __fastcall TForm1::Idleloop(TObject *Sender, bool &Done)
{
int j;
double x,y;
for (j=0;j<10000;j++,n++)
{
x=Random(); x*=x;
y=Random(); y*=y;
if (x+y<=1.0) i++;
}
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
tbeg();
Randomize();
Application->OnIdle = Idleloop;
}
//-------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
double dt;
AnsiString txt;
txt ="ref = 3.1415926535897932384626433832795\r\n";
if (n) txt+=AnsiString().sprintf("Pi = %.20lf\r\n",4.0*double(i)/double(n));
txt+=AnsiString().sprintf("i/n = %i / %i\r\n",i,n);
dt=tend();
if (dt>1e-100) txt+=AnsiString().sprintf("IPS = %8.0lf\r\n",double(n-n0)*1000.0/dt);
tbeg(); n0=n;
mm_log->Text=txt;
}
//---------------------------------------------------------------------------
Form h:
//$$---- Form HDR ----
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TMemo *mm_log;
TTimer *Timer1;
void __fastcall Timer1Timer(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
void __fastcall TForm1::Idleloop(TObject *Sender, bool &Done);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Form dfm:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Project Euler'
ClientHeight = 362
ClientWidth = 619
Color = clBtnFace
Font.Charset = OEM_CHARSET
Font.Color = clWindowText
Font.Height = 14
Font.Name = 'System'
Font.Pitch = fpFixed
Font.Style = [fsBold]
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 14
object mm_log: TMemo
Left = 0
Top = 0
Width = 619
Height = 362
Align = alClient
ScrollBars = ssBoth
TabOrder = 0
end
object Timer1: TTimer
Interval = 100
OnTimer = Timer1Timer
Left = 12
Top = 10
end
end
So you should add the save/load of state ...
As mentioned there are much much better ways of obtaining Pi like BBP
Also the code above use my time measurement heder so here it is:
//---------------------------------------------------------------------------
//--- Performance counter time measurement: 2.01 ----------------------------
//---------------------------------------------------------------------------
#ifndef _performance_h
#define _performance_h
//---------------------------------------------------------------------------
const int performance_max=64; // push urovni
double performance_Tms=-1.0, // perioda citaca [ms]
performance_tms=0.0, // zmerany cas po tend [ms]
performance_t0[performance_max]; // zmerane start casy [ms]
int performance_ix=-1; // index aktualneho casu
//---------------------------------------------------------------------------
void tbeg(double *t0=NULL) // mesure start time
{
double t;
LARGE_INTEGER i;
if (performance_Tms<=0.0)
{
for (int j=0;j<performance_max;j++) performance_t0[j]=0.0;
QueryPerformanceFrequency(&i); performance_Tms=1000.0/double(i.QuadPart);
}
QueryPerformanceCounter(&i); t=double(i.QuadPart); t*=performance_Tms;
if (t0) { t0[0]=t; return; }
performance_ix++;
if ((performance_ix>=0)&&(performance_ix<performance_max)) performance_t0[performance_ix]=t;
}
//---------------------------------------------------------------------------
void tpause(double *t0=NULL) // stop counting time between tbeg()..tend() calls
{
double t;
LARGE_INTEGER i;
QueryPerformanceCounter(&i); t=double(i.QuadPart); t*=performance_Tms;
if (t0) { t0[0]=t-t0[0]; return; }
if ((performance_ix>=0)&&(performance_ix<performance_max)) performance_t0[performance_ix]=t-performance_t0[performance_ix];
}
//---------------------------------------------------------------------------
void tresume(double *t0=NULL) // resume counting time between tbeg()..tend() calls
{
double t;
LARGE_INTEGER i;
QueryPerformanceCounter(&i); t=double(i.QuadPart); t*=performance_Tms;
if (t0) { t0[0]=t-t0[0]; return; }
if ((performance_ix>=0)&&(performance_ix<performance_max)) performance_t0[performance_ix]=t-performance_t0[performance_ix];
}
//---------------------------------------------------------------------------
double tend(double *t0=NULL) // return duration [ms] between matching tbeg()..tend() calls
{
double t;
LARGE_INTEGER i;
QueryPerformanceCounter(&i); t=double(i.QuadPart); t*=performance_Tms;
if (t0) { t-=t0[0]; performance_tms=t; return t; }
if ((performance_ix>=0)&&(performance_ix<performance_max)) t-=performance_t0[performance_ix]; else t=0.0;
performance_ix--;
performance_tms=t;
return t;
}
//---------------------------------------------------------------------------
double tper(double *t0=NULL) // return duration [ms] between tper() calls
{
double t,tt;
LARGE_INTEGER i;
if (performance_Tms<=0.0)
{
for (int j=0;j<performance_max;j++) performance_t0[j]=0.0;
QueryPerformanceFrequency(&i); performance_Tms=1000.0/double(i.QuadPart);
}
QueryPerformanceCounter(&i); t=double(i.QuadPart); t*=performance_Tms;
if (t0) { tt=t-t0[0]; t0[0]=t; performance_tms=tt; return tt; }
performance_ix++;
if ((performance_ix>=0)&&(performance_ix<performance_max))
{
tt=t-performance_t0[performance_ix];
performance_t0[performance_ix]=t;
}
else { t=0.0; tt=0.0; };
performance_ix--;
performance_tms=tt;
return tt;
}
//---------------------------------------------------------------------------
AnsiString tstr()
{
AnsiString s;
s=s.sprintf("%8.3lf",performance_tms); while (s.Length()<8) s=" "+s; s="["+s+" ms]";
return s;
}
//---------------------------------------------------------------------------
AnsiString tstr(int N)
{
AnsiString s;
s=s.sprintf("%8.3lf",performance_tms/double(N)); while (s.Length()<8) s=" "+s; s="["+s+" ms]";
return s;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
And here result after few seconds:
where IPS is iterations per second, i,n are the global variables holding actual state of computation, Pi is actual approximation and ref is refernce Pi value for comparison. As I computing in OnIdle and showing up in OnTimer there is no need for any locks as its all single thread. For more speed you could launch more computing threads however then you need to add multi threading lock mechanisms and have the global state as volatile.
In case you are doing console app (no forms) you still can do this just convert your code to infinite loop, recompute and output Pi value once in ??? iterations and stop on some key hit like escape.

PID Control: Is adding a delay before the next loop a good idea?

I am implementing PID control in c++ to make a differential drive robot turn an accurate number of degrees, but I am having many issues.
Exiting control loop early due to fast loop runtime
If the robot measures its error to be less than .5 degrees, it exits the control loop and consider the turn "finished" (the .5 is a random value that I might change at some point). It appears that the control loop is running so quickly that the robot can turn at a very high speed, turn past the setpoint, and exit the loop/cut motor powers, because it was at the setpoint for a short instant. I know that this is the entire purpose of PID control, to accurately reach the setpoint without overshooting, but this problem is making it very difficult to tune the PID constants. For example, I try to find a value of kp such that there is steady oscillation, but there is never any oscillation because the robot thinks it has "finished" once it passes the setpoint. To fix this, I have implemented a system where the robot has to be at the setpoint for a certain period of time before exiting, and this has been effective, allowing oscillation to occur, but the issue of exiting the loop early seems like an unusual problem and my solution may be incorrect.
D term has no effect due to fast runtime
Once I had the robot oscillating in a controlled manner using only P, I tried to add D to prevent overshoot. However, this was having no effect for the majority of the time, because the control loop is running so quickly that 19 loops out of 20, the rate of change of error is 0: the robot did not move or did not move enough for it to be measured in that time. I printed the change in error and the derivative term each loop to confirm this and I could see that these would both be 0 for around 20 loop cycles before taking a reasonable value and then back to 0 for another 20 cycles. Like I said, I think that this is because the loop cycles are so quick that the robot literally hasn't moved enough for any sort of noticeable change in error. This was a big problem because it meant that the D term had essentially no effect on robot movement because it was almost always 0. To fix this problem, I tried using the last non-zero value of the derivative in place of any 0 values, but this didn't work well, and the robot would oscillate randomly if the last derivative didn't represent the current rate of change of error.
Note: I am also using a small feedforward for the static coefficient of friction, and I call this feedforward "f"
Should I add a delay?
I realized that I think the source of both of these issues is the loop running very very quickly, so something I thought of was adding a wait statement at the end of the loop. However, it seems like an overall bad solution to intentionally slow down a loop. Is this a good idea?
turnHeading(double finalAngle, double kp, double ki, double kd, double f){
std::clock_t timer;
timer = std::clock();
double pastTime = 0;
double currentTime = ((std::clock() - timer) / (double)CLOCKS_PER_SEC);
const double initialHeading = getHeading();
finalAngle = angleWrapDeg(finalAngle);
const double initialAngleDiff = initialHeading - finalAngle;
double error = angleDiff(getHeading(), finalAngle);
double pastError = error;
double firstTimeAtSetpoint = 0;
double timeAtSetPoint = 0;
bool atSetpoint = false;
double integral = 0;
double derivative = 0;
double lastNonZeroD = 0;
while (timeAtSetPoint < .05)
{
updatePos(encoderL.read(), encoderR.read());
error = angleDiff(getHeading(), finalAngle);
currentTime = ((std::clock() - timer) / (double)CLOCKS_PER_SEC);
double dt = currentTime - pastTime;
double proportional = error / fabs(initialAngleDiff);
integral += dt * ((error + pastError) / 2.0);
double derivative = (error - pastError) / dt;
//FAILED METHOD OF USING LAST NON-0 VALUE OF DERIVATIVE
// if(epsilonEquals(derivative, 0))
// {
// derivative = lastNonZeroD;
// }
// else
// {
// lastNonZeroD = derivative;
// }
double power = kp * proportional + ki * integral + kd * derivative;
if (power > 0)
{
setMotorPowers(-power - f, power + f);
}
else
{
setMotorPowers(-power + f, power - f);
}
if (fabs(error) < 2)
{
if (!atSetpoint)
{
atSetpoint = true;
firstTimeAtSetpoint = currentTime;
}
else //at setpoint
{
timeAtSetPoint = currentTime - firstTimeAtSetpoint;
}
}
else //no longer at setpoint
{
atSetpoint = false;
timeAtSetPoint = 0;
}
pastTime = currentTime;
pastError = error;
}
setMotorPowers(0, 0);
}
turnHeading(90, .37, 0, .00004, .12);

C++ Using a sequence of values from 'for' loop one at a time in a consecutive order within another function

I would like to use a 'for' loop (OR anything that works for that matter) to generate a sequence of values.
I iterate many times and need to use values from the loop (OR anything that works) one at a time in a consequent manner. This values are used to represent 'time' value in an equation for population growth. Ultimately I am to have a chart representing solutions for calculations where 'time'is 1,2,3,4...60.
My question is: how to make the equation "value = a * exp(k * t)" consider t = 'time'as a new consecutive value from a vector that 'loop' generated ?
EDIT: I will try to clarify the set up - both reset and update act as iterations. In this specific case reset runs once and update runs n times. What I need is to use a consequent value of 'time' each iteration of update i.e. first time update runs the value of t = first value within the vector, second time update runs t = second value within the vector etc.
void ExponentialGrowth::reset() {update();}
void ExponentialGrowth::update() {value = a * exp(k * t); }
if t is integer type (0 to 60)
#include "math.h"
int a = 1;
int k = 2;
for(int time = 0; time < 60; ++time){
int value = a * exp(k * time);
}
if you have to pass the size juste make a function
void func(int _start, int _end){
int a = 1;
int k = 2;
for(int i = _start; i <= _end; ++i){
int value = a * exp(k * i);
}
}

How to measure the rate of rise of a variable

I am reading in a temperature value every 1 second/minute (this rate is not crucial). I want to measure this temperature so that if it begins to rise rapidly above a certain threshold I perform an action.
If the temperature rises above 30 degrees ( at any rate ) I increase the fan speed.
I think I must do something like set old temperature to new temp and then each time it loops set old temp to the current temp of the engine. But I am not sure if I need to use arrays for the engine temp or not.
Of course you can store just one old sample, then check difference like in:
bool isHot(int sample) {
static int oldSample = sample;
return ((sample > 30) || (sample - oldSample > threshold));
}
It's OK from C point of view, but very bad from metrology point of view. You should consider some conditioning of your signal (in this case temperature) to smothen out any spikes.
Of course you can add signal conditioning letter on. For (easy) example look at Simple Moving Avarage: https://en.wikipedia.org/wiki/Moving_average
If you want control the fan speed "right way" you should consider learning a bit about PID controller: https://en.wikipedia.org/wiki/PID_controller
Simple discrete PID:
PidController.h:
class PidController
{
public:
PidController();
double sim(double y);
void UpdateParams(double kp, double ki, double kd);
void setSP(double setPoint) { m_setPoint = setPoint; } //set current value of r(t)
private:
double m_setPoint; //current value of r(t)
double m_kp;
double m_ki;
double m_kd;
double m_outPrev;
double m_errPrev[2];
};
PidController.cpp
#include "PidController.h"
PidController::PidController():ControllerObject()
{
m_errPrev[0] = 0;
m_errPrev[1] = 0;
m_outPrev = 0;
}
void PidController::UpdateParams(double kp, double ki, double kd)
{
m_kp = kp;
m_ki = ki;
m_kd = kd;
}
//calculates PID output
//y - sample of y(t)
//returns sample of u(t)
double PidController::sim(double y)
{
double out; //u(t) sample
double e = m_setPoint - y; //error
out = m_outPrev + m_kp * (e - m_errPrev[0] + m_kd * (e - 2 * m_errPrev[0] + m_errPrev[1]) + m_ki * e);
m_outPrev = out; //store previous output
//store previous errors
m_errPrev[1] = m_errPrev[0];
m_errPrev[0] = e;
return out;
}

throughput networking estimation

How could I estimate the instantaneous throughput ? For example, in a way similar to what the browser does when downloading a file. It's not just a mean throughput, but rather the an instantaneous estimation, maybe with a 'moving average'. I'm looking for the algorithm, but you can specify it in c++. Ideally, it would not involve a thread (i.e., being continuously refreshed, say every second) but rather be only evaluated when the value is asked.
You can use an exponential moving average, as explained here, but I'll repeat the formula:
accumulator = (alpha * new_value) + (1.0 - alpha) * accumulator
To achieve an estimation, suppose you intend to query the computation every second, but you want an average over the last minute. Then, here would be one way to get that estimate:
struct AvgBps {
double rate_; // The average rate
double last_; // Accumulates bytes added until average is computed
time_t prev_; // Time of previous update
AvgBps () : rate_(0), last_(0), prev_(time(0)) {}
void add (unsigned bytes) {
time_t now = time(0);
if (now - prev_ < 60) { // The update is within the last minute
last_ += bytes; // Accumulate bytes into last
if (now > prev_) { // More than a second elapsed from previous
// exponential moving average
// the more time that has elapsed between updates, the more
// weight is assigned for the accumulated bytes
double alpha = (now - prev_)/60.0;
rate_ = (1 -alpha) * last_ + alpha * rate_;
last_ = 0; // Reset last_ (it has been averaged in)
prev_ = now; // Update prev_ to current time
}
} else { // The update is longer than a minute ago
rate_ = bytes; // Current update is average rate
last_ = 0; // Reset last_
prev_ = now; // Update prev_
}
}
double rate () {
add(0); // Compute rate by doing an update of 0 bytes
return rate_; // Return computed rate
}
};
You should actually use a monotonic clock instead of time.
You probably want a boxcar average.
Just keep the last n values, and average them. For each subsequent block, subtract out the oldest and add in the most recent. Note that for floating point values, you may get some aggregated error, in which case you might want to recalculate the total from scratch every m values. For integer values of course, you don't need something like that.