Returning a (multi-dimensional) Variant Array as a function result

I have a function that processes and returns a variant array. so far the array is one dimensional (I'll call it an array with one column), and everything works fine.  bwLPF function always takes in a one-column variant array, and will return a one column variant array.  See working code below for one-column arrays.  (For one column array: TimeHistory[0] := 0, TimeHistory[1] := 0.25, and so on..)

I want to expand this to array of variable number of columns.  Basically, I want the function to process each column by recursion.

I tried "NewButterworthLPF" (see below) without success.   Input for the new function was created as

    V := VarArrayCreate([0, 2], varVariant);
    V[0] := VarArrayCreate([0, VarArrayHighBound(FHistoryOriginal, 1)], varDouble);
    V[1] := VarArrayCreate([0, VarArrayHighBound(FHistoryOriginal, 1)], varDouble);
    V[2] := VarArrayCreate([0, VarArrayHighBound(FHistoryOriginal, 1)], varDouble);
    V[0] :=  History1;
    V[1] :=  History2;
    V[2] :=  History3;
    V := NewButterworthLPF(V, fs, fc, fOrder);

so, TimeHistory will look like:
TimeHistory[0][0] := 0, TimeHistory[0][1] := 0.21 and so on for column 0
TimeHistory[1][0] := 0, TimeHistory[1][1] := 0.05 and so on for column 1, etc


What am I missing ?  (also would it be better to use a multi-dimensional Variant array, instead of using a 1-D varVariant array in which each column is an array of varDouble  ?).  A working sample that uses recursion to solve the problem will get the points.

Thanks.

function ButterworthLPF(TimeHistory:OleVariant; SamplingFrequency, CutOffFrequency:real; FilterOrder:byte=8):OleVariant;
//This works for 1-column input
 
var fs, fc, odr   : OleVariant;
 
begin;
    fs  := SamplingFrequency;
    fc  := CutOffFrequency;
    odr := FilterOrder div 2;
    result := bwLPF(TimeHistory, fs, fc, odr);
end;
 
function NewButterworthLPF(TimeHistory:OleVariant; SamplingFrequency, CutOffFrequency:real; FilterOrder:byte=8):OleVariant;
//This does NOT work for 3-column input
 
var fs, fc, odr   : OleVariant;
    i, j : integer;
    vt : TVarType;
 
begin;
  vt := VarType(TimeHistory);
  if (vt and varVariant = varVariant) then
  for i := 1 to VarArrayHighBound(TimeHistory, 1) do
      result[i] := NewButterworthLPF(TimeHistory[i], SamplingFrequency, CutOffFrequency, FilterOrder)
  else
 
  fs  := SamplingFrequency;
  fc  := CutOffFrequency;
  odr := FilterOrder div 2;
  result := bwLPF(TimeHistory, fs, fc, odr);
end;

Open in new window

LVL 7
ahalyaAsked:
Who is Participating?
 
ahalyaConnect With a Mentor Author Commented:
yes, but you don't need this check after all.   The only thing needed to differentiate Variant array of double from a Variant array of Variant array of double is my original check:   if (vt and varVariant = varVariant)  then ....

I made the code to work by adding  Result := VarArrayCreate([0, VarArrayHighBound(TimeHistory, 1)], varVariant); before starting the recursion.  See below for my final solution.  Let me know if you see any errors with this.
function NewButterworthLPF(TimeHistory : Variant; SamplingFrequency, CutOffFrequency:real; FilterOrder:byte=8) : Variant;
//This does seem to work for both single column, and multi column inputs.
 
var fs, fc, odr   : OleVariant;
    i, j : integer;
    vt : TVarType;
 
begin;
  vt := VarType(TimeHistory);
  if (vt and varVariant = varVariant) then
  begin;
    Result := VarArrayCreate([0, VarArrayHighBound(TimeHistory, 1)], varVariant);
    for i := 1 to VarArrayHighBound(TimeHistory, 1) do
      result[i] := NewButterworthLPF(TimeHistory[i], SamplingFrequency, CutOffFrequency, FilterOrder);
  end
  else
  begin;
    fs  := SamplingFrequency;
    fc  := CutOffFrequency;
    odr := FilterOrder div 2;
    result := bwLPF(TimeHistory, fs, fc, odr);
  end;
end;

Open in new window

0
 
atul_parmarConnect With a Mentor Commented:
Hi,

Try the following.
function NewButterworthLPF(TimeHistory : Variant; SamplingFrequency, CutOffFrequency:real; FilterOrder:byte=8) : Variant;
var
  fs, fc, odr   : OleVariant;
  i, j : integer;
  vt : TVarType;
begin
  vt := VarType(TimeHistory);
  if (vt and varVariant = varVariant) and (TVarData(TimeHistory[VarArrayLowBound(TimeHistory, 1)]).VType and VarVariant = varVariant) then
  begin
    Result := VarArrayCreate([0, VarArrayHighBound(TimeHistory, 1)], varVariant);
    for i := 0 to VarArrayHighBound(TimeHistory, 1) do
    begin
      Result[i] := NewButterworthLPF(TimeHistory[i], SamplingFrequency, CutOffFrequency, FilterOrder)
    end;
  end
  else
  begin
    fs  := SamplingFrequency;
    fc  := CutOffFrequency;
    odr := FilterOrder div 2;
    result := bwLPF(TimeHistory, fs, fc, odr);
  end;
end;

Open in new window

0
 
ahalyaAuthor Commented:
I'll try your code when I get a chance, but you should give comments on why you suggest, what you suggest as well please.
0
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

 
ahalyaAuthor Commented:
Nope, doesn't work.

I don't understand why you have
(TVarData(TimeHistory[VarArrayLowBound(TimeHistory, 1)]).VType and VarVariant = varVariant) ??

My FHistoryOriginal is a Variant array of type varDouble.
0
 
atul_parmarCommented:
>>My FHistoryOriginal is a Variant array of type varDouble
I guess you are using the array you posted earlier. i.e.
V := VarArrayCreate([0, 2], varVariant);
V[0] := VarArrayCreate([0, VarArrayHighBound(FHistoryOriginal, 1)], varDouble);
V[1] := VarArrayCreate([0, VarArrayHighBound(FHistoryOriginal, 1)], varDouble);
V[2] := VarArrayCreate([0, VarArrayHighBound(FHistoryOriginal, 1)], varDouble);

Here, V[0] is an array of variant. NO matter what data type you specify. The data type of its individual element would be Double. i.e. V[0][0]. And thus V is a variant array of variant array.

>>(TVarData(TimeHistory[VarArrayLowBound(TimeHistory, 1)]).VType and VarVariant = varVariant) ??

In your original function (which doesn't work for multi column) you have
  vt := VarType(TimeHistory);
  if (vt and varVariant = varVariant)  ...

So if you pass V (variant array of variant array) to NewButterworthLPF function, in the first pass, "if (vt and varVariant = varVariant)" will return true and will call itself with its V[i] element. Now if I understand correctly, V[i] should be executed on same code which you use in your ButterworthLPF function. i.e.
   fs  := SamplingFrequency;
   fc  := CutOffFrequency;
   ...

But  in your original code "if (vt and varVariant = varVariant)" will again return true for V[i] and will call itself again. Which I thought INCORRECT.

Based on that understanding, I checked V[i][j] element of V using
(TVarData(TimeHistory[VarArrayLowBound(TimeHistory, 1)]).VType and VarVariant = varVariant)

Which will branch the V[i] element to the else part of your function.

If that's what you want; my function should work for variant array as well as variant array of variant array. If not, tell me how you use the function with some DUMMY data which I can test.

Atul
0
 
ahalyaAuthor Commented:
Atul,

I was using the array I posted earlier.  I understand that V is a variant array of variant array (of Double).

I want to be able to pass either of the following:
Case 1 (Recursion) : V -> Variant array of variant array
Case 2: (No recursion) V -> Variant Array.

I will make a short sample and post it to show you what I am after.  Thanks.
0
 
ahalyaAuthor Commented:
Atul,

While exploring you code, found the following.

Say
    U := VarArrayCreate([0, 2047], varDouble);
    vt := VarType(U);     //vt is not varVariant, instead it is varDouble

  V := VarArrayCreate([0, 4], varVariant);
  for i := 0 to 4 do
  begin;
    U := VarArrayCreate([0, 2047], varDouble);
    for j := 0 to 2047 do U[j] := random;
    V[i] := U;
  end;

    vt := VarType(V);        //vt is varVariant
    vt := VarType(V[1]);     //vt is not varVariant, it is varDouble

This suggests that your suggestion regarding varType is not correct.  Can you confirm.
0
 
ahalyaAuthor Commented:
The check that is needed is the following:

  vt1 := VarType(TimeHistory);
  vt2 := VarType(TimeHistory[VarArrayLowBound(TimeHistory, 1)]);

  if (vt2 and varArray = varArray) then ...
0
 
atul_parmarCommented:
Correct;
 vt2 := VarType(TimeHistory[VarArrayLowBound(TimeHistory, 1)]);
 if (vt2 and varArray = varArray)

IS SAME AS

IF (TVarData(TimeHistory[VarArrayLowBound(TimeHistory, 1)]).VType and VarVariant = varVariant)

0
 
atul_parmarCommented:
My misatake; it should be
IF (TVarData(TimeHistory[VarArrayLowBound(TimeHistory, 1)]).VType and varArray= varArray)
0
 
atul_parmarCommented:
>>yes, but you don't need this check after all.
It depends on the variant array you are passing. e.g. try with following array

var
  V, V1 : Variant;
begin
  V := VarArrayCreate([0, 2], varVariant);
  V1 := VarArrayCreate([0, 1], varDouble);
  V[0] := VarArrayOf(V1);
  V[1] := VarArrayOf(V1);
  V[2] := VarArrayOf(V1);
  NewButterworthLPF(V, 0, 0); // call to your function
end;

Atul.
0
 
atul_parmarCommented:
It works well with the code I posted first.

...
if (vt and varVariant = varVariant) and (TVarData(TimeHistory[VarArrayLowBound(TimeHistory, 1)]).VType and varVariant = varVariant) then
...
0
 
ahalyaAuthor Commented:
I haven't had a chance to try with an array as you have defined above. But, my question had the arrays defined in a specific way, and your solution doesn't work with that.

But, I managed to tweak my code (adding a line to create result as a VarArray) after seeing your solution.  Thanks.
0
 
atul_parmarCommented:
>>The solution I posted in the question required the addition one just one line of >>code to make it work.  (I figured it out myself after discussions).  

My first post has the line (line#10) which makes this work.

>>The answer posted posted might be correct for a different question, but it's not >>the answer for the posted question.

There are numerous ways to solve a problem. It doesn't matter which one u like or dislike.

If, the posted comment doesn't lead to solve the problem. I would rather suggest to delete this question.
0
 
ahalyaAuthor Commented:
Atul,

>> My first post has the line (line#10) which makes this work.

Even though you had that line, your solution was wrong, and did not work.  I accepted your suggestion as an "Assisted Solution" because I picked up your line 10.   I cannot accept your solution as a full solution, because it did not work with my array.

Accepting your solution as an "Assisted Solution" was fair, I thought. Don't you think so ?

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.