| 1195 | return l / (y1 - y2) * time; |
| 1196 | } |
| 1197 | static double SolveIntegrateInverseInterpolated(double y1, double y2, double time, double area, bool logarithmic) |
| 1198 | { |
| 1199 | // Calculates: solve (integral(1 / interpolate(y1, y2, x), x = 0 .. res) = area) for res |
| 1200 | // Don't try to derive these formulas by hand :). The threshold is 1.0e5 again. |
| 1201 | double a = area / time, res; |
| 1202 | if(logarithmic) |
| 1203 | { |
| 1204 | double l = log(y1 / y2); |
| 1205 | if(fabs(l) < 1.0e-5) // fall back to average |
| 1206 | res = a * (y1 + y2) * 0.5; |
| 1207 | else if(1.0 + a * y1 * l <= 0.0) |
| 1208 | res = 1.0; |
| 1209 | else |
| 1210 | res = log1p(a * y1 * l) / l; |
| 1211 | } |
| 1212 | else |
| 1213 | { |
| 1214 | if(fabs(y2 - y1) < 1.0e-5) // fall back to average |
| 1215 | res = a * (y1 + y2) * 0.5; |
| 1216 | else |
| 1217 | res = y1 * expm1(a * (y2 - y1)) / (y2 - y1); |
| 1218 | } |
| 1219 | return std::max(0.0, std::min(1.0, res)) * time; |
| 1220 | } |
| 1221 | |
| 1222 | // We should be able to write a very efficient memoizer for this |
| 1223 | // but make sure it gets reset when the envelope is changed. |
no test coverage detected