00001 /* Ergo, version 3.7, a program for linear scaling electronic structure 00002 * calculations. 00003 * Copyright (C) 2018 Elias Rudberg, Emanuel H. Rubensson, Pawel Salek, 00004 * and Anastasia Kruchinina. 00005 * 00006 * This program is free software: you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation, either version 3 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 * 00019 * Primary academic reference: 00020 * Ergo: An open-source program for linear-scaling electronic structure 00021 * calculations, 00022 * Elias Rudberg, Emanuel H. Rubensson, Pawel Salek, and Anastasia 00023 * Kruchinina, 00024 * SoftwareX 7, 107 (2018), 00025 * <http://dx.doi.org/10.1016/j.softx.2018.03.005> 00026 * 00027 * For further information about Ergo, see <http://www.ergoscf.org>. 00028 */ 00029 00043 #ifndef MAT_ALLOCATOR_HEADER 00044 #define MAT_ALLOCATOR_HEADER 00045 00046 #include <stdexcept> 00047 00048 namespace mat { 00049 00050 template<class Treal> 00051 class Allocator 00052 { 00053 public: 00054 Allocator(int noOfRealsPerBuffer_, 00055 int noOfBuffers_) : 00056 noOfRealsPerBuffer(noOfRealsPerBuffer_), 00057 noOfBuffers(noOfBuffers_) 00058 { 00059 buffer = new Treal[noOfBuffers * noOfRealsPerBuffer]; 00060 nextFreeIndexList = new int[noOfBuffers]; 00061 // Initialize nextFreeIndexList to indicate that all slots are free. 00062 for(int i = 0; i < noOfBuffers-1; i++) 00063 nextFreeIndexList[i] = i + 1; 00064 nextFreeIndexList[noOfBuffers-1] = -1; // last one points to -1 00065 firstFreeIndex = 0; 00066 noOfOccupiedSlots = 0; 00067 } 00068 ~Allocator() 00069 { 00070 delete [] buffer; 00071 delete [] nextFreeIndexList; 00072 } 00073 Treal* alloc() { 00074 if(firstFreeIndex < 0) 00075 throw std::runtime_error("Error in Allocator::alloc(): no free slots."); 00076 Treal* ptrToReturn = &buffer[firstFreeIndex*noOfRealsPerBuffer]; 00077 int firstFreeIndex_new = nextFreeIndexList[firstFreeIndex]; 00078 nextFreeIndexList[firstFreeIndex] = -1; 00079 firstFreeIndex = firstFreeIndex_new; 00080 noOfOccupiedSlots++; 00081 return ptrToReturn; 00082 } 00083 void free(Treal* ptr) { 00084 if(ptr < buffer || ptr >= &buffer[noOfBuffers * noOfRealsPerBuffer]) 00085 throw std::runtime_error("Error in Allocator::free(): unknown ptr."); 00086 int count = ptr - buffer; 00087 if((count % noOfRealsPerBuffer) != 0) 00088 throw std::runtime_error("Error in Allocator::free(): bad ptr."); 00089 int bufferIdx = count / noOfRealsPerBuffer; 00090 if(nextFreeIndexList[bufferIdx] != -1) 00091 throw std::runtime_error("Error in Allocator::free(): -1 not found."); 00092 nextFreeIndexList[bufferIdx] = firstFreeIndex; 00093 firstFreeIndex = bufferIdx; 00094 noOfOccupiedSlots--; 00095 } 00096 bool isFull() { 00097 if(noOfOccupiedSlots == noOfBuffers) 00098 return true; 00099 return false; 00100 } 00101 bool isEmpty() { 00102 if(noOfOccupiedSlots == 0) 00103 return true; 00104 return false; 00105 } 00106 bool ownsPtr(Treal* ptr) { 00107 if(ptr < buffer || ptr >= &buffer[noOfBuffers * noOfRealsPerBuffer]) 00108 return false; 00109 return true; 00110 } 00111 int getNoOfOccupiedSlots() { 00112 return noOfOccupiedSlots; 00113 } 00114 private: 00115 int noOfRealsPerBuffer; 00116 int noOfBuffers; 00117 Treal* buffer; 00118 int* nextFreeIndexList; 00119 int firstFreeIndex; 00120 int noOfOccupiedSlots; 00121 }; // end class Allocator 00122 00123 } /* end namespace mat */ 00124 00125 #endif