Solved

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

Posted on 2008-10-06
2,241 Views
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;
``````
0
Question by:ahalya
• 8
• 7

LVL 10

Assisted Solution

atul_parmar earned 100 total points
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;
``````
0

LVL 7

Author Comment

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

LVL 7

Author Comment

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

LVL 10

Expert Comment

>>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

LVL 7

Author Comment

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

LVL 7

Author Comment

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

LVL 7

Author Comment

The check that is needed is the following:

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

if (vt2 and varArray = varArray) then ...
0

LVL 10

Expert Comment

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

LVL 10

Expert Comment

My misatake; it should be
IF (TVarData(TimeHistory[VarArrayLowBound(TimeHistory, 1)]).VType and varArray= varArray)
0

LVL 7

Accepted Solution

ahalya earned 0 total points
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;
``````
0

LVL 10

Expert Comment

>>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

LVL 10

Expert Comment

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

LVL 7

Author Comment

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

LVL 10

Expert Comment

>>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

LVL 7

Author Comment

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

Featured Post

This article will show, step by step, how to integrate R code into a R Sweave document
This is about my first experience with programming Arduino.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…