/*******************************************************************************
 * Copyright (c) 2015-2016 ONERA.
 * Ce logiciel est la propriété de l’ONERA (the French Aerospace Lab).
 * Tous droits réservés.
 *
 * Ce programme et les éléments qui l'accompagnent sont mis à disposition
 * aux conditions définies par le contrat de licence logiciel CeCILL-C soumise
 * au droit français et respectant les principes de diffusion des logiciels libres.
 * Vous pouvez utiliser, modifier et/ou redistribuer ce programme
 * sous les conditions de la licence CeCILL-C (http://www.cecill.info).

 * This software is property of ONERA (the French Aerospace Lab).
 * All rights reserved.
 *
 * This program and the accompanying materials are made available under
 * the terms of the CeCILL-C license under French law and
 * abiding by the rules of distribution of free software.
 * You can  use, modify and/ or redistribute the software under the terms of
 * the CeCILL-C license (http://www.cecill.info).
 *
 * Contributeurs/contributors:
 *      Florent Teichteil-Königsbuch (ONERA - Centre de Toulouse) - initial API and implementation
 *
 *******************************************************************************/

namespace epoch {
	namespace algebra {
		using namespace boost::numeric::ublas;

		// Triangular Hessenberg Matrix element access
		template <typename T>
		inline const T& UblasTriangularHessenberg::MatrixType<T>::Implementation::operator()(const std::size_t& i, const std::size_t& j) const {
			if (i == (j + 1)) {
				return diagonalVector(i - 1);
			} else {
				return upperTriangle(i, j);
			}
		}
		
		template <typename T>
		inline T& UblasTriangularHessenberg::MatrixType<T>::Implementation::operator()(const std::size_t& i, const std::size_t& j) {
			if (i == (j + 1)) {
				return diagonalVector(i - 1);
			} else {
				return upperTriangle(i, j);
			}
		}
		
		// Identity constructs
		
		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline std::auto_ptr<typename UblasBackend<Thessenberg, Tbackend>::template Matrix<T>::Implementation>
				UblasBackend<Thessenberg, Tbackend>::Matrix<T>::identity(const std::size_t& dim) {
			boost::numeric::ublas::identity_matrix<T, boost::numeric::ublas::column_major> m(dim);
			return std::auto_ptr<Implementation>(new Implementation(m));
		}


		template <typename T>
		inline std::auto_ptr<typename UblasBandedHessenberg::template MatrixType<T>::Implementation>
				UblasBandedHessenberg::MatrixType<T>::identity(const std::size_t& dim) {
			std::auto_ptr<Implementation> m(new Implementation(dim, dim, 1, dim-1));
			for (std::size_t i = 0 ; i < dim ; i++) {
				for (std::size_t j = i + 1 ; j < dim ; j++) {
					(*m)(i, j) = 0;
				}
			}
			for (std::size_t i = 0 ; i < (dim-1) ; i++) {
				(*m)(i, i) = 1;
				(*m)(i + 1, i) = 0;
			}
			(*m)(dim - 1, dim - 1) = 1;
			return m;
		}


		template <typename T>
		inline std::auto_ptr<typename UblasTriangularHessenberg::template MatrixType<T>::Implementation>
				UblasTriangularHessenberg::template MatrixType<T>::identity(const std::size_t& dim) {
			std::auto_ptr<Implementation> m(new Implementation());
			m->upperTriangle.resize(dim, dim);
			m->diagonalVector.resize(dim - 1);
			for (std::size_t i = 0 ; i < dim ; i++) {
				for (std::size_t j = i + 1 ; j < dim ; j++) {
					(m->upperTriangle)(i, j) = 0;
				}
			}
			for (std::size_t i = 0 ; i < (dim-1) ; i++) {
				(m->upperTriangle)(i, i) = 1;
				(m->diagonalVector)(i) = 0;
			}
			(m->upperTriangle)(dim - 1, dim - 1) = 1;
			return m;
		}


		template <typename T>
		inline std::auto_ptr<typename UblasDenseHessenberg::template MatrixType<T>::Implementation>
				UblasDenseHessenberg::MatrixType<T>::identity(const std::size_t& dim) {
			boost::numeric::ublas::identity_matrix<T, boost::numeric::ublas::column_major> m(dim);
			return std::auto_ptr<Implementation>(new Implementation(m));
		}


		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline std::auto_ptr<typename UblasBackend<Thessenberg, Tbackend>::template Vector<T>::Implementation>
				UblasBackend<Thessenberg, Tbackend>::Vector<T>::identity(const std::size_t& dim) {
			boost::numeric::ublas::scalar_vector<T> v(dim, 1.0);
			return std::auto_ptr<Implementation>(new Implementation(v));
		}


		// Zero constructs
		
		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline std::auto_ptr<typename UblasBackend<Thessenberg, Tbackend>::template Matrix<T>::Implementation>
				UblasBackend<Thessenberg, Tbackend>::Matrix<T>::zero(const std::size_t& dim1, const std::size_t& dim2) {
			boost::numeric::ublas::zero_matrix<T, boost::numeric::ublas::column_major> m(dim1, dim2);
			return std::auto_ptr<Implementation>(new Implementation(m));
		}


		template <typename T>
		inline std::auto_ptr<typename UblasBandedHessenberg::template MatrixType<T>::Implementation>
				UblasBandedHessenberg::MatrixType<T>::zero(const std::size_t& dim1, const std::size_t& dim2) {
			std::auto_ptr<Implementation> m(new Implementation(dim1, dim2, 1, std::min(dim1, dim2) - 1));
			for (std::size_t j = 0 ; j < dim2 ; j++) {
				(*m)(0, j) = 0;
			}
			for (std::size_t i = 1 ; i < std::min(dim1, dim2) ; i++) {
				for (std::size_t j = i - 1 ; j < dim2 ; j++) {
					(*m)(i, j) = 0;
				}
			}
			return m;
		}


		template <typename T>
		inline std::auto_ptr<typename UblasTriangularHessenberg::template MatrixType<T>::Implementation>
				UblasTriangularHessenberg::MatrixType<T>::zero(const std::size_t& dim1, const std::size_t& dim2) {
			std::auto_ptr<Implementation> m(new Implementation());
			m->upperTriangle.resize(dim1, dim2);
			m->diagonalVector.resize(std::max(dim1, dim2) - 1);
			for (std::size_t i = 0 ; i < dim1 ; i++) {
				for (std::size_t j = i ; j < dim2 ; j++) {
					(m->upperTriangle)(i, j) = 0;
				}
			}
			for (std::size_t i = 0 ; i < (std::max(dim1, dim2) - 1) ; i++) {
				(m->diagonalVector)(i) = 0;
			}
			return m;
		}


		template <typename T>
		inline std::auto_ptr<typename UblasDenseHessenberg::template MatrixType<T>::Implementation>
				UblasDenseHessenberg::MatrixType<T>::zero(const std::size_t& dim1, const std::size_t& dim2) {
			boost::numeric::ublas::zero_matrix<T, boost::numeric::ublas::column_major> m(dim1, dim2);
			return std::auto_ptr<Implementation>(new Implementation(m));
		}


		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline std::auto_ptr<typename UblasBackend<Thessenberg, Tbackend>::template Vector<T>::Implementation>
				UblasBackend<Thessenberg, Tbackend>::Vector<T>::zero(const std::size_t& dim1, const std::size_t& dim2) {
			boost::numeric::ublas::zero_vector<T> v(dim1);
			return std::auto_ptr<Implementation>(new Implementation(v));
		}


		// Function conj

		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline std::auto_ptr<typename UblasBackend<Thessenberg, Tbackend>::template Matrix<T>::Implementation>
				UblasBackend<Thessenberg, Tbackend>::Matrix<T>::conj(const Implementation& m) {
			return std::auto_ptr<Implementation>(new Implementation(boost::numeric::ublas::conj(m)));
		}


		template <typename T>
		inline std::auto_ptr<typename UblasBandedHessenberg::template MatrixType<T>::Implementation>
				UblasBandedHessenberg::MatrixType<T>::conj(const Implementation& m) {
			return std::auto_ptr<Implementation>(new Implementation(boost::numeric::ublas::conj(m)));
		}


		template <typename T>
		inline std::auto_ptr<typename UblasTriangularHessenberg::template MatrixType<T>::Implementation>
				UblasTriangularHessenberg::MatrixType<T>::conj(const Implementation& m) {
			std::auto_ptr<Implementation> cm(new Implementation());
			cm->upperTriangle = boost::numeric::ublas::conj(m.upperTriangle);
			cm->diagonalVector = boost::numeric::ublas::conj(m.diagonalVector);
			return cm;
		}


		template <typename T>
		inline std::auto_ptr<typename UblasDenseHessenberg::template MatrixType<T>::Implementation>
				UblasDenseHessenberg::MatrixType<T>::conj(const Implementation& m) {
			return std::auto_ptr<Implementation>(new Implementation(boost::numeric::ublas::conj(m)));
		}


		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline std::auto_ptr<typename UblasBackend<Thessenberg, Tbackend>::template Vector<T>::Implementation>
				UblasBackend<Thessenberg, Tbackend>::Vector<T>::conj(const Implementation& v) {
			return std::auto_ptr<Implementation>(new Implementation(boost::numeric::ublas::conj(v)));
		}


		// Function real

		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline std::auto_ptr<typename UblasBackend<Thessenberg, Tbackend>::template Matrix<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>
				UblasBackend<Thessenberg, Tbackend>::Matrix<T>::real(const Implementation& m) {
			return std::auto_ptr<typename Matrix<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>(
					new typename Matrix<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation(boost::numeric::ublas::real(m)));
		}


		template <typename T>
		inline std::auto_ptr<typename UblasBandedHessenberg::template MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>
				UblasBandedHessenberg::MatrixType<T>::real(const Implementation& m) {
			return std::auto_ptr<typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>(
					new typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation(boost::numeric::ublas::real(m)));
		}


		template <typename T>
		inline std::auto_ptr<typename UblasTriangularHessenberg::template MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>
				UblasTriangularHessenberg::MatrixType<T>::real(const Implementation& m) {
			std::auto_ptr<typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation> rm(
					new typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation());
			rm->upperTriangle = boost::numeric::ublas::real(m.upperTriangle);
			rm->diagonalVector = boost::numeric::ublas::real(m.diagonalVector);
			return rm;
		}


