inline void callFunction(mxArray* plhs[], const mxArray*prhs[],const long nrhs, const long nlhs) { if (nrhs==3) { if (!mexCheckType<T>(prhs[0])) mexErrMsgTxt("type of argument 1 is not consistent"); if (mxIsSparse(prhs[0])) mexErrMsgTxt("argument 1 should be full"); if (!mexCheckType<T>(prhs[1])) mexErrMsgTxt("type of argument 2 is not consistent"); if (mxIsSparse(prhs[1])) mexErrMsgTxt("argument 2 should be full"); if (!mxIsStruct(prhs[2])) mexErrMsgTxt("argument 3 should be struct"); T* prX = reinterpret_cast<T*>(mxGetPr(prhs[0])); const mwSize* dimsX=mxGetDimensions(prhs[0]); long n=static_cast<long>(dimsX[0]); long M=static_cast<long>(dimsX[1]); T* prD = reinterpret_cast<T*>(mxGetPr(prhs[1])); const mwSize* dimsD=mxGetDimensions(prhs[1]); long nD=static_cast<long>(dimsD[0]); long K=static_cast<long>(dimsD[1]); if (n != nD) mexErrMsgTxt("argument sizes are not consistent"); T lambda = getScalarStruct<T>(prhs[2],"lambda"); T lambda2 = getScalarStructDef<T>(prhs[2],"lambda2",0); long L = getScalarStructDef<long>(prhs[2],"L",K); long length_path = MAX(2,getScalarStructDef<long>(prhs[2],"length_path",4*L)); long numThreads = getScalarStructDef<long>(prhs[2],"numThreads",-1); bool pos = getScalarStructDef<bool>(prhs[2],"pos",false); bool verbose = getScalarStructDef<bool>(prhs[2],"verbose",false); bool ols = getScalarStructDef<bool>(prhs[2],"ols",false); bool cholesky = ols || getScalarStructDef<bool>(prhs[2],"cholesky",false); constraint_type mode = (constraint_type)getScalarStructDef<long>(prhs[2],"mode",PENALTY); if (L > n && !(mode == PENALTY && isZero(lambda) && !pos && lambda2 > 0)) { // if (verbose) // printf("L is changed to %ld\n",n); L=n; } if (L > K) { // if (verbose) // printf("L is changed to %ld\n",K); L=K; } Matrix<T> X(prX,n,M); Matrix<T> D(prD,n,K); SpMatrix<T> alpha; if (nlhs == 2) { Matrix<T> norm(K,length_path); norm.setZeros(); if (cholesky) { lasso<T>(X,D,alpha,L,lambda,lambda2,mode,pos,ols,numThreads,&norm,length_path); } else { lasso2<T>(X,D,alpha,L,lambda,lambda2,mode,pos,numThreads,&norm,length_path); } Vector<T> norms_col; norm.norm_2_cols(norms_col); long length=1; for (long i = 1; i<norms_col.n(); ++i) if (norms_col[i]) ++length; plhs[1]=createMatrix<T>(K,length); T* pr_norm=reinterpret_cast<T*>(mxGetPr(plhs[1])); Matrix<T> norm2(pr_norm,K,length); Vector<T> col; for (long i = 0; i<length; ++i) { norm2.refCol(i,col); norm.copyCol(i,col); } } else { if (cholesky) { lasso<T>(X,D,alpha,L,lambda,lambda2,mode,pos,ols,numThreads,NULL,length_path); } else { lasso2<T>(X,D,alpha,L,lambda,lambda2,mode,pos,numThreads,NULL,length_path); } } convertSpMatrix(plhs[0],alpha.m(),alpha.n(),alpha.n(), alpha.nzmax(),alpha.v(),alpha.r(),alpha.pB()); } else { if (!mexCheckType<T>(prhs[0])) mexErrMsgTxt("type of argument 1 is not consistent"); if (mxIsSparse(prhs[0])) mexErrMsgTxt("argument 1 should be full"); if (!mexCheckType<T>(prhs[1])) mexErrMsgTxt("type of argument 2 is not consistent"); if (mxIsSparse(prhs[1])) mexErrMsgTxt("argument 2 should be full"); if (!mexCheckType<T>(prhs[2])) mexErrMsgTxt("type of argument 3 is not consistent"); if (mxIsSparse(prhs[2])) mexErrMsgTxt("argument 3 should be full"); if (!mxIsStruct(prhs[3])) mexErrMsgTxt("argument 4 should be struct"); T* prX = reinterpret_cast<T*>(mxGetPr(prhs[0])); const mwSize* dimsX=mxGetDimensions(prhs[0]); long n=static_cast<long>(dimsX[0]); long M=static_cast<long>(dimsX[1]); T* prG = reinterpret_cast<T*>(mxGetPr(prhs[1])); const mwSize* dimsD=mxGetDimensions(prhs[1]); long K1=static_cast<long>(dimsD[0]); long K2=static_cast<long>(dimsD[1]); if (K1 != K2) mexErrMsgTxt("argument sizes are not consistent"); long K=K1; T* prDtR = reinterpret_cast<T*>(mxGetPr(prhs[2])); const mwSize* dimsDtR=mxGetDimensions(prhs[2]); long K3=static_cast<long>(dimsDtR[0]); long M2=static_cast<long>(dimsDtR[1]); if (K1 != K3) mexErrMsgTxt("argument sizes are not consistent"); if (M != M2) mexErrMsgTxt("argument sizes are not consistent"); T lambda = getScalarStruct<T>(prhs[3],"lambda"); T lambda2 = getScalarStructDef<T>(prhs[3],"lambda2",0); long L = getScalarStructDef<long>(prhs[3],"L",K1); long length_path = getScalarStructDef<long>(prhs[3],"length_path",4*L); long numThreads = getScalarStructDef<long>(prhs[3],"numThreads",-1); bool pos = getScalarStructDef<bool>(prhs[3],"pos",false); bool verbose = getScalarStructDef<bool>(prhs[3],"verbose",true); bool ols = getScalarStructDef<bool>(prhs[3],"ols",false); bool cholesky = ols || getScalarStructDef<bool>(prhs[3],"cholesky",false); constraint_type mode = (constraint_type)getScalarStructDef<long>(prhs[3],"mode",PENALTY); if (L > n && !(mode == PENALTY && isZero(lambda) && !pos && lambda2 > 0)) { // if (verbose) // printf("L is changed to %ld\n",n); L=n; } if (L > K) { // if (verbose) // printf("L is changed to %ld\n",K); L=K; } Matrix<T> X(prX,n,M); Matrix<T> G(prG,K,K); Matrix<T> DtR(prDtR,K,M); SpMatrix<T> alpha; if (nlhs == 2) { Matrix<T> norm(K,length_path); norm.setZeros(); if (cholesky) { lasso<T>(X,G,DtR,alpha,L,lambda,mode,pos,ols,numThreads,&norm,length_path); } else { lasso2<T>(X,G,DtR,alpha,L,lambda,mode,pos,numThreads,&norm,length_path); } Vector<T> norms_col; norm.norm_2_cols(norms_col); long length=1; for (long i = 1; i<norms_col.n(); ++i) if (norms_col[i]) ++length; plhs[1]=createMatrix<T>(K,length); T* pr_norm=reinterpret_cast<T*>(mxGetPr(plhs[1])); Matrix<T> norm2(pr_norm,K,length); Vector<T> col; for (long i = 0; i<length; ++i) { norm2.refCol(i,col); norm.copyCol(i,col); } } else { if (cholesky) { lasso<T>(X,G,DtR,alpha,L,lambda,mode,pos,ols,numThreads,NULL,length_path); } else { lasso2<T>(X,G,DtR,alpha,L,lambda,mode,pos,numThreads,NULL,length_path); } } convertSpMatrix(plhs[0],alpha.m(),alpha.n(),alpha.n(), alpha.nzmax(),alpha.v(),alpha.r(),alpha.pB()); } }

static feeReturn feeGenPrivate(pubKeyInst *pkinst, const unsigned char *passwd, unsigned passwdLen, char hashPasswd) { unsigned privLen; // desired size of pkinst->privData feeHash *hash = NULL; // a malloc'd array unsigned digestLen; // size of MD5 digest unsigned dataSize; // min(privLen, passwdLen) unsigned numDigests = 0; unsigned i; unsigned char *cp; unsigned toMove; // for this digest unsigned moved; // total digested unsigned char *digest = NULL; unsigned char *privData = NULL; // temp, before modg(curveOrder) giant corder; // lesser of two curve orders /* * generate privData which is just larger than the smaller * curve order. * We'll take the result mod the curve order when we're done. * Note we do *not* have to free corder - it's a pointer to a giant * in pkinst->cp. */ corder = lesserX1Order(pkinst->cp); CKASSERT(!isZero(corder)); privLen = (bitlen(corder) / 8) + 1; if(!hashPasswd) { /* * Caller trusts the incoming entropy. Verify it's big enough and proceed. */ if(passwdLen < privLen) { return FR_ShortPrivData; } privLen = passwdLen; privData = (unsigned char *)passwd; goto finishUp; } if(passwdLen < 2) { return FR_IllegalArg; } /* * Calculate how many MD5 digests we'll generate. */ if(privLen > passwdLen) { dataSize = passwdLen; } else { dataSize = privLen; } digestLen = feeHashDigestLen(); numDigests = (dataSize + digestLen - 1) / digestLen; hash = (void**) fmalloc(numDigests * sizeof(feeHash)); for(i=0; i<numDigests; i++) { hash[i] = feeHashAlloc(); } /* * fill digests with passwd data, digestLen (or resid length) * at a time. If (passwdLen > privLen), last digest will hash all * remaining passwd data. */ cp = (unsigned char *)passwd; moved = 0; for(i=0; i<numDigests; i++) { if(i == (numDigests - 1)) { // last digest toMove = passwdLen - moved; } else { toMove = digestLen; } feeHashAddData(hash[i], cp, toMove); cp += toMove; moved += toMove; } /* * copy digests to privData, up to privLen bytes. Pad with * additional copies of digests if necessary. */ privData = (unsigned char*) fmalloc(privLen); cp = privData; moved = 0; i = 0; // digest number for(moved=0; moved<privLen; ) { if((moved + digestLen) > privLen) { toMove = privLen - moved; } else { toMove = digestLen; } digest = feeHashDigest(hash[i++]); bcopy(digest, cp, toMove); cp += toMove; moved += toMove; if(i == numDigests) { i = 0; // wrap to 0, start padding } } finishUp: /* * Convert to giant, justify result to within [2, lesserX1Order] */ pkinst->privGiant = giant_with_data(privData, privLen); #if FEE_DEBUG if(isZero(pkinst->privGiant)) { printf("feeGenPrivate: privData = 0!\n"); } #endif // FEE_DEBUG lesserX1OrderJustify(pkinst->privGiant, pkinst->cp); if(hashPasswd) { memset(privData, 0, privLen); ffree(privData); for(i=0; i<numDigests; i++) { feeHashFree(hash[i]); } ffree(hash); } return FR_Success; }

Spectrum MisPathTracer::Li(const Scene* scene, Sampler& sampler, Ray3f& ray) const { Spectrum L(0.f); Intersection its; Spectrum throughput(1.f); bool isSpecular = true; while (true) { if (!scene->rayIntersect(ray, its)) break; if (isSpecular && its.shape->getEmitter()) { EmitterSample emittanceSample(ray.o, its.p, its.shFrame.n); L += throughput * its.shape->getEmitter()->eval(emittanceSample); } if (its.shape->getBSDF()->getType() != BSDFType::Delta) { EmitterSample emSam(its.p); auto lightSpec = scene->sampleEmitter(its, sampler, emSam); float cosFactor = its.shFrame.n.dot(emSam.wi); if (!(cosFactor <= 0.f || lightSpec.isZero() || scene->rayIntersect(emSam.shadowRay))) { BSDFSample bsdfSam(its.p, its.toLocal(-ray.d), its.toLocal(emSam.wi)); bsdfSam.measure = Measure::SolidAngle; auto bsdfSpec = its.shape->getBSDF()->eval(bsdfSam); float pdfEm = emSam.pdf; float pdfBsdf = its.shape->getBSDF()->pdf(bsdfSam); L += throughput * bsdfSpec * lightSpec * cosFactor * miWeight(pdfEm, pdfBsdf); } } BSDFSample bsdfSample(its.p, its.toLocal(-ray.d)); auto bsdf = its.shape->getBSDF()->sample(bsdfSample, sampler); Intersection bsdfIts; Ray3f bsdfRay(its.p, its.toWorld(bsdfSample.wo)); if (scene->rayIntersect(bsdfRay, bsdfIts) && bsdfIts.shape->getEmitter()) { const auto* em = bsdfIts.shape->getEmitter(); EmitterSample emSam(its.p, bsdfIts.p, bsdfIts.shFrame.n); emSam.wi = bsdfRay.d; auto lightSpec = em->eval(emSam); float pdfBsdf = its.shape->getBSDF()->pdf(bsdfSample); float pdfEm = em->pdf(emSam) * scene->getEmitterPdf(); if (pdfBsdf + pdfEm > 0.f) L += throughput * bsdf * lightSpec * miWeight(pdfBsdf, pdfEm); } isSpecular = its.shape->getBSDF()->getType() == BSDFType::Delta; throughput *= bsdf; ray = bsdfRay; float q = 1.f - std::min(throughput.maxCoeff(), 0.99f); if (sampler.next1D() > q) throughput /= (1.f - q); else break; } return L; }

/* * Create new feeSig object, including a random large integer 'randGiant' for * possible use in salting a feeHash object, and 'PmX', equal to * randGiant 'o' P1. Note that this is not called when *verifying* a * signature, only when signing. */ feeSig feeSigNewWithKey( feePubKey pubKey, feeRandFcn randFcn, /* optional */ void *randRef) { sigInst *sinst = sinstAlloc(); feeRand frand; unsigned char *randBytes; unsigned randBytesLen; curveParams *cp; if(pubKey == NULL) { return NULL; } cp = feePubKeyCurveParams(pubKey); if(cp == NULL) { return NULL; } /* * Generate random m, a little larger than key size, save as randGiant */ randBytesLen = (feePubKeyBitsize(pubKey) / 8) + 1; randBytes = (unsigned char*) fmalloc(randBytesLen); if(randFcn) { randFcn(randRef, randBytes, randBytesLen); } else { frand = feeRandAlloc(); feeRandBytes(frand, randBytes, randBytesLen); feeRandFree(frand); } sinst->randGiant = giant_with_data(randBytes, randBytesLen); memset(randBytes, 0, randBytesLen); ffree(randBytes); #if FEE_DEBUG if(isZero(sinst->randGiant)) { printf("feeSigNewWithKey: randGiant = 0!\n"); } #endif // FEE_DEBUG /* * Justify randGiant to be in [2, x1OrderPlus] */ x1OrderPlusJustify(sinst->randGiant, cp); /* PmX := randGiant 'o' P1 */ sinst->PmX = newGiant(cp->maxDigits); #if CRYPTKIT_ELL_PROJ_ENABLE if(cp->curveType == FCT_Weierstrass) { pointProjStruct pt0; sinst->PmY = newGiant(cp->maxDigits); /* cook up pt0 as P1 */ pt0.x = sinst->PmX; pt0.y = sinst->PmY; pt0.z = borrowGiant(cp->maxDigits); gtog(cp->x1Plus, pt0.x); gtog(cp->y1Plus, pt0.y); int_to_giant(1, pt0.z); /* pt0 := P1 'o' randGiant */ ellMulProjSimple(&pt0, sinst->randGiant, cp); returnGiant(pt0.z); } else { if(SIG_CURVE == CURVE_PLUS) { gtog(cp->x1Plus, sinst->PmX); } else { gtog(cp->x1Minus, sinst->PmX); } elliptic_simple(sinst->PmX, sinst->randGiant, cp); } #else /* CRYPTKIT_ELL_PROJ_ENABLE */ if(SIG_CURVE == CURVE_PLUS) { gtog(cp->x1Plus, sinst->PmX); } else { gtog(cp->x1Minus, sinst->PmX); } elliptic_simple(sinst->PmX, sinst->randGiant, cp); #endif /* CRYPTKIT_ELL_PROJ_ENABLE */ return sinst; }

vec proj(const vec& base, const vec& v) { if (isZero(base)) return base; else return ((eucInnerProd(base, v)/eucInnerProd(base,base)) * base); }

/** * Currently, getDouble() depends on strtod() to do its conversion. * * WARNING!! * This is an extremely costly function. ~1/2 of the conversion time * can be linked to this function. */ double DigitList::getDouble() const { static char gDecimal = 0; char decimalSeparator; { Mutex mutex; if (fHave == kDouble) { return fUnion.fDouble; } else if(fHave == kInt64) { return (double)fUnion.fInt64; } decimalSeparator = gDecimal; } if (decimalSeparator == 0) { // We need to know the decimal separator character that will be used with strtod(). // Depends on the C runtime global locale. // Most commonly is '.' // TODO: caching could fail if the global locale is changed on the fly. char rep[MAX_DIGITS]; sprintf(rep, "%+1.1f", 1.0); decimalSeparator = rep[2]; } double tDouble = 0.0; if (isZero()) { tDouble = 0.0; if (decNumberIsNegative(fDecNumber)) { tDouble /= -1; } } else if (isInfinite()) { if (std::numeric_limits<double>::has_infinity) { tDouble = std::numeric_limits<double>::infinity(); } else { tDouble = std::numeric_limits<double>::max(); } if (!isPositive()) { tDouble = -tDouble; //this was incorrectly "-fDouble" originally. } } else { MaybeStackArray<char, MAX_DBL_DIGITS+18> s; // Note: 14 is a magic constant from the decNumber library documentation, // the max number of extra characters beyond the number of digits // needed to represent the number in string form. Add a few more // for the additional digits we retain. // Round down to appx. double precision, if the number is longer than that. // Copy the number first, so that we don't modify the original. if (getCount() > MAX_DBL_DIGITS + 3) { DigitList numToConvert(*this); numToConvert.reduce(); // Removes any trailing zeros, so that digit count is good. numToConvert.round(MAX_DBL_DIGITS+3); uprv_decNumberToString(numToConvert.fDecNumber, s); // TODO: how many extra digits should be included for an accurate conversion? } else { uprv_decNumberToString(this->fDecNumber, s); } U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18); if (decimalSeparator != '.') { char *decimalPt = strchr(s, '.'); if (decimalPt != NULL) { *decimalPt = decimalSeparator; } } char *end = NULL; tDouble = uprv_strtod(s, &end); } { Mutex mutex; DigitList *nonConstThis = const_cast<DigitList *>(this); nonConstThis->internalSetDouble(tDouble); gDecimal = decimalSeparator; } return tDouble; }

void ellAddProj(pointProj pt0, pointProj pt1, curveParams *cp) /* pt0 := pt0 + pt1 on the curve. */ { giant x0 = pt0->x, y0 = pt0->y, z0 = pt0->z, x1 = pt1->x, y1 = pt1->y, z1 = pt1->z; giant t1; giant t2; giant t3; giant t4; giant t5; giant t6; giant t7; if(isZero(z0)) { gtog(x1,x0); gtog(y1,y0); gtog(z1,z0); return; } if(isZero(z1)) return; t1 = borrowGiant(cp->maxDigits); t2 = borrowGiant(cp->maxDigits); t3 = borrowGiant(cp->maxDigits); t4 = borrowGiant(cp->maxDigits); t5 = borrowGiant(cp->maxDigits); t6 = borrowGiant(cp->maxDigits); t7 = borrowGiant(cp->maxDigits); gtog(x0, t1); gtog(y0,t2); gtog(z0, t3); gtog(x1, t4); gtog(y1, t5); if(!isone(z1)) { gtog(z1, t6); gtog(t6, t7); gsquare(t7); feemod(cp, t7); mulg(t7, t1); feemod(cp, t1); mulg(t6, t7); feemod(cp, t7); mulg(t7, t2); feemod(cp, t2); } gtog(t3, t7); gsquare(t7); feemod(cp, t7); mulg(t7, t4); feemod(cp, t4); mulg(t3, t7); feemod(cp, t7); mulg(t7, t5); feemod(cp, t5); negg(t4); addg(t1, t4); feemod(cp, t4); negg(t5); addg(t2, t5); feemod(cp, t5); if(isZero(t4)) { if(isZero(t5)) { ellDoubleProj(pt0, cp); } else { int_to_giant(1, x0); int_to_giant(1, y0); int_to_giant(0, z0); } goto out; } addg(t1, t1); subg(t4, t1); feemod(cp, t1); addg(t2, t2); subg(t5, t2); feemod(cp, t2); if(!isone(z1)) { mulg(t6, t3); feemod(cp, t3); } mulg(t4, t3); feemod(cp, t3); gtog(t4, t7); gsquare(t7); feemod(cp, t7); mulg(t7, t4); feemod(cp, t4); mulg(t1, t7); feemod(cp, t7); gtog(t5, t1); gsquare(t1); feemod(cp, t1); subg(t7, t1); feemod(cp, t1); subg(t1, t7); subg(t1, t7); feemod(cp, t7); mulg(t7, t5); feemod(cp, t5); mulg(t2, t4); feemod(cp, t4); gtog(t5, t2); subg(t4,t2); feemod(cp, t2); if(t2->n[0] & 1) { /* Test if t2 is odd. */ addg(cp->basePrime, t2); } gshiftright(1, t2); gtog(t1, x0); gtog(t2, y0); gtog(t3, z0); out: returnGiant(t1); returnGiant(t2); returnGiant(t3); returnGiant(t4); returnGiant(t5); returnGiant(t6); returnGiant(t7); }

void Negate(modp& ans,const modp& x,const Zp_Data& ZpD) { if (isZero(x,ZpD)) { ans=x; return; } mpn_sub_n(ans.x,ZpD.prA,x.x,ZpD.t); }

// Check Compare before and after normals of affected faces. // If a normal changes more by more than pi/2 (90 deg), then // we will disallow this contraction and terminate early. BOOL Pair::normalFlips(SmallPtrSet& updatedFaces, SmallPtrSet& rvFaces, BOOL& smallNormalChange) { Vertex* keepVertex = getContractTarget(); Vertex* removeVertex = NULL; if (keepVertex == v1) removeVertex = v2; else removeVertex = v1; // Compute adjusted faces: rvFaces.Clear(); updatedFaces.Clear(); removeVertex->computeFaceSet(rvFaces); // problem here, rvFaces different SmallPtrSet_Difference(&rvFaces, &m_Faces, &updatedFaces); Vertex *v1, *v2, *v3; U32 SetCtx = 0; Face* face = (Face*)updatedFaces.Begin(SetCtx); smallNormalChange = TRUE; F32 dotThresh = 0.966f; // about 15 degrees F32 worstDot=1; BOOL result = FALSE; IV3D u, v, oldNormal, newNormal; F32 dot; while(face && !result) { if( !result ) { v1 = face->a->getCommonVertex(face->b); v2 = face->b->getCommonVertex(face->c); v3 = face->c->getCommonVertex(face->a); // Compute the normal - we could grab this data from the equation of the plane (A, B, C, D), // but then we'd have to keep A, B, C, D around in the faces: subtract3D ((IV3D*)&v2->v, (IV3D*)&v1->v, (IV3D*)&u); if( isZero(&u) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) { normalize3D ((IV3D*)&u); subtract3D ((IV3D*)&v3->v, (IV3D*)&v1->v, (IV3D*)&v); if( isZero(&v) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) { normalize3D ((IV3D*)&v); crossprod ((IV3D*)&u, (IV3D*)&v, &oldNormal); if( isZero(&oldNormal) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) normalize3D (&oldNormal); // Recompute the normal: if( !result ) { // Install the keep vertex into this temp version of the adjusted face: if (v1 == removeVertex) v1 = keepVertex; if (v2 == removeVertex) v2 = keepVertex; if (v3 == removeVertex) v3 = keepVertex; subtract3D ((IV3D*)&v2->v, (IV3D*)&v1->v, (IV3D*)&u); if( isZero(&u) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) { normalize3D ((IV3D*)&u); subtract3D ((IV3D*)&v3->v, (IV3D*)&v1->v, (IV3D*)&v); if( isZero(&v) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) { normalize3D ((IV3D*)&v); crossprod ((IV3D*)&u, (IV3D*)&v, (IV3D*)&newNormal); if( isZero(&newNormal) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) { normalize3D ((IV3D*)&newNormal); dot = dotProduct3D ((IV3D*)&oldNormal, (IV3D*)&newNormal); // Did the normal flip?: if (dot < cosMaxNormalChange) { // Mark it flipped: if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } // test if( !result ) { if(dot < worstDot) worstDot = dot; face = (Face*)updatedFaces.Next(SetCtx); } } if(worstDot < dotThresh && !result) { smallNormalChange = FALSE; } return result; }

bool Number::isDigitOneToNine(char character) { return isDigit(character) && !isZero(character); }

bool Number::CoreValidate(char character) { if (_lexeme.length() == 0) _lexeme.reserve(20); switch ((States) _currentState) { case States::Start: { _lexeme.append(1, character); if (isMinus(character)) _currentState = (int) States::Negation; if (isZero(character)) _currentState = (int) States::RationalPercent; if (isDigitOneToNine(character)) _currentState = (int) States::Number; break; } case States::Negation: { _lexeme.append(1, character); if (isZero(character)) _currentState = (int) States::RationalPercent; if (isDigitOneToNine(character)) _currentState = (int) States::Number; break; } case States::RationalPercent: { _lexeme.append(1, character); if (isDot(character)) _currentState = (int) States::Decimal; if (isExponentialSymbol(character)) _currentState = (int) States::Exponential_1; break; } case States::Number: { _lexeme.append(1, character); if (isDigit(character)) _currentState = (int) States::Number; if (isDot(character)) _currentState = (int) States::Decimal; if (isExponentialSymbol(character)) _currentState = (int) States::Exponential_1; break; } case States::Decimal: { _lexeme.append(1, character); if (isDigit(character)) _currentState = (int) States::Decimal; if (isExponentialSymbol(character)) _currentState = (int) States::Exponential_1; break; } case States::Exponential_1: { _lexeme.append(1, character); _currentState = (int) States::Exponential_2; break; } case States::Exponential_2: { _lexeme.append(1, character); _currentState = (int) States::Exponential_2; break; } case States::Closing: return false; } return true; }

/*! \fn inline bool numericalZero(double value) * \param[in] value the value to be checked * * Returns true if value is less than 1.0e-14 */ inline bool numericalZero(double value) { return (isZero(value, 1.0e-14)); }

bool Tokenizer::consumeNumber(std::streambuf::int_type ch) { int count = 0; if (isSign(ch)) { bool number = false; while (!eof()) { ++count; auto nch = mpInput->get(); if (isWhitespace(nch)) continue; number = isDecimalDigit(nch); break; } if (count) mpInput->clear(); for (int i = 0; i < count; ++i) mpInput->unget(); if (!number) return false; } absorbed(ch); mpCurrent->addChar(ch); for (int i = 0; i < count; ++i) { auto nch = mpInput->get(); absorbed(nch); mpCurrent->addChar(nch); } bool bDot = false; if (isDot(ch)) { bDot = true; mpCurrent->setType(Token::TYPE_REAL_LITERAL); } else { mpCurrent->setType(Token::TYPE_INTEGER_LITERAL); if (!eof() && isZero(ch)) { ch = mpInput->get(); if (isHexIndicator(ch)) { if (eof()) { mpMessageCollector->addMessage( Message::SEVERITY_ERROR, Message::t_invalidIntegerLiteral, mpSourceId, mpCurrent->line(), mpCurrent->beginColumn()); mpCurrent.reset(); return false; } mpCurrent->addChar(ch); absorbed(ch); while (!eof()) { ch = mpInput->get(); if (isNonHexicalLetter(ch) || isUnderscore(ch) || isDot(ch)) { mpMessageCollector->addMessage(Message::SEVERITY_ERROR, Message::t_invalidIntegerLiteral, mpSourceId, mpCurrent->line(), mpCurrent->beginColumn()); mpCurrent.reset(); return false; } if (!isHexicalDigit(ch)) { mpInput->clear(); mpInput->unget(); break; } absorbed(ch); mpCurrent->addChar(ch); } mpCurrent->setEndColumn(column()); return true; } for (;;) { if ( isLetter(ch) || isDot(ch) || isNonOctalDecimalDigit(ch) || isUnderscore(ch)) { mpMessageCollector->addMessage( Message::SEVERITY_ERROR, Message::t_invalidIntegerLiteral, mpSourceId, mpCurrent->line(), mpCurrent->beginColumn()); mpCurrent.reset(); return false; } if (!isOctalDigit(ch)) { mpInput->clear(); mpInput->unget(); break; } absorbed(ch); mpCurrent->addChar(ch); if (eof()) { break; } ch = mpInput->get(); } mpCurrent->setEndColumn(column()); return true; } } bool bExponent = false; while (!eof()) { ch = mpInput->get(); if (isExponent(ch)) { if (bExponent) { mpMessageCollector->addMessage( Message::SEVERITY_ERROR, Message::t_invalidIntegerLiteral, mpSourceId, mpCurrent->line(), mpCurrent->beginColumn()); mpCurrent.reset(); return false; } bExponent = true; mpCurrent->setType(Token::TYPE_REAL_LITERAL); absorbed(ch); mpCurrent->addChar(ch); ch = mpInput->get(); if (isSign(ch)) { mpCurrent->setType(Token::TYPE_REAL_LITERAL); absorbed(ch); mpCurrent->addChar(ch); } else { mpInput->clear(); mpInput->unget(); } continue; } if (isLetter(ch) || isUnderscore(ch)) { mpMessageCollector->addMessage( Message::SEVERITY_ERROR, Message::t_invalidIntegerLiteral, mpSourceId, mpCurrent->line(), mpCurrent->beginColumn()); mpCurrent.reset(); return false; } if (isDot(ch)) { if (bExponent || bDot) { mpMessageCollector->addMessage( Message::SEVERITY_ERROR, Message::t_invalidIntegerLiteral, mpSourceId, mpCurrent->line(), mpCurrent->beginColumn()); mpCurrent.reset(); return false; } bDot = true; mpCurrent->setType(Token::TYPE_REAL_LITERAL); absorbed(ch); mpCurrent->addChar(ch); continue; } if (!isDecimalDigit(ch)) { mpInput->clear(); mpInput->unget(); break; } absorbed(ch); mpCurrent->addChar(ch); } mpCurrent->setEndColumn(column()); return true; }

bool areOrthogonal(sf::Vector2f left, sf::Vector2f right){ return isZero(dot(left, right)); }

void Rank(int n) { int N, i, k, r; double p_value, product, chi_squared, arg1, p_32, p_31, p_30, R, F_32, F_31, F_30; BitSequence **matrix = create_matrix(32, 32); N = n/(32*32); if ( isZero(N) ) { fprintf(stats[TEST_RANK], "\t\t\t\tRANK TEST\n"); fprintf(stats[TEST_RANK], "\t\tError: Insuffucient # Of Bits To Define An 32x32 (%dx%d) Matrix\n", 32, 32); p_value = 0.00; } else { r = 32; /* COMPUTE PROBABILITIES */ product = 1; for ( i=0; i<=r-1; i++ ) product *= ((1.e0-pow(2, i-32))*(1.e0-pow(2, i-32)))/(1.e0-pow(2, i-r)); p_32 = pow(2, r*(32+32-r)-32*32) * product; r = 31; product = 1; for ( i=0; i<=r-1; i++ ) product *= ((1.e0-pow(2, i-32))*(1.e0-pow(2, i-32)))/(1.e0-pow(2, i-r)); p_31 = pow(2, r*(32+32-r)-32*32) * product; p_30 = 1 - (p_32+p_31); F_32 = 0; F_31 = 0; for ( k=0; k<N; k++ ) { /* FOR EACH 32x32 MATRIX */ def_matrix(32, 32, matrix, k); #if (DISPLAY_MATRICES == 1) display_matrix(32, 32, matrix); #endif R = computeRank(32, 32, matrix); if ( R == 32 ) F_32++; /* DETERMINE FREQUENCIES */ if ( R == 31 ) F_31++; } F_30 = (double)N - (F_32+F_31); chi_squared =(pow(F_32 - N*p_32, 2)/(double)(N*p_32) + pow(F_31 - N*p_31, 2)/(double)(N*p_31) + pow(F_30 - N*p_30, 2)/(double)(N*p_30)); arg1 = -chi_squared/2.e0; fprintf(stats[TEST_RANK], "\t\t\t\tRANK TEST\n"); fprintf(stats[TEST_RANK], "\t\t---------------------------------------------\n"); fprintf(stats[TEST_RANK], "\t\tCOMPUTATIONAL INFORMATION:\n"); fprintf(stats[TEST_RANK], "\t\t---------------------------------------------\n"); fprintf(stats[TEST_RANK], "\t\t(a) Probability P_%d = %f\n", 32,p_32); fprintf(stats[TEST_RANK], "\t\t(b) P_%d = %f\n", 31,p_31); fprintf(stats[TEST_RANK], "\t\t(c) P_%d = %f\n", 30,p_30); fprintf(stats[TEST_RANK], "\t\t(d) Frequency F_%d = %d\n", 32,(int)F_32); fprintf(stats[TEST_RANK], "\t\t(e) F_%d = %d\n", 31,(int)F_31); fprintf(stats[TEST_RANK], "\t\t(f) F_%d = %d\n", 30,(int)F_30); fprintf(stats[TEST_RANK], "\t\t(g) # of matrices = %d\n", N); fprintf(stats[TEST_RANK], "\t\t(h) Chi^2 = %f\n", chi_squared); fprintf(stats[TEST_RANK], "\t\t(i) NOTE: %d BITS WERE DISCARDED.\n", n%(32*32)); fprintf(stats[TEST_RANK], "\t\t---------------------------------------------\n"); p_value = exp(arg1); if ( isNegative(p_value) || isGreaterThanOne(p_value) ) fprintf(stats[TEST_RANK], "WARNING: P_VALUE IS OUT OF RANGE.\n"); for ( i=0; i<32; i++ ) /* DEALLOCATE MATRIX */ free(matrix[i]); free(matrix); } fprintf(stats[TEST_RANK], "%s\t\tp_value = %f\n\n", p_value < ALPHA ? "FAILURE" : "SUCCESS", p_value); fflush(stats[TEST_RANK]); fprintf(results[TEST_RANK], "%f\n", p_value); fflush(results[TEST_RANK]); }

void CurrDisplay::sReformat() const { if (DEBUG) qDebug("CD %s::sReformat() entered with _state %d, _format %d", qPrintable(objectName()), _state, _format); QString na = tr("N/A"); QString unknown = tr(UNKNOWNSTR); QString local = ""; switch (_state) { case New: local = ""; break; case NANew: local = na; break; case Initialized: if (isZero()) switch (_format) { case SalesPrice: local = formatSalesPrice(0.0, id()); break; case PurchPrice: local = formatPurchPrice(0.0, id()); break; case ExtPrice: local = formatExtPrice(0.0, id()); break; case Cost: local = formatCost(0.0, id()); break; case Money: default: local = formatMoney(0.0, id()); break; } else if (_localKnown) switch (_format) { case SalesPrice: local = formatSalesPrice(_valueLocal, id()); break; case PurchPrice: local = formatPurchPrice(_valueLocal, id()); break; case ExtPrice: local = formatExtPrice(_valueLocal, id()); break; case Cost: local = formatCost(_valueLocal, id()); break; case Money: default: local = formatMoney(_valueLocal, id()); break; } else local = unknown; break; case NAInit: if (isZero()) local = na; else switch (_format) { case SalesPrice: local = formatSalesPrice(_valueLocal, id()); break; case PurchPrice: local = formatPurchPrice(_valueLocal, id()); break; case ExtPrice: local = formatExtPrice(_valueLocal, id()); break; case Cost: local = formatCost(_valueLocal, id()); break; case Money: default: local = formatMoney(_valueLocal, id()); break; } break; default: break; } _valueLocalWidget->setText(local); }

//============================================================================== Error Animation::load(const ResourceFilename& filename) { XmlElement el; I64 tmp; F64 ftmp; m_startTime = MAX_F32; F32 maxTime = MIN_F32; // Document XmlDocument doc; ANKI_CHECK(openFileParseXml(filename, doc)); XmlElement rootel; ANKI_CHECK(doc.getChildElement("animation", rootel)); // Count the number of identity keys. If all of the keys are identities // drop a vector U identPosCount = 0; U identRotCount = 0; U identScaleCount = 0; // <repeat> XmlElement repel; ANKI_CHECK(rootel.getChildElementOptional("repeat", repel)); if(repel) { ANKI_CHECK(repel.getI64(tmp)); m_repeat = tmp; } else { m_repeat = false; } // <channels> XmlElement channelsEl; ANKI_CHECK(rootel.getChildElement("channels", channelsEl)); XmlElement chEl; ANKI_CHECK(channelsEl.getChildElement("channel", chEl)); U32 channelCount = 0; ANKI_CHECK(chEl.getSiblingElementsCount(channelCount)); if(channelCount == 0) { ANKI_LOGE("Didn't found any channels"); return ErrorCode::USER_DATA; } m_channels.create(getAllocator(), channelCount); // For all channels channelCount = 0; do { AnimationChannel& ch = m_channels[channelCount]; // <name> ANKI_CHECK(chEl.getChildElement("name", el)); CString strtmp; ANKI_CHECK(el.getText(strtmp)); ch.m_name.create(getAllocator(), strtmp); XmlElement keysEl, keyEl; // <positionKeys> ANKI_CHECK(chEl.getChildElementOptional("positionKeys", keysEl)); if(keysEl) { ANKI_CHECK(keysEl.getChildElement("key", keyEl)); U32 count = 0; ANKI_CHECK(keyEl.getSiblingElementsCount(count)); ch.m_positions.create(getAllocator(), count); count = 0; do { Key<Vec3>& key = ch.m_positions[count++]; // <time> ANKI_CHECK(keyEl.getChildElement("time", el)); ANKI_CHECK(el.getF64(ftmp)); key.m_time = ftmp; m_startTime = std::min(m_startTime, key.m_time); maxTime = std::max(maxTime, key.m_time); // <value> ANKI_CHECK(keyEl.getChildElement("value", el)); ANKI_CHECK(el.getVec3(key.m_value)); // Check ident if(key.m_value == Vec3(0.0)) { ++identPosCount; } // Move to next ANKI_CHECK(keyEl.getNextSiblingElement("key", keyEl)); } while(keyEl); } // <rotationKeys> ANKI_CHECK(chEl.getChildElement("rotationKeys", keysEl)); if(keysEl) { ANKI_CHECK(keysEl.getChildElement("key", keyEl)); U32 count = 0; ANKI_CHECK(keysEl.getSiblingElementsCount(count)); ch.m_rotations.create(getAllocator(), count); count = 0; do { Key<Quat>& key = ch.m_rotations[count++]; // <time> ANKI_CHECK(keyEl.getChildElement("time", el)); ANKI_CHECK(el.getF64(ftmp)); key.m_time = ftmp; m_startTime = std::min(m_startTime, key.m_time); maxTime = std::max(maxTime, key.m_time); // <value> Vec4 tmp2; ANKI_CHECK(keyEl.getChildElement("value", el)); ANKI_CHECK(el.getVec4(tmp2)); key.m_value = Quat(tmp2); // Check ident if(key.m_value == Quat::getIdentity()) { ++identRotCount; } // Move to next ANKI_CHECK(keyEl.getNextSiblingElement("key", keyEl)); } while(keyEl); } // <scalingKeys> ANKI_CHECK(chEl.getChildElementOptional("scalingKeys", keysEl)); if(keysEl) { ANKI_CHECK(keysEl.getChildElement("key", keyEl)); U32 count = 0; ANKI_CHECK(keyEl.getSiblingElementsCount(count)); ch.m_scales.create(getAllocator(), count); count = 0; do { Key<F32>& key = ch.m_scales[count++]; // <time> ANKI_CHECK(keyEl.getChildElement("time", el)); ANKI_CHECK(el.getF64(ftmp)); key.m_time = ftmp; m_startTime = std::min(m_startTime, key.m_time); maxTime = std::max(maxTime, key.m_time); // <value> ANKI_CHECK(keyEl.getChildElement("value", el)); ANKI_CHECK(el.getF64(ftmp)); key.m_value = ftmp; // Check ident if(isZero(key.m_value - 1.0)) { ++identScaleCount; } // Move to next ANKI_CHECK(keyEl.getNextSiblingElement("key", keyEl)); } while(keyEl); } // Remove identity vectors if(identPosCount == ch.m_positions.getSize()) { ch.m_positions.destroy(getAllocator()); } if(identRotCount == ch.m_rotations.getSize()) { ch.m_rotations.destroy(getAllocator()); } if(identScaleCount == ch.m_scales.getSize()) { ch.m_scales.destroy(getAllocator()); } // Move to next channel ++channelCount; ANKI_CHECK(chEl.getNextSiblingElement("channel", chEl)); } while(chEl); m_duration = maxTime - m_startTime; return ErrorCode::NONE; }

static Tree simplification (Tree sig) { assert(sig); int opnum; Tree t1, t2, t3, t4; xtended* xt = (xtended*) getUserData(sig); // primitive elements if (xt) { //return 3; vector<Tree> args; for (int i=0; i<sig->arity(); i++) { args.push_back( sig->branch(i) ); } // to avoid negative power to further normalization if (xt != gPowPrim) { return xt->computeSigOutput(args); } else { return normalizeAddTerm(xt->computeSigOutput(args)); } } else if (isSigBinOp(sig, &opnum, t1, t2)) { BinOp* op = gBinOpTable[opnum]; Node n1 = t1->node(); Node n2 = t2->node(); if (isNum(n1) && isNum(n2)) return tree(op->compute(n1,n2)); else if (op->isLeftNeutral(n1)) return t2; else if (op->isRightNeutral(n2)) return t1; else return normalizeAddTerm(sig); } else if (isSigDelay1(sig, t1)) { return normalizeDelay1Term (t1); } else if (isSigFixDelay(sig, t1, t2)) { return normalizeFixedDelayTerm (t1, t2); } else if (isSigIntCast(sig, t1)) { Tree tx; int i; double x; Node n1 = t1->node(); if (isInt(n1, &i)) return t1; if (isDouble(n1, &x)) return tree(int(x)); if (isSigIntCast(t1, tx)) return t1; return sig; } else if (isSigFloatCast(sig, t1)) { Tree tx; int i; double x; Node n1 = t1->node(); if (isInt(n1, &i)) return tree(double(i)); if (isDouble(n1, &x)) return t1; if (isSigFloatCast(t1, tx)) return t1; return sig; } else if (isSigSelect2(sig, t1, t2, t3)){ Node n1 = t1->node(); if (isZero(n1)) return t2; if (isNum(n1)) return t3; if (t2==t3) return t2; return sig; } else if (isSigSelect3(sig, t1, t2, t3, t4)){ Node n1 = t1->node(); if (isZero(n1)) return t2; if (isOne(n1)) return t3; if (isNum(n1)) return t4; if (t3==t4) return simplification(sigSelect2(t1,t2,t3)); return sig; } else { return sig; } }

int solveCubic(double c3, double c2, double c1, double c0, double & s0, double & s1, double & s2) { int num; double sub, A, B, C, sq_A, p, q, cb_p, D; if (isZero(c3)) return solveQuadric(c2, c1, c0, s0, s1); // normalize the equation:x ^ 3 + Ax ^ 2 + Bx + C = 0 A = c2 / c3; B = c1 / c3; C = c0 / c3; // substitute x = y - A / 3 to eliminate the quadric term: x^3 + px + q = 0 sq_A = A * A; p = 1.0/3.0 * (-1.0/3.0 * sq_A + B); q = 1.0/2.0 * (2.0/27.0 * A *sq_A - 1.0/3.0 * A * B + C); // use Cardano's formula cb_p = p * p * p; D = q * q + cb_p; if (isZero(D)) { if (isZero(q)) { // one triple solution s0 = 0.0; num = 1; } else { // one single and one double solution double u = cbrt(-q); s0 = 2.0 * u; s1 = - u; num = 2; } } else { if (D < 0.0) { // casus irreductibilis: three real solutions double phi = 1.0/3.0 * acos(-q / sqrt(-cb_p)); double t = 2.0 * sqrt(-p); s0 = t * cos(phi); s1 = -t * cos(phi + M_PI / 3.0); s2 = -t * cos(phi - M_PI / 3.0); num = 3; } else { // one real solution double sqrt_D = sqrt(D); double u = cbrt(sqrt_D + fabs(q)); if (q > 0.0) s0 = - u + p / u ; else s0 = u - p / u; num = 1; } } // resubstitute sub = 1.0 / 3.0 * A; s0 -= sub; s1 -= sub; s2 -= sub; return num; }

inline bool areEqual(double a, double b) { return isZero(a-b); }

bool Mesh::fastIntersects(const Ray& ray, const Matrix4x4& inverseTransform) { HitRecord r; intersects(ray, &r, inverseTransform); return r.t > 0 && !isZero(r.t); }

inline UnitVector3d::UnitVector(double x, double y, double z) : Cartesian<double, 3>(x, y, z) { assert(isZero() || sqrt(x * x + y * y + z * z) - 1.0 == opensolid::Zero()); }

void CommandEffect::setDurationAct(float _duration, const char* _title) { m_fDuration = isZero(_duration) ? EffectUtil::getActionEffectTime(_title) : _duration; }

inline UnitVector2d::UnitVector(double x, double y) : Cartesian<double, 2>(x, y) { assert(isZero() || sqrt(x * x + y * y) - 1.0 == opensolid::Zero()); }

bool StringData::toBoolean() const { return !empty() && !isZero(); }

inline UnitVector2d::UnitVector(const ColumnMatrix2d& components) : Cartesian<double, 2>(components) { assert(isZero() || sqrt(x() * x() + y() * y()) - 1.0 == opensolid::Zero()); }

void Term::regZero () { if (isZero()) std::fill (index.begin(), index.end(), 0); }

/* * cons up: * cluePlus(0) * clueMinus(0) * sPlus * sMinus * r * Assumes: * cluePlus = clueMinus = ourPriv * theirPub * initialRS * initialRSSize * cp * * Called at feeFEEDNewWithPubKey while encrypting, or upon decrypting * first block of data. */ static feeReturn initFromRS(feedInst *finst) { giant s; unsigned rSize = finst->initialRSSize / 2; #if FEED_DEBUG if((finst->initialRS == NULL) || (finst->cp == NULL) || (finst->cluePlus == NULL) || (finst->clueMinus == NULL) || (finst->initialRSSize == 0)) { dbgLog(("initFromRS: resource shortage\n")); return FR_Internal; } #endif // FEED_DEBUG finst->r = giant_with_data(finst->initialRS, rSize); s = giant_with_data(finst->initialRS+rSize, rSize); #if FEED_DEBUG if(isZero(finst->r)) { printf("initFromRS: r = 0! initialRSSize = %d; encr = %s\n", finst->initialRSSize, (finst->rsCtext == NULL) ? "TRUE" : "FALSE"); } if(isZero(s)) { printf("initFromRS: s = 0! initialRSSize = %d; encr = %s\n", finst->initialRSSize, (finst->rsCtext == NULL) ? "TRUE" : "FALSE"); } #endif // FEE_DEBUG /* * Justify r and s to be in [2, minimumX1Order]. */ lesserX1OrderJustify(finst->r, finst->cp); lesserX1OrderJustify(s, finst->cp); /* * sPlus = s * x1Plus * sMinus = s * x1Minus */ finst->sPlus = newGiant(finst->cp->maxDigits); finst->sMinus = newGiant(finst->cp->maxDigits); gtog(finst->cp->x1Plus, finst->sPlus); elliptic_simple(finst->sPlus, s, finst->cp); gtog(finst->cp->x1Minus, finst->sMinus); elliptic_simple(finst->sMinus, s, finst->cp); /* * And finally, the initial clues. They are currently set to * ourPriv * theirPub. */ #if FEED_DEBUG printf("cluePlus : "); printGiant(finst->cluePlus); printf("clueMinus: "); printGiant(finst->clueMinus); #endif // FEED_EEBUG elliptic_simple(finst->cluePlus, finst->r, finst->cp); elliptic_simple(finst->clueMinus, finst->r, finst->cp); #if FEED_DEBUG printf("r : "); printGiant(finst->r); printf("s : "); printGiant(s); printf("sPlus : "); printGiant(finst->sPlus); printf("sMinus : "); printGiant(finst->sMinus); printf("cluePlus : "); printGiant(finst->cluePlus); printf("clueMinus: "); printGiant(finst->clueMinus); #endif // FEED_DEBUG freeGiant(s); return FR_Success; }

double DigitList::getDouble() const { // TODO: fix thread safety. Can probably be finessed some by analyzing // what public const functions can see which DigitLists. // Like precompute fDouble for DigitLists coming in from a parse // or from a Formattable::set(), but not for any others. if (fHaveDouble) { return fDouble; } DigitList *nonConstThis = const_cast<DigitList *>(this); if (gDecimal == 0) { char rep[MAX_DIGITS]; // For machines that decide to change the decimal on you, // and try to be too smart with localization. // This normally should be just a '.'. sprintf(rep, "%+1.1f", 1.0); gDecimal = rep[2]; } if (isZero()) { nonConstThis->fDouble = 0.0; if (decNumberIsNegative(fDecNumber)) { nonConstThis->fDouble /= -1; } } else if (isInfinite()) { // BEGIN android-changed // There is no numeric_limits template member in Android std. nonConstThis->fDouble = INFINITY; /* if (std::numeric_limits<double>::has_infinity) { nonConstThis->fDouble = std::numeric_limits<double>::infinity(); } else { nonConstThis->fDouble = std::numeric_limits<double>::max(); } */ // END android-changed if (!isPositive()) { nonConstThis->fDouble = -fDouble; } } else { MaybeStackArray<char, MAX_DBL_DIGITS+18> s; // Note: 14 is a magic constant from the decNumber library documentation, // the max number of extra characters beyond the number of digits // needed to represent the number in string form. Add a few more // for the additional digits we retain. // Round down to appx. double precision, if the number is longer than that. // Copy the number first, so that we don't modify the original. if (getCount() > MAX_DBL_DIGITS + 3) { DigitList numToConvert(*this); numToConvert.reduce(); // Removes any trailing zeros, so that digit count is good. numToConvert.round(MAX_DBL_DIGITS+3); uprv_decNumberToString(numToConvert.fDecNumber, s); // TODO: how many extra digits should be included for an accurate conversion? } else { uprv_decNumberToString(this->fDecNumber, s); } U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18); if (gDecimal != '.') { char *decimalPt = strchr(s, '.'); if (decimalPt != NULL) { *decimalPt = gDecimal; } } char *end = NULL; nonConstThis->fDouble = uprv_strtod(s, &end); } nonConstThis->fHaveDouble = TRUE; return fDouble; }

void getInverseDestroy(matrix *m, matrix *dest) { getIdentityMatrix(dest, m->R); int i; int j; int si; nType temp; for(i = 0; i < m->R; i++) { j = getMaxInRow(m, i); if(isZero(m->ptr[i][j])) { dest->R = 0; dest->C = 0; return; } temp = m->ptr[i][j]; if(temp != 1) { #ifdef DEBUG fprintf(stderr, "dividing row %d by %lf\n", i + 1, temp); #endif eop1(m, i, ((nType) 1.) / temp); eop1(dest, i, ((nType) 1.) / temp); #ifdef DEBUG printMatrices(m, dest); #endif } for(si = 0; si < m->R; si++) { if(si != i) { temp = m->ptr[si][j]; if(temp != 0) { #ifdef DEBUG fprintf(stderr, "subtracting row %d multiplied by %lf from row %d\n", i + 1, temp, si + 1); #endif eop2(m, i, temp, si); eop2(dest, i, temp, si); #ifdef DEBUG printMatrices(m, dest); #endif } } } } int k; for(k = 0; k < m->R; k++) for(i = 0; i < m->R; i++) { //0...1...0 //....j.... j = getMaxInRow(m, i); if(i != j) { #ifdef DEBUG fprintf(stderr, "swapping rows %d and %d\n", i + 1, j + 1); #endif eop3(m, i, j); eop3(dest, i, j); #ifdef DEBUG printMatrices(m, dest); #endif } } }