Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/MD_package/IntGroup.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 117 - (show annotations) (download) (as text)
Sun Oct 1 03:33:45 2017 UTC (6 years, 6 months ago) by toshinagata1964
File MIME type: text/x-csrc
File size: 30322 byte(s)
Sizes of the integer types are reconsidered.
1 /*
2 IntGroup.c
3 Created by Toshi Nagata, 2000.12.3.
4
5 Copyright (c) 2000-2016 Toshi Nagata.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation version 2 of the License.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 */
16
17 #include "IntGroup.h"
18
19 #include <stdio.h> /* for fprintf() in IntGroupDump() */
20 #include <stdlib.h> /* for malloc(), realloc(), and free() */
21 #include <string.h> /* for memmove() */
22 #include <limits.h> /* for INT_MAX */
23 #include <stdarg.h>
24
25 #pragma mark ====== Private definitions ======
26
27 struct IntGroup {
28 int refCount; /* the reference count */
29 int num; /* the number of entries */
30 int * entries; /* entries[2*n]: begin point, entries[2*n+1]: end point */
31 };
32
33 typedef short IntGroupOperation;
34 enum {
35 kIntGroupIntersect,
36 kIntGroupConvolute,
37 kIntGroupDeconvolute
38 };
39
40 #pragma mark ====== Private (static) functions ======
41
42 /* --------------------------------------
43 ��� IntGroupCalcRequiredStorage
44 -------------------------------------- */
45 static int
46 IntGroupCalcRequiredStorage(int inLength)
47 {
48 return ((inLength * 2 + 3) / 4) * 4 * sizeof(int);
49 }
50
51 /* --------------------------------------
52 ��� IntGroupAdjustStorage
53 -------------------------------------- */
54 static IntGroupStatus
55 IntGroupAdjustStorage(IntGroup *psRef, int inLength)
56 {
57 int theOldSize, theNewSize;
58
59 theOldSize = IntGroupCalcRequiredStorage(psRef->num);
60 theNewSize = IntGroupCalcRequiredStorage(inLength);
61 if (theOldSize == theNewSize)
62 return 0;
63
64 if (theOldSize == 0 && theNewSize != 0) {
65 psRef->entries = (int *)malloc(theNewSize);
66 if (psRef->entries == NULL)
67 return kIntGroupStatusOutOfMemory;
68 } else if (theOldSize != 0 && theNewSize == 0) {
69 free(psRef->entries);
70 psRef->entries = NULL;
71 } else {
72 int *ptr = (int *)realloc(psRef->entries, theNewSize);
73 if (ptr == NULL)
74 return kIntGroupStatusOutOfMemory;
75 psRef->entries = ptr;
76 }
77 return kIntGroupStatusNoError;
78 }
79
80 /* --------------------------------------
81 ��� IntGroupInsertAnEntry
82 -------------------------------------- */
83 static IntGroupStatus
84 IntGroupInsertAnEntry(IntGroup *psRef, int inIndex, int inBeginPt, int inEndPt)
85 {
86 IntGroupStatus result;
87 int moveAmount;
88 result = IntGroupAdjustStorage(psRef, psRef->num + 1);
89 if (result != kIntGroupStatusNoError)
90 return result; /* out of memory */
91 moveAmount = (psRef->num - inIndex) * 2 * sizeof(int);
92 if (moveAmount > 0)
93 memmove(&(psRef->entries[inIndex * 2 + 2]), &(psRef->entries[inIndex * 2]), moveAmount);
94 psRef->entries[inIndex * 2] = inBeginPt;
95 psRef->entries[inIndex * 2 + 1] = inEndPt;
96 psRef->num++;
97 return kIntGroupStatusNoError;
98 }
99
100 /* --------------------------------------
101 ��� IntGroupDeleteEntries
102 -------------------------------------- */
103 static IntGroupStatus
104 IntGroupDeleteEntries(IntGroup *psRef, int inStartIndex, int inEndIndex)
105 {
106 IntGroupStatus result;
107 int moveAmount;
108 if (inStartIndex > inEndIndex)
109 return 0; /* do nothing */
110 moveAmount = sizeof(int) * 2 * (psRef->num - inEndIndex - 1);
111 if (moveAmount > 0)
112 memmove(&(psRef->entries[inStartIndex * 2]), &(psRef->entries[inEndIndex * 2 + 2]), moveAmount);
113 result = IntGroupAdjustStorage(psRef, psRef->num - (inEndIndex - inStartIndex + 1));
114 if (result == kIntGroupStatusNoError)
115 psRef->num -= inEndIndex - inStartIndex + 1;
116 return result;
117 }
118
119 #pragma mark ====== New/Retain/Release ======
120
121 /* --------------------------------------
122 ��� IntGroupNew
123 -------------------------------------- */
124 IntGroup *
125 IntGroupNew(void)
126 {
127 IntGroup *psRef = (IntGroup *)malloc(sizeof(*psRef));
128 if (psRef == NULL)
129 return NULL; /* out of memory */
130 psRef->entries = NULL;
131 psRef->num = 0;
132 psRef->refCount = 1;
133 return psRef;
134 }
135
136 /* --------------------------------------
137 ��� IntGroupNewFromIntGroup
138 -------------------------------------- */
139 IntGroup *
140 IntGroupNewFromIntGroup(const IntGroup *src)
141 {
142 IntGroup *dst = IntGroupNew();
143 if (dst == NULL)
144 return NULL;
145 if (IntGroupCopy(dst, src) != kIntGroupStatusNoError) {
146 IntGroupRelease(dst);
147 return NULL;
148 }
149 return dst;
150 }
151
152 /* --------------------------------------
153 ��� IntGroupNewWithPoints
154 -------------------------------------- */
155 IntGroup *
156 IntGroupNewWithPoints(int start, ...)
157 {
158 va_list ap;
159 int length;
160 IntGroup *psRef = IntGroupNew();
161 if (psRef == NULL)
162 return NULL;
163 va_start(ap, start);
164 while (start >= 0) {
165 length = va_arg(ap, int);
166 if (IntGroupAdd(psRef, start, length) != 0) {
167 IntGroupRelease(psRef);
168 return NULL;
169 }
170 start = va_arg(ap, int);
171 }
172 va_end(ap);
173 return psRef;
174 }
175
176 /* --------------------------------------
177 ��� IntGroupRetain
178 -------------------------------------- */
179 void
180 IntGroupRetain(IntGroup *psRef)
181 {
182 if (psRef == NULL)
183 return;
184 psRef->refCount++;
185 }
186
187 /* --------------------------------------
188 ��� IntGroupRelease
189 -------------------------------------- */
190 void
191 IntGroupRelease(IntGroup *psRef)
192 {
193 if (psRef == NULL)
194 return;
195 if (--psRef->refCount == 0) {
196 IntGroupClear(psRef);
197 free(psRef);
198 }
199 }
200
201 #pragma mark ====== Clear/Copy ======
202
203 /* --------------------------------------
204 ��� IntGroupClear
205 -------------------------------------- */
206 void
207 IntGroupClear(IntGroup *psRef)
208 {
209 if (psRef == NULL)
210 return;
211 if (psRef->entries != NULL) {
212 free(psRef->entries);
213 psRef->entries = NULL;
214 }
215 psRef->num = 0;
216 }
217
218 /* --------------------------------------
219 ��� IntGroupCopy
220 -------------------------------------- */
221 IntGroupStatus
222 IntGroupCopy(IntGroup *psRef1, const IntGroup *psRef2)
223 {
224 IntGroupStatus sts;
225 if (psRef1 == NULL || psRef2 == NULL)
226 return kIntGroupStatusNoError;
227 sts = IntGroupAdjustStorage(psRef1, psRef2->num);
228 if (sts == kIntGroupStatusNoError) {
229 memmove(psRef1->entries, psRef2->entries, psRef2->num * 2 * sizeof(int));
230 psRef1->num = psRef2->num;
231 }
232 return sts;
233 }
234
235 #pragma mark ====== Point Manipulations ======
236
237 /* --------------------------------------
238 ��� IntGroupLookup
239 -------------------------------------- */
240 int
241 IntGroupLookup(const IntGroup *psRef, int inPoint, int *outIndex)
242 {
243 int i;
244 if (psRef == NULL)
245 return 0;
246 for (i = 0; i < psRef->num; i++) {
247 if (inPoint < psRef->entries[i*2]) {
248 if (outIndex != NULL)
249 *outIndex = i;
250 return 0;
251 } else if (inPoint < psRef->entries[i*2+1]) {
252 if (outIndex != NULL)
253 *outIndex = i;
254 return 1;
255 }
256 }
257 if (outIndex != NULL)
258 *outIndex = psRef->num;
259 return 0;
260 }
261
262 /* --------------------------------------
263 ��� IntGroupIsEqual
264 -------------------------------------- */
265 int
266 IntGroupIsEqual(const IntGroup *psRef1, const IntGroup *psRef2)
267 {
268 int i;
269 if (psRef1 == NULL || psRef2 == NULL)
270 return (psRef1 == psRef2);
271 if (psRef1->num != psRef2->num)
272 return 0;
273 for (i = 0; i < psRef1->num * 2; i++) {
274 if (psRef1->entries[i] != psRef2->entries[i])
275 return 0;
276 }
277 return 1;
278 }
279
280 /* --------------------------------------
281 ��� IntGroupGetCount
282 -------------------------------------- */
283 int
284 IntGroupGetCount(const IntGroup *psRef)
285 {
286 int i, n;
287 if (psRef == NULL)
288 return 0;
289 n = 0;
290 for (i = 0; i < psRef->num; i++)
291 n += psRef->entries[i*2+1] - psRef->entries[i*2];
292 return n;
293 }
294
295 /* --------------------------------------
296 ��� IntGroupGetIntervalCount
297 -------------------------------------- */
298 int
299 IntGroupGetIntervalCount(const IntGroup *psRef)
300 {
301 if (psRef == NULL)
302 return 0;
303 return psRef->num;
304 }
305
306 /* --------------------------------------
307 ��� IntGroupAdd
308 -------------------------------------- */
309 IntGroupStatus
310 IntGroupAdd(IntGroup *psRef, int inStart, int inCount)
311 {
312 int theBeginIndex, theEndIndex;
313 int theBeginFlag, theEndFlag;
314
315 if (psRef == NULL || inCount == 0)
316 return kIntGroupStatusNoError;
317
318 /* inStart, inStart+inCount ������������������������������������������������ */
319 theBeginFlag = IntGroupLookup(psRef, inStart, &theBeginIndex);
320 theEndFlag = IntGroupLookup(psRef, inStart + inCount, &theEndIndex);
321
322 if (theBeginFlag) {
323 /* psRef->entries[theBeginIndex*2] <= inStart < psRef->entries[theBeginIndex*2+1] */
324 if (theEndFlag) {
325 /* psRef->entries[theEndIndex*2] <= inStart + inCount
326 < psRef->entries[theEndIndex*2+1] */
327 if (theBeginIndex < theEndIndex) {
328 psRef->entries[theBeginIndex*2+1] = psRef->entries[theEndIndex*2+1];
329 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex);
330 } else return 0;
331 } else {
332 /* psRef->entries[(theEndIndex-1)*2+1] <= inStart + inCount
333 < psRef->entries[theEndIndex*2] */
334 psRef->entries[theBeginIndex*2+1] = inStart + inCount;
335 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex - 1);
336 }
337 } else {
338 /* psRef->entries[(theBeginIndex-1)*2+1] <= inStart < psRef->entries[theBeginIndex*2] */
339 int thePoint = 0;
340 if (theBeginIndex > 0 && psRef->entries[(theBeginIndex-1)*2+1] == inStart) {
341 /* ��������������������������������������������������� */
342 theBeginIndex--;
343 } else if (theBeginIndex < psRef->num) {
344 thePoint = psRef->entries[theBeginIndex*2]; /* ��������������������������������� */
345 psRef->entries[theBeginIndex*2] = inStart;
346 }
347 if (theEndFlag) {
348 /* psRef->entries[theEndIndex*2] <= inStart + inCount
349 < psRef->entries[theEndIndex*2+1] */
350 psRef->entries[theBeginIndex*2+1] = psRef->entries[theEndIndex*2+1];
351 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex);
352 } else {
353 /* psRef->entries[(theEndIndex-1)*2+1] <= inStart + inCount
354 < psRef->entries[theEndIndex*2] */
355 if (theBeginIndex == theEndIndex) {
356 if (theBeginIndex < psRef->num)
357 psRef->entries[theBeginIndex*2] = thePoint; /* ������������ */
358 return IntGroupInsertAnEntry(psRef, theBeginIndex, inStart, inStart + inCount);
359 } else {
360 psRef->entries[theBeginIndex*2+1] = inStart + inCount;
361 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex - 1);
362 }
363 }
364 }
365
366 }
367
368 /* --------------------------------------
369 ��� IntGroupRemove
370 -------------------------------------- */
371 IntGroupStatus
372 IntGroupRemove(IntGroup *psRef, int inStart, int inCount)
373 {
374 int theBeginIndex, theEndIndex;
375 int theBeginFlag, theEndFlag;
376
377 if (psRef == NULL || inCount == 0)
378 return kIntGroupStatusNoError;
379
380 /* inStart, inStart+inCount ������������������������������������������������ */
381 theBeginFlag = IntGroupLookup(psRef, inStart, &theBeginIndex);
382 theEndFlag = IntGroupLookup(psRef, inStart + inCount, &theEndIndex);
383
384 if (theBeginFlag) {
385 /* psRef->entries[theBeginIndex*2] <= inStart < psRef->entries[theBeginIndex*2+1] */
386 int thePoint = psRef->entries[theBeginIndex*2];
387 if (theEndFlag) {
388 /* psRef->entries[theEndIndex*2] <= inStart + inCount
389 < psRef->entries[theEndIndex*2+1] */
390 psRef->entries[theEndIndex*2] = inStart + inCount;
391 if (theBeginIndex == theEndIndex) {
392 if (thePoint == inStart)
393 return 0;
394 else
395 return IntGroupInsertAnEntry(psRef, theBeginIndex, thePoint, inStart);
396 } else {
397 if (thePoint == inStart)
398 theBeginIndex--;
399 else
400 psRef->entries[theBeginIndex*2+1] = inStart;
401 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex - 1);
402 }
403 } else {
404 /* psRef->entries[(theEndIndex-1)*2+1] <= inStart + inCount
405 < psRef->entries[theEndIndex*2] */
406 if (thePoint == inStart)
407 theBeginIndex--;
408 else
409 psRef->entries[theBeginIndex*2+1] = inStart;
410 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex - 1);
411 }
412 } else {
413 /* psRef->entries[(theBeginIndex-1)*2+1] <= inStart < psRef->entries[theBeginIndex*2] */
414 if (theEndFlag) {
415 /* psRef->entries[theEndIndex*2] <= inStart + inCount
416 < psRef->entries[theEndIndex*2+1] */
417 psRef->entries[theEndIndex*2] = inStart + inCount;
418 return IntGroupDeleteEntries(psRef, theBeginIndex, theEndIndex - 1);
419 } else {
420 /* psRef->entries[(theEndIndex-1)*2+1] <= inStart + inCount
421 < psRef->entries[theEndIndex*2] */
422 return IntGroupDeleteEntries(psRef, theBeginIndex, theEndIndex - 1);
423 }
424 }
425 }
426
427 /* --------------------------------------
428 ��� IntGroupReverse
429 -------------------------------------- */
430 IntGroupStatus
431 IntGroupReverse(IntGroup *psRef, int inStart, int inCount)
432 {
433 int theBeginIndex, theEndIndex, theIndex;
434 int theBeginFlag, theEndFlag;
435 IntGroupStatus result;
436
437 if (psRef == NULL)
438 return kIntGroupStatusNoError;
439
440 /* inStart, inStart+inCount ������������������������������������������������ */
441 theBeginFlag = IntGroupLookup(psRef, inStart, &theBeginIndex);
442 theEndFlag = IntGroupLookup(psRef, inStart + inCount, &theEndIndex);
443
444 if (theBeginFlag) {
445 /* psRef->entries[theBeginIndex*2] <= inStart < psRef->entries[theBeginIndex*2+1] */
446 if (psRef->entries[theBeginIndex*2] < inStart) {
447 result = IntGroupInsertAnEntry(psRef, theBeginIndex, psRef->entries[theBeginIndex*2], inStart);
448 if (result != 0)
449 return result;
450 theBeginIndex++;
451 theEndIndex++;
452 }
453 } else {
454 /* psRef->entries[(theBeginIndex-1)*2+1] <= inStart < psRef->entries[theBeginIndex*2] */
455 int thePoint;
456 if (theBeginIndex == theEndIndex && !theEndFlag)
457 thePoint = inStart + inCount; /* theBeginIndex == mNumberOfEntries ������������������ */
458 else
459 thePoint = psRef->entries[theBeginIndex*2];
460 result = IntGroupInsertAnEntry(psRef, theBeginIndex, inStart, thePoint);
461 if (result != 0)
462 return result;
463 theBeginIndex++;
464 theEndIndex++;
465 }
466
467 if (theEndFlag) {
468 /* psRef->entries[theEndIndex*2] <= inStart + inCount
469 < psRef->entries[theEndIndex*2+1] */
470 for (theIndex = theBeginIndex; theIndex < theEndIndex; theIndex++) {
471 psRef->entries[theIndex*2] = psRef->entries[theIndex*2+1];
472 psRef->entries[theIndex*2+1] = psRef->entries[(theIndex+1)*2];
473 }
474 psRef->entries[theEndIndex*2] = inStart + inCount;
475 if (theEndIndex > 0 && psRef->entries[(theEndIndex-1)*2+1] == inStart + inCount) {
476 /* ��������������������������������������������������� */
477 psRef->entries[(theEndIndex-1)*2+1] = psRef->entries[theEndIndex*2+1];
478 return IntGroupDeleteEntries(psRef, theEndIndex, theEndIndex);
479 }
480 } else {
481 /* psRef->entries[(theEndIndex-1)*2+1] <= inStart + inCount
482 < psRef->entries[theEndIndex*2] */
483 for (theIndex = theBeginIndex; theIndex < theEndIndex - 1; theIndex++) {
484 psRef->entries[theIndex*2] = psRef->entries[theIndex*2+1];
485 psRef->entries[theIndex*2+1] = psRef->entries[(theIndex+1)*2];
486 }
487 if (theIndex == theEndIndex - 1) {
488 if (psRef->entries[theIndex*2+1] == inStart + inCount)
489 return IntGroupDeleteEntries(psRef, theIndex, theIndex);
490 else {
491 psRef->entries[theIndex*2] = psRef->entries[theIndex*2+1];
492 psRef->entries[theIndex*2+1] = inStart + inCount;
493 }
494 }
495 }
496 return 0;
497 }
498
499 /* --------------------------------------
500 ��� IntGroupAddIntGroup
501 -------------------------------------- */
502 IntGroupStatus
503 IntGroupAddIntGroup(IntGroup *psRef1, const IntGroup *psRef2)
504 {
505 int i, n1, n2, result;
506 if (psRef1 == NULL || psRef2 == NULL)
507 return 0;
508 for (i = 0; (n1 = IntGroupGetStartPoint(psRef2, i)) >= 0; i++) {
509 n2 = IntGroupGetInterval(psRef2, i);
510 if ((result = IntGroupAdd(psRef1, n1, n2)) != 0)
511 return result;
512 }
513 return 0;
514 }
515
516 /* --------------------------------------
517 ��� IntGroupRemoveIntGroup
518 -------------------------------------- */
519 IntGroupStatus
520 IntGroupRemoveIntGroup(IntGroup *psRef1, const IntGroup *psRef2)
521 {
522 int i, n1, n2, result;
523 if (psRef1 == NULL || psRef2 == NULL)
524 return 0;
525 for (i = 0; (n1 = IntGroupGetStartPoint(psRef2, i)) >= 0; i++) {
526 n2 = IntGroupGetInterval(psRef2, i);
527 if ((result = IntGroupRemove(psRef1, n1, n2)) != 0)
528 return result;
529 }
530 return 0;
531 }
532
533 /* --------------------------------------
534 ��� IntGroupReverseIntGroup
535 -------------------------------------- */
536 IntGroupStatus
537 IntGroupReverseIntGroup(IntGroup *psRef1, const IntGroup *psRef2)
538 {
539 int i, n1, n2, result;
540 if (psRef1 == NULL || psRef2 == NULL)
541 return 0;
542 for (i = 0; (n1 = IntGroupGetStartPoint(psRef2, i)) >= 0; i++) {
543 n2 = IntGroupGetInterval(psRef2, i);
544 if ((result = IntGroupReverse(psRef1, n1, n2)) != 0)
545 return result;
546 }
547 return 0;
548 }
549
550 /* --------------------------------------
551 ��� IntGroupGetStartPoint
552 -------------------------------------- */
553 int
554 IntGroupGetStartPoint(const IntGroup *psRef, int inIndex)
555 {
556 if (psRef == NULL || inIndex < 0 || inIndex >= psRef->num)
557 return -1;
558 else return psRef->entries[inIndex*2];
559 }
560
561 /* --------------------------------------
562 ��� IntGroupGetEndPoint
563 -------------------------------------- */
564 int
565 IntGroupGetEndPoint(const IntGroup *psRef, int inIndex)
566 {
567 if (psRef == NULL || inIndex < 0 || inIndex >= psRef->num)
568 return -1;
569 else return psRef->entries[inIndex*2+1];
570 }
571
572 /* --------------------------------------
573 ��� IntGroupGetInterval
574 -------------------------------------- */
575 int
576 IntGroupGetInterval(const IntGroup *psRef, int inIndex)
577 {
578 if (psRef == NULL || inIndex < 0 || inIndex >= psRef->num)
579 return -1;
580 else return psRef->entries[inIndex*2+1] - psRef->entries[inIndex*2];
581 }
582
583 /* --------------------------------------
584 ��� IntGroupGetNthPoint
585 -------------------------------------- */
586 int
587 IntGroupGetNthPoint(const IntGroup *psRef, int inCount)
588 {
589 int i, n, dn;
590 if (psRef == NULL || inCount < 0)
591 return -1;
592 n = 0;
593 for (i = 0; i < psRef->num; i++) {
594 dn = psRef->entries[i*2+1] - psRef->entries[i*2];
595 if (inCount < n + dn) {
596 /* The inCount-th point is in this interval */
597 return psRef->entries[i*2] + inCount - n;
598 }
599 n += dn;
600 }
601 /* No such point */
602 return -1;
603 }
604
605 /* --------------------------------------
606 ��� IntGroupLookupPoint
607 -------------------------------------- */
608 int
609 IntGroupLookupPoint(const IntGroup *psRef, int inPoint)
610 {
611 int i, n;
612 if (psRef == NULL || inPoint < 0)
613 return -1;
614 n = 0;
615 for (i = 0; i < psRef->num; i++) {
616 if (inPoint >= psRef->entries[i*2] && inPoint < psRef->entries[i*2+1]) {
617 return n + inPoint - psRef->entries[i*2];
618 }
619 n += psRef->entries[i*2+1] - psRef->entries[i*2];
620 }
621 /* No such point */
622 return -1;
623 }
624
625 #pragma mark ====== Binary Operations ======
626
627 /* --------------------------------------
628 ��� IntGroupMyIntersect
629 -------------------------------------- */
630 static IntGroupStatus
631 IntGroupMyIntersect(
632 IntGroupOperation inCode,
633 const IntGroup *psRef1,
634 const IntGroup *psRef2,
635 IntGroup *psRef3)
636 {
637 int base = 0;
638 int i, j, offset1, offset2, where;
639 int theBeginIndex, theEndIndex;
640 int theBeginFlag, theEndFlag;
641 const int *ptr;
642 IntGroupStatus result = kIntGroupStatusNoError;
643
644 IntGroupClear(psRef3);
645 offset1 = offset2 = 0;
646 where = 0;
647
648 for (i = 0; result == 0 && i < psRef2->num; i++) {
649
650 int beginPt, endPt;
651 int newBeginPt, newEndPt;
652
653 ptr = &(psRef2->entries[i * 2]);
654 switch (inCode) {
655 case kIntGroupIntersect:
656 break; /* offset1 = offset2 = 0 */
657 case kIntGroupConvolute:
658 offset1 = base - ptr[0];
659 offset2 = -offset1;
660 break;
661 case kIntGroupDeconvolute:
662 offset2 = base - ptr[0];
663 break;
664 }
665 beginPt = ptr[0] + offset1;
666 endPt = ptr[1] + offset1;
667 theBeginFlag = IntGroupLookup(psRef1, beginPt, &theBeginIndex);
668 theEndFlag = IntGroupLookup(psRef1, endPt, &theEndIndex);
669
670 if (theBeginIndex == psRef1->num)
671 break; /* ������������������������������������ */
672
673 if (theBeginFlag) {
674 newBeginPt = beginPt + offset2;
675 } else {
676 newBeginPt = psRef1->entries[theBeginIndex * 2] + offset2;
677 }
678 if (theEndFlag && theBeginIndex == theEndIndex) {
679 newEndPt = endPt + offset2;
680 } else if (!theEndFlag && theBeginIndex == theEndIndex) {
681 newEndPt = newBeginPt; /* null interval */
682 } else {
683 newEndPt = psRef1->entries[theBeginIndex * 2 + 1] + offset2;
684 }
685 /* ��������������������������������������������������������������� */
686 if (where > 0 && newBeginPt == psRef3->entries[where * 2 - 1]) {
687 psRef3->entries[where * 2 - 1] = newEndPt;
688 } else if (newBeginPt < newEndPt) {
689 result = IntGroupInsertAnEntry(psRef3, where++, newBeginPt, newEndPt);
690 }
691 if (result == kIntGroupStatusNoError) {
692 for (j = theBeginIndex + 1; j < theEndIndex; j++) {
693 result = IntGroupInsertAnEntry(psRef3,
694 where++,
695 psRef1->entries[j * 2] + offset2,
696 psRef1->entries[j * 2 + 1] + offset2);
697 if (result != kIntGroupStatusNoError)
698 break;
699 }
700 }
701 if (result == kIntGroupStatusNoError) {
702 if (theEndFlag && theBeginIndex < theEndIndex
703 && psRef1->entries[theEndIndex * 2] < endPt)
704 result = IntGroupInsertAnEntry(psRef3,
705 where++,
706 psRef1->entries[theEndIndex * 2] + offset2,
707 endPt + offset2);
708 }
709
710 base += ptr[1] - ptr[0];
711 }
712
713 return result;
714 }
715
716 /* --------------------------------------
717 ��� IntGroupUnion
718 -------------------------------------- */
719 IntGroupStatus
720 IntGroupUnion(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
721 {
722 int i, startPt;
723 IntGroupStatus result;
724 result = IntGroupCopy(psRef3, psRef2);
725 if (result != kIntGroupStatusNoError)
726 return result;
727 for (i = 0; i < psRef1->num; i++) {
728 startPt = psRef1->entries[i*2];
729 result = IntGroupAdd(psRef3, startPt, psRef1->entries[i*2+1] - startPt);
730 if (result != kIntGroupStatusNoError)
731 return result;
732 }
733 return kIntGroupStatusNoError;
734 }
735
736 /* --------------------------------------
737 ��� IntGroupIntersect
738 -------------------------------------- */
739 IntGroupStatus
740 IntGroupIntersect(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
741 {
742 return IntGroupMyIntersect(kIntGroupIntersect, psRef1, psRef2, psRef3);
743 }
744
745 /* --------------------------------------
746 ��� IntGroupXor
747 -------------------------------------- */
748 IntGroupStatus
749 IntGroupXor(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
750 {
751 IntGroupStatus result;
752 int i, startPt;
753 result = IntGroupCopy(psRef3, psRef1);
754 if (result != kIntGroupStatusNoError)
755 return result;
756 for (i = 0; i < psRef2->num; i++) {
757 startPt = psRef2->entries[i*2];
758 result = IntGroupReverse(psRef3, startPt, psRef2->entries[i*2+1] - startPt);
759 if (result != kIntGroupStatusNoError)
760 return result;
761 }
762 return kIntGroupStatusNoError;
763 }
764
765 /* --------------------------------------
766 ��� IntGroupConvolute
767 -------------------------------------- */
768 IntGroupStatus
769 IntGroupConvolute(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
770 {
771 return IntGroupMyIntersect(kIntGroupConvolute, psRef1, psRef2, psRef3);
772 }
773
774 /* --------------------------------------
775 ��� IntGroupDeconvolute
776 -------------------------------------- */
777 IntGroupStatus
778 IntGroupDeconvolute(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
779 {
780 return IntGroupMyIntersect(kIntGroupDeconvolute, psRef1, psRef2, psRef3);
781 }
782
783 /* --------------------------------------
784 ��� IntGroupDifference
785 -------------------------------------- */
786 IntGroupStatus
787 IntGroupDifference(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
788 {
789 IntGroupStatus result;
790 int i, startPt;
791 result = IntGroupCopy(psRef3, psRef1);
792 if (result != kIntGroupStatusNoError)
793 return result;
794 for (i = 0; i < psRef2->num; i++) {
795 startPt = psRef2->entries[i*2];
796 result = IntGroupRemove(psRef3, startPt, psRef2->entries[i*2+1] - startPt);
797 if (result != kIntGroupStatusNoError)
798 return result;
799 }
800 return kIntGroupStatusNoError;
801 }
802
803 /* --------------------------------------
804 ��� IntGroupNegate
805 -------------------------------------- */
806 IntGroupStatus
807 IntGroupNegate(const IntGroup *psRef1, IntGroup *psRef2)
808 {
809 int i;
810
811 IntGroupCopy(psRef2, psRef1);
812 if (psRef1->num == 0) {
813 // ���������
814 return IntGroupInsertAnEntry(psRef2, 0, 0, INT_MAX);
815 }
816
817 if (psRef1->entries[0] == 0) {
818 for (i = 0; i < psRef1->num - 1; i++) {
819 psRef2->entries[i*2] = psRef1->entries[i*2+1];
820 psRef2->entries[i*2+1] = psRef1->entries[(i+1)*2];
821 }
822 if (psRef1->entries[i*2+1] != INT_MAX) {
823 psRef2->entries[i*2] = psRef1->entries[i*2+1];
824 psRef2->entries[i*2+1] = INT_MAX;
825 } else return IntGroupDeleteEntries(psRef2, i, i);
826 } else {
827 psRef2->entries[0] = 0;
828 psRef2->entries[1] = psRef1->entries[0];
829 for (i = 1; i < psRef1->num; i++) {
830 psRef2->entries[i*2] = psRef1->entries[(i-1)*2+1];
831 psRef2->entries[i*2+1] = psRef1->entries[i*2];
832 }
833 if (psRef1->entries[(i-1)*2+1] != INT_MAX) {
834 return IntGroupInsertAnEntry(psRef2, i, psRef1->entries[(i-1)*2+1], INT_MAX);
835 }
836 }
837 return kIntGroupStatusNoError;
838 }
839
840 /* --------------------------------------
841 ��� IntGroupMinimum
842 -------------------------------------- */
843 int
844 IntGroupMinimum(const IntGroup *psRef)
845 {
846 if (psRef == NULL || psRef->num == 0)
847 return -1;
848 return psRef->entries[0];
849 }
850
851 /* --------------------------------------
852 ��� IntGroupMaximum
853 -------------------------------------- */
854 int
855 IntGroupMaximum(const IntGroup *psRef)
856 {
857 if (psRef == NULL || psRef->num == 0)
858 return -1;
859 return psRef->entries[psRef->num*2-1] - 1;
860 }
861
862 /* --------------------------------------
863 ��� IntGroupOffset
864 -------------------------------------- */
865 IntGroupStatus
866 IntGroupOffset(IntGroup *psRef, int offset)
867 {
868 int i;
869 if (psRef == NULL || psRef->num == 0)
870 return kIntGroupStatusNoError;
871 if (psRef->entries[0] + offset < 0)
872 return kIntGroupStatusOutOfRange; /* Negative number is not allowed */
873 for (i = 0; i < psRef->num; i++) {
874 psRef->entries[i*2] += offset;
875 psRef->entries[i*2+1] += offset;
876 }
877 return kIntGroupStatusNoError;
878 }
879
880 #pragma mark ====== Debugging ======
881
882 char *
883 IntGroupInspect(const IntGroup *pset)
884 {
885 int i, sp, ep, len, len2, size;
886 char buf[64], *s;
887 if (pset == NULL)
888 return strdup("(null)");
889 size = 64;
890 s = (char *)malloc(size);
891 strcpy(s, "IntGroup[");
892 if (pset->num == 0) {
893 strcat(s, "]");
894 return s;
895 }
896 len = (int)strlen(s);
897 for (i = 0; i < pset->num; i++) {
898 const char *sep = (i == pset->num - 1 ? "]" : ", ");
899 sp = pset->entries[i * 2];
900 ep = pset->entries[i * 2 + 1];
901 if (ep > sp + 1)
902 snprintf(buf, sizeof buf, "%d..%d%s", sp, ep - 1, sep);
903 else
904 snprintf(buf, sizeof buf, "%d%s", sp, sep);
905 len2 = (int)strlen(buf);
906 if (len + len2 >= size - 1) {
907 size += 64;
908 s = (char *)realloc(s, size);
909 if (s == NULL)
910 return NULL; /* Out of memory */
911 }
912 len += len2;
913 strcat(s, buf);
914 }
915 return s; /* The caller needs to free the return value */
916 }
917
918 /* --------------------------------------
919 ��� IntGroupDump
920 -------------------------------------- */
921 void
922 IntGroupDump(const IntGroup *pset)
923 {
924 int i, n, m;
925 fprintf(stderr, "IntGroup[%p]: ", pset);
926 for (i = 0; i < pset->num; i++) {
927 n = pset->entries[i*2];
928 m = pset->entries[i*2+1];
929 fprintf(stderr, "%d", n);
930 if (m > n + 1)
931 fprintf(stderr, "-%d", m-1);
932 if (i < pset->num - 1)
933 fprintf(stderr, ",");
934 }
935 fprintf(stderr, "\n");
936 }
937
938 #pragma mark ====== Iterators ======
939
940 /* --------------------------------------
941 ��� IntGroupIteratorNew
942 -------------------------------------- */
943 IntGroupIterator *
944 IntGroupIteratorNew(IntGroup *psRef)
945 {
946 IntGroupIterator *piRef = (IntGroupIterator *)malloc(sizeof(*piRef));
947 if (piRef == NULL)
948 return NULL; /* out of memory */
949 IntGroupIteratorInit(psRef, piRef);
950 piRef->refCount = 1;
951 return piRef;
952 }
953
954 /* --------------------------------------
955 ��� IntGroupIteratorInit
956 -------------------------------------- */
957 IntGroupIterator *
958 IntGroupIteratorInit(IntGroup *psRef, IntGroupIterator *piRef)
959 {
960 piRef->intGroup = psRef;
961 IntGroupRetain(psRef);
962 piRef->index = -1;
963 piRef->position = -1;
964 piRef->refCount = -1;
965 return piRef;
966 }
967
968 /* --------------------------------------
969 ��� IntGroupIteratorRetain
970 -------------------------------------- */
971 void
972 IntGroupIteratorRetain(IntGroupIterator *piRef)
973 {
974 if (piRef == NULL)
975 return;
976 else if (piRef->refCount < 0)
977 piRef->refCount--;
978 else
979 piRef->refCount++;
980 }
981
982 /* --------------------------------------
983 ��� IntGroupIteratorRelease
984 -------------------------------------- */
985 void
986 IntGroupIteratorRelease(IntGroupIterator *piRef)
987 {
988 if (piRef == NULL)
989 return;
990 else if (piRef->refCount < 0) {
991 if (++piRef->refCount == 0)
992 IntGroupRelease(piRef->intGroup);
993 } else {
994 if (--piRef->refCount == 0) {
995 IntGroupRelease(piRef->intGroup);
996 free(piRef);
997 }
998 }
999 }
1000
1001 void
1002 IntGroupIteratorReset(IntGroupIterator *piRef)
1003 {
1004 if (piRef == NULL)
1005 return;
1006 piRef->index = -1;
1007 piRef->position = -1;
1008 }
1009
1010 void
1011 IntGroupIteratorResetAtLast(IntGroupIterator *piRef)
1012 {
1013 if (piRef == NULL || piRef->intGroup == NULL)
1014 return;
1015 piRef->index = piRef->intGroup->num - 1;
1016 if (piRef->index >= 0)
1017 piRef->position = piRef->intGroup->entries[piRef->intGroup->num * 2 - 1];
1018 else piRef->position = -1;
1019 }
1020
1021 int
1022 IntGroupIteratorNext(IntGroupIterator *piRef)
1023 {
1024 if (piRef == NULL || piRef->intGroup == NULL || piRef->intGroup->num == 0 || piRef->index >= piRef->intGroup->num)
1025 return -1;
1026 if (piRef->position < 0) {
1027 piRef->index = 0;
1028 piRef->position = piRef->intGroup->entries[0];
1029 return piRef->position;
1030 } else {
1031 piRef->position++;
1032 if (piRef->intGroup->entries[piRef->index * 2 + 1] > piRef->position)
1033 return piRef->position;
1034 if (piRef->index == piRef->intGroup->num - 1) {
1035 piRef->index = piRef->intGroup->num;
1036 return -1;
1037 } else {
1038 piRef->index++;
1039 piRef->position = piRef->intGroup->entries[piRef->index * 2];
1040 return piRef->position;
1041 }
1042 }
1043 }
1044
1045 int
1046 IntGroupIteratorLast(IntGroupIterator *piRef)
1047 {
1048 if (piRef == NULL || piRef->intGroup == NULL || piRef->intGroup->num == 0 || piRef->index < 0)
1049 return -1;
1050 piRef->position--;
1051 if (piRef->intGroup->entries[piRef->index * 2] <= piRef->position)
1052 return piRef->position;
1053 if (piRef->index == 0) {
1054 piRef->index = -1;
1055 piRef->position = -1;
1056 return -1;
1057 } else {
1058 piRef->index--;
1059 piRef->position = piRef->intGroup->entries[piRef->index * 2 + 1] - 1;
1060 return piRef->position;
1061 }
1062 }

Properties

Name Value
svn:executable *

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26