comparison liboctave/DiagArray2.h @ 8524:937921654627

clean up Array and DiagArray2
author Jaroslav Hajek <highegg@gmail.com>
date Thu, 15 Jan 2009 07:22:24 +0100
parents e3c9102431a9
children f5408862892f
comparison
equal deleted inserted replaced
8523:ad3afaaa19c1 8524:937921654627
1 // Template array classes 1 // Template array classes
2 /* 2 /*
3 3
4 Copyright (C) 1996, 1997, 2000, 2002, 2003, 2004, 2005, 2006, 2007 4 Copyright (C) 1996, 1997, 2000, 2002, 2003, 2004, 2005, 2006, 2007
5 John W. Eaton 5 John W. Eaton
6 Copyright (C) 2008 Jaroslav Hajek 6 Copyright (C) 2008, 2009 Jaroslav Hajek
7 7
8 This file is part of Octave. 8 This file is part of Octave.
9 9
10 Octave is free software; you can redistribute it and/or modify it 10 Octave is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the 11 under the terms of the GNU General Public License as published by the
28 28
29 #include <cassert> 29 #include <cassert>
30 #include <cstdlib> 30 #include <cstdlib>
31 31
32 #include "Array.h" 32 #include "Array.h"
33 #include "Array2.h"
33 #include "lo-error.h" 34 #include "lo-error.h"
34 35
35 // A two-dimensional array with diagonal elements only. 36 // A two-dimensional array with diagonal elements only.
36 //
37 // Idea and example code for Proxy class and functions from: 37 // Idea and example code for Proxy class and functions from:
38 // 38 //
39 // From: kanze@us-es.sel.de (James Kanze) 39 // From: kanze@us-es.sel.de (James Kanze)
40 // Subject: Re: How to overload [] to do READ/WRITE differently ? 40 // Subject: Re: How to overload [] to do READ/WRITE differently ?
41 // Message-ID: <KANZE.93Nov29151407@slsvhdt.us-es.sel.de> 41 // Message-ID: <KANZE.93Nov29151407@slsvhdt.us-es.sel.de>
43 // Date: 29 Nov 1993 14:14:07 GMT 43 // Date: 29 Nov 1993 14:14:07 GMT
44 // -- 44 // --
45 // James Kanze email: kanze@us-es.sel.de 45 // James Kanze email: kanze@us-es.sel.de
46 // GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France 46 // GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
47 47
48 // Array<T> is inherited privately because we abuse the dimensions variable 48 // Array<T> is inherited privately so that some methods, like index, don't
49 // for true dimensions. Therefore, the inherited Array<T> object is not a valid 49 // produce unexpected results.
50 // Array<T> object, and should not be publicly accessible.
51 50
52 template <class T> 51 template <class T>
53 class 52 class
54 DiagArray2 : private Array<T> 53 DiagArray2 : protected Array<T>
55 { 54 {
56 private: 55 private:
57 56
58 T get (octave_idx_type i) { return Array<T>::xelem (i); } 57 T get (octave_idx_type i) { return Array<T>::xelem (i); }
59 58
64 public: 63 public:
65 64
66 Proxy (DiagArray2<T> *ref, octave_idx_type r, octave_idx_type c) 65 Proxy (DiagArray2<T> *ref, octave_idx_type r, octave_idx_type c)
67 : i (r), j (c), object (ref) { } 66 : i (r), j (c), object (ref) { }
68 67
69 const Proxy& operator = (const T& val) const 68 const Proxy& operator = (const T& val) const;
70 { 69
71 if (i == j) 70 operator T () const;
72 {
73 if (object)
74 object->set (val, i);
75 }
76 else
77 (*current_liboctave_error_handler)
78 ("invalid assignment to off-diagonal in diagonal array");
79
80 return *this;
81 }
82
83 operator T () const
84 {
85 if (object && i == j)
86 return object->get (i);
87 else
88 {
89 static T foo;
90 return foo;
91 }
92 }
93 71
94 private: 72 private:
95 73
96 // FIXME -- this is declared private to keep the user from 74 // FIXME -- this is declared private to keep the user from
97 // taking the address of a Proxy. Maybe it should be implemented 75 // taking the address of a Proxy. Maybe it should be implemented
104 82
105 DiagArray2<T> *object; 83 DiagArray2<T> *object;
106 84
107 }; 85 };
108 86
109 friend class Proxy; 87 friend class Proxy;
110 88
111 protected: 89 protected:
112 90 octave_idx_type d1, d2;
113 DiagArray2 (T *d, octave_idx_type r, octave_idx_type c) : Array<T> (d, r < c ? r : c) 91
114 { Array<T>::dimensions = dim_vector (r, c); } 92 DiagArray2 (T *d, octave_idx_type r, octave_idx_type c)
93 : Array<T> (d, std::min (r, c)), d1 (r), d2 (c) { }
115 94
116 public: 95 public:
117 96
118 typedef T element_type; 97 typedef T element_type;
119 98
120 DiagArray2 (void) : Array<T> (dim_vector (0, 0)) { } 99 DiagArray2 (void)
121 100 : Array<T> (), d1 (0), d2 (0) { }
122 DiagArray2 (octave_idx_type r, octave_idx_type c) : Array<T> (r < c ? r : c) 101
123 { this->dimensions = dim_vector (r, c); } 102 DiagArray2 (octave_idx_type r, octave_idx_type c)
124 103 : Array<T> (std::min (r, c)), d1 (r), d2 (c) { }
125 DiagArray2 (octave_idx_type r, octave_idx_type c, const T& val) : Array<T> (r < c ? r : c) 104
126 { 105 DiagArray2 (octave_idx_type r, octave_idx_type c, const T& val)
127 this->dimensions = dim_vector (r, c); 106 : Array<T> (std::min (r, c), val), d1 (r), d2 (c) { }
128 107
129 Array<T>::fill (val); 108 DiagArray2 (const Array<T>& a)
130 } 109 : Array<T> (a), d1 (a.numel ()), d2 (a.numel ()) { }
131 110
132 DiagArray2 (const Array<T>& a) : Array<T> (a) 111 DiagArray2 (const DiagArray2<T>& a)
133 { this->dimensions = dim_vector (a.length (), a.length ()); } 112 : Array<T> (a), d1 (a.d1), d2 (a.d2) { }
134
135 DiagArray2 (const DiagArray2<T>& a) : Array<T> (a)
136 { this->dimensions = a.dims (); }
137 113
138 template <class U> 114 template <class U>
139 DiagArray2 (const DiagArray2<U>& a) : Array<T> (a.diag ()) 115 DiagArray2 (const DiagArray2<U>& a)
140 { this->dimensions = a.dims (); } 116 : Array<T> (a.diag ()), d1 (a.dim1 ()), d2 (a.dim2 ()) { }
141 117
142 ~DiagArray2 (void) { } 118 ~DiagArray2 (void) { }
143 119
144 DiagArray2<T>& operator = (const DiagArray2<T>& a) 120 DiagArray2<T>& operator = (const DiagArray2<T>& a)
145 { 121 {
146 if (this != &a) 122 if (this != &a)
147 Array<T>::operator = (a); 123 {
124 Array<T>::operator = (a);
125 d1 = a.d1;
126 d2 = a.d2;
127 }
148 128
149 return *this; 129 return *this;
150 } 130 }
151 131
152 132 octave_idx_type dim1 (void) const { return d1; }
153 octave_idx_type dim1 (void) const { return Array<T>::dimensions(0); } 133 octave_idx_type dim2 (void) const { return d2; }
154 octave_idx_type dim2 (void) const { return Array<T>::dimensions(1); }
155 134
156 octave_idx_type rows (void) const { return dim1 (); } 135 octave_idx_type rows (void) const { return dim1 (); }
157 octave_idx_type cols (void) const { return dim2 (); } 136 octave_idx_type cols (void) const { return dim2 (); }
158 octave_idx_type columns (void) const { return dim2 (); } 137 octave_idx_type columns (void) const { return dim2 (); }
159 138
139 // FIXME: a dangerous ambiguity?
160 octave_idx_type length (void) const { return Array<T>::length (); } 140 octave_idx_type length (void) const { return Array<T>::length (); }
161 octave_idx_type nelem (void) const { return dim1 () * dim2 (); } 141 octave_idx_type nelem (void) const { return dim1 () * dim2 (); }
162 octave_idx_type numel (void) const { return nelem (); } 142 octave_idx_type numel (void) const { return nelem (); }
163 143
164 size_t byte_size (void) const { return length () * sizeof (T); } 144 size_t byte_size (void) const { return length () * sizeof (T); }
165 145
166 dim_vector dims (void) const { return Array<T>::dimensions; } 146 dim_vector dims (void) const { return dim_vector (d1, d2); }
167 147
168 Array<T> diag (octave_idx_type k = 0) const; 148 Array<T> diag (octave_idx_type k = 0) const;
169 149
170 Proxy elem (octave_idx_type r, octave_idx_type c) 150 // Warning: the non-const two-index versions will silently ignore assignments
171 { 151 // to off-diagonal elements.
172 return Proxy (this, r, c);
173 }
174
175 Proxy checkelem (octave_idx_type r, octave_idx_type c)
176 {
177 if (r < 0 || c < 0 || r >= dim1 () || c >= dim2 ())
178 {
179 (*current_liboctave_error_handler) ("range error in DiagArray2");
180 return Proxy (0, r, c);
181 }
182 else
183 return Proxy (this, r, c);
184 }
185
186 Proxy operator () (octave_idx_type r, octave_idx_type c)
187 {
188 if (r < 0 || c < 0 || r >= dim1 () || c >= dim2 ())
189 {
190 (*current_liboctave_error_handler) ("range error in DiagArray2");
191 return Proxy (0, r, c);
192 }
193 else
194 return Proxy (this, r, c);
195 }
196 152
197 T elem (octave_idx_type r, octave_idx_type c) const 153 T elem (octave_idx_type r, octave_idx_type c) const
198 { 154 {
199 return (r == c) ? Array<T>::xelem (r) : T (0); 155 return (r == c) ? Array<T>::elem (r) : T (0);
200 } 156 }
157
158 T& elem (octave_idx_type r, octave_idx_type c)
159 {
160 static T zero (0);
161 return (r == c) ? Array<T>::elem (r) : zero;
162 }
163
164 T dgelem (octave_idx_type i) const
165 { return Array<T>::elem (i); }
166
167 T& dgelem (octave_idx_type i)
168 { return Array<T>::elem (i); }
201 169
202 T checkelem (octave_idx_type r, octave_idx_type c) const; 170 T checkelem (octave_idx_type r, octave_idx_type c) const;
171 Proxy checkelem (octave_idx_type r, octave_idx_type c);
172
203 T operator () (octave_idx_type r, octave_idx_type c) const 173 T operator () (octave_idx_type r, octave_idx_type c) const
204 { 174 {
205 #if defined (BOUNDS_CHECKING) 175 #if defined (BOUNDS_CHECKING)
206 return checkelem (r, c); 176 return checkelem (r, c);
207 #else 177 #else
208 return elem (r, c); 178 return elem (r, c);
209 #endif 179 #endif
210 } 180 }
211 181
182 // FIXME: can this cause problems?
183 #if defined (BOUNDS_CHECKING)
184 Proxy operator () (octave_idx_type r, octave_idx_type c)
185 {
186 return checkelem (r, c);
187 }
188 #else
189 T& operator () (octave_idx_type r, octave_idx_type c)
190 {
191 return elem (r, c);
192 }
193 #endif
194
212 // No checking. 195 // No checking.
213 196
214 T& xelem (octave_idx_type r, octave_idx_type c)
215 {
216 static T foo (0);
217 return (r == c) ? Array<T>::xelem (r) : foo;
218 }
219
220 T xelem (octave_idx_type r, octave_idx_type c) const 197 T xelem (octave_idx_type r, octave_idx_type c) const
221 { 198 {
222 return (r == c) ? Array<T>::xelem (r) : T (0); 199 return (r == c) ? Array<T>::xelem (r) : T (0);
223 } 200 }
224 201
202 T& dgxelem (octave_idx_type i)
203 { return Array<T>::xelem (i); }
204
205 T dgxelem (octave_idx_type i) const
206 { return Array<T>::xelem (i); }
207
225 void resize (octave_idx_type n, octave_idx_type m); 208 void resize (octave_idx_type n, octave_idx_type m);
226 void resize (octave_idx_type n, octave_idx_type m, const T& val); 209 void resize_fill (octave_idx_type n, octave_idx_type m, const T& val);
227 210
228 DiagArray2<T> transpose (void) const; 211 DiagArray2<T> transpose (void) const;
229 DiagArray2<T> hermitian (T (*fcn) (const T&) = 0) const; 212 DiagArray2<T> hermitian (T (*fcn) (const T&) = 0) const;
213
214 operator Array2<T> (void) const;
230 215
231 const T *data (void) const { return Array<T>::data (); } 216 const T *data (void) const { return Array<T>::data (); }
232 217
233 const T *fortran_vec (void) const { return Array<T>::fortran_vec (); } 218 const T *fortran_vec (void) const { return Array<T>::fortran_vec (); }
234 219