FgMatrixC<T,1,2>
fgBounds(const FgMatrixC<T,nrows,ncols> & mat)
{
    FGASSERT(mat.numElems() > 0);
    FgMatrixC<T,1,2>    ret(mat[0]);
    for (uint ii=0; ii<mat.numElems(); ++ii)
    {
        fgSetIfLess     (ret[0],mat[ii]);
        fgSetIfGreater  (ret[1],mat[ii]);
    }
    return ret;
}
T
fgTrace(const FgMatrixC<T,dim,dim> & m)
{
    T   ret(0);
    for (uint ii=0; ii<m.numElems(); ii+=dim+1)
        ret += m[ii];
    return ret;
}
FgMatrixC<uint,nrows,ncols>
fgRoundU(FgMatrixC<float,nrows,ncols> m)
{
    FgMatrixC<uint,nrows,ncols> ret;
    for (uint ii=0; ii<m.numElems(); ++ii)
        ret[ii] = fgRoundU(m[ii]);
    return ret;
}
FgMatrixC<int,nrows,ncols>
fgRound(FgMatrixC<double,nrows,ncols> m)
{
    FgMatrixC<int,nrows,ncols> ret;
    for (uint ii=0; ii<m.numElems(); ++ii)
        ret[ii] = fgRound(m[ii]);
    return ret;
}
void
fgRound_(
    const FgMatrixC<Flt,nrows,ncols> &    lhs,
    FgMatrixC<Int,nrows,ncols> &          rhs)
{
    for (uint ii=0; ii<rhs.numElems(); ++ii)
        fgRound_(lhs[ii],rhs[ii]);
}
FgMatrixC<T,nrows,ncols>
fgFloor(const FgMatrixC<T,nrows,ncols> & mat)
{
    FgMatrixC<T,nrows,ncols> ret;
    for (uint ii=0; ii<mat.numElems(); ++ii)
        ret[ii] = std::floor(mat[ii]);
    return ret;
}
uint
fgMaxIdx(const FgMatrixC<T,nrows,ncols> & mat)
{
    uint        idx(0);
    T           max(mat[0]);
    uint        sz = mat.numElems();
    for (uint ii=1; ii<sz; ++ii) {
        if (mat[ii] > max) {
            max = mat[ii];
            idx = ii;
        }
    }
    return idx;
}