矩阵(C++)
1 /* array.h 2 * ****** BEGIN LICENSE BLOCK ***** 3 * $Id: arrays.h,v 1.21 2008/03/14 08:17:36 asuraparaju Exp $ $Name: Dirac_1_0_2 $ 4 * 5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 6 * 7 * The contents of this file are subject to the Mozilla Public License 8 * Version 1.1 (the "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * http://www.mozilla.org/MPL/ 11 * 12 * Software distributed under the License is distributed on an "AS IS" basis, 13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for 14 * the specific language governing rights and limitations under the License. 15 * 16 * The Original Code is BBC Research and Development code. 17 * 18 * The Initial Developer of the Original Code is the British Broadcasting 19 * Corporation. 20 * Portions created by the Initial Developer are Copyright (C) 2004. 21 * All Rights Reserved. 22 * 23 * Contributor(s): Thomas Davies (Original Author), 24 * Peter Meerwald (pmeerw@users.sourceforge.net) 25 * Mike Ferenduros (mike_ferenzduros@users.sourceforge.net) 26 * Anuradha Suraparaju 27 * 28 * Alternatively, the contents of this file may be used under the terms of 29 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser 30 * Public License Version 2.1 (the "LGPL"), in which case the provisions of 31 * the GPL or the LGPL are applicable instead of those above. If you wish to 32 * allow use of your version of this file only under the terms of the either 33 * the GPL or LGPL and not to allow others to use your version of this file 34 * under the MPL, indicate your decision by deleting the provisions above 35 * and replace them with the notice and other provisions required by the GPL 36 * or LGPL. If you do not delete the provisions above, a recipient may use 37 * your version of this file under the terms of any one of the MPL, the GPL 38 * or the LGPL. 39 * ***** END LICENSE BLOCK ***** */ 40 41 #ifndef _ARRAYS_H_ 42 #define _ARRAYS_H_ 43 44 //basic array types used for pictures etc 45 46 #include <memory> 47 #include <cstddef> 48 #include <stdexcept> 49 #include <iostream> 50 #include <algorithm> 51 #include <cstring> 52 53 namespace dirac 54 { 55 //! Range type. 56 /*! 57 Range type encapsulating a closed range of values [first,last]. 58 Used to initialies OneDArrays. 59 */ 60 class Range 61 { 62 public: 63 //! Constructor 64 /*! 65 Constructor taking a start and an end point for the range. 66 */ 67 Range(int s, int e): m_fst(s), m_lst(e){} 68 69 //! Returns the start of the range. 70 int First() const {return m_fst;} 71 72 //! Returns the end point of the range. 73 int Last() const {return m_lst;} 74 75 int m_fst ,m_lst; 76 }; 77 78 ////////////////////////////// 79 //One-Dimensional Array type// 80 ////////////////////////////// 81 82 //! A template class for one-dimensional arrays. 83 /*! 84 A template class for one-D arrays. Can be used wherever built-in 85 arrays are used, and eliminates the need for explicit memory 86 (de-)allocation. Also supports arrays not based at zero. 87 */ 88 template <class T> class OneDArray 89 { 90 public: 91 //! Default constructor. 92 /*! 93 Default constructor produces an empty array. 94 */ 95 OneDArray(); 96 97 //! 'Length' constructor. 98 /*! 99 Length constructor produces a zero-based array. 100 */ 101 OneDArray(const int len); 102 103 //! Range constructor 104 /*! 105 Range constructor produces an array with values indexed within the 106 range parameters. 107 \param r a range of indexing values. 108 */ 109 OneDArray(const Range& r); 110 111 //! Destructor. 112 /*! 113 Destructor frees the data allocated in the constructors. 114 */ 115 ~OneDArray() 116 { 117 FreePtr(); 118 } 119 120 //! Copy constructor. 121 /*! 122 Copy constructor copies both data and metadata. 123 */ 124 OneDArray(const OneDArray<T>& cpy); 125 126 //! Assignment= 127 /*! 128 Assignment= assigns both data and metadata. 129 */ 130 OneDArray<T>& operator=(const OneDArray<T>& rhs); 131 132 //! Resize the array, throwing away the current data. 133 void Resize(int l); 134 135 //! Element access. 136 T& operator[](const int pos){return m_ptr[pos-m_first];} 137 138 //! Element access. 139 const T& operator[](const int pos) const {return m_ptr[pos-m_first];} 140 141 //! Returns the length of the array. 142 int Length() const {return m_length;} 143 144 //! Returns the index of the first element. 145 int First() const {return m_first;} 146 147 //! Returns the index of the last element. 148 int Last() const {return m_last;} 149 150 void Init(const int len); 151 152 void Init(const Range& r); 153 154 void FreePtr(); 155 156 int m_first, m_last; 157 int m_length; 158 T* m_ptr; 159 }; 160 161 //public member functions// 162 /////////////////////////// 163 164 template <class T> 165 OneDArray<T>::OneDArray() 166 { 167 Init(0); 168 } 169 170 template <class T> 171 OneDArray<T>::OneDArray(const int len) 172 { 173 Init(len); 174 } 175 176 template <class T> 177 OneDArray<T>::OneDArray(const Range& r) 178 { 179 Init(r); 180 } 181 182 template <class T> 183 OneDArray<T>::OneDArray(const OneDArray<T>& cpy) 184 { 185 m_first = cpy.m_first; 186 m_last = cpy.m_last; 187 m_length = m_last - m_first + 1; 188 189 if (m_first==0) 190 Init(m_length); 191 else 192 Init(Range(m_first , m_last)); 193 194 memcpy( m_ptr , cpy.m_ptr , m_length * sizeof( T ) ); 195 } 196 197 template <class T> 198 OneDArray<T>& OneDArray<T>::operator=(const OneDArray<T>& rhs) 199 { 200 if (&rhs != this) 201 { 202 FreePtr(); 203 m_first = rhs.m_first; 204 m_last = rhs.m_last; 205 m_length = rhs.m_length; 206 207 if (m_first == 0) 208 Init(m_length); 209 else 210 Init(Range(m_first , m_last)); 211 212 memcpy( m_ptr , rhs.m_ptr , m_length * sizeof( T ) ); 213 214 } 215 return *this; 216 } 217 218 template <class T> 219 void OneDArray<T>::Resize(int l) 220 { 221 if (l != m_length) 222 { 223 FreePtr(); 224 Init(l); 225 } 226 } 227 228 //private member functions// 229 //////////////////////////// 230 231 template <class T> 232 void OneDArray<T>::Init(const int len) 233 { 234 Range r(0 , len-1); 235 236 Init(r); 237 238 } 239 240 template <class T> 241 void OneDArray<T>::Init(const Range& r) 242 { 243 244 m_first = r.First(); 245 m_last = r.Last(); 246 m_length = m_last - m_first + 1; 247 248 if ( m_length>0 ) 249 { 250 m_ptr = new T[ m_length ]; 251 } 252 else 253 { 254 m_length = 0; 255 m_first = 0; 256 m_last = -1; 257 m_ptr = NULL; 258 } 259 } 260 261 template <class T> 262 void OneDArray<T>::FreePtr() 263 { 264 if ( m_length>0 ) 265 delete[] m_ptr; 266 } 267 268 269 ////////////////////////////// 270 //Two-Dimensional Array type// 271 ////////////////////////////// 272 273 //! A template class for two-dimensional arrays. 274 /*! 275 A template class to do two-d arrays, so that explicit memory 276 (de-)allocation is not required. Only zero-based arrays are 277 currently supported so that access is fast. Accessing elements along 278 a row is therefore much faster than accessing them along a column. 279 Rows are contiguous in memory, so array[y][x] is equivalent to 280 array[0][x+y*LengthX()]. 281 */ 282 template <class T> class TwoDArray 283 { 284 typedef T* element_type; 285 286 public: 287 288 //! Default constructor. 289 /*! 290 Default constructor creates an empty array. 291 */ 292 TwoDArray(){ Init(0,0); } 293 294 //! Constructor. 295 /*! 296 The constructor creates an array of given width height. 297 */ 298 TwoDArray( const int height , const int width ){Init(height , width);} 299 300 //! Constructor. 301 /*! 302 The constructor creates an array of given width and length height 303 and initialises it to a value 304 */ 305 TwoDArray( const int height , const int width , T val); 306 307 //! Destructor 308 /*! 309 Destructor frees the data allocated in the constructor. 310 */ 311 virtual ~TwoDArray(){ 312 FreeData(); 313 } 314 315 //! Copy constructor. 316 /*! 317 Copy constructor copies data and metadata. 318 */ 319 TwoDArray(const TwoDArray<T>& Cpy); 320 321 //! Assignment = 322 /*! 323 Assignement = assigns both data and metadata. 324 */ 325 TwoDArray<T>& operator=(const TwoDArray<T>& rhs); 326 327 //! Copy Contents 328 /*! 329 Copy contents of array into output array retaining the dimensions 330 of the output array. If output array is larger that array then 331 pad with last true value. 332 Return true is copy was successful 333 */ 334 bool CopyContents(TwoDArray<T>& out) const; 335 336 //! Fill contents 337 /*! 338 Initialise the array with the val provided. 339 */ 340 void Fill(T val); 341 342 //! Resizes the array, deleting the current data. 343 void Resize(const int height, const int width); 344 345 //! Element access. 346 /*! 347 Accesses the rows of the arrays, which are returned in the form 348 of pointers to the row data NOT OneDArray objects. 349 */ 350 inline element_type& operator[](const int pos){return m_array_of_rows[pos];} 351 352 //! Element access. 353 /*! 354 Accesses the rows of the arrays, which are returned in the form of 355 pointers to the row data NOT OneDArray objects. 356 */ 357 inline const element_type& operator[](const int pos) const {return m_array_of_rows[pos];} 358 359 //! Returns the width 360 int LengthX() const { return m_length_x; } 361 362 //! Returns the height 363 int LengthY() const { return m_length_y; } 364 365 //! Returns the index of the first element of a row 366 int FirstX() const { return m_first_x; } 367 368 //! Returns the index of the first element of a column 369 int FirstY() const { return m_first_y; } 370 371 //! Returns the index of the last element of a row 372 int LastX() const { return m_last_x; } 373 374 //! Returns the index of the first element of a column 375 int LastY() const { return m_last_y; } 376 377 //! Initialise the array 378 void Init(const int height,const int width); 379 380 //! Free all the allocated data 381 void FreeData(); 382 383 int m_first_x; 384 int m_first_y; 385 386 int m_last_x; 387 int m_last_y; 388 389 int m_length_x; 390 int m_length_y; 391 392 element_type* m_array_of_rows; 393 }; 394 395 //public member functions// 396 /////////////////////////// 397 398 template <class T> 399 TwoDArray<T>::TwoDArray( const int height , const int width , const T val) 400 { 401 Init( height , width ); 402 std::fill_n( m_array_of_rows[0], m_length_x*m_length_y, val); 403 } 404 405 template <class T> 406 TwoDArray<T>::TwoDArray(const TwoDArray<T>& Cpy) 407 { 408 m_first_x = Cpy.m_first_x; 409 m_first_y = Cpy.m_first_y; 410 m_last_x = Cpy.m_last_x; 411 m_last_y = Cpy.m_last_y; 412 413 m_length_x = m_last_x - m_first_x + 1; 414 m_length_y = m_last_y - m_first_y + 1; 415 416 if (m_first_x == 0 && m_first_y == 0) 417 Init(m_length_y , m_length_x); 418 else{ 419 //based 2D arrays not yet supported 420 } 421 422 memcpy( m_array_of_rows[0] , (Cpy.m_array_of_rows)[0] , m_length_x * m_length_y * sizeof( T ) ); 423 424 } 425 426 template <class T> 427 TwoDArray<T>& TwoDArray<T>::operator=(const TwoDArray<T>& rhs) 428 { 429 if (&rhs != this) 430 { 431 FreeData(); 432 433 m_first_x = rhs.m_first_x; 434 m_first_y = rhs.m_first_y; 435 436 m_last_x = rhs.m_last_x; 437 m_last_y = rhs.m_last_y; 438 439 m_length_x = m_last_x - m_first_x + 1; 440 m_length_y = m_last_y - m_first_y + 1; 441 442 if (m_first_x == 0 && m_first_y == 0) 443 Init(m_length_y , m_length_x); 444 else 445 { 446 //based 2D arrays not yet supported 447 } 448 449 memcpy( m_array_of_rows[0], (rhs.m_array_of_rows)[0], m_length_x * m_length_y * sizeof( T ) ); 450 451 } 452 453 return *this; 454 455 } 456 457 template <class T> 458 bool TwoDArray<T>::CopyContents(TwoDArray<T>& out) const 459 { 460 if (&out != this) 461 { 462 int rows = std::min (m_length_y, out.m_length_y); 463 int cols = std::min (m_length_x, out.m_length_x); 464 for (int j = 0; j < rows; ++j) 465 { 466 memcpy( out.m_array_of_rows[j], m_array_of_rows[j], cols * sizeof( T )) ; 467 for (int i = cols; i <out.m_length_x; ++i) 468 out.m_array_of_rows[j][i] = out.m_array_of_rows[j][cols-1]; 469 } 470 for (int j = rows; j < out.m_length_y; ++j) 471 { 472 memcpy( out.m_array_of_rows[j], out.m_array_of_rows[rows-1], out.m_length_x * sizeof( T )) ; 473 } 474 } 475 return true; 476 } 477 478 template <class T> 479 void TwoDArray<T>::Fill( T val) 480 { 481 if (m_length_x && m_length_y) 482 std::fill_n( m_array_of_rows[0], m_length_x*m_length_y, val); 483 } 484 485 template <class T> 486 void TwoDArray<T>::Resize(const int height, const int width) 487 { 488 if (height != m_length_y || width != m_length_x) 489 { 490 FreeData(); 491 Init(height , width); 492 } 493 } 494 495 //private member functions// 496 //////////////////////////// 497 498 template <class T> 499 void TwoDArray<T>::Init(const int height , const int width) 500 { 501 m_length_x = width; 502 m_length_y = height; 503 m_first_x = 0; 504 m_first_y = 0; 505 506 m_last_x = m_length_x-1; 507 m_last_y = m_length_y-1; 508 509 if (m_length_y>0) 510 { 511 // allocate the array containing ptrs to all the rows 512 m_array_of_rows = new element_type[ m_length_y ]; 513 514 if ( m_length_x>0 ) 515 { 516 // Allocate the whole thing as a single big block 517 m_array_of_rows[0] = new T[ m_length_x * m_length_y ]; 518 519 // Point the pointers 520 for (int j=1 ; j<m_length_y ; ++j) 521 m_array_of_rows[j] = m_array_of_rows[0] + j * m_length_x; 522 } 523 else 524 { 525 m_length_x = 0; 526 m_first_x = 0; 527 m_last_x = -1; 528 } 529 } 530 else 531 { 532 m_length_x = 0; 533 m_length_y = 0; 534 m_first_x = 0; 535 m_first_y = 0; 536 m_last_x = -1; 537 m_last_y = -1; 538 m_array_of_rows = NULL; 539 } 540 } 541 542 template <class T> 543 void TwoDArray<T>::FreeData() 544 { 545 if (m_length_y>0) 546 { 547 if (m_length_x>0) 548 { 549 delete[] m_array_of_rows[0]; 550 } 551 552 m_length_y = m_length_x = 0; 553 // deallocate the array of rows 554 delete[] m_array_of_rows; 555 } 556 } 557 558 // Related functions 559 560 //! A function for extracting array data 561 template <class T > 562 std::ostream & operator<< (std::ostream & stream, TwoDArray<T> & array) 563 { 564 for (int j=0 ; j<array.LengthY() ; ++j) 565 { 566 for (int i=0 ; i<array.LengthX() ; ++i) 567 { 568 stream << array[j][i] << " "; 569 }// i 570 stream << std::endl; 571 }// j 572 573 return stream; 574 } 575 576 //! A function for inserting array data 577 template <class T > 578 std::istream & operator>> (std::istream & stream, TwoDArray<T> & array) 579 { 580 for (int j=0 ; j<array.LengthY() ; ++j) 581 { 582 for (int i=0 ; i<array.LengthX() ; ++i) 583 { 584 stream >> array[j][i]; 585 }// i 586 }// j 587 588 return stream; 589 } 590 591 } //namespace dirac 592 #endif
1 // Arrays_Test.cpp 2 3 #include <iostream> 4 #include "arrays.h" 5 6 using namespace dirac; 7 using namespace std; 8 9 int main() 10 { 11 // test vector 12 13 cout <<"******** Test OneDArray ***********" << endl; 14 const int N = 10; 15 OneDArray<int> a(N); 16 17 for (int i = 0; i <N; i++) 18 a[i] = i; 19 20 for (int i = 0; i< N; i++) 21 cout << i <<" "; 22 cout <<endl; 23 24 const int first = 1; 25 const int last = 10; 26 OneDArray<int> b(Range(1, 10)); 27 for (int i =first; i<= last; i++) 28 b[i] = i; 29 30 for (int i =first; i<= last; i++) 31 cout << b[i] <<" "; 32 cout <<endl; 33 34 35 // test Matrix 36 cout <<"******** Test TwoDArray ***********" << endl; 37 int height = 4; 38 int width = 8; 39 40 TwoDArray<int> MA(height, width); 41 42 for (int i = 0; i< height; i++) 43 for (int j = 0; j <width; j++) 44 MA[i][j] = i-j; 45 46 for (int i = 0; i< height; i++) 47 { 48 for (int j = 0; j <width; j++) 49 { 50 cout << MA[i][j] <<" "; 51 } 52 cout << endl; 53 } 54 55 56 TwoDArray<int> MB(height, width, 5); 57 for (int i = 0; i< height; i++) 58 { 59 for (int j = 0; j <width; j++) 60 { 61 cout << MA[i][j] <<" "; 62 } 63 cout << endl; 64 } 65 66 67 return 0; 68 }
******** Test OneDArray ***********
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 10
******** Test TwoDArray ***********
0 -1 -2 -3 -4 -5 -6 -7
1 0 -1 -2 -3 -4 -5 -6
2 1 0 -1 -2 -3 -4 -5
3 2 1 0 -1 -2 -3 -4
******** Test TwoDArray initialized with assigne value***********
5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5