Commits

Martin Felis committed ad53006

replaced cml completely by both Eigen and SimpleMath

Comments (0)

Files changed (105)

+/**
+ * This is a highly inefficient math library. It was conceived by Martin
+ * Felis <martin.felis@iwr.uni-heidelberg.de> while he was compiling code
+ * that uses a highly efficient math library.
+ *
+ * It is intended to be used as a fast compiling substitute for the
+ * blazingly fast Eigen3 library and tries to mimic its API to a certain
+ * extend.
+ *
+ * Feel free to use it wherever you like. However, no guarantees are given
+ * that this code does what it says it would.
+ */
+
 #ifndef SIMPLEMATHFIXED_H
 #define SIMPLEMATHFIXED_H
 
 
 		static matrix_type Zero() {
 			matrix_type result;
-			result.zero();
+			result.setZero();
 			return result;
 		}
 
 		static matrix_type Zero(int ignore_me) {
 			matrix_type result;
-			result.zero();
+			result.setZero();
 			return result;
 		}
 
 		void identity() {
 			COMPILE_ASSERT (nrows == ncols);
 
-			zero();
+			setZero();
 			for (unsigned int i = 0; i < ncols; i++)
 				mData[i * ncols + i] = 1.;
 		}
 
 			Matrix<val_type, nrows, other_cols> result;
 			
-			result.zero();
+			result.setZero();
 
 			unsigned int i,j, k;
 			for (i = 0; i < nrows; i++) {
 }
 
 #endif /* SIMPLEMATHFIXED_H */
