Commits

Woojong Koh committed 479cbc2

hw2 프로젝트 추가

Comments (0)

Files changed (114)

 # Visual Studio 2010
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hw1", "hw1\hw1.vcxproj", "{A41009D4-53E8-410D-9840-789E932F730D}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hw2", "hw2\hw2.vcxproj", "{C6D6E0EB-3204-4E37-8669-BCA1F4C60287}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
 		{A41009D4-53E8-410D-9840-789E932F730D}.Debug|Win32.Build.0 = Debug|Win32
 		{A41009D4-53E8-410D-9840-789E932F730D}.Release|Win32.ActiveCfg = Release|Win32
 		{A41009D4-53E8-410D-9840-789E932F730D}.Release|Win32.Build.0 = Release|Win32
+		{C6D6E0EB-3204-4E37-8669-BCA1F4C60287}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C6D6E0EB-3204-4E37-8669-BCA1F4C60287}.Debug|Win32.Build.0 = Debug|Win32
+		{C6D6E0EB-3204-4E37-8669-BCA1F4C60287}.Release|Win32.ActiveCfg = Release|Win32
+		{C6D6E0EB-3204-4E37-8669-BCA1F4C60287}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

Binary file modified.

     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>glut32.lib;glu32.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+========================================================================
+    CONSOLE APPLICATION : hw2 Project Overview
+========================================================================
+
+AppWizard has created this hw2 application for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your hw2 application.
+
+
+hw2.vcxproj
+    This is the main project file for VC++ projects generated using an Application Wizard.
+    It contains information about the version of Visual C++ that generated the file, and
+    information about the platforms, configurations, and project features selected with the
+    Application Wizard.
+
+hw2.vcxproj.filters
+    This is the filters file for VC++ projects generated using an Application Wizard. 
+    It contains information about the association between the files in your project 
+    and the filters. This association is used in the IDE to show grouping of files with
+    similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+    "Source Files" filter).
+
+hw2.cpp
+    This is the main application source file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+    These files are used to build a precompiled header (PCH) file
+    named hw2.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
+/* -*- 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?aud, David Lesage and Rapha? 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
+
+#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

hw2/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

hw2/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

hw2/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

hw2/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

hw2/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) { 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[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

hw2/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) {
+        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 {
+        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

hw2/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

hw2/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;
+    const size_t                m_cols;
+};
+
+} // namespace cml
+
+#endif
+
+// -------------------------------------------------------------------------
+// vim:ft=cpp

hw2/cml/core/fixed_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 fixed_1D_h
+#define fixed_1D_h
+
+#include <cml/core/common.h>
+#include <cml/core/cml_meta.h>
+#include <cml/core/cml_assert.h>
+#include <cml/fixed.h>
+
+namespace cml {
+
+/** Statically-allocated array.
+ *
+ * @note This class is designed to have the same size as a C array with the
+ * same length.  It's therefore possible (but not recommended!) to coerce
+ * a normal C array into a fixed_1D<> like this:
+ *
+ * typedef fixed_1D<double,10> array;
+ * double c_array[10];
+ * array& array_object = *((array*)&c_array);
+ * double e1 = array_object[1];
+ *
+ * It's also possible to do this with a pointer to an array of values (e.g. a
+ * double*), whether or not it was actually declared as a fixed C array.  This
+ * is HIGHLY DISCOURAGED, though. It's relatively straightforward to implement
+ * a separate class to take a C array (or pointer) and turn it into an array
+ * object.
+ *
+ * @sa cml::fixed
+ *
+ * @internal Do <em>not</em> add the empty constructor and destructor; at
+ * least one compiler (Intel C++ 9.0) fails to optimize them away, and they
+ * aren't needed anyway here.
+ */
+template<typename Element, int Size>
+class fixed_1D
+{
+  public:
+
+    /* Require Size > 0: */
+    CML_STATIC_REQUIRE(Size > 0);
+
+    /* Record the generator: */
+    typedef fixed<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 fixed_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:
+
+    /** 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[0]; }
+
+    /** Return access to the data as a raw pointer. */
+    const_pointer data() const { return &m_data[0]; }
+
+  protected:
+
+    fixed_1D() {}
+
+
+  protected:
+
+    array_impl                  m_data;
+};
+
+} // namespace cml
+
+#endif
+
+// -------------------------------------------------------------------------
+// vim:ft=cpp

