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