+/**
+ * This is a highly inefficient math library. It was conceived by Martin
+ * Felis <martin.felis@iwr.uni-heidelberg.de> while he was compiling code
+ * that uses a highly efficient math library.
+ *
+ * It is intended to be used as a fast compiling substitute for the
+ * blazingly fast Eigen3 library and tries to mimic its API to a certain
+ * extend.
+ *
+ * Feel free to use it wherever you like. However, no guarantees are given
+ * that this code does what it says it would.
+ */
+
+#ifndef SIMPLEMATHDYNAMIC_H
+#define SIMPLEMATHDYNAMIC_H
+
+#include <sstream>
+#include <cstdlib>
+#include <assert.h>
+
+#include "compileassert.h"
+
+/** \brief Namespace for a highly inefficient math library
+ *
+ */
+namespace SimpleMath {
+
+/** \brief Namespace for elements of varying size.
+ */
+namespace Dynamic {
+
+// forward declaration
+template <typename val_type>
+class Matrix;
+
+/** \brief Block class that can be used to access blocks of a matrix.
+ *
+ * This class is a proxy class and only contains data on where to find the
+ * desired information.
+ *
+ */
+template <typename val_type, unsigned int block_rows, unsigned int block_cols>
+class Block {
+	public:
+	Block () :
+		parent_nrows(0),
+		parent_ncols(0),
+		parent_row_index(0),
+		parent_col_index(0),
+		transposed(false),
+		parent(NULL)
+	{ }
+	Block (const Block& other) :
+		parent_nrows(other.parent_nrows),
+		parent_ncols(other.parent_ncols),
+		parent_row_index(other.parent_row_index),
+		parent_col_index(other.parent_col_index),
+		transposed(other.transposed),
+		parent(other.parent)
+	{ }
+
+	Block (
+			val_type *parent_data,
+			unsigned int parent_row_start,
+			unsigned int parent_col_start,
+			unsigned int parent_num_rows,
+			unsigned int parent_num_cols)
+	{
+		parent = parent_data;
+		parent_row_index = parent_row_start;
+		parent_col_index = parent_col_start;
+
+		parent_nrows = parent_num_rows;
+		parent_ncols = parent_num_cols;
+
+		transposed = false;
+	}
+
+	/** This operater is only used to copy the data from other into this
+	 *
+	 */
+	Block& operator=(const Block& other) {
+		if (this != &other) {
+			// copy the data, but we have to ensure, that the sizes match!
+
+			unsigned int i, j;
+			for (i = 0; i < block_rows; i++) {
+				for (j = 0; j < block_cols; j++) {
+					this->operator()(i,j) = other(i,j);
+				}
+			}
+		}
+
+		// copy data depending on other.transposed!
+
+		return *this;
+	}
+
+	/** This operater is only used to copy the data from other into this
+	 */
+	Block& operator=(const Matrix<val_type>& data_in) {
+		assert (parent != NULL);
+		// copy the data, but we have to ensure, that the sizes match!
+		assert (block_rows == data_in.rows());
+		assert (block_cols == data_in.cols());
+
+		if (!transposed) {
+			for (unsigned int i = 0; i < block_rows; i++) {
+				for (unsigned int j = 0; j < block_cols; j++) {
+					parent[parent_nrows * (i + parent_row_index) + j + parent_col_index] = data_in(i,j);
+				}
+			}
+		} else {
+			for (unsigned int i = 0; i < block_rows; i++) {
+				for (unsigned int j = 0; j < block_cols; j++) {
+					parent[parent_nrows * (j + parent_row_index) + i + parent_col_index] = data_in(i,j);
+				}
+			}
+		}
+
+		return *this;
+	}
+
+	Block transpose() {
+		assert (parent != NULL);
+		Block result (*this);
+		result.transposed = transposed ^ true;
+		return result;
+	}
+
+	const val_type& operator() (const unsigned int i, const unsigned int j) const {
+		assert (parent != NULL);
+		assert (i < block_rows);
+		assert (j < block_cols);
+
+		if (!transposed)
+			return parent[parent_nrows * (i + parent_row_index) + j + parent_col_index];
+	
+		return parent[parent_nrows * (j + parent_row_index) + i + parent_col_index];
+	}
+
+	val_type& operator() (const unsigned int i, const unsigned int j) {
+		assert (parent != NULL);
+		assert (i < block_rows);
+		assert (j < block_cols);
+
+		if (!transposed)
+			return parent[parent_nrows * (i + parent_row_index) + j + parent_col_index];
+	
+		return parent[parent_nrows * (j + parent_row_index) + i + parent_col_index];
+	}
+
+	// casting operators
+	operator Matrix<val_type>() {
+		if (!transposed) {
+			Matrix<val_type> result (block_rows, block_cols);
+
+			for (unsigned int i = 0; i < block_rows; i++) 
+				for (unsigned int j = 0; j < block_cols; j++)
+					result(i,j) = parent[parent_nrows * (i + parent_row_index) + j + parent_col_index];
+
+			return result;
+		} 
+
+		Matrix<val_type> result (block_cols, block_rows);
+
+		for (unsigned int i = 0; i < block_rows; i++) 
+			for (unsigned int j = 0; j < block_cols; j++)
+				result(j,i) = parent[parent_nrows * (i + parent_row_index) + j + parent_col_index];
+
+		return result;
+	}
+
+	unsigned int parent_nrows;
+	unsigned int parent_ncols;
+	unsigned int parent_row_index;
+	unsigned int parent_col_index;
+	bool transposed;
+
+	val_type *parent;
+};
+
+/** \brief Class for both matrices and vectors.
+ */
+template <typename val_type>
+class Matrix {
+	public:
+		Matrix() :
+			nrows (0),
+			ncols (0),
+			mData (NULL) {};
+		Matrix(unsigned int rows) :
+			nrows (rows),
+			ncols (1) {
+				mData = new val_type[rows];
+			}
+		Matrix(unsigned int rows, unsigned int cols) :
+			nrows (rows),
+			ncols (cols) {
+				mData = new val_type[rows * cols];
+			}
+		unsigned int rows() const {
+			return nrows;
+		}
+
+		unsigned int cols() const {
+			return ncols;
+		}
+
+		unsigned int size() const {
+			return nrows * ncols;
+		}
+		void resize (unsigned int rows, unsigned int cols=1) {
+			if (nrows * ncols > 0 && mData != NULL) {
+				delete[] mData;
+			}
+
+			nrows = rows;
+			ncols = cols;
+
+			mData = new val_type[nrows * ncols];
+		}
+
+		typedef Matrix<val_type> matrix_type;
+
+		Matrix(const Matrix &matrix) :
+			nrows (matrix.nrows),
+			ncols (matrix.ncols) {
+			unsigned int i;
+		
+			mData = new val_type[nrows * ncols];
+
+			for (i = 0; i < nrows * ncols; i++)
+				mData[i] = matrix.mData[i];
+		}
+		Matrix& operator=(const Matrix &matrix) {
+			if (this != &matrix) {
+				delete[] mData;
+
+				nrows = matrix.nrows;
+				ncols = matrix.ncols;
+
+				mData = new val_type[nrows * ncols];
+
+				unsigned int i;
+				for (i = 0; i < nrows * ncols; i++)
+					mData[i] = matrix.mData[i];
+			}
+			return *this;
+		}
+
+		~Matrix() {
+			if (nrows * ncols > 0 && mData != NULL)
+				delete[] mData;
+
+			nrows = 0;
+			ncols = 0;
+			mData = NULL;
+		};
+
+		// comparison
+		bool operator==(const Matrix &matrix) const {
+			if (nrows != matrix.nrows || ncols != matrix.ncols)
+				return false;
+
+			for (unsigned int i = 0; i < nrows * ncols; i++) {
+				if (mData[i] != matrix.mData[i])
+					return false;
+			}
+			return true;
+		}
+		bool operator!=(const Matrix &matrix) const {
+			if (nrows != matrix.nrows || ncols != matrix.ncols)
+				return true;
+
+			for (unsigned int i = 0; i < nrows * ncols; i++) {
+				if (mData[i] != matrix.mData[i])
+					return true;
+			}
+			return false;
+		}
+
+		// access operators
+		const double& operator[](const unsigned int &index) const {
+			assert (index	>= 0 && index < nrows * ncols);
+			return mData[index];
+		};
+		double& operator[](const unsigned int &index) {
+			assert (index	>= 0 && index < nrows * ncols);
+			return mData[index];
+		}
+
+		const double& operator()(const unsigned int &row, const unsigned int &col) const {
+			assert (row	>= 0 && row < nrows && col >= 0 && col < ncols);
+			return mData[row*ncols + col];
+		};
+		double& operator()(const unsigned int &row, const unsigned int &col) {
+			assert (row	>= 0 && row < nrows && col >= 0 && col < ncols);
+			return mData[row*ncols + col];
+		};
+		
+		void zero() {
+			for (unsigned int i = 0; i < ncols * nrows; i++)
+				mData[i] = 0.;
+		}
+		void setZero() {
+			zero();
+		}
+
+		val_type norm() {
+			return sqrt(this->squaredNorm());
+		}
+
+		void normalize() {
+			val_type length = this->norm();
+
+			for (unsigned int i = 0; i < ncols * nrows; i++)
+				mData[i] /= length;
+		}
+
+		Matrix<val_type> cross(const Matrix<val_type> &other_vector) {
+			assert (nrows * ncols == 3);
+			assert (other_vector.nrows * other_vector.ncols == 3);
+
+			Matrix<val_type> result (3, 1);
+			result[0] = mData[1] * other_vector[2] - mData[2] * other_vector[1];
+			result[1] = mData[2] * other_vector[0] - mData[0] * other_vector[2];
+			result[2] = mData[0] * other_vector[1] - mData[1] * other_vector[0];
+
+			return result;
+		}
+
+		static matrix_type Zero() {
+			matrix_type result;
+			result.setZero();
+			return result;
+		}
+
+		static matrix_type Zero(int rows, int cols = 1) {
+			matrix_type result (rows, cols);
+			result.setZero();
+			return result;
+		}
+
+		static matrix_type Constant (int rows, val_type value) {
+			matrix_type result (rows, 1);
+			unsigned int i;
+			for (i = 0; i < result.size(); i++)
+				result[i] = value;
+			
+			return result;
+		}
+
+		static matrix_type Constant (int rows, int cols, val_type value) {
+			matrix_type result (rows, cols);
+			unsigned int i;
+			for (i = 0; i < result.size(); i++)
+				result[i] = value;
+			
+			return result;
+		}
+
+		void identity() {
+			assert (nrows == ncols);
+
+			setZero();
+			for (unsigned int i = 0; i < ncols; i++)
+				mData[i * ncols + i] = 1.;
+		}
+
+		void random() {
+			for (unsigned int i = 0; i < nrows * ncols; i++) 
+				mData[i] = static_cast<val_type> (rand()) / static_cast<val_type> (RAND_MAX);
+		}
+
+		val_type squaredNorm() const {
+			assert (ncols == 1 || nrows == 1);
+			val_type result = 0;
+
+			for (unsigned int i = 0; i < nrows * ncols; i++)
+				result += mData[i] * mData[i];
+
+			return result;
+		}
+
+		val_type dot(const matrix_type &matrix) const {
+			assert (ncols == 1 || nrows == 1);
+			val_type result = 0;
+
+			for (unsigned int i = 0; i < nrows * ncols; i++)
+				result += mData[i] * matrix[i];
+
+			return result;
+		}
+
+
+		// Block accessing functions
+		template <unsigned int blockrows, unsigned int blockcols>
+		Block<val_type, blockrows, blockcols> block (unsigned int i, unsigned int j) const {
+			assert (nrows > blockrows);
+			assert (ncols > blockcols);
+			return Block<val_type, blockrows, blockcols> (const_cast<double*> (this->mData), i, j, nrows, ncols);
+		}
+
+		// Operators with scalars
+		void operator*=(const val_type &scalar) {
+			for (unsigned int i = 0; i < nrows * ncols; i++)
+				mData[i] *= scalar;
+		};
+		void operator/=(const val_type &scalar) {
+			for (unsigned int i = 0; i < nrows * ncols; i++)
+				mData[i] /= scalar;
+		}
+		Matrix operator/(const val_type& scalar) const {
+			matrix_type result (*this);
+
+			for (unsigned int i = 0; i < nrows * ncols; i++)
+				result[i] /= scalar;
+
+			return result;
+		}
+
+		// Operators with other spatial matrices
+		Matrix operator+(const Matrix &matrix) const {
+			matrix_type result (*this);
+
+			for (unsigned int i = 0; i < nrows * ncols; i++)
+				result[i] += matrix[i];
+
+			return result;
+		}
+		void operator+=(const matrix_type &matrix) {
+			for (unsigned int i = 0; i < nrows * ncols; i++)
+				mData[i] += matrix.mData[i];
+		}
+		Matrix operator-(const Matrix &matrix) const {
+			matrix_type result (*this);
+
+			for (unsigned int i = 0; i < nrows * ncols; i++)
+				result[i] -= matrix[i];
+
+			return result;
+		}
+		void operator-=(const Matrix &matrix) {
+			for (unsigned int i = 0; i < nrows * ncols; i++)
+				mData[i] -= matrix.mData[i];
+		}
+
+		Matrix<val_type> operator*(const Matrix<val_type> &other_matrix) const {
+			assert (ncols == other_matrix.nrows);
+
+			Matrix<val_type> result(nrows, other_matrix.ncols);
+			
+			result.setZero();
+
+			unsigned int i,j, k;
+			for (i = 0; i < nrows; i++) {
+				for (j = 0; j < other_matrix.cols(); j++) {
+					for (k = 0; k < other_matrix.rows(); k++) {
+						result(i,j) += mData[i * ncols + k] * other_matrix(k,j);
+					}
+				}
+			}
+			
+			return result;
+		}
+
+		void operator*=(const Matrix &matrix) {
+			matrix_type temp (*this);
+			*this = temp * matrix;
+		}
+
+		// Special operators
+		val_type *data(){
+			return mData;
+		}
+
+		// regular transpose of a 6 dimensional matrix
+		Matrix<val_type> transpose() const {
+			Matrix<val_type> result(ncols, nrows);
+	
+			for (unsigned int i = 0; i < nrows; i++) {
+				for (unsigned int j = 0; j < ncols; j++) {
+					result(j,i) = mData[i * ncols + j];
+				}
+			}
+
+			return result;
+		}
+
+		operator val_type() {
+			assert (nrows == 1);
+			assert (nrows == 1);
+
+			return mData[0];
+		}
+
+	private:
+		unsigned int nrows;
+		unsigned int ncols;
+
+		val_type* mData;
+};
+
+template <unsigned int blockrows, unsigned int blockcols>
+inline std::ostream& operator<<(std::ostream& output, const Block<double, blockrows, blockcols> &block) {
+	output << std::endl;
+
+	unsigned int i,j;
+	for (i = 0; i < blockrows; i++) {
+		output << "[ ";
+		for (j = 0; j < blockcols; j++) {
+			output << block(i,j) << " ";
+		}
+		output << "]" << std::endl;
+	}
+
+	return output;
+}
+
+template <typename val_type>
+inline Matrix<val_type> operator*(val_type scalar, const Matrix<val_type> &matrix) {
+	Matrix<val_type> result (matrix);
+
+	for (unsigned int i = 0; i < matrix.rows() * matrix.cols(); i++)
+		result.data()[i] *= scalar;
+
+	return result;
+}
+
+template <typename val_type>
+inline Matrix<val_type> operator*(const Matrix<val_type> &matrix, val_type scalar) {
+	Matrix<val_type> result (matrix);
+
+	for (unsigned int i = 0; i < matrix.rows() * matrix.cols(); i++)
+		result.data()[i] *= scalar;
+
+	return result;
+}
+
+template <typename val_type>
+inline std::ostream& operator<<(std::ostream& output, const Matrix<val_type> &matrix) {
+	output << std::endl;
+	for (unsigned int i = 0; i < matrix.rows(); i++) {
+		output << "[ ";
+		for (unsigned int j = 0; j < matrix.cols(); j++) {
+			output << matrix(i,j) << " ";
+		}
+		output << "]" << std::endl;
+	}
+	return output;
+}
+
+}
+
+}
+
+#endif /* SIMPLEMATHDYNAMIC_H */
+/**
+ * This is a highly inefficient math library. It was conceived by Martin
+ * Felis <martin.felis@iwr.uni-heidelberg.de> while he was compiling code
+ * that uses a highly efficient math library.
+ *
+ * It is intended to be used as a fast compiling substitute for the
+ * blazingly fast Eigen3 library and tries to mimic its API to a certain
+ * extend.
+ *
+ * Feel free to use it wherever you like. However, no guarantees are given
+ * that this code does what it says it would.
+ */
+
+#ifndef SIMPLEMATHMIXED_H
+#define SIMPLEMATHMIXED_H
+
+#include <sstream>
+#include <cstdlib>
+#include <assert.h>
+
+#include "compileassert.h"
+
+/** \brief Namespace for a highly inefficient math library
+ *
+ */
+namespace SimpleMath {
+
+// multiplication
+template <typename val_type, unsigned int nrows, unsigned int ncols>
+inline Dynamic::Matrix<val_type> operator*(
+		const Fixed::Matrix<val_type, nrows, ncols> &matrix_a,
+		const Dynamic::Matrix<val_type> &matrix_b) {
+	assert (matrix_a.cols() == matrix_b.rows());
+
+	Dynamic::Matrix<val_type> result (nrows, matrix_b.cols());
+
+	result.setZero();
+
+	unsigned int i,j, k;
+	for (i = 0; i < nrows; i++) {
+		for (j = 0; j < matrix_b.cols(); j++) {
+			for (k = 0; k < matrix_b.rows(); k++) {
+				result(i,j) += matrix_a(i,k) * matrix_b(k,j);
+			}
+		}
+	}
+
+	return result;
+}
+
+template <typename val_type, unsigned int nrows, unsigned int ncols>
+inline Dynamic::Matrix<val_type> operator*(
+		const Dynamic::Matrix<val_type> &matrix_a,
+		const Fixed::Matrix<val_type, nrows, ncols> &matrix_b) {
+	assert (matrix_a.cols() == matrix_b.rows());
+	
+	Dynamic::Matrix<val_type> result (matrix_a.rows(), ncols);
+
+	result.setZero();
+
+	unsigned int i,j, k;
+	for (i = 0; i < matrix_a.rows(); i++) {
+		for (j = 0; j < matrix_b.cols(); j++) {
+			for (k = 0; k < matrix_b.rows(); k++) {
+				result(i,j) += matrix_a(i,k) * matrix_b(k,j);
+			}
+		}
+	}
+
+	return result;
+}
+
+// equality
+template <typename val_type, unsigned int nrows, unsigned int ncols>
+inline bool operator==(
+		const Fixed::Matrix<val_type, nrows, ncols> &matrix_a,
+		const Dynamic::Matrix<val_type> &matrix_b) {
+	assert (nrows == matrix_a.rows());
+	assert (ncols == matrix_a.cols());
+
+	unsigned int i;
+	for (i = 0; i < matrix_a.size(); i++) {
+		if (matrix_a[i] != matrix_b[i])
+			return false;
+	}
+
+	return true;
+}
+
+template <typename val_type, unsigned int nrows, unsigned int ncols>
+inline bool operator==(
+		const Dynamic::Matrix<val_type> &matrix_b,
+		const Fixed::Matrix<val_type, nrows, ncols> &matrix_a) {
+	assert (nrows == matrix_a.rows());
+	assert (ncols == matrix_a.cols());
+
+	unsigned int i;
+	for (i = 0; i < matrix_a.size(); i++) {
+		if (matrix_a[i] != matrix_b[i])
+			return false;
+	}
+
+	return true;
+}
+
+}
+
+#endif /* SIMPLEMATHMIXED_H */

