FgMatrixC<T,dim,1> fgClamp(FgMatrixC<T,dim,1> val,FgMatrixC<T,dim,2> bounds) { for (uint ii=0; ii<dim; ++ii) val[ii] = fgClamp(val[ii],bounds.elem(ii,0),bounds.elem(ii,1)); return val; }
FgMatrixC<T,sz,sz> fgDiagonal(FgMatrixC<T,sz,1> vec) { FgMatrixC<T,sz,sz> ret; for (uint ii=0; ii<sz; ++ii) ret.elem(ii,ii) = vec[ii]; return ret; }
FgAffineC<T,dim> asAffine() const { FgMatrixC<T,dim,dim> scales; for (uint ii=0; ii<dim; ++ii) scales.elm(ii,ii) = m_scales[ii]; return FgAffineC<T,dim>(scales,m_trans); }
FgMatrixC<T,3,3> fgPermuteAxes(uint axisToBecomeX) { FgMatrixC<T,3,3> ret; for (uint ii=0; ii<3; ++ii) ret.elem(ii,(ii+axisToBecomeX)%3) = T(1); return ret; }
FgMatrixC<T,dims+1,dims+1> fgAsHomogMat(const FgMatrixC<T,dims,1> & translation) { FgMatrixC<T,dims+1,dims+1> ret; ret.setIdentity(); for (uint rr=0; rr<dims; rr++) ret.elem(rr,dims) = translation[rr]; return ret; }
FgMatrixC<T,dim,ncols> operator*(const FgMatrixC<T,dim,ncols> & vec) const { FgMatrixC<T,dim,ncols> ret; for (uint row=0; row<dim; ++row) for (uint col=0; col<ncols; ++col) ret.elm(col,row) = m_scales[row] * (vec.elm(col,row) + m_trans[row]); return ret; }
FgMatrixC<T,ncols,nrows> transpose() const { FgMatrixC<T,ncols,nrows> tMat; for (uint ii=0; ii<nrows; ii++) for (uint jj=0; jj<ncols; jj++) tMat.elem(jj,ii) = elem(ii,jj); return tMat; }
FgMatrixC<T,nrows,1> fgMaxColwise(const FgMatrixC<T,nrows,ncols> & mat) { FG_STATIC_ASSERT(ncols > 1); FgMatrixC<T,nrows,1> ret(mat.colVec(0)); for (uint row=0; row<nrows; ++row) for (uint col=1; col<ncols; ++col) fgSetIfGreater(ret[row],mat.elm(col,row)); return ret; }
FgMatrixC<T,dims+1,dims+1> fgAsHomogMat(const FgMatrixC<T,dims,dims> & linear) { FgMatrixC<T,dims+1,dims+1> ret; for (uint rr=0; rr<dims; ++rr) for (uint cc=0; cc<dims; ++cc) ret.elem(rr,cc) = linear.elem(rr,cc); ret.elem(dims,dims) = T(1); return ret; }
FgMatrixC<T,2,2> fgMatRotate(T radians) { FgMatrixC<T,2,2> mat; FgTypeAttributeFloatingS<T>(); T ct = T(cos(radians)); T st = T(sin(radians)); mat.elem(0,0)=ct; mat.elem(0,1)=-st; mat.elem(1,0)=st; mat.elem(1,1)=ct; return mat; }
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; }
FgMatrixC<T,dim,2> fgCubeBounds(const vector<FgMatrixC<T,dim,1> > & verts,T padRatio=1) { FgMatrixC<T,dim,2> ret; FgMatrixC<T,dim,2> bounds = fgBounds(verts); FgMatrixC<T,dim,1> lo = bounds.colVec(0), hi = bounds.colVec(1), centre = (lo + hi) * T(0.5); T hsize = fgMaxElem(hi - lo) * 0.5f * padRatio; ret = fgConcatHoriz(centre-FgMatrixC<T,dim,1>(hsize),centre+FgMatrixC<T,dim,1>(hsize)); return ret; }
FgMatrixC<T,dim,2> fgBoundsIntersection( const FgMatrixC<T,dim,2> & b1, const FgMatrixC<T,dim,2> & b2) { FgMatrixC<T,dim,2> ret(b1); for (uint dd=0; dd<dim; ++dd) { fgSetIfGreater(ret.elm(0,dd),b2.elm(0,dd)); fgSetIfLess(ret.elm(1,dd),b2.elm(1,dd)); } return ret; }
FgMatrixC<T,2,2> fgMatInverse( const FgMatrixC<T,2,2>& m) { FgTypeAttributeFloatingS<T>(); FgMatrixC<T,2,2> retval; T fac = (m.elem(0,0) * m.elem(1,1) - m.elem(0,1) * m.elem(1,0)); FGASSERT(fac != T(0)); fac = T(1) / fac; retval.elem(0,0) = m.elem(1,1) * fac; retval.elem(0,1) = - m.elem(0,1) * fac; retval.elem(1,0) = - m.elem(1,0) * fac; retval.elem(1,1) = m.elem(0,0) * fac; return retval; }
double lnNormalCholesky( const FgMatrixC<double,dim,1> & pos, const FgMatrixC<double,dim,1> & mean, const FgMatrixC<double,dim,dim> & chol) { double det = 1.0; for (uint ii=0; ii<dim; ii++) det *= chol.elem(dim,dim); FgMatrixC<double,dim,1> mhlbs = chol * (pos-mean); return (0.5 * std::log(det) - // Cholesky has all diagonals > 0 0.5 * double(dim) * fgLn_2pi() - 0.5 * mhlbs.lengthSqr()); }
FgMatrixC<T,nrows1+nrows2,ncols> fgConcatVert( const FgMatrixC<T,nrows1,ncols> & upper, const FgMatrixC<T,nrows2,ncols> & lower) { FgMatrixC<T,nrows1+nrows2,ncols> ret; for (uint rr=0; rr<nrows1; ++rr) for (uint cc=0; cc<ncols; ++cc) ret.elem(rr,cc) = upper.elem(rr,cc); for (uint rr=0; rr<nrows2; ++rr) for (uint cc=0; cc<ncols; ++cc) ret.elem(nrows1+rr,cc) = lower.elem(rr,cc); return ret; }
FgMatrixC<T,dims+1,dims+1> fgAsHomogMat( const FgMatrixC<T,dims,dims> & linTrans, const FgMatrixC<T,dims,1> & translation) { FgMatrixC<T,dims+1,dims+1> ret; for (uint rr=0; rr<dims; rr++) for (uint cc=0; cc<dims; cc++) ret.elem(rr,cc) = linTrans.elem(rr,cc); for (uint rr=0; rr<dims; rr++) ret.elem(rr,dims) = translation[rr]; ret.elem(dims,dims) = 1; return ret; }
FgMatrixC<T,dim,2> fgBounds(const std::vector<FgMatrixC<T,dim,1> > & data) { FGASSERT(data.size() > 0); FgMatrixC<T,dim,2> ret; ret.setSubMatrix(data[0],0,0); ret.setSubMatrix(data[0],0,1); for (size_t ii=1; ii<data.size(); ++ii) { for (uint dd=0; dd<dim; ++dd) { fgSetIfLess (ret.elm(0,dd),data[ii][dd]); fgSetIfGreater (ret.elm(1,dd),data[ii][dd]); } } return ret; }
double normalCholesky( const FgMatrixC<double,dim,1> & pos, const FgMatrixC<double,dim,1> & mean, const FgMatrixC<double,dim,dim> & chol) // Right-hand cholesky term of concentration { double det = 1.0; for (uint ii=0; ii<dim; ii++) det *= chol.elem(ii,ii); // Cholesky is upper or lower triangular. FgMatrixC<double,dim,1> mhlbs = chol * (pos-mean); return ( std::pow(2.0 * fgPi(),double(dim) * -0.5) * std::sqrt(det) * fgExp(-0.5 * mhlbs.lengthSqr())); }
FgMatrixC<T,dim,2> fgBounds( const FgMatrixC<T,dim,1> & v0, const FgMatrixC<T,dim,1> & v1, const FgMatrixC<T,dim,1> & v2) { FgMatrixC<T,dim,2> ret; for (uint dd=0; dd<dim; ++dd) { ret.elm(0,dd) = ret.elm(1,dd) = v0[dd]; fgSetIfLess(ret.elm(0,dd),v1[dd]); fgSetIfLess(ret.elm(0,dd),v2[dd]); fgSetIfGreater(ret.elm(1,dd),v1[dd]); fgSetIfGreater(ret.elm(1,dd),v2[dd]); } return ret; }
FgMatrixC<T,nrows,ncols1+ncols2> fgConcatHoriz( const FgMatrixC<T,nrows,ncols1> & lhs, const FgMatrixC<T,nrows,ncols2> & rhs) { FgMatrixC<T,nrows,ncols1+ncols2> ret; for (uint row=0; row<nrows; ++row) { uint col=0; for (uint cc=0; cc<ncols1; ++cc) ret.elem(row,col++) = lhs.elem(row,cc); for (uint cc=0; cc<ncols2; ++cc) ret.elem(row,col++) = rhs.elem(row,cc); } return ret; }
bool fgBoundsIntersect( const FgMatrixC<T,dim,2> & bnds1, const FgMatrixC<T,dim,2> & bnds2, FgMatrixC<T,dim,2> & retval) { FgMatrixC<T,dim,2> tmp; for (uint dd=0; dd<dim; ++dd) { tmp.elm(0,dd) = std::max(bnds1.elm(0,dd),bnds2.elm(0,dd)); tmp.elm(1,dd) = std::min(bnds1.elm(1,dd),bnds2.elm(1,dd)); if (tmp.elm(0,dd) > tmp.elm(1,dd)) return false; } retval = tmp; return true; }
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<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; }
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; }
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; }
void setSubMat(const FgMatrixC<T,srows,scols> & sub,uint row,uint col) { FGASSERT((srows+row <= nrows) && (scols+col <= ncols)); for (uint rr=0; rr<srows; rr++) for (uint cc=0; cc<scols; cc++) elem(rr+row,cc+col) = sub.elem(rr,cc); }
void accSubMat(size_t row,size_t col,FgMatrixC<T,mrows,mcols> m) { FGASSERT((mrows+row <= nrows) && (mcols+col <= ncols)); for (uint rr=0; rr<mrows; ++rr) for (uint cc=0; cc<mcols; ++cc) elem(row+rr,col+cc) += m.elem(rr,cc); }
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; }
T fgMinElem(const FgMatrixC<T,nrows,ncols> & mat) { T ret(mat[0]); size_t sz = mat.size(); for (size_t ii=1; ii<sz; ++ii) fgSetIfLess(ret,mat[ii]); return ret; }