1 | ////////////////////////////////////////////////////////////////////////////////
|
---|
2 | // NTL Nonstandard Template Library for C++
|
---|
3 | // Copyright (c) 2003 by Miroslav Fidler, Tomas Rylek
|
---|
4 | //
|
---|
5 | // Created by Miroslav Fidler, Tomas Rylek, cxl@volny.cz
|
---|
6 | //
|
---|
7 | // Permission to use, copy, modify, distribute and sell this software for any
|
---|
8 | // purpose is hereby granted without fee, provided that the above copyright
|
---|
9 | // notice appear in all copies and that both that copyright notice and this
|
---|
10 | // permission notice appear in supporting documentation.
|
---|
11 | // The author makes no representations about the suitability of this software
|
---|
12 | // for any purpose. It is provided "as is"
|
---|
13 | // without express or implied warranty.
|
---|
14 | ////////////////////////////////////////////////////////////////////////////////
|
---|
15 |
|
---|
16 | template <class T>
|
---|
17 | inline int sgn(T a) { return a > 0 ? 1 : a < 0 ? -1 : 0; }
|
---|
18 |
|
---|
19 | template <class T>
|
---|
20 | inline T tabs(T a) { return (a >= 0 ? a : -a); }
|
---|
21 |
|
---|
22 | template <class T>
|
---|
23 | inline int cmp(const T& a, const T& b) { return a > b ? 1 : a < b ? -1 : 0; }
|
---|
24 |
|
---|
25 | template <class I>
|
---|
26 | void Reverse(I start, I end)
|
---|
27 | {
|
---|
28 | if(start != end && --end != start)
|
---|
29 | do
|
---|
30 | IterSwap(start, end);
|
---|
31 | while(++start != end && --end != start);
|
---|
32 | }
|
---|
33 |
|
---|
34 | template <class C>
|
---|
35 | void Reverse(C& container)
|
---|
36 | {
|
---|
37 | Reverse(container.Begin(), container.End());
|
---|
38 | }
|
---|
39 |
|
---|
40 | template <class T, class V>
|
---|
41 | void Sum(V& sum, T ptr, T end)
|
---|
42 |
|
---|
43 | {
|
---|
44 | while(ptr != end)
|
---|
45 | sum += *ptr++;
|
---|
46 | }
|
---|
47 |
|
---|
48 | template <class T>
|
---|
49 | typename T::ValueType Sum(const T& c)
|
---|
50 | {
|
---|
51 | typename T::ValueType sum;
|
---|
52 | Sum(sum, c.Begin(), c.End());
|
---|
53 | return sum;
|
---|
54 | }
|
---|
55 |
|
---|
56 | template <class T>
|
---|
57 | typename T::ValueType Sum(const T& c, const typename T::ValueType& init)
|
---|
58 | {
|
---|
59 | typename T::ValueType sum = init;
|
---|
60 | Sum(sum, c.Begin(), c.End());
|
---|
61 | return sum;
|
---|
62 | }
|
---|
63 |
|
---|
64 | template <class T>
|
---|
65 | typename T::ValueType Sum0(const T& c)
|
---|
66 | {
|
---|
67 | typename T::ValueType sum = 0;
|
---|
68 | Sum(sum, c.Begin(), c.End());
|
---|
69 | return sum;
|
---|
70 | }
|
---|
71 |
|
---|
72 | template <class T>
|
---|
73 | T MinElement(T ptr, T end)
|
---|
74 | {
|
---|
75 | ASSERT(ptr != end);
|
---|
76 | T min = ptr;
|
---|
77 | while(++ptr != end)
|
---|
78 | if(*ptr < *min) min = ptr;
|
---|
79 | return min;
|
---|
80 | }
|
---|
81 |
|
---|
82 | template <class T>
|
---|
83 | const typename T::ValueType& Min(const T& c)
|
---|
84 | {
|
---|
85 | return *MinElement(c.Begin(), c.End());
|
---|
86 | }
|
---|
87 |
|
---|
88 | template <class T>
|
---|
89 | T MaxElement(T ptr, T end)
|
---|
90 | {
|
---|
91 | ASSERT(ptr != end);
|
---|
92 | T max = ptr;
|
---|
93 | while(++ptr != end)
|
---|
94 | if(*max < *ptr) max = ptr;
|
---|
95 | return max;
|
---|
96 | }
|
---|
97 |
|
---|
98 | template <class T>
|
---|
99 | const typename T::ValueType& Max(const T& c)
|
---|
100 | {
|
---|
101 | return *MaxElement(c.Begin(), c.End());
|
---|
102 | }
|
---|
103 |
|
---|
104 | template<class T>
|
---|
105 | struct StdEqual
|
---|
106 | {
|
---|
107 | bool operator () (const T& a, const T& b) const { return a == b; }
|
---|
108 | };
|
---|
109 |
|
---|
110 | template<class T>
|
---|
111 | struct StdLess {
|
---|
112 | bool operator () (const T& a, const T& b) const { return a < b; }
|
---|
113 | };
|
---|
114 |
|
---|
115 | template<class T>
|
---|
116 | struct StdGreater
|
---|
117 | {
|
---|
118 | bool operator () (const T& a, const T& b) const { return a > b; }
|
---|
119 | };
|
---|
120 |
|
---|
121 | template <class T, class C>
|
---|
122 | bool Compare(T ptr1, T end1, T ptr2, T end2, const C& compare)
|
---|
123 | {
|
---|
124 | for(; ptr1 != end1 && ptr2 != end2; ++ptr1, ++ptr2)
|
---|
125 | if(!compare(*ptr1, *ptr2)) return false;
|
---|
126 | return ptr1 == end1 && ptr2 == end2;
|
---|
127 | }
|
---|
128 |
|
---|
129 | template <class T, class C>
|
---|
130 | bool Compare(const T& c1, const T& c2, const C& compare)
|
---|
131 | {
|
---|
132 | return Compare(c1.Begin(), c1.End(), c2.Begin(), c2.End(), compare);
|
---|
133 | }
|
---|
134 |
|
---|
135 | template <class T>
|
---|
136 | bool Compare(const T& c1, const T& c2)
|
---|
137 | {
|
---|
138 | typedef typename T::ValueType VT;
|
---|
139 | return Compare(c1, c2, StdEqual<VT>());
|
---|
140 | }
|
---|
141 |
|
---|
142 | template <class T, class V, class C>
|
---|
143 | T Find(T ptr, T end, const V& value, const C& equal)
|
---|
144 | {
|
---|
145 | while(ptr != end) {
|
---|
146 | if(equal(*ptr, value)) return ptr;
|
---|
147 | ptr++;
|
---|
148 | }
|
---|
149 | return NULL;
|
---|
150 | }
|
---|
151 |
|
---|
152 | template <class T, class V>
|
---|
153 | T Find(T ptr, T end, const V& value)
|
---|
154 | {
|
---|
155 | return Find(ptr, end, value, StdEqual<T>());
|
---|
156 | }
|
---|
157 |
|
---|
158 | template <class T, class V, class C>
|
---|
159 | int FindIndex(const T& cont, const V& value, const C& equal)
|
---|
160 | {
|
---|
161 | for(int i = 0; i < cont.GetCount(); i++)
|
---|
162 | if(equal(cont[i], value)) return i;
|
---|
163 | return -1;
|
---|
164 | }
|
---|
165 |
|
---|
166 | template <class T, class V>
|
---|
167 | int FindIndex(const T& cont, const V& value)
|
---|
168 | {
|
---|
169 | typedef typename T::ValueType VT;
|
---|
170 | return FindIndex(cont, value, StdEqual<VT>());
|
---|
171 | }
|
---|
172 |
|
---|
173 | //////////////////////////////////////////////////////////////////////
|
---|
174 | // BinFind
|
---|
175 |
|
---|
176 | template <class I, class K, class L>
|
---|
177 | int BinFindIndex(I begin, I end, const K& key, const L& less)
|
---|
178 | {
|
---|
179 | if(begin == end)
|
---|
180 | return 0;
|
---|
181 | int min = 0;
|
---|
182 | int max = end - begin;
|
---|
183 |
|
---|
184 | while(min < max)
|
---|
185 | {
|
---|
186 | int mid = (max + min) >> 1;
|
---|
187 | if(less(*(begin + mid), key))
|
---|
188 | min = mid + 1;
|
---|
189 | else
|
---|
190 | max = mid;
|
---|
191 | }
|
---|
192 | return min;
|
---|
193 | }
|
---|
194 |
|
---|
195 | template <class C, class K, class L>
|
---|
196 | inline int BinFindIndex(const C& container, const K& key, const L& less)
|
---|
197 | {
|
---|
198 | return BinFindIndex(container.Begin(), container.End(), key, less);
|
---|
199 | }
|
---|
200 |
|
---|
201 | template <class C, class K>
|
---|
202 | inline int BinFindIndex(const C& container, const K& key)
|
---|
203 | {
|
---|
204 | typedef typename C::ValueType VT;
|
---|
205 | return BinFindIndex(container, key, StdLess<VT>());
|
---|
206 | }
|
---|
207 |
|
---|
208 | template <class I, class K, class L>
|
---|
209 | inline I BinFind(I begin, I end, const K& key, const L& less)
|
---|
210 | {
|
---|
211 | return begin + BinFindIndex(begin, end, key, less);
|
---|
212 | }
|
---|
213 |
|
---|
214 | template <class C, class K, class L>
|
---|
215 | inline typename C::ConstIterator BinFind(const C& container, const K& key, const L& less)
|
---|
216 | {
|
---|
217 | return BinFind(container.Begin(), container.End(), key, less);
|
---|
218 | }
|
---|
219 |
|
---|
220 | template <class C, class K>
|
---|
221 | inline typename C::ConstIterator BinFind(const C& container, const K& key)
|
---|
222 | {
|
---|
223 | typedef typename C::ValueType VT;
|
---|
224 | return BinFind(container, key, StdLess<VT>());
|
---|
225 | }
|
---|
226 |
|
---|
227 | // -------------------------------------------------------------------
|
---|
228 |
|
---|
229 | template <class C, class T, class L>
|
---|
230 | int FindLowerBound(const C& v, int pos, int count, const T& val, const L& less)
|
---|
231 | {
|
---|
232 | while(count > 0) {
|
---|
233 | int half = count >> 1;
|
---|
234 | int m = pos + half;
|
---|
235 | if(less(v[m], val)) {
|
---|
236 | pos = m + 1;
|
---|
237 | count = count - half - 1;
|
---|
238 | }
|
---|
239 | else
|
---|
240 | count = half;
|
---|
241 | }
|
---|
242 | return pos;
|
---|
243 | }
|
---|
244 |
|
---|
245 | template <class I, class T, class L>
|
---|
246 | I FindLowerBoundIter(I begin, I end, const T& val, const L& less)
|
---|
247 | {
|
---|
248 | return begin + FindLowerBound(begin, 0, end - begin, val, less);
|
---|
249 | }
|
---|
250 |
|
---|
251 | template <class I, class T>
|
---|
252 | I FindLowerBoundIter(I begin, I end, const T& val)
|
---|
253 | {
|
---|
254 | return begin + FindLowerBound(begin, 0, end - begin, val, StdLess<T>());
|
---|
255 | }
|
---|
256 |
|
---|
257 | template <class C, class T, class L>
|
---|
258 | int FindLowerBound(const C& v, const T& val, const L& less)
|
---|
259 | {
|
---|
260 | return FindLowerBound(v, 0, v.GetCount(), val, less);
|
---|
261 | }
|
---|
262 |
|
---|
263 | template <class C, class T>
|
---|
264 | int FindLowerBound(const C& v, const T& val)
|
---|
265 | {
|
---|
266 | return FindLowerBound(v, val, StdLess<TYPENAME C::ValueType>());
|
---|
267 | }
|
---|
268 |
|
---|
269 | template <class C, class T, class L>
|
---|
270 | int FindUpperBound(const C& v, int pos, int count, const T& val, const L& less)
|
---|
271 | {
|
---|
272 | while(count > 0) {
|
---|
273 | int half = count >> 1;
|
---|
274 | int m = pos + half;
|
---|
275 | if(less(val, v[m]))
|
---|
276 | count = half;
|
---|
277 | else {
|
---|
278 | pos = m + 1;
|
---|
279 | count = count - half - 1;
|
---|
280 | }
|
---|
281 | }
|
---|
282 | return pos;
|
---|
283 | }
|
---|
284 |
|
---|
285 | template <class I, class T, class L>
|
---|
286 | I FindUpperBoundIter(I begin, I end, const T& val, const L& less)
|
---|
287 | {
|
---|
288 | return begin + FindUpperBound(begin, 0, end - begin, val, less);
|
---|
289 | }
|
---|
290 |
|
---|
291 | template <class I, class T>
|
---|
292 | I FindUpperBoundIter(I begin, I end, const T& val)
|
---|
293 | {
|
---|
294 | return begin + FindUpperBound(begin, 0, end - begin, val, StdLess<T>());
|
---|
295 | }
|
---|
296 |
|
---|
297 | template <class C, class T, class L>
|
---|
298 | int FindUpperBound(const C& v, const T& val, const L& less)
|
---|
299 | {
|
---|
300 | return FindUpperBound(v, 0, v.GetCount(), val, less);
|
---|
301 | }
|
---|
302 |
|
---|
303 | template <class C, class T>
|
---|
304 | int FindUpperBound(const C& v, const T& val)
|
---|
305 | {
|
---|
306 | return FindUpperBound(v, val, StdLess<TYPENAME C::ValueType>());
|
---|
307 | }
|
---|
308 |
|
---|
309 | template <class C, class T, class L>
|
---|
310 | int FindBinary(const C& v, const T& val, int pos, int count, const L& less)
|
---|
311 | {
|
---|
312 | int i = FindLowerBound(v, pos, count, val, less);
|
---|
313 | return i < count && !less(val, v[i]) ? i : -1;
|
---|
314 | }
|
---|
315 |
|
---|
316 | template <class I, class T, class L>
|
---|
317 | I FindBinaryIter(I begin, I end, const T& val, const L& less)
|
---|
318 | {
|
---|
319 | int q = FindUpperBound(begin, begin, end, val, less);
|
---|
320 | return q < 0 ? NULL : begin + q;
|
---|
321 | }
|
---|
322 |
|
---|
323 | template <class I, class T>
|
---|
324 | I FindBinaryIter(I begin, I end, const T& val)
|
---|
325 | {
|
---|
326 | return FindBinaryIter(begin, end, val, StdLess<T>());
|
---|
327 | }
|
---|
328 |
|
---|
329 | template <class C, class T, class L>
|
---|
330 | int FindBinary(const C& v, const T& val, const L& less)
|
---|
331 | {
|
---|
332 | return FindBinary(v, val, 0, v.GetCount(), less);
|
---|
333 | }
|
---|
334 |
|
---|
335 | template <class C, class T>
|
---|
336 | int FindBinary(const C& v, const T& val)
|
---|
337 | {
|
---|
338 | return FindBinary(v, val, StdLess<TYPENAME C::ValueType>());
|
---|
339 | }
|
---|
340 |
|
---|
341 | //////////////////////////////////////////////////////////////////////
|
---|
342 | // BinFindComp
|
---|
343 |
|
---|
344 | template <class I, class K, class X>
|
---|
345 | int BinFindCompIndex(I begin, I end, const K& key, const X& comp)
|
---|
346 | {
|
---|
347 | if(begin == end) // empty array
|
---|
348 | return 0;
|
---|
349 | int min = 0;
|
---|
350 | int max = end - begin;
|
---|
351 | while(min < max)
|
---|
352 | {
|
---|
353 | int mid = (max + min) >> 1;
|
---|
354 | if(comp.Compare(key, *(begin + mid)) > 0)
|
---|
355 | min = mid + 1;
|
---|
356 | else
|
---|
357 | max = mid;
|
---|
358 | }
|
---|
359 | return min;
|
---|
360 | }
|
---|
361 |
|
---|
362 | template <class C, class K, class X>
|
---|
363 | inline int BinFindCompIndex(const C& container, const K& key, const X& comp)
|
---|
364 | {
|
---|
365 | return BinFindCompIndex(container.Begin(), container.End(), key, comp);
|
---|
366 | }
|
---|
367 |
|
---|
368 | template <class I, class K, class X>
|
---|
369 | inline I BinFindComp(I begin, I end, const K& key, const X& comp)
|
---|
370 | {
|
---|
371 | return begin + BinFindCompIndex(begin, end, key, comp);
|
---|
372 | }
|
---|
373 |
|
---|
374 | template <class C, class K, class X>
|
---|
375 | inline typename C::ConstIterator BinFindComp(const C& container, const K& key, const X& comp)
|
---|
376 | {
|
---|
377 | return BinFindComp(container.Begin(), container.End(), key, comp);
|
---|
378 | }
|
---|
379 |
|
---|
380 | //////////////////////////////////////////////////////////////////////
|
---|
381 | // Append
|
---|
382 |
|
---|
383 | template <class T, class V>
|
---|
384 | void Append(T& dst, V ptr, V end)
|
---|
385 | {
|
---|
386 | for(; ptr != end; ++ptr)
|
---|
387 | dst.Add(*ptr);
|
---|
388 | }
|
---|
389 |
|
---|
390 | template <class T, class V>
|
---|
391 | void Append(T& dst, V ptr, int n)
|
---|
392 | {
|
---|
393 | for(; n--; ++ptr)
|
---|
394 | dst.Add(*ptr);
|
---|
395 | }
|
---|
396 |
|
---|
397 | template <class T, class V>
|
---|
398 | void Append(T& dst, const V& src)
|
---|
399 | {
|
---|
400 | Append(dst, src.Begin(), src.End());
|
---|
401 | }
|
---|
402 |
|
---|
403 | //////////////////////////////////////////////////////////////////////
|
---|
404 | // FindAppend::
|
---|
405 |
|
---|
406 | template <class C, class I>
|
---|
407 | C& FindAppend(C& dest, I begin, I end)
|
---|
408 | {
|
---|
409 | for(; begin != end; ++begin)
|
---|
410 | dest.FindAdd(*begin);
|
---|
411 | return dest;
|
---|
412 | }
|
---|
413 |
|
---|
414 | //////////////////////////////////////////////////////////////////////
|
---|
415 |
|
---|
416 | template <class C, class S>
|
---|
417 | inline C& FindAppend(C& dest, const S& source)
|
---|
418 | {
|
---|
419 | return FindAppend(dest, source.Begin(), source.End());
|
---|
420 | }
|
---|
421 |
|
---|
422 | //////////////////////////////////////////////////////////////////////
|
---|
423 |
|
---|
424 | template <class C, class L>
|
---|
425 | C& AppendSorted(C& dest, const C& src, const L& less)
|
---|
426 | {
|
---|
427 | if(src.IsEmpty())
|
---|
428 | return dest;
|
---|
429 | if(dest.IsEmpty())
|
---|
430 | {
|
---|
431 | dest <<= src;
|
---|
432 | return dest;
|
---|
433 | }
|
---|
434 | if(!less(*src, dest.Top()))
|
---|
435 | {
|
---|
436 | dest.Append(src);
|
---|
437 | return dest;
|
---|
438 | }
|
---|
439 | if(!less(*dest, src.Top()))
|
---|
440 | {
|
---|
441 | dest.Insert(0, src);
|
---|
442 | return dest;
|
---|
443 | }
|
---|
444 | int dc = dest.GetCount();
|
---|
445 | int sc = src.GetCount();
|
---|
446 | dest.SetCount(dc + sc);
|
---|
447 | typename C::Iterator de = dest.End();
|
---|
448 | typename C::ConstIterator se = src.End(), pe = dest.GetIter(dc);
|
---|
449 | --se;
|
---|
450 | --pe;
|
---|
451 | for(;;)
|
---|
452 | {
|
---|
453 | if(less(*se, *pe))
|
---|
454 | {
|
---|
455 | *--de = *pe;
|
---|
456 | if(pe == dest.Begin())
|
---|
457 | { // dest items are finished
|
---|
458 | *--de = *se;
|
---|
459 | while(se != src.Begin())
|
---|
460 | *--de = *--se;
|
---|
461 | return dest;
|
---|
462 | }
|
---|
463 | --pe;
|
---|
464 | }
|
---|
465 | else
|
---|
466 | {
|
---|
467 | *--de = *se;
|
---|
468 | if(se == src.Begin())
|
---|
469 | return dest; // src items are finished, dest items are in place
|
---|
470 | --se;
|
---|
471 | }
|
---|
472 | }
|
---|
473 | return dest;
|
---|
474 | }
|
---|
475 |
|
---|
476 | //////////////////////////////////////////////////////////////////////
|
---|
477 |
|
---|
478 | template <class C>
|
---|
479 | C& AppendSorted(C& dest, const C& src)
|
---|
480 | {
|
---|
481 | typedef typename C::ValueType VT;
|
---|
482 | return AppendSorted(dest, src, StdLess<VT>());
|
---|
483 | }
|
---|
484 |
|
---|
485 | //////////////////////////////////////////////////////////////////////
|
---|
486 |
|
---|
487 | template <class C, class L>
|
---|
488 | C& UnionSorted(C& dest, const C& src, const L& less)
|
---|
489 | {
|
---|
490 | if(src.IsEmpty())
|
---|
491 | return dest;
|
---|
492 | if(dest.IsEmpty())
|
---|
493 | {
|
---|
494 | dest <<= src;
|
---|
495 | return dest;
|
---|
496 | }
|
---|
497 | if(less(dest.Top(), *src))
|
---|
498 | {
|
---|
499 | dest.Append(src);
|
---|
500 | return dest;
|
---|
501 | }
|
---|
502 | if(less(src.Top(), *dest))
|
---|
503 | {
|
---|
504 | dest.Insert(0, src);
|
---|
505 | return dest;
|
---|
506 | }
|
---|
507 | int dc = dest.GetCount();
|
---|
508 | int sc = src.GetCount();
|
---|
509 | dest.SetCount(dc + sc);
|
---|
510 | typename C::Iterator de = dest.End();
|
---|
511 | typename C::ConstIterator se = src.End(), pe = dest.GetIter(dc);
|
---|
512 | --se;
|
---|
513 | --pe;
|
---|
514 | for(;;)
|
---|
515 | {
|
---|
516 | if(less(*se, *pe))
|
---|
517 | {
|
---|
518 | *--de = *pe;
|
---|
519 | if(pe == dest.Begin())
|
---|
520 | { // dest items are finished
|
---|
521 | *--de = *se;
|
---|
522 | while(se != src.Begin())
|
---|
523 | *--de = *--se;
|
---|
524 | dest.Remove(0, dest.GetIndex(*de));
|
---|
525 | return dest;
|
---|
526 | }
|
---|
527 | --pe;
|
---|
528 | }
|
---|
529 | else
|
---|
530 | {
|
---|
531 | *--de = *se;
|
---|
532 | if(!less(*pe, *se))
|
---|
533 | {
|
---|
534 | if(pe == dest.Begin())
|
---|
535 | {
|
---|
536 | while(se != src.Begin())
|
---|
537 | *--de = *--se;
|
---|
538 | dest.Remove(0, dest.GetIndex(*de));
|
---|
539 | return dest;
|
---|
540 | }
|
---|
541 | --pe;
|
---|
542 | }
|
---|
543 | if(se == src.Begin())
|
---|
544 | {
|
---|
545 | int pi = (pe - dest.Begin()) + 1;
|
---|
546 | dest.Remove(pi, (de - dest.Begin()) - pi);
|
---|
547 | return dest; // src items are finished, dest items are in place
|
---|
548 | }
|
---|
549 | --se;
|
---|
550 | }
|
---|
551 | }
|
---|
552 | return dest;
|
---|
553 | }
|
---|
554 |
|
---|
555 | //////////////////////////////////////////////////////////////////////
|
---|
556 |
|
---|
557 | template <class C>
|
---|
558 | C& UnionSorted(C& dest, const C& src)
|
---|
559 | {
|
---|
560 | typedef typename C::ValueType VT;
|
---|
561 | return UnionSorted(dest, src, StdLess<VT>());
|
---|
562 | }
|
---|
563 |
|
---|
564 | //////////////////////////////////////////////////////////////////////
|
---|
565 |
|
---|
566 | template <class C, class L>
|
---|
567 | C& RemoveSorted(C& from, const C& what, const L& less)
|
---|
568 | {
|
---|
569 | if(from.IsEmpty() || what.IsEmpty() ||
|
---|
570 | less(from.Top(), *what.Begin()) || less(what.Top(), *from.Begin()))
|
---|
571 | return from;
|
---|
572 | typename C::ConstIterator we = what.End(), wp = BinFind(what, from[0], less);
|
---|
573 | if(wp == we)
|
---|
574 | return from;
|
---|
575 | typename C::Iterator fp = from.Begin() + BinFindIndex(from, *wp), fe = from.End(), fd = fp;
|
---|
576 | if(fp == fe)
|
---|
577 | {
|
---|
578 | from.Clear();
|
---|
579 | return from;
|
---|
580 | }
|
---|
581 | for(;;)
|
---|
582 | {
|
---|
583 | while(less(*fp, *wp))
|
---|
584 | {
|
---|
585 | *fd = *fp;
|
---|
586 | ++fd;
|
---|
587 | if(++fp == fe)
|
---|
588 | {
|
---|
589 | from.SetCount(fd - from.Begin());
|
---|
590 | return from;
|
---|
591 | }
|
---|
592 | }
|
---|
593 | if(less(*wp, *fp))
|
---|
594 | {
|
---|
595 | do
|
---|
596 | if(++wp == we)
|
---|
597 | {
|
---|
598 | Copy(fd, fp, fe);
|
---|
599 | fd += (fe - fp);
|
---|
600 | from.SetCount(fd - from.Begin());
|
---|
601 | return from;
|
---|
602 | }
|
---|
603 | while(less(*wp, *fp));
|
---|
604 | }
|
---|
605 | else
|
---|
606 | {
|
---|
607 | const typename C::ValueType& value = *fp;
|
---|
608 | while(!less(value, *fp))
|
---|
609 | if(++fp == fe)
|
---|
610 | {
|
---|
611 | from.SetCount(fd - from.Begin());
|
---|
612 | return from;
|
---|
613 | }
|
---|
614 | do
|
---|
615 | if(++wp == we)
|
---|
616 | {
|
---|
617 | Copy(fd, fp, fe);
|
---|
618 | fd += (fe - fp);
|
---|
619 | from.SetCount(fd - from.Begin());
|
---|
620 | return from;
|
---|
621 | }
|
---|
622 | while(!less(value, *wp));
|
---|
623 | }
|
---|
624 | }
|
---|
625 | }
|
---|
626 |
|
---|
627 | //////////////////////////////////////////////////////////////////////
|
---|
628 |
|
---|
629 | template <class C>
|
---|
630 | C& RemoveSorted(C& from, const C& what)
|
---|
631 | {
|
---|
632 | typedef typename C::ValueType VT;
|
---|
633 | return RemoveSorted(from, what, StdLess<VT>());
|
---|
634 | }
|
---|
635 |
|
---|
636 | //////////////////////////////////////////////////////////////////////
|
---|
637 |
|
---|
638 | template <class D, class S, class L>
|
---|
639 | D& IntersectSorted(D& dest, const S& src, const L& less)
|
---|
640 | {
|
---|
641 | if(dest.IsEmpty())
|
---|
642 | return dest;
|
---|
643 | if(src.IsEmpty() || less(dest.Top(), src[0]) || less(src.Top(), dest[0]))
|
---|
644 | { // empty source set or disjunct intervals
|
---|
645 | dest.Clear();
|
---|
646 | return dest;
|
---|
647 | }
|
---|
648 | typename S::ConstIterator ss = BinFind(src, dest[0], less), se = src.End();
|
---|
649 | if(ss == se)
|
---|
650 | {
|
---|
651 | dest.Clear();
|
---|
652 | return dest;
|
---|
653 | }
|
---|
654 | typename D::ConstIterator ds = BinFind(dest, src[0], less), de = dest.End();
|
---|
655 | if(ds == de)
|
---|
656 | {
|
---|
657 | dest.Clear();
|
---|
658 | return dest;
|
---|
659 | }
|
---|
660 | typename D::Iterator d = dest.Begin();
|
---|
661 | int count = 0;
|
---|
662 | for(;;)
|
---|
663 | {
|
---|
664 | if(less(*ss, *ds))
|
---|
665 | {
|
---|
666 | if(++ss == se)
|
---|
667 | break;
|
---|
668 | }
|
---|
669 | else
|
---|
670 | {
|
---|
671 | if(!less(*ds, *ss))
|
---|
672 | {
|
---|
673 | *d = *ds;
|
---|
674 | ++d;
|
---|
675 | count++;
|
---|
676 | }
|
---|
677 | if(++ds == de)
|
---|
678 | break;
|
---|
679 | }
|
---|
680 | }
|
---|
681 | dest.SetCount(count);
|
---|
682 | return dest;
|
---|
683 | }
|
---|
684 |
|
---|
685 | //////////////////////////////////////////////////////////////////////
|
---|
686 |
|
---|
687 | template <class D, class S>
|
---|
688 | D& IntersectSorted(D& dest, const S& src)
|
---|
689 | {
|
---|
690 | typedef typename D::ValueType VT;
|
---|
691 | return IntersectSorted(dest, src, StdLess<VT>());
|
---|
692 | }
|
---|
693 |
|
---|
694 | //////////////////////////////////////////////////////////////////////
|
---|
695 | // StreamContainer
|
---|
696 |
|
---|
697 | #ifdef UPP
|
---|
698 | template <class T>
|
---|
699 | void StreamContainer(Stream& s, T& cont)
|
---|
700 | {
|
---|
701 | int n = cont.GetCount();
|
---|
702 | s / n;
|
---|
703 | if(s.IsLoading())
|
---|
704 | {
|
---|
705 | cont.Clear();
|
---|
706 | while(n--)
|
---|
707 | s % cont.Add();
|
---|
708 | }
|
---|
709 | else
|
---|
710 | {
|
---|
711 | for(typename T::Iterator ptr = cont.Begin(); n--; ++ptr)
|
---|
712 | s % *ptr;
|
---|
713 | }
|
---|
714 | }
|
---|
715 | #endif
|
---|
716 | //////////////////////////////////////////////////////////////////////
|
---|
717 | // ForwardSort
|
---|
718 |
|
---|
719 | template <class I, class Less>
|
---|
720 | void ForwardSort(I begin, I end, const Less& less)
|
---|
721 | {
|
---|
722 | if(begin == end)
|
---|
723 | return;
|
---|
724 | I limit = end;
|
---|
725 | --limit;
|
---|
726 | while(!(begin == limit))
|
---|
727 | {
|
---|
728 | for(I best = limit, next = limit, ptr = limit;; best = ptr)
|
---|
729 | if(!less(*best, *--ptr))
|
---|
730 | {
|
---|
731 | if(ptr == begin)
|
---|
732 | {
|
---|
733 | begin = next;
|
---|
734 | break;
|
---|
735 | }
|
---|
736 | }
|
---|
737 | else
|
---|
738 | {
|
---|
739 | do
|
---|
740 | {
|
---|
741 | if(ptr == begin)
|
---|
742 | {
|
---|
743 | IterSwap(begin, best);
|
---|
744 | ++begin;
|
---|
745 | goto NEXT_ITEM;
|
---|
746 | }
|
---|
747 | }
|
---|
748 | while(less(*best, *--ptr));
|
---|
749 | if(ptr == begin)
|
---|
750 | {
|
---|
751 | IterSwap(++begin, best);
|
---|
752 | ++begin;
|
---|
753 | break;
|
---|
754 | }
|
---|
755 | next = ptr;
|
---|
756 | ++next;
|
---|
757 | }
|
---|
758 | NEXT_ITEM:
|
---|
759 | ;
|
---|
760 | }
|
---|
761 | }
|
---|
762 |
|
---|
763 | //////////////////////////////////////////////////////////////////////
|
---|
764 |
|
---|
765 | template <class T, class Less>
|
---|
766 | void ForwardSort(T& c, const Less& less)
|
---|
767 | {
|
---|
768 | ForwardSort(c.Begin(), c.End(), less);
|
---|
769 | }
|
---|
770 |
|
---|
771 | //////////////////////////////////////////////////////////////////////
|
---|
772 |
|
---|
773 | template <class T>
|
---|
774 | void ForwardSort(T& c)
|
---|
775 | {
|
---|
776 | typedef typename T::ValueType VT;
|
---|
777 | ForwardSort(c.Begin(), c.End(), StdLess<VT>());
|
---|
778 | }
|
---|
779 |
|
---|
780 | //////////////////////////////////////////////////////////////////////
|
---|
781 |
|
---|
782 | enum
|
---|
783 | {
|
---|
784 | __SORT_THRESHOLD = 16
|
---|
785 | };
|
---|
786 |
|
---|
787 | //////////////////////////////////////////////////////////////////////
|
---|
788 | // Sort
|
---|
789 |
|
---|
790 | template <class I, class Less>
|
---|
791 | inline I IterMedian(I x, I y, I z, const Less& less)
|
---|
792 | {
|
---|
793 | return less(*x, *y)
|
---|
794 | ? less(*y, *z) ? y : less(*x, *z) ? z : x
|
---|
795 | : less(*x, *z) ? x : less(*y, *z) ? z : y;
|
---|
796 | }
|
---|
797 |
|
---|
798 | template <class I, class Less>
|
---|
799 | void Sort(I begin, I end, const Less& less)
|
---|
800 | {
|
---|
801 | int count;
|
---|
802 | while((count = end - begin) > __SORT_THRESHOLD)
|
---|
803 | {
|
---|
804 | I b = begin, e = end, m = IterMedian(b, b + (count >> 1), e - 1, less);
|
---|
805 | for(;; ++b)
|
---|
806 | {
|
---|
807 | while(less(*m, *--e))
|
---|
808 | ;
|
---|
809 | while(less(*b, *m))
|
---|
810 | ++b;
|
---|
811 | if(!(b < e))
|
---|
812 | break;
|
---|
813 | if(m == b) m = e;
|
---|
814 | else if(m == e) m = b;
|
---|
815 | IterSwap(b, e);
|
---|
816 | }
|
---|
817 | if(b - begin < end - e)
|
---|
818 | {
|
---|
819 | Sort(begin, b, less);
|
---|
820 | begin = b;
|
---|
821 | }
|
---|
822 | else
|
---|
823 | {
|
---|
824 | Sort(b, end, less);
|
---|
825 | end = b;
|
---|
826 | }
|
---|
827 | }
|
---|
828 | if(count >= 1)
|
---|
829 | ForwardSort(begin, end, less);
|
---|
830 | }
|
---|
831 |
|
---|
832 | template <class T, class Less>
|
---|
833 | void Sort(T& c, int l, int h, const Less& less)
|
---|
834 | {
|
---|
835 | Sort(c.GetIter(l), c.GetIter(h), less);
|
---|
836 | }
|
---|
837 |
|
---|
838 | template <class T, class Less>
|
---|
839 | void Sort(T& c, const Less& less)
|
---|
840 | {
|
---|
841 | Sort(c.Begin(), c.End(), less);
|
---|
842 | }
|
---|
843 |
|
---|
844 | template <class T>
|
---|
845 | void Sort(T& c)
|
---|
846 | {
|
---|
847 | typedef typename T::ValueType VT;
|
---|
848 | Sort(c.Begin(), c.End(), StdLess<VT>());
|
---|
849 | }
|
---|
850 |
|
---|
851 | //////////////////////////////////////////////////////////////////////
|
---|
852 | // IndexSort
|
---|
853 |
|
---|
854 | template <class II, class VI, class K>
|
---|
855 | struct IndexSortIterator
|
---|
856 | {
|
---|
857 | typedef IndexSortIterator<II, VI, K> Iter;
|
---|
858 |
|
---|
859 | IndexSortIterator(II ii, VI vi) : ii(ii), vi(vi) {}
|
---|
860 |
|
---|
861 | Iter& operator ++ () { ++ii; ++vi; return *this; }
|
---|
862 | Iter& operator -- () { --ii; --vi; return *this; }
|
---|
863 | const K& operator * () /*const*/ { return *ii; } //!! Fidler's bug in Array::Iterator
|
---|
864 | Iter operator + (int i) const { return Iter(ii + i, vi + i); }
|
---|
865 | Iter operator - (int i) const { return Iter(ii - i, vi - i); }
|
---|
866 | int operator - (Iter b) const { return (int)(ii - b.ii); }
|
---|
867 | bool operator == (Iter b) const { return ii == b.ii; }
|
---|
868 | bool operator < (Iter b) const { return ii < b.ii; }
|
---|
869 | friend void IterSwap (Iter a, Iter b) { IterSwap(a.ii, b.ii); IterSwap(a.vi, b.vi); }
|
---|
870 |
|
---|
871 | II ii;
|
---|
872 | VI vi;
|
---|
873 | };
|
---|
874 |
|
---|
875 | template <class II, class VI, class K, class Less>
|
---|
876 | inline void __IndexSort(II begin, II end, VI pair, const Less& less, const K *)
|
---|
877 | {
|
---|
878 | Sort(IndexSortIterator<II, VI, K>(begin, pair),
|
---|
879 | IndexSortIterator<II, VI, K>(end, pair + (end - begin)),
|
---|
880 | less);
|
---|
881 | }
|
---|
882 |
|
---|
883 | //////////////////////////////////////////////////////////////////////
|
---|
884 |
|
---|
885 | template <class II, class VI, class Less>
|
---|
886 | inline void IndexSort(II begin, II end, VI pair, const Less& less)
|
---|
887 | {
|
---|
888 | if(begin != end)
|
---|
889 | __IndexSort(begin, end, pair, less, &*begin);
|
---|
890 | }
|
---|
891 |
|
---|
892 | //////////////////////////////////////////////////////////////////////
|
---|
893 |
|
---|
894 | template <class KC, class VC, class Less>
|
---|
895 | inline void IndexSort(KC& keys, VC& values, const Less& less)
|
---|
896 | {
|
---|
897 | typedef typename KC::ValueType KT;
|
---|
898 | ASSERT(keys.GetCount() == values.GetCount());
|
---|
899 | if(keys.GetCount() >= 2)
|
---|
900 | __IndexSort(keys.Begin(), keys.End(), values.Begin(), less, (KT *)0);
|
---|
901 | }
|
---|
902 |
|
---|
903 | //////////////////////////////////////////////////////////////////////
|
---|
904 |
|
---|
905 | template <class KC, class VC>
|
---|
906 | inline void IndexSort(KC& keys, VC& values)
|
---|
907 | {
|
---|
908 | typedef typename KC::ValueType KT;
|
---|
909 | if(keys.GetCount() >= 2)
|
---|
910 | __IndexSort(keys.Begin(), keys.End(), values.Begin(), StdLess<KT>(), (KT *)0);
|
---|
911 | }
|
---|
912 |
|
---|
913 | //////////////////////////////////////////////////////////////////////
|
---|
914 |
|
---|
915 | template <class I, class V>
|
---|
916 | struct SortOrderIterator
|
---|
917 | {
|
---|
918 | typedef SortOrderIterator<I, V> Iter;
|
---|
919 |
|
---|
920 | SortOrderIterator(int *ii, I vi) : ii(ii), vi(vi) {}
|
---|
921 |
|
---|
922 | Iter& operator ++ () { ++ii; return *this; }
|
---|
923 | Iter& operator -- () { --ii; return *this; }
|
---|
924 | const V& operator * () const { return *(vi + *ii); }
|
---|
925 | Iter operator + (int i) const { return Iter(ii + i, vi); }
|
---|
926 | Iter operator - (int i) const { return Iter(ii - i, vi); }
|
---|
927 | int operator - (Iter b) const { return int(ii - b.ii); }
|
---|
928 | bool operator == (Iter b) const { return ii == b.ii; }
|
---|
929 | bool operator < (Iter b) const { return ii < b.ii; }
|
---|
930 | friend void IterSwap (Iter a, Iter b) { IterSwap(a.ii, b.ii); }
|
---|
931 |
|
---|
932 | int *ii;
|
---|
933 | I vi;
|
---|
934 | };
|
---|
935 |
|
---|
936 | template <class I, class V, class Less>
|
---|
937 | inline void __SortOrder(int *begin, int *end, I data, const Less& less, const V *)
|
---|
938 | {
|
---|
939 | Sort(SortOrderIterator<I, V>(begin, data), SortOrderIterator<I, V>(end, data), less);
|
---|
940 | }
|
---|
941 |
|
---|
942 | //////////////////////////////////////////////////////////////////////
|
---|
943 |
|
---|
944 | template <class I, class Less>
|
---|
945 | inline Vector<int> GetSortOrder(I begin, I end, const Less& less)
|
---|
946 | {
|
---|
947 | Vector<int> index;
|
---|
948 | index.SetCount((int)(end - begin));
|
---|
949 | for(int i = index.GetCount(); --i >= 0; index[i] = i)
|
---|
950 | ;
|
---|
951 | __SortOrder(index.Begin(), index.End(), begin, less, &*begin);
|
---|
952 | return index;
|
---|
953 | }
|
---|
954 |
|
---|
955 | //////////////////////////////////////////////////////////////////////
|
---|
956 |
|
---|
957 | template <class C, class Less>
|
---|
958 | inline Vector<int> GetSortOrder(const C& container, const Less& less)
|
---|
959 | {
|
---|
960 | return GetSortOrder(container.Begin(), container.End(), less);
|
---|
961 | }
|
---|
962 |
|
---|
963 | //////////////////////////////////////////////////////////////////////
|
---|
964 |
|
---|
965 | template <class C>
|
---|
966 | inline Vector<int> GetSortOrder(const C& container)
|
---|
967 | {
|
---|
968 | typedef typename C::ValueType V;
|
---|
969 | return GetSortOrder(container.Begin(), container.End(), StdLess<V>());
|
---|
970 | }
|
---|
971 |
|
---|
972 | //////////////////////////////////////////////////////////////////////
|
---|
973 |
|
---|
974 | template <class DC, class I, class F>
|
---|
975 | void GetFieldContainer(DC& dest, I begin, I end, F field)
|
---|
976 | {
|
---|
977 | for(; begin != end; ++begin)
|
---|
978 | dest.Add((*begin).*field);
|
---|
979 | }
|
---|
980 |
|
---|
981 | //////////////////////////////////////////////////////////////////////
|
---|
982 |
|
---|
983 | template <class DC, class SC, class F>
|
---|
984 | void GetFieldContainer(DC& dest, const SC& src, F field)
|
---|
985 | { GetFieldContainer<DC, TYPENAME SC::ConstIterator, F>(dest, src.Begin(), src.End(), field); }
|
---|
986 |
|
---|
987 | //////////////////////////////////////////////////////////////////////
|
---|
988 |
|
---|
989 | template <class I, class F, class O, class E>
|
---|
990 | I FindField(I begin, I end, F field, const O& object, const E& equal)
|
---|
991 | {
|
---|
992 | for(; begin != end && !equal((*begin).*field, object); ++begin)
|
---|
993 | ;
|
---|
994 | return begin;
|
---|
995 | }
|
---|
996 |
|
---|
997 | //////////////////////////////////////////////////////////////////////
|
---|
998 |
|
---|
999 | template <class I, class F, class O>
|
---|
1000 | I FindField(I begin, I end, F field, const O& object)
|
---|
1001 | { return FindField(begin, end, field, object, StdEqual<O>()); }
|
---|
1002 |
|
---|
1003 | //////////////////////////////////////////////////////////////////////
|
---|
1004 |
|
---|
1005 | template <class C, class F, class O, class E>
|
---|
1006 | int FindFieldIndex(const C& container, F field, const O& object, const E& equal)
|
---|
1007 | {
|
---|
1008 | int i = 0;
|
---|
1009 | for(typename C::ConstIterator b = container.Begin(), e = container.End(); b != e; ++b, ++i)
|
---|
1010 | if(equal((*b).*field, object))
|
---|
1011 | return i;
|
---|
1012 | return -1;
|
---|
1013 | }
|
---|
1014 |
|
---|
1015 | //////////////////////////////////////////////////////////////////////
|
---|
1016 |
|
---|
1017 | template <class C, class F, class O>
|
---|
1018 | int FindFieldIndex(const C& container, F field, const O& object)
|
---|
1019 | { return FindFieldIndex(container, field, object, StdEqual<O>()); }
|
---|
1020 |
|
---|
1021 | //////////////////////////////////////////////////////////////////////
|
---|
1022 |
|
---|
1023 | template <class O, class T, class R>
|
---|
1024 | class FieldRelationCls {
|
---|
1025 | O T::*member;
|
---|
1026 | const R& relation;
|
---|
1027 |
|
---|
1028 | public:
|
---|
1029 | FieldRelationCls(O (T::*member), const R& relation) : member(member), relation(relation) {}
|
---|
1030 | bool operator () (const T& t1, const T& t2) const { return relation(t1.*member, t2.*member); }
|
---|
1031 | };
|
---|
1032 |
|
---|
1033 | template <class O, class T, class R>
|
---|
1034 | inline FieldRelationCls<O, T, R> FieldRelation(O (T::*member), const R& relation)
|
---|
1035 | { return FieldRelationCls<O, T, R>(member, relation); }
|
---|
1036 |
|
---|
1037 | //////////////////////////////////////////////////////////////////////
|
---|
1038 |
|
---|
1039 | template <class M, class T, class R>
|
---|
1040 | class MethodRelationCls {
|
---|
1041 | M method;
|
---|
1042 | const R& relation;
|
---|
1043 |
|
---|
1044 | public:
|
---|
1045 | MethodRelationCls(M method, const R& relation) : method(method), relation(relation) {}
|
---|
1046 | bool operator () (const T& t1, const T& t2) const {
|
---|
1047 | return relation((t1.*method)(), (t2.*method)());
|
---|
1048 | }
|
---|
1049 | };
|
---|
1050 |
|
---|
1051 | template <class O, class T, class R>
|
---|
1052 | inline MethodRelationCls<O (T::*)(), T, R>
|
---|
1053 | MethodRelation(O (T::*method)(), const R& relation)
|
---|
1054 | { return MethodRelationCls<O (T::*)(), T, R>(method, relation); }
|
---|
1055 |
|
---|
1056 | template <class O, class T, class R>
|
---|
1057 | inline MethodRelationCls<O (T::*)() const, T, R>
|
---|
1058 | MethodRelation(O (T::*method)() const, const R& relation)
|
---|
1059 | { return MethodRelationCls<O (T::*)() const, T, R>(method, relation); }
|
---|
1060 |
|
---|
1061 | ///////////////////////////////////////////////////////////////////////
|
---|
1062 |
|
---|
1063 | template <class C, class T>
|
---|
1064 | void LruAdd(C& lru, T value, int limit = 10) {
|
---|
1065 | int q = FindIndex(lru, value);
|
---|
1066 | if(q >= 0)
|
---|
1067 | lru.Remove(q);
|
---|
1068 | lru.Insert(0, value);
|
---|
1069 | if(lru.GetCount() > limit)
|
---|
1070 | lru.SetCount(limit);
|
---|
1071 | }
|
---|