src/cml/cml.h

-/* -*- C++ -*- ------------------------------------------------------------
- 
-Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
-
-The Configurable Math Library (CML) is distributed under the terms of the
-Boost Software License, v1.0 (see cml/LICENSE for details).
-
- *-----------------------------------------------------------------------*/
-/** @file
- *  @brief Main CML header to include all CML functionality.
- *
- * @todo load vectors, matrices, and quaternions from a stream.
- *
- * @todo Move common vector and matrix class ops to a base class (requires
- * SCOOP-like programming, see below).
- *
- * @todo Implement matrix<>::orthogonalize().
- *
- * @todo Add is_square<>, is_rectangular<>, etc. to make it easier to
- * detect specific matrix types.
- *
- * @todo Implement dedicated square matrix classes to get rid of duplicated
- * code in the specialized matrix classes.
- *
- * @todo Implement automatic temporary generation, along with expression
- * node return types for mat-vec and mat-mat operators.
- *
- * @todo switch to ssize_t instead of size_t to avoid having to explicitly
- * deal with wrap-arounds to 2^32-1 when a size_t is subtracted from.
- *
- * @todo Finish tests for mat-vec multiply.
- *
- * @todo Differentiate between references used for function arguments, and
- * those used for variable types.  In particular, GCC 3.4 requires const T &
- * function arguments to ensure complete unrolling/inlining of expressions.
- *
- * @todo Specialize matrix multiplication based upon the size type (fixed or
- * dynamic). This makes a difference for at least GCC 3.4.
- *
- * @todo need a build system for the tests/ and examples/ directories.
- *
- * @todo clean up the testing infrastructure, and make it easier to add new
- * tests
- *
- * @todo figure out if scalars should be passed by value or reference, or
- * if it should be determined by traits
- *
- * @todo change use of typename and class to be like Alexandrescu book
- *
- * @todo figure out if it makes sense to unroll assignment if either the
- * source expression or the target vector/matrix has a fixed size (right
- * now, unrolling happens only if the target has a fixed size)
- *
- * @todo Allow addition of new types, a la glommable ETs (but simpler).
- * Can use ideas from "SCOOP" method: Nicolas Burrus, Alexandre Duret-Lutz,
- * Thierry G�raud, David Lesage and Rapha�l Poss. A Static C++
- * Object-Oriented Programming (SCOOP) Paradigm Mixing Benefits of
- * Traditional OOP and Generic Programming. In the Proceedings of the
- * Workshop on Multiple Paradigm with OO Languages (MPOOL'03) Anaheim, CA,
- * USA Oct. 2003
- */
-
-#ifndef cml_h
-#define cml_h
-
-#ifdef CML_CHECK_INDICES_RANGE
-#include <assert.h>
-#endif
-
-#include <cml/vector.h>
-#include <cml/matrix.h>
-#include <cml/quaternion.h>
-#include <cml/util.h>
-#include <cml/mathlib/mathlib.h>
-
-#endif
-
-// -------------------------------------------------------------------------
-// vim:ft=cpp

