Mat.h tdm/Types.h tdm/Vec.h Computations.h TDM.h tdm::mat tdm //CopyrightEpicGames,Inc.AllRightsReserved. #pragmaonce #include"tdm/Types.h" #include"tdm/Vec.h" namespacetdm{ template<dim_tR,dim_tC,typenameT> inlinemat<C,R,T>transpose(constmat<R,C,T>&m); template<dim_tN,typenameT> inlinemat<N,N,T>inverse(constmat<N,N,T>&m); template<dim_tR,dim_tC,typenameT> structmat{ usingvalue_type=T; usingrow_type=vec<C, value_type>; usingcolumn_type=vec<R, value_type>; staticconstexprdim_trows(){ returncolumn_type::dimensions(); } staticconstexprdim_tcolumns(){ returnrow_type::dimensions(); } private: row_typevalues[R]; public: mat():values{}{ } ~mat()=default; mat(constmat&)=default; mat&operator=(constmat&)=default; mat(mat&&)=default; mat&operator=(mat&&)=default; template<typenameU> explicitmat(Uscalar){ apply([scalar](row_type&row,dim_t/*unused*/){ row=row_type{scalar}; }); } template<typename...Us,typenamestd::enable_if<sizeof...(Us)==R*C>::type*=nullptr> mat(Us...scalars){ Ttmp[sizeof...(Us)]={static_cast<T>(scalars)...}; apply([&tmp](row_type&row,dim_tri){ row.apply([&tmp,ri](value_type&value,dim_tci){ value=tmp[ri*columns()+ci]; }); }); } template<typenameU> mat(constmat<R, C, U>&rhs){ apply([&rhs](row_type&row,dim_tri){ row=rhs[ri]; }); } template<typenameU> mat&operator=(constmat<R, C, U>&rhs){ returnoperator=(mat<R, C, T>{rhs}); } template<typename...Us,typenamestd::enable_if<sizeof...(Us)==R>::type*=nullptr> mat(constvec<C, Us>&...vs):values{row_type{vs}...}{ } template<typename...Us,typenamestd::enable_if<sizeof...(Us)==R>::type*=nullptr> staticmatfromRows(constvec<C, Us>&...vs){ returnmat{vs...}; } template<typename...Us,typenamestd::enable_if<sizeof...(Us)==C>::type*=nullptr> staticmatfromColumns(constvec<R, Us>&...vs){ mat<sizeof...(vs),R,T>tmp{vs...}; returntdm::transpose(tmp); } template<typenameU,typename...,dim_tH=R,dim_tW=C> statictypenamestd::enable_if<H==W,mat>::typediagonal(Uscalar){ matret; ret.apply([scalar](row_type&row,dim_tri){ row[ri]=scalar; }); returnret; } template<typenameU,typename...,dim_tH=R,dim_tW=C> statictypenamestd::enable_if<H==W,mat>::typediagonal(constvec<W, U>&scalars){ matret; ret.apply([&scalars](row_type&row,dim_tri){ row[ri]=scalars[ri]; }); returnret; } template<typename...Us,dim_tH=R,dim_tW=C> statictypenamestd::enable_if<(H==W)&&(sizeof...(Us)==H),mat>::typediagonal(Us...scalars){ returndiagonal(vec<R, T>{scalars...}); } template<typename...,dim_tH=R,dim_tW=C> statictypenamestd::enable_if<H==W,mat>::typeidentity(){ returndiagonal(static_cast<T>(1)); } row_type&operator[](dim_tindex){ //NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) assert(index<rows()); //NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index) returnvalues[index]; } constrow_type&operator[](dim_tindex)const{ //NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) assert(index<rows()); //NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index) returnvalues[index]; } T&operator()(dim_trowIndex,dim_tcolIndex){ returnoperator[](rowIndex)[colIndex]; } constT&operator()(dim_trowIndex,dim_tcolIndex)const{ returnoperator[](rowIndex)[colIndex]; } template<typenameF> mat&apply(Ffunc){ for(dim_tri{};ri!=rows();++ri){ func(values[ri],ri); } return*this; } template<typenameF> constmat&apply(Ffunc)const{ for(dim_tri{};ri!=rows();++ri){ func(values[ri],ri); } return*this; } mat&operator++(){ returnapply([](row_type&row,dim_t/*unused*/){ ++row; }); } mat&operator--(){ returnapply([](row_type&row,dim_t/*unused*/){ --row; }); } template<typenameU> mat&operator+=(Urhs){ returnapply([rhs](row_type&row,dim_t/*unused*/){ row+=rhs; }); } template<typenameU> mat&operator+=(constmat<R, C, U>&rhs){ returnapply([&rhs](row_type&row,dim_tri){ row+=rhs[ri]; }); } mat&operator+=(constmat&rhs){ returnoperator+=<T>(rhs); } template<typenameU> mat&operator-=(Urhs){ returnapply([rhs](row_type&row,dim_t/*unused*/){ row-=rhs; }); } template<typenameU> mat&operator-=(constmat<R, C, U>&rhs){ returnapply([&rhs](row_type&row,dim_tri){ row-=rhs[ri]; }); } mat&operator-=(constmat&rhs){ returnoperator-=<T>(rhs); } template<typenameU> mat&operator*=(Urhs){ returnapply([rhs](row_type&row,dim_t/*unused*/){ row*=rhs; }); } template<typenameU> mat&operator*=(constmat<R, C, U>&rhs){ return(*this=*this*rhs); } mat&operator*=(constmat&rhs){ returnoperator*=<T>(rhs); } template<typenameU> mat&operator/=(Urhs){ returnapply([rhs](row_type&row,dim_t/*unused*/){ row/=rhs; }); } template<typenameU> mat&operator/=(constmat<R, C, U>&rhs){ returnoperator*=(inverse(rhs)); } mat&operator/=(constmat&rhs){ returnoperator/=<T>(rhs); } template<typename...,dim_tH=R,dim_tW=C> typenamestd::enable_if<H==W,mat&>::typetranspose(){ return(*this=tdm::transpose(*this)); } mat&negate(){ apply([](row_type&row,dim_t/*unused*/){ row.negate(); }); return*this; } row_typerow(dim_tindex)const{ returnoperator[](index); } column_typecolumn(dim_tindex)const{ column_typecol; apply([&col,index](constrow_type&row,dim_tri){ col[ri]=row[index]; }); returncol; } template<dim_tH,dim_tW> typenamestd::enable_if<(H>1&&W>1&&H<=R&&W<=C),mat<H,W,T>>::typesubmat(dim_ty,dim_tx)const{ assert(H+y<=rows()); assert(W+x<=columns()); mat<H, W, T>ret; ret.apply([this,y,x](typenamemat<H, W, T>::row_type&row,dim_tri){ row.apply([this,y,x,ri](value_type&value,dim_tci){ value=values[y+ri][x+ci]; }); }); returnret; } }; template<dim_tR,dim_tC,typenameT> inlinebooloperator==(constmat<R, C, T>&lhs,constmat<R, C, T>&rhs){ usingrow_type=typenamemat<R, C, T>::row_type; boolretval=true; lhs.apply([&rhs,&retval](constrow_type&row,dim_tri){ retval=retval&&(row==rhs[ri]); }); returnretval; } template<dim_tR,dim_tC,typenameT> inlinebooloperator!=(constmat<R, C, T>&lhs,constmat<R, C, T>&rhs){ return!(lhs==rhs); } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator+(constmat<R, C, T>&m){ returnm; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator-(constmat<R, C, T>&m){ mat<R, C, T>ret{m}; ret.negate(); returnret; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator+(constmat<R, C, T>&lhs,Trhs){ returnmat<R, C, T>(lhs)+=rhs; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator+(Tlhs,constmat<R, C, T>&rhs){ returnmat<R, C, T>(lhs)+=rhs; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator+(constmat<R, C, T>&lhs,constmat<R, C, T>&rhs){ returnmat<R, C, T>(lhs)+=rhs; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator-(constmat<R, C, T>&lhs,Trhs){ returnmat<R, C, T>(lhs)-=rhs; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator-(Tlhs,constmat<R, C, T>&rhs){ returnmat<R, C, T>(lhs)-=rhs; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator-(constmat<R, C, T>&lhs,constmat<R, C, T>&rhs){ returnmat<R, C, T>(lhs)-=rhs; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator*(constmat<R, C, T>&lhs,Trhs){ returnmat<R, C, T>(lhs)*=rhs; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator*(Tlhs,constmat<R, C, T>&rhs){ returnmat<R, C, T>(rhs)*=lhs; } template<dim_tR,dim_tC,typenameT> inlinetypenamemat<R, C, T>::row_typeoperator*(consttypenamemat<R, C, T>::column_type&lhs,constmat<R, C, T>&rhs){ usingrow_type=typenamemat<R, C, T>::row_type; row_typeret; rhs.apply([&ret,&lhs](constrow_type&row,dim_tri){ ret+=(row*row_type{lhs[ri]}); }); returnret; } template<dim_tR,dim_tC,typenameT> inlinetypenamemat<R, C, T>::column_typeoperator*(constmat<R, C, T>&lhs,consttypenamemat<R, C, T>::row_type&rhs){ usingcolumn_type=typenamemat<R, C, T>::column_type; usingvalue_type=typenamecolumn_type::value_type; column_typeret; rhs.apply([&ret,&lhs](value_typevalue,dim_tci){ ret+=(lhs.column(ci)*column_type{value}); }); returnret; } template<dim_tR,dim_tS,dim_tC,typenameT> inlinemat<R, C, T>operator*(constmat<R, S, T>&lhs,constmat<S, C, T>&rhs){ usingrow_type=typenamemat<R, C, T>::row_type; mat<R, C, T>ret; ret.apply([&lhs,&rhs](row_type&row,dim_tri){ row=(lhs[ri]*rhs); }); returnret; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator/(constmat<R, C, T>&lhs,Trhs){ returnmat<R, C, T>(lhs)/=rhs; } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator/(Tlhs,constmat<R, C, T>&rhs){ usingrow_type=typenamemat<R, C, T>::row_type; mat<R, C, T>tmp{rhs}; tmp.apply([lhs](row_type&row,dim_t/*unused*/){ row=lhs/row; }); returntmp; } template<dim_tR,dim_tC,typenameT> inlinetypenamemat<R, C, T>::row_typeoperator/(consttypenamemat<R, C, T>::column_type&lhs,constmat<R, C, T>&rhs){ return(lhs*inverse(rhs)); } template<dim_tR,dim_tC,typenameT> inlinetypenamemat<R, C, T>::column_typeoperator/(constmat<R, C, T>&lhs,consttypenamemat<R, C, T>::row_type&rhs){ return(inverse(lhs)*rhs); } template<dim_tR,dim_tC,typenameT> inlinemat<R, C, T>operator/(constmat<R, C, T>&lhs,constmat<R, C, T>&rhs){ returnmat<R, C, T>(lhs)/=rhs; } }//namespacetdm