hw2/cml/core/fixed_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 fixed_2D_h
+#define fixed_2D_h
+
+#include <cml/core/common.h>
+#include <cml/core/fixed_1D.h>
+
+/* This is used below to create a more meaningful compile-time error when
+ * an unknown layout argument is given:
+ */
+struct invalid_layout_type_error;
+
+/* This is used below to create a more meaningful compile-time error when
+ * a negative size is given.
+ */
+struct negative_array_size_error;
+
+namespace cml {
+
+/** The internal statically-allocated 2D-array implementation class.
+ *
+ * This uses an internal class to setup the data matrix with the proper
+ * layout.  The alternative is to use a 1D array with size Rows*Cols and a
+ * multiplication to dereference an element, but it seems that compilers
+ * better optimize 2D array dereferences.  This is different from
+ * dynamic_2D<>, which must use the 1D array method.
+ *
+ * @sa cml::fixed
+ *
+ * @note This class is designed to have the same size as a C array with the
+ * same dimensions.  It's therefore possible (but not recommended!) to coerce
+ * a normal C array into a fixed_2D<> like this:
+ *
+ * typedef fixed_2D<double,10,10,row_major> array;
+ * double c_array[10][10];
+ * array& array_object = *((array*)&c_array);
+ * double e11 = array_object[1][1];
+ *
+ * It's also possible to do this with a pointer to an array of values (e.g. a
+ * double*), whether or not it was actually declared as a fixed C array.  This
+ * is HIGHLY DISCOURAGED, though, since it's relatively straightforward to
+ * implement a separate class to take a C array (or pointer) and turn it into
+ * an array object.
+ *
+ * @internal Do <em>not</em> add the empty constructor and destructor; at
+ * least one compiler (Intel C++ 9.0) fails to optimize them away, and they
+ * aren't needed anyway here.
+ */
+template<typename Element, int Rows, int Cols, typename Layout>
+class fixed_2D
+{
+  public:
+
+    /* Require Rows > 0, Cols > 0: */
+    CML_STATIC_REQUIRE_M(
+            (Rows > 0) && (Cols > 0),
+            negative_array_size_error);
+
+    /* Require Layout to be row_major or col_major: */
+    CML_STATIC_REQUIRE_M(
+            (same_type<Layout,row_major>::is_true
+             || same_type<Layout,col_major>::is_true),
+            invalid_layout_type_error);
+
+
+    /* Record the generator: */
+    typedef fixed<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 fixed_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;
+
+    /* To simplify the matrix row and column operators: */
+    typedef fixed_1D<Element,Rows> row_array_type;
+    typedef fixed_1D<Element,Cols> col_array_type;
+
+
+  public:
+
+    enum { array_rows = Rows, array_cols = Cols };
+
+
+  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[0][0]; }
+
+    /** Return access to the data as a raw pointer. */
+    const_pointer data() const { return &m_data[0][0]; }
+
+
+  public:
+
+    fixed_2D() {}
+
+
+  protected:
+
+    reference get_element(size_t row, size_t col, row_major) {
+        return m_data[row][col];
+    }
+
+    const_reference get_element(size_t row, size_t col, row_major) const {
+        return m_data[row][col];
+    }
+
+    reference get_element(size_t row, size_t col, col_major) {
+        return m_data[col][row];
+    }
+
+    const_reference get_element(size_t row, size_t col, col_major) const {
+        return m_data[col][row];
+    }
+
+
+  protected:
+
+    /* Typedef the possible layouts: */
+    typedef Element row_major_array[Rows][Cols];
+    typedef Element col_major_array[Cols][Rows];
+
+    /* Now, select the right layout for the current matrix: */
+    typedef typename select_switch<
+        Layout, row_major, row_major_array,     /* Case 1 */
+                col_major, col_major_array      /* Case 2 */
+        >::result array_data;
+
+    /* Declare the data array: */
+    array_data                  m_data;
+};
+
+} // namespace cml
+
+#endif
+
+// -------------------------------------------------------------------------
+// vim:ft=cpp