src/cml/cml_config.h

-/* An example config file. */
-/* A config file is generally the way to define configuration macros.  This
- * should be done automatically, though, not by the user:
- */
-//#define CML_NO_DEFAULT_EXPR_TRAITS
-#define CML_VECTOR_UNROLL_LIMIT 25
-#define CML_VECTOR_DOT_UNROLL_LIMIT 25
-#define CML_NO_2D_UNROLLER
-#define CML_DEFAULT_ARRAY_LAYOUT cml::row_major
-#define CML_ALWAYS_PROMOTE_TO_DEFAULT_LAYOUT
-#define CML_DEFAULT_ARRAY_ALLOC std::allocator<void>
-#define CML_AUTOMATIC_VECTOR_RESIZE_ON_ASSIGNMENT
-#define CML_CHECK_VECTOR_EXPR_SIZES
-#define CML_AUTOMATIC_MATRIX_RESIZE_ON_ASSIGNMENT
-#define CML_CHECK_MATRIX_EXPR_SIZES
-
-#define CML_CHECK_INDICES_RANGE

src/cml/constants.h

-/* -*- C++ -*- ------------------------------------------------------------
- 
-Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
-
-The Configurable Math Library (CML) is distributed under the terms of the
-Boost Software License, v1.0 (see cml/LICENSE for details).
-
- *-----------------------------------------------------------------------*/
-/** @file
- *  @brief Useful constants.
- */
-
-#ifndef cml_constants_h
-#define cml_constants_h
-
-#include <cmath>
-
-#if !defined(M_PI)
-#define M_PI 3.14159265358979323846264338327950288
-#endif
-
-#if !defined(M_SQRT2)
-#define M_SQRT2 1.41421356237309504880168872420969808
-#endif
-
-#if !defined(M_E)
-#define M_E 2.71828182845904523536028747135266250
-#endif
-
-namespace cml {
-
-#if 1
-
-/** Templated constants struct.
- *
- * Either float or double can be used.
- */
-template<typename Float>
-struct constants {
-    static Float pi()          { return Float(M_PI); }
-    static Float two_pi()      { return Float(2.*M_PI); }
-    static Float inv_pi()      { return Float(1./M_PI); }
-    static Float inv_two_pi()  { return Float(1./(2.*M_PI)); }
-    static Float pi_over_2()   { return Float(M_PI/2.); }
-    static Float pi_over_4()   { return Float(M_PI/4.); }
-    static Float deg_per_rad() { return Float(180./M_PI); }
-    static Float rad_per_deg() { return Float(M_PI/180.); }
-
-    static Float sqrt_2() { return Float(M_SQRT2); }
-    static Float sqrt_3() { return Float(1.732050807568877293527446341505); }
-    static Float sqrt_5() { return Float(2.236067977499789696409173668731); }
-    static Float sqrt_6() { return Float(2.449489742783178098197284074705); }
-
-    static Float e() { return Float(M_E); }
-};
-
-#else
-
-/* XXX This version requires an explicit instantiation of *every* constant
- * below, e.g.:
- *
- * template<typename F> const F cml::constants<F>::pi;
- */
-/** Templated constants struct.
- *
- * Either float or double can be used.
- */
-template<typename Float>
-struct constants {
-    static const Float pi = M_PI;
-    static const Float two_pi = 2.*M_PI;
-    static const Float inv_pi = 1./M_PI;                /* 1/pi */
-    static const Float inv_two_pi = 1./(2.*M_PI);       /* 1/(2*pi) */
-    static const Float pi_over_2 = M_PI/2.;             /* pi/2 */
-    static const Float pi_over_4 = M_PI/4.;             /* pi/4 */
-    static const Float deg_per_rad = 180./M_PI;
-    static const Float rad_per_deg = M_PI/180.;
-    static const Float sqrt_2 = M_SQRT2;
-    static const Float sqrt_3 = 1.73205080756887729352744634150587237;
-    static const Float sqrt_5 = 2.23606797749978969640917366873127624;
-    static const Float sqrt_6 = 2.44948974278317809819728407470589139;
-    static const Float e = M_E;
-};
-
-#endif
-
-} // namespace cml
-
-#endif

src/cml/core/cml_assert.h

-/* -*- C++ -*- ------------------------------------------------------------
- 
-Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
-
-The Configurable Math Library (CML) is distributed under the terms of the
-Boost Software License, v1.0 (see cml/LICENSE for details).
-
- *-----------------------------------------------------------------------*/
-/** @file
- *  @brief
- *
- * Macros and template metaprogramming to implement compile- and run-time
- * assertions.
- */
-
-#ifndef cml_assert_h
-#define cml_assert_h
-
-#include <cml/core/cml_meta.h>
-
-namespace cml {
-
-/* Join preprocessor macros into a new preprocessor macro: */
-#define CML_JOIN(X,Y) CML_DO_JOIN(X,Y)
-#define CML_DO_JOIN(X,Y) CML_DO_JOIN2(X,Y)
-#define CML_DO_JOIN2(X,Y) X##Y
-
-/* Change a macro value into a string: */
-#define TO_STRING(X) TO_STRING2(X)
-#define TO_STRING2(X) #X
-
-/** Default undefined compile-time assertion struct. */
-template<bool T> struct STATIC_ASSERTION_FAILURE;
-
-/** Struct instantiated when a true assertion is made at compile-time. */
-template<> struct STATIC_ASSERTION_FAILURE<true> {
-    typedef true_type result;
-    enum { value = true };
-};
-
-/** Create a compile-time assertion.
- *
- * @note Compile-time assertions must be expressions that can be evaluated at
- * comile time.  This means that the expression must only rely on constants,
- * enums, and/or template parameters, not variables having run-time storage
- * requirements.
- *
- * @warning Enclose expressions that have commas with parens, otherwise the
- * preprocessor will parse the commas as macro argument separators!
- *
- * @sa STATIC_ASSERTION_FAILURE
- */
-#define CML_STATIC_REQUIRE(_E_) \
-    typedef typename STATIC_ASSERTION_FAILURE<(_E_)>::result \
-        CML_JOIN(__cml_assert_test_typedef_, __LINE__)
-
-
-/** A more meaningful compile-time assertion struct.
- *
- * The parameter M is a struct type which has been declared but not
- * defined; e.g. struct this_is_an_error.
- *
- * When used with CML_STATIC_REQUIRE_M(<expr>,M), the compiler errors will
- * contain the struct name at the point of the error.
- */
-template<bool T, typename M> struct STATIC_ASSERTION_FAILURE_M {
-    typename M::bogus result;
-};
-
-/** Instantiated for true assertions. */
-template<typename M> struct STATIC_ASSERTION_FAILURE_M<true,M> {
-    typedef true_type result;
-    enum { value = true };
-};
-
-/** Create a compile-time assertion with a message.
- *
- * @note Compile-time assertions must be expressions that can be evaluated at
- * comile time.  This means that the expression must only rely on constants,
- * enums, and/or template parameters, not variables having run-time storage
- * requirements.
- *
- * @warning Enclose expressions that have commas with parens, otherwise the
- * preprocessor will parse the commas as macro argument separators!
- *
- * @sa STATIC_ASSERTION_FAILURE_M
- */
-#define CML_STATIC_REQUIRE_M(_E_, _M_) \
-    typedef typename STATIC_ASSERTION_FAILURE_M<(_E_),_M_> \
-        ::result CML_JOIN(__bogus_assert_type_, __LINE__)
-
-} // namespace cml
-
-#endif
-
-// -------------------------------------------------------------------------
-// vim:ft=cpp