		template <typename T>
		inline std::auto_ptr<typename UblasDenseHessenberg::template MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>
				UblasDenseHessenberg::MatrixType<T>::real(const Implementation& m) {
			return std::auto_ptr<typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>(
					new typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation(boost::numeric::ublas::real(m)));
		}


		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline std::auto_ptr<typename UblasBackend<Thessenberg, Tbackend>::template Vector<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>
				UblasBackend<Thessenberg, Tbackend>::Vector<T>::real(const Implementation& v) {
			return std::auto_ptr<typename Vector<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>(
					new typename Vector<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation(boost::numeric::ublas::real(v)));
		}


		// Function imag

		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline std::auto_ptr<typename UblasBackend<Thessenberg, Tbackend>::template Matrix<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>
				UblasBackend<Thessenberg, Tbackend>::Matrix<T>::imag(const Implementation& m) {
			return std::auto_ptr<typename Matrix<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>(
					new typename Matrix<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation(boost::numeric::ublas::imag(m)));
		}


		template <typename T>
		inline std::auto_ptr<typename UblasBandedHessenberg::template MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>
				UblasBandedHessenberg::MatrixType<T>::imag(const Implementation& m) {
			return std::auto_ptr<typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>(
					new typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation(boost::numeric::ublas::imag(m)));
		}


		template <typename T>
		inline std::auto_ptr<typename UblasTriangularHessenberg::template MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>
				UblasTriangularHessenberg::MatrixType<T>::imag(const Implementation& m) {
			std::auto_ptr<typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation> im(
					new typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation());
			im->upperTriangle = boost::numeric::ublas::imag(m.upperTriangle);
			im->diagonalVector = boost::numeric::ublas::imag(m.diagonalVector);
			return im;
		}


		template <typename T>
		inline std::auto_ptr<typename UblasDenseHessenberg::template MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>
				UblasDenseHessenberg::MatrixType<T>::imag(const Implementation& m) {
			return std::auto_ptr<typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>(
					new typename MatrixType<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation(boost::numeric::ublas::imag(m)));
		}


		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline std::auto_ptr<typename UblasBackend<Thessenberg, Tbackend>::template Vector<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>
				UblasBackend<Thessenberg, Tbackend>::Vector<T>::imag(const Implementation& v) {
			return std::auto_ptr<typename Vector<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation>(
					new typename Vector<typename boost::numeric::ublas::type_traits<T>::real_type>::Implementation(boost::numeric::ublas::imag(v)));
		}


		// Function print

		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline void UblasBackend<Thessenberg, Tbackend>::Matrix<T>::print(const Implementation& m, std::ostream& o) {
			o << m;
		}


		template <typename T>
		inline void UblasBandedHessenberg::MatrixType<T>::print(const Implementation& m, std::ostream& o) {
			o << m;
		}


		template <typename T>
		inline void UblasTriangularHessenberg::MatrixType<T>::print(const Implementation& m, std::ostream& o) {
			boost::numeric::ublas::matrix<T, boost::numeric::ublas::column_major> dm = m.upperTriangle;
			boost::numeric::ublas::matrix_vector_slice<boost::numeric::ublas::matrix<T, boost::numeric::ublas::column_major> >(
																		dm,
					                                                    boost::numeric::ublas::slice(1, 1, dm.size1() - 1),
					                                                    boost::numeric::ublas::slice(0, 1, dm.size2() - 1)) = m.diagonalVector;
			o << dm;
		}


		template <typename T>
		inline void UblasDenseHessenberg::MatrixType<T>::print(const Implementation& m, std::ostream& o) {
			o << m;
		}


		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline void UblasBackend<Thessenberg, Tbackend>::Vector<T>::print(const Implementation& v, std::ostream& o) {
			o << v;
		}


		// Function F1
		
		template <typename Thessenberg, typename Tbackend> template <typename T> template <typename Tc>
		inline void UblasBackend<Thessenberg, Tbackend>::Matrix<T>::computeF1(const T& a, const T& b, const T& c, const typename Matrix<Tc>::Implementation& L, Implementation& res) {
			res += a * ((b * real(L)) - (c * imag(L)));
		}


		template <typename T, typename Tc>
		inline void UblasBandedHessenberg::computeF1(const T& a, const T& b, const T& c, const typename MatrixType<Tc>::Implementation& L, typename MatrixType<T>::Implementation& res) {
			res += a * ((b * real(L)) - (c * imag(L)));
		}


		template <typename T, typename Tc>
		inline void UblasTriangularHessenberg::computeF1(const T& a, const T& b, const T& c, const typename MatrixType<Tc>::Implementation& L, typename MatrixType<T>::Implementation& res) {
			(res->upperTriangle) += a * ((b * real(L->upperTriangle)) - (c * imag(L->upperTriangle)));
			(res->diagonalVector) += a * ((b * real(L->diagonalVector)) - (c * imag(L->diagonalVector)));
		}


		template <typename T, typename Tc>
		inline void UblasDenseHessenberg::computeF1(const T& a, const T& b, const T& c, const typename MatrixType<Tc>::Implementation& L, typename MatrixType<T>::Implementation& res) {
			res += a * ((b * real(L)) - (c * imag(L)));
		}


		// Function F2
		
		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline void UblasBackend<Thessenberg, Tbackend>::Matrix<T>::computeF2(const T& a, const Implementation& L, Implementation& res) {
			res += a * L;
		}


		template <typename T>
		inline void UblasBandedHessenberg::computeF2(const T& a, const typename MatrixType<T>::Implementation& L, typename MatrixType<T>::Implementation& res) {
			res += a * L;
		}


		template <typename T>
		inline void UblasTriangularHessenberg::computeF2(const T& a, const typename MatrixType<T>::Implementation& L, typename MatrixType<T>::Implementation& res) {
			(res->upperTriangle) += a * (L->upperTriangle);
			(res->diagonalVector) += a * (L->diagonalVector);
		}


		template <typename T>
		inline void UblasDenseHessenberg::computeF2(const T& a, const typename MatrixType<T>::Implementation& L, typename MatrixType<T>::Implementation& res) {
			res += a * L;
		}


		template <typename Thessenberg, typename Tbackend> template <typename TrealMatrix, typename TcomplexVector>
		void UblasBackend<Thessenberg, Tbackend>::realSchurDecomposition(TrealMatrix& A, TcomplexVector& eig, TrealMatrix& sv) {
			fortran_int_t sdim; // useless since no sorting used
            boost::numeric::bindings::lapack::gees('V', 'N', 0, A, sdim, eig, sv, boost::numeric::bindings::lapack::optimal_workspace());
		}


		template <typename Thessenberg, typename Tbackend> template <typename T>
		inline void UblasBackend<Thessenberg, Tbackend>::subvector(const typename Matrix<T>::Implementation& M,
			                                                       const std::size_t& index,
			                                                       typename Vector<T>::Implementation& res) {
			noalias(res) = matrix_vector_slice<const typename Matrix<T>::Implementation>(M, slice(index - 1, 0, M.size1() - index), slice(index, 1, M.size1() - index));
		}


		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<Thessenberg, Tbackend>::submatrix(const typename Matrix<T1>::Implementation& M,
			                                                       const std::size_t& index,
			                                                       const T2& a,
			                                                       const T3& b,
			                                                       const T4& c,
			                                                       const T5& d,
			                                                       typename Matrix<T6>::Implementation& res) {
			typename Vector<T6>::Implementation v1 = matrix_vector_slice<const typename Matrix<T1>::Implementation>(M, slice(index - 2, 0, M.size1() - index), slice(index, 1, M.size1() - index));
			typename Vector<T6>::Implementation v2 = matrix_vector_slice<const typename Matrix<T1>::Implementation>(M, slice(index - 1, 0, M.size1() - index), slice(index, 1, M.size1() - index));
			noalias(row(res, 0)) = (a * v1) + (b * v2);
			noalias(row(res, 1)) = (c * v1) + (d * v2);
		}


		// Function computeO1a

