std::string FloatStr(const BigRat& q, const MachineInt& SigFig) { if (IsNegative(SigFig) || !IsSignedLong(SigFig) || IsZero(SigFig)) CoCoA_ERROR(ERR::BadArg, "FloatStr"); // if (IsOneDen(q)) return FloatStr(num(q), SigFig); return FloatStr(MantissaAndExponent10(q, SigFig), AsSignedLong(SigFig)); }
std::string DecimalStr(const BigInt& N, const MachineInt& DecimalPlaces) { if (IsNegative(DecimalPlaces) || !IsSignedLong(DecimalPlaces) || IsZero(DecimalPlaces)) CoCoA_ERROR(ERR::BadArg, "FixedStr"); return ToString(N); }
std::string FloatStr(const BigInt& N, const MachineInt& SigFig) { if (IsNegative(SigFig) || !IsSignedLong(SigFig) || IsZero(SigFig)) CoCoA_ERROR(ERR::BadArg, "FloatStr"); //??? if (abs(N) < power(10,SigFig)) return ToString(N); return FloatStr(MantissaAndExponent10(N, SigFig), AsSignedLong(SigFig)); }
LPPRoblemStatus lpengine::Solve() { LPPRoblemStatus current_status = LPPRoblemStatus::STATUS_NONE; if (IsSemiPositive(p_.b_) && IsNegative(p_.c_n_)) { std::cout << " -- Initial dictionary is Optimal" << std::endl; current_status = LPPRoblemStatus::STATUS_OPTIMAL; } else if (CheckDicfeasible(p_.x_b_hat_)) { std::cout << "-- Initial dictionary is primal feasible" << std::endl; p_.solver_type_ = LPSolverType::LP_SIMPLEX_PRIMAL; current_status = LPPRoblemStatus::STATUS_ITTERATING; while (current_status == LPPRoblemStatus::STATUS_ITTERATING) { current_status = PrimalSimplexStep(); } } else if (CheckDicfeasible(p_.z_n_hat_)) { std::cout << "-- Initial dictionary is dual feasible" << std::endl; p_.solver_type_ = LPSolverType::LP_SIMPLEX_DUAL; current_status = LPPRoblemStatus::STATUS_ITTERATING; while (current_status == LPPRoblemStatus::STATUS_ITTERATING) { current_status = DualSimplexStep(); } } else { std::cout << "-- Initial Primal and Dual dictionaries are not feasible" << std::endl << "-- Running PHASE1 algorithm" << std::endl; // modify the problem to feasible Dual problem and solve till optimal p_.ChangeToAuxiliary(); // p_.PrintDictionary(); std::cout << "--Aux dic is: "; if (CheckDicfeasible(p_.z_n_hat_)) { std::cout << "Dual feasible" << std::endl; } else { std::cout << "Error-> still not feasible" << std::endl; std::cout << "Exitting ..." << std::endl; current_status = LPPRoblemStatus::STATUS_INFEASIBLE; exit(EXIT_FAILURE); } p_.solver_type_ = LPSolverType::LP_SIMPLEX_DUAL; current_status = LPPRoblemStatus::STATUS_ITTERATING; while (current_status == LPPRoblemStatus::STATUS_ITTERATING) { current_status = DualSimplexStep(); } p_.PrintDictionary(); } // Problem is feasible and bounded at this point then do Simplex steps PrintStatusMsg(current_status); return current_status; }
EXPORT_C RInteger TInteger::InverseModL(const TInteger& aMod) const { assert(aMod.NotNegative()); RInteger result; if(IsNegative() || *this>=aMod) { RInteger temp = ModuloL(aMod); CleanupClosePushL(temp); result = temp.InverseModL(aMod); CleanupStack::PopAndDestroy(&temp); return result; } if(aMod.IsEven()) { if( !aMod || IsEven() ) { return RInteger::NewL(Zero()); } if( *this == One() ) { return RInteger::NewL(One()); } RInteger u = aMod.InverseModL(*this); CleanupClosePushL(u); if(!u) { result = RInteger::NewL(Zero()); } else { //calculates (aMod*(*this-u)+1)/(*this) result = MinusL(u); CleanupClosePushL(result); result *= aMod; ++result; result /= *this; CleanupStack::Pop(&result); } CleanupStack::PopAndDestroy(&u); return result; } result = RInteger::NewEmptyL(aMod.Size()); CleanupClosePushL(result); RInteger workspace = RInteger::NewEmptyL(aMod.Size() * 4); TUint k = AlmostInverse(result.Ptr(), workspace.Ptr(), Ptr(), Size(), aMod.Ptr(), aMod.Size()); DivideByPower2Mod(result.Ptr(), result.Ptr(), k, aMod.Ptr(), aMod.Size()); workspace.Close(); CleanupStack::Pop(&result); return result; }
const PolyRing& RingQQt(const MachineInt& NumIndets) { static vector<PolyRing*> QQtTable; if (IsNegative(NumIndets) || IsZero(NumIndets)) CoCoA_ERROR(ERR::NotPositive, "RingQQt"); const long n = AsSignedLong(NumIndets); if (n >= len(QQtTable)) QQtTable.resize(n+1); // will fill with NULL ptrs if (QQtTable[n] == 0/*NULL ptr*/) { vector<symbol> IndetNames; if (n == 1) IndetNames = symbols("t"); else IndetNames = SymbolRange("t",1,n); QQtTable[n] = new SparsePolyRing(NewPolyRing(RingQQ(), IndetNames)); // wasteful copy!! RegisterDtorForGlobal(QQtTable[n], &RingQQtDtor); } return *QQtTable[n]; }
Estimate Estimate::TruncateNegative(const char *origin) const { if (IsNegative()) throw DomainException(origin); if (IsPositive()) return *this; // (the theory says // we can't always give the correct DomainException, so we shouldn't try) // Get an interval centered at half the upper bound, with the same error. LongFloat center((m_Value + m_Error.AsLongFloat()) >> 1); Estimate a(center, ErrorEstimate(center)); assert(!a.IsPositive()); return a; //return a.SetError(a); }
/** * Creates a new buffer containing the big-endian binary representation of this * integer. * * Note that it does not support the exporting of negative integers. * * @return The new buffer. * * @leave KErrNegativeExportNotSupported If this instance is a negative integer. * */ EXPORT_C HBufC8* TInteger::BufferLC() const { if(IsNegative()) { User::Leave(KErrNegativeExportNotSupported); } TUint bytes = ByteCount(); HBufC8* buf = HBufC8::NewMaxLC(bytes); TUint8* bufPtr = (TUint8*)(buf->Ptr()); TUint8* regPtr = (TUint8*)Ptr(); // we internally store the number little endian, as a string we want it big // endian for(TUint i=0,j=bytes-1; i<bytes; ) { bufPtr[i++] = regPtr[j--]; } return buf; }
EXPORT_C TInteger& TInteger::operator--() { if (IsNegative()) { if (Increment(Ptr(), Size())) { CleanGrowL(2*Size()); (Ptr())[Size()/2]=1; } } else { if (Decrement(Ptr(), Size())) { this->CopyL(-1); } } return *this; }
EXPORT_C HBufC8* TInteger::BufferWithNoTruncationLC() const { if(IsNegative()) { User::Leave(KErrNegativeExportNotSupported); } TUint wordCount = Size(); TUint bytes = (wordCount)*WORD_SIZE; HBufC8* buf = HBufC8::NewMaxLC(bytes); TUint8* bufPtr = (TUint8*)(buf->Ptr()); TUint8* regPtr = (TUint8*)Ptr(); for(TUint i=0,j=bytes-1; i<bytes; ) { bufPtr[i++] = regPtr[j--]; } return buf; }
std::string DecimalStr(const BigRat& q, const MachineInt& DecimalPlaces) { if (IsNegative(DecimalPlaces) || !IsSignedLong(DecimalPlaces) || IsZero(DecimalPlaces)) CoCoA_ERROR(ERR::BadArg, "FixedStr"); if (IsOneDen(q)) return DecimalStr(num(q), DecimalPlaces); const long DigitsAfterPoint = AsSignedLong(DecimalPlaces); const BigInt N = RoundDiv(abs(num(q))*power(10,DigitsAfterPoint),den(q)); string digits = ToString(N); if (len(digits) < 1+DigitsAfterPoint) { digits = string(DigitsAfterPoint+1-len(digits), '0') + digits; } string ans; if (q < 0) ans = '-'; const long IntegerPart = len(digits) - DigitsAfterPoint; ans.insert(ans.end(), &digits[0], &digits[IntegerPart]); ans += '.'; ans.insert(ans.end(), &digits[IntegerPart], &digits[IntegerPart+DigitsAfterPoint]); return ans; }
void Light::SetIntensitySortValue(float distance) { // When sorting lights globally, give priority to directional lights so that they will be combined into the ambient pass if (!IsNegative()) { if (lightType_ != LIGHT_DIRECTIONAL) sortValue_ = Max(distance, M_MIN_NEARCLIP) / GetIntensityDivisor(); else sortValue_ = M_EPSILON / GetIntensityDivisor(); } else { // Give extra priority to negative lights in the global sorting order so that they're handled first, right after ambient. // Positive lights are added after them if (lightType_ != LIGHT_DIRECTIONAL) sortValue_ = -Max(distance, M_MIN_NEARCLIP) * GetIntensityDivisor(); else sortValue_ = -M_LARGE_VALUE * GetIntensityDivisor(); } }
bool NotNegative() const { return !IsNegative(); }
//----------------------------------------------------------------------------- // Inline Methods //----------------------------------------------------------------------------- inline bool PolyPlane::BehindPlane( const Vec3& point ) { return IsNegative( SignedDistance(point) ); }
/* item[n] = start + n * delta */ static Array MakeLinearList(Array start, Array end, int *n, Array delta) { int i, j; Array a_start = NULL, a_end = NULL, a_delta = NULL; int delstart = 0, delend = 0, deldelta = 0; Array alist[3]; Array output = NULL; int count = 1; int bytes; Type t; Category c; int rank; int shape[MAXSHAPE]; int nitems; int i_start, i_end, i_delta; float f_start, f_end, f_delta, f_count; Pointer dp; int *ip; Object in[MAXCOMPINPUTS]; /* hardcoded in compute */ Object out; String compstr = NULL; char cbuf[64]; Error rc; /* do this or die in compute */ for (i=0; i<MAXCOMPINPUTS; i++) in[i] = NULL; /* find common format of start, end, delta and check for 4 parms */ i = 0; if (start) alist[i++] = start; if (end) alist[i++] = end; if (delta) alist[i++] = delta; if (n) { count = *n; if (i == 3) { DXWarning("too many inputs specified; ignoring delta"); i--; delta = NULL; } } else if (i == 2) count = 2; if (i < 2) { DXSetError(ERROR_BAD_PARAMETER, "not enough inputs specified to generate a list"); return NULL; } if (!DXQueryArrayCommonV(&t, &c, &rank, shape, i, alist)) { DXAddMessage("start, end and/or delta"); return NULL; } /* shortcut the process here if the data is scalar integer or * scalar float. otherwise, if the data is vector or ubyte * or whatever, fall through and use Compute so we can increment * by irregular values. */ if (t != TYPE_INT && t != TYPE_FLOAT) goto complicated; if (c != CATEGORY_REAL || rank != 0) goto complicated; /* compute missing value(s): * start = end - ((count - 1) * delta) * end = start + ((count - 1) * delta) * count = ((end - start) / delta) + 1 * delta = (end - start) / (count - 1) */ /* convert to the common format */ if (start) a_start = DXArrayConvertV(start, t, c, rank, shape); if (end) a_end = DXArrayConvertV(end, t, c, rank, shape); if (delta) a_delta = DXArrayConvertV(delta, t, c, rank, shape); /* for integer, scalar lists */ if (t == TYPE_INT) { if (!start) { i_end = *(int *)DXGetArrayData(a_end); i_delta = *(int *)DXGetArrayData(a_delta); i_start = i_end - ((count - 1) * i_delta); } if (!end) { i_start = *(int *)DXGetArrayData(a_start); i_delta = *(int *)DXGetArrayData(a_delta); i_end = i_start + ((count - 1) * i_delta); } if (!delta) { /* if count == 1, generate a zero of the right type. otherwise * divide to figure out the right delta to make count-1 steps * between start and end. it's count-1 because if you want * N numbers between start and end, you have N-1 increments. */ i_start = *(int *)DXGetArrayData(a_start); i_end = *(int *)DXGetArrayData(a_end); if (count == 1) i_delta = 0; else i_delta = (i_end - i_start) / (count - 1); /* try to catch the case where delta ends up being 0 (like * because the inputs are int and the count is larger than * the difference between start and end). allow it to be zero * only if start == end; i suppose if you ask for 10 things * where start == end you should be able to get them. */ if (i_delta == 0 && i_start != i_end) { DXSetError(ERROR_BAD_PARAMETER, "count too large to generate list between start and end"); goto error; } } /* if all three arrays are there, count must be missing */ if (i == 3) { i_start = *(int *)DXGetArrayData(a_start); i_end = *(int *)DXGetArrayData(a_end); i_delta = *(int *)DXGetArrayData(a_delta); if (i_delta == 0) count = 1; else { if ((i_end >= i_start && i_delta > 0) || (i_end < i_start && i_delta < 0)) count = (int)(((double)i_end-i_start) / (double)i_delta) +1; else { if (i_delta < 0) DXSetError(ERROR_BAD_PARAMETER, "delta must be positive if start is less than end"); else DXSetError(ERROR_BAD_PARAMETER, "delta must be negative if end is less than start"); goto error; } } } output = (Array)DXNewRegularArray(TYPE_INT, 1, count, (Pointer)&i_start, (Pointer)&i_delta); } /* for float, scalar lists */ if (t == TYPE_FLOAT) { if (!start) { f_end = *(float *)DXGetArrayData(a_end); f_delta = *(float *)DXGetArrayData(a_delta); f_start = f_end - ((count - 1.0) * f_delta); } if (!end) { f_start = *(float *)DXGetArrayData(a_start); f_delta = *(float *)DXGetArrayData(a_delta); f_end = f_start + ((count - 1.0) * f_delta); } if (!delta) { /* if count == 1, generate a zero of the right type. otherwise * divide to figure out the right delta to make count-1 steps * between start and end. it's count-1 because if you want * N numbers between start and end, you have N-1 increments. */ f_start = *(float *)DXGetArrayData(a_start); f_end = *(float *)DXGetArrayData(a_end); if (count == 1) f_delta = 0.0; else f_delta = (f_end - f_start) / (count - 1.0); /* try to catch the case where delta ends up being 0 (like * because the inputs are int and the count is larger than * the difference between start and end). allow it to be zero * only if start == end; i suppose if you ask for 10 things * where start == end you should be able to get them. */ if (f_delta == 0.0 && f_start != f_end) { DXSetError(ERROR_BAD_PARAMETER, "count too large to generate list between start and end"); goto error; } } /* if all three arrays are there, count must be missing */ if (i == 3) { f_start = *(float *)DXGetArrayData(a_start); f_end = *(float *)DXGetArrayData(a_end); f_delta = *(float *)DXGetArrayData(a_delta); if (f_delta == 0.0) count = 1; else { if ((f_end >= f_start && f_delta > 0) || (f_end < f_start && f_delta < 0)) { /* the intermediate float variable below is to minimize * float round-off error. if delta is 0.1 and you * ask for a list between 0 and 1, it does the math in * double, the delta used is actually 0.10000001, and * you get counts = 10.9999999 instead of 11. when * converted directly to int it becomes just 10 and your * list ends at 0.9 instead of 1. * math in base 2 has some problems. */ f_count = ((f_end - f_start) / f_delta) +1; count = (int)f_count; } else { if (f_delta < 0) DXSetError(ERROR_BAD_PARAMETER, "delta must be positive if start is less than end"); else DXSetError(ERROR_BAD_PARAMETER, "delta must be negative if end is less than start"); goto error; } } } output = (Array)DXNewRegularArray(TYPE_FLOAT, 1, count, (Pointer)&f_start, (Pointer)&f_delta); } DXDelete((Object)a_start); DXDelete((Object)a_end); DXDelete((Object)a_delta); /* return Array */ return output; /* input is a vector, or a data type different from int or float. * use compute so this code doesn't have to be replicated for each * different shape and type. */ complicated: nitems = 1; for (j=0; j<rank; j++) nitems *= shape[j]; /* compute missing value(s): * start = end - ((count - 1) * delta) * end = start + ((count - 1) * delta) * count = ((end - start) / delta) + 1 * delta = (end - start) / (count - 1) */ if (!start) { compstr = DXNewString("$0 - (($1 - 1) * $2)"); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)end; in[3] = (Object)delta; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count)) goto error; /* i need to explain this - it's basically so if compute was * going to try to cache this, it could add a reference and * then later when i call delete the object won't get deleted * out from underneath compute. (i know compute doesn't cache * things, but a different module might.) */ DXReference((Object)compstr); DXReference(in[2]); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; DXDelete(in[2]); in[2] = NULL; if (rc == ERROR) goto error; start = (Array)out; delstart++; } if (!end) { compstr = DXNewString("$0 + (($1 - 1) * $2)"); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)start; in[3] = (Object)delta; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count)) goto error; DXReference((Object)compstr); DXReference(in[2]); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; DXDelete(in[2]); in[2] = NULL; if (rc == ERROR) goto error; end = (Array)out; delend++; } if (!delta) { /* if count == 1, generate a zero of the right type. otherwise * divide to figure out the right delta to make count-1 steps * between start and end. it's count-1 because if you want * N numbers between start and end, you have N-1 increments. */ if (count == 1) compstr = DXNewString("$1 - $1"); else compstr = DXNewString("($2 - $0) / ($1 - 1)"); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)start; in[3] = (Object)end; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count)) goto error; DXReference((Object)compstr); DXReference(in[2]); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; DXDelete(in[2]); in[2] = NULL; if (rc == ERROR) goto error; delta = (Array)out; deldelta++; /* try to catch the case where delta ends up being 0 (like * because the inputs are int and the count is larger than * the difference between start and end). allow it to be zero * only if start == end; i suppose if you ask for 10 things * where start == end you should be able to get them. */ if (IsZero(delta) && !IsEqual(start, end)) { DXSetError(ERROR_BAD_PARAMETER, "count too large to generate list between start and end"); goto error; } } /* if all three arrays are there, count must be missing */ if (i == 3) { char tbuf[512]; int firsttime = 1; int lastcount = 0; /* this loop allows us to to handle vectors or matricies as * well as scalars. it requires that the deltas compute to * a consistent count. like start=[0 2 4], end=[4 8 16], * would work if delta=[1 2 4] but not if delta was [1 2 2]. */ for (j=0; j < nitems; j++) { /* i think this code only works for vectors - i'm not sure * what it will do with rank=2 data. */ /* this point of this next compute expression: * if the delta is 0, don't divide by zero - the count is 1. * if the end is smaller than the start, the delta has to be * negative. if it's not, return -1. you can't generate a * negative count from the equations, so this is a safe signal. */ sprintf(tbuf, "float($2.%d) == 0.0 ? " " 1 : " " ( (($1.%d >= $0.%d) && ($2.%d > 0) || " " ($1.%d < $0.%d) && ($2.%d < 0)) ? " " int(float($1.%d - $0.%d) / float($2.%d)) + 1 : " " -1 ) ", j, j, j, j, j, j, j, j, j, j); compstr = DXNewString(tbuf); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)start; in[2] = (Object)end; in[3] = (Object)delta; DXReference((Object)compstr); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; if (rc == ERROR) goto error; if (!DXExtractInteger(out, &count)) { DXSetError(ERROR_BAD_PARAMETER, "can't compute number of items"); goto error; } DXDelete((Object)out); if (count == 0) continue; if (count < 0) { if (IsNegative(delta)) DXSetError(ERROR_BAD_PARAMETER, "delta must be positive if start is less than end"); else DXSetError(ERROR_BAD_PARAMETER, "delta must be negative if end is less than start"); goto error; } if (firsttime) { lastcount = count; firsttime = 0; } else { if (count != lastcount) { DXSetError(ERROR_BAD_PARAMETER, "inconsistent number of items required by inputs"); goto error; } } } } /* now have 4 consistant values - once again make sure they are * converted into an identical format. */ a_start = DXArrayConvertV(start, t, c, rank, shape); a_end = DXArrayConvertV(end, t, c, rank, shape); a_delta = DXArrayConvertV(delta, t, c, rank, shape); /* make empty array with n items */ output = DXNewArrayV(t, c, rank, shape); if (!output) goto error; if (!DXAddArrayData(output, 0, count, NULL)) goto error; dp = DXGetArrayData(output); if (!dp) goto error; /* foreach n */ /* call compute to add delta */ /* memcpy to right offset in array */ /* end */ bytes = DXGetItemSize(output); sprintf(cbuf, "%s($0 + ($1 * $2))", TypeName(t)); compstr = DXNewString(cbuf); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)a_start; in[3] = (Object)a_delta; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, NULL)) goto error; ip = (int *)DXGetArrayData((Array)in[2]); DXReference((Object)compstr); DXReference(in[2]); for (i=0; i<count; i++) { *ip = i; rc = m_Compute(in, &out); if (rc == ERROR) goto error; memcpy(INCVOID(dp, bytes*i), DXGetArrayData((Array)out), bytes); DXDelete((Object)out); } DXDelete((Object)compstr); DXDelete(in[2]); DXDelete((Object)a_start); DXDelete((Object)a_end); DXDelete((Object)a_delta); if (delstart) DXDelete((Object)start); if (delend) DXDelete((Object)end); if (deldelta) DXDelete((Object)delta); /* return Array */ return output; error: DXDelete((Object)output); DXDelete((Object)compstr); DXDelete((Object)a_start); DXDelete((Object)a_end); DXDelete((Object)a_delta); if (delstart) DXDelete((Object)start); if (delend) DXDelete((Object)end); if (deldelta) DXDelete((Object)delta); return NULL; }
double DigitEntry::GetDoubleValue() const { double value = GetPositiveInteger() + GetPositiveFractional(); return IsNegative() ? -value : value; }
int DigitEntry::GetIntegerValue() const { int value = GetPositiveInteger(); return IsNegative() ? -value : value; }
fixed DigitEntry::GetFixedValue() const { fixed value = fixed(GetPositiveInteger()) + GetPositiveFractional(); return IsNegative() ? -value : value; }
// The resulting hull will not contain interior points // Note that this is a cheap and cheerful implementation that can only handle // reasonably small point sets. However, except for the final hull it doesn't do any dynamic // memory allocation - all the work happens on the stack. Hull* Hull::MakeHull(int numPoints, const Point3* pPoints) { assert(numPoints >= 4); assert(pPoints); // check first 4 points are disjoint // TODO: make it search points so it can cope better with this assert(Length(pPoints[1] - pPoints[0]) > 0.01f); assert(Length(pPoints[2] - pPoints[0]) > 0.01f); assert(Length(pPoints[3] - pPoints[0]) > 0.01f); assert(Length(pPoints[2] - pPoints[1]) > 0.01f); assert(Length(pPoints[3] - pPoints[1]) > 0.01f); assert(Length(pPoints[3] - pPoints[2]) > 0.01f); s_pPoints = pPoints; // put all temp faces on a free list TmpFace tmpFaces[kMaxFaces]; s_firstFreeTmpFace = 0; s_firstUsedTmpFace = -1; s_pTmpFaces = tmpFaces; for (short i = 0; i < kMaxEdges; i++) { tmpFaces[i].m_index = i; tmpFaces[i].m_next = i + 1; } tmpFaces[kMaxFaces - 1].m_next = -1; // put all temp edges on a free list TmpEdge tmpEdges[kMaxEdges]; s_firstFreeTmpEdge = 0; s_firstUsedTmpEdge = -1; s_pTmpEdges = tmpEdges; for (short i = 0; i < kMaxEdges; i++) { tmpEdges[i].m_index = i; tmpEdges[i].m_next = i + 1; } tmpEdges[kMaxEdges - 1].m_next = -1; // make initial tetrahedron Plane plane = Plane(pPoints[0], pPoints[1], pPoints[2]); Scalar dot = Dot(plane, pPoints[3]); assert(Abs(dot) > 0.01f); // first 4 points are co-planar if (IsNegative(dot)) { AddTmpFace(0, 1, 2); AddTmpFace(1, 0, 3); AddTmpFace(0, 2, 3); AddTmpFace(2, 1, 3); } else { AddTmpFace(2, 1, (short)0); AddTmpFace(1, 2, 3); AddTmpFace(2, 0, 3); AddTmpFace(0, 1, 3); } // merge all remaining points for (int i = 4; i < numPoints; i++) if (RemoveVisibleFaces(pPoints[i]) > 0) FillHole(i); return MakeHullFromTemp(); }
int Hull::AddContactsHullHull(Separation& sep, const Point3* pVertsA, const Point3* pVertsB, const Transform& trA, const Transform& trB,const Hull& hullA,const Hull& hullB, HullContactCollector* hullContactCollector) { const int maxContacts = hullContactCollector->GetMaxNumContacts(); Vector3 normalWorld = sep.m_axis; // edge->edge contact is always a single point if (sep.m_separator == Separation::kFeatureBoth) { const Hull::Edge& edgeA = hullA.GetEdge(sep.m_featureA); const Hull::Edge& edgeB = hullB.GetEdge(sep.m_featureB); float ta, tb; Line la(pVertsA[edgeA.m_verts[0]], pVertsA[edgeA.m_verts[1]]); Line lb(pVertsB[edgeB.m_verts[0]], pVertsB[edgeB.m_verts[1]]); Intersect(la, lb, ta, tb); #ifdef VALIDATE_CONTACT_POINTS AssertPointInsideHull(contact.m_points[0].m_pos, trA, hullA); AssertPointInsideHull(contact.m_points[0].m_pos, trB, hullB); #endif Point3 posWorld = Lerp(la.m_start, la.m_end, ta); float depth = -sep.m_dist; Vector3 tangent = Normalize(pVertsA[edgeA.m_verts[1]] - pVertsA[edgeA.m_verts[0]]); sep.m_contact = hullContactCollector->BatchAddContactGroup(sep,1,normalWorld,tangent,&posWorld,&depth); } // face->face contact is polygon else { short faceA = sep.m_featureA; short faceB = sep.m_featureB; Vector3 tangent; // find face of hull A that is most opposite contact axis // TODO: avoid having to transform planes here if (sep.m_separator == Separation::kFeatureB) { const Hull::Edge& edgeB = hullB.GetEdge(hullB.GetFaceFirstEdge(faceB)); tangent = Normalize(pVertsB[edgeB.m_verts[1]] - pVertsB[edgeB.m_verts[0]]); Scalar dmin = Scalar::Consts::MaxValue; for (short face = 0; face < hullA.m_numFaces; face++) { Vector3 normal = hullA.GetPlane(face).GetNormal() * trA; Scalar d = Dot(normal, sep.m_axis); if (d < dmin) { dmin = d; faceA = face; } } } else { const Hull::Edge& edgeA = hullA.GetEdge(hullA.GetFaceFirstEdge(faceA)); tangent = Normalize(pVertsA[edgeA.m_verts[1]] - pVertsA[edgeA.m_verts[0]]); Scalar dmin = Scalar::Consts::MaxValue; for (short face = 0; face < hullB.m_numFaces; face++) { Vector3 normal = hullB.GetPlane(face).GetNormal() * trB; Scalar d = Dot(normal, -sep.m_axis); if (d < dmin) { dmin = d; faceB = face; } } } Point3 workspace[2][Hull::kMaxVerts]; // setup initial clip face (minimizing face from hull B) int numContacts = 0; for (short edge = hullB.GetFaceFirstEdge(faceB); edge != -1; edge = hullB.GetFaceNextEdge(faceB, edge)) workspace[0][numContacts++] = pVertsB[ hullB.GetEdgeVertex0(faceB, edge) ]; // clip polygon to back of planes of all faces of hull A that are adjacent to witness face Point3* pVtxIn = workspace[0]; Point3* pVtxOut = workspace[1]; #if 0 for (short edge = hullA.GetFaceFirstEdge(faceA); edge != -1; edge = hullA.GetFaceNextEdge(faceA, edge)) { Plane planeA = hullA.GetPlane( hullA.GetEdgeOtherFace(edge, faceA) ) * trA; numContacts = ClipFace(numContacts, &pVtxIn, &pVtxOut, planeA); } #else for (short f = 0; f < hullA.GetNumFaces(); f++) { Plane planeA = hullA.GetPlane(f) * trA; numContacts = ClipFace(numContacts, &pVtxIn, &pVtxOut, planeA); } #endif // only keep points that are behind the witness face Plane planeA = hullA.GetPlane(faceA) * trA; float depths[Hull::kMaxVerts]; int numPoints = 0; for (int i = 0; i < numContacts; i++) { Scalar d = Dot(planeA, pVtxIn[i]); if (IsNegative(d)) { depths[numPoints] = (float)-d; pVtxIn[numPoints] = pVtxIn[i]; #ifdef VALIDATE_CONTACT_POINTS AssertPointInsideHull(pVtxIn[numPoints], trA, hullA); AssertPointInsideHull(pVtxIn[numPoints], trB, hullB); #endif numPoints++; } } //we can also use a persistentManifold/reducer class // keep maxContacts points at most if (numPoints > 0) { if (numPoints > maxContacts) { int step = (numPoints << 8) / maxContacts; numPoints = maxContacts; for (int i = 0; i < numPoints; i++) { int nth = (step * i) >> 8; depths[i] = depths[nth]; pVtxIn[i] = pVtxIn[nth]; #ifdef VALIDATE_CONTACT_POINTS AssertPointInsideHull(contact.m_points[i].m_pos, trA, hullA); AssertPointInsideHull(contact.m_points[i].m_pos, trB, hullB); #endif } } sep.m_contact = hullContactCollector->BatchAddContactGroup(sep,numPoints,normalWorld,tangent,pVtxIn,depths); } return numPoints; }
std::string ScientificStr(const BigRat& q, const MachineInt& SigFig) { if (IsNegative(SigFig) || !IsSignedLong(SigFig) || IsZero(SigFig)) CoCoA_ERROR(ERR::BadArg, "ScientificStr"); return ScientificStr(MantissaAndExponent10(q, SigFig), AsSignedLong(SigFig)); }
static bool IsNegative(FloatConstant* value) { return IsNegative(value->Value(), value->GetType()->GetSubtype()); }