src/cml/core/cml_meta.h

-/* -*- C++ -*- ------------------------------------------------------------
- 
-Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
-
-The Configurable Math Library (CML) is distributed under the terms of the
-Boost Software License, v1.0 (see cml/LICENSE for details).
-
- *-----------------------------------------------------------------------*/
-/** @file
- *  @brief A few simple metaprogramming tools.
- */
-
-#ifndef cml_meta_h
-#define cml_meta_h
-
-/* Include all of the template metaprogramming tools: */
-#include <cml/core/meta/common.h>
-#include <cml/core/meta/if.h>
-#include <cml/core/meta/switch.h>
-
-#endif
-
-// -------------------------------------------------------------------------
-// vim:ft=cpp

src/cml/core/common.h

-/* -*- C++ -*- ------------------------------------------------------------
- 
-Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
-
-The Configurable Math Library (CML) is distributed under the terms of the
-Boost Software License, v1.0 (see cml/LICENSE for details).
-
- *-----------------------------------------------------------------------*/
-/** @file
- *  @brief
- */
-
-#ifndef core_common_h
-#define core_common_h
-
-// XXX This isn't really the right place for this.
-#if defined(_MSC_VER)
-#include <cstdlib>
-#ifndef _SSIZE_T_DEFINED
-#ifdef  _WIN64
-typedef __int64    ssize_t;
-#else
-typedef _W64 int   ssize_t;
-#endif
-#define _SSIZE_T_DEFINED
-#endif
-#endif
-
-#include <cstddef>              // for size_t
-#include <utility>              // for std::pair<>
-#include <cml/defaults.h>
-
-namespace cml {
-
-/** 1D tag (to select array shape). */
-struct oned_tag {};
-
-/** 2D tag (to select array shape). */
-struct twod_tag {};
-
-/** Statically-allocated memory tag. */
-struct fixed_memory_tag {};
-
-/** Dynamically-allocated memory tag. */
-struct dynamic_memory_tag {};
-
-/** Externally-allocated memory tag. */
-struct external_memory_tag {};
-
-/** Statically-sized tag. */
-struct fixed_size_tag {};
-
-/** Runtime-sized tag. */
-struct dynamic_size_tag {};
-
-/** Resizable tag. */
-struct resizable_tag {};
-
-/** Not resizable tag. */
-struct not_resizable_tag {};
-
-/** Unit-sized tag. */
-struct unit_size_tag {};
-
-/** Row-major storage tag. */
-struct row_major {};
-
-/** Col-major storage tag. */
-struct col_major {};
-
-/** Row-vector matrix basis tag. */
-struct row_basis {};
-
-/** Column-vector matrix basis tag. */
-struct col_basis {};
-
-/* This is the pair returned from the matrix size() method, as well as from
- * the matrix expression size checking code:
- */
-typedef std::pair<size_t,size_t> matrix_size;
-
-} // namespace cml
-
-#endif
-
-// -------------------------------------------------------------------------
-// vim:ft=cpp

src/cml/core/dynamic_1D.h

-/* -*- C++ -*- ------------------------------------------------------------
- 
-Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
-
-The Configurable Math Library (CML) is distributed under the terms of the
-Boost Software License, v1.0 (see cml/LICENSE for details).
-
- *-----------------------------------------------------------------------*/
-/** @file
- *  @brief
- */
-
-#ifndef dynamic_1D_h
-#define dynamic_1D_h
-
-#include <memory>
-#include <cml/core/common.h>
-#include <cml/dynamic.h>
-
-namespace cml {
-
-/** Dynamically-sized and allocated 1D array.
- *
- * @note The allocator should be an STL-compatible allocator.
- *
- * @internal The internal array type <em>must</em> have the proper copy
- * semantics, otherwise copy construction will fail.
- */
-template<typename Element, class Alloc>
-class dynamic_1D
-{
-  public:
-
-    /* Record the allocator type: */
-    typedef typename Alloc::template rebind<Element>::other allocator_type;
-
-    /* Record the generator: */
-    typedef dynamic<Alloc> generator_type;
-
-    /* Standard: */
-    typedef typename allocator_type::value_type value_type;
-    typedef typename allocator_type::pointer pointer; 
-    typedef typename allocator_type::reference reference; 
-    typedef typename allocator_type::const_reference const_reference; 
-    typedef typename allocator_type::const_pointer const_pointer; 
-
-    /* For matching by memory type: */
-    typedef dynamic_memory_tag memory_tag;
-
-    /* For matching by size type: */
-    typedef dynamic_size_tag size_tag;
-
-    /* For matching by resizability: */
-    typedef resizable_tag resizing_tag;
-
-    /* For matching by dimensions: */
-    typedef oned_tag dimension_tag;
-
-
-  public:
-
-    /** Dynamic arrays have no fixed size. */
-    enum { array_size = -1 };
-
-
-  public:
-
-    /** Construct a dynamic array with no size. */
-    dynamic_1D() : m_size(0), m_data(0), m_alloc() {}
-
-    /** Construct a dynamic array given the size. */
-    explicit dynamic_1D(size_t size) : m_size(0), m_data(0), m_alloc() {
-      this->resize(size);
-    }
-
-    /** Copy construct a dynamic array. */
-    dynamic_1D(const dynamic_1D& other)
-      : m_size(0), m_data(0), m_alloc()
-    {
-      this->copy(other);
-    }
-
-    ~dynamic_1D() {
-      this->destroy();
-    }
-
-
-  public:
-
-    /** Return the number of elements in the array. */
-    size_t size() const { return m_size; }
-
-    /** Access to the data as a C array.
-     *
-     * @param i a size_t index into the array.
-     * @return a mutable reference to the array value at i.
-     *
-     * @note This function does not range-check the argument.
-     */
-    reference operator[](size_t i) { 
-			#ifdef CML_CHECK_INDICES_RANGE
-			assert (i >= 0 && i < m_size);
-			#endif
-			return m_data[i]; }
-
-    /** Const access to the data as a C array.
-     *
-     * @param i a size_t index into the array.
-     * @return a const reference to the array value at i.
-     *
-     * @note This function does not range-check the argument.
-     */
-    const_reference operator[](size_t i) const {
-			#ifdef CML_CHECK_INDICES_RANGE
-			assert (i >= 0 && i < m_size);
-			#endif
-			return m_data[i];
-		}
-
-    /** Return access to the data as a raw pointer. */
-    pointer data() { return &m_data[0]; }
-
-    /** Return access to the data as a raw pointer. */
-    const_pointer data() const { return &m_data[0]; }
-
-
-  public:
-
-    /** Set the array size to the given value.  The previous contents are
-     * destroyed before reallocating the array.  If s == size(),
-     * nothing happens.
-     *
-     * @warning This is not guaranteed to preserve the original data.
-     */
-    void resize(size_t s) {
-
-      /* Nothing to do if the size isn't changing: */
-      if(s == m_size) return;
-
-      /* Destroy the current array contents: */
-      this->destroy();
-
-      /* Set the new size if non-zero: */
-      if(s > 0) {
-	value_type* data = m_alloc.allocate(s);
-	for(size_t i = 0; i < s; ++ i)
-	  m_alloc.construct(&data[i], value_type());
-
-	/* Success, save s and data: */
-	m_size = s;
-	m_data = data;
-      }
-    }
-
-    /** Copy the source array. The previous contents are destroyed before
-     * reallocating the array.  If other == *this, nothing happens.
-     */
-    void copy(const dynamic_1D& other) {
-
-      /* Nothing to do if it's the same array: */
-      if(&other == this) return;
-
-      /* Destroy the current array contents: */
-      this->destroy();
-
-      /* Set the new size if non-zero: */
-      size_t s = other.size();
-      if(s > 0) {
-	value_type* data = m_alloc.allocate(s);
-	for(size_t i = 0; i < s; ++ i)
-	  m_alloc.construct(&data[i], other[i]);
-
-	/* Success, so save the new array and the size: */
-	m_size = s;
-	m_data = data;
-      }
-    }
-
-
-  protected:
-
-    /** Destroy the current contents of the array. */
-    void destroy() {
-      if(m_data) {
-	for(size_t i = 0; i < m_size; ++ i)
-	  m_alloc.destroy(&m_data[i]);
-	m_alloc.deallocate(m_data, m_size);
-	m_size = 0;
-	m_data = 0;
-      }
-    }
-
-
-  protected:
-
-    /** Current array size (may be 0). */
-    size_t			m_size;
-
-    /** Array data (may be NULL). */
-    value_type*			m_data;
-
-    /** Allocator for the array. */
-    allocator_type		m_alloc;
-};
-
-} // namespace cml
-
-#endif
-
-// -------------------------------------------------------------------------
-// vim:ft=cpp

