ICU-1043 Fractional UCA now canonicaly closes suplementary codepoints. Builder checks canonical closure for suplementary ranges. Element lookup in UCA needs to distinguish between implict suplementary codepoint and codepoint redefined in the UCA.

X-SVN-Rev: 6642
This commit is contained in:
Vladimir Weinstein 2001-11-06 22:55:29 +00:00
parent d3b7cc9043
commit 12c74a4400
10 changed files with 2138 additions and 57 deletions

File diff suppressed because it is too large Load diff

View file

@ -51,33 +51,94 @@ ucmpe32_open(int32_t defaultValue, int32_t surrogateValue, UErrorCode *status)
uprv_memset(this_obj->stage1, 0, this_obj->stage1Top*sizeof(uint16_t));
/* allocate stage 2 of the trie and reset the first block */
this_obj->stage2= (int32_t*)uprv_malloc(60000*sizeof(*(this_obj->stage2)));
this_obj->stage2= (int32_t*)uprv_malloc(INIT_UCMPE32_STAGE2_SIZE*sizeof(*(this_obj->stage2)));
if(this_obj->stage2 == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
uprv_free(this_obj->stage1);
uprv_free(this_obj);
return NULL;
}
this_obj->stage2Size = INIT_UCMPE32_STAGE2_SIZE;
this_obj->stage2DefaultTop = 0;
this_obj->fDefaultValue = defaultValue;
this_obj->fSurrogateValue = surrogateValue;
for(bla = this_obj->stage2; bla<this_obj->stage2+_UCMPE32_STAGE_2_BLOCK_COUNT; bla++) {
for(bla = this_obj->stage2; bla<this_obj->stage2+INIT_UCMPE32_STAGE2_SIZE; bla++) {
/*for(bla = this_obj->stage2; bla<this_obj->stage2+_UCMPE32_STAGE_2_BLOCK_COUNT; bla++) {*/
*bla = this_obj->fDefaultValue;
}
this_obj->stage2Top = _UCMPE32_STAGE_2_BLOCK_COUNT;
this_obj->fCompact = FALSE;
this_obj->fBogus = FALSE;
this_obj->fInitPhase = TRUE;
return this_obj;
}
/*
* Set a range of UnicodeChars to the same value
*/
void
ucmpe32_setRange32(CompactEIntArray* this_obj, UChar32 start, UChar32 end, int32_t value) {
UChar32 code = 0;
uint32_t s1Start = start>>_UCMPE32_TRIE_SHIFT;
uint32_t s1End = end>>_UCMPE32_TRIE_SHIFT;
int32_t *bla;
uint32_t i = 0;
/* Allocate a block for repeat stuff */
int32_t repeatBlock = 0;
if (this_obj->fInitPhase == FALSE || this_obj->fCompact == TRUE || (start > end)) {
return;
}
/* if there is stuff that doesn't fit */
if((start & _UCMPE32_STAGE_2_MASK) != 0) { /* at the start */
s1Start++;
for(code = start; code < (UChar32)(s1Start<<_UCMPE32_TRIE_SHIFT); code++) {
ucmpe32_set32(this_obj, code, value);
}
}
repeatBlock = this_obj->stage2Top;
this_obj->stage2Top += _UCMPE32_STAGE_2_BLOCK_COUNT;
for(bla = this_obj->stage2+repeatBlock; bla<this_obj->stage2+this_obj->stage2Top; bla++) {
*bla = value;
}
for(i = s1Start; i< s1End; i++) {
this_obj->stage1[i] = (uint16_t)(repeatBlock);
}
if((end & _UCMPE32_STAGE_2_MASK) != 0) { /* at the end */
for(code = (s1End<<_UCMPE32_TRIE_SHIFT); code <= end; code++) {
ucmpe32_set32(this_obj, code, value);
}
} else {
this_obj->stage1[s1End] = (uint16_t)(repeatBlock);
}
this_obj->stage2DefaultTop = this_obj->stage2Top;
this_obj->fInitPhase = TRUE;
}
/*
* get or create a Norm unit;
* get or create the intermediate trie entries for it as well
*/
/********* THIS IS THE ADD FUNCTION ********************/
int32_t
ucmpe32_get32(CompactEIntArray* this_obj, UChar32 code) {
int16_t stage1 = (this_obj->stage1[(code >> _UCMPE32_TRIE_SHIFT)]);
int32_t offset = (code & _UCMPE32_STAGE_2_MASK);
int32_t result = this_obj->stage2[stage1 + offset];
return result;
}
void
ucmpe32_set32(CompactEIntArray* this_obj, UChar32 code, int32_t value)
{
@ -87,18 +148,27 @@ ucmpe32_set32(CompactEIntArray* this_obj, UChar32 code, int32_t value)
return;
}
this_obj->fInitPhase = FALSE;
{
uint32_t i;
uint16_t j;
i=code>>_UCMPE32_TRIE_SHIFT;
j=this_obj->stage1[i];
if(j==0) {
if(j<=this_obj->stage2DefaultTop) {
/* allocate a stage 2 block */
int32_t *p, *bla;
int32_t *p, *bla, value;
value = this_obj->stage2[j]; /* pick the value the empty block was filled with */
if(this_obj->stage2Size < (this_obj->stage2Top + _UCMPE32_STAGE_2_BLOCK_COUNT)) {
this_obj->stage2 = (int32_t *)uprv_realloc(this_obj->stage2, 2*this_obj->stage2Size);
if(this_obj->stage2 == NULL) {
}
this_obj->stage2Size *= 2;
}
p = this_obj->stage2+this_obj->stage2Top;
for(bla = p; bla<p+_UCMPE32_STAGE_2_BLOCK_COUNT; bla++) {
*bla = this_obj->fDefaultValue;
*bla = value; /* fill the newly allocated block with the default values for that block */
}
this_obj->stage2Top += _UCMPE32_STAGE_2_BLOCK_COUNT;
@ -126,11 +196,10 @@ ucmpe32_setSurrogate(CompactEIntArray* this_obj, UChar lead, UChar trail, int32_
* Fold the supplementary code point data for one lead surrogate.
*/
static uint16_t
foldLeadSurrogate(uint16_t *parent, int32_t parentCount,
int32_t *stage, int32_t *pStageCount,
uint32_t base, int32_t surrogateValue) {
foldLeadSurrogate(CompactEIntArray* this_obj,
uint32_t base, int32_t top) {
uint32_t leadNorm32=0;
uint32_t i, j, s2;
int32_t i, j, s2;
uint32_t leadSurrogate=0xd7c0+(base>>10);
#if 0
@ -138,11 +207,11 @@ foldLeadSurrogate(uint16_t *parent, int32_t parentCount,
#endif
/* calculate the 32-bit data word for the lead surrogate */
for(i=0; i<_UCMPE32_SURROGATE_BLOCK_COUNT; ++i) {
s2=parent[(base>>_UCMPE32_TRIE_SHIFT)+i];
s2=this_obj->stage1[(base>>_UCMPE32_TRIE_SHIFT)+i];
if(s2!=0) {
for(j=0; j<_UCMPE32_STAGE_2_BLOCK_COUNT; ++j) {
/* basically, or all 32-bit data into the one for the lead surrogate */
leadNorm32|=stage[s2+j];
leadNorm32|=this_obj->stage2[s2+j];
}
}
}
@ -160,19 +229,19 @@ foldLeadSurrogate(uint16_t *parent, int32_t parentCount,
* this is because 16 bits in the FCD trie data do not allow for anything
* but the two leading and trailing combining classes of the canonical decomposition.
*/
leadNorm32= surrogateValue | ((parentCount<<_UCMPE32_TRIE_SHIFT)&~_UCMPE32_STAGE_2_MASK);
leadNorm32= this_obj->fSurrogateValue | ((top<<_UCMPE32_TRIE_SHIFT)&~_UCMPE32_STAGE_2_MASK);
/* enter the lead surrogate's data */
s2=parent[leadSurrogate>>_UCMPE32_TRIE_SHIFT];
if(s2==0) {
s2=this_obj->stage1[leadSurrogate>>_UCMPE32_TRIE_SHIFT];
if(s2<=this_obj->stage2DefaultTop) {
/* allocate a new stage 2 block in stage (the memory is there from makeAll32()/makeFCD()) */
s2=parent[leadSurrogate>>_UCMPE32_TRIE_SHIFT]=(uint16_t)*pStageCount;
*pStageCount+=_UCMPE32_STAGE_2_BLOCK_COUNT;
s2=this_obj->stage1[leadSurrogate>>_UCMPE32_TRIE_SHIFT]=(uint16_t)this_obj->stage2Top;
this_obj->stage2Top+=_UCMPE32_STAGE_2_BLOCK_COUNT;
}
stage[s2+(leadSurrogate&_UCMPE32_STAGE_2_MASK)]=leadNorm32;
this_obj->stage2[s2+(leadSurrogate&_UCMPE32_STAGE_2_MASK)]=leadNorm32;
/* move the actual stage 1 indexes from the supplementary position to the new one */
uprv_memmove(parent+parentCount, parent+(base>>_UCMPE32_TRIE_SHIFT), _UCMPE32_SURROGATE_BLOCK_COUNT*2);
uprv_memmove(this_obj->stage1+top, this_obj->stage1+(base>>_UCMPE32_TRIE_SHIFT), _UCMPE32_SURROGATE_BLOCK_COUNT*2);
/* increment stage 1 top */
return _UCMPE32_SURROGATE_BLOCK_COUNT;
@ -186,19 +255,17 @@ foldLeadSurrogate(uint16_t *parent, int32_t parentCount,
* Use after makeAll32().
*/
static uint32_t
foldSupplementary(uint16_t *parent, int32_t parentCount,
int32_t *stage, int32_t *pStageCount,
int32_t surrogateValue) {
foldSupplementary(CompactEIntArray* this_obj, int32_t top) {
uint32_t c;
uint16_t i;
/* search for any stage 1 entries for supplementary code points */
for(c=0x10000; c<0x110000;) {
i=parent[c>>_UCMPE32_TRIE_SHIFT];
i=this_obj->stage1[c>>_UCMPE32_TRIE_SHIFT];
if(i!=0) {
/* there is data, treat the full block for a lead surrogate */
c&=~0x3ff;
parentCount+=foldLeadSurrogate(parent, parentCount, stage, pStageCount, c, surrogateValue);
top+=foldLeadSurrogate(this_obj, c, top);
c+=0x400;
} else {
c+=_UCMPE32_STAGE_2_BLOCK_COUNT;
@ -208,7 +275,7 @@ foldSupplementary(uint16_t *parent, int32_t parentCount,
printf("trie index count: BMP %u all Unicode %lu folded %u\n",
_UCMPE32_STAGE_1_BMP_COUNT, (long)_UCMPE32_STAGE_1_MAX_COUNT, parentCount);
#endif
return parentCount;
return top;
}
void
@ -225,9 +292,7 @@ ucmpe32_compact(CompactEIntArray* this_obj) {
uint16_t i, start, prevEnd, newStart;
/* fold supplementary code points into lead surrogates */
this_obj->stage1Top=foldSupplementary(this_obj->stage1, _UCMPE32_STAGE_1_BMP_COUNT,
this_obj->stage2, &this_obj->stage2Top, this_obj->fSurrogateValue);
this_obj->stage1Top=foldSupplementary(this_obj, _UCMPE32_STAGE_1_BMP_COUNT);
map[0]=0;
newStart=_UCMPE32_STAGE_2_BLOCK_COUNT;
for(start=newStart; start<this_obj->stage2Top;) {
@ -297,6 +362,8 @@ ucmpe32_clone(CompactEIntArray* orig, UErrorCode *status)
}
uprv_memcpy(this_obj->stage1, orig->stage1, this_obj->stage1Top*sizeof(uint16_t));
this_obj->stage2Size = orig->stage2Size;
this_obj->stage2DefaultTop = orig->stage2DefaultTop;
this_obj->stage2Top = orig->stage2Top;
this_obj->stage2 = (int32_t*)uprv_malloc(60000*sizeof(*(this_obj->stage2)));
if(this_obj->stage2 == NULL) {
@ -311,6 +378,7 @@ ucmpe32_clone(CompactEIntArray* orig, UErrorCode *status)
this_obj->fStructSize = sizeof(CompactEIntArray);
this_obj->fCompact = orig->fCompact;
this_obj->fInitPhase = orig->fInitPhase;
return this_obj;
}

View file

@ -31,6 +31,7 @@
#define UCMPE32_H
#define ICU_UCMPE32_VERSION 0x01260000
#define INIT_UCMPE32_STAGE2_SIZE 60000
#include "unicode/utypes.h"
@ -69,13 +70,16 @@ typedef struct CompactEIntArray{
UBool fCompact;
UBool fAlias;
UBool fBogus;
UBool fInitPhase;
uint16_t *stage1;
int32_t *stage2;
int32_t stage1Top;
int32_t stage2Top;
int32_t stage2DefaultTop;
int32_t fDefaultValue;
int32_t fSurrogateValue;
int32_t stage2Size;
} CompactEIntArray;
@ -117,6 +121,9 @@ U_CAPI void U_EXPORT2 ucmpe32_close(CompactEIntArray* array);
*/
#define ucmpe32_get(this_obj, index) (this_obj->stage2[(this_obj->stage1[(index >> _UCMPE32_TRIE_SHIFT)] )+ \
(index & _UCMPE32_STAGE_2_MASK)])
U_CAPI
int32_t
ucmpe32_get32(CompactEIntArray* this_obj, UChar32 code);
/**
* Get the mapped value of a confirmed surrogate. First value already comes
@ -148,6 +155,14 @@ ucmpe32_getSurrogateEx(CompactEIntArray *array, UChar lead, UChar trail);
U_CAPI void U_EXPORT2 ucmpe32_set32(CompactEIntArray *array,
UChar32 character,
int32_t value);
/**
* Sets an inclusive range of characters to the same value
* @param start start of the range
* @param end end of the range
* @param value value to be set
*/
U_CAPI void
ucmpe32_setRange32(CompactEIntArray* this_obj, UChar32 start, UChar32 end, int32_t value);
/**
* alias for compatibility

File diff suppressed because it is too large Load diff

View file

@ -1854,6 +1854,9 @@ uint32_t ucol_prv_getSpecialCE(const UCollator *coll, UChar ch, uint32_t CE, col
if(CE == UCOL_NOT_FOUND) { // there are tailored surrogates in this block, but not this one.
// We need to backup
loadState(source, &state, TRUE);
} else if (getCETag(CE) == IMPLICIT_TAG) { // got an untailored surrogate here
uint32_t cp = ((((uint32_t)ch)<<10UL)+(trail)-(((uint32_t)0xd800<<10UL)+0xdc00-0x10000));
return getImplicit(cp, source, 0);
}
}
}

View file

@ -841,7 +841,7 @@ U_CFUNC void ucol_createElements(UColTokenParser *src, tempUCATable *t, UColTokL
uprv_uca_addAnElement(t, &el, status);
}
}
#endif
#endif
#if UCOL_DEBUG_DUPLICATES
if(*status != U_ZERO_ERROR) {
@ -1042,6 +1042,66 @@ UCATableHeader *ucol_assembleTailoringTable(UColTokenParser *src, UErrorCode *st
uprv_uca_closeTempTable(tempTable);
}
/* produce canonical closure */
UCollationElements* colEl = ucol_openElements(tempColl, NULL, 0, status);
UChar32 u32 = 0;
UChar comp[2];
uint32_t len = 0;
for(u32 = 0; u32 < 0x30000; u32++) {
len = 0;
UTF_APPEND_CHAR_UNSAFE(comp, len, u32);
if((noOfDec = unorm_normalize(comp, len, UNORM_NFD, 0, decomp, 256, status)) > 1
|| (noOfDec == 1 && *decomp != (UChar)u))
{
if(ucol_strcoll(tempColl, comp, len, decomp, noOfDec) != UCOL_EQUAL) {
el.cPoints = decomp;
el.cSize = noOfDec;
el.noOfCEs = 0;
el.prefix = el.prefixChars;
el.prefixSize = 0;
UCAElements *prefix=(UCAElements *)uhash_get(t->prefixLookup, &el);
if(prefix == NULL) {
el.cPoints = comp;
el.cSize = len;
el.prefix = el.prefixChars;
el.prefixSize = 0;
el.noOfCEs = 0;
ucol_setText(colEl, decomp, noOfDec, status);
while((el.CEs[el.noOfCEs] = ucol_next(colEl, status)) != UCOL_NULLORDER) {
el.noOfCEs++;
}
} else {
el.cPoints = comp;
el.cSize = len;
el.prefix = el.prefixChars;
el.prefixSize = 0;
el.noOfCEs = 1;
el.CEs[0] = prefix->mapCE;
// This character uses a prefix. We have to add it
// to the unsafe table, as it decomposed form is already
// in. In Japanese, this happens for \u309e & \u30fe
// Since unsafeCPSet is static in ucol_elm, we are going
// to wrap it up in the uprv_uca_unsafeCPAddCCNZ function
}
uprv_uca_addAnElement(t, &el, status);
}
}
switch(u32) {
case 0x33FF:
u32 = 0xAC00;
break;
case 0xFFFF:
u32 = 0x1D000;
break;
case 0x1DFFF:
u32 = 0x2F800;
break;
}
}
#if 0
/* produce canonical closure */
UCollationElements* colEl = ucol_openElements(tempColl, NULL, 0, status);
for(u = 0; u < 0xFFFF; u++) {
@ -1086,6 +1146,7 @@ UCATableHeader *ucol_assembleTailoringTable(UColTokenParser *src, UErrorCode *st
}
}
}
#endif
ucol_closeElements(colEl);
ucol_close(tempColl);
}

View file

@ -829,23 +829,6 @@ static uint32_t uprv_uca_processContraction(CntTable *contractions, UCAElements
return existingCE;
}
/* Set a range of elements to a value */
uint32_t uprv_uca_setRange(tempUCATable *t, UChar32 rangeStart, UChar32 rangeEnd, int32_t value, UErrorCode *status) {
if(U_FAILURE(*status) || (rangeEnd < rangeStart)) {
return 0;
}
UChar32 counter = rangeStart;
uint32_t i = 0;
for(counter = rangeStart; counter <= rangeEnd; counter++) {
ucmpe32_set32(t->mapping, counter, value);
i++;
}
return i;
}
static uint32_t uprv_uca_finalizeAddition(tempUCATable *t, UCAElements *element, UErrorCode *status) {
uint32_t CE = UCOL_NOT_FOUND;
if(element->cSize > 1) { /* we're adding a contraction */

View file

@ -92,8 +92,6 @@ U_CAPI tempUCATable * U_EXPORT2 uprv_uca_cloneTempTable(tempUCATable *t, UErrorC
U_CAPI void U_EXPORT2 uprv_uca_closeTempTable(tempUCATable *t);
U_CAPI uint32_t U_EXPORT2 uprv_uca_addAnElement(tempUCATable *t, UCAElements *element, UErrorCode *status);
U_CAPI UCATableHeader * U_EXPORT2 uprv_uca_assembleTable(tempUCATable *t, UErrorCode *status);
U_CAPI uint32_t U_EXPORT2 uprv_uca_setRange(tempUCATable *t, UChar32 rangeStart, UChar32 rangeEnd, int32_t value, UErrorCode *status);
#define paddedsize(something) ((something)+((((something)%4)!=0)?(4-(something)%4):0))
#define headersize (paddedsize(sizeof(UCATableHeader))+paddedsize(sizeof(UColOptionSet)))

View file

@ -1649,9 +1649,9 @@ static UBool checkCEValidity(const UCollator *coll, const UChar *codepoints,
goto fail;
}
}
if ((primary != 0 && primary < primarymax) || primary >= 0xFF00) {
if ((primary != 0 && primary < primarymax) || (primary >= 0xFF00 && !isContinuation(ce))) {
log_err("UCA primary weight out of bounds\n");
return FALSE;
goto fail;
}
/* case matching not done since data generated by ken */
if (first) {

View file

@ -614,12 +614,39 @@ write_uca_table(const char *filename,
#endif
// * set to zero
struct {
UChar32 start;
UChar32 end;
int32_t value;
} ranges[] =
{
{0xAC00, 0xD7AF, UCOL_SPECIAL_FLAG | (HANGUL_SYLLABLE_TAG << 24) }, //0 HANGUL_SYLLABLE_TAG,/* AC00-D7AF*/
{0xD800, 0xDBFF, UCOL_SPECIAL_FLAG | (LEAD_SURROGATE_TAG << 24) }, //1 LEAD_SURROGATE_TAG, /* D800-DBFF*/
{0xDC00, 0xDFFF, UCOL_SPECIAL_FLAG | (TRAIL_SURROGATE_TAG << 24) }, //2 TRAIL_SURROGATE DC00-DFFF
{0x3400, 0x4DB5, UCOL_SPECIAL_FLAG | (CJK_IMPLICIT_TAG << 24) }, //3 CJK_IMPLICIT_TAG, /* 0x3400-0x4DB5*/
{0x4E00, 0x9FA5, UCOL_SPECIAL_FLAG | (CJK_IMPLICIT_TAG << 24) }, //4 CJK_IMPLICIT_TAG, /* 0x4E00-0x9FA5*/
{0xF900, 0xFA2D, UCOL_SPECIAL_FLAG | (CJK_IMPLICIT_TAG << 24) }, //5 CJK_IMPLICIT_TAG, /* 0xF900-0xFA2D*/
{0x20000, 0x2A6D6, UCOL_SPECIAL_FLAG | (CJK_IMPLICIT_TAG << 24) }, //6 CJK_IMPLICIT_TAG, /* 0x20000-0x2A6D6*/
{0x2F800, 0x2FA1D, UCOL_SPECIAL_FLAG | (CJK_IMPLICIT_TAG << 24) }, //7 CJK_IMPLICIT_TAG, /* 0x2F800-0x2FA1D*/
};
uint32_t i = 0;
for(i = 0; i<sizeof(ranges)/sizeof(ranges[0]); i++) {
ucmpe32_setRange32(t->mapping, ranges[i].start, ranges[i].end, ranges[i].value);
test_uca_ranges(t->mapping, ranges[i].start, ranges[i].end, ranges[i].value);
}
#if 0
uprv_uca_setRange(t, 0xAC00, 0xD7AF, UCOL_SPECIAL_FLAG | (HANGUL_SYLLABLE_TAG << 24), status); // HANGUL_SYLLABLE_TAG,/* AC00-D7AF*/
uprv_uca_setRange(t, 0xD800, 0xDBFF, UCOL_SPECIAL_FLAG | (LEAD_SURROGATE_TAG << 24), status); // LEAD_SURROGATE_TAG, /* D800-DBFF*/
uprv_uca_setRange(t, 0xDC00, 0xDFFF, UCOL_SPECIAL_FLAG | (TRAIL_SURROGATE_TAG << 24), status); // TRAIL_SURROGATE DC00-DFFF
uprv_uca_setRange(t, 0x3400, 0x4DB5, UCOL_SPECIAL_FLAG | (CJK_IMPLICIT_TAG << 24), status); // CJK_IMPLICIT_TAG, /* 0x3400-0x4DB5*/
uprv_uca_setRange(t, 0x4E00, 0x9FA5, UCOL_SPECIAL_FLAG | (CJK_IMPLICIT_TAG << 24), status); // CJK_IMPLICIT_TAG, /* 0x4E00-0x9FA5*/
uprv_uca_setRange(t, 0xF900, 0xFA2D, UCOL_SPECIAL_FLAG | (CJK_IMPLICIT_TAG << 24), status); // CJK_IMPLICIT_TAG, /* 0xF900-0xFA2D*/
uprv_uca_setRange(t, 0x2F800, 0x2FA1D, UCOL_SPECIAL_FLAG | (CJK_IMPLICIT_TAG << 24), status); // CJK_IMPLICIT_TAG, /* 0xF900-0xFA2D*/
uprv_uca_setRange(t, 0x20000, 0x2A6D6, UCOL_SPECIAL_FLAG | (CJK_IMPLICIT_TAG << 24), status); // CJK_IMPLICIT_TAG, /* 0xF900-0xFA2D*/
#endif
@ -641,14 +668,18 @@ write_uca_table(const char *filename,
// if element is a contraction, we want to add it to contractions
if(element->cSize > 1) { // this is a contraction
contractionCEs[noOfContractions][0] = element->cPoints[0];
contractionCEs[noOfContractions][1] = element->cPoints[1];
if(element->cSize > 2) { // the third one
contractionCEs[noOfContractions][2] = element->cPoints[2];
if(UTF_IS_LEAD(element->cPoints[0]) && UTF_IS_TRAIL(element->cPoints[1]) && element->cSize == 2) {
//fprintf(stdout, "Surrogate %04X %04X!\n", element->cPoints[0], element->cPoints[1]);
} else {
contractionCEs[noOfContractions][2] = 0;
contractionCEs[noOfContractions][0] = element->cPoints[0];
contractionCEs[noOfContractions][1] = element->cPoints[1];
if(element->cSize > 2) { // the third one
contractionCEs[noOfContractions][2] = element->cPoints[2];
} else {
contractionCEs[noOfContractions][2] = 0;
}
noOfContractions++;
}
noOfContractions++;
}
/* we're first adding to inverse, because addAnElement will reverse the order */