HOW TO: How can I make sure that the size of a matrix input matches two vector inputs?
Reference: Q0039
Article last modified on 30-Sep-2006
The information in this article applies to:
- XLL+ for Visual Studio 2005 - 5.0
- XLL+ for Visual Studio .NET - 4.2, 4.3.1, 5.0
- XLL+ for Visual Studio 6 - 3, 4.1, 4.2, 4.3.1, 5.0
HOW TO: How can I make sure that the size of a matrix input matches two vector inputs?
Question
I have an add-in function with 3 inputs, x
, y
and z
.
x
and y
are vectors, while z
is a
matrix. The size of z
is constrained such that:
-
Height of
z
= Size ofx
-
Width of
z
= Size ofy
Answer
You can modify your arguments to be bounded input arrays. The XLL+ Function Wizard has a tab which lets you set the bounds of an array, so that they are tied to a named variable (or to a constant). The code which is generated will automatically check that all matrix and vector inputs satisfy the constraints you apply.
By using the same named variable for each pair of inputs, you can ensure that each dimension of each input is the same size as its pair.
If the input is not of the expected size, then an error value is returned, e.g.:
#Error: expected 5 columns in z
Example
Problem: constrain a matrix input to match the size of two vector inputs.
Steps
-
Create a new function,
ConstrainedMatrix()
, using the XLL+ Function Wizard. It takes a three arguments:x
,y
andz
.x
andy
are defined as vectors of doubles.z
is defined as a matrix of doubles. -
Select the Dimensions column of the row containing the definition of
x
, and click on the...
button. (Or use the short-cut Ctrl+E.) This will display the Edit Argument dialog.Select the Array tab
In the Bounds box, check the Bounded check-box and set the upper bound (UBound) to be
cx
, as shown below. - Press OK to close the dialog.
-
Select the Dimensions column of the row containing the definition of
y
, and click on the...
button. (Or use the short-cut Ctrl+E.) This will display the Edit Argument dialog.Select the Array tab
In the Bounds box, check the Bounded check-box and set the upper bound (UBound) to be
cy
, as shown below. - Press OK to close the dialog.
-
Select the Dimensions column of the row containing the definition of
z
, and click on the...
button. (Or use the short-cut Ctrl+E.) This will display the Edit Argument dialog.Select the Array tab
In the Rows box, check the Bounded check-box and set the upper bound (UBound) to be
cx
, as shown below. This forces the height ofz
to match the size ofx
, as required.In the Columns box, check the Bounded check-box and set the upper bound (UBound) to be
cy
, as shown below. This forces the height ofz
to match the size ofy
, as required. - Press OK to close the dialog.
-
Inspect the changes to the Function Wizard. The Dimensions column now contains the new definitions of
x
,y
andz
.Argument Dimensions x
Vector (0 to cx) y
Vector (0 to cy) z
Matrix (0 to cx)(0 to cy) - Press OK to close the dialog, and save the function.
Code
The code generated is shown below:
// Function: ConstrainedMatrix // Purpose: Matrix input is constrained by two vector inputs //{{XLP_SRC(ConstrainedMatrix) // NOTE - the FunctionWizard will add and remove mapping code here. // DO NOT EDIT what you see in these blocks of generated code! IMPLEMENT_XLLFN2(ConstrainedMatrix, "RPPP", "ConstrainedMatrix", "x,y,z", "User Defined", "Matrix input is constrained by two" " vector inputs", "No description provided\000No description" " provided\000No description provided\000", "B0(0,cx)x No des" "cription provided\0B0(0,cy)y No description provided\0B0(0" ",cx)0(0,cy)z No description provided\0appscope=1\0", 1) extern "C" __declspec( dllexport ) LPXLOPER ConstrainedMatrix(const COper* x, const COper* y, const COper* z) { XLL_FIX_STATE; CXlOper xloResult; BOOL bOk = TRUE; long cx = -1; long cy = -1; std::vector<double> vecx; bOk = bOk && x->ReadVectorBounded(vecx, "x", xloResult, 0, cx); std::vector<double> vecy; bOk = bOk && y->ReadVectorBounded(vecy, "y", xloResult, 0, cy); MTX_PTRS<double> matz; bOk = bOk && z->ReadMatrix(matz, "z", xloResult, &cx, &cy, XLA_ARRAY_FLAGS_NUMERIC_STD, 0, 0); if (!bOk) return xloResult.Ret(); //}}XLP_SRC // TODO - Set the value of xloResult return xloResult.Ret(); }
Explanation
The interesting code is shown in bold above.
-
The bounds variables
cx
andcy
, which we entered as UBounds in the Edit Argument dialog, are declared, and are each initialized to-1
. This value represents "not yet known". -
A reference to
cx
is passed to COper::ReadVectorBounded when readingx
, and is also passed to COper::ReadMatrix (aslpUBound1
) when readingz
. -
When ReadVectorBounded receives
cx
, it contains -1 (meaning "not yet known"), and ReadVectorBounded simply sets its value to the size ofx
. -
When ReadMatrix is called,
cx
contains a non-negative integer, and is therefore treated as a fixed size constraint. Ifz
does not containcx
rows then an error is returned. -
Similarly, a reference to
cy
is also passed to ReadVectorBounded (when readingy
) and to ReadMatrix, aslpUBound2
(when reading z). An error is returned if the width ofz
does not match the length ofy
.
Result
If, for example, x
contains 6 cells, y
contains 4
cells and z
contains 6 rows x 5 columns , then the following error
value is returned
#Error: expected 4 columns in z
and the function does not continue.
See also
FAQ #0034 discusses various ways to use bounded input
arrays to constrain the bounds of an input.
Bounded input arrays - technical note in the online documentation.
Argument Dialog - Array Tab - tools help in the online documentation.