28 {
31
33
34 if (numberOfSamples < 3) {
35 samples.push_back({a, 0.0, 0.0});
37 return;
38 }
39
40
41 const double domainSize =
b - a;
42 const double intervalSize = domainSize / static_cast<double>(numberOfSamples - 1);
43 double sum = 0.0;
44 double lastX, lastY, lastSum;
45 size_t effectiveNumberOfSamples = numberOfSamples;
46
47
48
49 {
50 for (size_t i = 0; i < numberOfSamples; ++i) {
51 const double x = a + intervalSize *
static_cast<double>(i);
52 const double y =
f(x);
53 if (y > 0.0) {
54 if (i > 0) {
55 a += intervalSize * static_cast<double>(i - 1);
56 effectiveNumberOfSamples -= i - 1;
57 }
58 break;
59 }
60 if (i == numberOfSamples - 1) {
61
62 return;
63 }
64 }
65
66 for (size_t i = 0; i < numberOfSamples; ++i) {
67 const double x =
b - intervalSize *
static_cast<double>(i);
68 const double y =
f(x);
69 if (y > 0.0) {
70 if (i > 0) {
71 b -= intervalSize *
static_cast<double>(i - 1);
72 effectiveNumberOfSamples -= i - 1;
73 }
74 break;
75 }
76 }
77 }
78
79 {
80 samples.push_back({a, 0.0, 0.0});
81 lastX = a;
83 lastSum = 0.0;
84 }
85
86 {
87
88
89 constexpr double maximumAngleDeviationToSkip{
M_PI / 1000.0};
90 double referenceAngle = 0.0;
91 bool mustCheckAngle = false;
92 int skippedPoints = 0;
93
94 for (size_t i = 1; i < effectiveNumberOfSamples; ++i) {
95 const double x = a + intervalSize *
static_cast<double>(i);
96 const double y =
f(x);
97
98 sum += (
x - lastX) * (y + lastY) / 2.0;
99
100 if (y == 0.0) {
101 if (lastY == 0.0) {
104 lastSum = sum;
105 ++skippedPoints;
106 continue;
107 } else {
108 mustCheckAngle = false;
109 }
110 } else {
111 if (lastY == 0.0) {
112 if (skippedPoints > 0) {
113 samples.push_back({lastX, lastSum, 0.0});
114 }
115 mustCheckAngle = false;
116 }
117 }
118
119
120 if (i > 1 && mustCheckAngle) {
121 const int nPoints =
samples.size();
122 const double angle = std::atan2(sum -
samples[nPoints - 2].cdfAtX, x -
samples[nPoints - 2].x);
123 if (std::abs(angle - referenceAngle) <= maximumAngleDeviationToSkip) {
126 continue;
127 }
128 }
129
131 referenceAngle = std::atan2(sum - lastSum, x - lastX);
132 mustCheckAngle = true;
133 skippedPoints = 0;
134
137 lastSum = sum;
138 }
139 }
140
141 {
142 for (
size_t i = 1; i <
samples.size() - 1; ++i) {
145 }
148 }
149 }
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)