C++98 線形代数パッケージ Eigenを調べる2 DenseCoeffsBase

#DenseCoeffsBase
/src/Core/DenseCoeffsBase.hに定義がある。
EigenBaseでは行列のサイズと、Expression-templateのためのヘルパ関数しなかったが、DenseCoeffsBaseでは要素へのアクセッサ(operator(Index,Index))の定義を要求する。
要素が読み込み可能か、書き込み可能か、その両方かによって３種類の定義がある。
#ReadOnlyAccessors
まずはReadOnlyAccessors版から

```cpp
namespace Eigen{
        template<typename Derived> class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
        {
                public:
                typedef typename internal::traits<Derived>::StorageKind StorageKind;
                typedef typename internal::traits<Derived>::Index Index;
                typedef typename internal::traits<Derived>::Scalar Scalar;
                typedef typename internal::packet_traits<Scalar>::type PacketScalar;

                typedef typename internal::conditional<bool(internal::traits<Derived>::Flags&LvalueBit),
                        const Scalar&,
                        typename internal::conditional<internal::is_arithmetic<Scalar>::value, Scalar, const Scalar>::type
                                >::type CoeffReturnType;

                typedef typename internal::add_const_on_value_type_if_arithmetic<
                        typename internal::packet_traits<Scalar>::type
                        >::type PacketReturnType;

                typedef EigenBase<Derived> Base;
                using Base::rows;
                using Base::cols;
                using Base::size;
                using Base::derived;

                EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner) const;
                EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner) const;

                EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const;
                EIGEN_STRONG_INLINE CoeffReturnType coeffByOuterInner(Index outer, Index inner) const;
                EIGEN_STRONG_INLINE CoeffReturnType operator()(Index row, Index col) const;
                EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const;
                EIGEN_STRONG_INLINE CoeffReturnType operator[](Index index) const;
                EIGEN_STRONG_INLINE CoeffReturnType x() const;
                EIGEN_STRONG_INLINE CoeffReturnType y() const;
                EIGEN_STRONG_INLINE CoeffReturnType z() const;
                EIGEN_STRONG_INLINE CoeffReturnType w() const;

                template<int LoadMode> EIGEN_STRONG_INLINE PacketReturnType packet(Index row, Index col) const;
                template<int LoadMode> EIGEN_STRONG_INLINE PacketReturnType packetByOuterInner(Index outer, Index inner) const;
                template<int LoadMode> EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const;

                protected:

                void coeffRef();
                void coeffRefByOuterInner();
                void writePacket();
                void writePacketByOuterInner();
                void copyCoeff();
                void copyCoeffByOuterInner();
                void copyPacket();
                void copyPacketByOuterInner();
                void stride();
                void innerStride();
                void outerStride();
                void rowStride();
        };
};
```

まず、typedef traitsに要素の型とSIMD用のパケットの型(SIMD以外にも使えるが)が追加された。
その次のブロックでは、ifメタ関数internal::conditionalを用いてアクセッサで要素を返す時の型を決めている。
可能なら、参照にしたりconstにしたりする。

次のブロックでは、EigenBaseから要求されていたメンバ関数の定義をDenseCoeffsBaseを継承するクラスに丸投げしている。

さらに次のEIGEN_STRONG_INLINEで修飾されたブロックに入る。
EIGEN_STRONG_INLINEはgccやclangにとってはただのinlineであるが、MS-Cやintel compilerにとっては__forcelineとなるマクロである。（/src/Core/util/Macros.h)

coeffとoperator()はアクセッサとして振舞うが、デバッグ時に振舞が異なる。
coeffはデバッグ時でも、範囲チェック等を行わない。
一方、operator()はデバッグ時では範囲チェックを行う。
デバッグ時で無いなら、operator()は範囲チェックを行わない。（行うようにすることもできる。）
デバッグフラグはやはり/src/Core/util/Macros.hに定義してあり、EIGEN_NO_DEBUGをdefineすれば良い。