hw2/cml/core/fwd.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
+ *
+ * Forward declarations, useful to avoid including lots of headers.
+ *
+ * @sa cml/et/array_promotions.h
+ */
+
+#ifndef core_fwd_h
+#define core_fwd_h
+
+namespace cml {
+
+/* cml/core/fixed_1D.h */
+template<typename E, int S> class fixed_1D;
+
+/* cml/core/fixed_2D.h */
+template<typename E, int R, int C, class L> class fixed_2D;
+
+/* cml/core/dynamic_1D.h */
+template<typename E, class A> class dynamic_1D;
+
+/* cml/core/dynamic_2D.h */
+template<typename E, class L, class A> class dynamic_2D;
+
+/* cml/core/external_1D.h */
+template<typename E, int S> class external_1D;
+
+/* cml/core/external_2D.h */
+template<typename E, int R, int C, class L> class external_2D;
+
+/* cml/fixed.h */
+template<int Dim1, int Dim2> struct fixed;
+
+/* cml/dynamic.h */
+template<class Alloc> struct dynamic;
+
+/* cml/external.h */
+template<int Dim1, int Dim2> struct external;
+
+/* cml/vector.h */
+template<typename E, class AT> class vector;
+
+/* cml/matrix.h */
+template<typename E, class AT, class BO, class L> class matrix;
+
+/* cml/quaternion.h */
+template<typename E, class AT, class OT, class CT> class quaternion;
+
+} // namespace cml
+
+#endif
+
+// -------------------------------------------------------------------------
+// vim:ft=cpp

hw2/cml/core/meta/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_meta_common_h
+#define core_meta_common_h
+
+namespace cml {
+
+/** Type of a true statement. */
+struct true_type {};
+
+/** Type of a false statement. */
+struct false_type {};
+
+template<bool B> struct is_true {
+    typedef false_type result;
+};
+
+template<> struct is_true<true> {
+    typedef true_type result;
+};
+
+/** A "type pair". */
+template<typename T1, typename T2> struct type_pair {
+    typedef T1 first;
+    typedef T2 second;
+};
+
+/** A "type quadruple". */
+template<typename T1, typename T2, typename T3, typename T4>
+struct type_quad {
+    typedef T1 first;
+    typedef T2 second;
+    typedef T3 third;
+    typedef T3 fourth;
+};
+
+/** Match any type (for use with same_type<> and select_switch<>). */
+struct any_type {};
+
+/** Determine if two types are the same.
+ *
+ * Defaults to false.
+ */
+template<typename T, typename U> struct same_type {
+    typedef false_type result;
+    enum { is_true = false, is_false = true };
+};
+
+/** Match the same type for both of same_type's template arguments. */
+template<typename T> struct same_type<T,T> {
+    typedef true_type result;
+    enum { is_true = true, is_false = false };
+};
+
+/** Match a type and any_type. */
+template<typename T> struct same_type<T,any_type> {
+    typedef true_type result;
+    enum { is_true = true, is_false = false };
+};
+
+/** Match a type and any_type. */
+template<typename T> struct same_type<any_type,T> {
+    typedef true_type result;
+    enum { is_true = true, is_false = false };
+};
+
+/** Disambiguate pair of any_type's. */
+template<> struct same_type<any_type,any_type> {
+    typedef true_type result;
+    enum { is_true = true, is_false = false };
+};
+
+/** Remove a reference qualifier from a type. */
+template<typename T> struct remove_reference {
+    template<typename Q, typename Dummy> struct helper {
+        typedef Q type;
+    };
+
+    template<typename Q> struct helper<Q&, void> {
+        typedef Q type;
+    };
+
+    template<typename Q> struct helper<const Q&, void> {
+        typedef const Q type;
+    };
+
+    typedef typename helper<T,void>::type type;
+};
+
+/** Remove a const qualifier from a type. */
+template<typename T> struct remove_const {
+    template<typename Q, typename Dummy> struct helper {
+        typedef Q type;
+    };
+
+    template<typename Q> struct helper<const Q, void> {
+        typedef Q type;
+    };
+
+    typedef typename helper<T,void>::type type;
+};
+
+} // namespace cml
+
+#endif
+
+// -------------------------------------------------------------------------
+// vim:ft=cpp

