Question

I receive a buffer of data periodically that contains a number of values that are a fixed distance in time apart. I need to differentiate them. It is soo long since I did calculus at school ....

What I have come up with is this:

function DifferentiateBuffer(
  ABuffer: TDoubleDynArray; AVPS: integer): TDoubleDynArray;
var
  i: integer;
  dt, dy: double;
begin
  if (AVPS = 0) then exit;

  // calc the delta time
  dt := 1 / AVPS;

  // run through the whole buffer
  for i := 0 to high(ABuffer) do begin
    if (i = 0) then
      if (IsNan(FLastDiffValue) = false) then
        dy := ABuffer[0] - FLastDiffValue
      else
        dy := ABuffer[0]
    else
      dy := Abuffer[i] - ABuffer[i -1];

    result[i] := dy / dt
  end;

  // remember the last value for next time
  FLastDiffValue := ABuffer[high(ABuffer)];
end;

AVPS is values per second. A typical value for this would be between 10 and 100. The length of the buffers would typically be 500 to 1000 values.

I call the buffer time after time with new data which is continuous with the previous block of data, hence keeping the last value of the block for next time. That last value is set to NAN in a constructor.

Is what I have done correct? ie, will it differentiate the values properly?

I also need to integrate similar data ... what is that likely to look like?

Was it helpful?

Solution

I cannot find any faults in that.

The first value returned, on the first call will be (ABuffer[0] - 0.0) / dt which is based on the assumption that the signal starts with a zero. I presume that is what you intend.

Now, rather than asking the Stack Overflow community to check your code, you can do much better yourself. You should test the code to prove it is accurate. Test it using a unit testing framework, for example DUnitX. Feed the function values for which you can predict the output. For example, feed it values from y = x2, or y = sin(x).

The other great benefit of writing tests is that they can be executed again and again. As you develop your code you run the risk of introducing faults. The code might be correct today, but who knows whether it will still be correct after the modification you make tomorrow. If you have a strong test in place, you can defend against faults introduced during maintenance.

One comment on style is that you should not ever test = false or = true. The if statement operates on boolean expressions and so comparing against a boolean value is always rather pointless. I would write your test like this:

if not IsNan(FLastDiffValue) then
  dy := ABuffer[0] - FLastDiffValue
else
  dy := ABuffer[0]

or like this:

if IsNan(FLastDiffValue) then
  dy := ABuffer[0]
else
  dy := ABuffer[0] - FLastDiffValue
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top