3 Created by Toshi Nagata, 2000.12.3.
5 Copyright (c) 2000-2008 Toshi Nagata.
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.
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.
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 */
26 #pragma mark ====== Private definitions ======
30 int refCount; /* the reference count */
31 int num; /* the number of entries */
32 int * entries; /* entries[2*n]: begin point, entries[2*n+1]: end point */
35 typedef short IntGroupOperation;
43 #pragma mark ====== Private (static) functions ======
46 /* --------------------------------------
47 ・ IntGroupCalcRequiredStorage
48 -------------------------------------- */
50 IntGroupCalcRequiredStorage(int inLength)
52 return ((inLength * 2 + 3) / 4) * 4 * sizeof(int);
55 /* --------------------------------------
56 ・ IntGroupAdjustStorage
57 -------------------------------------- */
59 IntGroupAdjustStorage(IntGroup *psRef, int inLength)
61 int theOldSize, theNewSize;
63 theOldSize = IntGroupCalcRequiredStorage(psRef->num);
64 theNewSize = IntGroupCalcRequiredStorage(inLength);
65 if (theOldSize == theNewSize)
68 if (theOldSize == 0 && theNewSize != 0) {
69 psRef->entries = (int *)malloc(theNewSize);
70 if (psRef->entries == NULL)
71 return kIntGroupStatusOutOfMemory;
72 } else if (theOldSize != 0 && theNewSize == 0) {
74 psRef->entries = NULL;
76 int *ptr = (int *)realloc(psRef->entries, theNewSize);
78 return kIntGroupStatusOutOfMemory;
81 return kIntGroupStatusNoError;
84 /* --------------------------------------
85 ・ IntGroupInsertAnEntry
86 -------------------------------------- */
88 IntGroupInsertAnEntry(IntGroup *psRef, int inIndex, int inBeginPt, int inEndPt)
90 IntGroupStatus result;
92 result = IntGroupAdjustStorage(psRef, psRef->num + 1);
93 if (result != kIntGroupStatusNoError)
94 return result; /* out of memory */
95 moveAmount = (psRef->num - inIndex) * 2 * sizeof(int);
97 memmove(&(psRef->entries[inIndex * 2 + 2]), &(psRef->entries[inIndex * 2]), moveAmount);
98 psRef->entries[inIndex * 2] = inBeginPt;
99 psRef->entries[inIndex * 2 + 1] = inEndPt;
101 return kIntGroupStatusNoError;
104 /* --------------------------------------
105 ・ IntGroupDeleteEntries
106 -------------------------------------- */
107 static IntGroupStatus
108 IntGroupDeleteEntries(IntGroup *psRef, int inStartIndex, int inEndIndex)
110 IntGroupStatus result;
112 if (inStartIndex > inEndIndex)
113 return 0; /* do nothing */
114 moveAmount = sizeof(int) * 2 * (psRef->num - inEndIndex - 1);
116 memmove(&(psRef->entries[inStartIndex * 2]), &(psRef->entries[inEndIndex * 2 + 2]), moveAmount);
117 result = IntGroupAdjustStorage(psRef, psRef->num - (inEndIndex - inStartIndex + 1));
118 if (result == kIntGroupStatusNoError)
119 psRef->num -= inEndIndex - inStartIndex + 1;
124 #pragma mark ====== New/Retain/Release ======
127 /* --------------------------------------
129 -------------------------------------- */
133 IntGroup *psRef = (IntGroup *)malloc(sizeof(*psRef));
135 return NULL; /* out of memory */
136 psRef->entries = NULL;
142 /* --------------------------------------
143 ・ IntGroupNewFromIntGroup
144 -------------------------------------- */
146 IntGroupNewFromIntGroup(const IntGroup *src)
148 IntGroup *dst = IntGroupNew();
151 if (IntGroupCopy(dst, src) != kIntGroupStatusNoError) {
152 IntGroupRelease(dst);
158 /* --------------------------------------
159 ・ IntGroupNewWithPoints
160 -------------------------------------- */
162 IntGroupNewWithPoints(int start, ...)
166 IntGroup *psRef = IntGroupNew();
171 length = va_arg(ap, int);
172 if (IntGroupAdd(psRef, start, length) != 0) {
173 IntGroupRelease(psRef);
176 start = va_arg(ap, int);
182 /* --------------------------------------
184 -------------------------------------- */
186 IntGroupRetain(IntGroup *psRef)
193 /* --------------------------------------
195 -------------------------------------- */
197 IntGroupRelease(IntGroup *psRef)
201 if (--psRef->refCount == 0) {
202 IntGroupClear(psRef);
208 #pragma mark ====== Clear/Copy ======
210 /* --------------------------------------
212 -------------------------------------- */
214 IntGroupClear(IntGroup *psRef)
218 if (psRef->entries != NULL) {
219 free(psRef->entries);
220 psRef->entries = NULL;
225 /* --------------------------------------
227 -------------------------------------- */
229 IntGroupCopy(IntGroup *psRef1, const IntGroup *psRef2)
232 if (psRef1 == NULL || psRef2 == NULL)
233 return kIntGroupStatusNoError;
234 sts = IntGroupAdjustStorage(psRef1, psRef2->num);
235 if (sts == kIntGroupStatusNoError) {
236 memmove(psRef1->entries, psRef2->entries, psRef2->num * 2 * sizeof(int));
237 psRef1->num = psRef2->num;
243 #pragma mark ====== Point Manipulations ======
246 /* --------------------------------------
248 -------------------------------------- */
250 IntGroupLookup(const IntGroup *psRef, int inPoint, int *outIndex)
255 for (i = 0; i < psRef->num; i++) {
256 if (inPoint < psRef->entries[i*2]) {
257 if (outIndex != NULL)
260 } else if (inPoint < psRef->entries[i*2+1]) {
261 if (outIndex != NULL)
266 if (outIndex != NULL)
267 *outIndex = psRef->num;
271 /* --------------------------------------
273 -------------------------------------- */
275 IntGroupIsEqual(const IntGroup *psRef1, const IntGroup *psRef2)
278 if (psRef1 == NULL || psRef2 == NULL)
279 return (psRef1 == psRef2);
280 if (psRef1->num != psRef2->num)
282 for (i = 0; i < psRef1->num * 2; i++) {
283 if (psRef1->entries[i] != psRef2->entries[i])
289 /* --------------------------------------
291 -------------------------------------- */
293 IntGroupGetCount(const IntGroup *psRef)
299 for (i = 0; i < psRef->num; i++)
300 n += psRef->entries[i*2+1] - psRef->entries[i*2];
304 /* --------------------------------------
305 ・ IntGroupGetIntervalCount
306 -------------------------------------- */
308 IntGroupGetIntervalCount(const IntGroup *psRef)
315 /* --------------------------------------
317 -------------------------------------- */
319 IntGroupAdd(IntGroup *psRef, int inStart, int inCount)
321 int theBeginIndex, theEndIndex;
322 int theBeginFlag, theEndFlag;
325 return kIntGroupStatusNoError;
327 /* inStart, inStart+inCount が位置指定の中でどこにあるか探す */
328 theBeginFlag = IntGroupLookup(psRef, inStart, &theBeginIndex);
329 theEndFlag = IntGroupLookup(psRef, inStart + inCount, &theEndIndex);
332 /* psRef->entries[theBeginIndex*2] <= inStart < psRef->entries[theBeginIndex*2+1] */
334 /* psRef->entries[theEndIndex*2] <= inStart + inCount
335 < psRef->entries[theEndIndex*2+1] */
336 if (theBeginIndex < theEndIndex) {
337 psRef->entries[theBeginIndex*2+1] = psRef->entries[theEndIndex*2+1];
338 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex);
341 /* psRef->entries[(theEndIndex-1)*2+1] <= inStart + inCount
342 < psRef->entries[theEndIndex*2] */
343 psRef->entries[theBeginIndex*2+1] = inStart + inCount;
344 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex - 1);
347 /* psRef->entries[(theBeginIndex-1)*2+1] <= inStart < psRef->entries[theBeginIndex*2] */
349 if (theBeginIndex > 0 && psRef->entries[(theBeginIndex-1)*2+1] == inStart) {
350 /* 1つ前のブロックとくっついてしまう */
352 } else if (theBeginIndex < psRef->num) {
353 thePoint = psRef->entries[theBeginIndex*2]; /* あとで必要かもしれない */
354 psRef->entries[theBeginIndex*2] = inStart;
357 /* psRef->entries[theEndIndex*2] <= inStart + inCount
358 < psRef->entries[theEndIndex*2+1] */
359 psRef->entries[theBeginIndex*2+1] = psRef->entries[theEndIndex*2+1];
360 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex);
362 /* psRef->entries[(theEndIndex-1)*2+1] <= inStart + inCount
363 < psRef->entries[theEndIndex*2] */
364 if (theBeginIndex == theEndIndex) {
365 if (theBeginIndex < psRef->num)
366 psRef->entries[theBeginIndex*2] = thePoint; /* 元に戻す */
367 return IntGroupInsertAnEntry(psRef, theBeginIndex, inStart, inStart + inCount);
369 psRef->entries[theBeginIndex*2+1] = inStart + inCount;
370 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex - 1);
377 /* --------------------------------------
379 -------------------------------------- */
381 IntGroupRemove(IntGroup *psRef, int inStart, int inCount)
383 int theBeginIndex, theEndIndex;
384 int theBeginFlag, theEndFlag;
387 return kIntGroupStatusNoError;
389 /* inStart, inStart+inCount が位置指定の中でどこにあるか探す */
390 theBeginFlag = IntGroupLookup(psRef, inStart, &theBeginIndex);
391 theEndFlag = IntGroupLookup(psRef, inStart + inCount, &theEndIndex);
394 /* psRef->entries[theBeginIndex*2] <= inStart < psRef->entries[theBeginIndex*2+1] */
395 int thePoint = psRef->entries[theBeginIndex*2];
397 /* psRef->entries[theEndIndex*2] <= inStart + inCount
398 < psRef->entries[theEndIndex*2+1] */
399 psRef->entries[theEndIndex*2] = inStart + inCount;
400 if (theBeginIndex == theEndIndex) {
401 if (thePoint == inStart)
404 return IntGroupInsertAnEntry(psRef, theBeginIndex, thePoint, inStart);
406 if (thePoint == inStart)
409 psRef->entries[theBeginIndex*2+1] = inStart;
410 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex - 1);
413 /* psRef->entries[(theEndIndex-1)*2+1] <= inStart + inCount
414 < psRef->entries[theEndIndex*2] */
415 if (thePoint == inStart)
418 psRef->entries[theBeginIndex*2+1] = inStart;
419 return IntGroupDeleteEntries(psRef, theBeginIndex + 1, theEndIndex - 1);
422 /* psRef->entries[(theBeginIndex-1)*2+1] <= inStart < psRef->entries[theBeginIndex*2] */
424 /* psRef->entries[theEndIndex*2] <= inStart + inCount
425 < psRef->entries[theEndIndex*2+1] */
426 psRef->entries[theEndIndex*2] = inStart + inCount;
427 return IntGroupDeleteEntries(psRef, theBeginIndex, theEndIndex - 1);
429 /* psRef->entries[(theEndIndex-1)*2+1] <= inStart + inCount
430 < psRef->entries[theEndIndex*2] */
431 return IntGroupDeleteEntries(psRef, theBeginIndex, theEndIndex - 1);
436 /* --------------------------------------
438 -------------------------------------- */
440 IntGroupReverse(IntGroup *psRef, int inStart, int inCount)
442 int theBeginIndex, theEndIndex, theIndex;
443 int theBeginFlag, theEndFlag;
444 IntGroupStatus result;
447 return kIntGroupStatusNoError;
449 /* inStart, inStart+inCount が位置指定の中でどこにあるか探す */
450 theBeginFlag = IntGroupLookup(psRef, inStart, &theBeginIndex);
451 theEndFlag = IntGroupLookup(psRef, inStart + inCount, &theEndIndex);
454 /* psRef->entries[theBeginIndex*2] <= inStart < psRef->entries[theBeginIndex*2+1] */
455 if (psRef->entries[theBeginIndex*2] < inStart) {
456 result = IntGroupInsertAnEntry(psRef, theBeginIndex, psRef->entries[theBeginIndex*2], inStart);
463 /* psRef->entries[(theBeginIndex-1)*2+1] <= inStart < psRef->entries[theBeginIndex*2] */
465 if (theBeginIndex == theEndIndex && !theEndFlag)
466 thePoint = inStart + inCount; /* theBeginIndex == mNumberOfEntries の場合を含む */
468 thePoint = psRef->entries[theBeginIndex*2];
469 result = IntGroupInsertAnEntry(psRef, theBeginIndex, inStart, thePoint);
477 /* psRef->entries[theEndIndex*2] <= inStart + inCount
478 < psRef->entries[theEndIndex*2+1] */
479 for (theIndex = theBeginIndex; theIndex < theEndIndex; theIndex++) {
480 psRef->entries[theIndex*2] = psRef->entries[theIndex*2+1];
481 psRef->entries[theIndex*2+1] = psRef->entries[(theIndex+1)*2];
483 psRef->entries[theEndIndex*2] = inStart + inCount;
484 if (theEndIndex > 0 && psRef->entries[(theEndIndex-1)*2+1] == inStart + inCount) {
485 /* 1つ前のブロックとくっついてしまう */
486 psRef->entries[(theEndIndex-1)*2+1] = psRef->entries[theEndIndex*2+1];
487 return IntGroupDeleteEntries(psRef, theEndIndex, theEndIndex);
490 /* psRef->entries[(theEndIndex-1)*2+1] <= inStart + inCount
491 < psRef->entries[theEndIndex*2] */
492 for (theIndex = theBeginIndex; theIndex < theEndIndex - 1; theIndex++) {
493 psRef->entries[theIndex*2] = psRef->entries[theIndex*2+1];
494 psRef->entries[theIndex*2+1] = psRef->entries[(theIndex+1)*2];
496 if (theIndex == theEndIndex - 1) {
497 if (psRef->entries[theIndex*2+1] == inStart + inCount)
498 return IntGroupDeleteEntries(psRef, theIndex, theIndex);
500 psRef->entries[theIndex*2] = psRef->entries[theIndex*2+1];
501 psRef->entries[theIndex*2+1] = inStart + inCount;
508 /* --------------------------------------
509 ・ IntGroupAddIntGroup
510 -------------------------------------- */
512 IntGroupAddIntGroup(IntGroup *psRef1, const IntGroup *psRef2)
514 int i, n1, n2, result;
515 if (psRef1 == NULL || psRef2 == NULL)
517 for (i = 0; (n1 = IntGroupGetStartPoint(psRef2, i)) >= 0; i++) {
518 n2 = IntGroupGetInterval(psRef2, i);
519 if ((result = IntGroupAdd(psRef1, n1, n2)) != 0)
525 /* --------------------------------------
526 ・ IntGroupRemoveIntGroup
527 -------------------------------------- */
529 IntGroupRemoveIntGroup(IntGroup *psRef1, const IntGroup *psRef2)
531 int i, n1, n2, result;
532 if (psRef1 == NULL || psRef2 == NULL)
534 for (i = 0; (n1 = IntGroupGetStartPoint(psRef2, i)) >= 0; i++) {
535 n2 = IntGroupGetInterval(psRef2, i);
536 if ((result = IntGroupRemove(psRef1, n1, n2)) != 0)
542 /* --------------------------------------
543 ・ IntGroupReverseIntGroup
544 -------------------------------------- */
546 IntGroupReverseIntGroup(IntGroup *psRef1, const IntGroup *psRef2)
548 int i, n1, n2, result;
549 if (psRef1 == NULL || psRef2 == NULL)
551 for (i = 0; (n1 = IntGroupGetStartPoint(psRef2, i)) >= 0; i++) {
552 n2 = IntGroupGetInterval(psRef2, i);
553 if ((result = IntGroupReverse(psRef1, n1, n2)) != 0)
559 /* --------------------------------------
560 ・ IntGroupGetStartPoint
561 -------------------------------------- */
563 IntGroupGetStartPoint(const IntGroup *psRef, int inIndex)
565 if (psRef == NULL || inIndex < 0 || inIndex >= psRef->num)
567 else return psRef->entries[inIndex*2];
570 /* --------------------------------------
571 ・ IntGroupGetEndPoint
572 -------------------------------------- */
574 IntGroupGetEndPoint(const IntGroup *psRef, int inIndex)
576 if (psRef == NULL || inIndex < 0 || inIndex >= psRef->num)
578 else return psRef->entries[inIndex*2+1];
581 /* --------------------------------------
582 ・ IntGroupGetInterval
583 -------------------------------------- */
585 IntGroupGetInterval(const IntGroup *psRef, int inIndex)
587 if (psRef == NULL || inIndex < 0 || inIndex >= psRef->num)
589 else return psRef->entries[inIndex*2+1] - psRef->entries[inIndex*2];
592 /* --------------------------------------
593 ・ IntGroupGetNthPoint
594 -------------------------------------- */
596 IntGroupGetNthPoint(const IntGroup *psRef, int inCount)
599 if (psRef == NULL || inCount < 0)
602 for (i = 0; i < psRef->num; i++) {
603 dn = psRef->entries[i*2+1] - psRef->entries[i*2];
604 if (inCount < n + dn) {
605 /* The inCount-th point is in this interval */
606 return psRef->entries[i*2] + inCount - n;
614 /* --------------------------------------
615 ・ IntGroupLookupPoint
616 -------------------------------------- */
618 IntGroupLookupPoint(const IntGroup *psRef, int inPoint)
621 if (psRef == NULL || inPoint < 0)
624 for (i = 0; i < psRef->num; i++) {
625 if (inPoint >= psRef->entries[i*2] && inPoint < psRef->entries[i*2+1]) {
626 return n + inPoint - psRef->entries[i*2];
628 n += psRef->entries[i*2+1] - psRef->entries[i*2];
635 #pragma mark ====== Binary Operations ======
638 /* --------------------------------------
639 ・ IntGroupMyIntersect
640 -------------------------------------- */
641 static IntGroupStatus
643 IntGroupOperation inCode,
644 const IntGroup *psRef1,
645 const IntGroup *psRef2,
649 int i, j, offset1, offset2, where;
650 int theBeginIndex, theEndIndex;
651 int theBeginFlag, theEndFlag;
653 IntGroupStatus result = kIntGroupStatusNoError;
655 IntGroupClear(psRef3);
656 offset1 = offset2 = 0;
659 for (i = 0; result == 0 && i < psRef2->num; i++) {
662 int newBeginPt, newEndPt;
664 ptr = &(psRef2->entries[i * 2]);
666 case kIntGroupIntersect:
667 break; /* offset1 = offset2 = 0 */
668 case kIntGroupConvolute:
669 offset1 = base - ptr[0];
672 case kIntGroupDeconvolute:
673 offset2 = base - ptr[0];
676 beginPt = ptr[0] + offset1;
677 endPt = ptr[1] + offset1;
678 theBeginFlag = IntGroupLookup(psRef1, beginPt, &theBeginIndex);
679 theEndFlag = IntGroupLookup(psRef1, endPt, &theEndIndex);
681 if (theBeginIndex == psRef1->num)
682 break; /* もう加えるべき区間はない */
685 newBeginPt = beginPt + offset2;
687 newBeginPt = psRef1->entries[theBeginIndex * 2] + offset2;
689 if (theEndFlag && theBeginIndex == theEndIndex) {
690 newEndPt = endPt + offset2;
691 } else if (!theEndFlag && theBeginIndex == theEndIndex) {
692 newEndPt = newBeginPt; /* null interval */
694 newEndPt = psRef1->entries[theBeginIndex * 2 + 1] + offset2;
696 /* 直前の区間と連続していないかどうかチェック */
697 if (where > 0 && newBeginPt == psRef3->entries[where * 2 - 1]) {
698 psRef3->entries[where * 2 - 1] = newEndPt;
699 } else if (newBeginPt < newEndPt) {
700 result = IntGroupInsertAnEntry(psRef3, where++, newBeginPt, newEndPt);
702 if (result == kIntGroupStatusNoError) {
703 for (j = theBeginIndex + 1; j < theEndIndex; j++) {
704 result = IntGroupInsertAnEntry(psRef3,
706 psRef1->entries[j * 2] + offset2,
707 psRef1->entries[j * 2 + 1] + offset2);
708 if (result != kIntGroupStatusNoError)
712 if (result == kIntGroupStatusNoError) {
713 if (theEndFlag && theBeginIndex < theEndIndex
714 && psRef1->entries[theEndIndex * 2] < endPt)
715 result = IntGroupInsertAnEntry(psRef3,
717 psRef1->entries[theEndIndex * 2] + offset2,
721 base += ptr[1] - ptr[0];
724 /* ***** debug ***** */
727 fp = ::fopen("intersect.out", "at");
729 case code_Intersect: ::fprintf(fp, "Intersect:\n"); break;
730 case code_Convolute: ::fprintf(fp, "Convolute:\n"); break;
731 case code_Deconvolute: ::fprintf(fp, "Deconvolute:\n"); break;
733 for (i = 0; i < psRef1.mNumberOfEntries; i++) {
734 ::fprintf(fp, "%c%ld %ld", (i == 0 ? '(' : ' '),
735 (int)psRef1.mEntries[i].beginPt,
736 (int)psRef1.mEntries[i].endPt);
738 ::fprintf(fp, ")\n");
739 for (i = 0; i < psRef2.mNumberOfEntries; i++) {
740 ::fprintf(fp, "%c%ld %ld", (i == 0 ? '(' : ' '),
741 (int)psRef2.mEntries[i].beginPt,
742 (int)psRef2.mEntries[i].endPt);
744 ::fprintf(fp, ")\n");
745 for (i = 0; i < psRef3.mNumberOfEntries; i++) {
746 ::fprintf(fp, "%c%ld %ld", (i == 0 ? '(' : ' '),
747 (int)psRef3.mEntries[i].beginPt,
748 (int)psRef3.mEntries[i].endPt);
750 ::fprintf(fp, ")\n");
753 /* ********************* */
758 /* --------------------------------------
760 -------------------------------------- */
762 IntGroupUnion(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
765 IntGroupStatus result;
766 result = IntGroupCopy(psRef3, psRef2);
767 if (result != kIntGroupStatusNoError)
769 for (i = 0; i < psRef1->num; i++) {
770 startPt = psRef1->entries[i*2];
771 result = IntGroupAdd(psRef3, startPt, psRef1->entries[i*2+1] - startPt);
772 if (result != kIntGroupStatusNoError)
775 return kIntGroupStatusNoError;
778 /* --------------------------------------
780 -------------------------------------- */
782 IntGroupIntersect(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
784 return IntGroupMyIntersect(kIntGroupIntersect, psRef1, psRef2, psRef3);
787 /* --------------------------------------
789 -------------------------------------- */
791 IntGroupXor(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
793 IntGroupStatus result;
795 result = IntGroupCopy(psRef3, psRef1);
796 if (result != kIntGroupStatusNoError)
798 for (i = 0; i < psRef2->num; i++) {
799 startPt = psRef2->entries[i*2];
800 result = IntGroupReverse(psRef3, startPt, psRef2->entries[i*2+1] - startPt);
801 if (result != kIntGroupStatusNoError)
804 return kIntGroupStatusNoError;
807 /* --------------------------------------
809 -------------------------------------- */
811 IntGroupConvolute(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
813 return IntGroupMyIntersect(kIntGroupConvolute, psRef1, psRef2, psRef3);
816 /* --------------------------------------
817 ・ IntGroupDeconvolute
818 -------------------------------------- */
820 IntGroupDeconvolute(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
822 return IntGroupMyIntersect(kIntGroupDeconvolute, psRef1, psRef2, psRef3);
825 /* --------------------------------------
827 -------------------------------------- */
829 IntGroupDifference(const IntGroup *psRef1, const IntGroup *psRef2, IntGroup *psRef3)
831 IntGroupStatus result;
833 result = IntGroupCopy(psRef3, psRef1);
834 if (result != kIntGroupStatusNoError)
836 for (i = 0; i < psRef2->num; i++) {
837 startPt = psRef2->entries[i*2];
838 result = IntGroupRemove(psRef3, startPt, psRef2->entries[i*2+1] - startPt);
839 if (result != kIntGroupStatusNoError)
842 return kIntGroupStatusNoError;
845 /* --------------------------------------
847 -------------------------------------- */
849 IntGroupNegate(const IntGroup *psRef1, IntGroup *psRef2)
853 IntGroupCopy(psRef2, psRef1);
854 if (psRef1->num == 0) {
856 return IntGroupInsertAnEntry(psRef2, 0, 0, INT_MAX);
859 if (psRef1->entries[0] == 0) {
860 for (i = 0; i < psRef1->num - 1; i++) {
861 psRef2->entries[i*2] = psRef1->entries[i*2+1];
862 psRef2->entries[i*2+1] = psRef1->entries[(i+1)*2];
864 if (psRef1->entries[i*2+1] != INT_MAX) {
865 psRef2->entries[i*2] = psRef1->entries[i*2+1];
866 psRef2->entries[i*2+1] = INT_MAX;
867 } else return IntGroupDeleteEntries(psRef2, i, i);
869 psRef2->entries[0] = 0;
870 psRef2->entries[1] = psRef1->entries[0];
871 for (i = 1; i < psRef1->num; i++) {
872 psRef2->entries[i*2] = psRef1->entries[(i-1)*2+1];
873 psRef2->entries[i*2+1] = psRef1->entries[i*2];
875 if (psRef1->entries[(i-1)*2+1] != INT_MAX) {
876 return IntGroupInsertAnEntry(psRef2, i, psRef1->entries[(i-1)*2+1], INT_MAX);
879 return kIntGroupStatusNoError;
882 /* --------------------------------------
884 -------------------------------------- */
886 IntGroupOffset(IntGroup *psRef, int offset)
889 if (psRef == NULL || psRef->num == 0)
890 return kIntGroupStatusNoError;
891 if (psRef->entries[0] + offset < 0)
892 return kIntGroupStatusOutOfRange; /* Negative number is not allowed */
893 for (i = 0; i < psRef->num; i++) {
894 psRef->entries[i*2] += offset;
895 psRef->entries[i*2+1] += offset;
897 return kIntGroupStatusNoError;
901 #pragma mark ====== Debugging ======
904 /* --------------------------------------
906 -------------------------------------- */
908 IntGroupDump(const IntGroup *pset)
911 fprintf(stderr, "IntGroup[%p]: ", pset);
912 for (i = 0; i < pset->num; i++) {
913 n = pset->entries[i*2];
914 m = pset->entries[i*2+1];
915 fprintf(stderr, "%d", n);
917 fprintf(stderr, "-%d", m-1);
918 if (i < pset->num - 1)
919 fprintf(stderr, ",");
921 fprintf(stderr, "\n");
924 #pragma mark ====== Iterators ======
926 /* --------------------------------------
927 ・ IntGroupIteratorNew
928 -------------------------------------- */
930 IntGroupIteratorNew(IntGroup *psRef)
932 IntGroupIterator *piRef = (IntGroupIterator *)malloc(sizeof(*piRef));
934 return NULL; /* out of memory */
935 IntGroupIteratorInit(psRef, piRef);
940 /* --------------------------------------
941 ・ IntGroupIteratorInit
942 -------------------------------------- */
944 IntGroupIteratorInit(IntGroup *psRef, IntGroupIterator *piRef)
946 piRef->intGroup = psRef;
947 IntGroupRetain(psRef);
949 piRef->position = -1;
950 piRef->refCount = -1;
954 /* --------------------------------------
955 ・ IntGroupIteratorRetain
956 -------------------------------------- */
958 IntGroupIteratorRetain(IntGroupIterator *piRef)
962 else if (piRef->refCount < 0)
968 /* --------------------------------------
969 ・ IntGroupIteratorRelease
970 -------------------------------------- */
972 IntGroupIteratorRelease(IntGroupIterator *piRef)
976 else if (piRef->refCount < 0) {
977 if (++piRef->refCount == 0)
978 IntGroupRelease(piRef->intGroup);
980 if (--piRef->refCount == 0) {
981 IntGroupRelease(piRef->intGroup);
988 IntGroupIteratorReset(IntGroupIterator *piRef)
993 piRef->position = -1;
997 IntGroupIteratorResetAtLast(IntGroupIterator *piRef)
999 if (piRef == NULL || piRef->intGroup == NULL)
1001 piRef->index = piRef->intGroup->num - 1;
1002 if (piRef->index >= 0)
1003 piRef->position = piRef->intGroup->entries[piRef->intGroup->num * 2 - 1];
1004 else piRef->position = -1;
1008 IntGroupIteratorNext(IntGroupIterator *piRef)
1010 if (piRef == NULL || piRef->intGroup == NULL || piRef->intGroup->num == 0 || piRef->index >= piRef->intGroup->num)
1012 if (piRef->position < 0) {
1014 piRef->position = piRef->intGroup->entries[0];
1015 return piRef->position;
1018 if (piRef->intGroup->entries[piRef->index * 2 + 1] > piRef->position)
1019 return piRef->position;
1020 if (piRef->index == piRef->intGroup->num - 1) {
1021 piRef->index = piRef->intGroup->num;
1025 piRef->position = piRef->intGroup->entries[piRef->index * 2];
1026 return piRef->position;
1032 IntGroupIteratorLast(IntGroupIterator *piRef)
1034 if (piRef == NULL || piRef->intGroup == NULL || piRef->intGroup->num == 0 || piRef->index < 0)
1037 if (piRef->intGroup->entries[piRef->index * 2] <= piRef->position)
1038 return piRef->position;
1039 if (piRef->index == 0) {
1041 piRef->position = -1;
1045 piRef->position = piRef->intGroup->entries[piRef->index * 2 + 1] - 1;
1046 return piRef->position;