coeff,coeffByOuterInner,...を定義するために継承先ではcoeff(Index,Index)を定義しなければならない。
また、packet用の関数群のために継承先でpacket(Index,Index)を定義しなければならない。
継承先で新たに定義するべきものは
CoeffReturnType coeff(Index,Index);
CoeffReturnType coeff(Index);
PacketReturnType packet(Index,Index);
PacketReturnType packet(Index);

最後のprotectedメンバはアクセス権限をテンプレートで抽象化したままDenseCoeffsBaseを継承したクラスを定義した時のusingでエラーが出るのを回避するためにある。エラーは適切なアクセス権限を持たないクラスをインスタンス化してprotectedメンバ関数にアクセスした時に起きる。

#WriteAccessors

```cpp
   template<typename Derived> class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived, ReadOnlyAccessors>
        {
                public:

                        typedef DenseCoeffsBase<Derived, ReadOnlyAccessors> Base;

                        typedef typename internal::traits<Derived>::StorageKind StorageKind;
                        typedef typename internal::traits<Derived>::Index Index;
                        typedef typename internal::traits<Derived>::Scalar Scalar;
                        typedef typename internal::packet_traits<Scalar>::type PacketScalar;
                        typedef typename NumTraits<Scalar>::Real RealScalar;

                        using Base::coeff;
                        using Base::rows;
                        using Base::cols;
                        using Base::size;
                        using Base::derived;
                        using Base::rowIndexByOuterInner;
                        using Base::colIndexByOuterInner;
                        using Base::operator[];
                        using Base::operator();
                        using Base::x;
                        using Base::y;
                        using Base::z;
                        using Base::w;

                        EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col);
                        EIGEN_STRONG_INLINE Scalar& coeffRefByOuterInner(Index outer, Index inner);
                        EIGEN_STRONG_INLINE Scalar& operator()(Index row, Index col);
                        EIGEN_STRONG_INLINE Scalar& coeffRef(Index index);
                        EIGEN_STRONG_INLINE Scalar&
                                operator[](Index index)
                        EIGEN_STRONG_INLINE Scalar&
                                operator()(Index index)
                        EIGEN_STRONG_INLINE Scalar& x();
                        EIGEN_STRONG_INLINE Scalar& y();
                        EIGEN_STRONG_INLINE Scalar& z();
                        EIGEN_STRONG_INLINE Scalar& w();


                        template<int StoreMode> EIGEN_STRONG_INLINE void writePacket (Index row, Index col, const typename internal::packet_traits<Scalar>::type& val);
                        template<int StoreMode> EIGEN_STRONG_INLINE void writePacketByOuterInner (Index outer, Index inner, const typename internal::packet_traits<Scalar>::type& val)
                        template<typename OtherDerived> EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other);
                        template<typename OtherDerived> EIGEN_STRONG_INLINE void copyCoeff(Index index, const DenseBase<OtherDerived>& other);
                        template<typename OtherDerived> EIGEN_STRONG_INLINE void copyCoeffByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other);
                        template<typename OtherDerived, int StoreMode, int LoadMode> EIGEN_STRONG_INLINE void copyPacket(Index row, Index col, const DenseBase<OtherDerived>& other);
                        template<typename OtherDerived, int StoreMode, int LoadMode> EIGEN_STRONG_INLINE void copyPacket(Index index, const DenseBase<OtherDerived>& other);
                        template<typename OtherDerived, int StoreMode, int LoadMode> EIGEN_STRONG_INLINE void copyPacketByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other);
         };
};

```

参照を返すoperator()と関連した関数群が追加された。
継承先では
Scalar& coeffRef(Index,Index)
Scalar& coeffRef(Index)
void write_packet<Index,Index,type)
void write_packet<Index,type)
void copy_packet<Index,Index,type)
void copy_packet<Index,type)
を定義すれば良い。