datasketches-cpp
Loading...
Searching...
No Matches
CubicInterpolation-internal.hpp
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#ifndef _CUBICINTERPOLATION_INTERNAL_HPP_
21#define _CUBICINTERPOLATION_INTERNAL_HPP_
22
23#include "CubicInterpolation.hpp"
24
25#include <string>
26#include <stdexcept>
27
28namespace datasketches {
29
30template<typename A>
31static double interpolateUsingXAndYTables(const double xArr[], const double yArr[], const int offset, const double x);
32
33template<typename A>
34static double cubicInterpolate(const double x0, const double y0, const double x1, const double y1,
35 const double x2, const double y2, const double x3, const double y3, const double x);
36
37template<typename A>
38static int findStraddle(const double xArr[], const int len, const double x);
39
40template<typename A>
41static int recursiveFindStraddle(const double xArr[], const int l, const int r, const double x);
42
43template<typename A>
44static double interpolateUsingXArrAndYStride(const double xArr[], const double yStride,
45 const int offset, const double x);
46
47const int numEntries = 40;
48
49//Computed for Coupon lgK = 26 ONLY. Designed for the cubic interpolator function.
50const double xArrComputed[numEntries] = {
51 0.0, 1.0, 20.0, 400.0,
52 8000.0, 160000.0, 300000.0, 600000.0,
53 900000.0, 1200000.0, 1500000.0, 1800000.0,
54 2100000.0, 2400000.0, 2700000.0, 3000000.0,
55 3300000.0, 3600000.0, 3900000.0, 4200000.0,
56 4500000.0, 4800000.0, 5100000.0, 5400000.0,
57 5700000.0, 6000000.0, 6300000.0, 6600000.0,
58 6900000.0, 7200000.0, 7500000.0, 7800000.0,
59 8100000.0, 8400000.0, 8700000.0, 9000000.0,
60 9300000.0, 9600000.0, 9900000.0, 10200000.0
61};
62
63//Computed for Coupon lgK = 26 ONLY. Designed for the cubic interpolator function.
64const double yArrComputed[numEntries] = {
65 0.0000000000000000, 1.0000000000000000, 20.0000009437402611, 400.0003963713384110,
66 8000.1589294602090376, 160063.6067763759638183, 300223.7071597663452849, 600895.5933856170158833,
67 902016.8065120954997838, 1203588.4983199508860707, 1505611.8245524743106216, 1808087.9449319066479802,
68 2111018.0231759352609515, 2414403.2270142501220107, 2718244.7282051891088486, 3022543.7025524540804327,
69 3327301.3299219091422856, 3632518.7942584538832307, 3938197.2836029687896371, 4244337.9901093561202288,
70 4550942.1100616492331028, 4858010.8438911894336343, 5165545.3961938973516226, 5473546.9757476449012756,
71 5782016.7955296505242586, 6090956.0727340159937739, 6400366.0287892958149314, 6710247.8893762007355690,
72 7020602.8844453142955899, 7331432.2482349723577499, 7642737.2192891482263803, 7954519.0404754765331745,
73 8266778.9590033423155546, 8579518.2264420464634895, 8892738.0987390466034412, 9206439.8362383283674717,
74 9520624.7036988288164139, 9835293.9703129194676876, 10150448.9097250290215015, 10466090.8000503256917000
75};
76
77template<typename A>
78double CubicInterpolation<A>::usingXAndYTables(const double x) {
79 return usingXAndYTables(xArrComputed, yArrComputed, numEntries, x);
80}
81
82template<typename A>
83double CubicInterpolation<A>::usingXAndYTables(const double xArr[], const double yArr[],
84 const int len, const double x) {
85 int offset;
86 if (x < xArr[0] || x > xArr[len-1]) {
87 throw std::invalid_argument("x value out of range: " + std::to_string(x));
88 }
89
90 if (x == xArr[len-1]) { // corner case
91 return (yArr[len-1]);
92 }
93
94 offset = findStraddle<A>(xArr, len, x);
95 if (offset < 0 && offset > len-2) {
96 throw std::logic_error("offset must be >= 0 and <= " + std::to_string(len) + "-2");
97 }
98
99 if (offset == 0) { // corner case
100 return (interpolateUsingXAndYTables<A>(xArr, yArr, (offset-0), x));
101 }
102 else if (offset == numEntries-2) { // corner case
103 return (interpolateUsingXAndYTables<A>(xArr, yArr, (offset-2), x));
104 }
105 // main case
106 return (interpolateUsingXAndYTables<A>(xArr, yArr, (offset-1), x));
107}
108
109// In C: again-two-registers cubic_interpolate_aux L1368
110template<typename A>
111static double interpolateUsingXAndYTables(const double xArr[], const double yArr[],
112 const int offset, const double x) {
113 return (cubicInterpolate<A>(xArr[offset+0], yArr[offset+0],
114 xArr[offset+1], yArr[offset+1],
115 xArr[offset+2], yArr[offset+2],
116 xArr[offset+3], yArr[offset+3],
117 x) );
118}
119
120template<typename A>
121static inline double cubicInterpolate(const double x0, const double y0,
122 const double x1, const double y1,
123 const double x2, const double y2,
124 const double x3, const double y3,
125 const double x)
126{
127 double l0_numer = (x - x1) * (x - x2) * (x - x3);
128 double l1_numer = (x - x0) * (x - x2) * (x - x3);
129 double l2_numer = (x - x0) * (x - x1) * (x - x3);
130 double l3_numer = (x - x0) * (x - x1) * (x - x2);
131
132 double l0_denom = (x0 - x1) * (x0 - x2) * (x0 - x3);
133 double l1_denom = (x1 - x0) * (x1 - x2) * (x1 - x3);
134 double l2_denom = (x2 - x0) * (x2 - x1) * (x2 - x3);
135 double l3_denom = (x3 - x0) * (x3 - x1) * (x3 - x2);
136
137 double term0 = y0 * l0_numer / l0_denom;
138 double term1 = y1 * l1_numer / l1_denom;
139 double term2 = y2 * l2_numer / l2_denom;
140 double term3 = y3 * l3_numer / l3_denom;
141
142 return (term0 + term1 + term2 + term3);
143}
144
145/* returns j such that xArr[j] <= x and x < xArr[j+1] */
146template<typename A>
147static int findStraddle(const double xArr[], const int len, const double x)
148{
149 if ((len < 2) || (x < xArr[0]) || (x > xArr[len-1])) {
150 throw std::logic_error("invariant violated during interpolation");
151 }
152 return(recursiveFindStraddle<A>(xArr, 0, len-1, x));
153}
154
155
156/* the invariant here is that xArr[l] <= x && x < xArr[r] */
157template<typename A>
158static int recursiveFindStraddle(const double xArr[], const int l, const int r, const double x)
159{
160 int m;
161 if (l >= r) {
162 throw std::logic_error("lower bound not less than upper bound in search");
163 }
164 if ((xArr[l] > x) || (x >= xArr[r])) { // the invariant
165 throw std::logic_error("target value invariant violated in search");
166 }
167
168 if (l+1 == r) return (l);
169 m = l + ((r-l)/2);
170 if (xArr[m] <= x) return (recursiveFindStraddle<A>(xArr, m, r, x));
171 else return (recursiveFindStraddle<A>(xArr, l, m, x));
172}
173
174
175//Interpolate using X table and Y stride
176
186//In C: again-two-registers cubic_interpolate_with_x_arr_and_y_stride L1411
187// Used by HllEstimators
188template<typename A>
189double CubicInterpolation<A>::usingXArrAndYStride(const double xArr[], const int xArrLen,
190 const double yStride, const double x) {
191 const int xArrLenM1 = xArrLen - 1;
192
193 if ((xArrLen < 4) || (x < xArr[0]) || (x > xArr[xArrLenM1])) {
194 throw std::logic_error("impossible values during interpolaiton");
195 }
196
197 if (x == xArr[xArrLenM1]) { /* corner case */
198 return (yStride * (xArrLenM1));
199 }
200
201 const int offset = findStraddle<A>(xArr, xArrLen, x); //uses recursion
202 const int xArrLenM2 = xArrLen - 2;
203 if ((offset < 0) || (offset > xArrLenM2)) {
204 throw std::logic_error("invalid offset during interpolation");
205 }
206
207 if (offset == 0) { /* corner case */
208 return (interpolateUsingXArrAndYStride<A>(xArr, yStride, (offset - 0), x));
209 }
210 else if (offset == xArrLenM2) { /* corner case */
211 return (interpolateUsingXArrAndYStride<A>(xArr, yStride, (offset - 2), x));
212 }
213 /* main case */
214 return (interpolateUsingXArrAndYStride<A>(xArr, yStride, (offset - 1), x));
215}
216
217//In C: again-two-registers cubic_interpolate_with_x_arr_and_y_stride_aux L1402
218template<typename A>
219static double interpolateUsingXArrAndYStride(const double xArr[], const double yStride,
220 const int offset, const double x) {
221 return cubicInterpolate<A>(
222 xArr[offset + 0], yStride * (offset + 0),
223 xArr[offset + 1], yStride * (offset + 1),
224 xArr[offset + 2], yStride * (offset + 2),
225 xArr[offset + 3], yStride * (offset + 3),
226 x);
227}
228
229}
230
231#endif // _CUBICINTERPOLATION_INTERNAL_HPP_
DataSketches namespace.
Definition binomial_bounds.hpp:38