void checkBuf() { if (!buffer1Active && !buffer2Active && !buffer3Active) { clearTile(&buffer1); clearTile(&buffer2); clearTile(&buffer3); setRandomTile(&buffer1); setRandomTile(&buffer2); setRandomTile(&buffer3); buffer1Active = true; buffer2Active = true; buffer3Active = true; } if (currentBufferInUse == 1 && !buffer1Active) { currentBufferInUse++; checkBuf(); } if (currentBufferInUse == 2 && !buffer2Active) { currentBufferInUse++; checkBuf(); } if (currentBufferInUse == 3 && !buffer3Active) { currentBufferInUse=1; checkBuf(); } fixBounds(); }
Color::Color(const Color& color) noexcept : red(color.red), green(color.green), blue(color.blue), alpha(color.alpha) { fixBounds(); }
Color::Color(float r, float g, float b, float a) noexcept : red(r), green(g), blue(b), alpha(a) { fixBounds(); }
Color::Color(int r, int g, int b, int a) noexcept : red(static_cast<float>(r)/255.0f), green(static_cast<float>(g)/255.0f), blue(static_cast<float>(b)/255.0f), alpha(static_cast<float>(a)/255.0f) { fixBounds(); }
Color& Color::operator=(const Color& color) noexcept { red = color.red; green = color.green; blue = color.blue; alpha = color.alpha; fixBounds(); return *this; }
void Color::interpolate(const Color& other, float u) noexcept { fixRange(u); const float oneMinusU(1.0f - u); red = red * oneMinusU + other.red * u; green = green * oneMinusU + other.green * u; blue = blue * oneMinusU + other.blue * u; alpha = alpha * oneMinusU + other.alpha * u; fixBounds(); }
void fixBounds() { if (currentBufferInUse == 1) { inBounds(buffer1, selectx, selecty); } if (currentBufferInUse == 2) { inBounds(buffer2, selectx, selecty); } if (currentBufferInUse == 3) { inBounds(buffer3, selectx, selecty); } if (!canDrawTileBool) { selectx--; selecty--; fixBounds(); } }
bool mooijBound(size_t nNodes, const double *theta, const cscMatrix &W, double thresh, int maxIter, double *A, // outputs double *B, double *alpha) { // copy-pasted alpha calculation (rest of code relies on it) double posW[nNodes], negW[nNodes]; for (size_t j = 0; j < nNodes; j++) { posW[j] = 0; negW[j] = 0; for (size_t idx = W.jc[j]; idx < W.jc[j+1]; idx++) { double w = W.pr[idx]; if (w > 0) { posW[j] += w; } else { negW[j] -= w; } alpha[idx] = exp(fabs(w)) - 1; } } //////////////////////////////////////////////////////// // Convert to {-1, +1} format. //////////////////////////////////////////////////////// // Jpr is the entries of the same sparsity pattern as W. double Jpr[W.nzMax]; std::transform(W.pr, W.pr + W.nzMax, Jpr, [](double x) { return 0.25 * x;}); double eta[nNodes]; for (int n = 0; n < nNodes; n++) { eta[n] = 0.5 * theta[n]; for (size_t idx = W.jc[n]; idx < W.jc[n+1]; idx++) { eta[n] += Jpr[idx]; //mexPrintf("%s:%d eta[%d] = %g; Jpr[%d] = %g\n", __FILE__, __LINE__, n, eta[n], idx, Jpr[idx]); } } //////////////////////////////////////////////////////// // Propagate bounds on the cavity fields //////////////////////////////////////////////////////// double etaLo[W.nzMax]; double etaHi[W.nzMax]; std::fill_n(etaLo, W.nzMax, std::numeric_limits<double>::lowest()); std::fill_n(etaHi, W.nzMax, std::numeric_limits<double>::max()); double etaLoNew[W.nzMax]; double etaHiNew[W.nzMax]; double a, b; bool converged = false; int t; for (t = 0; t < maxIter; t++) { for (size_t j = 0; j < nNodes; j++) { for (size_t outIdx = W.jc[j]; outIdx < W.jc[j+1]; outIdx++) { size_t i = W.ir[outIdx]; etaLoNew[outIdx] = eta[i]; etaHiNew[outIdx] = eta[i]; for (size_t inIdx = W.jc[i]; inIdx < W.jc[i+1]; inIdx++) { size_t k = W.ir[inIdx]; if (k == j) { continue; } a = atanh(tanh(Jpr[inIdx]) * tanh(etaLo[inIdx])); b = atanh(tanh(Jpr[inIdx]) * tanh(etaHi[inIdx])); etaLoNew[outIdx] += std::min(a, b); etaHiNew[outIdx] += std::max(a, b); /* if (t < 3) { mexPrintf("%s:%d i = %d, j = %d, k = %d\n", __FILE__, __LINE__, i, j, k); mexPrintf("%s:%d a = %g, b = %g, etaLo[%d] = %g, etaHi[%d] = %g, etaLoNew[%d] = %g, etaHiNew[%d] = %g\n", __FILE__, __LINE__, a, b, inIdx, etaLo[inIdx], inIdx, etaHi[inIdx], outIdx, etaLoNew[outIdx], outIdx, etaHiNew[outIdx]); } */ } } } // Check for convergence before the obligatory copy // (This might be a bit slow) if (oneNormConverged(W.nzMax, etaLoNew, etaLo, thresh) && oneNormConverged(W.nzMax, etaHiNew, etaHi, thresh)) { converged = true; break; } std::copy(etaLoNew, etaLoNew + W.nzMax, etaLo); std::copy(etaHiNew, etaHiNew + W.nzMax, etaHi); /* if (t < 3) { for (int n = 0; n < W.nzMax; n++) { mexPrintf("%s:%d %g %g %g %g\n", __FILE__, __LINE__, etaLo[n], etaHi[n], etaLoNew[n], etaHiNew[n]); } } */ } // debug /* for (size_t idx = 0; idx < W.nzMax; idx++) { mexPrintf("%s:%d etaLo[%d] = %g; etaHi[%d] = %g\n", __FILE__, __LINE__, idx, etaLo[idx], idx, etaHi[idx]); } */ //////////////////////////////////////////////////////// // Calculate beliefs in tanh parameterization //////////////////////////////////////////////////////// double betaLo[nNodes]; double betaHi[nNodes]; std::copy(eta, eta + nNodes, betaLo); std::copy(eta, eta + nNodes, betaHi); for (size_t j = 0; j < nNodes; j++) { for (size_t idx = W.jc[j]; idx < W.jc[j+1]; idx++) { size_t i = W.ir[idx]; //mexPrintf("%s:%d i = %d, j = %d\n", __FILE__, __LINE__, i, j); a = atanh(tanh(Jpr[idx]) * tanh(etaLo[idx])); b = atanh(tanh(Jpr[idx]) * tanh(etaHi[idx])); betaLo[j] += std::min(a, b); betaHi[j] += std::max(a, b); } } /* for (size_t j = 0; j < nNodes; j++) { mexPrintf("%s:%d betaLo[%d] = %g; betaHi[%d] = %g\n", __FILE__, __LINE__, j, betaLo[j], j, betaHi[j]); } */ //////////////////////////////////////////////////////// // Calculate A,B bounds on pseudomargina //////////////////////////////////////////////////////// std::transform(betaLo, betaLo + nNodes, A, [](double x) { return 0.5 * (tanh(x) + 1); }); std::transform(betaHi, betaHi + nNodes, B, [](double x) { return 1 - (0.5 * (tanh(x) + 1)); }); fixBounds(nNodes, A, B); return converged; }
// Return true if convergence threshold met // Output are A, B, and alpha, which must be preallocated! bool propogateBetheBound(size_t nNodes, const double *theta, const cscMatrix &W, double thresh, int maxIter, double *A, // outputs double *B, double *alpha) { double posW[nNodes], negW[nNodes]; for (size_t j = 0; j < nNodes; j++) { posW[j] = 0; negW[j] = 0; for (size_t idx = W.jc[j]; idx < W.jc[j+1]; idx++) { double w = W.pr[idx]; if (w > 0) { posW[j] += w; } else { negW[j] -= w; } alpha[idx] = exp(fabs(w)) - 1; } A[j] = sigmoid(theta[j] - negW[j]); B[j] = 1 - sigmoid(theta[j] + posW[j]); } bool converged = false; double oldA[nNodes], oldB[nNodes]; double L, U; int t; // scope it outside for debug for (t = 0; !converged && t < maxIter; t++) { std::copy(A, A + nNodes, oldA); std::copy(B, B + nNodes, oldB); for (size_t j = 0; j < nNodes; j++) { L = 1.0; U = 1.0; for (int idx = W.jc[j]; idx < W.jc[j+1]; idx++) { int i = W.ir[idx]; double a = alpha[idx]; if (W.pr[idx] > 0) { L = L * (1 + a*A[i] / (1 + a*(1 - B[j])*(1 - A[i]))); U = U * (1 + a*B[i] / (1 + a*(1 - A[j])*(1 - B[i]))); } else { L = L * (1 + a*B[i] / (1 + a*(1 - B[j])*(1 - B[i]))); U = U * (1 + a*A[i] / (1 + a*(1 - A[j])*(1 - A[i]))); } } A[j] = 1 / (1 + exp(-theta[j] + negW[j]) / L); B[j] = 1 / (1 + exp(theta[j] + posW[j]) / U); } converged = oneNormConverged(nNodes, A, oldA, thresh) && oneNormConverged(nNodes, B, oldB, thresh); } #ifndef NDEBUG mexPrintf("DEBUG: Ran for %d iterations; maxIter = %d\n", t, maxIter); #endif fixBounds(nNodes, A, B); return converged; }
Color::Color(const NVGcolor& c) noexcept : red(c.r), green(c.g), blue(c.b), alpha(c.a) { fixBounds(); }