src/cml/core/dynamic_2D.h

-/* -*- C++ -*- ------------------------------------------------------------
- 
-Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
-
-The Configurable Math Library (CML) is distributed under the terms of the
-Boost Software License, v1.0 (see cml/LICENSE for details).
-
- *-----------------------------------------------------------------------*/
-/** @file
- *  @brief
- */
-
-#ifndef dynamic_2D_h
-#define dynamic_2D_h
-
-#include <memory>
-#include <cml/core/common.h>
-#include <cml/core/dynamic_1D.h>
-#include <cml/dynamic.h>
-
-namespace cml {
-
-/** Dynamically-sized and allocated 2D array.
- *
- * @note The allocator should be an STL-compatible allocator.
- *
- * @internal The internal array type <em>must</em> have the proper copy
- * semantics, otherwise copy construction will fail.
- *
- * @internal This class does not need a destructor.
- */
-template<typename Element, typename Layout, class Alloc>
-class dynamic_2D
-{
-  public:
-
-    /* Record the allocator type: */
-    typedef typename Alloc::template rebind<Element>::other allocator_type;
-
-    /* Record the generator: */
-    typedef dynamic<Alloc> generator_type;
-
-    /* Standard: */
-    typedef typename allocator_type::value_type value_type;
-    typedef typename allocator_type::pointer pointer; 
-    typedef typename allocator_type::reference reference; 
-    typedef typename allocator_type::const_reference const_reference; 
-    typedef typename allocator_type::const_pointer const_pointer; 
-
-    /* For matching by memory layout: */
-    typedef Layout layout;
-
-    /* For matching by memory type: */
-    typedef dynamic_memory_tag memory_tag;
-
-    /* For matching by size type: */
-    typedef dynamic_size_tag size_tag;
-
-    /* For matching by resizability: */
-    typedef resizable_tag resizing_tag;
-
-    /* For matching by dimensions: */
-    typedef twod_tag dimension_tag;
-
-    /* To simplify the matrix transpose operator: */
-    typedef dynamic_2D<typename cml::remove_const<Element>::type,
-            Layout,Alloc> transposed_type;
-
-    /* To simplify the matrix row and column operators: */
-    typedef dynamic_1D<Element,Alloc> row_array_type;
-    typedef dynamic_1D<Element,Alloc> col_array_type;
-
-
-  protected:
-
-    /** Construct a dynamic array with no size. */
-    dynamic_2D() : m_rows(0), m_cols(0), m_data(0), m_alloc() {}
-
-    /** Construct a dynamic matrix given the dimensions. */
-    explicit dynamic_2D(size_t rows, size_t cols) 
-        : m_rows(0), m_cols(0), m_data(0), m_alloc()
-       	{
-	  this->resize(rows, cols);
-	}
-
-    /** Copy construct a dynamic matrix. */
-    dynamic_2D(const dynamic_2D& other)
-        : m_rows(0), m_cols(0), m_data(0), m_alloc()
-       	{
-	  this->copy(other);
-	}
-
-    ~dynamic_2D() {
-      this->destroy();
-    }
-
-
-  public:
-
-    enum { array_rows = -1, array_cols = -1 };
-
-
-  public:
-
-    /** Return the number of rows in the array. */
-    size_t rows() const { return m_rows; }
-
-    /** Return the number of cols in the array. */
-    size_t cols() const { return m_cols; }
-
-
-  public:
-
-    /** Access the given element of the matrix.
-     *
-     * @param row row of element.
-     * @param col column of element.
-     * @returns mutable reference.
-     */
-    reference operator()(size_t row, size_t col) {
-			#ifdef CML_CHECK_INDICES_RANGE
-			assert (row >= 0 && row < m_rows);
-			assert (col >= 0 && col < m_cols);
-			#endif
-      return this->get_element(row, col, layout());
-    }
-
-    /** Access the given element of the matrix.
-     *
-     * @param row row of element.
-     * @param col column of element.
-     * @returns const reference.
-     */
-		const_reference operator()(size_t row, size_t col) const {
-			#ifdef CML_CHECK_INDICES_RANGE
-			assert (row >= 0 && row < m_rows);
-			assert (col >= 0 && col < m_cols);
-			#endif
-			return this->get_element(row, col, layout());
-		}
-
-    /** Return access to the data as a raw pointer. */
-    pointer data() { return &m_data[0]; }
-
-    /** Return access to the data as a raw pointer. */
-    const_pointer data() const { return &m_data[0]; }
-
-
-  public:
-
-    /** Set the array dimensions.  The previous contents are destroyed
-     * before reallocating the array.  If the number of rows and columns
-     * isn't changing, nothing happens.  Also, if either rows or cols is 0,
-     * the array is cleared.
-     *
-     * @warning This is not guaranteed to preserve the original data.
-     */
-    void resize(size_t rows, size_t cols) {
-
-      /* Nothing to do if the size isn't changing: */
-      if(rows == m_rows && cols == m_cols) return;
-
-      /* Destroy the current array contents: */
-      this->destroy();
-
-      /* Set the new size if non-zero: */
-      if(rows*cols > 0) {
-	value_type* data = m_alloc.allocate(rows*cols);
-	for(size_t i = 0; i < rows*cols; ++ i)
-	  m_alloc.construct(&data[i], value_type());
-
-	/* Success, so save the new array and the dimensions: */
-	m_rows = rows;
-	m_cols = cols;
-	m_data = data;
-      }
-    }
-
-    /** Copy the other array.  The previous contents are destroyed before
-     * reallocating the array.  If other == *this, nothing happens.  Also,
-     * if either other.rows() or other.cols() is 0, the array is cleared.
-     */
-    void copy(const dynamic_2D& other) {
-
-      /* Nothing to do if it's the same array: */
-      if(&other == this) return;
-
-      /* Destroy the current array contents: */
-      this->destroy();
-
-      /* Set the new size if non-zero: */
-      size_t rows = other.rows(), cols = other.cols();
-      if(rows*cols > 0) {
-	value_type* data = m_alloc.allocate(rows*cols);
-	for(size_t i = 0; i < rows*cols; ++ i)
-	  m_alloc.construct(&data[i], other[i]);
-
-	/* Success, so save the new array and the dimensions: */
-	m_rows = rows;
-	m_cols = cols;
-	m_data = data;
-      }
-    }
-
-
-  protected:
-
-    reference get_element(size_t row, size_t col, row_major) {
-        return m_data[row*m_cols + col];
-    }
-
-    const_reference get_element(size_t row, size_t col, row_major) const {
-        return m_data[row*m_cols + col];
-    }
-
-    reference get_element(size_t row, size_t col, col_major) {
-        return m_data[col*m_rows + row];
-    }
-
-    const_reference get_element(size_t row, size_t col, col_major) const {
-        return m_data[col*m_rows + row];
-    }
-
-
-  protected:
-
-    /** Destroy the current contents of the array. */
-    void destroy() {
-      if(m_data) {
-	for(size_t i = 0; i < m_rows*m_cols; ++ i)
-	  m_alloc.destroy(&m_data[i]);
-	m_alloc.deallocate(m_data, m_rows*m_cols);
-	m_rows = m_cols = 0;
-	m_data = 0;
-      }
-    }
-
-
-  protected:
-
-    /** Current array dimensions (may be 0,0). */
-    size_t                      m_rows, m_cols;
-
-    /** Array data (may be NULL). */
-    value_type*			m_data;
-
-    /** Allocator for the array. */
-    allocator_type		m_alloc;
-};
-
-} // namespace cml
-
-#endif
-
-// -------------------------------------------------------------------------
-// vim:ft=cpp