hw2/cml/core/meta/if.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 meta_if_h
+#define meta_if_h
+
+#include <cml/core/meta/common.h>
+
+namespace cml {
+
+/** Select argument type based upon truth value. */
+template<bool yn, typename TrueT, typename FalseT> struct select_if;
+
+/** Result is TrueT if true. */
+template<typename TrueT, typename FalseT>
+struct select_if<true,TrueT,FalseT> {
+    typedef TrueT result;
+    enum { is_true = true };
+};
+
+/** Result is FalseT if false. */
+template<typename TrueT, typename FalseT>
+struct select_if<false,TrueT,FalseT> {
+    typedef FalseT result;
+    enum { is_true = false };
+};
+
+} // namespace cml
+
+#endif
+
+// -------------------------------------------------------------------------
+// vim:ft=cpp

hw2/cml/core/meta/switch.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 meta_switch_h
+#define meta_switch_h
+
+#include <cml/core/meta/common.h>
+#include <cml/core/meta/if.h>
+
+namespace cml {
+
+struct NilCase {};      /* For terminating the case list. */
+struct Default {};      /* For indicating the default result. */
+
+/* The working parts of the meta-switch go into namespace meta: */
+namespace meta {
+
+/* "Interior" case statements: */
+template<typename Case, typename Result, typename NextCase>
+struct select_case
+{
+    template<typename Find> struct match {
+        typedef typename select_if<
+            same_type<Find,Case>::is_true,
+            Result,
+            typename NextCase::template match<Find>::result
+        >::result result;
+    };
+};
+
+/* Default case, returned when no match is found in a previous case: */
+template<typename Result>
+struct select_case<Default,Result,NilCase>
+{
+    template<typename Find> struct match {
+        typedef Result result;
+    };
+};
+
+/* The last case statement (if no match until now, the result is 'void'): */
+template<typename Case, typename Result>
+struct select_case<Case,Result,NilCase>
+{
+    template<typename Find> struct match {
+        typedef typename select_if<
+            same_type<Find,Case>::is_true,
+            Result,
+            void
+        >::result result;
+    };
+};
+
+} // namespace meta
+
+/** Return the matched type (like a switch/case statement).
+ *
+ * This is a convenience wrapper to avoid having to explicitly type out
+ * select_case for each case in the list of types to match against.
+ */
+template<typename Find
+, typename T1,           typename R1
+, typename T2 = NilCase, typename R2 = void
+, typename T3 = NilCase, typename R3 = void
+, typename T4 = NilCase, typename R4 = void
+, typename T5 = NilCase, typename R5 = void
+, typename T6 = NilCase, typename R6 = void
+, typename T7 = NilCase, typename R7 = void
+, typename T8 = NilCase, typename R8 = void
+, typename T9 = NilCase, typename R9 = void
+, typename T10 = NilCase, typename R10 = void
+, typename T11 = NilCase, typename R11 = void
+, typename T12 = NilCase, typename R12 = void
+, typename T13 = NilCase, typename R13 = void
+, typename T14 = NilCase, typename R14 = void
+, typename T15 = NilCase, typename R15 = void
+, typename T16 = NilCase, typename R16 = void
+> struct select_switch
+{
+    typedef typename
+          meta::select_case< T1,R1
+        , meta::select_case< T2,R2
+        , meta::select_case< T3,R3
+        , meta::select_case< T4,R4
+        , meta::select_case< T5,R5
+        , meta::select_case< T6,R6