From 6554598530b6d148e5f4e70c7071f97883f904f5 Mon Sep 17 00:00:00 2001 From: Deborah Goldsmith Date: Tue, 5 Jun 2007 02:40:31 +0000 Subject: [PATCH] ICU-5563 Redo setAdd and setEquals to not be O(N^2) X-SVN-Rev: 21632 --- icu4c/source/common/rbbitblb.cpp | 117 ++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 42 deletions(-) diff --git a/icu4c/source/common/rbbitblb.cpp b/icu4c/source/common/rbbitblb.cpp index 73ffd6dd0a..abf30be3ca 100644 --- a/icu4c/source/common/rbbitblb.cpp +++ b/icu4c/source/common/rbbitblb.cpp @@ -1,6 +1,6 @@ /* ********************************************************************** -* Copyright (c) 2002-2006, International Business Machines +* Copyright (c) 2002-2007, International Business Machines * Corporation and others. All Rights Reserved. ********************************************************************** */ @@ -20,6 +20,7 @@ #include "rbbidata.h" #include "cstring.h" #include "uassert.h" +#include "cmemory.h" U_NAMESPACE_BEGIN @@ -234,6 +235,9 @@ void RBBITableBuilder::calcFirstPos(RBBINode *n) { n->fType == RBBINode::lookAhead || n->fType == RBBINode::tag) { // These are non-empty leaf node types. + // Note: In order to maintain the sort invariant on the set, + // this function should only be called on a node whose set is + // empty to start with. n->fFirstPosSet->addElement(n, *fStatus); return; } @@ -277,6 +281,9 @@ void RBBITableBuilder::calcLastPos(RBBINode *n) { n->fType == RBBINode::lookAhead || n->fType == RBBINode::tag) { // These are non-empty leaf node types. + // Note: In order to maintain the sort invariant on the set, + // this function should only be called on a node whose set is + // empty to start with. n->fLastPosSet->addElement(n, *fStatus); return; } @@ -895,23 +902,78 @@ void RBBITableBuilder::sortedAdd(UVector **vector, int32_t val) { // // setAdd Set operation on UVector // dest = dest union source -// Elements may only appear once. Order is unimportant. +// Elements may only appear once and must be sorted. // //----------------------------------------------------------------------------- void RBBITableBuilder::setAdd(UVector *dest, UVector *source) { int destOriginalSize = dest->size(); int sourceSize = source->size(); - int32_t si, di; + int32_t di = 0; + void *(destS[16]), *(sourceS[16]); // Handle small cases without malloc + void **destH = 0, **sourceH = 0; + void **destBuff, **sourceBuff; + void **destLim, **sourceLim; - for (si=0; sielementAt(si); - for (di=0; dielementAt(di) == elToAdd) { - goto elementAlreadyInDest; - } + if (destOriginalSize > sizeof(destS)/sizeof(destS[0])) { + destH = (void **)uprv_malloc(sizeof(void *) * destOriginalSize); + destBuff = destH; + } + else { + destBuff = destS; + } + if (destBuff == 0) { + return; + } + destLim = destBuff + destOriginalSize; + + if (sourceSize > sizeof(sourceS)/sizeof(sourceS[0])) { + sourceH = (void **)uprv_malloc(sizeof(void *) * sourceSize); + sourceBuff = sourceH; + } + else { + sourceBuff = sourceS; + } + if (sourceBuff == 0) { + if (destH) { + uprv_free(destH); } - dest->addElement(elToAdd, *fStatus); - elementAlreadyInDest: ; + return; + } + sourceLim = sourceBuff + sourceSize; + + // Avoid multiple "get element" calls by getting the contents into arrays + (void) dest->toArray(destBuff); + (void) source->toArray(sourceBuff); + + dest->setSize(sourceSize+destOriginalSize); + + while (sourceBuff < sourceLim && destBuff < destLim) { + if (*destBuff < *sourceBuff) { + dest->setElementAt(*destBuff++, di++); + } + else if (*sourceBuff < *destBuff) { + dest->setElementAt(*sourceBuff++, di++); + } + else { + dest->setElementAt(*sourceBuff++, di++); + destBuff++; + } + } + + // At most one of these two cleanup loops will execute + while (destBuff < destLim) { + dest->setElementAt(*destBuff++, di++); + } + while (sourceBuff < sourceLim) { + dest->setElementAt(*sourceBuff++, di++); + } + + dest->setSize(di); + if (destH) { + uprv_free(destH); + } + if (sourceH) { + uprv_free(sourceH); } } @@ -921,40 +983,11 @@ void RBBITableBuilder::setAdd(UVector *dest, UVector *source) { // // setEqual Set operation on UVector. // Compare for equality. -// Elements may appear only once. -// Elements may appear in any order. +// Elements must be sorted. // //----------------------------------------------------------------------------- UBool RBBITableBuilder::setEquals(UVector *a, UVector *b) { - int32_t aSize = a->size(); - int32_t bSize = b->size(); - - if (aSize != bSize) { - return FALSE; - } - - int32_t ax; - int32_t bx; - int32_t firstBx = 0; - void *aVal; - void *bVal = NULL; - - for (ax=0; axelementAt(ax); - for (bx=firstBx; bxelementAt(bx); - if (aVal == bVal) { - if (bx==firstBx) { - firstBx++; - } - break; - } - } - if (aVal != bVal) { - return FALSE; - } - } - return TRUE; + return a->equals(*b); }