src/cml/core/external_1D.h

-/* -*- C++ -*- ------------------------------------------------------------
- 
-Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
-
-The Configurable Math Library (CML) is distributed under the terms of the
-Boost Software License, v1.0 (see cml/LICENSE for details).
-
- *-----------------------------------------------------------------------*/
-/** @file
- *  @brief
- *
- * Defines the fixed-size and runtime-sized external 1D arrays.
- *
- * @todo Need a better way to designate non-resizable, run-time sized
- * arrays (e.g. by a resizeable tag).
- */
-
-#ifndef external_1D_h
-#define external_1D_h
-
-#include <cml/core/common.h>
-#include <cml/core/cml_meta.h>
-#include <cml/core/cml_assert.h>
-#include <cml/external.h>
-
-namespace cml {
-
-/** Fixed-size external 1D array.
- *
- * Both the memory and the size are fixed at compile time, and cannot be
- * changed.
- */
-template<typename Element, int Size = -1>
-class external_1D
-{
-  public:
-
-    /* Require Size > 0: */
-    CML_STATIC_REQUIRE(Size > 0);
-
-    /* Record the generator: */
-    typedef external<Size,-1> generator_type;
-
-    /* Standard: */
-    typedef Element value_type;
-    typedef Element* pointer;
-    typedef Element& reference;
-    typedef const Element& const_reference;
-    typedef const Element* const_pointer;
-
-    /* Array implementation: */
-    typedef value_type array_impl[Size];
-
-    /* For matching by memory type: */
-    typedef external_memory_tag memory_tag;
-
-    /* For matching by size type: */
-    typedef fixed_size_tag size_tag;
-
-    /* For matching by resizability: */
-    typedef not_resizable_tag resizing_tag;
-
-    /* For matching by dimensions: */
-    typedef oned_tag dimension_tag;
-
-
-  public:
-
-    /** The length as an enumerated value. */
-    enum { array_size = Size };
-
-
-  public:
-
-    external_1D(pointer const ptr)
-        : m_data(ptr) {}
-
-
-  public:
-
-    /** Return the number of elements in the array. */
-    size_t size() const { return size_t(array_size); }
-
-    /** Access to the data as a C array.
-     *
-     * @param i a size_t index into the array.
-     * @return a mutable reference to the array value at i.
-     *
-     * @note This function does not range-check the argument.
-     */
-    reference operator[](size_t i) { return m_data[i]; }
-
-    /** Const access to the data as a C array.
-     *
-     * @param i a size_t index into the array.
-     * @return a const reference to the array value at i.
-     *
-     * @note This function does not range-check the argument.
-     */
-    const_reference operator[](size_t i) const { return m_data[i]; }
-
-    /** Return access to the data as a raw pointer. */
-    pointer data() { return m_data; }
-
-    /** Return access to the data as a raw pointer. */
-    const_pointer data() const { return m_data; }
-
-
-  protected:
-
-    pointer const               m_data;
-
-
-  private:
-
-    /* Initialization without an argument isn't allowed: */
-    external_1D();
-};
-
-/** Run-time sized external 1D array.
- *
- * Both the memory and the size are fixed at run-time, and cannot be
- * changed.  This is a specialization for the case that Rows and Cols are
- * not specified (i.e. given as the default of -1,-1).
- */
-template<typename Element>
-class external_1D<Element,-1>
-{
-  public:
-
-    /* Record the generator.  Note: this is *not* unique, as it is the same
-     * generator used by external_2D.  However, external_2D is used only by
-     * matrix<> classes, so this is not a problem.
-     */
-    typedef external<> generator_type;
-
-    /* Standard: */
-    typedef Element value_type;
-    typedef Element* pointer;
-    typedef Element& reference;
-    typedef const Element& const_reference;
-    typedef const Element* const_pointer;
-
-    /* For matching by memory type: */
-    typedef external_memory_tag memory_tag;
-
-    /* For matching by size type: */
-    typedef dynamic_size_tag size_tag;
-
-    /* For matching by resizability: */
-    typedef not_resizable_tag resizing_tag;
-
-    /* For matching by dimensions: */
-    typedef oned_tag dimension_tag;
-
-
-  public:
-
-    /** The length as an enumerated value. */
-    enum { array_size = -1 };
-
-
-  public:
-
-    external_1D(pointer const ptr, size_t size)
-        : m_data(ptr), m_size(size) {}
-
-
-  public:
-
-    /** Return the number of elements in the array. */
-    size_t size() const { return m_size; }
-
-    /** Access to the data as a C array.
-     *
-     * @param i a size_t index into the array.
-     * @return a mutable reference to the array value at i.
-     *
-     * @note This function does not range-check the argument.
-     */
-    reference operator[](size_t i) { return m_data[i]; }
-
-    /** Const access to the data as a C array.
-     *
-     * @param i a size_t index into the array.
-     * @return a const reference to the array value at i.
-     *
-     * @note This function does not range-check the argument.
-     */
-    const_reference operator[](size_t i) const { return m_data[i]; }
-
-    /** Return access to the data as a raw pointer. */
-    pointer data() { return m_data; }
-
-    /** Return access to the data as a raw pointer. */
-    const_pointer data() const { return m_data; }
-
-
-  protected:
-
-    pointer const               m_data;
-    const size_t                m_size;
-
-
-  private:
-
-    /* Initialization without an argument isn't allowed: */
-    external_1D();
-};
-
-} // namespace cml
-
-#endif
-
-// -------------------------------------------------------------------------
-// vim:ft=cpp

src/cml/core/external_2D.h