		// computeO1a(a, M, tm, V, tv, res): res = a * tv(trans(V)) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::computeO1a(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res,
							   const std::size_t& index) {
			axpy_prod(vTransformation.opsV(V), mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())), res, true);
			res *= a;
		}

		// computeO1a(a, M, tm, V, tv, res): res = a * tv(trans(V)) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::computeO1a(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res,
							   const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), vTransformation.opsV(V), 0, res);
		}

		// computeO1a(a, M, tm, V, tv, res): res = a * tv(trans(V)) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO1a(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res,
							   const std::size_t& index) {
			axpy_prod(vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M.upperTriangle, index, M.upperTriangle.size1(), index, M.upperTriangle.size2())),
			          res, true);
			res *= a;
			noalias(subrange(res, 0, res.size() - 1)) += a * element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
		}

		// computeO1a(a, M, tm, V, tv, res): res = a * tv(trans(V)) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO1a(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res,
							   const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation::UpperTriangleType sM(M.size1() - index, M.size2() - index);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			noalias(res) = vTransformation.opsV(V);
			boost::numeric::bindings::blas::trmv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), res);
			noalias(subrange(res, 0, res.size() - 1)) += a * element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
		}

		// computeO1a(a, M, tm, V, tv, res): res = a * tv(trans(V)) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::computeO1a(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res,
							   const std::size_t& index) {
			axpy_prod(vTransformation.opsV(V), mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())), res, true);
			res *= a;
		}

		// computeO1a(a, M, tm, V, tv, res): res = a * tv(trans(V)) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::computeO1a(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res,
							   const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation sM(M.size1() - index, M.size2() - index);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gemv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), vTransformation.opsV(V), 0, res);
		}


		// Function computeO1b

		// computeO1b(a, M, tm, V, tv, res): res = a * tv(V) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::computeO1b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(a * vTransformation.opsM(V), mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())), res, true);
		}

		// computeO1b(a, M, tm, V, tv, res): res = a * tv(V) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::computeO1b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(a,
			                                     boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(row(V, 0)),
			                                     0,
			                                     row(res, 0));
			boost::numeric::bindings::blas::gbmv(a,
			                                     boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(row(V, 1)),
			                                     0,
			                                     row(res, 1));
		}

		// computeO1b(a, M, tm, V, tv, res): res = a * tv(V) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO1b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(a * vTransformation.opsM(V), mTransformation.opsM(subrange(M.upperTriangle, index, M.upperTriangle.size1(), index, M.upperTriangle.size2())), res, true);
			
			noalias(matrix_vector_slice<typename Matrix<T6>::Implementation>(res, slice(0, 0, res.size2() - 1), slice(0, 1, res.size2() - 1)))
				+= a * element_prod(vTransformation.opsV(matrix_vector_slice<const typename Matrix<T4>::Implementation>(V, slice(0, 0, V.size2() - 1), slice(1, 1, V.size2() - 1))),
				                    mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));

			noalias(matrix_vector_slice<typename Matrix<T6>::Implementation>(res, slice(1, 0, res.size2() - 1), slice(0, 1, res.size2() - 1)))
				+= a * element_prod(vTransformation.opsV(matrix_vector_slice<const typename Matrix<T4>::Implementation>(V, slice(1, 0, V.size2() - 1), slice(1, 1, V.size2() - 1))),
				                    mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
		}

		// computeO1b(a, M, tm, V, tv, res): res = a * tv(V) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO1b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation::UpperTriangleType sM(M.size1() - index, M.size2() - index);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			noalias(row(res, 0)) = vTransformation.opsV(row(V, 0));
			boost::numeric::bindings::blas::trmv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), row(res, 0));
			noalias(subrange(row(res, 0), 0, res.size2() - 1)) += a * element_prod(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			noalias(row(res, 1)) = vTransformation.opsV(row(V, 1));
			boost::numeric::bindings::blas::trmv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), row(res, 1));
			noalias(subrange(row(res, 1), 0, res.size2() - 1)) += a * element_prod(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
		}

		// computeO1b(a, M, tm, V, tv, res): res = a * tv(V) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::computeO1b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(a * vTransformation.opsM(V), mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())), res, true);
		}

		// computeO1b(a, M, tm, V, tv, res): res = a * tv(V) * tm(M)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::computeO1b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation sM(M.size1() - index, M.size2() - index);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gemm(a, vTransformation.opbM(V), mTransformation.opbM(sM), 0, res);
		}


		// Function computeO1c

		// computeO1c(a, M, tm, V, tv, res): res = a * tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::computeO1c(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M), vTransformation.opsV(V), res, true);
			res *= a;
		}

		// computeO1c(a, M, tm, V, tv, res): res = a * tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::computeO1c(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res) {
			boost::numeric::bindings::blas::gbmv(a, mTransformation.opbM(M), vTransformation.opsV(V), 0, res);
		}

		// computeO1c(a, M, tm, V, tv, res): res = a * tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO1c(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M.upperTriangle), vTransformation.opsV(V), res, true);
			res *= a;
			noalias(subrange(res, 1, res.size())) += a * element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1));
		}

		// computeO1c(a, M, tm, V, tv, res): res = a * tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO1c(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res) {
			noalias(res) = vTransformation.opsV(V);
			boost::numeric::bindings::blas::trmv(a, mTransformation.opbM(M.upperTriangle), res);
			noalias(subrange(res, 1, res.size())) += a * element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1));
		}

		// computeO1c(a, M, tm, V, tv, res): res = a * tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::computeO1c(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M), vTransformation.opsV(V), res, true);
			res *= a;
		}

		// computeO1c(a, M, tm, V, tv, res): res = a * tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::computeO1c(
		                       const T1& a,
							   const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
							   const typename Vector<T4>::Implementation& V, const T5& vTransformation,
							   typename Vector<T6>::Implementation& res) {
			boost::numeric::bindings::blas::gemv(a, mTransformation.opbM(M), vTransformation.opsV(V), 0, res);
		}


		// Function computeO2pa

		// computeO2pa(V, tv, res): res += tv(V)
		// Operates on the subvector of res at row i, starting from column i+1
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO2pa(
								const typename Vector<T1>::Implementation& V, const T2& vTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(matrix_vector_slice<typename HessenbergMatrix<T3>::Implementation>(res, slice(index, 0, V.size()), slice(index + 1, 1, V.size())))
					+= vTransformation.opsV(V);
		}

		// computeO2pa(V, tv, res): res += tv(V)
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO2pa(
								const typename Vector<T1>::Implementation& V, const T2& vTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(matrix_vector_slice<typename HessenbergMatrix<T3>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index, 0, V.size()), slice(index + 1, 1, V.size())))
					+= vTransformation.opsV(V);
		}

		// computeO2pa(V, tv, res): res += tv(V)
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO2pa(
								const typename Vector<T1>::Implementation& V, const T2& vTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(matrix_vector_slice<typename HessenbergMatrix<T3>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index, 0, V.size()), slice(index + 1, 1, V.size())))
					+= vTransformation.opsV(V);
		}


		// Function computeO2ma

		// computeO2ma(V, tv, res): res -= tv(V)
		// Operates on the subvector of res at row i, starting from column i+1
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO2ma(
								const typename Vector<T1>::Implementation& V, const T2& vTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(matrix_vector_slice<typename HessenbergMatrix<T3>::Implementation>(res, slice(index, 0, V.size()), slice(index + 1, 1, V.size())))
					-= vTransformation.opsV(V);
		}

		// computeO2ma(V, tv, res): res -= tv(V)
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO2ma(
								const typename Vector<T1>::Implementation& V, const T2& vTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(matrix_vector_slice<typename HessenbergMatrix<T3>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index, 0, V.size()), slice(index + 1, 1, V.size())))
					-= vTransformation.opsV(V);
		}

		// computeO2ma(V, tv, res): res -= tv(V)
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO2ma(
								const typename Vector<T1>::Implementation& V, const T2& vTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(matrix_vector_slice<typename HessenbergMatrix<T3>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index, 0, V.size()), slice(index + 1, 1, V.size())))
					-= vTransformation.opsV(V);
		}


		// Function computeO2pb

		// computeO2pb(M, tm, res): res += tm(M)
		// Operates on the submatrix of res at rows i and i+1, starting from column i+2
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO2pb(
								const typename Matrix<T1>::Implementation& M, const T2& mTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(subrange(res, index, index + 2, index + 2, res.size2())) += mTransformation.opsM(M);
		}

		// computeO2pb(M, tm, res): res += tm(M)
		// Operates on the submatrix of res at rows i and i+1, starting from column i+2
		template <> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO2pb(
								const typename Matrix<T1>::Implementation& M, const T2& mTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(subrange(res.upperTriangle, index, index + 2, index + 2, res.upperTriangle.size2())) += mTransformation.opsM(M);
		}

		// computeO2pb(M, tm, res): res += tm(M)
		// Operates on the submatrix of res at rows i and i+1, starting from column i+2
		template <> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO2pb(
								const typename Matrix<T1>::Implementation& M, const T2& mTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(subrange(res.upperTriangle, index, index + 2, index + 2, res.upperTriangle.size2())) += mTransformation.opsM(M);
		}


		// Function computeO2mb

		// computeO2mb(M, tm, res): res -= tm(M)
		// Operates on the submatrix of res at rows i and i+1, starting from column i+2
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO2mb(
								const typename Matrix<T1>::Implementation& M, const T2& mTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(subrange(res, index, index + 2, index + 2, res.size2())) -= mTransformation.opsM(M);
		}

		// computeO2mb(M, tm, res): res -= tm(M)
		// Operates on the submatrix of res at rows i and i+1, starting from column i+2
		template <> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO2mb(
								const typename Matrix<T1>::Implementation& M, const T2& mTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(subrange(res.upperTriangle, index, index + 2, index + 2, res.upperTriangle.size2())) -= mTransformation.opsM(M);
		}

		// computeO2mb(M, tm, res): res -= tm(M)
		// Operates on the submatrix of res at rows i and i+1, starting from column i+2
		template <> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO2mb(
								const typename Matrix<T1>::Implementation& M, const T2& mTransformation,
								typename HessenbergMatrix<T3>::Implementation& res,
								const std::size_t& index) {
			noalias(subrange(res.upperTriangle, index, index + 2, index + 2, res.upperTriangle.size2())) -= mTransformation.opsM(M);
		}


		// Function computeO2pc
		// computeO2pc(V, tv, res): res += tv(V)

		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO2pc(
								const typename Vector<T1>::Implementation& V, const T2& vTransformation,
								typename Vector<T3>::Implementation& res) {
			noalias(res) += vTransformation.opsV(V);
		}


		// Function computeO2mc
		// computeO2mc(V, tv, res): res -= tv(V)

		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO2mc(
								const typename Vector<T1>::Implementation& V, const T2& vTransformation,
								typename Vector<T3>::Implementation& res) {
			noalias(res) -= vTransformation.opsV(V);
		}


		// Function computeO3a

		// computeO3a(a, M, tm, V, tv, res): res = a * ((tv(trans(V)) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::computeO3a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsV(V), mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())), res, false);
			res *= - a;
		}

		// computeO3a(a, M, tm, V, tv, res): res = a * ((tv(trans(V)) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::computeO3a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), vTransformation.opsV(V), - a, res);
		}

		// computeO3a(a, M, tm, V, tv, res): res = a * ((tv(trans(V)) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO3a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsV(V), mTransformation.opsM(subrange(M.upperTriangle, index, M.upperTriangle.size1(), index, M.upperTriangle.size2())), res, false);
			noalias(subrange(res, 0, res.size() - 1)) += element_prod(subrange(- vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			res *= - a;
		}

		// computeO3a(a, M, tm, V, tv, res): res = a * ((tv(trans(V)) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO3a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation::UpperTriangleType sM(M.size1() - index, M.size2() - index);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Vector<T4>::Implementation tmpV = vTransformation.opsV(V);
			boost::numeric::bindings::blas::trmv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), tmpV);
			noalias(subrange(tmpV, 0, tmpV.size() - 1)) += a * element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			res = tmpV - (a * res);
		}

		// computeO3a(a, M, tm, V, tv, res): res = a * ((tv(trans(V)) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::computeO3a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsV(V), mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())), res, false);
			res *= - a;
		}

		// computeO3a(a, M, tm, V, tv, res): res = a * ((tv(trans(V)) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::computeO3a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gemv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), vTransformation.opsV(V), - a, res);
		}


		// Function computeO3b

		// computeO3b(a, M, tm, V, tv, res): res = a * ((tv(V) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::computeO3b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsM(V), mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())), res, false);
			res *= - a;
		}

		// computeO3b(a, M, tm, V, tv, res): res = a * ((tv(V) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::computeO3b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), vTransformation.opsV(row(V, 0)), - a, row(res, 0));
			boost::numeric::bindings::blas::gbmv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), vTransformation.opsV(row(V, 1)), - a, row(res, 1));
		}

		// computeO3b(a, M, tm, V, tv, res): res = a * ((tv(V) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO3b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsV(V), mTransformation.opsM(subrange(M.upperTriangle, index, M.upperTriangle.size1(), index, M.upperTriangle.size2())), res, false);
			
			noalias(matrix_vector_slice<typename Matrix<T6>::Implementation>(res, slice(0, 0, res.size2() - 1), slice(0, 1, res.size2() - 1)))
				-= element_prod(vTransformation.opsV(matrix_vector_slice<const typename Matrix<T4>::Implementation>(V, slice(0, 0, V.size2() - 1), slice(1, 1, V.size2() - 1))),
				                    mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));

			noalias(matrix_vector_slice<typename Matrix<T6>::Implementation>(res, slice(1, 0, res.size2() - 1), slice(0, 1, res.size2() - 1)))
				-= element_prod(vTransformation.opsV(matrix_vector_slice<const typename Matrix<T4>::Implementation>(V, slice(1, 0, V.size2() - 1), slice(1, 1, V.size2() - 1))),
				                    mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			
			res *= - a;
		}

		// computeO3b(a, M, tm, V, tv, res): res = a * ((tv(V) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO3b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation::UpperTriangleType sM(M.size1() - index, M.size2() - index);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T4>::Implementation tmpV = vTransformation.opsM(V);
			boost::numeric::bindings::blas::trmv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), row(tmpV, 0));
			noalias(subrange(row(tmpV, 0), 0, tmpV.size2() - 1)) += a * element_prod(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			boost::numeric::bindings::blas::trmv(a, boost::numeric::bindings::trans(mTransformation.opbM(sM)), row(tmpV, 1));
			noalias(subrange(row(tmpV, 1), 0, tmpV.size2() - 1)) += a * element_prod(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			res = tmpV - (a * res);
		}

		// computeO3b(a, M, tm, V, tv, res): res = a * ((tv(V) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::computeO3b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsM(V), mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())), res, false);
			res *= - a;
		}

		// computeO3b(a, M, tm, V, tv, res): res = a * ((tv(V) * tm(M)) - res)
		// Operates on the square submatrix of M starting at row i and column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::computeO3b(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Matrix<T4>::Implementation& V, const T5& vTransformation,
								typename Matrix<T6>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T2>::Implementation sM(M.size1() - index, M.size2() - index);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gemm(a, vTransformation.opbM(V), mTransformation.opbM(sM), - a, res);
		}


		// Function computeO3c

		// computeO3c(a, M, tm, V, tv, res): res = a * ((tm(M) * tv(V)) - res)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::computeO3c(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M), - vTransformation.opsV(V), res, false);
			res *= - a;
		}

		// computeO3c(a, M, tm, V, tv, res): res = a * ((tm(M) * tv(V)) - res)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::computeO3c(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res) {
			boost::numeric::bindings::blas::gbmv(a, mTransformation.opbM(M), vTransformation.opsV(V), - a, res);
		}

		// computeO3c(a, M, tm, V, tv, res): res = a * ((tm(M) * tv(V)) - res)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO3c(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M.upperTriangle), - vTransformation.opsV(V), res, false);
			noalias(subrange(res, 1, res.size())) += element_prod(subrange(- vTransformation.opsV(V), 0, V.size() - 1), mTransformation.opsV(M.diagonalVector));
			res *= - a;
		}

		// computeO3c(a, M, tm, V, tv, res): res = a * ((tm(M) * tv(V)) - res)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO3c(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res) {
			typename Vector<T4>::Implementation tmpV = vTransformation.opsV(V);
			boost::numeric::bindings::blas::trmv(a, mTransformation.opbM(M), tmpV);
			noalias(subrange(tmpV, 1, tmpV.size())) += a * element_prod(subrange(vTransformation.opsV(V), 0, V.size() - 1), mTransformation.opsV(M.diagonalVector));
			res = tmpV - (a * res);
		}

		// computeO3c(a, M, tm, V, tv, res): res = a * ((tm(M) * tv(V)) - res)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::computeO3c(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M), - vTransformation.opsV(V), res, false);
			res *= - a;
		}

		// computeO3c(a, M, tm, V, tv, res): res = a * ((tm(M) * tv(V)) - res)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::computeO3c(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								const typename Vector<T4>::Implementation& V, const T5& vTransformation,
								typename Vector<T6>::Implementation& res) {
			boost::numeric::bindings::blas::gemv(a, mTransformation.opbM(M), vTransformation.opsV(V), - a, res);
		}


		// Function computeO4pa

		template <typename Thessenberg, typename Tbackend, typename TresTransformation>
		struct ComputeO4Factory {
			template <typename T>
			struct Matrix {
				typedef typename UblasBackend<Thessenberg, Tbackend>::template Matrix<T>::Implementation Implementation;
			};

			template <typename T>
			struct HessenbergMatrix {
				typedef typename UblasBackend<Thessenberg, Tbackend>::template HessenbergMatrix<T>::Implementation Implementation;
			};

			template <typename T>
			struct Vector {
				typedef typename UblasBackend<Thessenberg, Tbackend>::template Vector<T>::Implementation Implementation;
			};
			
			// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
			// Operates on the square submatrix of M starting at row i and column i
			// Operates on the subvector of res at row i-1, starting from column i
			template <typename T1, typename T2, typename T3, typename T4, typename T5>
			static void pa(const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
						   const typename Vector<T3>::Implementation& V, const T4& vTransformation,
						   typename HessenbergMatrix<T5>::Implementation& res,
						   const std::size_t& index);

			// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
			// Operates on the square submatrix of M starting at row i and column i
			// Operates on the subvector of res at row i-1, starting from column i
			template <typename T1, typename T2, typename T3, typename T4, typename T5>
			static void ma(const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
						   const typename Vector<T3>::Implementation& V, const T4& vTransformation,
						   typename HessenbergMatrix<T5>::Implementation& res,
						   const std::size_t& index);

			// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
			// Operates on the square submatrix of M starting at row i and column i
			// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
			template <typename T1, typename T2, typename T3, typename T4, typename T5>
			static void pb(const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
						   const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
						   typename HessenbergMatrix<T5>::Implementation& res,
						   const std::size_t& index);

			// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
			// Operates on the square submatrix of M starting at row i and column i
			// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
			template <typename T1, typename T2, typename T3, typename T4, typename T5>
			static void mb(const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
						   const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
						   typename HessenbergMatrix<T5>::Implementation& res,
						   const std::size_t& index);

			// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
			template <typename T1, typename T2, typename T3, typename T4, typename T5>
			static void pc(const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
						   const typename Vector<T3>::Implementation& V, const T4& vTransformation,
						   typename Vector<T5>::Implementation& res);

			// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
			template <typename T1, typename T2, typename T3, typename T4, typename T5>
			static void mc(const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
						   const typename Vector<T3>::Implementation& V, const T4& vTransformation,
						   typename Vector<T5>::Implementation& res);
		};
			

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO4pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res, const T6& resTransformation,
								const std::size_t& index) {
			ComputeO4Factory<Thessenberg, Tbackend, T6>::template pa<T1, T2, T3, T4, T5>(M, mTransformation, V, vTransformation, res, index);
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::NoTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation> resS(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size()));
			axpy_prod(vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())),
			          resS,
			          false);
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::ConjugateTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation> resS(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size()));
			axpy_prod(conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resS,
			          false);
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::MakeRealTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation> resS(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size()));
			axpy_prod(2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resS,
			          false);
			axpy_prod(-2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resS,
			          false);
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::NoTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(1, boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(V),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::ConjugateTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(1, boost::numeric::bindings::herm(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(conj(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::MakeRealTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(2.0, boost::numeric::bindings::trans(mTransformation.opbM(real(sM))),
			                                     vTransformation.opsV(real(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
			boost::numeric::bindings::blas::gbmv(-2.0, boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))),
			                                     vTransformation.opsV(imag(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::NoTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType> resS(res.upperTriangle, slice(index - 1, 0, V.size()), slice(index, 1, V.size()));
			axpy_prod(vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M.upperTriangle, index, M.upperTriangle.size1(), index, M.upperTriangle.size2())),
			          resS,
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::ConjugateTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType> resS(res.upperTriangle, slice(index - 1, 0, V.size()), slice(index, 1, V.size()));
			axpy_prod(conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M.upperTriangle, index, M.upperTriangle.size1(), index, M.upperTriangle.size2()))),
			          resS,
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= conj(element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::MakeRealTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= 2.0 * element_prod(real(subrange(vTransformation.opsV(V), 1, V.size())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));

			axpy_prod(-2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= 2.0 * element_prod(imag(subrange(vTransformation.opsV(V), 1, V.size())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::NoTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Vector<T5>::Implementation tmp = vTransformation.opsV(V);
			boost::numeric::bindings::blas::trmv(boost::numeric::bindings::trans(mTransformation.opbM(sM)), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= subrange(tmp, 0, tmp.size() - 1)
				 + element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			res(index - 1, res.size2() - 1) += tmp(tmp.size() - 1);
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::ConjugateTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Vector<T5>::Implementation tmp = conj(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmv(boost::numeric::bindings::herm(mTransformation.opbM(sM)), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= subrange(tmp, 0, tmp.size() - 1)
				 + conj(element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			res(index - 1, res.size2() - 1) += tmp(tmp.size() - 1);
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::MakeRealTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Vector<T5>::Implementation tmp = real(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmv(boost::numeric::bindings::trans(real(mTransformation.opbM(sM))), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= 2.0 * (subrange(tmp, 0, tmp.size() - 1)
				 + element_prod(real(subrange(vTransformation.opsV(V), 1, V.size())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			res(index - 1, res.size2() - 1) += 2.0 * tmp(tmp.size() - 1);

			noalias(tmp) = imag(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmv(boost::numeric::bindings::trans(imag(mTransformation.opbM(sM))), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= 2.0 * (subrange(tmp, 0, tmp.size() - 1)
				 + element_prod(imag(subrange(vTransformation.opsV(V), 1, V.size())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			res(index - 1, res.size2() - 1) -= 2.0 * tmp(tmp.size() - 1);
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::NoTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation> resS(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size()));
			axpy_prod(vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())),
			          resS,
			          false);
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::ConjugateTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation> resS(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size()));
			axpy_prod(conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resS,
			          false);
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::MakeRealTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation> resS(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size()));
			axpy_prod(2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resS,
			          false);
			axpy_prod(-2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resS,
			          false);
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::NoTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gemv(1, boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(V),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::ConjugateTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gemv(1, boost::numeric::bindings::herm(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(conj(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}

		// computeO4pa(M, tM, V, tV, res, mr): res += mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::MakeRealTransformation>::pa(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gemv(2.0, boost::numeric::bindings::trans(mTransformation.opbM(real(sM))),
			                                     vTransformation.opsV(real(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
			boost::numeric::bindings::blas::gemv(-2.0, boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))),
			                                     vTransformation.opsV(imag(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}


		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO4ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res, const T6& resTransformation,
								const std::size_t& index) {
			ComputeO4Factory<Thessenberg, Tbackend, T6>::template ma<T1, T2, T3, T4, T5>(M, mTransformation, V, vTransformation, res, index);
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::NoTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::ConjugateTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::MakeRealTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(-2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
			axpy_prod(2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::NoTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(-1, boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(V),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::ConjugateTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(-1, boost::numeric::bindings::herm(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(conj(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::MakeRealTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(-2.0, boost::numeric::bindings::trans(mTransformation.opbM(real(sM))),
			                                     vTransformation.opsV(real(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
			boost::numeric::bindings::blas::gbmv(2.0, boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))),
			                                     vTransformation.opsV(imag(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::NoTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2())),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::ConjugateTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= conj(element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::MakeRealTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(-2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= 2.0 * element_prod(real(subrange(vTransformation.opsV(V), 1, V.size())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));

			axpy_prod(2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= 2.0 * element_prod(imag(subrange(vTransformation.opsV(V), 1, V.size())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::NoTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Vector<T5>::Implementation tmp = vTransformation.opsV(V);
			boost::numeric::bindings::blas::trmv(boost::numeric::bindings::trans(mTransformation.opbM(sM)), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= subrange(tmp, 0, tmp.size() - 1)
				 + element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			res(index - 1, res.size2() - 1) -= tmp(tmp.size() - 1);
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::ConjugateTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Vector<T5>::Implementation tmp = conj(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmv(boost::numeric::bindings::herm(mTransformation.opbM(sM)), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= subrange(tmp, 0, tmp.size() - 1)
				 + conj(element_prod(subrange(vTransformation.opsV(V), 1, V.size()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			res(index - 1, res.size2() - 1) -= tmp(tmp.size() - 1);
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::MakeRealTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Vector<T5>::Implementation tmp = real(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmv(boost::numeric::bindings::trans(real(mTransformation.opbM(sM))), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= 2.0 * (subrange(tmp, 0, tmp.size() - 1)
				 + element_prod(real(subrange(vTransformation.opsV(V), 1, V.size())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			res(index - 1, res.size2() - 1) -= 2.0 * tmp(tmp.size() - 1);

			noalias(tmp) = imag(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmv(boost::numeric::bindings::trans(imag(mTransformation.opbM(sM))), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= 2.0 * (subrange(tmp, 0, tmp.size() - 1)
				 + element_prod(imag(subrange(vTransformation.opsV(V), 1, V.size())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			res(index - 1, res.size2() - 1) += 2.0 * tmp(tmp.size() - 1);
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::NoTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::ConjugateTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::MakeRealTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(-2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
			axpy_prod(2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())),
			          false);
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::NoTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gemv(-1, boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(V),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i, starting from column i+1
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::ConjugateTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gemv(-1, boost::numeric::bindings::herm(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(conj(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}

		// computeO4ma(M, tM, V, tV, res, mr): res -= mr(tv(trans(V)) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the subvector of res at row i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::MakeRealTransformation>::ma(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gemv(-2.0, boost::numeric::bindings::trans(mTransformation.opbM(real(sM))),
			                                     vTransformation.opsV(real(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
			boost::numeric::bindings::blas::gemv(2.0, boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))),
			                                     vTransformation.opsV(imag(V)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size()), slice(index, 1, V.size())));
		}


		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO4pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res, const T6& resTransformation,
								const std::size_t& index) {
			ComputeO4Factory<Thessenberg, Tbackend, T6>::template pb<T1, T2, T3, T4, T5>(M, mTransformation, V, vTransformation, res, index);
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::NoTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_range<typename HessenbergMatrix<T5>::Implementation> resR = subrange(res, index - 2, index, index, res.size2());
			axpy_prod(vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())),
			          resR,
			          false);
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::ConjugateTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_range<typename HessenbergMatrix<T5>::Implementation> resR = subrange(res, index - 2, index, index, res.size2());
			axpy_prod(conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resR,
			          false);
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::MakeRealTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_range<typename HessenbergMatrix<T5>::Implementation> resR = subrange(res, index - 2, index, index, res.size2());
			axpy_prod(2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resR,
			          false);
			axpy_prod(-2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resR,
			          false);
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::NoTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(1, boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(row(V, 0)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2()), slice(index, 1, V.size2())));
			boost::numeric::bindings::blas::gbmv(1, boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(row(V, 1)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2()), slice(index, 1, V.size2())));
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::ConjugateTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(1, boost::numeric::bindings::herm(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(conj(row(V, 0))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2()), slice(index, 1, V.size2())));
			boost::numeric::bindings::blas::gbmv(1, boost::numeric::bindings::herm(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(conj(row(V, 1))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2()), slice(index, 1, V.size2())));
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::MakeRealTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(2.0, boost::numeric::bindings::trans(mTransformation.opbM(real(sM))),
			                                     vTransformation.opsV(real(row(V, 0))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2()), slice(index, 1, V.size2())));
			boost::numeric::bindings::blas::gbmv(-2.0, boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))),
			                                     vTransformation.opsV(imag(row(V, 0))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2()), slice(index, 1, V.size2())));
			boost::numeric::bindings::blas::gbmv(2.0, boost::numeric::bindings::trans(mTransformation.opbM(real(sM))),
			                                     vTransformation.opsV(real(row(V, 1))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2()), slice(index, 1, V.size2())));
			boost::numeric::bindings::blas::gbmv(-2.0, boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))),
			                                     vTransformation.opsV(imag(row(V, 1))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2()), slice(index, 1, V.size2())));
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::NoTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_range<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType> resR = subrange(res.upperTriangle, index - 2, index, index, res.upperTriangle.size2());
			axpy_prod(vTransformation.opsM(V),
			          mTransformation.opsM(subrange(M.upperTriangle, index, M.upperTriangle.size1(), index, M.upperTriangle.size2())),
			          resR,
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= element_prod(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= element_prod(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::ConjugateTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_range<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType> resR = subrange(res.upperTriangle, index - 2, index, index, res.upperTriangle.size2());
			axpy_prod(conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M.upperTriangle, index, M.upperTriangle.size1(), index, M.upperTriangle.size2()))),
			          resR,
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= conj(element_prod(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= conj(element_prod(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::MakeRealTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= 2.0 * element_prod(real(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation::UpperTriangleType>(res.upperTriangle, slice(index - 1, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= 2.0 * element_prod(real(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));

			axpy_prod(-2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= 2.0 * element_prod(imag(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= 2.0 * element_prod(imag(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::NoTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp = trans(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmm(boost::numeric::bindings::trans(mTransformation.opbM(sM)), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= subrange(column(tmp, 1), 0, tmp.size1() - 1)
				 + element_prod(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= subrange(column(tmp, 0), 0, tmp.size1() - 1)
				 + element_prod(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			res(index - 2, res.size2() - 1) += tmp(tmp.size1() - 1, 1);
			res(index - 1, res.size2() - 1) += tmp(tmp.size1() - 1, 0);
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::ConjugateTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp = herm(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmm(boost::numeric::bindings::herm(mTransformation.opbM(sM)), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= subrange(column(tmp, 1), 0, tmp.size1() - 1)
				 + conj(element_prod(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= subrange(column(tmp, 0), 0, tmp.size1() - 1)
				 + conj(element_prod(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			res(index - 2, res.size2() - 1) += tmp(tmp.size1() - 1, 1);
			res(index - 1, res.size2() - 1) += tmp(tmp.size1() - 1, 0);
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::MakeRealTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp = trans(vTransformation.opsV(real(V)));
			boost::numeric::bindings::blas::trmm(boost::numeric::bindings::trans(mTransformation.opbM(real(sM))), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= 2.0 * (subrange(column(tmp, 1), 0, tmp.size1() - 1)
				 + element_prod(real(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= 2.0 * (subrange(column(tmp, 0), 0, tmp.size1() - 1)
				 + element_prod(real(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			res(index - 2, res.size2() - 1) += 2.0 * tmp(tmp.size1() - 1, 1);
			res(index - 1, res.size2() - 1) += 2.0 * tmp(tmp.size1() - 1, 0);

			noalias(tmp) = trans(vTransformation.opsV(imag(V)));
			boost::numeric::bindings::blas::trmm(boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= 2.0 * (subrange(column(tmp, 1), 0, tmp.size1() - 1)
				 + element_prod(imag(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= 2.0 * (subrange(column(tmp, 0), 0, tmp.size1() - 1)
				 + element_prod(imag(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			res(index - 2, res.size2() - 1) -= 2.0 * tmp(tmp.size1() - 1, 1);
			res(index - 1, res.size2() - 1) -= 2.0 * tmp(tmp.size1() - 1, 0);
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::NoTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_range<typename HessenbergMatrix<T5>::Implementation> resR = subrange(res, index - 2, index, index, res.size2());
			axpy_prod(vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())),
			          resR,
			          false);
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::ConjugateTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_range<typename HessenbergMatrix<T5>::Implementation> resR = subrange(res, index - 2, index, index, res.size2());
			axpy_prod(conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resR,
			          false);
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::MakeRealTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			matrix_range<typename HessenbergMatrix<T5>::Implementation> resR = subrange(res, index - 2, index, index, res.size2());
			axpy_prod(2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resR,
			          false);
			axpy_prod(-2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          resR,
			          false);
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::NoTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp(2, res.size2() - index);
			boost::numeric::bindings::blas::gemm(1, vTransformation.opbM(V),
			                                     mTransformation.opbM(sM),
			                                     0, tmp);
			noalias(subrange(res, index - 2, index, index, res.size2())) += tmp;
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::ConjugateTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp(2, res.size2() - index);
			boost::numeric::bindings::blas::gemm(1, boost::numeric::bindings::conj(vTransformation.opbM(V)),
			                                     boost::numeric::bindings::conj(mTransformation.opbM(sM)),
			                                     0, tmp);
			noalias(subrange(res, index - 2, index, index, res.size2())) += tmp;
		}

		// computeO4pb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::MakeRealTransformation>::pb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp(2, res.size2() - index);
			boost::numeric::bindings::blas::gemm(2.0, vTransformation.opbM(real(V)),
			                                     mTransformation.opbM(real(sM)),
			                                     0, tmp);
			noalias(subrange(res, index - 2, index, index, res.size2())) += tmp;

			boost::numeric::bindings::blas::gemm(-2.0, vTransformation.opbM(imag(V)),
			                                     mTransformation.opbM(imag(sM)),
			                                     0, tmp);
			noalias(subrange(res, index - 2, index, index, res.size2())) += tmp;
		}


		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO4mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res, const T6& resTransformation,
								const std::size_t& index) {
			ComputeO4Factory<Thessenberg, Tbackend, T6>::template mb<T1, T2, T3, T4, T5>(M, mTransformation, V, vTransformation, res, index);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::NoTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::ConjugateTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::MakeRealTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(-2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
			axpy_prod(2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::NoTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(-1, boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(row(V, 0)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2()), slice(index, 1, V.size2())));
			boost::numeric::bindings::blas::gbmv(-1, boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(row(V, 1)),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2()), slice(index, 1, V.size2())));
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::ConjugateTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(-1, boost::numeric::bindings::herm(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(conj(row(V, 0))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2()), slice(index, 1, V.size2())));
			boost::numeric::bindings::blas::gbmv(-1, boost::numeric::bindings::herm(mTransformation.opbM(sM)),
			                                     vTransformation.opsV(conj(row(V, 1))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2()), slice(index, 1, V.size2())));
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::MakeRealTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			boost::numeric::bindings::blas::gbmv(-2.0, boost::numeric::bindings::trans(mTransformation.opbM(real(sM))),
			                                     vTransformation.opsV(real(row(V, 0))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2()), slice(index, 1, V.size2())));
			boost::numeric::bindings::blas::gbmv(2.0, boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))),
			                                     vTransformation.opsV(imag(row(V, 0))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2()), slice(index, 1, V.size2())));
			boost::numeric::bindings::blas::gbmv(-2.0, boost::numeric::bindings::trans(mTransformation.opbM(real(sM))),
			                                     vTransformation.opsV(real(row(V, 1))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2()), slice(index, 1, V.size2())));
			boost::numeric::bindings::blas::gbmv(2.0, boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))),
			                                     vTransformation.opsV(imag(row(V, 1))),
			                                     1, matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2()), slice(index, 1, V.size2())));
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::NoTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2())),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= element_prod(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= element_prod(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::ConjugateTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= conj(element_prod(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= conj(element_prod(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::MakeRealTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(-2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= 2.0 * element_prod(real(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= 2.0 * element_prod(real(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));

			axpy_prod(2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M.upperTriangle, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= 2.0 * element_prod(imag(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= 2.0 * element_prod(imag(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::NoTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp = trans(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmm(boost::numeric::bindings::trans(mTransformation.opbM(sM)), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= subrange(column(tmp, 1), 0, tmp.size1() - 1)
				 + element_prod(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= subrange(column(tmp, 0), 0, tmp.size1() - 1)
				 + element_prod(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())));
			res(index - 2, res.size2() - 1) -= tmp(tmp.size1() - 1, 1);
			res(index - 1, res.size2() - 1) -= tmp(tmp.size1() - 1, 0);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res += mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::ConjugateTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp = herm(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmm(boost::numeric::bindings::herm(mTransformation.opbM(sM)), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= subrange(column(tmp, 1), 0, tmp.size1() - 1)
				 + conj(element_prod(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= subrange(column(tmp, 0), 0, tmp.size1() - 1)
				 + conj(element_prod(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2()), mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size()))));
			res(index - 2, res.size2() - 1) -= tmp(tmp.size1() - 1, 1);
			res(index - 1, res.size2() - 1) -= tmp(tmp.size1() - 1, 0);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::MakeRealTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp = trans(vTransformation.opsV(real(V)));
			boost::numeric::bindings::blas::trmm(boost::numeric::bindings::trans(mTransformation.opbM(real(sM))), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				-= 2.0 * (subrange(column(tmp, 1), 0, tmp.size1() - 1)
				 + element_prod(real(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				-= 2.0 * (subrange(column(tmp, 0), 0, tmp.size1() - 1)
				 + element_prod(real(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2())), real(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			res(index - 2, res.size2() - 1) -= 2.0 * tmp(tmp.size1() - 1, 1);
			res(index - 1, res.size2() - 1) -= 2.0 * tmp(tmp.size1() - 1, 0);

			noalias(tmp) = trans(vTransformation.opsV(imag(V)));
			boost::numeric::bindings::blas::trmm(boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))), tmp);
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 2, 0, V.size2() - 1), slice(index, 1, V.size2() - 1)))
				+= 2.0 * (subrange(column(tmp, 1), 0, tmp.size1() - 1)
				 + element_prod(imag(subrange(vTransformation.opsV(row(V, 0)), 1, V.size2())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			noalias(matrix_vector_slice<typename HessenbergMatrix<T5>::Implementation>(res, slice(index - 1, 0, V.size() - 1), slice(index, 1, V.size() - 1)))
				+= 2.0 * (subrange(column(tmp, 0), 0, tmp.size1() - 1)
				 + element_prod(imag(subrange(vTransformation.opsV(row(V, 1)), 1, V.size2())), imag(mTransformation.opsV(subrange(M.diagonalVector, index, M.diagonalVector.size())))));
			res(index - 2, res.size2() - 1) += 2.0 * tmp(tmp.size1() - 1, 1);
			res(index - 1, res.size2() - 1) += 2.0 * tmp(tmp.size1() - 1, 0);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::NoTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- vTransformation.opsV(V),
			          mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2())),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::ConjugateTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(- conj(vTransformation.opsV(V)),
			          conj(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::MakeRealTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			axpy_prod(-2.0 * real(vTransformation.opsV(V)),
			          real(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
			axpy_prod(2.0 * imag(vTransformation.opsV(V)),
			          imag(mTransformation.opsM(subrange(M, index, M.size1(), index, M.size2()))),
			          subrange(res, range(index - 2, index), range(index, res.size2())),
			          false);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::NoTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp(res.size2() - index, 2);
			boost::numeric::bindings::blas::gemm(1, boost::numeric::bindings::trans(mTransformation.opbM(sM)),
			                                     trans(vTransformation.opsV(V)),
			                                     0, tmp);
			noalias(subrange(res, range(index - 2, index), range(index, res.size2()))) -= trans(tmp);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::ConjugateTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp(res.size2() - index, 2);
			boost::numeric::bindings::blas::gemm(1, boost::numeric::bindings::herm(mTransformation.opbM(sM)),
			                                     herm(vTransformation.opsV(V)),
			                                     0, tmp);
			noalias(subrange(res, range(index - 2, index), range(index, res.size2()))) -= trans(tmp);
		}

		// computeO4mb(M, tM, V, tV, res, mr): res -= mr(tv(V) * tM(M))
		// Operates on the square submatrix of M starting at row i and column i
		// Operates on the submatrix of res at rows i-2 and i-1, starting from column i
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::MakeRealTransformation>::mb(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Matrix<T3>::Implementation& V, const T4& vTransformation,
								typename HessenbergMatrix<T5>::Implementation& res,
								const std::size_t& index) {
			typename HessenbergMatrix<T1>::Implementation sM(M.size1() - index, M.size2() - index, 1, std::min(M.size1(), M.size2()) - index - 1);
			noalias(sM) = subrange(M, index, M.size1(), index, M.size2());
			typename Matrix<T5>::Implementation tmp(res.size2() - index, 2);
			boost::numeric::bindings::blas::gemm(2.0, boost::numeric::bindings::trans(mTransformation.opbM(real(sM))),
			                                     trans(vTransformation.opsV(real(V))),
			                                     0, tmp);
			noalias(subrange(res, range(index - 2, index), range(index, res.size2()))) -= trans(tmp);

			boost::numeric::bindings::blas::gemm(-2.0, boost::numeric::bindings::trans(mTransformation.opbM(imag(sM))),
			                                     trans(vTransformation.opsV(imag(V))),
			                                     0, tmp);
			noalias(subrange(res, range(index - 2, index), range(index, res.size2()))) -= trans(tmp);
		}


		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO4pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res, const T6& resTransformation) {
			ComputeO4Factory<Thessenberg, Tbackend, T6>::template pc<T1, T2, T3, T4, T5>(M, mTransformation, V, vTransformation, res);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::NoTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M),
			          vTransformation.opsV(V),
			          res,
			          false);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::ConjugateTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(conj(mTransformation.opsM(M)),
			          conj(vTransformation.opsV(V)),
			          res,
			          false);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::MakeRealTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(real(mTransformation.opsM(M)),
			          2.0 * real(vTransformation.opsV(V)),
			          res,
			          false);
			axpy_prod(imag(mTransformation.opsM(M)),
			          -2.0 * imag(vTransformation.opsV(V)),
			          res,
			          false);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::NoTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gbmv(1, mTransformation.opbM(M),
			                                     vTransformation.opsV(V),
			                                     1, res);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::ConjugateTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gbmv(1, boost::numeric::bindings::conj(mTransformation.opbM(M)),
			                                     vTransformation.opsV(conj(V)),
			                                     1, res);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::MakeRealTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gbmv(2.0, mTransformation.opbM(real(M)),
			                                     vTransformation.opsV(real(V)),
			                                     1, res);
			boost::numeric::bindings::blas::gbmv(-2.0, mTransformation.opbM(imag(M)),
			                                     vTransformation.opsV(imag(V)),
			                                     1, res);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::NoTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M.upperTriangle),
			          vTransformation.opsV(V),
			          res,
			          false);
			noalias(subrange(res, 1, res.size()))
				+= element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1));
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::ConjugateTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(conj(mTransformation.opsM(M.upperTriangle)),
			          conj(vTransformation.opsV(V)),
			          res,
			          false);
			noalias(subrange(res, 1, res.size()))
				+= conj(element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1)));
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::MakeRealTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(real(M.upperTriangle)),
			          2.0 * vTransformation.opsV(real(V)),
			          res,
			          false);
			noalias(subrange(res, 1, res.size()))
				+= 2.0 * element_prod(real(mTransformation.opsV(M.diagonalVector)), real(subrange(vTransformation.opsV(V), 0, V.size() - 1)));

			axpy_prod(mTransformation.opsM(imag(M.upperTriangle)),
			          -2.0 * vTransformation.opsV(imag(V)),
			          res,
			          false);
			noalias(subrange(res, 1, res.size()))
				-= 2.0 * element_prod(imag(mTransformation.opsV(M.diagonalVector)), imag(subrange(vTransformation.opsV(V), 0, V.size() - 1)));
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::NoTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			typename Vector<T5>::Implementation tmp = vTransformation.opsV(V);
			boost::numeric::bindings::blas::trmv(mTransformation.opbM(M), tmp);
			noalias(subrange(res, 1, res.size()))
				+= subrange(tmp, 1, tmp.size())
				 + element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1));
			res(0) += tmp(0);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::ConjugateTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			typename Vector<T5>::Implementation tmp = conj(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmv(boost::numeric::bindings::conj(mTransformation.opbM(M)), tmp);
			noalias(subrange(res, 1, res.size()))
				+= subrange(tmp, 1, tmp.size())
				 + conj(element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1)));
			res(0) += tmp(0);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::MakeRealTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			typename Vector<T5>::Implementation tmp = vTransformation.opsV(real(V));
			boost::numeric::bindings::blas::trmv(mTransformation.opbM(real(M)), tmp);
			noalias(subrange(res, 1, res.size()))
				+= 2.0 * (subrange(tmp, 1, tmp.size())
				 + element_prod(real(mTransformation.opsV(M.diagonalVector)), real(subrange(vTransformation.opsV(V), 0, V.size() - 1))));
			res(0) += 2.0 * tmp(0);

			noalias(tmp) = vTransformation.opsV(imag(V));
			boost::numeric::bindings::blas::trmv(mTransformation.opbM(imag(M)), tmp);
			noalias(subrange(res, 1, res.size()))
				-= 2.0 * (subrange(tmp, 1, tmp.size())
				 + element_prod(imag(mTransformation.opsV(M.diagonalVector)), imag(subrange(vTransformation.opsV(V), 0, V.size() - 1))));
			res(0) -= 2.0 * tmp(0);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::NoTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M),
			          vTransformation.opsV(V),
			          res,
			          false);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::ConjugateTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(conj(mTransformation.opsM(M)),
			          conj(vTransformation.opsV(V)),
			          res,
			          false);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::MakeRealTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(real(mTransformation.opsM(M)),
			          2.0 * real(vTransformation.opsV(V)),
			          res,
			          false);
			axpy_prod(imag(mTransformation.opsM(M)),
			          -2.0 * imag(vTransformation.opsV(V)),
			          res,
			          false);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::NoTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gemv(1, mTransformation.opbM(M),
			                                     vTransformation.opsV(V),
			                                     1, res);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::ConjugateTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gemv(1, boost::numeric::bindings::conj(mTransformation.opbM(M)),
			                                     vTransformation.opsV(conj(V)),
			                                     1, res);
		}

		// computeO4pc(M, tM, V, tV, res, mr): res += mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::MakeRealTransformation>::pc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gemv(2.0, mTransformation.opbM(real(M)),
			                                     vTransformation.opsV(real(V)),
			                                     1, res);
			boost::numeric::bindings::blas::gemv(-2.0, mTransformation.opbM(imag(M)),
			                                     vTransformation.opsV(imag(V)),
			                                     1, res);
		}


		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO4mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res, const T6& resTransformation) {
			ComputeO4Factory<Thessenberg, Tbackend, T6>::template mc<T1, T2, T3, T4, T5>(M, mTransformation, V, vTransformation, res);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::NoTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M),
			          - vTransformation.opsV(V),
			          res,
			          false);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::ConjugateTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(conj(mTransformation.opsM(M)),
			          - conj(vTransformation.opsV(V)),
			          res,
			          false);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendStandard, UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::MakeRealTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(real(mTransformation.opsM(M)),
			          -2.0 * real(vTransformation.opsV(V)),
			          res,
			          false);
			axpy_prod(imag(mTransformation.opsM(M)),
			          2.0 * imag(vTransformation.opsV(V)),
			          res,
			          false);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::NoTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gbmv(-1, mTransformation.opbM(M),
			                                     vTransformation.opsV(V),
			                                     1, res);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::ConjugateTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gbmv(-1, boost::numeric::bindings::conj(mTransformation.opbM(M)),
			                                     vTransformation.opsV(conj(V)),
			                                     1, res);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasBandedHessenberg, UblasBackendBLAS, UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::MakeRealTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gbmv(-2.0, mTransformation.opbM(real(M)),
			                                     vTransformation.opsV(real(V)),
			                                     1, res);
			boost::numeric::bindings::blas::gbmv(2.0, mTransformation.opbM(imag(M)),
			                                     vTransformation.opsV(imag(V)),
			                                     1, res);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::NoTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M.upperTriangle),
			          - vTransformation.opsV(V),
			          res,
			          false);
			noalias(subrange(res, 1, res.size()))
				-= element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1));
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::ConjugateTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(conj(mTransformation.opsM(M.upperTriangle)),
			          - conj(vTransformation.opsV(V)),
			          res,
			          false);
			noalias(subrange(res, 1, res.size()))
				-= conj(element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1)));
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendStandard, UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::MakeRealTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(real(M.upperTriangle)),
			          -2.0 * vTransformation.opsV(real(V)),
			          res,
			          false);
			noalias(subrange(res, 1, res.size()))
				-= 2.0 * element_prod(real(mTransformation.opsV(M.diagonalVector)), real(subrange(vTransformation.opsV(V), 0, V.size() - 1)));

			axpy_prod(mTransformation.opsM(imag(M.upperTriangle)),
			          2.0 * vTransformation.opsV(imag(V)),
			          res,
			          false);
			noalias(subrange(res, 1, res.size()))
				+= 2.0 * element_prod(imag(mTransformation.opsV(M.diagonalVector)), imag(subrange(vTransformation.opsV(V), 0, V.size() - 1)));
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::NoTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			typename Vector<T5>::Implementation tmp = vTransformation.opsV(V);
			boost::numeric::bindings::blas::trmv(mTransformation.opbM(M), tmp);
			noalias(subrange(res, 1, res.size()))
				-= subrange(tmp, 1, tmp.size())
				 + element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1));
			res(0) -= tmp(0);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::ConjugateTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			typename Vector<T5>::Implementation tmp = conj(vTransformation.opsV(V));
			boost::numeric::bindings::blas::trmv(boost::numeric::bindings::conj(mTransformation.opbM(M)), tmp);
			noalias(subrange(res, 1, res.size()))
				-= subrange(tmp, 1, tmp.size())
				 + conj(element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1)));
			res(0) -= tmp(0);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasTriangularHessenberg, UblasBackendBLAS, UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::MakeRealTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			typename Vector<T5>::Implementation tmp = vTransformation.opsV(real(V));
			boost::numeric::bindings::blas::trmv(mTransformation.opbM(real(M)), tmp);
			noalias(subrange(res, 1, res.size()))
				-= 2.0 * (subrange(tmp, 1, tmp.size())
				 + element_prod(real(mTransformation.opsV(M.diagonalVector)), real(subrange(vTransformation.opsV(V), 0, V.size() - 1))));
			res(0) -= 2.0 * tmp(0);

			noalias(tmp) = vTransformation.opsV(imag(V));
			boost::numeric::bindings::blas::trmv(mTransformation.opbM(imag(M)), tmp);
			noalias(subrange(res, 1, res.size()))
				+= 2.0 * (subrange(tmp, 1, tmp.size())
				 + element_prod(imag(mTransformation.opsV(M.diagonalVector)), imag(subrange(vTransformation.opsV(V), 0, V.size() - 1))));
			res(0) += 2.0 * tmp(0);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::NoTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M),
			          - vTransformation.opsV(V),
			          res,
			          false);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::ConjugateTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(conj(mTransformation.opsM(M)),
			          - conj(vTransformation.opsV(V)),
			          res,
			          false);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendStandard, UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::MakeRealTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(real(mTransformation.opsM(M)),
			          -2.0 * real(vTransformation.opsV(V)),
			          res,
			          false);
			axpy_prod(imag(mTransformation.opsM(M)),
			          2.0 * imag(vTransformation.opsV(V)),
			          res,
			          false);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::NoTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gemv(-1, mTransformation.opbM(M),
			                                     vTransformation.opsV(V),
			                                     1, res);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::ConjugateTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gemv(-1, boost::numeric::bindings::conj(mTransformation.opbM(M)),
			                                     vTransformation.opsV(conj(V)),
			                                     1, res);
		}

		// computeO4mc(M, tM, V, tV, res, mr): res -= mr(tM(M) * tv(V))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void ComputeO4Factory<UblasDenseHessenberg, UblasBackendBLAS, UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::MakeRealTransformation>::mc(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gemv(-2.0, mTransformation.opbM(real(M)),
			                                     vTransformation.opsV(real(V)),
			                                     1, res);
			boost::numeric::bindings::blas::gemv(2.0, mTransformation.opbM(imag(M)),
			                                     vTransformation.opsV(imag(V)),
			                                     1, res);
		}


		// Function computeO5

		// computeO5a(a, M, tm, res): res = a * tm(M)
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3, typename T4>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO5a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								typename HessenbergMatrix<T4>::Implementation& res) {
			noalias(res) = mTransformation.opsM(M);
			res *= a;
		}

		// computeO5a(a, M, tm, res): res = a * tm(M)
		template <> template <typename T1, typename T2, typename T3, typename T4>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO5a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								typename HessenbergMatrix<T4>::Implementation& res) {
			noalias(res.upperTriangle) = mTransformation.opsM(M.upperTriangle);
			res.upperTriangle *= a;
			noalias(res.diagonalVector) = mTransformation.opsV(M.diagonalVector);
			res.diagonalVector *= a;
		}

		// computeO5a(a, M, tm, res): res = a * tm(M)
		template <> template <typename T1, typename T2, typename T3, typename T4>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO5a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M, const T3& mTransformation,
								typename HessenbergMatrix<T4>::Implementation& res) {
			noalias(res.upperTriangle) = mTransformation.opsM(M.upperTriangle);
			res.upperTriangle *= a;
			noalias(res.diagonalVector) = mTransformation.opsV(M.diagonalVector);
			res.diagonalVector *= a;
		}

		// computeO5b(a, V, tv, res): res = a * tv(V)
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3, typename T4>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO5b(
								const T1& a,
								const typename Vector<T2>::Implementation& V, const T3& vTransformation,
								typename Vector<T4>::Implementation& res) {
			noalias(res) = vTransformation.opsV(V);
			res *= a;
		}


		// Function computeO6

		// computeO6a(a, M1, tm1, M2, tm2, res): res = a * (tm1(M1) - tm2(M2))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::computeO6a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M1, const T3& m1Transformation,
								const typename HessenbergMatrix<T4>::Implementation& M2, const T5& m2Transformation,
								typename HessenbergMatrix<T6>::Implementation& res) {
			noalias(res) = a * (m1Transformation.opsM(M1) - m2Transformation.opsM(M2));
		}

		// computeO6a(a, M1, tm1, M2, tm2, res): res = a * (tm1(M1) - tm2(M2))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::computeO6a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M1, const T3& m1Transformation,
								const typename HessenbergMatrix<T4>::Implementation& M2, const T5& m2Transformation,
								typename HessenbergMatrix<T6>::Implementation& res) {
			noalias(res) = a * (m1Transformation.opsM(M1) - m2Transformation.opsM(M2));
		}

		// computeO6a(a, M1, tm1, M2, tm2, res): res = a * (tm1(M1) - tm2(M2))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::computeO6a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M1, const T3& m1Transformation,
								const typename HessenbergMatrix<T4>::Implementation& M2, const T5& m2Transformation,
								typename HessenbergMatrix<T6>::Implementation& res) {
			noalias(res) = m1Transformation.opsM(M1);
			noalias(res) -= m2Transformation.opsM(M2);
			res *= a;
		}

		// computeO6a(a, M1, tm1, M2, tm2, res): res = a * (tm1(M1) - tm2(M2))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::computeO6a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M1, const T3& m1Transformation,
								const typename HessenbergMatrix<T4>::Implementation& M2, const T5& m2Transformation,
								typename HessenbergMatrix<T6>::Implementation& res) {
			noalias(res) = m1Transformation.opsM(M1);
			noalias(res) -= m2Transformation.opsM(M2);
			res *= a;
		}

		// computeO6a(a, M1, tm1, M2, tm2, res): res = a * (tm1(M1) - tm2(M2))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO6a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M1, const T3& m1Transformation,
								const typename HessenbergMatrix<T4>::Implementation& M2, const T5& m2Transformation,
								typename HessenbergMatrix<T6>::Implementation& res) {
			noalias(res.upperTriangle) = m1Transformation.opsM(M1.upperTriangle);
			noalias(res.upperTriangle) -= m2Transformation.opsM(M2.upperTriangle);
			res.upperTriangle *= a;
			noalias(res.diagonalVector) = a * (m1Transformation.opsV(M1.diagonalVector) - m2Transformation.opsV(M2.diagonalVector));
		}

		// computeO6a(a, M1, tm1, M2, tm2, res): res = a * (tm1(M1) - tm2(M2))
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO6a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M1, const T3& m1Transformation,
								const typename HessenbergMatrix<T4>::Implementation& M2, const T5& m2Transformation,
								typename HessenbergMatrix<T6>::Implementation& res) {
			noalias(res.upperTriangle) = a * (m1Transformation.opsM(M1.upperTriangle) - m2Transformation.opsM(M2.upperTriangle));
			noalias(res.diagonalVector) = a * (m1Transformation.opsV(M1.diagonalVector) - m2Transformation.opsV(M2.diagonalVector));
		}

		// computeO6b(a, V1, tv1, V2, tv2, res): res = a * (tv1(V1) - tv2(V2))
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO6b(
								const T1& a,
								const typename Vector<T2>::Implementation& V1, const T3& v1Transformation,
								const typename Vector<T4>::Implementation& V2, const T5& v2Transformation,
								typename Vector<T6>::Implementation& res) {
			noalias(res) = a * (v1Transformation.opsV(V1) - v2Transformation.opsV(V2));
		}


		// Function computeO7

		// computeO7(M, tm, V, tv, res): res = tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendStandard>::computeO7(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M), vTransformation.opsV(V), res, true);
		}

		// computeO7(M, tm, V, tv, res): res = tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::computeO7(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gbmv(1, mTransformation.opbM(M),
			                                     vTransformation.opsV(V),
			                                     0, res);
		}

		// computeO7(M, tm, V, tv, res): res = tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO7(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M.upperTriangle), vTransformation.opsV(V), res, true);
			noalias(subrange(res, 1, res.size()))
				+= element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1));
		}

		// computeO7(M, tm, V, tv, res): res = tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO7(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			typename Vector<T5>::Implementation tmp = vTransformation.opsV(V);
			boost::numeric::bindings::blas::trmv(mTransformation.opbM(M.upperTriangle), tmp);
			noalias(subrange(res, 1, res.size()))
				= subrange(tmp, 1, tmp.size())
				 + element_prod(mTransformation.opsV(M.diagonalVector), subrange(vTransformation.opsV(V), 0, V.size() - 1));
			res(0) = tmp(0);
		}

		// computeO7(M, tm, V, tv, res): res = tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendStandard>::computeO7(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			axpy_prod(mTransformation.opsM(M), vTransformation.opsV(V), res, true);
		}

		// computeO7(M, tm, V, tv, res): res = tm(M) * tv(V)
		template <> template <typename T1, typename T2, typename T3, typename T4, typename T5>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::computeO7(
								const typename HessenbergMatrix<T1>::Implementation& M, const T2& mTransformation,
								const typename Vector<T3>::Implementation& V, const T4& vTransformation,
								typename Vector<T5>::Implementation& res) {
			boost::numeric::bindings::blas::gemv(1, mTransformation.opbM(M),
			                                     vTransformation.opsV(V),
			                                     0, res);
		}


		// Function computeO8

		// computeO8a(a, res): res *= a
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO8a(const T1& a, typename HessenbergMatrix<T2>::Implementation& res) {
			res *= a;
		}

		// computeO8a(a, res): res *= a
		template <> template <typename T1, typename T2>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO8a(const T1& a, typename HessenbergMatrix<T2>::Implementation& res) {
			res.upperTriangle *= a;
			res.diagonalVector *= a;
		}

		// computeO8a(a, res): res *= a
		template <> template <typename T1, typename T2>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO8a(const T1& a, typename HessenbergMatrix<T2>::Implementation& res) {
			res.upperTriangle *= a;
			res.diagonalVector *= a;
		}

		// computeO8b(a, res): res *= a
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO8b(const T1& a, typename Vector<T2>::Implementation& res) {
			res *= a;
		}


		// Function computeO9

		// computeO9a(a, M, res): res = a * (res - M)
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO9a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M,
								typename HessenbergMatrix<T3>::Implementation& res) {
			res = a * (res - M);
		}

		// computeO9a(a, M, res): res = a * (res - M)
		template <> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendStandard>::computeO9a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M,
								typename HessenbergMatrix<T3>::Implementation& res) {
			res.upperTriangle = a * (res.upperTriangle - M.upperTriangle);
			res.diagonalVector = a * (res.diagonalVector - M.diagonalVector);
		}

		// computeO9a(a, M, res): res = a * (res - M)
		template <> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO9a(
								const T1& a,
								const typename HessenbergMatrix<T2>::Implementation& M,
								typename HessenbergMatrix<T3>::Implementation& res) {
			res.upperTriangle = a * (res.upperTriangle - M.upperTriangle);
			res.diagonalVector = a * (res.diagonalVector - M.diagonalVector);
		}

		// computeO9b(a, V, res): res = a * (res - V)
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2, typename T3>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO9b(
								const T1& a,
								const typename Vector<T2>::Implementation& V,
								typename Vector<T3>::Implementation& res) {
			res = a * (res - V);
		}


		// Function computeO10
		
		// computeO10(M, V): V = trans(M) * V
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO10(const typename Matrix<T1>::Implementation& M, typename Vector<T2>::Implementation& V) {
			V = prod(V, M);
		}
		
		// computeO10(M, V): V = trans(M) * V
		template <> template <typename T1, typename T2>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::computeO10(const typename Matrix<T1>::Implementation& M, typename Vector<T2>::Implementation& V) {
			typename Vector<T2>::Implementation tmp = V;
			boost::numeric::bindings::blas::gemv(1, boost::numeric::bindings::trans(M),
			                                     tmp,
			                                     0, V);
		};

		// computeO10(M, V): V = trans(M) * V
		template <> template <typename T1, typename T2>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO10(const typename Matrix<T1>::Implementation& M, typename Vector<T2>::Implementation& V) {
			typename Vector<T2>::Implementation tmp = V;
			boost::numeric::bindings::blas::gemv(1, boost::numeric::bindings::trans(M),
			                                     tmp,
			                                     0, V);
		};

		// computeO10(M, V): V = trans(M) * V
		template <> template <typename T1, typename T2>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::computeO10(const typename Matrix<T1>::Implementation& M, typename Vector<T2>::Implementation& V) {
			typename Vector<T2>::Implementation tmp = V;
			boost::numeric::bindings::blas::gemv(1, boost::numeric::bindings::trans(M),
			                                     tmp,
			                                     0, V);
		};


		// Function computeO11
		
		// computeO11(M, V): V = M * V
		template <typename Thessenberg, typename Tbackend> template <typename T1, typename T2>
		inline void UblasBackend<Thessenberg, Tbackend>::computeO11(const typename Matrix<T1>::Implementation& M, typename Vector<T2>::Implementation& V) {
			V = prod(M, V);
		}
		
		// computeO11(M, V): V = M * V
		template <> template <typename T1, typename T2>
		inline void UblasBackend<UblasBandedHessenberg, UblasBackendBLAS>::computeO11(const typename Matrix<T1>::Implementation& M, typename Vector<T2>::Implementation& V) {
			typename Vector<T2>::Implementation tmp = V;
			boost::numeric::bindings::blas::gemv(1, M,
			                                     tmp,
			                                     0, V);
		};

		// computeO11(M, V): V = M * V
		template <> template <typename T1, typename T2>
		inline void UblasBackend<UblasTriangularHessenberg, UblasBackendBLAS>::computeO11(const typename Matrix<T1>::Implementation& M, typename Vector<T2>::Implementation& V) {
			typename Vector<T2>::Implementation tmp = V;
			boost::numeric::bindings::blas::gemv(1, M,
			                                     tmp,
			                                     0, V);
		};

		// computeO11(M, V): V = M * V
		template <> template <typename T1, typename T2>
		inline void UblasBackend<UblasDenseHessenberg, UblasBackendBLAS>::computeO11(const typename Matrix<T1>::Implementation& M, typename Vector<T2>::Implementation& V) {
			typename Vector<T2>::Implementation tmp = V;
			boost::numeric::bindings::blas::gemv(1, M,
			                                     tmp,
			                                     0, V);
		};
	} // namespace algebra
} // namespace epoch
