/* * NOTICE and LICENSE for Tecplot Input/Output Library (TecIO) - OpenFOAM * * Copyright (C) 1988-2009 Tecplot, Inc. All rights reserved worldwide. * * Tecplot hereby grants OpenCFD limited authority to distribute without * alteration the source code to the Tecplot Input/Output library, known * as TecIO, as part of its distribution of OpenFOAM and the * OpenFOAM_to_Tecplot converter. Users of this converter are also hereby * granted access to the TecIO source code, and may redistribute it for the * purpose of maintaining the converter. However, no authority is granted * to alter the TecIO source code in any form or manner. * * This limited grant of distribution does not supersede Tecplot, Inc.'s * copyright in TecIO. Contact Tecplot, Inc. for further information. * * Tecplot, Inc. * 3535 Factoria Blvd, Ste. 550 * Bellevue, WA 98006, USA * Phone: +1 425 653 1200 * http://www.tecplot.com/ * */ #include "stdafx.h" #include "MASTER.h" #define TECPLOTENGINEMODULE /* ***************************************************************** ***************************************************************** ******* ******** ****** Copyright (C) 1988-2008 Tecplot, Inc. ******* ******* ******** ***************************************************************** ***************************************************************** */ #define SETMODULE #include "GLOBAL.h" #include "TASSERT.h" #include "Q_UNICODE.h" #include "ALLOC.h" #include "SET.h" /* * SET FUNCTIONS * */ #if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ #if InitNumZones > InitNumVars #else #endif #if ZoneExpansionFactor > VarExpansionFactor #else #endif #else #define SetInitSize (PadOut(1,SetBitSize)) #define SetExpansionFactor 2 #endif using namespace tecplot::strutil; /* */ Set_pa AllocSet(Boolean_t show_error_msg) { Set_pa Set = ALLOC_ITEM(struct _Set_a, "Set header"); if (Set) { Set->size = SetInitSize; Set->data = ALLOC_ARRAY(SetInitSize / SetBitSize, SetData_t, "Set data"); if (Set->data == NULL) DeallocSet(&Set); else ClearSet(Set); } if ((Set == NULL) && show_error_msg) { # if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ # else fprintf(stderr, "Out of memory for sets"); # endif } return Set; } /* AllocSet() */ /* */ void DeallocSet(Set_pa *Set) { if (Set && *Set) { if ((*Set)->data) FREE_ARRAY((*Set)->data, "Set data"); FREE_ITEM(*Set, "Set header"); *Set = NULL; } } /* DeallocSet() */ /** * This function adapts the DeallocSet function to work with the * ArrayList's deallocation callback. */ Boolean_t SetItemDestructor(void *ItemRef, ArbParam_t ClientData) { Set_pa *SetRef = (Set_pa *)ItemRef; REQUIRE(VALID_REF(SetRef)); REQUIRE(VALID_REF(*SetRef) || *SetRef == NULL); if (*SetRef != NULL) DeallocSet(SetRef); ENSURE(*SetRef == NULL); return TRUE; } /* */ Boolean_t ExpandSet(Set_pa Set, SetIndex_t max_val, Boolean_t show_error_msg) { SetData_t *data; long new_size; REQUIRE(max_val >= 0); if (!Set) { if (show_error_msg) { # if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ # else fprintf(stderr, "Null Set expand"); # endif } return FALSE; } if (max_val <= Set->size) return TRUE; new_size = Set->size; while (new_size < max_val) new_size *= SetExpansionFactor; new_size = PadOut(new_size, SetBitSize); data = ALLOC_ARRAY(new_size / SetBitSize, SetData_t, "new Set data"); if (!data) { if (show_error_msg) { # if defined TECPLOTKERNEL /* CORE SOURCE CODE REMOVED */ # else fprintf(stderr, "Out of memory for sets"); # endif } return FALSE; } size_t old_set_size_in_bytes = sizeof(data[0]) * (Set->size / SetBitSize); memcpy(data, Set->data, old_set_size_in_bytes); size_t new_set_size_in_bytes = sizeof(data[0]) * (new_size / SetBitSize); size_t numBytesToReset = new_set_size_in_bytes - old_set_size_in_bytes; memset(((char*)data) + old_set_size_in_bytes, 0, numBytesToReset); FREE_ARRAY(Set->data, "old Set data"); Set->data = data; Set->size = new_size; return TRUE; } /* ExpandSet() */ /* */ Boolean_t CopySet(Set_pa dst, Set_pa src, Boolean_t show_error_msg) { if (dst && dst->data && src && src->data && ExpandSet(dst, src->size, show_error_msg)) { SetIndex_t src_size_in_words = src->size / SetBitSize; size_t numBytesToCopy = sizeof(dst->data[0]) * src_size_in_words; memcpy(dst->data, src->data, numBytesToCopy); SetIndex_t dst_size_in_words = dst->size / SetBitSize; CHECK(dst_size_in_words>=src_size_in_words); // ...guaranteed by above ExpandSet() call size_t numBytesToReset = sizeof(dst->data[0]) * (dst_size_in_words - src_size_in_words); memset((char*)(dst->data + src_size_in_words), 0, numBytesToReset); return TRUE; } else return FALSE; } /* CopySet() */ /* */ Boolean_t AppendSet(Set_pa dst, Set_pa src, Boolean_t show_error_msg) { if (dst && dst->data && src && src->data) { SetIndex_t member; ForAllMembersInSet(member, src) { if (!AddToSet(dst, member, TRUE)) return FALSE; } return TRUE; } else return FALSE; } /* AppendSet() */ /* */ void ClearSet(Set_pa Set) { if (Set && Set->data) memset(Set->data, 0, Set->size / SetBitSize * sizeof(Set->data[0])); } /* ClearSet() */ #if defined USE_FUNCTIONS_FOR_SETS /* */ Boolean_t AddToSet(Set_pa Set, SetIndex_t member, Boolean_t show_error_msg) { REQUIRE(member >= 0); if (Set && Set->data && ((member + 1 <= Set->size) || ExpandSet(Set, member + 1, show_error_msg))) { SetIndex_t word = member / SetBitSize; SetData_t bit = (SetData_t)1 << (member % SetBitSize); Set->data[word] |= bit; return TRUE; } else return FALSE; } /* AddToSet() */ #endif /* */ void RemoveFromSet(Set_pa Set, SetIndex_t member) { REQUIRE(member >= 0); if (Set && (member < Set->size) && Set->data) { SetIndex_t word = member / SetBitSize; SetData_t bit = (SetData_t)1 << (member % SetBitSize); Set->data[word] &= (((SetData_t) - 1) ^ bit); } } /* RemoveFromSet() */ /** * Similar to RemoveFromSet except it shifts the Set. */ void DeleteSetMember(Set_pa Set, SetIndex_t Member) { SetIndex_t LastMember; REQUIRE(VALID_REF(Set)); REQUIRE(Member >= 0); LastMember = GetPrevMember(Set, BAD_SET_VALUE); if (Member <= LastMember) { ShiftSet(Set, Member + 1, LastMember, -1); RemoveFromSet(Set, LastMember); } } /** * Similar to AddToSet except that if the new member is within the currently * defined set the members are shifted accordingly. */ Boolean_t InsertSetMember(Set_pa Set, SetIndex_t Member, Boolean_t ShowErrMsg) { Boolean_t IsOk = TRUE; SetIndex_t OrigLastMember; REQUIRE(VALID_REF(Set)); /* first, determine if we need to shift the set */ OrigLastMember = GetPrevMember(Set, BAD_SET_VALUE); if (Member <= OrigLastMember) { IsOk = ExpandSet(Set, (OrigLastMember + 1) + 1, ShowErrMsg); ShiftSet(Set, Member, OrigLastMember, 1); } if (IsOk) IsOk = AddToSet(Set, Member, ShowErrMsg); ENSURE(VALID_BOOLEAN(IsOk)); return IsOk; } #if defined USE_FUNCTIONS_FOR_SETS /* */ Boolean_t InSet(Set_pa Set, SetIndex_t member) { /* * Sometimes InSet is called with negative numbers. This is not correct, but * its what we have to work with. Maybe some day, we can make this assertion. REQUIRE(member>=0); */ if (Set && (0 <= member && member < Set->size)) { SetIndex_t word = member / SetBitSize; SetData_t bit = (SetData_t)1 << (member % SetBitSize); return (Set->data[word]&bit) != 0; } else return FALSE; } /* InSet() */ #endif /* */ Boolean_t IsEmpty(Set_pa Set) { if (Set && Set->data) { SetIndex_t set_size_in_words = Set->size / SetBitSize; SetIndex_t word; for (word = 0; word < set_size_in_words; word++) if (Set->data[word] != 0) return FALSE; } return TRUE; } /* IsEmpty() */ /* */ Boolean_t HasVoids(Set_pa Set) { Boolean_t Result = FALSE; SetIndex_t ContiguousMember = 0; SetIndex_t Member = 0; REQUIRE(VALID_REF(Set)); /* look for voids in the set */ ForAllMembersInSet(Member, Set) { if (Member == ContiguousMember) { ContiguousMember++; } else { Result = TRUE; break; } } ENSURE(VALID_BOOLEAN(Result)); return Result; } /* */ SetIndex_t MemberCount(Set_pa Set) { SetIndex_t count = 0; if (Set && Set->data) { SetIndex_t set_size_in_words = Set->size / SetBitSize; SetIndex_t word; for (word = 0; word < set_size_in_words; word++) { SetData_t word_val = Set->data[word]; while (word_val) { if (word_val&1) count++; word_val = word_val >> 1; } } } return count; } /* MemberCount() */ /* */ SetIndex_t GetNextMember(Set_pa Set, SetIndex_t start_at) { SetIndex_t next_member = BAD_SET_VALUE; if (Set && Set->data) { SetIndex_t set_size_in_words = Set->size / SetBitSize; SetIndex_t word; SetData_t word_val = 0; int bit; if (start_at == BAD_SET_VALUE) { word = 0; bit = 0; if (word < set_size_in_words) word_val = Set->data[0]; } else if (start_at + 1 < Set->size) { word = (start_at + 1) / SetBitSize; bit = (start_at + 1) % SetBitSize; if (word < set_size_in_words) word_val = Set->data[word] >> bit; } else { return BAD_SET_VALUE; } while ((word < set_size_in_words) && (word_val == 0)) { word++; bit = 0; if (word < set_size_in_words) word_val = Set->data[word]; } if (word < set_size_in_words) { while (!(word_val&1)) { word_val >>= 1; bit++; } next_member = word * SetBitSize + bit; } } return next_member; } /* GetNextMember() */ /* */ SetIndex_t GetPrevMember(Set_pa Set, SetIndex_t start_at) { SetIndex_t next_member = BAD_SET_VALUE; if (Set && Set->data) { SetIndex_t set_size_in_words = Set->size / SetBitSize; SetIndex_t word; SetData_t word_val = 0; int bit; if (start_at == BAD_SET_VALUE) { word = set_size_in_words - 1; bit = SetBitSize - 1; if (word >= 0) word_val = Set->data[word]; } else if (start_at > 0) { word = (start_at - 1) / SetBitSize; bit = (start_at - 1) % SetBitSize; if (word >= 0) word_val = Set->data[word] << (SetBitSize - bit - 1); } else { return BAD_SET_VALUE; } while ((word >= 0) && (word_val == 0)) { word--; bit = SetBitSize - 1; if (word >= 0) word_val = Set->data[word] << (SetBitSize - bit - 1); } if (word >= 0) { while (!(word_val&SetLastBit)) { word_val <<= 1; bit--; } next_member = word * SetBitSize + bit; } } return next_member; } /* GetPrevMember() */ /* */ Boolean_t EqualSets(Set_pa set1, Set_pa set2) { SetIndex_t set1_size_in_words, set2_size_in_words, min_set_size_in_words, ii; if (!set1 || !set2) return FALSE; set1_size_in_words = set1->size / SetBitSize; set2_size_in_words = set2->size / SetBitSize; min_set_size_in_words = MIN(set1_size_in_words, set2_size_in_words); for (ii = 0; ii < min_set_size_in_words; ii++) if (set1->data[ii] != set2->data[ii]) return FALSE; for (ii = min_set_size_in_words; ii < set1_size_in_words; ii++) if (set1->data[ii] != 0) return FALSE; for (ii = min_set_size_in_words; ii < set2_size_in_words; ii++) if (set2->data[ii] != 0) return FALSE; return TRUE; } /* EqualSets() */ Boolean_t IsSubSet(Set_pa childset, Set_pa parentset) { SetIndex_t s; ForAllMembersInSet(s, childset) { if (!InSet(parentset, s)) return (FALSE); } return (TRUE); } /* IsSubSet() */ /* * functions added 11/7 by byron. These are roughed in for now and could * stand to be optimized later..... */ /* * Return the number of members in a set that preceed a given member. */ SetIndex_t MemberOffset(Set_pa Set, SetIndex_t Member) { SetIndex_t I; SetIndex_t Offset = -1; if (InSet(Set, Member)) { for (I = 0; I <= Member; I++) { if (InSet(Set, I)) Offset++; } } return (Offset); } /* * Return the position in the set of the nth member of a set. */ SetIndex_t OffsetMember(Set_pa Set, SetIndex_t Offset) { SetIndex_t I; SetIndex_t Member = BAD_SET_VALUE; for (I = 0; I <= Offset; I++) { Member = GetNextMember(Set, Member); if (Member == BAD_SET_VALUE) break; } return (Member); } Boolean_t CopySetMember(Set_pa DstSet, SetIndex_t DstOffset, Set_pa SrcSet, SetIndex_t SrcOffset) { if (InSet(SrcSet, SrcOffset)) return (AddToSet(DstSet, DstOffset, TRUE)); else RemoveFromSet(DstSet, DstOffset); return (TRUE); } /* * Initial: * v---ShiftPos1 v--ShiftPos2 * +-------------------------------------+ * | | | | | | | |x| | | | | | | |x| | | | * +-------------------------------------+ * * Shift +2 * v---ShiftPos1 v--ShiftPos2 * +-------------------------------------+ * | | | | | | | | | |x| | | | | | | |x| | * +-------------------------------------+ * * * Shift all bits between ShiftPos1 and ShiftPos2 * by ShiftAmount. The bits that the shift * replaces fill in the hole left by the shift * * */ void ShiftSet(Set_pa Set, SetIndex_t ShiftPos1, SetIndex_t ShiftPos2, SetIndex_t ShiftAmount) { Set_pa NewSet; SetIndex_t DPos; SetIndex_t SPos; if ((Set == NULL) || (IsEmpty(Set))) return; NewSet = AllocSet(TRUE); if (NewSet == NULL) return; if (!CopySet(NewSet, Set, TRUE)) return; if (ShiftAmount < 0) { DPos = ShiftPos2; SPos = ShiftPos1 - 1; while (DPos > ShiftPos2 + ShiftAmount) CopySetMember(NewSet, DPos--, Set, SPos--); SPos = ShiftPos2; while (SPos >= ShiftPos1) CopySetMember(NewSet, DPos--, Set, SPos--); } else if (ShiftAmount > 0) { DPos = ShiftPos1; SPos = ShiftPos2 + 1; while (DPos < ShiftPos1 + ShiftAmount) CopySetMember(NewSet, DPos++, Set, SPos++); SPos = ShiftPos1; while (SPos <= ShiftPos2) CopySetMember(NewSet, DPos++, Set, SPos++); } CopySet(Set, NewSet, TRUE); DeallocSet(&NewSet); }