-/* -*- C++ -*- ------------------------------------------------------------
- 
-Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
-
-The Configurable Math Library (CML) is distributed under the terms of the
-Boost Software License, v1.0 (see cml/LICENSE for details).
-
- *-----------------------------------------------------------------------*/
-/** @file
- *  @brief
- *
- * Defines the fixed-size and runtime-sized external 2D arrays.
- *
- * @todo Would casting get better performance in the external_2D<> element
- * access methods?
- */
-
-#ifndef external_2D_h
-#define external_2D_h
-
-#include <cml/core/common.h>
-#include <cml/core/fixed_1D.h>
-#include <cml/core/fixed_2D.h>
-#include <cml/core/dynamic_1D.h>
-#include <cml/core/dynamic_2D.h>
-#include <cml/external.h>
-
-namespace cml {
-
-/** Fixed-size external 2D array.
- *
- * Both the memory and the size are fixed at compile time, and cannot be
- * changed.
- */
-template<typename Element, int Rows, int Cols, typename Layout>
-class external_2D
-{
-  public:
-
-    /* Require Rows > 0, Cols > 0: */
-    CML_STATIC_REQUIRE((Rows > 0) && (Cols > 0));
-
-    /* Record the generator: */
-    typedef external<Rows,Cols> generator_type;
-
-    /* Standard: */
-    typedef Element value_type;
-    typedef Element* pointer;
-    typedef Element& reference;
-    typedef const Element& const_reference;
-    typedef const Element* const_pointer;
-
-    /* For matching by memory layout: */
-    typedef Layout layout;
-
-    /* For matching by memory type: */
-    typedef external_memory_tag memory_tag;
-
-    /* For matching by size type: */
-    typedef fixed_size_tag size_tag;
-
-    /* For matching by resizability: */
-    typedef not_resizable_tag resizing_tag;
-
-    /* For matching by dimensions: */
-    typedef twod_tag dimension_tag;
-
-    /* To simplify the matrix transpose operator: */
-    typedef fixed_2D<typename cml::remove_const<Element>::type,
-            Cols,Rows,Layout> transposed_type;
-    /* Note: the transposed type must be fixed_2D, since an external array
-     * cannot be specified without a corresponding memory location.
-     */
-
-    /* To simplify the matrix row and column operators: */
-    typedef fixed_1D<Element,Rows> row_array_type;
-    typedef fixed_1D<Element,Cols> col_array_type;
-    /* Note: the row types must be fixed_1D, since external arrays cannot be
-     * specified without a memory location.
-     */
-
-
-  public:
-
-    enum { array_rows = Rows, array_cols = Cols };
-
-
-  public:
-
-    /** Construct an external array from a pointer. */
-    external_2D(value_type const ptr[Rows][Cols])
-        : m_data(const_cast<pointer>(&ptr[0][0])) {}
-
-    /** Construct an external array from a pointer. */
-    external_2D(value_type* const ptr) : m_data(ptr) {}
-
-
-  public:
-
-    /** Return the number of rows in the array. */
-    size_t rows() const { return size_t(array_rows); }
-
-    /** Return the number of cols in the array. */
-    size_t cols() const { return size_t(array_cols); }
-
-
-  public:
-
-    /** Access element (row,col) of the matrix.
-     *
-     * @param row row of element.
-     * @param col column of element.
-     * @returns mutable reference.
-     *
-     * @note This function does not range-check the arguments.
-     */
-    reference operator()(size_t row, size_t col) {
-        /* Dispatch to the right function based on layout: */
-        return get_element(row,col,layout());
-    }
-
-    /** Const access element (row,col) of the matrix.
-     *
-     * @param row row of element.
-     * @param col column of element.
-     * @returns const reference.
-     *
-     * @note This function does not range-check the arguments.
-     */
-    const_reference operator()(size_t row, size_t col) const {
-        /* Dispatch to the right function based on layout: */
-        return get_element(row,col,layout());
-    }
-
-    /** Return access to the data as a raw pointer. */
-    pointer data() { return m_data; }
-
-    /** Return access to the data as a raw pointer. */
-    const_pointer data() const { return m_data; }
-
-
-  protected:
-
-    /* XXX May be able to cast to get better performance? */
-    reference get_element(size_t row, size_t col, row_major) {
-        return m_data[row*Cols + col];
-    }
-
-    const_reference get_element(size_t row, size_t col, row_major) const {
-        return m_data[row*Cols + col];
-    }
-
-    reference get_element(size_t row, size_t col, col_major) {
-        return m_data[col*Rows + row];
-    }
-
-    const_reference get_element(size_t row, size_t col, col_major) const {
-        return m_data[col*Rows + row];
-    }
-
-
-  protected:
-
-    /* Declare the data array: */
-    pointer const               m_data;
-};
-
-/** Run-time sized external 2D array.
- *
- * Both the memory and the size are fixed at run-time, but cannot be changed.
- * This is a specialization for the case that Rows and Cols are not specified
- * (i.e. given as the default of -1,-1).
- */
-template<typename Element, typename Layout>
-class external_2D<Element,-1,-1,Layout>
-{
-  public:
-
-    /* Record the generator.  Note: this is *not* unique, as it is the same
-     * generator used by external_1D.  However, external_1D is used only by
-     * vector<> classes, so this is not a problem.
-     */
-    typedef external<> generator_type;
-
-    /* Standard: */
-    typedef Element value_type;
-    typedef Element* pointer;
-    typedef Element& reference;
-    typedef const Element& const_reference;
-    typedef const Element* const_pointer;
-
-    /* For matching by memory layout: */
-    typedef Layout layout;
-
-    /* For matching by memory type: */
-    typedef external_memory_tag memory_tag;
-
-    /* For matching by size type: */
-    typedef dynamic_size_tag size_tag;
-
-    /* For matching by resizability: */
-    typedef not_resizable_tag resizing_tag;
-
-    /* For matching by dimensions: */
-    typedef twod_tag dimension_tag;
-
-    /* To simplify the matrix transpose operator: */
-    typedef dynamic_2D<typename cml::remove_const<Element>::type,
-        Layout, CML_DEFAULT_ARRAY_ALLOC> transposed_type;
-
-    /* To simplify the matrix row and column operators: */
-    typedef dynamic_1D<Element, CML_DEFAULT_ARRAY_ALLOC> row_array_type;
-    typedef dynamic_1D<Element, CML_DEFAULT_ARRAY_ALLOC> col_array_type;
-
-
-  public:
-
-    enum { array_rows = -1, array_cols = -1 };
-
-
-  public:
-
-    /** Construct an external array with no size. */
-    external_2D(pointer const ptr, size_t rows, size_t cols)
-        : m_data(ptr), m_rows(rows), m_cols(cols) {}
-
-
-  public:
-
-    /** Return the number of rows in the array. */
-    size_t rows() const { return m_rows; }
-
-    /** Return the number of cols in the array. */
-    size_t cols() const { return m_cols; }
-
-
-  public:
-
-    /** Access element (row,col) of the matrix.
-     *
-     * @param row row of element.
-     * @param col column of element.
-     * @returns mutable reference.
-     *
-     * @note This function does not range-check the arguments.
-     */
-    reference operator()(size_t row, size_t col) {
-        /* Dispatch to the right function based on layout: */
-        return get_element(row,col,layout());
-    }
-
-    /** Const access element (row,col) of the matrix.
-     *
-     * @param row row of element.
-     * @param col column of element.
-     * @returns const reference.
-     *
-     * @note This function does not range-check the arguments.
-     */
-    const_reference operator()(size_t row, size_t col) const {
-        /* Dispatch to the right function based on layout: */
-        return get_element(row,col,layout());
-    }
-
-    /** Return access to the data as a raw pointer. */
-    pointer data() { return m_data; }
-
-    /** Return access to the data as a raw pointer. */
-    const_pointer data() const { return m_data; }
-
-
-  protected:
-
-    /* XXX May be able to cast to get better performance? */
-    reference get_element(size_t row, size_t col, row_major) {
-        return m_data[row*m_cols + col];
-    }
-
-    const_reference get_element(size_t row, size_t col, row_major) const {
-        return m_data[row*m_cols + col];
-    }
-
-    reference get_element(size_t row, size_t col, col_major) {
-        return m_data[col*m_rows + row];
-    }
-
-    const_reference get_element(size_t row, size_t col, col_major) const {
-        return m_data[col*m_rows + row];
-    }
-
-
-  protected:
-
-    /* Declare the data array: */
-    value_type* const           m_data;
-    const size_t                m_rows;