≡ ▼

This page lists some useful functions which might end up as officially documented functions in the LAMBDA Library. For now, they need to be tested, evaluated, researched, improved, etc.

The code is meant to be copy/pasted directly into the AFE in the Excel Labs add-in. Note that the names of these functions are not the typical L_FUNCTION names. They will be renamed if they end up making it into the library.

Array and Matrix Functions

shuffleArray(array,[dimension])

/**
* Shuffle Rows (dim=1, default) or Columns (dim=2)
*/
shuffleArray = LAMBDA(array,[dimension],
LET(doc,"https://www.vertex42.com/lambda/",
    dim,IF(ISOMITTED(dimension),1,dimension),
    array,IF(dim=1,array,TRANSPOSE(array)),
    rand,RANDARRAY(ROWS(array),1),
    shuffled,DROP(SORT(HSTACK(rand,array)),0,1),
    IF(dim=1,shuffled,TRANSPOSE(shuffled))
));

isPositiveDefinite(matrix)

A positive definite matrix is symmetric, but not all symmetric matrices are positive definite. The matrix {-1,3,-4;3,-10,8,-4,8,-2} is an example where the first two principal minors are negative, but the overall determinant is positive. This matrix has 2 negative eigenvalues.

/**
* Returns TRUE if all leading principal minors (upper-left determinants) are greater than zero
*/
isPositiveDefinite = LAMBDA(matrix,
LET(doc,"https://www.vertex42.com/lambda/",
    REDUCE(TRUE,SEQUENCE(ROWS(matrix)),LAMBDA(acc,i,
        AND(acc,MDETERM(CHOOSEROWS(CHOOSECOLS(matrix,SEQUENCE(i)),SEQUENCE(i)))>0)
    ))
));

isSymmetric(matrix)

/**
* Returns TRUE if the matrix is symmetric
*/
isSymmetric = LAMBDA(matrix,
LET(doc,"https://www.vertex42.com/lambda/",
    IF(ROWS(matrix)<>COLUMNS(matrix),FALSE,SUM(--(matrix<>TRANSPOSE(matrix)))=0)
));

Filter Help

filterOut(remove_list,from_list)

/**
* Remove values in remove_list from from_list
* Both lists are single-column or single-row arrays
*/
filterOut = LAMBDA(remove_list,from_list,
LET(doc,"https://www.vertex42.com/lambda/",
    FILTER(from_list,ISERROR(MATCH(from_list,remove_list,0)),FALSE)
));

Function Helpers / Utilities

MAP_IJ(array,LAMBDA(cell,i,j, expression) )

/**
* Like MAP for a single array, but with access to array indices
*/
MAP_IJ = LAMBDA(array,function,
LET(doc,"https://www.vertex42.com/lambda/",
    iMat,L_REPARRAY(SEQUENCE(ROWS(array),1),1,COLUMNS(array)),
    jMat,L_REPARRAY(SEQUENCE(1,COLUMNS(array)),ROWS(array),1),
    MAP(array,iMat,jMat,LAMBDA(cell,i,j,function(cell,i,j)))
));

Other Polynomial Fitting

Newton Polynomials: These functions take about 2-3 times as long to run as L_POLYFIT and L_POLYVAL. Unless the Newton form of an exact polynomial is needed, may be better to use L_POLYFIT and L_POLYVAL.

/**
* Fit a Newton Polynomial of order n to a set of n+1 points
* known_xs and known_ys must be column vectors of the same length
* Result is a column of x values and a column of divdiffs
*/
L_NPOLYFIT = LAMBDA(known_xs,known_ys,
LET(doc,"https://www.vertex42.com/lambda/candidates.html",
    m,ROWS(known_xs),
    res,REDUCE(INDEX(known_ys,1,1),SEQUENCE(m-1),LAMBDA(acc,i,
    LET(coeffs,TAKE(acc,i,1),
        divdiffs,IF(i=1,known_ys,TAKE(acc,m-i+1,-1)),
        diffx,DROP(known_xs,i)-DROP(known_xs,-i),
        diffy,DROP(divdiffs,1)-DROP(divdiffs,-1),
        newdivdiffs,diffy/diffx,
        HSTACK(VSTACK(coeffs,INDEX(newdivdiffs,1,1)),newdivdiffs)
    ))),
    HSTACK(known_xs,CHOOSECOLS(res,1))
));
/**
* Evaluate a Newton Polynomial defined by a column of x values and a column of divdiffs
* for values of x.
* npoly is the output of L_NPOLYFIT(known_xs,known_ys)
*/
L_NPOLYVAL = LAMBDA(npoly,x,
LET(doc,"https://www.vertex42.com/lambda/candidates.html",
    m,ROWS(npoly),
    xs,CHOOSECOLS(npoly,1),
    coeffs,CHOOSECOLS(npoly,2),
    init_acc,HSTACK(L_ONES(ROWS(x),1),L_REPARRAY(INDEX(coeffs,1,1),ROWS(x),1)),
    res,REDUCE(init_acc,SEQUENCE(m-1),LAMBDA(acc,i,
    LET(xdiffs,CHOOSECOLS(acc,1),
        cumsum,CHOOSECOLS(acc,2),
        newxdiffs,xdiffs*(x-INDEX(xs,i,1)),
        newcumsum,cumsum+INDEX(coeffs,i+1,1)*newxdiffs,
        HSTACK(newxdiffs,newcumsum)
    ))),
    CHOOSECOLS(res,2)
));