
A1.3 Adding C/C
++
code: returning values in arguments 7
static void OXCALL
fnInvert(OxVALUE *rtn, OxVALUE *pv, int cArg)
{
int r, signdet = 0; double logdet = 0;
OxZero(rtn, 0);
OxLibCheckSquareMatrix(pv, 0, 0);
if (cArg == 2) /* either 1 or 3 arguments */
OxRunError(ER_ARGS, "invert");
else if (cArg == 3)
OxLibCheckType(OX_ARRAY, pv, 1, 2);
r = OxMatr(pv, 0);
OxLibValMatDup(rtn, OxMat(pv, 0), r, r);
if (IInvDet(OxMat(rtn, 0), r, &logdet, &signdet) != 0)
{
OxRunMessage("invert(): inversion failed");
OxFreeByValue(rtn);
OxZero(rtn, 0);
}
if (cArg == 3)
{
OxSetDbl( OxArray(pv,1), 0, logdet);
OxSetInt( OxArray(pv,2), 0, signdet);
}
}
• OxLibCheckSquareMatrix(pv, 0, 0) is the same as making a call to
OxLibCheckType(OX
MATRIX, pv, 0, 0) followed by a check if the matrix
is square.
• Using invert with two arguments is an error. When there are three arguments,
the code checks if the second and third are of type OX
ARRAY.
• OxMatr gets the number of rows in the first argument (we already know that it is
a matrix, with the same number of rows as columns).
• Next, we duplicate (allocate a matrix and copy) the matrix in the first argument
to the return value. We shall overwrite this with the actual inverse.
• If the matrix inversion fails, the matrix in rtn is freed, and rtn is changed back
to an integer with value 0. It is important to free before setting the value to an
integer: otherwise a memory leak occurs.
• Otherwise, but only if the second and third argument were provided, do we put the
log-determinant(logdet) and sign in those argument. OxArray(pv,1) accesses
the array at element 1 in pv. This is then used in the same way as pv was used to
access the first entry in that array (index 0).
A more complex example is that for the square root free Choleski decomposition
decldl, again from the standard library. The first argument is the symmetric matrix to
decompose, the next two are arrays in which we expect the function to return the lower
triangular matrix and vector with diagonal elements.
Komentáře k této Příručce