NABLA  Nabla Ain't Basic Linear Algebra
matrix.h
Go to the documentation of this file.
1 //matrix.h
2 //describes 'matrix' and 'vector' template classes and related stuff
3 //file version 0.0 20120622
4 //100% hand crafted
578 #ifndef TOOLS_MATRIX_INCLUDED
579 #define TOOLS_MATRIX_INCLUDED
580 #include <algorithm>
581 #include <cmath>
582 #include <stdexcept>
583 #pragma warning(push, 4)
584 
586 namespace nabla {
587 #ifdef NDEBUG
588 #define ASSERT(cond) (void)(sizeof(cond?0:0))
589 #else
590 #include <cassert>
591 #define ASSERT(cond) assert(cond)
592 #endif
593 
595 
598 template<typename type>
599 class traits
600 {
601 public:
602  static const type unit;
603  static const type zero;
604 };
605 
606 template<typename type> const type traits<type>::unit = static_cast<type>(1);
607 template<typename type> const type traits<type>::zero = static_cast<type>(0);
608 
650 namespace tag {
846 struct storage {};
847 
921 struct reference {};
922 
924 
988 template<size_t complexity>
989 struct expression {};
990 }//namespace tag
991 
1020 struct rectangular {};
1021 
1028 struct symmetric {};
1029 
1040 
1051 
1053 
1194 template<typename value_t, typename expr_t, typename tag>
1196 {};
1197 
1199 
1201 {
1203  const size_t value;
1205  constrained_index(size_t i) : value(i) {}
1207  operator size_t() { return value; }
1208 
1209 private:
1212 };
1213 
1215 namespace util {
1217 template<typename tag>
1218 struct tag_complexity
1219 { enum { value = 0 }; };
1221 template<size_t c>
1222 struct tag_complexity<tag::expression<c> >
1223 { enum { value = c }; };
1225 struct unconstrained_first_non_zero
1226 {
1227  typedef size_t first_type;
1228  template<typename type>
1229  static first_type first(const type&, size_t) { return 0; }
1230 };
1232 struct unconstrained_last_non_zero_in_row
1233 {
1234  typedef size_t last_type;
1235  template<typename type>
1236  static last_type last(const type &m, size_t) { return m.cols() - 1; }
1237 };
1239 struct unconstrained_last_non_zero_in_column
1240 {
1241  typedef size_t last_type;
1242  template<typename type>
1243  static last_type last(const type &m, size_t) { return m.rows() - 1; }
1244 };
1246 struct constrained_first_non_zero
1247 {
1248  typedef constrained_index first_type;
1249  template<typename type>
1250  static first_type first(const type&, size_t i) { return i; }
1251 };
1253 struct constrained_last_non_zero
1254 {
1255  typedef constrained_index last_type;
1256  template<typename type>
1257  static last_type last(const type &, size_t i) { return i; }
1258 };
1260 template<typename shape>
1261 struct non_zero_in_row : unconstrained_first_non_zero, unconstrained_last_non_zero_in_row
1262 {
1263  //typedef size_t first_type;
1264  //typedef size_t last_type;
1265  //template<typename type>
1266  //static first_type first(const type&, size_t) { return 0; }
1267  //template<typename type>
1268  //static last_type last(const type &m, size_t) { return m.cols() - 1; }
1269 };
1271 template<typename shape>
1272 struct non_zero_in_column : unconstrained_first_non_zero, unconstrained_last_non_zero_in_column
1273 {
1274  //typedef size_t first_type;
1275  //typedef size_t last_type;
1276  //template<typename type>
1277  //static first_type first(const type&, size_t) { return 0; }
1278  //template<typename type>
1279  //static last_type last(const type &m, size_t) { return m.rows() - 1; }
1280 };
1282 template<>
1283 struct non_zero_in_row<lower_triangular> : unconstrained_first_non_zero, constrained_last_non_zero
1284 {
1285  //typedef size_t first_type;
1286  //typedef constrained_index last_type;
1287  //template<typename type>
1288  //static first_type first(const type&, size_t) { return 0; }
1289  //template<typename type>
1290  //static last_type last(const type&, size_t row) { return row; }
1291 };
1293 template<>
1294 struct non_zero_in_column<lower_triangular> : constrained_first_non_zero, unconstrained_last_non_zero_in_column
1295 {
1296  //typedef constrained_index first_type;
1297  //typedef size_t last_type;
1298  //template<typename type>
1299  //static first_type first(const type&, size_t column) { return column; }
1300  //template<typename type>
1301  //static last_type last(const type &m, size_t) { return m.rows() - 1; }
1302 };
1304 template<>
1305 struct non_zero_in_row<upper_triangular> : constrained_first_non_zero, unconstrained_last_non_zero_in_row
1306 {
1307  //typedef constrained_index first_type;
1308  //typedef size_t last_type;
1309  //template<typename type>
1310  //static first_type first(const type&, size_t row) { return row; }
1311  //template<typename type>
1312  //static last_type last(const type &m, size_t) { return m.cols() - 1; }
1313 };
1315 template<>
1316 struct non_zero_in_column<upper_triangular> : unconstrained_first_non_zero, constrained_last_non_zero
1317 {
1318  //typedef size_t first_type;
1319  //typedef constrained_index last_type;
1320  //template<typename type>
1321  //static first_type first(const type&, size_t) { return 0; }
1322  //template<typename type>
1323  //static last_type last(const type &, size_t column) { return column; }
1324 };
1325 }//namespace util
1326 
1328 
1403 template<typename value_t, typename expr_t, typename tag_t, typename shape>
1405  public matrix_expression<value_t,
1406  expr_t,
1407  tag::expression<util::tag_complexity<tag_t>::value>
1408  >
1409 {
1411  friend
1412  typename util::non_zero_in_row<shape>::first_type
1413  first_non_zero_in_row(const expr_t &m, size_t row)
1414  { return util::non_zero_in_row<shape>::first(m, row); }
1416  friend
1417  typename util::non_zero_in_row<shape>::last_type
1418  last_non_zero_in_row(const expr_t &m, size_t row)
1419  { return util::non_zero_in_row<shape>::last(m, row); }
1421  friend
1422  typename util::non_zero_in_column<shape>::first_type
1423  first_non_zero_in_column(const expr_t &m, size_t column)
1424  { return util::non_zero_in_column<shape>::first(m, column); }
1426  friend
1427  typename util::non_zero_in_column<shape>::last_type
1428  last_non_zero_in_column(const expr_t &m, size_t column)
1429  { return util::non_zero_in_column<shape>::last(m, column); }
1430 };
1431 
1433 
1434 
1435 template<typename expr_t> inline
1436 util::non_zero_in_row<rectangular>::first_type
1437 first_non_zero_in_row(const expr_t &m, size_t row)
1438 { return util::non_zero_in_row<rectangular>::first(m, row); }
1440 template<typename expr_t> inline
1441 util::non_zero_in_row<rectangular>::last_type
1442 last_non_zero_in_row(const expr_t &m, size_t row)
1443 { return util::non_zero_in_row<rectangular>::last(m, row); }
1445 template<typename expr_t> inline
1446 util::non_zero_in_column<rectangular>::first_type
1447 first_non_zero_in_column(const expr_t &m, size_t column)
1448 { return util::non_zero_in_column<rectangular>::first(m, column); }
1450 template<typename expr_t> inline
1451 util::non_zero_in_column<rectangular>::last_type
1452 last_non_zero_in_column(const expr_t &m, size_t column)
1453 { return util::non_zero_in_column<rectangular>::last(m, column); }
1455 
1461 template<typename expression_type> struct expr_traits;
1462 
1465 template<typename value_t, typename expr_t, typename tag_t>
1466 struct expr_traits<matrix_expression<value_t, expr_t, tag_t> >
1467 {
1468  typedef value_t value_type;
1469  typedef expr_t type;
1470  typedef tag_t tag;
1471  typedef rectangular shape;
1472  enum {
1473  complexity = util::tag_complexity<tag>::value
1474  };
1475 };
1476 
1479 template<typename value_t, typename expr_t, typename tag_t, typename shape_t>
1480 struct expr_traits<shaped_expression<value_t, expr_t, tag_t, shape_t> >
1481 {
1482  typedef value_t value_type;
1483  typedef expr_t type;
1484  typedef tag_t tag;
1485  typedef shape_t shape;
1486  enum {
1487  complexity = util::tag_complexity<tag>::value
1488  };
1489 };
1490 
1492 
1493 
1494 
1497 template<typename value_t, typename expr_t, typename tag> inline
1499 { return *static_cast<expr_t*>(&a); }
1500 
1502 
1505 template<typename value_t, typename expr_t, typename tag> inline
1507 { return *static_cast<const expr_t*>(&a); }
1509 
1511 namespace orientation {
1513 struct undefined {};
1514 
1516 struct column {};
1517 
1519 struct row {};
1520 }//namespace orientation
1521 
1523 
1524 
1525 
1526 template<typename expr_t>
1527 orientation::undefined orientation_type(expr_t*); //do not define
1529 
1530 namespace util { //all this allows to determine the orientation of a given vector expression
1531 char id(orientation::undefined);
1532 char (&id(orientation::column))[2];
1533 char (&id(orientation::row))[3];
1534 template<size_t> struct interpret_orientation;
1535 template<> struct interpret_orientation<1> { typedef orientation::undefined type; };
1536 template<> struct interpret_orientation<2> { typedef orientation::column type; };
1537 template<> struct interpret_orientation<3> { typedef orientation::row type; };
1538 template<typename expr_t>
1539 struct vector_orientation
1540 {
1541  typedef typename interpret_orientation<sizeof(id(orientation_type((expr_t*)42)))>::type type;
1542 };
1543 }//namespace util
1544 
1545 //forward declaration
1546 template<typename value_t, typename expr_t, typename tag,
1547  typename orientation = typename util::vector_orientation<expr_t>::type
1548  >
1549 struct vector_expression;
1550 
1552 
1665 template<typename value_t, typename expr_t, typename tag, typename orientation>
1667 
1669 
1670 template<typename iterator_type>
1672 {
1674  const size_t row;
1676  size_t col;
1678  base_row_iterator(size_t r, size_t c) : row(r), col(c) {}
1680  iterator_type &operator++() { ++col; return *static_cast<iterator_type*>(this); }
1681 private:
1684 };
1686 
1687 template<typename t>
1689 {
1691  struct type : public base_row_iterator<type>
1692  {
1694  t &ref;
1696  type(t &m, size_t r, size_t c) : base_row_iterator(r, c), ref(m) { ASSERT(row<ref.rows()); }
1698  typename t::reference operator*() { ASSERT(col<ref.cols()); return ref(row, col); }
1699  };
1700  static type begin(t &v, size_t r, size_t c) { return type(v, r, c); }
1701 };
1703 
1704 template<typename t>
1706 {
1708  struct type : public base_row_iterator<type>
1709  {
1711  const t &ref;
1713  type(const t &m, size_t r, size_t c) : base_row_iterator(r, c), ref(m) { ASSERT(row<ref.rows()); }
1715  typename t::const_reference operator*() const { ASSERT(col<ref.cols()); return ref(row, col); }
1716  };
1717  static type begin(const t &v, size_t r, size_t c) { return type(v, r, c); }
1718 };
1720 
1721 template<typename iterator_type>
1723 {
1725  const size_t col;
1727  size_t row;
1729  base_column_iterator(size_t r, size_t c) : row(r), col(c) {}
1731  iterator_type &operator++() { ++row; return *static_cast<iterator_type*>(this); }
1732 private:
1735 };
1737 
1738 template<typename t>
1740 {
1742  struct type : public base_column_iterator<type>
1743  {
1745  t &ref;
1747  type(type &m, size_t c, size_t r) : base_column_iterator(r, c), ref(m) { ASSERT(col<ref.cols()); }
1749  typename t::reference operator*() { ASSERT(row<ref.rows()); return ref(row, col); }
1750  };
1751  static type begin(const t &v, size_t c, size_t r) { return type(v, c, r); }
1752 };
1754 
1755 template<typename t>
1757 {
1759  struct type : public base_column_iterator<type>
1760  {
1762  const t &ref;
1764  type(const t &m, size_t c, size_t r) : base_column_iterator(r, c), ref(m) { ASSERT(col<ref.cols()); }
1766  typename t::const_reference operator*() const { ASSERT(row<ref.rows()); return ref(row, col); }
1767  };
1768  static type begin(const t &v, size_t c, size_t r) { return type(v, c, r); }
1769 };
1771 
1772 template<typename iterator_type>
1774 {
1776  size_t index;
1778  explicit base_vector_iterator(size_t i) : index(i) {}
1780  iterator_type &operator++() { ++index; return *static_cast<iterator_type*>(this); }
1781 private:
1784 };
1786 
1787 template<typename t>
1788 struct iterator
1789 {
1791  struct type : public base_vector_iterator<type>
1792  {
1794  t &ref;
1796  type(t &v, size_t i) : base_vector_iterator(i), ref(v) { ASSERT(index<ref.size()); }
1798  typename t::reference operator*() { ASSERT(index<ref.size()); return ref(index); }
1799  };
1800  static type begin(t &v, size_t i) { return type(v, i); }
1801 };
1803 
1804 template<typename t>
1806 {
1808  struct type : public base_vector_iterator<type>
1809  {
1811  const t &ref;
1813  type(const t &v, size_t i) : base_vector_iterator(i), ref(v) { ASSERT(index<ref.size()); }
1815  typename t::const_reference operator*() const { ASSERT(index<ref.size()); return ref(index); }
1816  };
1817  static type begin(const t &v, size_t i) { return type(v, i); }
1818 };
1819 
1821 
1822 template<typename value_t, typename expr_t, typename tag> inline
1824 { return iterator<expr_t>::begin(get_vector(v), i); }
1826 
1827 template<typename value_t, typename expr_t, typename tag> inline
1829 { return const_iterator<expr_t>::begin(get_vector(v), i); }
1830 
1832 
1836 template<typename value_t, typename expr_t, typename tag_t>
1838  public matrix_expression<value_t,
1839  column_wrapper<value_t, expr_t, tag_t>,
1840  tag::expression<util::tag_complexity<tag_t>::value>
1841  >
1842 {
1843 public:
1844  typedef value_t value_type;
1845  typedef const value_type const_reference;
1846 
1849  {}
1851 
1852  const_reference operator()(size_t row, size_t col) const
1853  {
1854  ASSERT(col==0);
1855  return (*static_cast<const expr_t*>(this))(row);
1856  }
1858 
1859  size_t rows() const { return static_cast<const expr_t*>(this)->size(); }
1861 
1862  size_t cols() const { return 1; }
1863 private:
1868 };
1869 
1871 
1880 template<typename value_t, typename expr_t, typename tag>
1881 class vector_expression<value_t, expr_t, tag, orientation::column> : public column_wrapper<value_t, expr_t, tag>
1882 {
1883 private: //hiding members of 'column_wrapper'
1889 
1891 };
1892 
1894 
1898 template<typename value_t, typename expr_t, typename tag_t>
1900  public matrix_expression<value_t,
1901  row_wrapper<value_t, expr_t, tag_t>,
1902  tag::expression<util::tag_complexity<tag_t>::value>
1903  >
1904 {
1905 public:
1906  typedef value_t value_type;
1907  typedef const value_type const_reference;
1908 
1911  {}
1913 
1914  const_reference operator()(size_t row, size_t col) const
1915  {
1916  ASSERT(row==0);
1917  return (*static_cast<const expr_t*>(this))(col);
1918  }
1920 
1921  size_t rows() const { return 1; }
1923 
1924  size_t cols() const { return static_cast<const expr_t*>(this)->size(); }
1925 private:
1927  row_wrapper(const row_wrapper&);
1930 };
1931 
1933 
1940 template<typename value_t, typename expr_t, typename tag>
1941 class vector_expression<value_t, expr_t, tag, orientation::row> : public row_wrapper<value_t, expr_t, tag>
1942 {
1943 private: //hiding members of 'row_wrapper'
1949 
1951 };
1952 
1955 template<typename value_t, typename expr_t, typename tag_t, typename orientation_t>
1956 struct expr_traits<vector_expression<value_t, expr_t, tag_t, orientation_t> >
1957 {
1958  typedef value_t value_type;
1959  typedef expr_t type;
1960  typedef tag_t tag;
1961  typedef orientation_t orientation;
1962  enum {
1963  complexity = util::tag_complexity<tag>::value
1964  };
1965 };
1966 
1968 
1969 
1970 
1973 template<typename value_t, typename expr_t, typename tag> inline
1975 { return *static_cast<expr_t*>(&a); }
1976 
1978 
1981 template<typename value_t, typename expr_t, typename tag> inline
1983 { return *static_cast<const expr_t*>(&a); }
1985 
1986 namespace util {
1988 template<typename type, size_t static_size>
1989 class sequence_base
1990 {
1991 public:
1993  sequence_base() : _p(0) {}
1995  ~sequence_base() { if (_p && _p!=_data) delete[] _p; }
1997  void realloc(size_t size)
1998  {
1999  type *p = size<=static_size ? _data : new type[size]; //if (size>static_size) allocates memory
2000  if (_p && _p!=_data) delete[] _p; //note that static_size>0
2001  _p = size!=0 ? p : 0; //if size==0 frees memory
2002  return;
2003  }
2004 protected:
2005  type *_p;
2006  type _data[static_size];
2007 };
2009 template<typename type>
2010 class sequence_base<type, 0>
2011 {
2012 public:
2014  sequence_base() : _p(0) {}
2016  ~sequence_base() { if (_p) delete[] _p; }
2018  void realloc(size_t size)
2019  {
2020  type *p = size!=0 ? new type[size] : 0; //if size==0 frees memory
2021  if (_p) delete[] _p;
2022  _p = p;
2023  return;
2024  }
2025 protected:
2026  type *_p;
2027 };
2028 template<typename type, size_t static_size = 0> class sequence;
2029 template<typename type, size_t static_size> void swap(sequence<type, static_size>&, size_t, sequence<type, static_size>&, size_t);
2030 template<typename type> void swap(sequence<type>&, sequence<type>&);
2032 template<typename type, size_t static_size>
2033 class sequence : public sequence_base<type, static_size>
2034 {
2035 public:
2036  typedef type value_type;
2037  typedef type &reference;
2038  typedef const type &const_reference;
2039 
2041  sequence() {}
2043  sequence(size_t size) { this->realloc(size); }
2045  sequence(size_t size, const value_type &value) { this->realloc(size, value); }
2047  value_type &operator[](size_t i) { ASSERT(!this->is_null()); return _p[i]; }
2049  const value_type &operator[](size_t i) const { ASSERT(!this->is_null()); return _p[i]; }
2051  template<size_t s>
2052  sequence &copy(const sequence<type, s> &a, size_t size)
2053  {
2054  ASSERT(!this->is_null() && !a.is_null());
2055  for (size_t i = 0; i<size; ++i)
2056  _p[i] = a._p[i];
2057  return *this;
2058  }
2060  void fill(const value_type &value, size_t count)
2061  {
2062  ASSERT(!this->is_null());
2063  for (size_t i = 0; i<count; ++i)
2064  _p[i] = value;
2065  return;
2066  }
2068  using sequence_base<type, static_size>::realloc;
2070  void realloc(size_t size, const value_type &value)
2071  {
2072  this->realloc(size);
2073  fill(value, size);
2074  return;
2075  }
2077  bool is_null() const { return _p==0; }
2078 
2079 private:
2080  //value_type *_p;
2081  //value_type _data[static_size];
2082 
2083  sequence(const sequence&);
2084  sequence &operator=(const sequence&);
2085 
2086  friend void swap<type, static_size>(sequence<type, static_size>&, size_t, sequence<type, static_size>&, size_t);
2087  friend void swap<type>(sequence<type>&, sequence<type>&);
2088 
2089 };
2091 template<typename type, size_t static_size>
2092 void swap(sequence<type, static_size> &a, size_t a_size, sequence<type, static_size> &b, size_t b_size)
2093 {
2094  using std::swap;
2095  const bool
2096  a_is_static = a_size<=static_size,
2097  b_is_static = b_size<=static_size;
2098  if (!a_is_static)
2099  {
2100  if (!b_is_static)
2101  swap(a._p, b._p);
2102  else
2103  {
2104  for (size_t i = 0; i<b_size; ++i)
2105  a._data[i] = b._p[i];
2106  b._p = a._p;
2107  a._p = a._data;
2108  }
2109  return;
2110  }
2111  else if (!b_is_static)
2112  {
2113  for (size_t i = 0; i<a_size; ++i)
2114  b._data[i] = a._p[i];
2115  a._p = b._p;
2116  b._p = b._data;
2117  return;
2118  }
2119  size_t min;
2120  if (a_size<b_size)
2121  {
2122  min = a_size;
2123  for (size_t i = min; i<b_size; ++i)
2124  a._p[i] = b._p[i];
2125  }
2126  else//a_size>=b_size
2127  {
2128  min = b_size;
2129  for (size_t i = min; i<a_size; ++i)
2130  b._p[i] = a._p[i];
2131  }
2132  for (size_t i = 0; i<min; ++i)
2133  swap(a._p[i], b._p[i]);
2134  return;
2135 }
2137 template<typename type> inline
2138 void swap(sequence<type> &a, sequence<type> &b)
2139 {
2140  using std::swap;
2141  swap(a._p, b._p);
2142  return;
2143 }
2144 }//namespace util
2145 
2147 
2231 template<typename type>
2232 class temporary : public type
2233 {
2234 public:
2236  temporary() : type() {}
2238 
2239  temporary(temporary &a) : type()
2240  {
2241  using std::swap;
2242  swap(*static_cast<type*>(this), *static_cast<type*>(&a));
2243  }
2245 
2248  template<typename other>
2249  temporary(const other &a) : type(a) {}
2251 
2253  {
2254  using std::swap;
2255  swap(*static_cast<type*>(this), *static_cast<type*>(&a));
2256  return *this;
2257  }
2259 
2262  template<typename other>
2263  temporary &operator=(const other &a) { type::operator=(a); return *this; }
2264 };
2265 
2267 
2269 template<typename type>
2270 struct rvalue : public type
2271 {
2272  rvalue(); //these member declarations are needed for compiler not to complain about the impossibility
2273  ~rvalue(); //to generate corresponding members (these two shall not be defined!!!)
2274 };
2275 
2277 
2278 
2279 
2281 template<typename type>
2283 { return *static_cast<rvalue<type>*>(&a); }
2285 
2286 //forward declaration
2287 template<typename expression_type, typename tag, typename orientation> class vector_ref;
2288 
2290 
2297 template<typename expression_type>
2298 class vector_ref<expression_type, tag::reference, orientation::row> :
2299  public vector_expression<typename expr_traits<expression_type>::value_type,
2300  vector_ref<expression_type, tag::reference, orientation::row>,
2301  tag::reference,
2302  orientation::row
2303  >
2304 {
2305  typedef typename expr_traits<expression_type>::type expr_t;
2306 public:
2307  typedef typename expr_t::value_type value_type;
2308  typedef typename expr_t::reference reference;
2309  typedef typename expr_t::const_reference const_reference;
2310 
2312  vector_ref(vector_ref &a) : _ref(a._ref), _row(a._row)
2313  {}
2315  vector_ref(rvalue<vector_ref> &a) : _ref(a._ref), _row(a._row)
2316  {}
2318  vector_ref(expr_t &a, size_t row) : _ref(a), _row(row)
2319  {}
2321  reference operator()(size_t i)
2322  { return _ref(_row, i); }
2324  const_reference operator()(size_t i) const
2325  { return _ref(_row, i); }
2327  reference operator[](size_t i)
2328  { return _ref(_row, i); }
2330  const_reference operator[](size_t i) const
2331  { return _ref(_row, i); }
2333  size_t size() const
2334  { return _ref.cols(); }
2335  //Conversion to "reference to rvalue".
2336  operator rvalue<vector_ref>&()
2337  { return to_rvalue_ref(*this); }
2338 
2339 private:
2340  expr_t &_ref;
2341  const size_t _row;
2342 
2344  vector_ref &operator=(const vector_ref&); //do not implement
2345 
2347  friend expr_t &get_vector_ref(vector_ref &a) { return a._ref; }
2349  friend const expr_t &get_vector_ref(const vector_ref &a) { return a._ref; }
2351  friend size_t get_vector_row(const vector_ref &a) { return a._row; }
2352 };
2353 
2354 namespace util {
2356 template<size_t a, size_t b, size_t c = 0>
2357 struct select
2358 {
2359  template<bool cond, size_t true_clause, size_t false_clause>
2360  struct _if { enum { value = true_clause }; };
2361  template<size_t true_clause, size_t false_clause>
2362  struct _if<false, true_clause, false_clause> { enum { value = false_clause }; };
2363  enum {
2364  max_of_2 = _if<(a>b), a, b>::value,
2365  max = _if<(max_of_2>c), max_of_2, c>::value
2366  };
2367 };
2368 }//namespace util
2369 
2371 
2379 template<typename expression_type, size_t complexity>
2380 class vector_ref<expression_type, tag::expression<complexity>, orientation::row> :
2381  public vector_expression<typename expr_traits<expression_type>::value_type,
2382  vector_ref<expression_type, tag::expression<complexity>, orientation::row>,
2383  tag::expression<util::select<complexity, 1>::max - 1>,
2384  orientation::row
2385  >
2386 {
2387  typedef typename expr_traits<expression_type>::type expr_t;
2388 public:
2389  typedef typename expr_t::value_type value_type;
2390  typedef typename expr_t::const_reference const_reference;
2391 
2393  vector_ref(const vector_ref &a) : _ref(a._ref), _row(a._row)
2394  {}
2396  vector_ref(const expr_t &a, size_t row) : _ref(a), _row(row)
2397  {}
2399  const_reference operator()(size_t i) const
2400  { return _ref(_row, i); }
2402  const_reference operator[](size_t i) const
2403  { return _ref(_row, i); }
2405  size_t size() const
2406  { return _ref.cols(); }
2407 
2408 private:
2409  const expr_t &_ref;
2410  const size_t _row;
2411 
2413  vector_ref &operator=(const vector_ref&); //do not implement
2414 
2416  friend expr_t &get_vector_ref(vector_ref &a) { return a._ref; }
2418  friend const expr_t &get_vector_ref(const vector_ref &a) { return a._ref; }
2420  friend size_t get_vector_row(const vector_ref &a) { return a._row; }
2421 };
2422 
2424 
2425 
2426 template<typename expression_type, typename tag> inline
2427 typename util::non_zero_in_row<typename expr_traits<expression_type>::shape>::first_type
2428 first_non_zero(const vector_ref<expression_type, tag, orientation::row> &v)
2429 { return first_non_zero_in_row(get_vector_ref(v), get_vector_row(v)); }
2431 template<typename expression_type, typename tag> inline
2432 typename util::non_zero_in_row<typename expr_traits<expression_type>::shape>::last_type
2433 last_non_zero(const vector_ref<expression_type, tag, orientation::row> &v)
2434 { return last_non_zero_in_row(get_vector_ref(v), get_vector_row(v)); }
2436 
2438 
2439 template<typename expression_type, typename tag>
2440 struct iterator<vector_ref<expression_type, tag, orientation::row> >
2441 {
2443  static type begin(vector_ref<expression_type, tag, orientation::row> &v, size_t i = 0)
2444  { return row_iterator<typename expr_traits<expression_type>::type>::begin(get_vector_ref(v), get_vector_row(v), i); }
2445 };
2447 
2448 template<typename expression_type, typename tag>
2449 struct const_iterator<vector_ref<expression_type, tag, orientation::row> >
2450 {
2452  static type begin(const vector_ref<expression_type, tag, orientation::row> &v, size_t i = 0)
2453  { return row_const_iterator<typename expr_traits<expression_type>::type>::begin(get_vector_ref(v), get_vector_row(v), i); }
2454 };
2455 
2457 
2461 struct access_error : public std::logic_error
2462 {
2463  access_error() : std::logic_error("access violation (inaccessible element)") {}
2464  virtual ~access_error() throw() {}
2465 };
2466 
2467 namespace util {
2469 struct details_base
2470 {
2472  static size_t alloc_size(size_t size) { return (size*(size + 1))/2; }
2473 };
2474 //forward declaration
2475 template<typename shape> struct details;
2477 template<>
2478 struct details<lower_triangular> : public details_base
2479 {
2481  static size_t index(size_t row, size_t column, size_t/*size*/ = 0)
2482  { return details_base::alloc_size(row) + column; }
2484  template<typename storage>
2485  static typename storage::reference element(storage &p, size_t row, size_t column, size_t/*size*/)
2486  {
2487  if (row<column)
2488  throw access_error();
2489  return p[details::index(row, column)];
2490  }
2492  template<typename storage>
2493  static typename storage::const_reference element(const storage &p, size_t row, size_t column, size_t/*size*/)
2494  { return row>=column ? p[details::index(row, column)] : traits<typename storage::value_type>::zero; }
2496  template<typename storage, typename value_t, typename expr_t, typename tag>
2497  static void copy_values(storage &p, const shaped_expression<value_t, expr_t, tag, lower_triangular> &rhs, size_t size)
2498  {
2499  const expr_t &a = get_matrix(rhs);
2500  for (size_t i = 0, k = 0; i<size; ++i)
2501  for (size_t j = 0; j<=i; ++j, ++k)
2502  p[k] = a(i, j);
2503  return;
2504  }
2505 };
2507 template<>
2508 struct details<symmetric> : public details_base
2509 {
2511  static size_t index(size_t row, size_t column, size_t/*size*/ = 0)
2512  {
2513  typedef details<lower_triangular> det_lower_tr;
2514  return row>=column ? det_lower_tr::index(row, column) : det_lower_tr::index(column, row);
2515  }
2517  template<typename storage>
2518  static typename storage::reference element(storage &p, size_t row, size_t column, size_t/*size*/)
2519  { return p[details::index(row, column)]; }
2521  template<typename storage>
2522  static typename storage::const_reference element(const storage &p, size_t row, size_t column, size_t/*size*/)
2523  { return p[details::index(row, column)]; }
2525  template<typename storage, typename value_t, typename expr_t, typename tag>
2526  static void copy_values(storage &p, const shaped_expression<value_t, expr_t, tag, symmetric> &rhs, size_t size)
2527  {
2528  const expr_t &a = get_matrix(rhs);
2529  for (size_t i = 0, k = 0; i<size; ++i)
2530  for (size_t j = 0; j<=i; ++j, ++k)
2531  p[k] = a(i, j);
2532  return;
2533  }
2534 };
2536 template<>
2537 struct details<upper_triangular> : public details_base
2538 {
2540  static size_t index(size_t row, size_t column, size_t size)
2541  { return (row*(2*size - row - 1))/2 + column; } //returns n'th element in triangular matrix stored row-by-row
2543  template<typename storage>
2544  static typename storage::reference element(storage &p, size_t row, size_t column, size_t size)
2545  {
2546  if (row>column)
2547  throw access_error();
2548  return p[details::index(row, column, size)];
2549  }
2551  template<typename storage>
2552  static typename storage::const_reference element(const storage &p, size_t row, size_t column, size_t size)
2553  { return row<=column ? p[details::index(row, column, size)] : traits<typename storage::value_type>::zero; }
2555  template<typename storage, typename value_t, typename expr_t, typename tag>
2556  static void copy_values(storage &p, const shaped_expression<value_t, expr_t, tag, upper_triangular> &rhs, size_t size)
2557  {
2558  const expr_t &a = get_matrix(rhs);
2559  for (size_t i = 0, k = 0; i<size; ++i)
2560  for (size_t j = i; j<size; ++j, ++k)
2561  p[k] = a(i, j);
2562  return;
2563  }
2564 };
2565 }//namespace util
2566 
2567 //forward declaration
2568 template<typename value_t, typename shape = rectangular> class matrix;
2569 
2571 
2623 template<typename value_t, typename shape>
2624 class matrix : public shaped_expression<value_t, matrix<value_t, shape>, tag::storage, shape>
2625 {
2627 public:
2628  typedef value_t value_type;
2629  typedef typename util::sequence<value_type>::reference reference;
2630  typedef typename util::sequence<value_type>::const_reference const_reference;
2632  typedef vector_ref<expression_type, tag::expression<0>, orientation::row> const_row_ref;
2633 
2635  matrix() : _p(), _size(0)
2636  {}
2638  matrix(const matrix &a) : _p(), _size(0)
2639  { this->operator=(a); }
2641  matrix(temporary<matrix> &a) : _p(), _size(0)
2642  { this->swap(a); }
2644  template<typename expr_t, typename tag>
2646  { this->assign(a); }
2648  explicit matrix(size_t size) : _p(), _size(0)
2649  { this->resize(size); }
2651  matrix(size_t size, const_reference value) : _p(), _size(0)
2652  { this->resize(size, value); }
2655  {}
2658  {
2659  this->resize(a._size);
2660  _p.copy(a._p, util::details<shape>::alloc_size(_size));
2661  return *this;
2662  }
2664  template<typename expr_t, typename tag>
2666  {
2667  matrix(a).swap(*this);
2668  return *this;
2669  }
2672  { this->swap(a); return *this; }
2674 
2685  reference operator()(size_t row, size_t column)
2686  {
2687  ASSERT(row<this->rows() && column<this->cols());
2688  return util::details<shape>::element(_p, row, column, _size);
2689  }
2691  const_reference operator()(size_t row, size_t column) const
2692  {
2693  ASSERT(row<this->rows() && column<this->cols());
2694  return util::details<shape>::element(_p, row, column, _size);
2695  }
2697  row_ref operator()(size_t row)
2698  { ASSERT(row<this->rows()); return row_ref(*this, row); }
2700  const_row_ref operator()(size_t row) const
2701  { ASSERT(row<this->rows()); return const_row_ref(*this, row); }
2703  row_ref operator[](size_t row)
2704  { ASSERT(row<this->rows()); return row_ref(*this, row); }
2706  const_row_ref operator[](size_t row) const
2707  { ASSERT(row<this->rows()); return const row_ref(*this, row); }
2709 
2710  template<typename expr_t, typename tag>
2712  {
2713  const expr_t &a = get_matrix(rhs);
2714  ASSERT(a.rows()==a.cols()); //equal by definition
2715  this->resize(a.rows());
2716  util::details<shape>::copy_values(_p, rhs, _size);
2717  return;
2718  }
2720 
2722  void resize(size_t size)
2723  {
2724  if (size!=_size)
2725  {
2726  _p.realloc(util::details<shape>::alloc_size(size));
2727  _size = size;
2728  }
2729  return;
2730  }
2732 
2734  void resize(size_t size, const_reference value)
2735  {
2736  this->resize(size);
2737  _p.fill(value, util::details<shape>::alloc_size(_size));
2738  return;
2739  }
2741 
2742  void swap(matrix &a)
2743  {
2744  using std::swap;
2745  swap(_p, a._p);
2746  swap(_size, a._size);
2747  return;
2748  }
2750  size_t rows() const
2751  { return _size; }
2753  size_t cols() const
2754  { return _size; }
2755 
2756 private:
2757  util::sequence<value_type> _p;
2758  size_t _size;
2759 };
2760 
2761 namespace util {
2763 struct base_symmetric_matrix_iterator
2764 {
2766  const size_t row;
2768  size_t col;
2770  base_symmetric_matrix_iterator(size_t r, size_t c) : row(r), col(c) {}
2772  template<typename ptr_t>
2773  void advance(ptr_t &ptr)
2774  {
2775  ptr += size_t(row<=col)*col + 1; ++col;
2776  return;
2777  }
2778 private:
2780  base_symmetric_matrix_iterator &operator=(const base_symmetric_matrix_iterator&);
2781 };
2783 template<typename value_t, typename iterator_type>
2784 struct symmetric_matrix_iterator : public base_symmetric_matrix_iterator
2785 {
2789  symmetric_matrix_iterator(matrix<value_t, symmetric> &m, size_t r, size_t c) :
2790  base_symmetric_matrix_iterator(r, c), ptr(&m(r, c))
2791  {}
2793  typename matrix<value_t, symmetric>::reference operator*() { return *ptr; }
2795  iterator_type &operator++() { this->advance(ptr); return *static_cast<iterator_type*>(this); }
2796 };
2798 template<typename value_t, typename iterator_type>
2799 struct symmetric_matrix_const_iterator : public base_symmetric_matrix_iterator
2800 {
2802  const typename matrix<value_t, symmetric>::value_type *ptr;
2804  symmetric_matrix_const_iterator(const matrix<value_t, symmetric> &m, size_t r, size_t c) :
2805  base_symmetric_matrix_iterator(r, c), ptr(&m(r, c))
2806  {}
2808  typename matrix<value_t, symmetric>::const_reference operator*() const { return *ptr; }
2810  iterator_type &operator++() { this->advance(ptr); return *static_cast<iterator_type*>(this); }
2811 };
2812 }//namespace util
2813 
2815 template<typename value_t>
2816 struct row_iterator<matrix<value_t, symmetric> >
2817 {
2819  struct type : public util::symmetric_matrix_iterator<value_t, type>
2820  {
2822  type(matrix<value_t> &m, size_t r, size_t c) : util::symmetric_matrix_iterator(m, r, c) {}
2823  };
2824  static type begin(matrix<value_t, symmetric> &m, size_t r, size_t c) { return type(m, r, c); }
2825 };
2827 template<typename value_t>
2828 struct row_const_iterator<matrix<value_t, symmetric> >
2829 {
2831  struct type : public util::symmetric_matrix_const_iterator<value_t, type>
2832  {
2834  type(const matrix<value_t, symmetric> &m, size_t r, size_t c) : symmetric_matrix_const_iterator(m, r, c) {}
2835  };
2836  static type begin(const matrix<value_t, symmetric> &m, size_t r, size_t c) { return type(m, r, c); }
2837 };
2838 
2840 template<typename value_t>
2841 struct column_iterator<matrix<value_t, symmetric> >
2842 {
2844  struct type : public util::symmetric_matrix_iterator<value_t, type>
2845  {
2847  type(matrix<value_t, symmetric> &m, size_t c, size_t r) : util::symmetric_matrix_iterator(m, c, r) {}
2848  };
2849  static type begin(matrix<value_t, symmetric> &m, size_t c, size_t r) { return type(m, c, r); }
2850 };
2852 template<typename value_t>
2853 struct column_const_iterator<matrix<value_t, symmetric> >
2854 {
2856  struct type : public util::symmetric_matrix_const_iterator<value_t, type>
2857  {
2859  type(const matrix<value_t, symmetric> &m, size_t c, size_t r) : symmetric_matrix_const_iterator(m, c, r) {}
2860  };
2861  static type begin(const matrix<value_t, symmetric> &m, size_t c, size_t r) { return type(m, c, r); }
2862 };
2863 
2864 //forward declaration
2865 template<typename expression1, typename expression2> class product;
2866 
2868 
2879 template<typename value_t>
2880 class matrix<value_t, rectangular> :
2881  public matrix_expression<value_t, matrix<value_t, rectangular>, tag::storage>
2882 {
2884 public:
2885  typedef value_t value_type;
2886  typedef typename util::sequence<value_type>::reference reference;
2887  typedef typename util::sequence<value_type>::const_reference const_reference;
2889  typedef vector_ref<expression_type, tag::expression<0>, orientation::row> const_row_ref;
2890 
2892 
2893  matrix() : _p(), _rows(0), _cols(0)
2894  {}
2896  matrix(const matrix &a) : _p(), _rows(0), _cols(0)
2897  { operator=(a); }
2899  matrix(temporary<matrix> &a) : _p(), _rows(0), _cols(0)
2900  { this->swap(a); }
2902  template<typename expr_t, typename tag>
2903  matrix(const matrix_expression<value_type, expr_t, tag> &a) : _p(), _rows(0), _cols(0)
2904  { this->assign(a); }
2906  matrix(size_t nrows, size_t ncols) : _p(), _rows(0), _cols(0)
2907  { this->resize(nrows, ncols); }
2909  matrix(size_t nrows, size_t ncols, const_reference value) : _p(), _rows(0), _cols(0)
2910  { this->resize(nrows, ncols, value); }
2913  {}
2916  {
2917  this->resize(a._rows, a._cols);
2918  _p.copy(a._p, _rows*_cols);
2919  return *this;
2920  }
2922  template<typename expr_t, typename tag>
2924  {
2925  matrix(rhs).swap(*this);
2926  return *this;
2927  }
2930  { this->swap(a); return *this; }
2932  reference operator()(size_t row, size_t column)
2933  { ASSERT(row<this->rows() && column<this->cols()); return _p[row*_cols + column]; }
2935  const_reference operator()(size_t row, size_t column) const
2936  { ASSERT(row<this->rows() && column<this->cols()); return _p[row*_cols + column]; }
2938  row_ref operator()(size_t row)
2939  { ASSERT(row<this->rows()); return row_ref(*this, row); }
2941  const_row_ref operator()(size_t row) const
2942  { ASSERT(row<this->rows()); return const_row_ref(*this, row); }
2944  row_ref operator[](size_t row)
2945  { ASSERT(row<this->rows()); return row_ref(*this, row); }
2947  const_row_ref operator[](size_t row) const
2948  { ASSERT(row<this->rows()); return const_row_ref(*this, row); }
2950 
2966  template<typename expr_t, typename tag>
2968  {
2969  const expr_t &a = get_matrix(rhs);
2970  this->resize(a.rows(), a.cols());
2971  for (size_t i = 0, k = 0; i<_rows; ++i)
2972  for (size_t j = 0; j<_cols; ++j, ++k)
2973  _p[k] = a(i, j);
2974  return;
2975  }
2977  template<typename expression1, typename expression2, typename tag>
2980 
2982  void resize(size_t nrows, size_t ncols)
2983  {
2984  const size_t size = nrows*ncols;
2985  if (size==0)
2986  nrows = ncols = 0;
2987  if (size!=_rows*_cols)
2988  {
2989  _p.realloc(size);
2990  _rows = nrows;
2991  _cols = ncols;
2992  }
2993  return;
2994  }
2996 
2998  void resize(size_t nrows, size_t ncols, const_reference value)
2999  {
3000  this->resize(nrows, ncols);
3001  _p.fill(value, _rows*_cols);
3002  return;
3003  }
3005 
3006  void swap(matrix &a)
3007  {
3008  using std::swap;
3009  swap(_p, a._p);
3010  swap(_rows, a._rows);
3011  swap(_cols, a._cols);
3012  return;
3013  }
3015  size_t rows() const
3016  { return _rows; }
3018  size_t cols() const
3019  { return _cols; }
3020 
3021 private:
3022  util::sequence<value_type> _p;
3023  size_t _rows, _cols;
3024 };
3025 
3027 template<typename value_t>
3028 struct row_iterator<matrix<value_t> >
3029 {
3031  struct type
3032  {
3036  type(matrix<value_t> &m, size_t r, size_t c) : ptr(&m(r, c)) {}
3038  type &operator++() { ++ptr; return *this; }
3040  typename matrix<value_t>::reference operator*() { return *ptr; }
3041  private:
3043  type &operator=(const type&);
3044  };
3045  static type begin(matrix<value_t> &m, size_t r, size_t c) { return type(m, r, c); }
3046 };
3048 template<typename value_t>
3049 struct row_const_iterator<matrix<value_t> >
3050 {
3052  struct type
3053  {
3057  type(const matrix<value_t> &m, size_t r, size_t c) : ptr(&m(r, c)) {}
3059  type &operator++() { ++ptr; return *this; }
3061  typename matrix<value_t>::const_reference operator*() const { return *ptr; }
3062  private:
3064  type &operator=(const type&);
3065  };
3066  static type begin(const matrix<value_t> &m, size_t r, size_t c) { return type(m, r, c); }
3067 };
3069 template<typename value_t>
3070 struct column_iterator<matrix<value_t> >
3071 {
3073  struct type
3074  {
3078  const size_t cols;
3080  type(matrix<value_t> &m, size_t c, size_t r) : ptr(&m(r, c)), cols(m.cols()) {}
3082  type &operator++() { ptr += cols; return *this; }
3084  typename matrix<value_t>::reference operator*() { return *ptr; }
3085  private:
3087  type &operator=(const type&);
3088  };
3089  static type begin(matrix<value_t> &m, size_t c, size_t r) { return type(m, c, r); }
3090 };
3092 template<typename value_t>
3093 struct column_const_iterator<matrix<value_t> >
3094 {
3096  struct type
3097  {
3101  const size_t cols;
3103  type(const matrix<value_t> &m, size_t c, size_t r) : ptr(&m(r, c)), cols(m.cols()) {}
3105  type &operator++() { ptr += cols; return *this; }
3107  typename matrix<value_t>::const_reference operator*() const { return *ptr; }
3108  private:
3110  type &operator=(const type&);
3111  };
3112  static type begin(const matrix<value_t> &m, size_t c, size_t r) { return type(m, c, r); }
3113 };
3114 
3116 
3127 template<typename value_t>
3128 class vector : public vector_expression<value_t, vector<value_t>, tag::storage, orientation::column>
3129 {
3130 public:
3131  typedef value_t value_type;
3132  typedef typename util::sequence<value_type>::reference reference;
3133  typedef typename util::sequence<value_type>::const_reference const_reference;
3134 
3136 
3137  vector() : _p(), _size(0)
3138  {}
3140  vector(const vector &a) : _p(), _size(0)
3141  { operator=(a); }
3143  vector(temporary<vector> &a) : _p(), _size(0)
3144  { this->swap(a); }
3146  template<typename expr_t, typename tag>
3148  { this->assign(a); }
3150  explicit vector(size_t size) : _p(), _size(0)
3151  { this->resize(size); }
3153  vector(size_t size, const_reference value) : _p(), _size(0)
3154  { this->resize(size, value); }
3157  {}
3160  {
3161  this->resize(a._size);
3162  _p.copy(a._p, _size);
3163  return *this;
3164  }
3166  template<typename expr_t, typename tag>
3168  {
3169  vector<value_type>(rhs).swap(*this);
3170  return *this;
3171  }
3174  { this->swap(a); return *this; }
3177  { ASSERT(i<this->size()); return _p[i]; }
3179  const_reference operator()(size_t i) const
3180  { ASSERT(i<this->size()); return _p[i]; }
3183  { ASSERT(i<this->size()); return _p[i]; }
3185  const_reference operator[](size_t i) const
3186  { ASSERT(i<this->size()); return _p[i]; }
3188 
3204  template<typename expr_t, typename tag>
3206  {
3207  const expr_t &a = get_vector(rhs);
3208  this->resize(a.size());
3209  for (size_t i = 0; i<_size; ++i)
3210  _p[i] = a(i);
3211  return;
3212  }
3214 
3215  void resize(size_t size)
3216  {
3217  if (size!=_size)
3218  {
3219  _p.realloc(size);
3220  _size = size;
3221  }
3222  return;
3223  }
3225 
3226  void resize(size_t size, const_reference value)
3227  {
3228  this->resize(size);
3229  _p.fill(value, _size);
3230  return;
3231  }
3233 
3234  void swap(vector &a)
3235  {
3236  using std::swap;
3237  swap(_p, a._p);
3238  swap(_size, a._size);
3239  return;
3240  }
3242  size_t size() const
3243  { return _size; }
3244 
3245 private:
3246  util::sequence<value_type> _p;
3247  size_t _size;
3248 };
3249 
3251 
3252 
3253 
3262 template<typename value_t, typename expr_t> inline
3265 { get_matrix(a).swap(get_matrix(b)); return; }
3266 
3268 
3277 template<typename value_t, typename expr_t, typename shape> inline
3280 { get_matrix(a).swap(get_matrix(b)); return; }
3282 
3284 
3288 struct reshape_error : public std::logic_error
3289 {
3290  reshape_error() : std::logic_error("matrix must be square (of size strictly n by n)") {}
3291  virtual ~reshape_error() throw() {}
3292 };
3293 
3295 
3299 struct size_error : public std::invalid_argument
3300 {
3301  explicit size_error(const std::string &msg) : std::invalid_argument(msg) {}
3302  virtual ~size_error() throw() {}
3303 };
3304 
3306 
3323 template<typename value_t, typename expr_t, typename tag, typename shape>
3325  public shaped_expression<value_t, expr_t, tag, shape>
3326 {};
3327 
3330 template<typename value_t, typename expr_t, typename tag>
3331 struct base_matrix_expression<value_t, expr_t, tag, rectangular> :
3332  public matrix_expression<value_t, expr_t, tag>
3333 {};
3334 
3335 namespace util {
3336 template<typename side> struct choose;
3338 template<>
3339 struct choose<upper_triangular>
3340 {
3342  template<typename expr_t>
3343  static typename expr_t::reference element(expr_t &a, size_t row, size_t col)
3344  { return a(row, col); }
3346  template<typename expr_t>
3347  static typename expr_t::const_reference element(const expr_t &a, size_t row, size_t col)
3348  { return a(row, col); }
3349 };
3351 template<>
3352 struct choose<lower_triangular>
3353 {
3355  template<typename expr_t>
3356  static typename expr_t::reference element(expr_t &a, size_t row, size_t col)
3357  { return a(col, row); }
3359  template<typename expr_t>
3360  static typename expr_t::const_reference element(const expr_t &a, size_t row, size_t col)
3361  { return a(col, row); }
3362 };
3364 template<typename shape, typename side = upper_triangular>
3365 struct translate_access
3366 {
3368  template<typename expr_t>
3369  static typename expr_t::reference get(expr_t &a, size_t row, size_t col)
3370  { return choose<side>::element(a, row, col); }
3372  template<typename expr_t>
3373  static typename expr_t::const_reference get(const expr_t &a, size_t row, size_t col)
3374  { return choose<side>::element(a, row, col); }
3375 };
3377 //struct minmax
3378 //{
3379 // const size_t x, y, mask;
3380 // minmax(size_t a, size_t b) : x(a), y(b), mask((x ^ y) & -(x < y))
3381 // { ASSERT(std::min(a, b)==min() && std::max(a, b)==max()); }
3382 // size_t min() const { return y^mask; }
3383 // size_t max() const { return x^mask; }
3384 //};
3385 struct minmax
3386 {
3387  size_t sup, inf;
3388  minmax(size_t a, size_t b)
3389  {
3390  if (a<b)
3391  {
3392  sup = a;
3393  inf = b;
3394  }
3395  else
3396  {
3397  sup = b;
3398  inf = a;
3399  }
3400  ASSERT(std::min(a, b)==min() && std::max(a, b)==max());
3401  }
3402  size_t min() const { return sup; }
3403  size_t max() const { return inf; }
3404 };
3406 template<typename side>
3407 struct translate_access<symmetric, side>
3408 {
3410  template<typename expr_t>
3411  static typename expr_t::reference get(expr_t &a, size_t row, size_t col)
3412  {
3413  //const size_t
3414  // r = std::min(row, col),
3415  // c = std::max(row, col);
3416  //return choose<side>::element(a, r, c);
3417  const minmax i(row, col);
3418  return choose<side>::element(a, i.min(), i.max());
3419  }
3421  template<typename expr_t>
3422  static typename expr_t::const_reference get(const expr_t &a, size_t row, size_t col)
3423  {
3424  //const size_t
3425  // r = std::min(row, col),
3426  // c = std::max(row, col);
3427  //return choose<side>::element(a, r, c);
3428  const minmax i(row, col);
3429  return choose<side>::element(a, i.min(), i.max());
3430  }
3431 };
3433 template<typename side>
3434 struct translate_access<upper_triangular, side>
3435 {
3437 
3438  template<typename expr_t>
3439  static typename expr_t::reference get(expr_t &a, size_t row, size_t col)
3440  {
3441  if (row<=col)
3442  return choose<side>::element(a, row, col);
3443  throw access_error();
3444  }
3446  template<typename expr_t>
3447  static typename expr_t::const_reference get(const expr_t &a, size_t row, size_t col)
3448  { return row<=col ? choose<side>::element(a, row, col) : traits<typename expr_t::value_type>::zero; }
3449 };
3451 template<typename side>
3452 struct translate_access<lower_triangular, side>
3453 {
3455 
3456  template<typename expr_t>
3457  static typename expr_t::reference get(expr_t &a, size_t row, size_t col)
3458  {
3459  if (row>=col)
3460  return choose<side>::element(a, col, row);
3461  throw access_error();
3462  }
3464  template<typename expr_t>
3465  static typename expr_t::const_reference get(const expr_t &a, size_t row, size_t col)
3466  { return row>=col ? choose<side>::element(a, col, row) : traits<typename expr_t::value_type>::zero; }
3467 };
3469 template<typename expr_t>
3470 struct const_ref
3471 {
3472  const expr_t &ref;
3473 
3475  explicit const_ref(const expr_t &a) : ref(a)
3476  {}
3478  operator const expr_t&() { return ref; }
3479 
3480 private:
3482  const_ref &operator=(const const_ref&); //do not define
3483 };
3485 template<typename expr_t> inline
3486 const_ref<expr_t> make_const_ref(const expr_t &a)
3487 { return const_ref<expr_t>(a); }
3488 }//namespace util
3489 
3491 
3496 template<typename target_shape>
3498 {
3500 
3503  template<typename value_t, typename expr_t, typename tag>
3505  {
3506  const expr_t &m = get_matrix(a);
3507  if (m.rows()!=m.cols()) //matrix must be square!
3508  throw reshape_error();
3509  return true;
3510  }
3511 };
3512 
3515 template<>
3517 {
3519 
3522  template<typename value_t, typename expr_t, typename tag>
3524  { return true; }
3525 };
3526 
3581 template<typename expression_type, typename target_shape, typename side = upper_triangular> class reshaped;
3582 
3585 template<typename value_t, typename expr_t, typename tag_t, typename target_shape>
3586 class reshaped<matrix_expression<value_t, expr_t, tag_t>, target_shape, upper_triangular> :
3587  public base_matrix_expression<
3588  typename expr_t::value_type,
3589  reshaped<matrix_expression<value_t, expr_t, tag_t>, target_shape, upper_triangular>,
3590  tag::expression<util::tag_complexity<tag_t>::value>,
3591  target_shape
3592  >
3593 {
3594 public:
3595  typedef typename expr_t::value_type value_type;
3596  //typedef typename expr_t::reference reference; ///<Type of reference to element.
3597  typedef typename expr_t::const_reference const_reference;
3598 
3600  reshaped(const util::const_ref<expr_t> &a) : _ref(a.ref)
3601  { //assertion is needed if user tries to construct reshaped object directly
3603  }
3605  const_reference operator()(size_t row, size_t col) const
3606  { return util::translate_access<target_shape, upper_triangular>::get(_ref, row, col); }
3608  size_t rows() const
3609  { return _ref.rows(); }
3611  size_t cols() const
3612  { return _ref.cols(); }
3613 private:
3614  const expr_t &_ref;
3615 
3617  reshaped(const reshaped&);
3618  //Inaccessible assignment operator.
3619  reshaped &operator=(const reshaped&);
3620 };
3621 
3624 template<typename value_t, typename expr_t, typename tag_t, typename target_shape>
3625 class reshaped<matrix_expression<value_t, expr_t, tag_t>, target_shape, lower_triangular> :
3626  public base_matrix_expression<
3627  typename expr_t::value_type,
3628  reshaped<matrix_expression<value_t, expr_t, tag_t>, target_shape, lower_triangular>,
3629  tag::expression<util::tag_complexity<tag_t>::value>,
3630  target_shape
3631  >
3632 {
3633 public:
3634  typedef typename expr_t::value_type value_type;
3635  //typedef typename expr_t::reference reference; ///<Type of reference to element.
3636  typedef typename expr_t::const_reference const_reference;
3637 
3639  reshaped(const util::const_ref<expr_t> &a) : _ref(a.ref)
3640  { //assertion is needed if user tries to construct reshaped object directly
3642  }
3644  const_reference operator()(size_t row, size_t col) const
3645  { return util::translate_access<target_shape, lower_triangular>::get(_ref, row, col); }
3647  size_t rows() const
3648  { return _ref.rows(); }
3650  size_t cols() const
3651  { return _ref.cols(); }
3652 private:
3653  const expr_t &_ref;
3654 
3656  reshaped(const reshaped&);
3657  //Inaccessible assignment operator.
3658  reshaped &operator=(const reshaped&);
3659 };
3660 
3661 namespace util {
3662 template<typename expr_t, typename target_shape, typename side = upper_triangular> struct reshape_return;
3664 template<typename value_t, typename expr_t, typename tag, typename target_shape, typename side>
3665 struct reshape_return<matrix_expression<value_t, expr_t, tag>, target_shape, side>
3666 {
3668 };
3670 template<typename value_t, typename expr_t, typename tag, typename side>
3671 struct reshape_return<matrix_expression<value_t, expr_t, tag>, rectangular, side>
3672 {
3673  typedef const expr_t &type;
3674 };
3675 }//namespace util
3676 
3678 
3679 
3680 
3716 template<typename target_shape, typename value_t, typename expr_t, typename tag> inline
3717 typename util::reshape_return<matrix_expression<value_t, expr_t, tag>, target_shape>::type
3719 {
3721  return util::make_const_ref(get_matrix(a));
3722 }
3723 
3724 //reshape<target_shape, side>() form overload
3725 template<typename target_shape, typename side, typename value_t, typename expr_t, typename tag> inline
3726 typename util::reshape_return<matrix_expression<value_t, expr_t, tag>, target_shape, side>::type
3728 {
3730  return util::make_const_ref(get_matrix(a));
3731 }
3733 
3734 namespace util {
3735 template<typename type1, typename type2> struct same_types;
3737 template<typename t>
3738 struct same_types<t, t>
3739 {
3740  typedef t type;
3741 };
3742 }//namespace util
3743 
3745 namespace dummy {
3747 template<typename value_t> inline
3748 const value_t &conj(const value_t &a) { return a; }
3750 template<typename type>
3752 {
3754  typedef type result_type;
3756  static const result_type &op(const type &a) { return a; }
3757 };
3758 }
3759 
3761 namespace op {
3763 template<typename type>
3764 struct plus
3765 {
3767  typedef type result_type;
3769  static result_type op(const type &a) { return +a; }
3770 };
3772 template<typename type>
3773 struct minus
3774 {
3776  typedef type result_type;
3778  static result_type op(const type &a) { return -a; }
3779 };
3781 template<typename type>
3782 struct conj
3783 {
3785  typedef type result_type;
3787  static result_type op(const type &a) { using dummy::conj; return conj(a); }
3788 };
3790 template<typename type1, typename type2>
3791 struct add
3792 {
3794  typedef typename util::same_types<type1, type2>::type result_type;
3796  static result_type op(const type1 &a, const type2 &b) { return a + b; }
3797 };
3799 template<typename type1, typename type2>
3800 struct sub
3801 {
3803  typedef typename util::same_types<type1, type2>::type result_type;
3805  static result_type op(const type1 &a, const type2 &b) { return a - b; }
3806 };
3808 template<typename type1, typename type2>
3809 struct mul
3810 {
3812  typedef typename util::same_types<type1, type2>::type result_type;
3814  static result_type op(const type1 &a, const type2 &b) { return a*b; }
3815 };
3817 template<typename type1, typename type2>
3818 struct div
3819 {
3821  typedef typename util::same_types<type1, type2>::type result_type;
3823  static result_type op(const type1 &a, const type2 &b) { return a/b; }
3824 };
3825 }//namespace op
3826 
3828 
3830 template<typename expression_type, template<typename> class op>
3831 class unary :
3832  public base_matrix_expression<
3833  typename expr_traits<expression_type>::type::value_type,
3834  unary<expression_type, op>, //by convention this expression itself has constant complexity
3835  tag::expression<expr_traits<expression_type>::complexity>,
3836  typename expr_traits<expression_type>::shape
3837  >
3838 {
3839  typedef typename expr_traits<expression_type>::type expr_t;
3840 public:
3841  typedef typename expr_t::value_type value_type;
3842  typedef const value_type const_reference;
3843 
3845  unary(const expr_t &a) : _ref(a)
3846  {}
3848  const_reference operator()(size_t row, size_t col) const
3849  { return op<value_type>::op(_ref(row, col)); }
3851  size_t rows() const
3852  { return _ref.rows(); }
3854  size_t cols() const
3855  { return _ref.cols(); }
3856 
3857 private:
3858  const expr_t &_ref;
3859 
3861  unary(const unary&); //do not implement
3863  unary &operator=(const unary&); //do not implement
3864 };
3865 
3867 
3868 
3869 
3874 template<typename value_t, typename expr_t, typename tag> inline
3875 const unary<matrix_expression<value_t, expr_t, tag>, op::plus>
3877 { return get_matrix(a); }
3878 
3880 
3882 template<typename value_t, typename expr_t, typename tag, typename shape> inline
3883 const unary<shaped_expression<value_t, expr_t, tag, shape>, op::plus>
3885 { return get_matrix(a); }
3886 
3888 
3893 template<typename value_t, typename expr_t, typename tag> inline
3894 const unary<matrix_expression<value_t, expr_t, tag>, op::minus>
3896 { return get_matrix(a); }
3897 
3899 
3901 template<typename value_t, typename expr_t, typename tag, typename shape> inline
3902 const unary<shaped_expression<value_t, expr_t, tag, shape>, op::minus>
3904 { return get_matrix(a); }
3905 
3907 
3919 template<typename value_t, typename expr_t, typename tag> inline
3920 const unary<matrix_expression<value_t, expr_t, tag>, op::conj>
3922 { return get_matrix(a); }
3923 
3925 
3927 template<typename value_t, typename expr_t, typename tag, typename shape> inline
3928 const unary<shaped_expression<value_t, expr_t, tag, shape>, op::conj>
3930 { return get_matrix(a); }
3932 
3934 
3936 template<typename expression_type, template<typename> class op = dummy::operation>
3937 class transposed :
3938  public base_matrix_expression<
3939  typename expr_traits<expression_type>::type::value_type,
3940  transposed<expression_type, op>, //by convention this expression has constant complexity
3941  tag::expression<expr_traits<expression_type>::complexity>,
3942  typename expr_traits<expression_type>::shape
3943  >
3944 {
3945  typedef typename expr_traits<expression_type>::type expr_t;
3946 public:
3947  typedef typename expr_t::value_type value_type;
3948  typedef typename op<value_type>::result_type const_reference;
3949 
3951  transposed(const expr_t &a) : _ref(a)
3952  {}
3954  const_reference operator()(size_t row, size_t col) const
3955  { return op<value_type>::op(_ref(col, row)); }
3957  size_t rows() const
3958  { return _ref.cols(); }
3960  size_t cols() const
3961  { return _ref.rows(); }
3962 
3963 private:
3964  const expr_t &_ref;
3965 
3967  transposed(const transposed&); //do not implement
3969  transposed &operator=(const transposed&); //do not implement
3970 };
3971 
3973 
3974 
3975 
3980 template<typename value_t, typename expr_t, typename tag> inline
3981 const transposed<matrix_expression<value_t, expr_t, tag> >
3983 { return get_matrix(a); }
3984 
3986 
3988 template<typename value_t, typename expr_t, typename tag, typename shape> inline
3989 const transposed<shaped_expression<value_t, expr_t, tag, shape> >
3991 { return get_matrix(a); }
3992 
3994 
4001 template<typename value_t, typename expr_t, typename tag> inline
4003 { return get_matrix(a); }
4004 
4006 
4013 template<typename value_t, typename expr_t, typename tag> inline
4014 const reshaped<shaped_expression<value_t, expr_t, tag, lower_triangular>, upper_triangular, lower_triangular>
4016 { return get_matrix(a); }
4017 
4019 
4026 template<typename value_t, typename expr_t, typename tag> inline
4027 const reshaped<shaped_expression<value_t, expr_t, tag, upper_triangular>, lower_triangular, upper_triangular>
4029 { return get_matrix(a); }
4031 
4033 
4035 template<typename expression_type>
4036 class scaled :
4037  public base_matrix_expression<
4038  typename expr_traits<expression_type>::type::value_type,
4039  scaled<expression_type>,
4040  tag::expression<util::select<expr_traits<expression_type>::complexity, 2>::max>,
4041  typename expr_traits<expression_type>::shape
4042  >
4043 {
4044  typedef typename expr_traits<expression_type>::type expr_t;
4045 public:
4046  typedef typename expr_t::value_type value_type;
4047  typedef const value_type const_reference;
4048 
4050  scaled(const scaled &a) : _ref(a._ref), _scale(a._scale)
4051  {}
4053  scaled(const expr_t &a, const_reference s) : _ref(a), _scale(s)
4054  {}
4056  const_reference operator()(size_t row, size_t col) const
4057  { return _ref(row, col)*_scale; }
4059  size_t rows() const
4060  { return _ref.rows(); }
4062  size_t cols() const
4063  { return _ref.cols(); }
4064 
4065 private:
4066  const expr_t &_ref;
4067  const value_type _scale;
4068 
4070  scaled &operator=(const scaled&); //do not implement
4071 };
4072 
4074 
4075 
4076 
4079 template<typename value_t, typename expr_t, typename tag> inline
4080 const scaled<matrix_expression<value_t, expr_t, tag> >
4081 operator*(const matrix_expression<value_t, expr_t, tag> &a, const typename expr_t::value_type &s)
4083 
4085 
4087 template<typename value_t, typename expr_t, typename tag, typename shape> inline
4088 const scaled<shaped_expression<value_t, expr_t, tag, shape> >
4089 operator*(const shaped_expression<value_t, expr_t, tag, shape> &a, const typename expr_t::value_type &s)
4091 
4093 
4096 template<typename value_t, typename expr_t, typename tag> inline
4097 const scaled<matrix_expression<value_t, expr_t, tag> >
4098 operator*(const typename expr_t::value_type &s, const matrix_expression<value_t, expr_t, tag> &a)
4100 
4102 
4104 template<typename value_t, typename expr_t, typename tag, typename shape> inline
4105 const scaled<shaped_expression<value_t, expr_t, tag, shape> >
4106 operator*(const typename expr_t::value_type &s, const shaped_expression<value_t, expr_t, tag, shape> &a)
4109 
4110 namespace util {
4112 template<typename shape1, typename shape2>
4113 struct binary_shapes
4114 {
4115  typedef rectangular resulting_shape;
4116 };
4118 template<typename shape>
4119 struct binary_shapes<shape, shape>
4120 {
4121  typedef shape resulting_shape;
4122 };
4124 template<typename expr1, typename expr2>
4126 {
4127  const expr1 &first;
4128  const expr2 &second;
4129 
4131  pair_const_ref(const expr1 &a, const expr2 &b) : first(a), second(b)
4132  {}
4133 
4134 private:
4136  pair_const_ref &operator=(const pair_const_ref&); //do not define
4137 };
4139 template<typename expr1, typename expr2>
4140 pair_const_ref<expr1, expr2> make_pair_const_ref(const expr1 &a, const expr2 &b)
4141 { return pair_const_ref<expr1, expr2>(a, b); }
4142 }//namespace util
4143 
4145 
4147 template<typename expression1, typename expression2, template<typename, typename> class op>
4148 class binary :
4149  public base_matrix_expression<
4150  typename util::same_types<typename expr_traits<expression1>::value_type,
4151  typename expr_traits<expression2>::value_type>::type,
4152  binary<expression1, expression2, op>,
4153  tag::expression<util::select<expr_traits<expression1>::complexity,
4154  expr_traits<expression2>::complexity,
4155  2>::max>,
4156  typename util::binary_shapes<typename expr_traits<expression1>::shape,
4157  typename expr_traits<expression2>::shape>::resulting_shape
4158  >
4159 {
4160  typedef typename expr_traits<expression1>::type expr1;
4161  typedef typename expr_traits<expression2>::type expr2;
4162 public:
4163  typedef typename op<typename expr1::value_type, typename expr2::value_type>::result_type value_type;
4164  typedef const value_type const_reference;
4165 
4168  _left(p.first), _right(p.second)
4169  {
4170  if (_left.rows()!=_right.rows() || _left.cols()!=_right.cols())
4171  throw size_error("sizes of matrices must be equal");
4172  }
4174  const_reference operator()(size_t row, size_t col) const
4175  { return op<typename expr1::value_type, typename expr2::value_type>::op(_left(row, col), _right(row, col)); }
4177  size_t rows() const
4178  {
4179  ASSERT(_left.rows()==_right.rows());
4180  return _left.rows();
4181  }
4183  size_t cols() const
4184  {
4185  ASSERT(_left.cols()==_right.cols());
4186  return _left.cols();
4187  }
4188 
4189 private:
4190  const expr1 &_left;
4191  const expr2 &_right;
4192 
4194  binary(const binary&); //do not implement
4196  binary &operator=(const binary&); //do not implement
4197 };
4198 
4200 
4201 
4202 
4207 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
4208 const binary<matrix_expression<value_t, expr1, tag1>, matrix_expression<value_t, expr2, tag2>, op::add>
4211  )
4212 { return util::make_pair_const_ref(get_matrix(left), get_matrix(right)); }
4213 
4215 
4220 template<typename value_t, typename expr1, typename tag1, typename shape1, typename expr2, typename tag2, typename shape2> inline
4221 const binary<shaped_expression<value_t, expr1, tag1, shape1>, shaped_expression<value_t, expr2, tag2, shape1>, op::add>
4224  )
4225 { return util::make_pair_const_ref(get_matrix(left), get_matrix(right)); }
4226 
4228 
4233 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
4234 const binary<matrix_expression<value_t, expr1, tag1>, matrix_expression<value_t, expr2, tag2>, op::sub>
4237  )
4238 { return util::make_pair_const_ref(get_matrix(left), get_matrix(right)); }
4239 
4241 
4246 template<typename value_t, typename expr1, typename tag1, typename shape1, typename expr2, typename tag2, typename shape2> inline
4247 const binary<shaped_expression<value_t, expr1, tag1, shape1>, shaped_expression<value_t, expr2, tag2, shape2>, op::sub>
4250  )
4251 { return util::make_pair_const_ref(get_matrix(left), get_matrix(right)); }
4252 
4254 
4263 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
4264 const binary<matrix_expression<value_t, expr1, tag1>, matrix_expression<value_t, expr2, tag2>, op::mul>
4267  )
4268 { return util::make_pair_const_ref(get_matrix(left), get_matrix(right)); }
4269 
4271 
4276 template<typename value_t, typename expr1, typename tag1, typename shape1, typename expr2, typename tag2, typename shape2> inline
4277 const binary<shaped_expression<value_t, expr1, tag1, shape1>, shaped_expression<value_t, expr2, tag2, shape2>, op::mul>
4280  )
4281 { return util::make_pair_const_ref(get_matrix(left), get_matrix(right)); }
4282 
4284 
4293 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
4294 const binary<matrix_expression<value_t, expr1, tag1>, matrix_expression<value_t, expr2, tag2>, op::div>
4297  )
4298 { return util::make_pair_const_ref(get_matrix(left), get_matrix(right)); }
4299 
4301 
4306 template<typename value_t, typename expr1, typename tag1, typename shape1, typename expr2, typename tag2, typename shape2> inline
4307 const binary<shaped_expression<value_t, expr1, tag1, shape1>, shaped_expression<value_t, expr2, tag2, shape2>, op::div>
4310  )
4311 { return util::make_pair_const_ref(get_matrix(left), get_matrix(right)); }
4313 
4315 
4322 template<typename expression_type>
4323 class vector_ref<expression_type, tag::reference, orientation::column> :
4324  public vector_expression<typename expr_traits<expression_type>::value_type,
4325  vector_ref<expression_type, tag::reference, orientation::column>,
4326  tag::reference,
4327  orientation::column
4328  >
4329 {
4330  typedef typename expr_traits<expression_type>::type expr_t;
4331 public:
4332  typedef typename expr_t::value_type value_type;
4333  typedef typename expr_t::reference reference;
4334  typedef typename expr_t::const_reference const_reference;
4335 
4337  vector_ref(vector_ref &a) : _ref(a._ref), _col(a._col)
4338  {}
4340  vector_ref(rvalue<vector_ref> &a) : _ref(a._ref), _col(a._col)
4341  {}
4343  vector_ref(expr_t &a, size_t column) : _ref(a), _col(column)
4344  {}
4346  reference operator()(size_t i)
4347  { return _ref(i, _col); }
4349  const_reference operator()(size_t i) const
4350  { return _ref(i, _col); }
4352  reference operator[](size_t i)
4353  { return _ref(i, _col); }
4355  const_reference operator[](size_t i) const
4356  { return _ref(i, _col); }
4358  size_t size() const
4359  { return _ref.rows(); }
4360  //Conversion to "reference to rvalue".
4361  operator rvalue<vector_ref>&()
4362  { return to_rvalue_ref(*this); }
4363 
4364 private:
4365  expr_t &_ref;
4366  const size_t _col;
4367 
4369  vector_ref &operator=(const vector_ref&); //do not implement
4370 
4372  friend expr_t &get_vector_ref(vector_ref &a) { return a._ref; }
4374  friend const expr_t &get_vector_ref(const vector_ref &a) { return a._ref; }
4376  friend size_t get_vector_column(const vector_ref &a) { return a._col; }
4377 };
4378 
4380 template<typename expression_type, size_t complexity>
4388 class vector_ref<expression_type, tag::expression<complexity>, orientation::column> :
4389  public vector_expression<typename expr_traits<expression_type>::value_type,
4390  vector_ref<expression_type, tag::expression<complexity>, orientation::column>,
4391  tag::expression<util::select<complexity, 1>::max - 1>,
4392  orientation::column
4393  >
4394 {
4395  typedef typename expr_traits<expression_type>::type expr_t;
4396 public:
4397  typedef typename expr_t::value_type value_type;
4398  typedef typename expr_t::const_reference const_reference;
4399 
4401  vector_ref(const vector_ref &a) : _ref(a._ref), _col(a._col)
4402  {}
4404  vector_ref(const expr_t &a, size_t col) : _ref(a), _col(col)
4405  {}
4407  const_reference operator()(size_t i) const
4408  { return _ref(i, _col); }
4410  const_reference operator[](size_t i) const
4411  { return _ref(i, _col); }
4413  size_t size() const
4414  { return _ref.rows(); }
4415 
4416 private:
4417  const expr_t &_ref;
4418  const size_t _col;
4419 
4421  vector_ref &operator=(const vector_ref&); //do not implement
4422 
4424  friend const expr_t &get_vector_ref(vector_ref &a) { return a._ref; }
4426  friend const expr_t &get_vector_ref(const vector_ref &a) { return a._ref; }
4428  friend size_t get_vector_column(const vector_ref &a) { return a._col; }
4429 };
4430 
4432 
4433 
4434 template<typename expression_type, typename tag> inline
4435 typename util::non_zero_in_column<typename expr_traits<expression_type>::shape>::first_type
4436 first_non_zero(const vector_ref<expression_type, tag, orientation::column> &v)
4437 { return first_non_zero_in_column(get_vector_ref(v), get_vector_column(v)); }
4439 template<typename expression_type, typename tag> inline
4440 typename util::non_zero_in_column<typename expr_traits<expression_type>::shape>::last_type
4441 last_non_zero(const vector_ref<expression_type, tag, orientation::column> &v)
4442 { return last_non_zero_in_column(get_vector_ref(v), get_vector_column(v)); }
4444 
4446 
4447 template<typename expression_type, typename tag>
4448 struct iterator<vector_ref<expression_type, tag, orientation::column> >
4449 {
4451  static type begin(vector_ref<expression_type, tag, orientation::column> &v, size_t i = 0)
4452  { return column_iterator<typename expr_traits<expression_type>::type>::begin(get_vector_ref(v), get_vector_column(v), i); }
4453 };
4455 
4456 template<typename expression_type, typename tag>
4457 struct const_iterator<vector_ref<expression_type, tag, orientation::column> >
4458 {
4460  static type begin(const vector_ref<expression_type, tag, orientation::column> &v, size_t i = 0)
4461  { return column_const_iterator<typename expr_traits<expression_type>::type>::begin(get_vector_ref(v), get_vector_column(v), i); }
4462 };
4463 
4464 namespace util {
4466 template<typename expression_type>
4467 struct row_ref { typedef vector_ref<expression_type, tag::reference, orientation::row> type; };
4469 template<typename expression_type>
4470 struct const_row_ref { typedef const vector_ref<expression_type, tag::expression<expr_traits<expression_type>::complexity>, orientation::row> type; };
4472 template<typename expression_type>
4473 struct column_ref { typedef vector_ref<expression_type, tag::reference, orientation::column> type; };
4475 template<typename expression_type>
4476 struct const_column_ref { typedef const vector_ref<expression_type, tag::expression<expr_traits<expression_type>::complexity>, orientation::column> type; };
4477 }//namespace util
4478 
4480 
4481 
4483 template<typename value_t, typename expr_t, typename tag> inline
4484 typename util::row_ref<matrix_expression<value_t, expr_t, tag> >::type
4486 {
4487  ASSERT(r<get_matrix(a).rows());
4488  return util::row_ref<matrix_expression<value_t, expr_t, tag> >::type(get_matrix(a), r);
4489 }
4490 
4493 template<typename value_t, typename expr_t, typename tag_t> inline
4494 typename util::const_row_ref<matrix_expression<value_t, expr_t, tag_t> >::type
4496 {
4497  ASSERT(r<get_matrix(a).rows());
4498  return util::const_row_ref<matrix_expression<value_t, expr_t, tag_t> >::type(get_matrix(a), r);
4499 }
4500 
4503 template<typename value_t, typename expr_t, typename tag, typename shape> inline
4504 typename util::row_ref<shaped_expression<value_t, expr_t, tag, shape> >::type
4506 {
4507  ASSERT(r<get_matrix(a).rows());
4508  return util::row_ref<shaped_expression<value_t, expr_t, tag, shape> >::type(get_matrix(a), r);
4509 }
4510 
4513 template<typename value_t, typename expr_t, typename tag_t, typename shape> inline
4514 typename util::const_row_ref<shaped_expression<value_t, expr_t, tag_t, shape> >::type
4516 {
4517  ASSERT(r<get_matrix(a).rows());
4518  return util::const_row_ref<shaped_expression<value_t, expr_t, tag_t, shape> >::type(get_matrix(a), r);
4519 }
4520 
4523 template<typename value_t, typename expr_t, typename tag> inline
4524 typename util::column_ref<matrix_expression<value_t, expr_t, tag> >::type
4526 {
4527  ASSERT(c<get_matrix(a).cols());
4528  return util::column_ref<matrix_expression<value_t, expr_t, tag> >::type(get_matrix(a), c);
4529 }
4530 
4533 template<typename value_t, typename expr_t, typename tag_t> inline
4534 typename util::const_column_ref<matrix_expression<value_t, expr_t, tag_t> >::type
4536 {
4537  ASSERT(c<get_matrix(a).cols());
4538  return util::const_column_ref<matrix_expression<value_t, expr_t, tag_t> >::type(get_matrix(a), c);
4539 }
4540 
4543 template<typename value_t, typename expr_t, typename tag, typename shape> inline
4544 typename util::column_ref<shaped_expression<value_t, expr_t, tag, shape> >::type
4546 {
4547  ASSERT(c<get_matrix(a).cols());
4548  return util::column_ref<shaped_expression<value_t, expr_t, tag, shape> >::type(get_matrix(a), c);
4549 }
4550 
4553 template<typename value_t, typename expr_t, typename tag_t, typename shape> inline
4554 typename util::const_column_ref<shaped_expression<value_t, expr_t, tag_t, shape> >::type
4556 {
4557  ASSERT(c<get_matrix(a).cols());
4558  return util::const_column_ref<shaped_expression<value_t, expr_t, tag_t, shape> >::type(get_matrix(a), c);
4559 }
4561 
4563 
4564 
4565 template<typename expr_t> inline
4566 size_t first_non_zero(const expr_t&)
4567 { return 0; }
4569 template<typename expr_t> inline
4570 size_t last_non_zero(const expr_t &v)
4571 { return v.size() - 1; }
4573 
4574 namespace util {
4575 struct min { static size_t op(size_t a, size_t b) { return std::min(a, b); } };
4576 struct max { static size_t op(size_t a, size_t b) { return std::max(a, b); } };
4577 template<typename op> inline
4578 size_t combine_indices(size_t a, size_t b)
4579 { ASSERT(a==b); return a; }
4580 template<typename op> inline
4581 size_t combine_indices(constrained_index a, size_t b)
4582 { ASSERT(op::op(a, b)==a); return a; }
4583 template<typename op> inline
4584 size_t combine_indices(size_t a, constrained_index b)
4585 { ASSERT(op::op(a, b)==b); return b; }
4586 template<typename op> inline
4587 size_t combine_indices(constrained_index a, constrained_index b)
4588 { return op::op(a, b); }
4589 }//namespace util
4590 
4592 
4593 
4594 template<typename expr1, typename expr2>
4595 size_t first_non_zero(const expr1 &a, const expr2 &b)
4596 { return util::combine_indices<util::max>(first_non_zero(a), first_non_zero(b)); }
4598 template<typename expr1, typename expr2>
4599 size_t last_non_zero(const expr1 &a, const expr2 &b)
4600 { return util::combine_indices<util::min>(last_non_zero(a), last_non_zero(b)); }
4602 
4604 
4605 
4606 
4607 
4616 template<template<typename, typename> class op, typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
4617 typename op<value_t, value_t>::result_type
4619 {
4620  typedef typename op<value_t, value_t>::result_type result_type;
4621  const expr1 &v1 = get_vector(a);
4622  const expr2 &v2 = get_vector(b);
4623  ASSERT(v1.size()==v2.size());
4624  result_type sum = traits<result_type>::zero;
4625  const size_t size = v1.size();
4626  /*for (; i<=last; ++i)
4627  sum = sum + op<value_t, value_t>::op(v1(i), v2(i));*/
4628 
4629  typename const_iterator<expr1>::type i1 = begin(v1, 0);
4630  typename const_iterator<expr2>::type i2 = begin(v2, 0);
4631  for (size_t i = 0; i<size; ++i, ++i1, ++i2)
4632  sum = sum + op<value_t, value_t>::op(*i1, *i2);
4633 
4634  return sum;
4635 }
4636 template<template<typename, typename> class op_t, typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
4637 typename op_t<value_t, value_t>::result_type
4639 {
4640  typedef op_t<value_t, value_t> op;
4641  typedef typename op::result_type result_type;
4642  const expr1 &v1 = get_vector(a);
4643  const expr2 &v2 = get_vector(b);
4644  ASSERT(v1.size()==v2.size());
4645  result_type sum = traits<result_type>::zero;
4646  size_t i = first_non_zero(v1, v2);
4647  const size_t last = last_non_zero(v1, v2);
4648  ASSERT(last<v1.size());
4649  /*for (; i<=last; ++i)
4650  sum = sum + op<value_t, value_t>::op(v1(i), v2(i));*/
4651 
4652  typename const_iterator<expr1>::type i1 = begin(v1, i);
4653  typename const_iterator<expr2>::type i2 = begin(v2, i);
4654  for (; i<=last; ++i, ++i1, ++i2)
4655  sum = sum + op::op(*i1, *i2);
4656 
4657  return sum;
4658 }
4660 
4662 
4678 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
4679 typename op::mul<value_t, value_t>::result_type
4682 { return accumulate_skip_zeros<op::mul>(a, b); }
4684 
4685 namespace util {
4687 template<typename shape1, typename shape2>
4688 struct product_shapes
4689 {
4690  typedef rectangular resulting_shape;
4691 };
4693 template<>
4694 struct product_shapes<lower_triangular, lower_triangular>
4695 {
4696  typedef lower_triangular resulting_shape;
4697 };
4699 template<>
4700 struct product_shapes<upper_triangular, upper_triangular>
4701 {
4702  typedef upper_triangular resulting_shape;
4703 };
4705 template<typename expression_type, size_t complexity = expr_traits<expression_type>::complexity>
4706 struct const_complexity
4707 {
4708  typedef const matrix<typename expr_traits<expression_type>::value_type,
4709  typename expr_traits<expression_type>::shape> type;
4710  typedef type &const_reference;
4711 };
4713 template<typename expression_type>
4714 struct const_complexity<expression_type, 0>
4715 {
4716  typedef const typename expr_traits<expression_type>::type &type;
4717  typedef type const_reference;
4718 };
4719 }//namespace util
4720 
4722 
4724 template<typename expression1, typename expression2>
4725 class product :
4726  public base_matrix_expression<
4727  typename util::same_types<typename expr_traits<expression1>::value_type,
4728  typename expr_traits<expression2>::value_type>::type,
4729  product<expression1, expression2>,
4730  tag::expression<3>,
4731  typename util::product_shapes<typename expr_traits<expression1>::shape,
4732  typename expr_traits<expression2>::shape>::resulting_shape
4733  >
4734 {
4735  typedef typename expr_traits<expression1>::type expr1;
4736  typedef typename expr_traits<expression2>::type expr2;
4737  typedef typename util::same_types<typename expr1::value_type, typename expr2::value_type>::type deduced_value_type;
4738 public:
4739  typedef deduced_value_type value_type;
4740  typedef const value_type const_reference;
4741 
4744  _left(p.first), _right(p.second)
4745  {
4746  if (_left.cols()!=_right.rows())
4747  throw size_error("number of columns of the first matrix and number of rows of the second matrix must be equal");
4748  }
4750 
4751  const_reference operator()(size_t r, size_t c) const
4752  { return sum_of_products(row(_left, r), column(_right, c)); }
4754  size_t rows() const
4755  { return _left.rows(); }
4757  size_t cols() const
4758  { return _right.cols(); }
4759 private:
4762 
4764  product(const product&); //do not implement
4766  product &operator=(const product&); //do not implement
4767 
4768  friend typename util::const_complexity<expression1>::const_reference left(const product &p) { return p._left; }
4769  friend typename util::const_complexity<expression2>::const_reference right(const product &p) { return p._right; }
4770 };
4771 
4772 template<typename value_t>
4773 template<typename expression1, typename expression2, typename tag>
4774 void matrix<value_t>::assign(const matrix_expression<value_type, product<expression1, expression2>, tag> &rhs)
4775 {
4776  const product<expression1, expression2> &p = get_matrix(rhs);
4777  const size_t
4778  rows = p.rows(),
4779  cols = p.cols();
4780  if (rows*cols<64*64 && false)
4781  {
4782  this->resize(rows, cols);
4783  for (size_t i = 0, k = 0; i<_rows; ++i)
4784  for (size_t j = 0; j<_cols; ++j, ++k)
4785  _p[k] = p(i, j);
4786  return;
4787  }
4788  typename util::const_complexity<expression1>::const_reference a = left(p);
4789  typename util::const_complexity<expression2>::const_reference b = right(p);
4790  typedef typename expr_traits<expression1>::type left_t;
4791  typedef typename expr_traits<expression2>::type right_t;
4792  this->resize(a.rows(), b.cols(), traits<value_type>::zero);
4793  const size_t n = a.cols();
4794  ASSERT(n==b.rows());
4795  for (size_t i = 0; i<_rows; ++i)
4796  {
4797  const size_t
4798  k0 = first_non_zero(row(a, i)),
4799  k1 = last_non_zero(row(a, i));
4800  ASSERT(k1<n);
4801  typename row_const_iterator<left_t>::type i1(a, i, k0);
4802  value_type * const p_i = &_p[i*_cols];
4803  for (size_t k = k0; k<=k1; ++k, ++i1)
4804  {
4805  value_type *p = p_i;
4806  //const value_type a1 = a(i, k);
4807  const value_type a1 = *i1;
4808  const size_t
4809  first = first_non_zero(row(b, k)),
4810  last = last_non_zero(row(b, k));
4811  ASSERT(last<_cols);
4812  typename row_const_iterator<right_t>::type i2(b, k, first);
4813  p += first;
4814  for (size_t j = first; j<=last; ++j, ++p, ++i2)
4815  *p = *p + a1*(*i2);
4816  }
4817  }
4818  return;
4819 }
4820 
4821 
4823 
4824 
4825 
4831 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
4832 product<matrix_expression<value_t, expr1, tag1>, matrix_expression<value_t, expr2, tag2> >
4835  )
4836 { return util::pair_const_ref<expr1, expr2>(get_matrix(left), get_matrix(right)); }
4837 
4839 
4848 template<typename value_t, typename expr1, typename tag1, typename shape1, typename expr2, typename tag2, typename shape2> inline
4849 product<shaped_expression<value_t, expr1, tag1, shape1>, shaped_expression<value_t, expr2, tag2, shape2> >
4852  )
4853 { return util::pair_const_ref<expr1, expr2>(get_matrix(left), get_matrix(right)); }
4855 
4856 namespace util {
4858 template<typename value_t, typename expr_t, typename tag_t, size_t complexity>
4859 struct const_complexity<vector_expression<value_t, expr_t, tag_t>, complexity>
4860 {
4861  typedef const vector<value_t> type;
4862 };
4864 template<typename value_t, typename expr_t, typename tag_t>
4865 struct const_complexity<vector_expression<value_t, expr_t, tag_t>, 0>
4866 {
4867  typedef const expr_t &type;
4868 };
4869 }//namespace util
4870 
4872 
4874 template<typename expression1, typename value_t, typename expr2, typename tag2>
4875 class product<expression1, vector_expression<value_t, expr2, tag2> > :
4876  public vector_expression<
4877  typename util::same_types<typename expr_traits<expression1>::value_type, value_t>::type,
4878  product<expression1, vector_expression<value_t, expr2, tag2> >,
4879  tag::expression<2>,
4880  typename util::vector_orientation<expr2>::type
4881  >
4882 {
4883  typedef typename expr_traits<expression1>::type expr1;
4884  typedef typename util::same_types<typename expr1::value_type, typename expr2::value_type>::type deduced_value_type;
4885 public:
4886  typedef deduced_value_type value_type;
4887  typedef const value_type const_reference;
4888 
4891  _left(p.first), _right(p.second)
4892  {
4893  if (_left.cols()!=_right.size())
4894  throw size_error("number of columns of matrix and size of vector must be equal");
4895  }
4897 
4898  const_reference operator()(size_t i) const
4899  { return sum_of_products(row(_left, i), _right); }
4901  size_t size() const
4902  { return _left.rows(); }
4903 private:
4905  typename util::const_complexity<vector_expression<value_t, expr2, tag2> >::type _right;
4906 
4908  product(const product&); //do not implement
4910  product &operator=(const product&); //do not implement
4911 };
4912 
4914 
4915 
4916 
4923 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
4924 product<matrix_expression<value_t, expr1, tag1>, vector_expression<value_t, expr2, tag2> >
4927  )
4928 { return util::pair_const_ref<expr1, expr2>(get_matrix(left), get_vector(right)); }
4929 
4931 
4936 template<typename value_t, typename expr1, typename tag1, typename shape, typename expr2, typename tag2> inline
4937 product<shaped_expression<value_t, expr1, tag1, shape>, vector_expression<value_t, expr2, tag2> >
4940  )
4941 { return util::pair_const_ref<expr1, expr2>(get_matrix(left), get_vector(right)); }
4943 
4963 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
4964 product<matrix_expression<value_t, expr1, tag1>, vector_expression<value_t, expr2, tag2> >
4967  )
4968 { return util::pair_const_ref<expr1, expr2>(get_matrix(linear_map), get_vector(v)); }
4969 
4971 
4976 template<typename value_t, typename expr1, typename tag1, typename shape, typename expr2, typename tag2> inline
4977 product<shaped_expression<value_t, expr1, tag1, shape>, vector_expression<value_t, expr2, tag2> >
4980  )
4981 { return util::pair_const_ref<expr1, expr2>(get_matrix(linear_map), get_vector(v)); }
4982 
4984 
4988 template<typename value_t, typename expr1, typename expr2, typename tag2> inline
4991  )
4992 {
4993  expr1 &a = get_matrix(left);
4994  expr1(a + right).swap(a);
4995  return a;
4996 }
4997 
4999 
5003 template<typename value_t, typename expr1, typename shape, typename expr2, typename tag2> inline
5006  )
5007 {
5008  expr1 &a = get_matrix(left);
5009  expr1(a + right).swap(a);
5010  return a;
5011 }
5012 
5014 
5018 template<typename value_t, typename expr1, typename expr2, typename tag2> inline
5021  )
5022 {
5023  expr1 &a = get_matrix(left);
5024  expr1(a - right).swap(a);
5025  return a;
5026 }
5027 
5029 
5033 template<typename value_t, typename expr1, typename shape, typename expr2, typename tag2> inline
5036  )
5037 {
5038  expr1 &a = get_matrix(left);
5039  expr1(a - right).swap(a);
5040  return a;
5041 }
5042 
5044 
5047 template<typename value_t, typename expr_t> inline
5049  const value_t &right
5050  )
5051 {
5052  expr_t &a = get_matrix(left);
5053  const size_t
5054  rows = a.rows(),
5055  cols = a.cols();
5056  for (size_t i = 0; i<rows; ++i)
5057  for (size_t j = 0; j<cols; ++j)
5058  a(i, j) *= right;
5059  return a;
5060 }
5061 
5063 
5065 template<typename value_t, typename expr_t, typename shape> inline
5067  const value_t &right
5068  )
5069 {
5070  expr_t &a = get_matrix(left);
5071  expr_t(a*right).swap(a);
5072  return a;
5073 }
5074 
5076 
5081 template<typename value_t, typename expr1, typename expr2, typename tag2> inline
5084  )
5085 {
5086  expr1 &a = get_matrix(left);
5087  expr1(a*right).swap(a);
5088  return a;
5089 }
5090 
5092 
5096 template<typename value_t, typename expr1, typename expr2, typename tag2> inline
5099  )
5100 {
5101  expr1 &a = get_matrix(left);
5102  expr1(a*right).swap(a);
5103  return a;
5104 }
5105 
5107 
5111 template<typename value_t, typename expr1, typename expr2, typename tag2> inline
5114  )
5115 {
5116  expr1 &a = get_matrix(left);
5117  expr1(a*right).swap(a);
5118  return a;
5119 }
5121 
5123 
5124 
5125 
5134 template<typename value_t, typename expr_t> inline
5137 { get_vector(a).swap(get_vector(b)); return; }
5138 
5140 
5157 template<typename value_t, typename expr1, typename expr2> inline
5160 {
5161  expr1 &v1 = get_vector(a);
5162  expr2 &v2 = get_vector(b);
5163  expr1 temp = v2;
5164  v2 = v1;
5165  swap(v1, temp);
5166  return;
5167 }
5169 
5170 namespace util {
5172 template<typename expr1, typename expr2> inline
5173 void swap_vectors(expr1& a, expr2 &b)
5174 {
5175  using std::swap;
5176  const size_t count = std::min(a.size(), b.size());
5177  for (size_t i = 0; i<count; ++i)
5178  swap(a(i), b(i));
5179  return;
5180 }
5181 }//namespace util
5182 
5184 
5185 
5186 
5204 template<typename value_t, typename expr1, typename expr2, typename orientation> inline
5206  vector_ref<expr2, tag::reference, orientation> b)
5207 { //ensuring the value type is the same
5208  typedef typename util::same_types<value_t, expr_traits<expr2>::value_type>::type value_type;
5209  util::swap_vectors(get_vector(a), b);
5210  return;
5211 }
5212 
5215 template<typename expr1, typename orientation, typename value_t, typename expr2> inline
5216 void swap(vector_ref<expr1, tag::reference, orientation> a,
5218 { //ensuring the value type is the same
5219  typedef typename util::same_types<value_t, expr_traits<expr1>::value_type>::type value_type;
5220  util::swap_vectors(a, get_vector(b));
5221  return;
5222 }
5223 
5226 template<typename expr1, typename orientation1, typename expr2, typename orientation2> inline
5227 void swap(vector_ref<expr1, tag::reference, orientation1> a,
5228  vector_ref<expr2, tag::reference, orientation2> b)
5229 { //ensuring the value type is the same
5230  typedef typename util::same_types<expr_traits<expr1>::value_type, expr_traits<expr2>::value_type>::type value_type;
5231  util::swap_vectors(a, b);
5232  return;
5233 }
5235 
5236 namespace util {
5238 template<typename type1, typename type2>
5239 struct mul_conj
5240 {
5242  typedef typename util::same_types<type1, type2>::type result_type;
5244  static result_type op(const type1 &a, const type2 &b) { using dummy::conj; return a*conj(b); }
5245 };
5246 }//namespace util
5247 
5250 
5270 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
5271 typename util::mul_conj<value_t, value_t>::result_type
5274 { return accumulate_skip_zeros<util::mul_conj>(v1, v2); }
5275 
5277 
5278 
5288 template<template<typename> class op, typename value_t, typename expr_t, typename tag> inline
5289 typename op<value_t>::result_type
5291 {
5292  typedef typename op<value_t>::result_type result_type;
5293  const expr_t v = get_vector(a);
5294  result_type sum = traits<result_type>::zero;
5295  const size_t size = v.size();
5296  for (size_t i = 0; i<size; ++i)
5297  sum = sum + op<value_t>::op(v(i));
5298  return sum;
5299 }
5300 template<template<typename> class op_t, typename value_t, typename expr_t, typename tag> inline
5301 typename op_t<value_t>::result_type
5303 {
5304  //typedef typename op<value_t>::result_type result_type;
5305  //const expr_t v = get_vector(a);
5306  //result_type sum = traits<result_type>::zero;
5307  //const size_t size = v.size();
5308  //for (size_t i = 0; i<size; ++i)
5309  // sum = sum + op<value_t>::op(v(i));
5310  //return sum;
5311 
5312  typedef op_t<value_t> op;
5313  typedef typename op::result_type result_type;
5314  const expr_t &v = get_vector(a);
5315  result_type sum = traits<result_type>::zero;
5316  size_t i = first_non_zero(v);
5317  const size_t last = last_non_zero(v);
5318  ASSERT(last<v.size());
5319 
5320  typename const_iterator<expr_t>::type it = begin(v, i);
5321  for (; i<=last; ++i, ++it)
5322  sum = sum + op::op(*it);
5323 
5324  return sum;
5325 }
5327 
5328 
5329 namespace util {
5331 template<typename type>
5332 struct sqr
5333 {
5335  typedef type result_type;
5337  static result_type op(const type &a) { using dummy::conj; return a*conj(a); }
5338 };
5339 }//namespace util
5340 
5342 
5343 
5344 
5363 template<typename value_t, typename expr_t, typename tag>
5365 { return accumulate_skip_zeros<util::sqr>(v); }
5366 
5368 
5388 template<typename value_t, typename expr_t, typename tag>
5390 { return sqrt(sqrnorm(v)); }
5392 
5394 
5396 template<typename value_t, typename expr_t, typename tag_t, template<typename> class op>
5397 class unary<vector_expression<value_t, expr_t, tag_t>, op> :
5398  public vector_expression<value_t,
5399  unary<vector_expression<value_t, expr_t, tag_t>, op>,
5400  tag::expression< util::select<util::tag_complexity<tag_t>::value, 0>::max>,
5401  typename util::vector_orientation<expr_t>::type
5402  >
5403 {
5404 public:
5405  typedef value_t value_type;
5406  typedef const value_type const_reference;
5407 
5409  unary(const expr_t &a) : _ref(a)
5410  {}
5412  const_reference operator()(size_t i) const
5413  { return op<value_type>::op(_ref(i)); }
5415  size_t size() const
5416  { return _ref.size(); }
5417 
5418 private:
5419  const expr_t &_ref;
5420 
5422  unary(const unary&); //do not implement
5424  unary &operator=(const unary&); //do not implement
5425 };
5426 
5428 
5429 
5430 
5435 template<typename value_t, typename expr_t, typename tag> inline
5436 const unary<vector_expression<value_t, expr_t, tag>, op::plus>
5438 { return get_vector(a); }
5439 
5441 
5446 template<typename value_t, typename expr_t, typename tag> inline
5447 const unary<vector_expression<value_t, expr_t, tag>, op::minus>
5449 { return get_vector(a); }
5450 
5452 
5464 template<typename value_t, typename expr_t, typename tag> inline
5465 const unary<vector_expression<value_t, expr_t, tag>, op::conj>
5467 { return get_vector(a); }
5469 
5471 
5473 template<typename value_t, typename expr_t, typename tag_t>
5474 class scaled<vector_expression<value_t, expr_t, tag_t> > :
5475  public vector_expression<value_t,
5476  scaled<vector_expression<value_t, expr_t, tag_t> >,
5477  tag::expression<util::select<util::tag_complexity<tag_t>::value, 2>::max>,
5478  typename util::vector_orientation<expr_t>::type
5479  >
5480 {
5481 public:
5482  typedef value_t value_type;
5483  typedef const value_type const_reference;
5484 
5486  scaled(const scaled &a) : _ref(a._ref), _scale(a._scale)
5487  {}
5489  scaled(const expr_t &a, const_reference s) : _ref(a), _scale(s)
5490  {}
5492  const_reference operator()(size_t i) const
5493  { return _ref(i)*_scale; }
5495  size_t size() const
5496  { return _ref.size(); }
5497 
5498 private:
5499  const expr_t &_ref;
5500  const value_type _scale;
5501 
5503  scaled &operator=(const scaled&); //do not implement
5504 };
5505 
5507 
5508 
5509 
5512 template<typename value_t, typename expr_t, typename tag> inline
5513 const scaled<vector_expression<value_t, expr_t, tag> >
5514 operator*(const vector_expression<value_t, expr_t, tag> &a, const typename expr_t::value_type &s)
5516 
5518 
5521 template<typename value_t, typename expr_t, typename tag> inline
5522 const scaled<vector_expression<value_t, expr_t, tag> >
5523 operator*(const typename expr_t::value_type &s, const vector_expression<value_t, expr_t, tag> &a)
5526 
5527 namespace util {
5529 template<typename orienation1, typename orienation2>
5530 struct orientations
5531 {
5532  typedef orientation::undefined resulting_orientation;
5533 };
5534 template<typename orienation_t>
5535 struct orientations<orienation_t, orienation_t>
5536 {
5537  typedef orienation_t resulting_orientation;
5538 };
5539 template<typename orienation_t>
5540 struct orientations<orientation::undefined, orienation_t>
5541 {
5542  typedef orienation_t resulting_orientation;
5543 };
5544 template<typename orienation_t>
5545 struct orientations<orienation_t, orientation::undefined>
5546 {
5547  typedef orienation_t resulting_orientation;
5548 };
5549 }//namespace util
5550 
5552 
5554 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2, template<typename, typename> class op>
5555 class binary<vector_expression<value_t, expr1, tag1>, vector_expression<value_t, expr2, tag2>, op> :
5556  public vector_expression<
5557  value_t,
5558  binary<vector_expression<value_t, expr1, tag1>, vector_expression<value_t, expr2, tag2>, op>,
5559  tag::expression<util::select<util::tag_complexity<tag1>::value,
5560  util::tag_complexity<tag2>::value,
5561  1>::max>,
5562  typename util::orientations<typename util::vector_orientation<expr1>::type,
5563  typename util::vector_orientation<expr2>::type>::resulting_orientation
5564  >
5565 {
5566 public:
5567  typedef typename op<typename expr1::value_type, typename expr2::value_type>::result_type value_type;
5568  typedef const value_type const_reference;
5569 
5572  _left(p.first), _right(p.second)
5573  {
5574  if (_left.size()!=_right.size())
5575  throw size_error("sizes of vectors must be equal");
5576  }
5578  const_reference operator()(size_t i) const
5579  { return op<typename expr1::value_type, typename expr2::value_type>::op(_left(i), _right(i)); }
5581  size_t size() const
5582  {
5583  ASSERT(_left.size()==_right.size());
5584  return _left.size();
5585  }
5586 
5587 private:
5588  const expr1 &_left;
5589  const expr2 &_right;
5590 
5592  binary(const binary&); //do not implement
5594  binary &operator=(const binary&); //do not implement
5595 };
5596 
5598 
5599 
5600 
5605 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
5606 const binary<vector_expression<value_t, expr1, tag1>, vector_expression<value_t, expr2, tag2>, op::add>
5609  )
5610 { return util::pair_const_ref<expr1, expr2>(get_vector(left), get_vector(right)); }
5611 
5613 
5618 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
5619 const binary<vector_expression<value_t, expr1, tag1>, vector_expression<value_t, expr2, tag2>, op::sub>
5622  )
5623 { return util::pair_const_ref<expr1, expr2>(get_vector(left), get_vector(right)); }
5624 
5626 
5631 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
5632 const binary<vector_expression<value_t, expr1, tag1>, vector_expression<value_t, expr2, tag2>, op::mul>
5635  )
5636 { return util::pair_const_ref<expr1, expr2>(get_vector(left), get_vector(right)); }
5637 
5639 
5644 template<typename value_t, typename expr1, typename tag1, typename expr2, typename tag2> inline
5645 const binary<vector_expression<value_t, expr1, tag1>, vector_expression<value_t, expr2, tag2>, op::div>
5648  )
5649 { return util::pair_const_ref<expr1, expr2>(get_vector(left), get_vector(right)); }
5650 
5652 
5656 template<typename value_t, typename expr1, typename expr2, typename tag2> inline
5659  )
5660 {
5661  expr1 &a = get_vector(left);
5662  expr1(a + get_vector(right)).swap(a);
5663  return a;
5664 }
5665 
5667 
5677 template<typename value_t, typename expr1, typename expr2, typename tag2> inline
5680  )
5681 {
5682  expr1 &a = get_vector(left);
5683  const expr2 &b = get_vector(right);
5684  const size_t size = a.size();
5685  ASSERT(size==b.size());
5686  for (size_t i = 0; i<size; ++i)
5687  a(i) += b(i);
5688  return a;
5689 }
5690 
5692 
5696 template<typename value_t, typename expr1, typename expr2, typename tag2> inline
5699  )
5700 {
5701  expr1 &a = get_vector(left);
5702  expr1(a - get_vector(right)).swap(a);
5703  return a;
5704 }
5705 
5707 
5717 template<typename value_t, typename expr1, typename expr2, typename tag2> inline
5720  )
5721 {
5722  expr1 &a = get_vector(left);
5723  const expr2 &b = get_vector(right);
5724  const size_t size = a.size();
5725  ASSERT(size==b.size());
5726  for (size_t i = 0; i<size; ++i)
5727  a(i) -= b(i);
5728  return a;
5729 }
5731 
5732 namespace util {
5734 template<typename type> inline
5735 type &scale_vector(type &a, typename const type::value_type &b)
5736 {
5737  const size_t size = a.size();
5738  for (size_t i = 0; i<size; ++i)
5739  a(i) = a(i)*b;
5740  return a;
5741 }
5742 }//namespace util
5743 
5745 
5746 
5747 
5750 template<typename value_t, typename expr_t> inline
5752  const value_t &right
5753  )
5754 { return util::scale_vector(get_vector(left), right); }
5755 
5757 
5763 template<typename value_t, typename expr_t> inline
5765  const value_t &right
5766  )
5767 { return util::scale_vector(get_vector(left), right); }
5769 
5770 }//namespace nabla
5771 #pragma warning(pop)
5772 #endif//TOOLS_MATRIX_INCLUDED