1 
2 /******************************************************************************
3  *
4  *  This file is part of meryl-utility, a collection of miscellaneous code
5  *  used by Meryl, Canu and others.
6  *
7  *  This software is based on:
8  *    'Canu' v2.0              (https://github.com/marbl/canu)
9  *  which is based on:
10  *    'Celera Assembler' r4587 (http://wgs-assembler.sourceforge.net)
11  *    the 'kmer package' r1994 (http://kmer.sourceforge.net)
12  *
13  *  Except as indicated otherwise, this is a 'United States Government Work',
14  *  and is released in the public domain.
15  *
16  *  File 'README.licenses' in the root directory of this distribution
17  *  contains full conditions and disclaimers.
18  */
19 
20 #ifndef ARRAYS_H
21 #define ARRAYS_H
22 
23 #include "types.H"
24 #include <algorithm>
25 
26 
27 enum class _raAct {
28   doNothing        = 0x00,
29   copyData         = 0x01,
30   clearNew         = 0x02,
31   copyDataClearNew = 0x03,
32 };
33 
34 
35 inline   //  Combine two _raAct into one.
36 _raAct
37 operator|(_raAct a, _raAct b) {
38 
39   if (a == _raAct::doNothing)  return(b);
40   if (b == _raAct::doNothing)  return(a);
41 
42   if ((a == _raAct::copyData) && (b == _raAct::copyData))   return(_raAct::copyData);
43   if ((a == _raAct::copyData) && (b == _raAct::clearNew))   return(_raAct::copyDataClearNew);
44   if ((a == _raAct::clearNew) && (b == _raAct::copyData))   return(_raAct::copyDataClearNew);
45   if ((a == _raAct::clearNew) && (b == _raAct::clearNew))   return(_raAct::clearNew);
46 
47   if (a == _raAct::copyDataClearNew)  return(_raAct::copyDataClearNew);
48   if (b == _raAct::copyDataClearNew)  return(_raAct::copyDataClearNew);
49 
50   assert(0);
51   return(_raAct::doNothing);
52 }
53 
54 
55 inline   //  Return true if _raAct a has property b set.
56 bool
57 operator&(_raAct a, _raAct b) {
58 
59   if ((a == _raAct::copyData)         && (b == _raAct::copyData))           return(true);
60   if ((a == _raAct::copyDataClearNew) && (b == _raAct::copyData))           return(true);
61 
62   if ((a == _raAct::clearNew)         && (b == _raAct::clearNew))           return(true);
63   if ((a == _raAct::copyDataClearNew) && (b == _raAct::clearNew))           return(true);
64 
65   if ((a == _raAct::copyDataClearNew) && (b == _raAct::copyDataClearNew))   return(true);
66 
67   return(false);
68 }
69 
70 
71 //  Allocate an array of size 'allocSize', and set 'arrayMax' to that value.
72 //  By default. clear the array.
73 template<typename TT, typename LL>
74 void
75 allocateArray(TT*& array, LL &arrayMax, uint64 allocSize, _raAct op=_raAct::clearNew) {
76 
77   if (array != NULL)
78     delete [] array;
79 
80   arrayMax = allocSize;
81   array    = new TT [allocSize];
82 
83   assert(arrayMax == allocSize);   //  Make sure we don't truncate the value!
84 
85   if (op == _raAct::clearNew)
86     memset(array, 0, sizeof(TT) * allocSize);
87 }
88 
89 
90 //  Allocate an array of size 'allocSize'.
91 //  By default, clear the array.
92 template<typename TT>
93 void
94 allocateArray(TT*& array, uint64 allocSize, _raAct op=_raAct::clearNew) {
95 
96   if (array != NULL)
97     delete [] array;
98 
99   array    = new TT [allocSize];
100 
101   if (op == _raAct::clearNew)
102     memset(array, 0, sizeof(TT) * allocSize);
103 }
104 
105 
106 
107 template<typename TT>
108 TT *
duplicateString(TT const * fr)109 duplicateString(TT const *fr) {
110 
111   if (fr == NULL)
112     return(NULL);
113 
114   uint32  ln = strlen(fr);
115   TT     *to = new TT [ln+1];
116 
117   memcpy(to, fr, sizeof(TT) * (ln+1));
118 
119   return(to);
120 }
121 
122 
123 
124 template<typename TT, typename LL>
125 void
126 duplicateArray(TT*& to, LL &toLen, LL &toMax, TT const *fr, LL frLen, LL frMax=0, bool forceAlloc=false) {
127 
128   if (fr == NULL)
129     assert(frLen == 0);
130 
131   if ((toMax < frLen) || (forceAlloc)) {
132     delete [] to;
133 
134     toMax = frLen;
135     to    = new TT [toMax];
136   }
137 
138   toLen = frLen;
139 
140   if (frLen > 0)
141     memcpy(to, fr, sizeof(TT) * frLen);
142 }
143 
144 
145 //  Set the array size to 'newMax'.
146 //  No guards, the array will ALWAYS be reallocated.
147 //
148 template<typename TT, typename LL>
149 void
150 setArraySize(TT*& array, uint64 arrayLen, LL &arrayMax, uint64 newMax, _raAct op=_raAct::copyData) {
151 
152   arrayMax =          newMax;
153   arrayLen = std::min(newMax, arrayLen);
154 
155   TT *copy = new TT [arrayMax];
156 
157   if ((array != nullptr) &&
158       (arrayLen > 0) &&
159       ((op == _raAct::copyData) ||
160        (op == _raAct::copyDataClearNew)))
161     for (uint32 ii=0; ii<arrayLen; ii++)
162       copy[ii] = array[ii];
163 
164   delete [] array;
165   array = copy;
166 
167   if ((op == _raAct::clearNew) ||
168       (op == _raAct::copyDataClearNew))
169     for (uint32 ii=arrayLen; ii<arrayMax; ii++)
170       copy[ii] = TT();
171 }
172 
173 
174 
175 //  Ensure that there is enough space to hold one more element in the array.
176 //  Increase the array by 'moreSpace' if needed.
177 //
178 //  With the array used as a stack, a call of
179 //    increaseArray(arr, arrLen, arrMax, 32)
180 //  will allocate 32 more elements if arrLen == arrMax, and do nothing
181 //  otherwise.  After the call, array element arr[arrLen] is guaranteed to
182 //  exist.  If arrLen > arrMax, see below.
183 //
184 //  With the array used for random access, a call of
185 //    increaseArray(arr, idx, arrMax, 32)
186 //  will do nothing if idx < arrMax, and resize the array to have idx+32
187 //  elements otherwise.
188 //
189 //  In both cases, if 'moreSpace' is 0, it is reset to 1.
190 //
191 //  If the array is reallocated, the contents of the entire array are copied
192 //  to the new space.  New elements are NOT cleared to zero; override op as
193 //  desired.
194 //
195 template<typename TT, typename LL>
196 void
197 increaseArray(TT*& array, uint64 idx, LL &arrayMax, uint64 moreSpace, _raAct op=_raAct::copyData) {
198   uint64  newMax = idx + ((moreSpace == 0) ? 1 : moreSpace);
199 
200   if (idx < arrayMax)
201     return;
202 
203   setArraySize(array, arrayMax, arrayMax, newMax, op);
204 }
205 
206 
207 template<typename T1, typename T2, typename LL>
208 void
209 increaseArrayPair(T1*& array1, T2*& array2, uint64 idx, LL &arrayMax, uint64 moreSpace, _raAct op=_raAct::copyData) {
210   uint64  newMax = idx + ((moreSpace == 0) ? 1 : moreSpace);
211 
212   if (idx < arrayMax)
213     return;
214 
215   setArraySize(array1, arrayMax, arrayMax, newMax, op);
216   setArraySize(array2, arrayMax, arrayMax, newMax, op);
217 }
218 
219 
220 //  Resize the array so that it is at least as big as new max.  Do nothing
221 //  if the array is big enough already.
222 
223 template<typename TT, typename LL>
224 void
225 resizeArray(TT*& array, uint64 arrayLen, LL &arrayMax, uint64 newMax, _raAct op=_raAct::copyData) {
226 
227   if (newMax <= arrayMax)
228     return;
229 
230   setArraySize(array, arrayLen, arrayMax, newMax, op);
231 }
232 
233 
234 template<typename T1, typename T2, typename LL>
235 void
236 resizeArrayPair(T1*& array1, T2*& array2, uint64 arrayLen, LL &arrayMax, uint64 newMax, _raAct op=_raAct::copyData) {
237 
238   if (newMax <= arrayMax)
239     return;
240 
241   setArraySize(array1, arrayLen, arrayMax, newMax, op);
242   setArraySize(array2, arrayLen, arrayMax, newMax, op);
243 }
244 
245 
246 #endif  //  ARRAYS_H
247