Warning: this documentation for the development version is under construction.
00001 // Copyright (C) 2001-2009 Vivien Mallet 00002 // Copyright (C) 2003-2009 Marc Duruflé 00003 // 00004 // This file is part of the linear-algebra library Seldon, 00005 // http://seldon.sourceforge.net/. 00006 // 00007 // Seldon is free software; you can redistribute it and/or modify it under the 00008 // terms of the GNU Lesser General Public License as published by the Free 00009 // Software Foundation; either version 2.1 of the License, or (at your option) 00010 // any later version. 00011 // 00012 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY 00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00014 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 00015 // more details. 00016 // 00017 // You should have received a copy of the GNU Lesser General Public License 00018 // along with Seldon. If not, see http://www.gnu.org/licenses/. 00019 00020 00021 #ifndef SELDON_FILE_ARRAY3D_CXX 00022 00023 #include "Array3D.hxx" 00024 00025 namespace Seldon 00026 { 00027 00028 00029 /**************** 00030 * CONSTRUCTORS * 00031 ****************/ 00032 00033 00035 00038 template <class T, class Allocator> 00039 inline Array3D<T, Allocator>::Array3D() 00040 { 00041 length1_ = 0; 00042 length2_ = 0; 00043 length3_ = 0; 00044 00045 length23_ = 0; 00046 00047 data_ = NULL; 00048 } 00049 00050 00052 00057 template <class T, class Allocator> 00058 inline Array3D<T, Allocator>::Array3D(int i, int j, int k) 00059 { 00060 length1_ = i; 00061 length2_ = j; 00062 length3_ = k; 00063 00064 length23_ = length2_ * length3_; 00065 00066 #ifdef SELDON_CHECK_MEMORY 00067 try 00068 { 00069 #endif 00070 00071 data_ = array3D_allocator_.allocate(i*j*k, this); 00072 00073 #ifdef SELDON_CHECK_MEMORY 00074 } 00075 catch (...) 00076 { 00077 length1_ = 0; 00078 length2_ = 0; 00079 length3_ = 0; 00080 length23_ = 0; 00081 data_ = NULL; 00082 } 00083 if (data_ == NULL && i != 0 && j != 0 && k != 0) 00084 throw NoMemory("Array3D::Array3D(int, int, int)", 00085 string("Unable to allocate memory for an array of size ") 00086 + to_str(static_cast<long int>(i) 00087 * static_cast<long int>(j) 00088 * static_cast<long int>(k) 00089 * static_cast<long int>(sizeof(T))) 00090 + " bytes (" + to_str(i) + " x " + to_str(j) 00091 + " x " + to_str(k) + " elements)."); 00092 #endif 00093 00094 } 00095 00096 00098 template <class T, class Allocator> 00099 Array3D<T, Allocator>::Array3D(const Array3D<T, Allocator>& A) 00100 { 00101 length1_ = 0; 00102 length2_ = 0; 00103 length3_ = 0; 00104 00105 length23_ = 0; 00106 00107 data_ = NULL; 00108 00109 Copy(A); 00110 } 00111 00112 00113 /************** 00114 * DESTRUCTOR * 00115 **************/ 00116 00117 00119 template <class T, class Allocator> 00120 inline Array3D<T, Allocator>::~Array3D() 00121 { 00122 length1_ = 0; 00123 length2_ = 0; 00124 length3_ = 0; 00125 length23_ = 0; 00126 00127 #ifdef SELDON_CHECK_MEMORY 00128 try 00129 { 00130 #endif 00131 00132 if (data_ != NULL) 00133 { 00134 array3D_allocator_.deallocate(data_, length1_ * length23_); 00135 data_ = NULL; 00136 } 00137 00138 #ifdef SELDON_CHECK_MEMORY 00139 } 00140 catch (...) 00141 { 00142 data_ = NULL; 00143 } 00144 #endif 00145 00146 } 00147 00148 00149 /********************* 00150 * MEMORY MANAGEMENT * 00151 *********************/ 00152 00153 00155 00162 template <class T, class Allocator> 00163 inline void Array3D<T, Allocator>::Reallocate(int i, int j, int k) 00164 { 00165 if (i != length1_ || j != length2_ || k != length3_) 00166 { 00167 length1_ = i; 00168 length2_ = j; 00169 length3_ = k; 00170 00171 length23_ = j * k; 00172 00173 #ifdef SELDON_CHECK_MEMORY 00174 try 00175 { 00176 #endif 00177 00178 data_ = 00179 reinterpret_cast<pointer>(array3D_allocator_.reallocate(data_, 00180 i*j*k, 00181 this)); 00182 00183 #ifdef SELDON_CHECK_MEMORY 00184 } 00185 catch (...) 00186 { 00187 length1_ = 0; 00188 length2_ = 0; 00189 length3_ = 0; 00190 length23_ = 0; 00191 data_ = NULL; 00192 } 00193 if (data_ == NULL && i != 0 && j != 0 && k != 0) 00194 throw NoMemory("Array3D::Reallocate(int, int, int)", 00195 string("Unable to reallocate memory") 00196 + " for an array of size " 00197 + to_str(static_cast<long int>(i) 00198 * static_cast<long int>(j) 00199 * static_cast<long int>(k) 00200 * static_cast<long int>(sizeof(T))) 00201 + " bytes (" + to_str(i) + " x " + to_str(j) 00202 + " x " + to_str(k) + " elements)."); 00203 #endif 00204 00205 } 00206 } 00207 00208 00210 00214 template <class T, class Allocator> 00215 inline void Array3D<T, Allocator>::Clear() 00216 { 00217 this->~Array3D(); 00218 this->length1_ = 0; 00219 this->length2_ = 0; 00220 this->length3_ = 0; 00221 } 00222 00223 00224 /***************** 00225 * BASIC METHODS * 00226 *****************/ 00227 00228 00230 00233 template <class T, class Allocator> 00234 int Array3D<T, Allocator>::GetLength1() const 00235 { 00236 return length1_; 00237 } 00238 00239 00241 00244 template <class T, class Allocator> 00245 int Array3D<T, Allocator>::GetLength2() const 00246 { 00247 return length2_; 00248 } 00249 00250 00252 00255 template <class T, class Allocator> 00256 int Array3D<T, Allocator>::GetLength3() const 00257 { 00258 return length3_; 00259 } 00260 00261 00263 00268 template <class T, class Allocator> 00269 int Array3D<T, Allocator>::GetSize() const 00270 { 00271 return length1_ * length23_; 00272 } 00273 00274 00276 00282 template <class T, class Allocator> 00283 int Array3D<T, Allocator>::GetDataSize() const 00284 { 00285 return length1_ * length23_; 00286 } 00287 00288 00290 00295 template <class T, class Allocator> 00296 typename Array3D<T, Allocator>::pointer Array3D<T, Allocator> 00297 ::GetData() const 00298 { 00299 return data_; 00300 } 00301 00302 00303 /********************************** 00304 * ELEMENT ACCESS AND AFFECTATION * 00305 **********************************/ 00306 00307 00309 00316 template <class T, class Allocator> 00317 inline typename Array3D<T, Allocator>::reference 00318 Array3D<T, Allocator>::operator() (int i, int j, int k) 00319 { 00320 00321 #ifdef SELDON_CHECK_BOUNDS 00322 if (i < 0 || i >= length1_) 00323 throw WrongIndex("Array3D::operator()", 00324 string("Index along dimension #1 should be in [0, ") 00325 + to_str(length1_-1) + "], but is equal to " 00326 + to_str(i) + "."); 00327 if (j < 0 || j >= length2_) 00328 throw WrongIndex("Array3D::operator()", 00329 string("Index along dimension #2 should be in [0, ") 00330 + to_str(length2_-1) + "], but is equal to " 00331 + to_str(j) + "."); 00332 if (k < 0 || k >= length3_) 00333 throw WrongIndex("Array3D::operator()", 00334 string("Index along dimension #3 should be in [0, ") 00335 + to_str(length3_-1) + "], but is equal to " 00336 + to_str(k) + "."); 00337 #endif 00338 00339 return data_[i * length23_ + j * length3_ + k]; 00340 } 00341 00342 00344 00351 template <class T, class Allocator> 00352 inline typename Array3D<T, Allocator>::const_reference 00353 Array3D<T, Allocator>::operator() (int i, int j, int k) const 00354 { 00355 00356 #ifdef SELDON_CHECK_BOUNDS 00357 if (i < 0 || i >= length1_) 00358 throw WrongIndex("Array3D::operator()", 00359 string("Index along dimension #1 should be in [0, ") 00360 + to_str(length1_-1) + "], but is equal to " 00361 + to_str(i) + "."); 00362 if (j < 0 || j >= length2_) 00363 throw WrongIndex("Array3D::operator()", 00364 string("Index along dimension #2 should be in [0, ") 00365 + to_str(length2_-1) + "], but is equal to " 00366 + to_str(j) + "."); 00367 if (k < 0 || k >= length3_) 00368 throw WrongIndex("Array3D::operator()", 00369 string("Index along dimension #3 should be in [0, ") 00370 + to_str(length3_-1) + "], but is equal to " 00371 + to_str(k) + "."); 00372 #endif 00373 00374 return data_[i*length23_ + j*length3_ + k]; 00375 } 00376 00378 00383 template <class T, class Allocator> 00384 inline Array3D<T, Allocator>& Array3D<T, Allocator>::operator= 00385 (const Array3D<T, Allocator>& A) 00386 { 00387 Copy(A); 00388 00389 return *this; 00390 } 00391 00393 00398 template <class T, class Allocator> 00399 inline void Array3D<T, Allocator>::Copy(const Array3D<T, Allocator>& A) 00400 { 00401 Reallocate(A.GetLength1(), A.GetLength2(), A.GetLength3()); 00402 00403 array3D_allocator_.memorycpy(data_, A.GetData(), GetDataSize()); 00404 } 00405 00406 00407 /************************ 00408 * CONVENIENT FUNCTIONS * 00409 ************************/ 00410 00411 00413 00417 template <class T, class Allocator> 00418 void Array3D<T, Allocator>::Zero() 00419 { 00420 array3D_allocator_.memoryset(data_, char(0), 00421 GetDataSize()*sizeof(value_type)); 00422 } 00423 00424 00426 00430 template <class T, class Allocator> 00431 void Array3D<T, Allocator>::Fill() 00432 { 00433 for (int i = 0; i < GetDataSize(); i++) 00434 data_[i] = i; 00435 } 00436 00437 00439 00443 template <class T, class Allocator> 00444 template <class T0> 00445 void Array3D<T, Allocator>::Fill(const T0& x) 00446 { 00447 for (int i = 0; i < GetDataSize(); i++) 00448 data_[i] = x; 00449 } 00450 00451 00453 00456 template <class T, class Allocator> 00457 void Array3D<T, Allocator>::FillRand() 00458 { 00459 srand(time(NULL)); 00460 for (int i = 0; i < GetDataSize(); i++) 00461 data_[i] = rand(); 00462 } 00463 00464 00466 00469 template <class T, class Allocator> 00470 void Array3D<T, Allocator>::Print() const 00471 { 00472 int i, j, k; 00473 00474 for (i = 0; i < GetLength1(); i++) 00475 { 00476 for (j = 0; j < GetLength2(); j++) 00477 { 00478 for (k = 0; k < GetLength3(); k++) 00479 cout << (*this)(i, j, k) << '\t'; 00480 cout << endl; 00481 } 00482 cout << endl; 00483 } 00484 } 00485 00486 00487 /************************** 00488 * INPUT/OUTPUT FUNCTIONS * 00489 **************************/ 00490 00491 00493 00500 template <class T, class Allocator> void Array3D<T, Allocator> 00501 ::Write(string FileName) const 00502 { 00503 ofstream FileStream; 00504 FileStream.open(FileName.c_str(), ofstream::binary); 00505 00506 #ifdef SELDON_CHECK_IO 00507 // Checks if the file was opened. 00508 if (!FileStream.is_open()) 00509 throw IOError("Array3D::Write(string FileName)", 00510 string("Unable to open file \"") + FileName + "\"."); 00511 #endif 00512 00513 Write(FileStream); 00514 00515 FileStream.close(); 00516 } 00517 00518 00520 00527 template <class T, class Allocator> void Array3D<T, Allocator> 00528 ::Write(ofstream& FileStream) const 00529 { 00530 00531 #ifdef SELDON_CHECK_IO 00532 // Checks if the stream is ready. 00533 if (!FileStream.good()) 00534 throw IOError("Array3D::Write(ofstream& FileStream)", 00535 "Stream is not ready."); 00536 #endif 00537 00538 FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&length1_)), 00539 sizeof(int)); 00540 FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&length2_)), 00541 sizeof(int)); 00542 FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&length3_)), 00543 sizeof(int)); 00544 00545 FileStream.write(reinterpret_cast<char*>(data_), 00546 length23_ * length1_ * sizeof(value_type)); 00547 00548 #ifdef SELDON_CHECK_IO 00549 // Checks if data was written. 00550 if (!FileStream.good()) 00551 throw IOError("Array3D::Write(ofstream& FileStream)", 00552 string("Output operation failed.") 00553 + string(" The output file may have been removed") 00554 + " or there is no space left on device."); 00555 #endif 00556 00557 } 00558 00559 00561 00568 template <class T, class Allocator> 00569 void Array3D<T, Allocator>::Read(string FileName) 00570 { 00571 ifstream FileStream; 00572 FileStream.open(FileName.c_str(), ifstream::binary); 00573 00574 #ifdef SELDON_CHECK_IO 00575 // Checks if the file was opened. 00576 if (!FileStream.is_open()) 00577 throw IOError("Array3D::Read(string FileName)", 00578 string("Unable to open file \"") + FileName + "\"."); 00579 #endif 00580 00581 Read(FileStream); 00582 00583 FileStream.close(); 00584 } 00585 00586 00588 00595 template <class T, class Allocator> 00596 void Array3D<T, Allocator> 00597 ::Read(ifstream& FileStream) 00598 { 00599 00600 #ifdef SELDON_CHECK_IO 00601 // Checks if the stream is ready. 00602 if (!FileStream.good()) 00603 throw IOError("Matrix_Pointers::Read(ifstream& FileStream)", 00604 "Stream is not ready."); 00605 #endif 00606 00607 int new_l1, new_l2, new_l3; 00608 FileStream.read(reinterpret_cast<char*>(&new_l1), sizeof(int)); 00609 FileStream.read(reinterpret_cast<char*>(&new_l2), sizeof(int)); 00610 FileStream.read(reinterpret_cast<char*>(&new_l3), sizeof(int)); 00611 Reallocate(new_l1, new_l2, new_l3); 00612 00613 FileStream.read(reinterpret_cast<char*>(data_), 00614 length23_ * length1_ * sizeof(value_type)); 00615 00616 #ifdef SELDON_CHECK_IO 00617 // Checks if data was read. 00618 if (!FileStream.good()) 00619 throw IOError("Array3D::Read(ifstream& FileStream)", 00620 string("Input operation failed.") 00621 + string(" The input file may have been removed") 00622 + " or may not contain enough data."); 00623 #endif 00624 00625 } 00626 00627 00629 00634 template <class T, class Allocator> 00635 ostream& operator << (ostream& out, 00636 const Array3D<T, Allocator>& A) 00637 { 00638 int i, j, k; 00639 00640 for (i = 0; i < A.GetLength1(); i++) 00641 { 00642 for (j = 0; j < A.GetLength2(); j++) 00643 { 00644 for (k = 0; k < A.GetLength3(); k++) 00645 out << A(i, j, k) << '\t'; 00646 out << endl; 00647 } 00648 out << endl; 00649 } 00650 00651 return out; 00652 } 00653 00654 00656 00660 template <class T0, class T, class Allocator> 00661 void Mlt(const T0& alpha, Array3D<T, Allocator>& A) 00662 { 00663 T* data = A.GetData(); 00664 for (int i = 0; i < A.GetDataSize(); i++) 00665 data[i] *= alpha; 00666 } 00667 00668 00669 } // namespace Seldon. 00670 00671 #define SELDON_FILE_ARRAY3D_CXX 00672 #endif