1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
43 #define ICV_FREE_PTR(storage) \
44 ((char*)(storage)->top + (storage)->block_size - (storage)->free_space)
46 #define ICV_ALIGNED_SEQ_BLOCK_SIZE \
47 (int)cvAlign(sizeof(CvSeqBlock), CV_STRUCT_ALIGN)
50 cvAlignLeft( int size, int align )
55 #define CV_GET_LAST_ELEM( seq, block ) \
56 ((block)->data + ((block)->count - 1)*((seq)->elem_size))
58 #define CV_SWAP_ELEMS(a,b,elem_size) \
61 for( k = 0; k < elem_size; k++ ) \
70 #define ICV_SHIFT_TAB_MAX 32
71 static const char icvPower2ShiftTab[] =
73 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4,
74 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5
77 /****************************************************************************************\
78 * Functions for manipulating memory storage - list of memory blocks *
79 \****************************************************************************************/
81 /* initializes allocated storage */
83 icvInitMemStorage( CvMemStorage* storage, int block_size )
85 CV_FUNCNAME( "icvInitMemStorage " );
90 CV_ERROR( CV_StsNullPtr, "" );
93 block_size = CV_STORAGE_BLOCK_SIZE;
95 block_size = cvAlign( block_size, CV_STRUCT_ALIGN );
96 assert( sizeof(CvMemBlock) % CV_STRUCT_ALIGN == 0 );
98 memset( storage, 0, sizeof( *storage ));
99 storage->signature = CV_STORAGE_MAGIC_VAL;
100 storage->block_size = block_size;
106 /* creates root memory storage */
107 CV_IMPL CvMemStorage*
108 cvCreateMemStorage( int block_size )
110 CvMemStorage *storage = 0;
112 CV_FUNCNAME( "cvCreateMemStorage" );
116 CV_CALL( storage = (CvMemStorage *)cvAlloc( sizeof( CvMemStorage )));
117 CV_CALL( icvInitMemStorage( storage, block_size ));
121 if( cvGetErrStatus() < 0 )
128 /* creates child memory storage */
129 CV_IMPL CvMemStorage *
130 cvCreateChildMemStorage( CvMemStorage * parent )
132 CvMemStorage *storage = 0;
133 CV_FUNCNAME( "cvCreateChildMemStorage" );
138 CV_ERROR( CV_StsNullPtr, "" );
140 CV_CALL( storage = cvCreateMemStorage(parent->block_size));
141 storage->parent = parent;
145 if( cvGetErrStatus() < 0 )
152 /* releases all blocks of the storage (or returns them to parent if any) */
154 icvDestroyMemStorage( CvMemStorage* storage )
156 CV_FUNCNAME( "icvDestroyMemStorage" );
163 CvMemBlock *dst_top = 0;
166 CV_ERROR( CV_StsNullPtr, "" );
168 if( storage->parent )
169 dst_top = storage->parent->top;
171 for( block = storage->bottom; block != 0; k++ )
173 CvMemBlock *temp = block;
176 if( storage->parent )
180 temp->prev = dst_top;
181 temp->next = dst_top->next;
183 temp->next->prev = temp;
184 dst_top = dst_top->next = temp;
188 dst_top = storage->parent->bottom = storage->parent->top = temp;
189 temp->prev = temp->next = 0;
190 storage->free_space = storage->block_size - sizeof( *temp );
199 storage->top = storage->bottom = 0;
200 storage->free_space = 0;
206 /* releases memory storage */
208 cvReleaseMemStorage( CvMemStorage** storage )
211 CV_FUNCNAME( "cvReleaseMemStorage" );
216 CV_ERROR( CV_StsNullPtr, "" );
223 CV_CALL( icvDestroyMemStorage( st ));
231 /* clears memory storage (returns blocks to the parent if any) */
233 cvClearMemStorage( CvMemStorage * storage )
235 CV_FUNCNAME( "cvClearMemStorage" );
240 CV_ERROR( CV_StsNullPtr, "" );
242 if( storage->parent )
244 icvDestroyMemStorage( storage );
248 storage->top = storage->bottom;
249 storage->free_space = storage->bottom ? storage->block_size - sizeof(CvMemBlock) : 0;
256 /* moves stack pointer to next block.
257 If no blocks, allocate new one and link it to the storage */
259 icvGoNextMemBlock( CvMemStorage * storage )
261 CV_FUNCNAME( "icvGoNextMemBlock" );
266 CV_ERROR( CV_StsNullPtr, "" );
268 if( !storage->top || !storage->top->next )
272 if( !(storage->parent) )
274 CV_CALL( block = (CvMemBlock *)cvAlloc( storage->block_size ));
278 CvMemStorage *parent = storage->parent;
279 CvMemStoragePos parent_pos;
281 cvSaveMemStoragePos( parent, &parent_pos );
282 CV_CALL( icvGoNextMemBlock( parent ));
285 cvRestoreMemStoragePos( parent, &parent_pos );
287 if( block == parent->top ) /* the single allocated block */
289 assert( parent->bottom == block );
290 parent->top = parent->bottom = 0;
291 parent->free_space = 0;
295 /* cut the block from the parent's list of blocks */
296 parent->top->next = block->next;
298 block->next->prev = parent->top;
304 block->prev = storage->top;
307 storage->top->next = block;
309 storage->top = storage->bottom = block;
312 if( storage->top->next )
313 storage->top = storage->top->next;
314 storage->free_space = storage->block_size - sizeof(CvMemBlock);
315 assert( storage->free_space % CV_STRUCT_ALIGN == 0 );
321 /* remembers memory storage position */
323 cvSaveMemStoragePos( const CvMemStorage * storage, CvMemStoragePos * pos )
325 CV_FUNCNAME( "cvSaveMemStoragePos" );
329 if( !storage || !pos )
330 CV_ERROR( CV_StsNullPtr, "" );
332 pos->top = storage->top;
333 pos->free_space = storage->free_space;
339 /* restores memory storage position */
341 cvRestoreMemStoragePos( CvMemStorage * storage, CvMemStoragePos * pos )
343 CV_FUNCNAME( "cvRestoreMemStoragePos" );
347 if( !storage || !pos )
348 CV_ERROR( CV_StsNullPtr, "" );
349 if( pos->free_space > storage->block_size )
350 CV_ERROR( CV_StsBadSize, "" );
353 // this breaks icvGoNextMemBlock, so comment it off for now
354 if( storage->parent && (!pos->top || pos->top->next) )
356 CvMemBlock* save_bottom;
361 save_bottom = storage->bottom;
362 storage->bottom = pos->top->next;
364 storage->bottom->prev = 0;
366 icvDestroyMemStorage( storage );
367 storage->bottom = save_bottom;
370 storage->top = pos->top;
371 storage->free_space = pos->free_space;
375 storage->top = storage->bottom;
376 storage->free_space = storage->top ? storage->block_size - sizeof(CvMemBlock) : 0;
383 /* Allocates continuous buffer of the specified size in the storage */
385 cvMemStorageAlloc( CvMemStorage* storage, size_t size )
389 CV_FUNCNAME( "cvMemStorageAlloc" );
394 CV_ERROR( CV_StsNullPtr, "NULL storage pointer" );
397 CV_ERROR( CV_StsOutOfRange, "Too large memory block is requested" );
399 assert( storage->free_space % CV_STRUCT_ALIGN == 0 );
401 if( (size_t)storage->free_space < size )
403 size_t max_free_space = cvAlignLeft(storage->block_size - sizeof(CvMemBlock), CV_STRUCT_ALIGN);
404 if( max_free_space < size )
405 CV_ERROR( CV_StsOutOfRange, "requested size is negative or too big" );
407 CV_CALL( icvGoNextMemBlock( storage ));
410 ptr = ICV_FREE_PTR(storage);
411 assert( (size_t)ptr % CV_STRUCT_ALIGN == 0 );
412 storage->free_space = cvAlignLeft(storage->free_space - (int)size, CV_STRUCT_ALIGN );
421 cvMemStorageAllocString( CvMemStorage* storage, const char* ptr, int len )
424 CV_FUNCNAME( "cvMemStorageAllocString" );
428 str.len = len >= 0 ? len : (int)strlen(ptr);
429 CV_CALL( str.ptr = (char*)cvMemStorageAlloc( storage, str.len + 1 ));
430 memcpy( str.ptr, ptr, str.len );
431 str.ptr[str.len] = '\0';
439 /****************************************************************************************\
440 * Sequence implementation *
441 \****************************************************************************************/
443 /* creates empty sequence */
445 cvCreateSeq( int seq_flags, int header_size, int elem_size, CvMemStorage * storage )
449 CV_FUNCNAME( "cvCreateSeq" );
454 CV_ERROR( CV_StsNullPtr, "" );
455 if( header_size < (int)sizeof( CvSeq ) || elem_size <= 0 )
456 CV_ERROR( CV_StsBadSize, "" );
458 /* allocate sequence header */
459 CV_CALL( seq = (CvSeq*)cvMemStorageAlloc( storage, header_size ));
460 memset( seq, 0, header_size );
462 seq->header_size = header_size;
463 seq->flags = (seq_flags & ~CV_MAGIC_MASK) | CV_SEQ_MAGIC_VAL;
465 int elemtype = CV_MAT_TYPE(seq_flags);
466 int typesize = CV_ELEM_SIZE(elemtype);
468 if( elemtype != CV_SEQ_ELTYPE_GENERIC &&
469 typesize != 0 && typesize != elem_size )
470 CV_ERROR( CV_StsBadSize,
471 "Specified element size doesn't match to the size of the specified element type "
472 "(try to use 0 for element type)" );
474 seq->elem_size = elem_size;
475 seq->storage = storage;
477 CV_CALL( cvSetSeqBlockSize( seq, (1 << 10)/elem_size ));
485 /* adjusts <delta_elems> field of sequence. It determines how much the sequence
486 grows if there are no free space inside the sequence buffers */
488 cvSetSeqBlockSize( CvSeq *seq, int delta_elements )
491 int useful_block_size;
493 CV_FUNCNAME( "cvSetSeqBlockSize" );
497 if( !seq || !seq->storage )
498 CV_ERROR( CV_StsNullPtr, "" );
499 if( delta_elements < 0 )
500 CV_ERROR( CV_StsOutOfRange, "" );
502 useful_block_size = cvAlignLeft(seq->storage->block_size - sizeof(CvMemBlock) -
503 sizeof(CvSeqBlock), CV_STRUCT_ALIGN);
504 elem_size = seq->elem_size;
506 if( delta_elements == 0 )
508 delta_elements = (1 << 10) / elem_size;
509 delta_elements = MAX( delta_elements, 1 );
511 if( delta_elements * elem_size > useful_block_size )
513 delta_elements = useful_block_size / elem_size;
514 if( delta_elements == 0 )
515 CV_ERROR( CV_StsOutOfRange, "Storage block size is too small "
516 "to fit the sequence elements" );
519 seq->delta_elems = delta_elements;
525 /* finds sequence element by its index */
527 cvGetSeqElem( const CvSeq *seq, int index )
530 int count, total = seq->total;
532 if( (unsigned)index >= (unsigned)total )
534 index += index < 0 ? total : 0;
535 index -= index >= total ? total : 0;
536 if( (unsigned)index >= (unsigned)total )
541 if( index + index <= total )
543 while( index >= (count = block->count) )
554 total -= block->count;
556 while( index < total );
560 return block->data + index * seq->elem_size;
564 /* calculates index of sequence element */
566 cvSeqElemIdx( const CvSeq* seq, const void* _element, CvSeqBlock** _block )
568 const char *element = (const char *)_element;
571 CvSeqBlock *first_block;
574 CV_FUNCNAME( "cvSeqElemIdx" );
578 if( !seq || !element )
579 CV_ERROR( CV_StsNullPtr, "" );
581 block = first_block = seq->first;
582 elem_size = seq->elem_size;
586 if( (unsigned)(element - block->data) < (unsigned) (block->count * elem_size) )
590 if( elem_size <= ICV_SHIFT_TAB_MAX && (id = icvPower2ShiftTab[elem_size - 1]) >= 0 )
591 id = (int)((size_t)(element - block->data) >> id);
593 id = (int)((size_t)(element - block->data) / elem_size);
594 id += block->start_index - seq->first->start_index;
598 if( block == first_block )
609 cvSliceLength( CvSlice slice, const CvSeq* seq )
611 int total = seq->total;
612 int length = slice.end_index - slice.start_index;
616 if( slice.start_index < 0 )
617 slice.start_index += total;
618 if( slice.end_index <= 0 )
619 slice.end_index += total;
621 length = slice.end_index - slice.start_index;
630 else if( length > total )
637 /* copies all the sequence elements into single continuous array */
639 cvCvtSeqToArray( const CvSeq *seq, void *array, CvSlice slice )
641 CV_FUNCNAME( "cvCvtSeqToArray" );
645 int elem_size, total;
647 char *dst = (char*)array;
650 CV_ERROR( CV_StsNullPtr, "" );
652 elem_size = seq->elem_size;
653 total = cvSliceLength( slice, seq )*elem_size;
658 cvStartReadSeq( seq, &reader, 0 );
659 CV_CALL( cvSetSeqReaderPos( &reader, slice.start_index, 0 ));
663 int count = (int)(reader.block_max - reader.ptr);
667 memcpy( dst, reader.ptr, count );
669 reader.block = reader.block->next;
670 reader.ptr = reader.block->data;
671 reader.block_max = reader.ptr + reader.block->count*elem_size;
682 /* constructs sequence from array without copying any data.
683 the resultant sequence can't grow above its initial size */
685 cvMakeSeqHeaderForArray( int seq_flags, int header_size, int elem_size,
686 void *array, int total, CvSeq *seq, CvSeqBlock * block )
690 CV_FUNCNAME( "cvMakeSeqHeaderForArray" );
694 if( elem_size <= 0 || header_size < (int)sizeof( CvSeq ) || total < 0 )
695 CV_ERROR( CV_StsBadSize, "" );
697 if( !seq || ((!array || !block) && total > 0) )
698 CV_ERROR( CV_StsNullPtr, "" );
700 memset( seq, 0, header_size );
702 seq->header_size = header_size;
703 seq->flags = (seq_flags & ~CV_MAGIC_MASK) | CV_SEQ_MAGIC_VAL;
705 int elemtype = CV_MAT_TYPE(seq_flags);
706 int typesize = CV_ELEM_SIZE(elemtype);
708 if( elemtype != CV_SEQ_ELTYPE_GENERIC &&
709 typesize != 0 && typesize != elem_size )
710 CV_ERROR( CV_StsBadSize,
711 "Element size doesn't match to the size of predefined element type "
712 "(try to use 0 for sequence element type)" );
714 seq->elem_size = elem_size;
716 seq->block_max = seq->ptr = (char *) array + total * elem_size;
721 block->prev = block->next = block;
722 block->start_index = 0;
723 block->count = total;
724 block->data = (char *) array;
735 /* the function allocates space for at least one more sequence element.
736 if there are free sequence blocks (seq->free_blocks != 0),
737 they are reused, otherwise the space is allocated in the storage */
739 icvGrowSeq( CvSeq *seq, int in_front_of )
741 CV_FUNCNAME( "icvGrowSeq" );
748 CV_ERROR( CV_StsNullPtr, "" );
749 block = seq->free_blocks;
753 int elem_size = seq->elem_size;
754 int delta_elems = seq->delta_elems;
755 CvMemStorage *storage = seq->storage;
757 if( seq->total >= delta_elems*4 )
758 cvSetSeqBlockSize( seq, delta_elems*2 );
761 CV_ERROR( CV_StsNullPtr, "The sequence has NULL storage pointer" );
763 /* if there is a free space just after last allocated block
764 and it's big enough then enlarge the last block
765 (this can happen only if the new block is added to the end of sequence */
766 if( (unsigned)(ICV_FREE_PTR(storage) - seq->block_max) < CV_STRUCT_ALIGN &&
767 storage->free_space >= seq->elem_size && !in_front_of )
769 int delta = storage->free_space / elem_size;
771 delta = MIN( delta, delta_elems ) * elem_size;
772 seq->block_max += delta;
773 storage->free_space = cvAlignLeft((int)(((char*)storage->top + storage->block_size) -
774 seq->block_max), CV_STRUCT_ALIGN );
779 int delta = elem_size * delta_elems + ICV_ALIGNED_SEQ_BLOCK_SIZE;
781 /* try to allocate <delta_elements> elements */
782 if( storage->free_space < delta )
784 int small_block_size = MAX(1, delta_elems/3)*elem_size +
785 ICV_ALIGNED_SEQ_BLOCK_SIZE;
786 /* try to allocate smaller part */
787 if( storage->free_space >= small_block_size + CV_STRUCT_ALIGN )
789 delta = (storage->free_space - ICV_ALIGNED_SEQ_BLOCK_SIZE)/seq->elem_size;
790 delta = delta*seq->elem_size + ICV_ALIGNED_SEQ_BLOCK_SIZE;
794 CV_CALL( icvGoNextMemBlock( storage ));
795 assert( storage->free_space >= delta );
799 CV_CALL( block = (CvSeqBlock*)cvMemStorageAlloc( storage, delta ));
800 block->data = (char*)cvAlignPtr( block + 1, CV_STRUCT_ALIGN );
801 block->count = delta - ICV_ALIGNED_SEQ_BLOCK_SIZE;
802 block->prev = block->next = 0;
807 seq->free_blocks = block->next;
813 block->prev = block->next = block;
817 block->prev = seq->first->prev;
818 block->next = seq->first;
819 block->prev->next = block->next->prev = block;
822 /* for free blocks the <count> field means total number of bytes in the block.
823 And for used blocks it means a current number of sequence
824 elements in the block */
825 assert( block->count % seq->elem_size == 0 && block->count > 0 );
829 seq->ptr = block->data;
830 seq->block_max = block->data + block->count;
831 block->start_index = block == block->prev ? 0 :
832 block->prev->start_index + block->prev->count;
836 int delta = block->count / seq->elem_size;
837 block->data += block->count;
839 if( block != block->prev )
841 assert( seq->first->start_index == 0 );
846 seq->block_max = seq->ptr = block->data;
849 block->start_index = 0;
853 block->start_index += delta;
855 if( block == seq->first )
865 /* recycles a sequence block for the further use */
867 icvFreeSeqBlock( CvSeq *seq, int in_front_of )
869 /*CV_FUNCNAME( "icvFreeSeqBlock" );*/
873 CvSeqBlock *block = seq->first;
875 assert( (in_front_of ? block : block->prev)->count == 0 );
877 if( block == block->prev ) /* single block case */
879 block->count = (int)(seq->block_max - block->data) + block->start_index * seq->elem_size;
880 block->data = seq->block_max - block->count;
882 seq->ptr = seq->block_max = 0;
890 assert( seq->ptr == block->data );
892 block->count = (int)(seq->block_max - seq->ptr);
893 seq->block_max = seq->ptr = block->prev->data +
894 block->prev->count * seq->elem_size;
898 int delta = block->start_index;
900 block->count = delta * seq->elem_size;
901 block->data -= block->count;
903 /* update start indices of sequence blocks */
906 block->start_index -= delta;
908 if( block == seq->first )
912 seq->first = block->next;
915 block->prev->next = block->next;
916 block->next->prev = block->prev;
919 assert( block->count > 0 && block->count % seq->elem_size == 0 );
920 block->next = seq->free_blocks;
921 seq->free_blocks = block;
927 /****************************************************************************************\
928 * Sequence Writer implementation *
929 \****************************************************************************************/
931 /* initializes sequence writer */
933 cvStartAppendToSeq( CvSeq *seq, CvSeqWriter * writer )
935 CV_FUNCNAME( "cvStartAppendToSeq" );
939 if( !seq || !writer )
940 CV_ERROR( CV_StsNullPtr, "" );
942 memset( writer, 0, sizeof( *writer ));
943 writer->header_size = sizeof( CvSeqWriter );
946 writer->block = seq->first ? seq->first->prev : 0;
947 writer->ptr = seq->ptr;
948 writer->block_max = seq->block_max;
954 /* initializes sequence writer */
956 cvStartWriteSeq( int seq_flags, int header_size,
957 int elem_size, CvMemStorage * storage, CvSeqWriter * writer )
961 CV_FUNCNAME( "cvStartWriteSeq" );
965 if( !storage || !writer )
966 CV_ERROR( CV_StsNullPtr, "" );
968 CV_CALL( seq = cvCreateSeq( seq_flags, header_size, elem_size, storage ));
969 cvStartAppendToSeq( seq, writer );
975 /* updates sequence header */
977 cvFlushSeqWriter( CvSeqWriter * writer )
981 CV_FUNCNAME( "cvFlushSeqWriter" );
986 CV_ERROR( CV_StsNullPtr, "" );
989 seq->ptr = writer->ptr;
994 CvSeqBlock *first_block = writer->seq->first;
995 CvSeqBlock *block = first_block;
997 writer->block->count = (int)((writer->ptr - writer->block->data) / seq->elem_size);
998 assert( writer->block->count > 0 );
1002 total += block->count;
1003 block = block->next;
1005 while( block != first_block );
1007 writer->seq->total = total;
1014 /* calls icvFlushSeqWriter and finishes writing process */
1016 cvEndWriteSeq( CvSeqWriter * writer )
1020 CV_FUNCNAME( "cvEndWriteSeq" );
1025 CV_ERROR( CV_StsNullPtr, "" );
1027 CV_CALL( cvFlushSeqWriter( writer ));
1030 /* truncate the last block */
1031 if( writer->block && writer->seq->storage )
1033 CvMemStorage *storage = seq->storage;
1034 char *storage_block_max = (char *) storage->top + storage->block_size;
1036 assert( writer->block->count > 0 );
1038 if( (unsigned)((storage_block_max - storage->free_space)
1039 - seq->block_max) < CV_STRUCT_ALIGN )
1041 storage->free_space = cvAlignLeft((int)(storage_block_max - seq->ptr), CV_STRUCT_ALIGN);
1042 seq->block_max = seq->ptr;
1054 /* creates new sequence block */
1056 cvCreateSeqBlock( CvSeqWriter * writer )
1058 CV_FUNCNAME( "cvCreateSeqBlock" );
1064 if( !writer || !writer->seq )
1065 CV_ERROR( CV_StsNullPtr, "" );
1069 cvFlushSeqWriter( writer );
1071 CV_CALL( icvGrowSeq( seq, 0 ));
1073 writer->block = seq->first->prev;
1074 writer->ptr = seq->ptr;
1075 writer->block_max = seq->block_max;
1081 /****************************************************************************************\
1082 * Sequence Reader implementation *
1083 \****************************************************************************************/
1085 /* initializes sequence reader */
1087 cvStartReadSeq( const CvSeq *seq, CvSeqReader * reader, int reverse )
1089 CvSeqBlock *first_block;
1090 CvSeqBlock *last_block;
1092 CV_FUNCNAME( "cvStartReadSeq" );
1098 reader->ptr = reader->block_max = reader->block_min = 0;
1103 if( !seq || !reader )
1104 CV_ERROR( CV_StsNullPtr, "" );
1106 reader->header_size = sizeof( CvSeqReader );
1107 reader->seq = (CvSeq*)seq;
1109 first_block = seq->first;
1113 last_block = first_block->prev;
1114 reader->ptr = first_block->data;
1115 reader->prev_elem = CV_GET_LAST_ELEM( seq, last_block );
1116 reader->delta_index = seq->first->start_index;
1120 char *temp = reader->ptr;
1122 reader->ptr = reader->prev_elem;
1123 reader->prev_elem = temp;
1125 reader->block = last_block;
1129 reader->block = first_block;
1132 reader->block_min = reader->block->data;
1133 reader->block_max = reader->block_min + reader->block->count * seq->elem_size;
1137 reader->delta_index = 0;
1140 reader->ptr = reader->prev_elem = reader->block_min = reader->block_max = 0;
1147 /* changes the current reading block to the previous or to the next */
1149 cvChangeSeqBlock( void* _reader, int direction )
1151 CV_FUNCNAME( "cvChangeSeqBlock" );
1155 CvSeqReader* reader = (CvSeqReader*)_reader;
1158 CV_ERROR( CV_StsNullPtr, "" );
1162 reader->block = reader->block->next;
1163 reader->ptr = reader->block->data;
1167 reader->block = reader->block->prev;
1168 reader->ptr = CV_GET_LAST_ELEM( reader->seq, reader->block );
1170 reader->block_min = reader->block->data;
1171 reader->block_max = reader->block_min + reader->block->count * reader->seq->elem_size;
1177 /* returns the current reader position */
1179 cvGetSeqReaderPos( CvSeqReader* reader )
1184 CV_FUNCNAME( "cvGetSeqReaderPos" );
1188 if( !reader || !reader->ptr )
1189 CV_ERROR( CV_StsNullPtr, "" );
1191 elem_size = reader->seq->elem_size;
1192 if( elem_size <= ICV_SHIFT_TAB_MAX && (index = icvPower2ShiftTab[elem_size - 1]) >= 0 )
1193 index = (int)((reader->ptr - reader->block_min) >> index);
1195 index = (int)((reader->ptr - reader->block_min) / elem_size);
1197 index += reader->block->start_index - reader->delta_index;
1205 /* sets reader position to given absolute or relative
1206 (relatively to the current one) position */
1208 cvSetSeqReaderPos( CvSeqReader* reader, int index, int is_relative )
1210 CV_FUNCNAME( "cvSetSeqReaderPos" );
1215 int elem_size, count, total;
1217 if( !reader || !reader->seq )
1218 CV_ERROR( CV_StsNullPtr, "" );
1220 total = reader->seq->total;
1221 elem_size = reader->seq->elem_size;
1227 if( index < -total )
1228 CV_ERROR( CV_StsOutOfRange, "" );
1231 else if( index >= total )
1234 if( index >= total )
1235 CV_ERROR( CV_StsOutOfRange, "" );
1238 block = reader->seq->first;
1239 if( index >= (count = block->count) )
1241 if( index + index <= total )
1245 block = block->next;
1248 while( index >= (count = block->count) );
1254 block = block->prev;
1255 total -= block->count;
1257 while( index < total );
1261 reader->ptr = block->data + index * elem_size;
1262 if( reader->block != block )
1264 reader->block = block;
1265 reader->block_min = block->data;
1266 reader->block_max = block->data + block->count * elem_size;
1271 char* ptr = reader->ptr;
1273 block = reader->block;
1277 while( ptr + index >= reader->block_max )
1279 int delta = (int)(reader->block_max - ptr);
1281 reader->block = block = block->next;
1282 reader->block_min = ptr = block->data;
1283 reader->block_max = block->data + block->count*elem_size;
1285 reader->ptr = ptr + index;
1289 while( ptr + index < reader->block_min )
1291 int delta = (int)(ptr - reader->block_min);
1293 reader->block = block = block->prev;
1294 reader->block_min = block->data;
1295 reader->block_max = ptr = block->data + block->count*elem_size;
1297 reader->ptr = ptr + index;
1305 /* pushes element to the sequence */
1307 cvSeqPush( CvSeq *seq, void *element )
1312 CV_FUNCNAME( "cvSeqPush" );
1317 CV_ERROR( CV_StsNullPtr, "" );
1319 elem_size = seq->elem_size;
1322 if( ptr >= seq->block_max )
1324 CV_CALL( icvGrowSeq( seq, 0 ));
1327 assert( ptr + elem_size <= seq->block_max /*&& ptr == seq->block_min */ );
1331 CV_MEMCPY_AUTO( ptr, element, elem_size );
1332 seq->first->prev->count++;
1334 seq->ptr = ptr + elem_size;
1342 /* pops the last element out of the sequence */
1344 cvSeqPop( CvSeq *seq, void *element )
1349 CV_FUNCNAME( "cvSeqPop" );
1354 CV_ERROR( CV_StsNullPtr, "" );
1355 if( seq->total <= 0 )
1356 CV_ERROR( CV_StsBadSize, "" );
1358 elem_size = seq->elem_size;
1359 seq->ptr = ptr = seq->ptr - elem_size;
1362 CV_MEMCPY_AUTO( element, ptr, elem_size );
1366 if( --(seq->first->prev->count) == 0 )
1368 icvFreeSeqBlock( seq, 0 );
1369 assert( seq->ptr == seq->block_max );
1376 /* pushes element to the front of the sequence */
1378 cvSeqPushFront( CvSeq *seq, void *element )
1384 CV_FUNCNAME( "cvSeqPushFront" );
1389 CV_ERROR( CV_StsNullPtr, "" );
1391 elem_size = seq->elem_size;
1394 if( !block || block->start_index == 0 )
1396 CV_CALL( icvGrowSeq( seq, 1 ));
1399 assert( block->start_index > 0 );
1402 ptr = block->data -= elem_size;
1405 CV_MEMCPY_AUTO( ptr, element, elem_size );
1407 block->start_index--;
1416 /* pulls out the first element of the sequence */
1418 cvSeqPopFront( CvSeq *seq, void *element )
1423 CV_FUNCNAME( "cvSeqPopFront" );
1428 CV_ERROR( CV_StsNullPtr, "" );
1429 if( seq->total <= 0 )
1430 CV_ERROR( CV_StsBadSize, "" );
1432 elem_size = seq->elem_size;
1436 CV_MEMCPY_AUTO( element, block->data, elem_size );
1437 block->data += elem_size;
1438 block->start_index++;
1441 if( --(block->count) == 0 )
1443 icvFreeSeqBlock( seq, 1 );
1449 /* inserts new element in the middle of the sequence */
1451 cvSeqInsert( CvSeq *seq, int before_index, void *element )
1460 CV_FUNCNAME( "cvSeqInsert" );
1465 CV_ERROR( CV_StsNullPtr, "" );
1468 before_index += before_index < 0 ? total : 0;
1469 before_index -= before_index > total ? total : 0;
1471 if( (unsigned)before_index > (unsigned)total )
1472 CV_ERROR( CV_StsOutOfRange, "" );
1474 if( before_index == total )
1476 CV_CALL( ret_ptr = cvSeqPush( seq, element ));
1478 else if( before_index == 0 )
1480 CV_CALL( ret_ptr = cvSeqPushFront( seq, element ));
1484 elem_size = seq->elem_size;
1486 if( before_index >= total >> 1 )
1488 char *ptr = seq->ptr + elem_size;
1490 if( ptr > seq->block_max )
1492 CV_CALL( icvGrowSeq( seq, 0 ));
1494 ptr = seq->ptr + elem_size;
1495 assert( ptr <= seq->block_max );
1498 delta_index = seq->first->start_index;
1499 block = seq->first->prev;
1501 block_size = (int)(ptr - block->data);
1503 while( before_index < block->start_index - delta_index )
1505 CvSeqBlock *prev_block = block->prev;
1507 memmove( block->data + elem_size, block->data, block_size - elem_size );
1508 block_size = prev_block->count * elem_size;
1509 memcpy( block->data, prev_block->data + block_size - elem_size, elem_size );
1512 /* check that we don't fall in the infinite loop */
1513 assert( block != seq->first->prev );
1516 before_index = (before_index - block->start_index + delta_index) * elem_size;
1517 memmove( block->data + before_index + elem_size, block->data + before_index,
1518 block_size - before_index - elem_size );
1520 ret_ptr = block->data + before_index;
1523 memcpy( ret_ptr, element, elem_size );
1530 if( block->start_index == 0 )
1532 CV_CALL( icvGrowSeq( seq, 1 ));
1537 delta_index = block->start_index;
1539 block->start_index--;
1540 block->data -= elem_size;
1542 while( before_index > block->start_index - delta_index + block->count )
1544 CvSeqBlock *next_block = block->next;
1546 block_size = block->count * elem_size;
1547 memmove( block->data, block->data + elem_size, block_size - elem_size );
1548 memcpy( block->data + block_size - elem_size, next_block->data, elem_size );
1550 /* check that we don't fall in the infinite loop */
1551 assert( block != seq->first );
1554 before_index = (before_index - block->start_index + delta_index) * elem_size;
1555 memmove( block->data, block->data + elem_size, before_index - elem_size );
1557 ret_ptr = block->data + before_index - elem_size;
1560 memcpy( ret_ptr, element, elem_size );
1563 seq->total = total + 1;
1572 /* removes element from the sequence */
1574 cvSeqRemove( CvSeq *seq, int index )
1581 int total, front = 0;
1583 CV_FUNCNAME( "cvSeqRemove" );
1588 CV_ERROR( CV_StsNullPtr, "" );
1592 index += index < 0 ? total : 0;
1593 index -= index >= total ? total : 0;
1595 if( (unsigned) index >= (unsigned) total )
1596 CV_ERROR( CV_StsOutOfRange, "Invalid index" );
1598 if( index == total - 1 )
1602 else if( index == 0 )
1604 cvSeqPopFront( seq, 0 );
1609 elem_size = seq->elem_size;
1610 delta_index = block->start_index;
1611 while( block->start_index - delta_index + block->count <= index )
1612 block = block->next;
1614 ptr = block->data + (index - block->start_index + delta_index) * elem_size;
1616 front = index < total >> 1;
1619 block_size = block->count * elem_size - (int)(ptr - block->data);
1621 while( block != seq->first->prev ) /* while not the last block */
1623 CvSeqBlock *next_block = block->next;
1625 memmove( ptr, ptr + elem_size, block_size - elem_size );
1626 memcpy( ptr + block_size - elem_size, next_block->data, elem_size );
1629 block_size = block->count * elem_size;
1632 memmove( ptr, ptr + elem_size, block_size - elem_size );
1633 seq->ptr -= elem_size;
1638 block_size = (int)(ptr - block->data);
1640 while( block != seq->first )
1642 CvSeqBlock *prev_block = block->prev;
1644 memmove( block->data + elem_size, block->data, block_size - elem_size );
1645 block_size = prev_block->count * elem_size;
1646 memcpy( block->data, prev_block->data + block_size - elem_size, elem_size );
1650 memmove( block->data + elem_size, block->data, block_size - elem_size );
1651 block->data += elem_size;
1652 block->start_index++;
1655 seq->total = total - 1;
1656 if( --block->count == 0 )
1657 icvFreeSeqBlock( seq, front );
1664 /* adds several elements to the end or in the beginning of sequence */
1666 cvSeqPushMulti( CvSeq *seq, void *_elements, int count, int front )
1668 char *elements = (char *) _elements;
1670 CV_FUNCNAME( "cvSeqPushMulti" );
1676 CV_ERROR( CV_StsNullPtr, "NULL sequence pointer" );
1678 CV_ERROR( CV_StsBadSize, "number of removed elements is negative" );
1680 elem_size = seq->elem_size;
1686 int delta = (int)((seq->block_max - seq->ptr) / elem_size);
1688 delta = MIN( delta, count );
1691 seq->first->prev->count += delta;
1692 seq->total += delta;
1697 memcpy( seq->ptr, elements, delta );
1704 CV_CALL( icvGrowSeq( seq, 0 ));
1709 CvSeqBlock* block = seq->first;
1715 if( !block || block->start_index == 0 )
1717 CV_CALL( icvGrowSeq( seq, 1 ));
1720 assert( block->start_index > 0 );
1723 delta = MIN( block->start_index, count );
1725 block->start_index -= delta;
1726 block->count += delta;
1727 seq->total += delta;
1729 block->data -= delta;
1732 memcpy( block->data, elements + count*elem_size, delta );
1740 /* removes several elements from the end of sequence */
1742 cvSeqPopMulti( CvSeq *seq, void *_elements, int count, int front )
1744 char *elements = (char *) _elements;
1746 CV_FUNCNAME( "cvSeqPopMulti" );
1751 CV_ERROR( CV_StsNullPtr, "NULL sequence pointer" );
1753 CV_ERROR( CV_StsBadSize, "number of removed elements is negative" );
1755 count = MIN( count, seq->total );
1760 elements += count * seq->elem_size;
1764 int delta = seq->first->prev->count;
1766 delta = MIN( delta, count );
1767 assert( delta > 0 );
1769 seq->first->prev->count -= delta;
1770 seq->total -= delta;
1772 delta *= seq->elem_size;
1778 memcpy( elements, seq->ptr, delta );
1781 if( seq->first->prev->count == 0 )
1782 icvFreeSeqBlock( seq, 0 );
1789 int delta = seq->first->count;
1791 delta = MIN( delta, count );
1792 assert( delta > 0 );
1794 seq->first->count -= delta;
1795 seq->total -= delta;
1797 seq->first->start_index += delta;
1798 delta *= seq->elem_size;
1802 memcpy( elements, seq->first->data, delta );
1806 seq->first->data += delta;
1807 if( seq->first->count == 0 )
1808 icvFreeSeqBlock( seq, 1 );
1816 /* removes all elements from the sequence */
1818 cvClearSeq( CvSeq *seq )
1820 CV_FUNCNAME( "cvClearSeq" );
1825 CV_ERROR( CV_StsNullPtr, "" );
1826 cvSeqPopMulti( seq, 0, seq->total );
1833 cvSeqSlice( const CvSeq* seq, CvSlice slice, CvMemStorage* storage, int copy_data )
1837 CV_FUNCNAME("cvSeqSlice");
1841 int elem_size, count, length;
1843 CvSeqBlock *block, *first_block = 0, *last_block = 0;
1845 if( !CV_IS_SEQ(seq) )
1846 CV_ERROR( CV_StsBadArg, "Invalid sequence header" );
1850 storage = seq->storage;
1852 CV_ERROR( CV_StsNullPtr, "NULL storage pointer" );
1855 elem_size = seq->elem_size;
1856 length = cvSliceLength( slice, seq );
1857 if( slice.start_index < 0 )
1858 slice.start_index += seq->total;
1859 else if( slice.start_index >= seq->total )
1860 slice.start_index -= seq->total;
1861 if( (unsigned)length > (unsigned)seq->total ||
1862 ((unsigned)slice.start_index >= (unsigned)seq->total && length != 0) )
1863 CV_ERROR( CV_StsOutOfRange, "Bad sequence slice" );
1865 CV_CALL( subseq = cvCreateSeq( seq->flags, seq->header_size, elem_size, storage ));
1869 cvStartReadSeq( seq, &reader, 0 );
1870 cvSetSeqReaderPos( &reader, slice.start_index, 0 );
1871 count = (int)((reader.block_max - reader.ptr)/elem_size);
1875 int bl = MIN( count, length );
1879 block = (CvSeqBlock*)cvMemStorageAlloc( storage, sizeof(*block) );
1882 first_block = subseq->first = block->prev = block->next = block;
1883 block->start_index = 0;
1887 block->prev = last_block;
1888 block->next = first_block;
1889 last_block->next = first_block->prev = block;
1890 block->start_index = last_block->start_index + last_block->count;
1893 block->data = reader.ptr;
1895 subseq->total += bl;
1898 cvSeqPushMulti( subseq, reader.ptr, bl, 0 );
1900 reader.block = reader.block->next;
1901 reader.ptr = reader.block->data;
1902 count = reader.block->count;
1904 while( length > 0 );
1913 // Remove slice from the middle of the sequence
1914 // !!! TODO !!! Implement more efficient algorithm
1916 cvSeqRemoveSlice( CvSeq* seq, CvSlice slice )
1918 CV_FUNCNAME("cvSeqRemoveSlice");
1924 if( !CV_IS_SEQ(seq) )
1925 CV_ERROR( CV_StsBadArg, "Invalid sequence header" );
1927 length = cvSliceLength( slice, seq );
1930 if( slice.start_index < 0 )
1931 slice.start_index += total;
1932 else if( slice.start_index >= total )
1933 slice.start_index -= total;
1935 if( (unsigned)slice.start_index >= (unsigned)total )
1936 CV_ERROR( CV_StsOutOfRange, "start slice index is out of range" );
1938 slice.end_index = slice.start_index + length;
1940 if( slice.end_index < total )
1942 CvSeqReader reader_to, reader_from;
1943 int elem_size = seq->elem_size;
1945 cvStartReadSeq( seq, &reader_to );
1946 cvStartReadSeq( seq, &reader_from );
1948 if( slice.start_index > total - slice.end_index )
1950 int i, count = seq->total - slice.end_index;
1951 cvSetSeqReaderPos( &reader_to, slice.start_index );
1952 cvSetSeqReaderPos( &reader_from, slice.end_index );
1954 for( i = 0; i < count; i++ )
1956 CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size );
1957 CV_NEXT_SEQ_ELEM( elem_size, reader_to );
1958 CV_NEXT_SEQ_ELEM( elem_size, reader_from );
1961 cvSeqPopMulti( seq, 0, slice.end_index - slice.start_index );
1965 int i, count = slice.start_index;
1966 cvSetSeqReaderPos( &reader_to, slice.end_index );
1967 cvSetSeqReaderPos( &reader_from, slice.start_index );
1969 for( i = 0; i < count; i++ )
1971 CV_PREV_SEQ_ELEM( elem_size, reader_to );
1972 CV_PREV_SEQ_ELEM( elem_size, reader_from );
1974 CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size );
1977 cvSeqPopMulti( seq, 0, slice.end_index - slice.start_index, 1 );
1982 cvSeqPopMulti( seq, 0, total - slice.start_index );
1983 cvSeqPopMulti( seq, 0, slice.end_index - total, 1 );
1990 // Inserts a new sequence into the middle of another sequence
1991 // !!! TODO !!! Implement more efficient algorithm
1993 cvSeqInsertSlice( CvSeq* seq, int index, const CvArr* from_arr )
1995 CvSeqReader reader_to, reader_from;
1996 int i, elem_size, total, from_total;
1998 CV_FUNCNAME("cvSeqInsertSlice");
2002 CvSeq from_header, *from = (CvSeq*)from_arr;
2005 if( !CV_IS_SEQ(seq) )
2006 CV_ERROR( CV_StsBadArg, "Invalid destination sequence header" );
2008 if( !CV_IS_SEQ(from))
2010 CvMat* mat = (CvMat*)from;
2011 if( !CV_IS_MAT(mat))
2012 CV_ERROR( CV_StsBadArg, "Source is not a sequence nor matrix" );
2014 if( !CV_IS_MAT_CONT(mat->type) || (mat->rows != 1 && mat->cols != 1) )
2015 CV_ERROR( CV_StsBadArg, "The source array must be 1d coninuous vector" );
2017 CV_CALL( from = cvMakeSeqHeaderForArray( CV_SEQ_KIND_GENERIC, sizeof(from_header),
2018 CV_ELEM_SIZE(mat->type),
2019 mat->data.ptr, mat->cols + mat->rows - 1,
2020 &from_header, &block ));
2023 if( seq->elem_size != from->elem_size )
2024 CV_ERROR( CV_StsUnmatchedSizes,
2025 "Sizes of source and destination sequences' elements are different" );
2027 from_total = from->total;
2029 if( from_total == 0 )
2033 index += index < 0 ? total : 0;
2034 index -= index > total ? total : 0;
2036 if( (unsigned)index > (unsigned)total )
2037 CV_ERROR( CV_StsOutOfRange, "" );
2039 elem_size = seq->elem_size;
2041 if( index < (total >> 1) )
2043 cvSeqPushMulti( seq, 0, from_total, 1 );
2045 cvStartReadSeq( seq, &reader_to );
2046 cvStartReadSeq( seq, &reader_from );
2047 cvSetSeqReaderPos( &reader_from, from_total );
2049 for( i = 0; i < index; i++ )
2051 CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size );
2052 CV_NEXT_SEQ_ELEM( elem_size, reader_to );
2053 CV_NEXT_SEQ_ELEM( elem_size, reader_from );
2058 cvSeqPushMulti( seq, 0, from_total );
2060 cvStartReadSeq( seq, &reader_to );
2061 cvStartReadSeq( seq, &reader_from );
2062 cvSetSeqReaderPos( &reader_from, total );
2063 cvSetSeqReaderPos( &reader_to, seq->total );
2065 for( i = 0; i < total - index; i++ )
2067 CV_PREV_SEQ_ELEM( elem_size, reader_to );
2068 CV_PREV_SEQ_ELEM( elem_size, reader_from );
2069 CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size );
2073 cvStartReadSeq( from, &reader_from );
2074 cvSetSeqReaderPos( &reader_to, index );
2076 for( i = 0; i < from_total; i++ )
2078 CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size );
2079 CV_NEXT_SEQ_ELEM( elem_size, reader_to );
2080 CV_NEXT_SEQ_ELEM( elem_size, reader_from );
2086 // Sort the sequence using user-specified comparison function.
2087 // The semantics is similar to qsort() function. The code is based
2088 // on BSD system qsort():
2089 // * Copyright (c) 1992, 1993
2090 // * The Regents of the University of California. All rights reserved.
2092 // * Redistribution and use in source and binary forms, with or without
2093 // * modification, are permitted provided that the following conditions
2095 // * 1. Redistributions of source code must retain the above copyright
2096 // * notice, this list of conditions and the following disclaimer.
2097 // * 2. Redistributions in binary form must reproduce the above copyright
2098 // * notice, this list of conditions and the following disclaimer in the
2099 // * documentation and/or other materials provided with the distribution.
2100 // * 3. All advertising materials mentioning features or use of this software
2101 // * must display the following acknowledgement:
2102 // * This product includes software developed by the University of
2103 // * California, Berkeley and its contributors.
2104 // * 4. Neither the name of the University nor the names of its contributors
2105 // * may be used to endorse or promote products derived from this software
2106 // * without specific prior written permission.
2108 // * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2109 // * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2110 // * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2111 // * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2112 // * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2113 // * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2114 // * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2115 // * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2116 // * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2117 // * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2120 typedef struct CvSeqReaderPos
2129 #define CV_SAVE_READER_POS( reader, pos ) \
2131 (pos).block = (reader).block; \
2132 (pos).ptr = (reader).ptr; \
2133 (pos).block_min = (reader).block_min; \
2134 (pos).block_max = (reader).block_max; \
2137 #define CV_RESTORE_READER_POS( reader, pos )\
2139 (reader).block = (pos).block; \
2140 (reader).ptr = (pos).ptr; \
2141 (reader).block_min = (pos).block_min; \
2142 (reader).block_max = (pos).block_max; \
2146 icvMed3( char* a, char* b, char* c, CvCmpFunc cmp_func, void* aux )
2148 return cmp_func(a, b, aux) < 0 ?
2149 (cmp_func(b, c, aux) < 0 ? b : cmp_func(a, c, aux) < 0 ? c : a)
2150 :(cmp_func(b, c, aux) > 0 ? b : cmp_func(a, c, aux) < 0 ? a : c);
2154 cvSeqSort( CvSeq* seq, CvCmpFunc cmp_func, void* aux )
2157 int isort_thresh = 7;
2158 CvSeqReader left, right;
2168 CV_FUNCNAME( "cvSeqSort" );
2172 if( !CV_IS_SEQ(seq) )
2173 CV_ERROR( !seq ? CV_StsNullPtr : CV_StsBadArg, "Bad input sequence" );
2176 CV_ERROR( CV_StsNullPtr, "Null compare function" );
2178 if( seq->total <= 1 )
2181 elem_size = seq->elem_size;
2182 isort_thresh *= elem_size;
2184 cvStartReadSeq( seq, &left, 0 );
2186 CV_SAVE_READER_POS( left, stack[0].lb );
2187 CV_PREV_SEQ_ELEM( elem_size, right );
2188 CV_SAVE_READER_POS( right, stack[0].ub );
2192 CV_RESTORE_READER_POS( left, stack[sp].lb );
2193 CV_RESTORE_READER_POS( right, stack[sp].ub );
2199 CvSeqReader ptr, ptr2;
2201 if( left.block == right.block )
2202 n = (int)(right.ptr - left.ptr) + elem_size;
2205 n = cvGetSeqReaderPos( &right );
2206 n = (n - cvGetSeqReaderPos( &left ) + 1)*elem_size;
2209 if( n <= isort_thresh )
2213 CV_NEXT_SEQ_ELEM( elem_size, ptr );
2214 CV_NEXT_SEQ_ELEM( elem_size, right );
2215 while( ptr.ptr != right.ptr )
2218 if( ptr2.block != ptr.block )
2220 ptr2.block = ptr.block;
2221 ptr2.block_min = ptr.block_min;
2222 ptr2.block_max = ptr.block_max;
2224 while( ptr2.ptr != left.ptr )
2226 char* cur = ptr2.ptr;
2227 CV_PREV_SEQ_ELEM( elem_size, ptr2 );
2228 if( cmp_func( ptr2.ptr, cur, aux ) <= 0 )
2230 CV_SWAP_ELEMS( ptr2.ptr, cur, elem_size );
2232 CV_NEXT_SEQ_ELEM( elem_size, ptr );
2238 CvSeqReader left0, left1, right0, right1;
2239 CvSeqReader tmp0, tmp1;
2240 char *m1, *m2, *m3, *pivot;
2242 int l, l0, l1, r, r0, r1;
2244 left0 = tmp0 = left;
2245 right0 = right1 = right;
2253 cvSetSeqReaderPos( &tmp0, d, 1 );
2255 cvSetSeqReaderPos( &tmp0, d, 1 );
2257 m1 = icvMed3( p1, p2, p3, cmp_func, aux );
2258 cvSetSeqReaderPos( &tmp0, (n/2) - d*3, 1 );
2260 cvSetSeqReaderPos( &tmp0, d, 1 );
2262 cvSetSeqReaderPos( &tmp0, d, 1 );
2264 m2 = icvMed3( p1, p2, p3, cmp_func, aux );
2265 cvSetSeqReaderPos( &tmp0, n - 1 - d*3 - n/2, 1 );
2267 cvSetSeqReaderPos( &tmp0, d, 1 );
2269 cvSetSeqReaderPos( &tmp0, d, 1 );
2271 m3 = icvMed3( p1, p2, p3, cmp_func, aux );
2276 cvSetSeqReaderPos( &tmp0, n/2, 1 );
2278 cvSetSeqReaderPos( &tmp0, n - 1 - n/2, 1 );
2282 pivot = icvMed3( m1, m2, m3, cmp_func, aux );
2284 if( pivot != left.ptr )
2286 CV_SWAP_ELEMS( pivot, left.ptr, elem_size );
2289 CV_NEXT_SEQ_ELEM( elem_size, left );
2294 while( left.ptr != right.ptr && (r = cmp_func(left.ptr, pivot, aux)) <= 0 )
2298 if( left1.ptr != left.ptr )
2299 CV_SWAP_ELEMS( left1.ptr, left.ptr, elem_size );
2301 CV_NEXT_SEQ_ELEM( elem_size, left1 );
2303 CV_NEXT_SEQ_ELEM( elem_size, left );
2306 while( left.ptr != right.ptr && (r = cmp_func(right.ptr,pivot, aux)) >= 0 )
2310 if( right1.ptr != right.ptr )
2311 CV_SWAP_ELEMS( right1.ptr, right.ptr, elem_size );
2313 CV_PREV_SEQ_ELEM( elem_size, right1 );
2315 CV_PREV_SEQ_ELEM( elem_size, right );
2318 if( left.ptr == right.ptr )
2320 r = cmp_func(left.ptr, pivot, aux);
2323 if( left1.ptr != left.ptr )
2324 CV_SWAP_ELEMS( left1.ptr, left.ptr, elem_size );
2326 CV_NEXT_SEQ_ELEM( elem_size, left1 );
2330 CV_NEXT_SEQ_ELEM( elem_size, left );
2334 CV_PREV_SEQ_ELEM( elem_size, right );
2339 CV_SWAP_ELEMS( left.ptr, right.ptr, elem_size );
2340 CV_NEXT_SEQ_ELEM( elem_size, left );
2341 r = left.ptr == right.ptr;
2342 CV_PREV_SEQ_ELEM( elem_size, right );
2350 left = left0, right = right0;
2354 l = cvGetSeqReaderPos( &left );
2357 l0 = cvGetSeqReaderPos( &left0 );
2358 l1 = cvGetSeqReaderPos( &left1 );
2362 n = MIN( l - l1, l1 - l0 );
2367 cvSetSeqReaderPos( &tmp1, 0-n, 1 );
2368 for( i = 0; i < n; i++ )
2370 CV_SWAP_ELEMS( tmp0.ptr, tmp1.ptr, elem_size );
2371 CV_NEXT_SEQ_ELEM( elem_size, tmp0 );
2372 CV_NEXT_SEQ_ELEM( elem_size, tmp1 );
2376 r = cvGetSeqReaderPos( &right );
2377 r0 = cvGetSeqReaderPos( &right0 );
2378 r1 = cvGetSeqReaderPos( &right1 );
2379 m = MIN( r0 - r1, r1 - r );
2384 cvSetSeqReaderPos( &tmp1, 1-m, 1 );
2385 for( i = 0; i < m; i++ )
2387 CV_SWAP_ELEMS( tmp0.ptr, tmp1.ptr, elem_size );
2388 CV_NEXT_SEQ_ELEM( elem_size, tmp0 );
2389 CV_NEXT_SEQ_ELEM( elem_size, tmp1 );
2402 CV_SAVE_READER_POS( left0, stack[sp].lb );
2403 cvSetSeqReaderPos( &left0, n - 1, 1 );
2404 CV_SAVE_READER_POS( left0, stack[sp].ub );
2405 left = right = right0;
2406 cvSetSeqReaderPos( &left, 1 - m, 1 );
2411 CV_SAVE_READER_POS( right0, stack[sp].ub );
2412 cvSetSeqReaderPos( &right0, 1 - m, 1 );
2413 CV_SAVE_READER_POS( right0, stack[sp].lb );
2414 left = right = left0;
2415 cvSetSeqReaderPos( &right, n - 1, 1 );
2420 left = right = left0;
2421 cvSetSeqReaderPos( &right, n - 1, 1 );
2426 left = right = right0;
2427 cvSetSeqReaderPos( &left, 1 - m, 1 );
2440 cvSeqSearch( CvSeq* seq, const void* _elem, CvCmpFunc cmp_func,
2441 int is_sorted, int* _idx, void* userdata )
2444 const char* elem = (const char*)_elem;
2447 CV_FUNCNAME("cvSeqSort");
2451 int elem_size, i, j, total;
2453 if( !CV_IS_SEQ(seq) )
2454 CV_ERROR( !seq ? CV_StsNullPtr : CV_StsBadArg, "Bad input sequence" );
2457 CV_ERROR( CV_StsNullPtr, "Null element pointer" );
2459 elem_size = seq->elem_size;
2468 cvStartReadSeq( seq, &reader, 0 );
2472 for( i = 0; i < total; i++ )
2474 if( cmp_func( elem, reader.ptr, userdata ) == 0 )
2476 CV_NEXT_SEQ_ELEM( elem_size, reader );
2479 else if( (elem_size & (sizeof(int)-1)) == 0 )
2481 for( i = 0; i < total; i++ )
2483 for( j = 0; j < elem_size; j += sizeof(int) )
2485 if( *(const int*)(reader.ptr + j) != *(const int*)(elem + j) )
2488 if( j == elem_size )
2490 CV_NEXT_SEQ_ELEM( elem_size, reader );
2495 for( i = 0; i < total; i++ )
2497 for( j = 0; j < elem_size; j++ )
2499 if( reader.ptr[j] != elem[j] )
2502 if( j == elem_size )
2504 CV_NEXT_SEQ_ELEM( elem_size, reader );
2510 result = reader.ptr;
2515 CV_ERROR( CV_StsNullPtr, "Null compare function" );
2521 int k = (i+j)>>1, code;
2522 char* ptr = cvGetSeqElem( seq, k );
2523 code = cmp_func( elem, ptr, userdata );
2548 cvSeqInvert( CvSeq* seq )
2550 CV_FUNCNAME( "cvSeqInvert" );
2554 CvSeqReader left_reader, right_reader;
2558 CV_CALL( cvStartReadSeq( seq, &left_reader, 0 ));
2559 CV_CALL( cvStartReadSeq( seq, &right_reader, 1 ));
2560 elem_size = seq->elem_size;
2561 count = seq->total >> 1;
2563 for( i = 0; i < count; i++ )
2565 CV_SWAP_ELEMS( left_reader.ptr, right_reader.ptr, elem_size );
2566 CV_NEXT_SEQ_ELEM( elem_size, left_reader );
2567 CV_PREV_SEQ_ELEM( elem_size, right_reader );
2574 typedef struct CvPTreeNode
2576 struct CvPTreeNode* parent;
2583 // the function splits the input sequence or set into one or more equivalence classes.
2584 // is_equal(a,b,...) returns non-zero if the two sequence elements
2585 // belong to the same class. the function returns sequence of integers -
2586 // 0-based class indexes for each element.
2588 // The algorithm is described in "Introduction to Algorithms"
2589 // by Cormen, Leiserson and Rivest, chapter "Data structures for disjoint sets"
2591 cvSeqPartition( const CvSeq* seq, CvMemStorage* storage, CvSeq** labels,
2592 CvCmpFunc is_equal, void* userdata )
2595 CvMemStorage* temp_storage = 0;
2598 CV_FUNCNAME( "cvSeqPartition" );
2603 CvSeqReader reader, reader0;
2609 CV_ERROR( CV_StsNullPtr, "" );
2611 if( !seq || !is_equal )
2612 CV_ERROR( CV_StsNullPtr, "" );
2615 storage = seq->storage;
2618 CV_ERROR( CV_StsNullPtr, "" );
2620 is_set = CV_IS_SET(seq);
2622 temp_storage = cvCreateChildMemStorage( storage );
2624 nodes = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPTreeNode), temp_storage );
2626 cvStartReadSeq( seq, &reader );
2627 memset( &writer, 0, sizeof(writer));
2628 cvStartAppendToSeq( nodes, &writer );
2630 // Initial O(N) pass. Make a forest of single-vertex trees.
2631 for( i = 0; i < seq->total; i++ )
2633 CvPTreeNode node = { 0, 0, 0 };
2634 if( !is_set || CV_IS_SET_ELEM( reader.ptr ))
2635 node.element = reader.ptr;
2636 CV_WRITE_SEQ_ELEM( node, writer );
2637 CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
2640 cvEndWriteSeq( &writer );
2642 // because in the next loop we will iterate
2643 // through all the sequence nodes each time,
2644 // we do not need to initialize reader every time
2645 cvStartReadSeq( nodes, &reader );
2646 cvStartReadSeq( nodes, &reader0 );
2648 // The main O(N^2) pass. Merge connected components.
2649 for( i = 0; i < nodes->total; i++ )
2651 CvPTreeNode* node = (CvPTreeNode*)(reader0.ptr);
2652 CvPTreeNode* root = node;
2653 CV_NEXT_SEQ_ELEM( nodes->elem_size, reader0 );
2655 if( !node->element )
2659 while( root->parent )
2660 root = root->parent;
2662 for( j = 0; j < nodes->total; j++ )
2664 CvPTreeNode* node2 = (CvPTreeNode*)reader.ptr;
2666 if( node2->element && node2 != node &&
2667 is_equal( node->element, node2->element, userdata ))
2669 CvPTreeNode* root2 = node2;
2672 while( root2->parent )
2673 root2 = root2->parent;
2677 if( root->rank > root2->rank )
2678 root2->parent = root;
2681 root->parent = root2;
2682 root2->rank += root->rank == root2->rank;
2685 assert( root->parent == 0 );
2687 // compress path from node2 to the root
2688 while( node2->parent )
2690 CvPTreeNode* temp = node2;
2691 node2 = node2->parent;
2692 temp->parent = root;
2695 // compress path from node to the root
2697 while( node2->parent )
2699 CvPTreeNode* temp = node2;
2700 node2 = node2->parent;
2701 temp->parent = root;
2706 CV_NEXT_SEQ_ELEM( sizeof(*node), reader );
2710 // Final O(N) pass (Enumerate classes)
2711 // Reuse reader one more time
2712 result = cvCreateSeq( 0, sizeof(CvSeq), sizeof(int), storage );
2713 cvStartAppendToSeq( result, &writer );
2715 for( i = 0; i < nodes->total; i++ )
2717 CvPTreeNode* node = (CvPTreeNode*)reader.ptr;
2722 while( node->parent )
2723 node = node->parent;
2724 if( node->rank >= 0 )
2725 node->rank = ~class_idx++;
2729 CV_NEXT_SEQ_ELEM( sizeof(*node), reader );
2730 CV_WRITE_SEQ_ELEM( idx, writer );
2733 cvEndWriteSeq( &writer );
2740 cvReleaseMemStorage( &temp_storage );
2745 /****************************************************************************************\
2746 * Set implementation *
2747 \****************************************************************************************/
2749 /* creates empty set */
2751 cvCreateSet( int set_flags, int header_size, int elem_size, CvMemStorage * storage )
2755 CV_FUNCNAME( "cvCreateSet" );
2760 CV_ERROR( CV_StsNullPtr, "" );
2761 if( header_size < (int)sizeof( CvSet ) ||
2762 elem_size < (int)sizeof(void*)*2 ||
2763 (elem_size & (sizeof(void*)-1)) != 0 )
2764 CV_ERROR( CV_StsBadSize, "" );
2766 set = (CvSet*) cvCreateSeq( set_flags, header_size, elem_size, storage );
2767 set->flags = (set->flags & ~CV_MAGIC_MASK) | CV_SET_MAGIC_VAL;
2775 /* adds new element to the set */
2777 cvSetAdd( CvSet* set, CvSetElem* element, CvSetElem** inserted_element )
2781 CV_FUNCNAME( "cvSetAdd" );
2785 CvSetElem *free_elem;
2788 CV_ERROR( CV_StsNullPtr, "" );
2790 if( !(set->free_elems) )
2792 int count = set->total;
2793 int elem_size = set->elem_size;
2795 CV_CALL( icvGrowSeq( (CvSeq *) set, 0 ));
2797 set->free_elems = (CvSetElem*) (ptr = set->ptr);
2798 for( ; ptr + elem_size <= set->block_max; ptr += elem_size, count++ )
2800 ((CvSetElem*)ptr)->flags = count | CV_SET_ELEM_FREE_FLAG;
2801 ((CvSetElem*)ptr)->next_free = (CvSetElem*)(ptr + elem_size);
2803 assert( count <= CV_SET_ELEM_IDX_MASK+1 );
2804 ((CvSetElem*)(ptr - elem_size))->next_free = 0;
2805 set->first->prev->count += count - set->total;
2807 set->ptr = set->block_max;
2810 free_elem = set->free_elems;
2811 set->free_elems = free_elem->next_free;
2813 id = free_elem->flags & CV_SET_ELEM_IDX_MASK;
2815 CV_MEMCPY_INT( free_elem, element, (size_t)set->elem_size/sizeof(int) );
2817 free_elem->flags = id;
2818 set->active_count++;
2820 if( inserted_element )
2821 *inserted_element = free_elem;
2829 /* removes element from the set given its index */
2831 cvSetRemove( CvSet* set, int index )
2833 CV_FUNCNAME( "cvSetRemove" );
2837 CvSetElem* elem = cvGetSetElem( set, index );
2839 cvSetRemoveByPtr( set, elem );
2841 CV_ERROR( CV_StsNullPtr, "" );
2847 /* removes all elements from the set */
2849 cvClearSet( CvSet* set )
2851 CV_FUNCNAME( "cvClearSet" );
2855 CV_CALL( cvClearSeq( (CvSeq*)set ));
2856 set->free_elems = 0;
2857 set->active_count = 0;
2863 /****************************************************************************************\
2864 * Graph implementation *
2865 \****************************************************************************************/
2867 /* creates new graph */
2869 cvCreateGraph( int graph_type, int header_size,
2870 int vtx_size, int edge_size, CvMemStorage * storage )
2875 CV_FUNCNAME( "cvCleateGraph" );
2879 CvSet *vertices = 0;
2881 if( header_size < (int)sizeof( CvGraph ) ||
2882 edge_size < (int)sizeof( CvGraphEdge ) ||
2883 vtx_size < (int)sizeof( CvGraphVtx ))
2884 CV_ERROR( CV_StsBadSize, "" );
2886 CV_CALL( vertices = cvCreateSet( graph_type, header_size, vtx_size, storage ));
2887 CV_CALL( edges = cvCreateSet( CV_SEQ_KIND_GENERIC | CV_SEQ_ELTYPE_GRAPH_EDGE,
2888 sizeof( CvSet ), edge_size, storage ));
2890 graph = (CvGraph*)vertices;
2891 graph->edges = edges;
2899 /* Removes all the vertices and edges from the graph */
2901 cvClearGraph( CvGraph * graph )
2903 CV_FUNCNAME( "cvClearGraph" );
2908 CV_ERROR( CV_StsNullPtr, "" );
2910 cvClearSet( graph->edges );
2911 cvClearSet( (CvSet*)graph );
2917 /* Adds vertex to the graph */
2919 cvGraphAddVtx( CvGraph* graph, const CvGraphVtx* _vertex, CvGraphVtx** _inserted_vertex )
2921 CvGraphVtx *vertex = 0;
2924 CV_FUNCNAME( "cvGraphAddVtx" );
2929 CV_ERROR( CV_StsNullPtr, "" );
2931 vertex = (CvGraphVtx*)cvSetNew((CvSet*)graph);
2935 CV_MEMCPY_INT( vertex + 1, _vertex + 1,
2936 (size_t)(graph->elem_size - sizeof(CvGraphVtx))/sizeof(int) );
2938 index = vertex->flags;
2941 if( _inserted_vertex )
2942 *_inserted_vertex = vertex;
2950 /* Removes vertex from the graph together with incident edges */
2952 cvGraphRemoveVtxByPtr( CvGraph* graph, CvGraphVtx* vtx )
2956 CV_FUNCNAME( "cvGraphRemoveVtxByPtr" );
2960 if( !graph || !vtx )
2961 CV_ERROR( CV_StsNullPtr, "" );
2963 if( !CV_IS_SET_ELEM(vtx))
2964 CV_ERROR( CV_StsBadArg, "The vertex does not belong to the graph" );
2966 count = graph->edges->active_count;
2969 CvGraphEdge *edge = vtx->first;
2972 cvGraphRemoveEdgeByPtr( graph, edge->vtx[0], edge->vtx[1] );
2974 count -= graph->edges->active_count;
2975 cvSetRemoveByPtr( (CvSet*)graph, vtx );
2983 /* Removes vertex from the graph together with incident edges */
2985 cvGraphRemoveVtx( CvGraph* graph, int index )
2988 CvGraphVtx *vtx = 0;
2990 CV_FUNCNAME( "cvGraphRemoveVtx" );
2995 CV_ERROR( CV_StsNullPtr, "" );
2997 vtx = cvGetGraphVtx( graph, index );
2999 CV_ERROR( CV_StsBadArg, "The vertex is not found" );
3001 count = graph->edges->active_count;
3004 CvGraphEdge *edge = vtx->first;
3009 cvGraphRemoveEdgeByPtr( graph, edge->vtx[0], edge->vtx[1] );
3011 count -= graph->edges->active_count;
3012 cvSetRemoveByPtr( (CvSet*)graph, vtx );
3020 /* Finds graph edge given pointers to the ending vertices */
3021 CV_IMPL CvGraphEdge*
3022 cvFindGraphEdgeByPtr( const CvGraph* graph,
3023 const CvGraphVtx* start_vtx,
3024 const CvGraphVtx* end_vtx )
3026 CvGraphEdge *edge = 0;
3027 CV_FUNCNAME( "cvFindGraphEdgeByPtr" );
3033 if( !graph || !start_vtx || !end_vtx )
3034 CV_ERROR( CV_StsNullPtr, "" );
3036 if( start_vtx == end_vtx )
3039 if( !CV_IS_GRAPH_ORIENTED( graph ) &&
3040 (start_vtx->flags & CV_SET_ELEM_IDX_MASK) > (end_vtx->flags & CV_SET_ELEM_IDX_MASK) )
3042 const CvGraphVtx* t;
3043 CV_SWAP( start_vtx, end_vtx, t );
3046 edge = start_vtx->first;
3047 for( ; edge; edge = edge->next[ofs] )
3049 ofs = start_vtx == edge->vtx[1];
3050 assert( ofs == 1 || start_vtx == edge->vtx[0] );
3051 if( edge->vtx[1] == end_vtx )
3061 /* Finds edge in the graph given indices of the ending vertices */
3062 CV_IMPL CvGraphEdge *
3063 cvFindGraphEdge( const CvGraph* graph, int start_idx, int end_idx )
3065 CvGraphEdge *edge = 0;
3066 CvGraphVtx *start_vtx;
3067 CvGraphVtx *end_vtx;
3069 CV_FUNCNAME( "cvFindGraphEdge" );
3074 CV_ERROR( CV_StsNullPtr, "graph pointer is NULL" );
3076 start_vtx = cvGetGraphVtx( graph, start_idx );
3077 end_vtx = cvGetGraphVtx( graph, end_idx );
3079 edge = cvFindGraphEdgeByPtr( graph, start_vtx, end_vtx );
3087 /* Connects the two given vertices if they were not connected before,
3088 otherwise it returns the existing edge */
3090 cvGraphAddEdgeByPtr( CvGraph* graph,
3091 CvGraphVtx* start_vtx, CvGraphVtx* end_vtx,
3092 const CvGraphEdge* _edge,
3093 CvGraphEdge ** _inserted_edge )
3095 CvGraphEdge *edge = 0;
3098 CV_FUNCNAME( "cvGraphAddEdgeByPtr" );
3105 CV_ERROR( CV_StsNullPtr, "graph pointer is NULL" );
3107 if( !CV_IS_GRAPH_ORIENTED( graph ) &&
3108 (start_vtx->flags & CV_SET_ELEM_IDX_MASK) > (end_vtx->flags & CV_SET_ELEM_IDX_MASK) )
3111 CV_SWAP( start_vtx, end_vtx, t );
3114 CV_CALL( edge = cvFindGraphEdgeByPtr( graph, start_vtx, end_vtx ));
3121 if( start_vtx == end_vtx )
3122 CV_ERROR( start_vtx ? CV_StsBadArg : CV_StsNullPtr,
3123 "vertex pointers coinside (or set to NULL)" );
3125 CV_CALL( edge = (CvGraphEdge*)cvSetNew( (CvSet*)(graph->edges) ));
3126 assert( edge->flags >= 0 );
3128 edge->vtx[0] = start_vtx;
3129 edge->vtx[1] = end_vtx;
3130 edge->next[0] = start_vtx->first;
3131 edge->next[1] = end_vtx->first;
3132 start_vtx->first = end_vtx->first = edge;
3134 delta = (graph->edges->elem_size - sizeof(*edge))/sizeof(int);
3138 CV_MEMCPY_INT( edge + 1, _edge + 1, delta );
3139 edge->weight = _edge->weight;
3144 CV_ZERO_INT( edge + 1, delta );
3152 if( _inserted_edge )
3153 *_inserted_edge = edge;
3158 /* Connects the two given vertices if they were not connected before,
3159 otherwise it returns the existing edge */
3161 cvGraphAddEdge( CvGraph* graph,
3162 int start_idx, int end_idx,
3163 const CvGraphEdge* _edge,
3164 CvGraphEdge ** _inserted_edge )
3166 CvGraphVtx *start_vtx;
3167 CvGraphVtx *end_vtx;
3170 CV_FUNCNAME( "cvGraphAddEdge" );
3175 CV_ERROR( CV_StsNullPtr, "" );
3177 start_vtx = cvGetGraphVtx( graph, start_idx );
3178 end_vtx = cvGetGraphVtx( graph, end_idx );
3180 result = cvGraphAddEdgeByPtr( graph, start_vtx, end_vtx, _edge, _inserted_edge );
3188 /* Removes the graph edge connecting two given vertices */
3190 cvGraphRemoveEdgeByPtr( CvGraph* graph, CvGraphVtx* start_vtx, CvGraphVtx* end_vtx )
3192 CV_FUNCNAME( "cvGraphRemoveEdgeByPtr" );
3197 CvGraphEdge *edge, *next_edge, *prev_edge;
3199 if( !graph || !start_vtx || !end_vtx )
3200 CV_ERROR( CV_StsNullPtr, "" );
3202 if( start_vtx == end_vtx )
3205 if( !CV_IS_GRAPH_ORIENTED( graph ) &&
3206 (start_vtx->flags & CV_SET_ELEM_IDX_MASK) > (end_vtx->flags & CV_SET_ELEM_IDX_MASK) )
3209 CV_SWAP( start_vtx, end_vtx, t );
3212 for( ofs = prev_ofs = 0, prev_edge = 0, edge = start_vtx->first; edge != 0;
3213 prev_ofs = ofs, prev_edge = edge, edge = edge->next[ofs] )
3215 ofs = start_vtx == edge->vtx[1];
3216 assert( ofs == 1 || start_vtx == edge->vtx[0] );
3217 if( edge->vtx[1] == end_vtx )
3224 next_edge = edge->next[ofs];
3226 prev_edge->next[prev_ofs] = next_edge;
3228 start_vtx->first = next_edge;
3230 for( ofs = prev_ofs = 0, prev_edge = 0, edge = end_vtx->first; edge != 0;
3231 prev_ofs = ofs, prev_edge = edge, edge = edge->next[ofs] )
3233 ofs = end_vtx == edge->vtx[1];
3234 assert( ofs == 1 || end_vtx == edge->vtx[0] );
3235 if( edge->vtx[0] == start_vtx )
3239 assert( edge != 0 );
3241 next_edge = edge->next[ofs];
3243 prev_edge->next[prev_ofs] = next_edge;
3245 end_vtx->first = next_edge;
3247 cvSetRemoveByPtr( graph->edges, edge );
3253 /* Removes the graph edge connecting two given vertices */
3255 cvGraphRemoveEdge( CvGraph* graph, int start_idx, int end_idx )
3257 CvGraphVtx *start_vtx;
3258 CvGraphVtx *end_vtx;
3260 CV_FUNCNAME( "cvGraphRemoveEdge" );
3265 CV_ERROR( CV_StsNullPtr, "" );
3267 start_vtx = cvGetGraphVtx( graph, start_idx );
3268 end_vtx = cvGetGraphVtx( graph, end_idx );
3270 cvGraphRemoveEdgeByPtr( graph, start_vtx, end_vtx );
3276 /* Counts number of edges incident to the vertex */
3278 cvGraphVtxDegreeByPtr( const CvGraph* graph, const CvGraphVtx* vertex )
3283 CV_FUNCNAME( "cvGraphVtxDegreeByPtr" );
3287 if( !graph || !vertex )
3288 CV_ERROR( CV_StsNullPtr, "" );
3290 for( edge = vertex->first, count = 0; edge; )
3293 edge = CV_NEXT_GRAPH_EDGE( edge, vertex );
3302 /* Counts number of edges incident to the vertex */
3304 cvGraphVtxDegree( const CvGraph* graph, int vtx_idx )
3310 CV_FUNCNAME( "cvGraphVtxDegree" );
3315 CV_ERROR( CV_StsNullPtr, "" );
3317 vertex = cvGetGraphVtx( graph, vtx_idx );
3319 CV_ERROR( CV_StsObjectNotFound, "" );
3321 for( edge = vertex->first, count = 0; edge; )
3324 edge = CV_NEXT_GRAPH_EDGE( edge, vertex );
3333 typedef struct CvGraphItem
3342 icvSeqElemsClearFlags( CvSeq* seq, int offset, int clear_mask )
3344 CV_FUNCNAME("icvStartScanGraph");
3349 int i, total, elem_size;
3352 CV_ERROR( CV_StsNullPtr, "" );
3354 elem_size = seq->elem_size;
3357 if( (unsigned)offset > (unsigned)elem_size )
3358 CV_ERROR( CV_StsBadArg, "" );
3360 CV_CALL( cvStartReadSeq( seq, &reader ));
3362 for( i = 0; i < total; i++ )
3364 int* flag_ptr = (int*)(reader.ptr + offset);
3365 *flag_ptr &= ~clear_mask;
3367 CV_NEXT_SEQ_ELEM( elem_size, reader );
3375 icvSeqFindNextElem( CvSeq* seq, int offset, int mask,
3376 int value, int* start_index )
3380 CV_FUNCNAME("icvStartScanGraph");
3385 int total, elem_size, index;
3387 if( !seq || !start_index )
3388 CV_ERROR( CV_StsNullPtr, "" );
3390 elem_size = seq->elem_size;
3392 index = *start_index;
3394 if( (unsigned)offset > (unsigned)elem_size )
3395 CV_ERROR( CV_StsBadArg, "" );
3400 if( (unsigned)index >= (unsigned)total )
3403 index += index < 0 ? total : 0;
3406 CV_CALL( cvStartReadSeq( seq, &reader ));
3409 CV_CALL( cvSetSeqReaderPos( &reader, index ));
3411 for( index = 0; index < total; index++ )
3413 int* flag_ptr = (int*)(reader.ptr + offset);
3414 if( (*flag_ptr & mask) == value )
3417 CV_NEXT_SEQ_ELEM( elem_size, reader );
3422 elem_ptr = reader.ptr;
3423 *start_index = index;
3431 #define CV_FIELD_OFFSET( field, structtype ) ((int)(size_t)&((structtype*)0)->field)
3433 CV_IMPL CvGraphScanner*
3434 cvCreateGraphScanner( CvGraph* graph, CvGraphVtx* vtx, int mask )
3436 CvGraphScanner* scanner = 0;
3437 CvMemStorage* child_storage = 0;
3439 CV_FUNCNAME("cvCreateGraphScanner");
3444 CV_ERROR( CV_StsNullPtr, "Null graph pointer" );
3446 CV_ASSERT( graph->storage != 0 );
3448 CV_CALL( scanner = (CvGraphScanner*)cvAlloc( sizeof(*scanner) ));
3449 memset( scanner, 0, sizeof(*scanner));
3451 scanner->graph = graph;
3452 scanner->mask = mask;
3454 scanner->index = vtx == 0 ? 0 : -1;
3456 CV_CALL( child_storage = cvCreateChildMemStorage( graph->storage ));
3458 CV_CALL( scanner->stack = cvCreateSeq( 0, sizeof(CvSet),
3459 sizeof(CvGraphItem), child_storage ));
3461 CV_CALL( icvSeqElemsClearFlags( (CvSeq*)graph,
3462 CV_FIELD_OFFSET( flags, CvGraphVtx),
3463 CV_GRAPH_ITEM_VISITED_FLAG|
3464 CV_GRAPH_SEARCH_TREE_NODE_FLAG ));
3466 CV_CALL( icvSeqElemsClearFlags( (CvSeq*)(graph->edges),
3467 CV_FIELD_OFFSET( flags, CvGraphEdge),
3468 CV_GRAPH_ITEM_VISITED_FLAG ));
3472 if( cvGetErrStatus() < 0 )
3474 cvReleaseMemStorage( &child_storage );
3483 cvReleaseGraphScanner( CvGraphScanner** scanner )
3485 CV_FUNCNAME("cvReleaseGraphScanner");
3490 CV_ERROR( CV_StsNullPtr, "Null double pointer to graph scanner" );
3494 if( (*scanner)->stack )
3495 CV_CALL( cvReleaseMemStorage( &((*scanner)->stack->storage)));
3504 cvNextGraphItem( CvGraphScanner* scanner )
3508 CV_FUNCNAME("cvNextGraphItem");
3517 if( !scanner || !(scanner->stack))
3518 CV_ERROR( CV_StsNullPtr, "Null graph scanner" );
3522 edge = scanner->edge;
3528 if( dst && !CV_IS_GRAPH_VERTEX_VISITED(dst) )
3530 scanner->vtx = vtx = dst;
3532 dst->flags |= CV_GRAPH_ITEM_VISITED_FLAG;
3534 if((scanner->mask & CV_GRAPH_VERTEX))
3537 scanner->edge = vtx->first;
3539 code = CV_GRAPH_VERTEX;
3546 dst = edge->vtx[vtx == edge->vtx[0]];
3548 if( !CV_IS_GRAPH_EDGE_VISITED(edge) )
3550 // check that the edge is outcoming
3551 if( !CV_IS_GRAPH_ORIENTED( scanner->graph ) || dst != edge->vtx[0] )
3553 edge->flags |= CV_GRAPH_ITEM_VISITED_FLAG;
3555 if( !CV_IS_GRAPH_VERTEX_VISITED(dst) )
3560 vtx->flags |= CV_GRAPH_SEARCH_TREE_NODE_FLAG;
3562 cvSeqPush( scanner->stack, &item );
3564 if( scanner->mask & CV_GRAPH_TREE_EDGE )
3566 code = CV_GRAPH_TREE_EDGE;
3569 scanner->edge = edge;
3576 if( scanner->mask & (CV_GRAPH_BACK_EDGE|
3577 CV_GRAPH_CROSS_EDGE|
3578 CV_GRAPH_FORWARD_EDGE) )
3580 code = (dst->flags & CV_GRAPH_SEARCH_TREE_NODE_FLAG) ?
3581 CV_GRAPH_BACK_EDGE :
3582 (edge->flags & CV_GRAPH_FORWARD_EDGE_FLAG) ?
3583 CV_GRAPH_FORWARD_EDGE : CV_GRAPH_CROSS_EDGE;
3584 edge->flags &= ~CV_GRAPH_FORWARD_EDGE_FLAG;
3585 if( scanner->mask & code )
3589 scanner->edge = edge;
3595 else if( (dst->flags & (CV_GRAPH_ITEM_VISITED_FLAG|
3596 CV_GRAPH_SEARCH_TREE_NODE_FLAG)) ==
3597 (CV_GRAPH_ITEM_VISITED_FLAG|
3598 CV_GRAPH_SEARCH_TREE_NODE_FLAG))
3600 edge->flags |= CV_GRAPH_FORWARD_EDGE_FLAG;
3604 edge = CV_NEXT_GRAPH_EDGE( edge, vtx );
3607 if( !edge ) /* need to backtrack */
3609 if( scanner->stack->total == 0 )
3611 if( scanner->index >= 0 )
3617 cvSeqPop( scanner->stack, &item );
3619 vtx->flags &= ~CV_GRAPH_SEARCH_TREE_NODE_FLAG;
3623 if( scanner->mask & CV_GRAPH_BACKTRACKING )
3626 scanner->edge = edge;
3627 scanner->dst = edge->vtx[vtx == edge->vtx[0]];
3628 code = CV_GRAPH_BACKTRACKING;
3636 vtx = (CvGraphVtx*)icvSeqFindNextElem( (CvSeq*)(scanner->graph),
3637 CV_FIELD_OFFSET( flags, CvGraphVtx ), CV_GRAPH_ITEM_VISITED_FLAG|INT_MIN,
3638 0, &(scanner->index) );
3642 code = CV_GRAPH_OVER;
3648 if( scanner->mask & CV_GRAPH_NEW_TREE )
3653 code = CV_GRAPH_NEW_TREE;
3665 cvCloneGraph( const CvGraph* graph, CvMemStorage* storage )
3667 int* flag_buffer = 0;
3668 CvGraphVtx** ptr_buffer = 0;
3669 CvGraph* result = 0;
3671 CV_FUNCNAME( "cvCloneGraph" );
3676 int vtx_size, edge_size;
3679 if( !CV_IS_GRAPH(graph))
3680 CV_ERROR( CV_StsBadArg, "Invalid graph pointer" );
3683 storage = graph->storage;
3686 CV_ERROR( CV_StsNullPtr, "NULL storage pointer" );
3688 vtx_size = graph->elem_size;
3689 edge_size = graph->edges->elem_size;
3691 CV_CALL( flag_buffer = (int*)cvAlloc( graph->total*sizeof(flag_buffer[0])));
3692 CV_CALL( ptr_buffer = (CvGraphVtx**)cvAlloc( graph->total*sizeof(ptr_buffer[0])));
3693 CV_CALL( result = cvCreateGraph( graph->flags, graph->header_size,
3694 vtx_size, edge_size, storage ));
3695 memcpy( result + sizeof(CvGraph), graph + sizeof(CvGraph),
3696 graph->header_size - sizeof(CvGraph));
3698 // pass 1. save flags, copy vertices
3699 cvStartReadSeq( (CvSeq*)graph, &reader );
3700 for( i = 0, k = 0; i < graph->total; i++ )
3702 if( CV_IS_SET_ELEM( reader.ptr ))
3704 CvGraphVtx* vtx = (CvGraphVtx*)reader.ptr;
3705 CvGraphVtx* dstvtx = 0;
3706 CV_CALL( cvGraphAddVtx( result, vtx, &dstvtx ));
3707 flag_buffer[k] = dstvtx->flags = vtx->flags;
3709 ptr_buffer[k++] = dstvtx;
3711 CV_NEXT_SEQ_ELEM( vtx_size, reader );
3714 // pass 2. copy edges
3715 cvStartReadSeq( (CvSeq*)graph->edges, &reader );
3716 for( i = 0; i < graph->edges->total; i++ )
3718 if( CV_IS_SET_ELEM( reader.ptr ))
3720 CvGraphEdge* edge = (CvGraphEdge*)reader.ptr;
3721 CvGraphEdge* dstedge = 0;
3722 CvGraphVtx* new_org = ptr_buffer[edge->vtx[0]->flags];
3723 CvGraphVtx* new_dst = ptr_buffer[edge->vtx[1]->flags];
3724 CV_CALL( cvGraphAddEdgeByPtr( result, new_org, new_dst, edge, &dstedge ));
3725 dstedge->flags = edge->flags;
3727 CV_NEXT_SEQ_ELEM( edge_size, reader );
3730 // pass 3. restore flags
3731 cvStartReadSeq( (CvSeq*)graph, &reader );
3732 for( i = 0, k = 0; i < graph->edges->total; i++ )
3734 if( CV_IS_SET_ELEM( reader.ptr ))
3736 CvGraphVtx* vtx = (CvGraphVtx*)reader.ptr;
3737 vtx->flags = flag_buffer[k++];
3739 CV_NEXT_SEQ_ELEM( vtx_size, reader );
3744 cvFree( &flag_buffer );
3745 cvFree( &ptr_buffer );
3747 if( cvGetErrStatus() < 0 )
3754 /****************************************************************************************\
3755 * Working with sequence tree *
3756 \****************************************************************************************/
3758 // Gathers pointers to all the sequences, accessible from the <first>, to the single sequence.
3760 cvTreeToNodeSeq( const void* first, int header_size, CvMemStorage* storage )
3764 CV_FUNCNAME("cvTreeToNodeSeq");
3768 CvTreeNodeIterator iterator;
3771 CV_ERROR( CV_StsNullPtr, "NULL storage pointer" );
3773 CV_CALL( allseq = cvCreateSeq( 0, header_size, sizeof(first), storage ));
3777 CV_CALL( cvInitTreeNodeIterator( &iterator, first, INT_MAX ));
3781 void* node = cvNextTreeNode( &iterator );
3784 cvSeqPush( allseq, &node );
3794 typedef struct CvTreeNode
3796 int flags; /* micsellaneous flags */
3797 int header_size; /* size of sequence header */
3798 struct CvTreeNode* h_prev; /* previous sequence */
3799 struct CvTreeNode* h_next; /* next sequence */
3800 struct CvTreeNode* v_prev; /* 2nd previous sequence */
3801 struct CvTreeNode* v_next; /* 2nd next sequence */
3807 // Insert contour into tree given certain parent sequence.
3808 // If parent is equal to frame (the most external contour),
3809 // then added contour will have null pointer to parent.
3811 cvInsertNodeIntoTree( void* _node, void* _parent, void* _frame )
3813 CV_FUNCNAME( "cvInsertNodeIntoTree" );
3817 CvTreeNode* node = (CvTreeNode*)_node;
3818 CvTreeNode* parent = (CvTreeNode*)_parent;
3820 if( !node || !parent )
3821 CV_ERROR( CV_StsNullPtr, "" );
3823 node->v_prev = _parent != _frame ? parent : 0;
3824 node->h_next = parent->v_next;
3826 assert( parent->v_next != node );
3828 if( parent->v_next )
3829 parent->v_next->h_prev = node;
3830 parent->v_next = node;
3836 // Removes contour from tree (together with the contour children).
3838 cvRemoveNodeFromTree( void* _node, void* _frame )
3840 CV_FUNCNAME( "cvRemoveNodeFromTree" );
3844 CvTreeNode* node = (CvTreeNode*)_node;
3845 CvTreeNode* frame = (CvTreeNode*)_frame;
3848 CV_ERROR_FROM_CODE( CV_StsNullPtr );
3851 CV_ERROR( CV_StsBadArg, "frame node could not be deleted" );
3854 node->h_next->h_prev = node->h_prev;
3857 node->h_prev->h_next = node->h_next;
3860 CvTreeNode* parent = node->v_prev;
3866 assert( parent->v_next == node );
3867 parent->v_next = node->h_next;
3876 cvInitTreeNodeIterator( CvTreeNodeIterator* treeIterator,
3877 const void* first, int max_level )
3879 CV_FUNCNAME("icvInitTreeNodeIterator");
3883 if( !treeIterator || !first )
3884 CV_ERROR( CV_StsNullPtr, "" );
3887 CV_ERROR( CV_StsOutOfRange, "" );
3889 treeIterator->node = (void*)first;
3890 treeIterator->level = 0;
3891 treeIterator->max_level = max_level;
3898 cvNextTreeNode( CvTreeNodeIterator* treeIterator )
3900 CvTreeNode* prevNode = 0;
3902 CV_FUNCNAME("cvNextTreeNode");
3910 CV_ERROR( CV_StsNullPtr, "NULL iterator pointer" );
3912 prevNode = node = (CvTreeNode*)treeIterator->node;
3913 level = treeIterator->level;
3917 if( node->v_next && level+1 < treeIterator->max_level )
3919 node = node->v_next;
3924 while( node->h_next == 0 )
3926 node = node->v_prev;
3933 node = node && treeIterator->max_level != 0 ? node->h_next : 0;
3937 treeIterator->node = node;
3938 treeIterator->level = level;
3947 cvPrevTreeNode( CvTreeNodeIterator* treeIterator )
3949 CvTreeNode* prevNode = 0;
3951 CV_FUNCNAME("cvPrevTreeNode");
3959 CV_ERROR( CV_StsNullPtr, "" );
3961 prevNode = node = (CvTreeNode*)treeIterator->node;
3962 level = treeIterator->level;
3968 node = node->v_prev;
3974 node = node->h_prev;
3976 while( node->v_next && level < treeIterator->max_level )
3978 node = node->v_next;
3981 while( node->h_next )
3982 node = node->h_next;
3987 treeIterator->node = node;
3988 treeIterator->level = level;