/src/libvips/libvips/resample/templates.h
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* various interpolation templates  | 
2  |  |  */  | 
3  |  |  | 
4  |  | /*  | 
5  |  |  | 
6  |  |   This file is part of VIPS.  | 
7  |  |  | 
8  |  |   VIPS is free software; you can redistribute it and/or modify  | 
9  |  |   it under the terms of the GNU Lesser General Public License as published by  | 
10  |  |   the Free Software Foundation; either version 2 of the License, or  | 
11  |  |   (at your option) any later version.  | 
12  |  |  | 
13  |  |   This program is distributed in the hope that it will be useful,  | 
14  |  |   but WITHOUT ANY WARRANTY; without even the implied warranty of  | 
15  |  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  | 
16  |  |   GNU Lesser General Public License for more details.  | 
17  |  |  | 
18  |  |   You should have received a copy of the GNU Lesser General Public License  | 
19  |  |   along with this program; if not, write to the Free Software  | 
20  |  |   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  | 
21  |  |   02110-1301  USA  | 
22  |  |  | 
23  |  |  */  | 
24  |  |  | 
25  |  | /*  | 
26  |  |  | 
27  |  |   These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk  | 
28  |  |  | 
29  |  |  */  | 
30  |  |  | 
31  |  | #include <cstdint>  | 
32  |  |  | 
33  |  | /*  | 
34  |  |  * Various casts which assume that the data is already in range. (That  | 
35  |  |  * is, they are to be used with monotone samplers.)  | 
36  |  |  */  | 
37  |  | template <typename T>  | 
38  |  | static T inline to_fptypes(const double val)  | 
39  | 0  | { | 
40  | 0  |   const T newval = val;  | 
41  |  | 
  | 
42  | 0  |   return newval;  | 
43  | 0  | } Unexecuted instantiation: lbb.cpp:float to_fptypes<float>(double) Unexecuted instantiation: lbb.cpp:double to_fptypes<double>(double) Unexecuted instantiation: nohalo.cpp:float to_fptypes<float>(double) Unexecuted instantiation: nohalo.cpp:double to_fptypes<double>(double) Unexecuted instantiation: vsqbs.cpp:float to_fptypes<float>(double) Unexecuted instantiation: vsqbs.cpp:double to_fptypes<double>(double)  | 
44  |  |  | 
45  |  | template <typename T>  | 
46  |  | static T inline to_withsign(const double val)  | 
47  | 0  | { | 
48  | 0  |   const int sign_of_val = 2 * (val >= 0.) - 1;  | 
49  | 0  |   const int rounded_abs_val = .5 + sign_of_val * val;  | 
50  | 0  |   const T newval = sign_of_val * rounded_abs_val;  | 
51  |  | 
  | 
52  | 0  |   return newval;  | 
53  | 0  | } Unexecuted instantiation: lbb.cpp:signed char to_withsign<signed char>(double) Unexecuted instantiation: lbb.cpp:short to_withsign<short>(double) Unexecuted instantiation: lbb.cpp:int to_withsign<int>(double) Unexecuted instantiation: nohalo.cpp:signed char to_withsign<signed char>(double) Unexecuted instantiation: nohalo.cpp:short to_withsign<short>(double) Unexecuted instantiation: nohalo.cpp:int to_withsign<int>(double) Unexecuted instantiation: vsqbs.cpp:signed char to_withsign<signed char>(double) Unexecuted instantiation: vsqbs.cpp:short to_withsign<short>(double) Unexecuted instantiation: vsqbs.cpp:int to_withsign<int>(double)  | 
54  |  |  | 
55  |  | template <typename T>  | 
56  |  | static T inline to_nosign(const double val)  | 
57  | 0  | { | 
58  | 0  |   const T newval = .5 + val;  | 
59  |  | 
  | 
60  | 0  |   return newval;  | 
61  | 0  | } Unexecuted instantiation: lbb.cpp:unsigned char to_nosign<unsigned char>(double) Unexecuted instantiation: lbb.cpp:unsigned short to_nosign<unsigned short>(double) Unexecuted instantiation: lbb.cpp:unsigned int to_nosign<unsigned int>(double) Unexecuted instantiation: nohalo.cpp:unsigned char to_nosign<unsigned char>(double) Unexecuted instantiation: nohalo.cpp:unsigned short to_nosign<unsigned short>(double) Unexecuted instantiation: nohalo.cpp:unsigned int to_nosign<unsigned int>(double) Unexecuted instantiation: vsqbs.cpp:unsigned char to_nosign<unsigned char>(double) Unexecuted instantiation: vsqbs.cpp:unsigned short to_nosign<unsigned short>(double) Unexecuted instantiation: vsqbs.cpp:unsigned int to_nosign<unsigned int>(double)  | 
62  |  |  | 
63  |  | /*  | 
64  |  |  * Various bilinear implementation templates. Note that no clampling  | 
65  |  |  * is used: There is an assumption that the data is such that  | 
66  |  |  * over/underflow is not an issue:  | 
67  |  |  */  | 
68  |  |  | 
69  |  | /*  | 
70  |  |  * Bilinear interpolation for float and double types. The first four  | 
71  |  |  * inputs are weights, the last four are the corresponding pixel  | 
72  |  |  * values:  | 
73  |  |  */  | 
74  |  | template <typename T>  | 
75  |  | static T inline bilinear_fptypes(  | 
76  |  |   const double w_times_z,  | 
77  |  |   const double x_times_z,  | 
78  |  |   const double w_times_y,  | 
79  |  |   const double x_times_y,  | 
80  |  |   const double tre_thr,  | 
81  |  |   const double tre_thrfou,  | 
82  |  |   const double trequa_thr,  | 
83  |  |   const double trequa_thrfou)  | 
84  |  | { | 
85  |  |   const T newval =  | 
86  |  |     w_times_z * tre_thr +  | 
87  |  |     x_times_z * tre_thrfou +  | 
88  |  |     w_times_y * trequa_thr +  | 
89  |  |     x_times_y * trequa_thrfou;  | 
90  |  |  | 
91  |  |   return newval;  | 
92  |  | }  | 
93  |  |  | 
94  |  | /*  | 
95  |  |  * Bilinear interpolation for signed integer types:  | 
96  |  |  */  | 
97  |  | template <typename T>  | 
98  |  | static T inline bilinear_withsign(  | 
99  |  |   const double w_times_z,  | 
100  |  |   const double x_times_z,  | 
101  |  |   const double w_times_y,  | 
102  |  |   const double x_times_y,  | 
103  |  |   const double tre_thr,  | 
104  |  |   const double tre_thrfou,  | 
105  |  |   const double trequa_thr,  | 
106  |  |   const double trequa_thrfou)  | 
107  |  | { | 
108  |  |   const double val =  | 
109  |  |     w_times_z * tre_thr +  | 
110  |  |     x_times_z * tre_thrfou +  | 
111  |  |     w_times_y * trequa_thr +  | 
112  |  |     x_times_y * trequa_thrfou;  | 
113  |  |  | 
114  |  |   const int sign_of_val = 2 * (val >= 0.) - 1;  | 
115  |  |  | 
116  |  |   const int rounded_abs_val = .5 + sign_of_val * val;  | 
117  |  |  | 
118  |  |   const T newval = sign_of_val * rounded_abs_val;  | 
119  |  |  | 
120  |  |   return newval;  | 
121  |  | }  | 
122  |  |  | 
123  |  | /*  | 
124  |  |  * Bilinear Interpolation for unsigned integer types:  | 
125  |  |  */  | 
126  |  | template <typename T>  | 
127  |  | static T inline bilinear_nosign(  | 
128  |  |   const double w_times_z,  | 
129  |  |   const double x_times_z,  | 
130  |  |   const double w_times_y,  | 
131  |  |   const double x_times_y,  | 
132  |  |   const double tre_thr,  | 
133  |  |   const double tre_thrfou,  | 
134  |  |   const double trequa_thr,  | 
135  |  |   const double trequa_thrfou)  | 
136  |  | { | 
137  |  |   const T newval =  | 
138  |  |     w_times_z * tre_thr +  | 
139  |  |     x_times_z * tre_thrfou +  | 
140  |  |     w_times_y * trequa_thr +  | 
141  |  |     x_times_y * trequa_thrfou +  | 
142  |  |     0.5;  | 
143  |  |  | 
144  |  |   return newval;  | 
145  |  | }  | 
146  |  |  | 
147  |  | /*  | 
148  |  |  * Bicubic (Catmull-Rom) interpolation templates:  | 
149  |  |  */  | 
150  |  |  | 
151  |  | template <typename T>  | 
152  |  | static T inline unsigned_fixed_round(T v)  | 
153  | 0  | { | 
154  | 0  |   const int round_by = VIPS_INTERPOLATE_SCALE >> 1;  | 
155  |  | 
  | 
156  | 0  |   return (v + round_by) >> VIPS_INTERPOLATE_SHIFT;  | 
157  | 0  | } Unexecuted instantiation: reduceh.cpp:int unsigned_fixed_round<int>(int) Unexecuted instantiation: reduceh.cpp:long unsigned_fixed_round<long>(long) Unexecuted instantiation: reducev.cpp:int unsigned_fixed_round<int>(int) Unexecuted instantiation: reducev.cpp:long unsigned_fixed_round<long>(long) Unexecuted instantiation: bicubic.cpp:int unsigned_fixed_round<int>(int)  | 
158  |  |  | 
159  |  | /* Fixed-point integer bicubic, used for 8-bit types.  | 
160  |  |  */  | 
161  |  | template <typename T>  | 
162  |  | static int inline bicubic_unsigned_int(  | 
163  |  |   const T uno_one, const T uno_two, const T uno_thr, const T uno_fou,  | 
164  |  |   const T dos_one, const T dos_two, const T dos_thr, const T dos_fou,  | 
165  |  |   const T tre_one, const T tre_two, const T tre_thr, const T tre_fou,  | 
166  |  |   const T qua_one, const T qua_two, const T qua_thr, const T qua_fou,  | 
167  |  |   const int *restrict cx, const int *restrict cy)  | 
168  | 0  | { | 
169  | 0  |   const int c0 = cx[0];  | 
170  | 0  |   const int c1 = cx[1];  | 
171  | 0  |   const int c2 = cx[2];  | 
172  | 0  |   const int c3 = cx[3];  | 
173  |  | 
  | 
174  | 0  |   const int r0 = unsigned_fixed_round(  | 
175  | 0  |     c0 * uno_one +  | 
176  | 0  |     c1 * uno_two +  | 
177  | 0  |     c2 * uno_thr +  | 
178  | 0  |     c3 * uno_fou);  | 
179  | 0  |   const int r1 = unsigned_fixed_round(  | 
180  | 0  |     c0 * dos_one +  | 
181  | 0  |     c1 * dos_two +  | 
182  | 0  |     c2 * dos_thr +  | 
183  | 0  |     c3 * dos_fou);  | 
184  | 0  |   const int r2 = unsigned_fixed_round(  | 
185  | 0  |     c0 * tre_one +  | 
186  | 0  |     c1 * tre_two +  | 
187  | 0  |     c2 * tre_thr +  | 
188  | 0  |     c3 * tre_fou);  | 
189  | 0  |   const int r3 = unsigned_fixed_round(  | 
190  | 0  |     c0 * qua_one +  | 
191  | 0  |     c1 * qua_two +  | 
192  | 0  |     c2 * qua_thr +  | 
193  | 0  |     c3 * qua_fou);  | 
194  |  | 
  | 
195  | 0  |   return unsigned_fixed_round(  | 
196  | 0  |     cy[0] * r0 +  | 
197  | 0  |     cy[1] * r1 +  | 
198  | 0  |     cy[2] * r2 +  | 
199  | 0  |     cy[3] * r3);  | 
200  | 0  | }  | 
201  |  |  | 
202  |  | template <typename T>  | 
203  |  | static T inline signed_fixed_round(T v)  | 
204  | 0  | { | 
205  | 0  |   const int sign_of_v = 2 * (v >= 0) - 1;  | 
206  | 0  |   const int round_by = sign_of_v * (VIPS_INTERPOLATE_SCALE >> 1);  | 
207  |  | 
  | 
208  | 0  |   return (v + round_by) >> VIPS_INTERPOLATE_SHIFT;  | 
209  | 0  | } Unexecuted instantiation: reduceh.cpp:int signed_fixed_round<int>(int) Unexecuted instantiation: reduceh.cpp:long signed_fixed_round<long>(long) Unexecuted instantiation: reducev.cpp:int signed_fixed_round<int>(int) Unexecuted instantiation: reducev.cpp:long signed_fixed_round<long>(long) Unexecuted instantiation: bicubic.cpp:int signed_fixed_round<int>(int)  | 
210  |  |  | 
211  |  | /* Fixed-point integer bicubic, used for 8-bit types.  | 
212  |  |  */  | 
213  |  | template <typename T>  | 
214  |  | static int inline bicubic_signed_int(  | 
215  |  |   const T uno_one, const T uno_two, const T uno_thr, const T uno_fou,  | 
216  |  |   const T dos_one, const T dos_two, const T dos_thr, const T dos_fou,  | 
217  |  |   const T tre_one, const T tre_two, const T tre_thr, const T tre_fou,  | 
218  |  |   const T qua_one, const T qua_two, const T qua_thr, const T qua_fou,  | 
219  |  |   const int *restrict cx, const int *restrict cy)  | 
220  | 0  | { | 
221  | 0  |   const int c0 = cx[0];  | 
222  | 0  |   const int c1 = cx[1];  | 
223  | 0  |   const int c2 = cx[2];  | 
224  | 0  |   const int c3 = cx[3];  | 
225  |  | 
  | 
226  | 0  |   const int r0 = signed_fixed_round(  | 
227  | 0  |     c0 * uno_one +  | 
228  | 0  |     c1 * uno_two +  | 
229  | 0  |     c2 * uno_thr +  | 
230  | 0  |     c3 * uno_fou);  | 
231  | 0  |   const int r1 = signed_fixed_round(  | 
232  | 0  |     c0 * dos_one +  | 
233  | 0  |     c1 * dos_two +  | 
234  | 0  |     c2 * dos_thr +  | 
235  | 0  |     c3 * dos_fou);  | 
236  | 0  |   const int r2 = signed_fixed_round(  | 
237  | 0  |     c0 * tre_one +  | 
238  | 0  |     c1 * tre_two +  | 
239  | 0  |     c2 * tre_thr +  | 
240  | 0  |     c3 * tre_fou);  | 
241  | 0  |   const int r3 = signed_fixed_round(  | 
242  | 0  |     c0 * qua_one +  | 
243  | 0  |     c1 * qua_two +  | 
244  | 0  |     c2 * qua_thr +  | 
245  | 0  |     c3 * qua_fou);  | 
246  |  | 
  | 
247  | 0  |   return signed_fixed_round(  | 
248  | 0  |     cy[0] * r0 +  | 
249  | 0  |     cy[1] * r1 +  | 
250  | 0  |     cy[2] * r2 +  | 
251  | 0  |     cy[3] * r3);  | 
252  | 0  | }  | 
253  |  |  | 
254  |  | template <typename T>  | 
255  |  | static T inline cubic_float(  | 
256  |  |   const T one, const T two, const T thr, const T fou,  | 
257  |  |   const double *restrict cx)  | 
258  | 0  | { | 
259  | 0  |   return cx[0] * one +  | 
260  | 0  |     cx[1] * two +  | 
261  | 0  |     cx[2] * thr +  | 
262  | 0  |     cx[3] * fou;  | 
263  | 0  | } Unexecuted instantiation: bicubic.cpp:double cubic_float<double>(double, double, double, double, double const*) Unexecuted instantiation: bicubic.cpp:float cubic_float<float>(float, float, float, float, double const*)  | 
264  |  |  | 
265  |  | /* Floating-point bicubic, used for int/float/double types.  | 
266  |  |  */  | 
267  |  | template <typename T>  | 
268  |  | static T inline bicubic_float(  | 
269  |  |   const T uno_one, const T uno_two, const T uno_thr, const T uno_fou,  | 
270  |  |   const T dos_one, const T dos_two, const T dos_thr, const T dos_fou,  | 
271  |  |   const T tre_one, const T tre_two, const T tre_thr, const T tre_fou,  | 
272  |  |   const T qua_one, const T qua_two, const T qua_thr, const T qua_fou,  | 
273  |  |   const double *restrict cx, const double *restrict cy)  | 
274  | 0  | { | 
275  | 0  |   const double r0 = cubic_float<T>(  | 
276  | 0  |     uno_one, uno_two, uno_thr, uno_fou, cx);  | 
277  | 0  |   const double r1 = cubic_float<T>(  | 
278  | 0  |     dos_one, dos_two, dos_thr, dos_fou, cx);  | 
279  | 0  |   const double r2 = cubic_float<T>(  | 
280  | 0  |     tre_one, tre_two, tre_thr, tre_fou, cx);  | 
281  | 0  |   const double r3 = cubic_float<T>(  | 
282  | 0  |     qua_one, qua_two, qua_thr, qua_fou, cx);  | 
283  |  | 
  | 
284  | 0  |   return cubic_float<T>(r0, r1, r2, r3, cy);  | 
285  | 0  | } Unexecuted instantiation: bicubic.cpp:double bicubic_float<double>(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double const*, double const*) Unexecuted instantiation: bicubic.cpp:float bicubic_float<float>(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, double const*, double const*)  | 
286  |  |  | 
287  |  | /* Given an offset in [0,1] (we can have x == 1 when building tables),  | 
288  |  |  * calculate c0, c1, c2, c3, the catmull-rom coefficients. This is called  | 
289  |  |  * from the interpolator as well as from the table builder.  | 
290  |  |  */  | 
291  |  | static void inline calculate_coefficients_catmull(double c[4], const double x)  | 
292  | 65  | { | 
293  |  |   /* Nicolas believes that the following is an hitherto unknown  | 
294  |  |    * hyper-efficient method of computing Catmull-Rom coefficients. It  | 
295  |  |    * only uses 4* & 1+ & 5- for a total of only 10 flops to compute  | 
296  |  |    * four coefficients.  | 
297  |  |    */  | 
298  | 65  |   const double cr1 = 1. - x;  | 
299  | 65  |   const double cr2 = -.5 * x;  | 
300  | 65  |   const double cr3 = cr1 * cr2;  | 
301  | 65  |   const double cone = cr1 * cr3;  | 
302  | 65  |   const double cfou = x * cr3;  | 
303  | 65  |   const double cr4 = cfou - cone;  | 
304  | 65  |   const double ctwo = cr1 - cone + cr4;  | 
305  | 65  |   const double cthr = x - cfou - cr4;  | 
306  |  |  | 
307  | 65  |   g_assert(x >= 0. && x <= 1.);  | 
308  |  |  | 
309  | 65  |   c[0] = cone;  | 
310  | 65  |   c[3] = cfou;  | 
311  | 65  |   c[1] = ctwo;  | 
312  | 65  |   c[2] = cthr;  | 
313  | 65  | } Unexecuted instantiation: reduceh.cpp:calculate_coefficients_catmull(double*, double) Unexecuted instantiation: reducev.cpp:calculate_coefficients_catmull(double*, double) bicubic.cpp:calculate_coefficients_catmull(double*, double) Line  | Count  | Source  |  292  | 65  | { |  293  |  |   /* Nicolas believes that the following is an hitherto unknown  |  294  |  |    * hyper-efficient method of computing Catmull-Rom coefficients. It  |  295  |  |    * only uses 4* & 1+ & 5- for a total of only 10 flops to compute  |  296  |  |    * four coefficients.  |  297  |  |    */  |  298  | 65  |   const double cr1 = 1. - x;  |  299  | 65  |   const double cr2 = -.5 * x;  |  300  | 65  |   const double cr3 = cr1 * cr2;  |  301  | 65  |   const double cone = cr1 * cr3;  |  302  | 65  |   const double cfou = x * cr3;  |  303  | 65  |   const double cr4 = cfou - cone;  |  304  | 65  |   const double ctwo = cr1 - cone + cr4;  |  305  | 65  |   const double cthr = x - cfou - cr4;  |  306  |  |  |  307  | 65  |   g_assert(x >= 0. && x <= 1.);  |  308  |  |  |  309  | 65  |   c[0] = cone;  |  310  | 65  |   c[3] = cfou;  |  311  | 65  |   c[1] = ctwo;  |  312  | 65  |   c[2] = cthr;  |  313  | 65  | }  |  
 Unexecuted instantiation: lbb.cpp:calculate_coefficients_catmull(double*, double) Unexecuted instantiation: nohalo.cpp:calculate_coefficients_catmull(double*, double) Unexecuted instantiation: vsqbs.cpp:calculate_coefficients_catmull(double*, double)  | 
314  |  |  | 
315  |  | /* Generate a cubic filter. See:  | 
316  |  |  *  | 
317  |  |  * Mitchell and Netravali, Reconstruction Filters in Computer Graphics  | 
318  |  |  * Computer Graphics, Volume 22, Number 4, August 1988.  | 
319  |  |  *  | 
320  |  |  * B = 1,   C = 0   - cubic B-spline  | 
321  |  |  * B = 1/3, C = 1/3 - Mitchell  | 
322  |  |  * B = 0,   C = 1/2 - Catmull-Rom spline  | 
323  |  |  */  | 
324  |  | static double inline cubic_filter(double x, double B, double C)  | 
325  | 0  | { | 
326  | 0  |   const double ax = VIPS_FABS(x);  | 
327  | 0  |   const double ax2 = ax * ax;  | 
328  | 0  |   const double ax3 = ax2 * ax;  | 
329  |  | 
  | 
330  | 0  |   if (ax <= 1)  | 
331  | 0  |     return ((12 - 9 * B - 6 * C) * ax3 +  | 
332  | 0  |            (-18 + 12 * B + 6 * C) * ax2 +  | 
333  | 0  |            (6 - 2 * B)) /  | 
334  | 0  |       6;  | 
335  |  |  | 
336  | 0  |   if (ax <= 2)  | 
337  | 0  |     return ((-B - 6 * C) * ax3 +  | 
338  | 0  |            (6 * B + 30 * C) * ax2 +  | 
339  | 0  |            (-12 * B - 48 * C) * ax +  | 
340  | 0  |            (8 * B + 24 * C)) /  | 
341  | 0  |       6;  | 
342  |  |  | 
343  | 0  |   return 0.0;  | 
344  | 0  | } Unexecuted instantiation: reduceh.cpp:cubic_filter(double, double, double) Unexecuted instantiation: reducev.cpp:cubic_filter(double, double, double) Unexecuted instantiation: bicubic.cpp:cubic_filter(double, double, double) Unexecuted instantiation: lbb.cpp:cubic_filter(double, double, double) Unexecuted instantiation: nohalo.cpp:cubic_filter(double, double, double) Unexecuted instantiation: vsqbs.cpp:cubic_filter(double, double, double)  | 
345  |  |  | 
346  |  | static double inline sinc_filter(double x)  | 
347  | 0  | { | 
348  | 0  |   if (x == 0.0)  | 
349  | 0  |     return 1.0;  | 
350  |  |  | 
351  | 0  |   x = x * VIPS_PI;  | 
352  |  | 
  | 
353  | 0  |   return sin(x) / x;  | 
354  | 0  | } Unexecuted instantiation: reduceh.cpp:sinc_filter(double) Unexecuted instantiation: reducev.cpp:sinc_filter(double) Unexecuted instantiation: bicubic.cpp:sinc_filter(double) Unexecuted instantiation: lbb.cpp:sinc_filter(double) Unexecuted instantiation: nohalo.cpp:sinc_filter(double) Unexecuted instantiation: vsqbs.cpp:sinc_filter(double)  | 
355  |  |  | 
356  |  | using VipsFilterFn = double (*)(double);  | 
357  |  |  | 
358  |  | template <VipsKernel K>  | 
359  |  | static double inline filter(double x);  | 
360  |  |  | 
361  |  | template <>  | 
362  |  | double inline filter<VIPS_KERNEL_LINEAR>(double x)  | 
363  | 0  | { | 
364  | 0  |   x = VIPS_FABS(x);  | 
365  |  | 
  | 
366  | 0  |   if (x < 1.0)  | 
367  | 0  |     return 1.0 - x;  | 
368  |  |  | 
369  | 0  |   return 0.0;  | 
370  | 0  | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)1>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)1>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)1>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)1>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)1>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)1>(double)  | 
371  |  |  | 
372  |  | /* Catmull-Rom.  | 
373  |  |  */  | 
374  |  | template <>  | 
375  |  | double inline filter<VIPS_KERNEL_CUBIC>(double x)  | 
376  | 0  | { | 
377  | 0  |   return cubic_filter(x, 0.0, 0.5);  | 
378  | 0  | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)2>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)2>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)2>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)2>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)2>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)2>(double)  | 
379  |  |  | 
380  |  | template <>  | 
381  |  | double inline filter<VIPS_KERNEL_MITCHELL>(double x)  | 
382  | 0  | { | 
383  | 0  |   return cubic_filter(x, 1.0 / 3.0, 1.0 / 3.0);  | 
384  | 0  | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)3>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)3>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)3>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)3>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)3>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)3>(double)  | 
385  |  |  | 
386  |  | template <>  | 
387  |  | double inline filter<VIPS_KERNEL_LANCZOS2>(double x)  | 
388  | 0  | { | 
389  | 0  |   if (x >= -2 && x <= 2)  | 
390  | 0  |     return sinc_filter(x) * sinc_filter(x / 2);  | 
391  |  |  | 
392  | 0  |   return 0.0;  | 
393  | 0  | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)4>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)4>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)4>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)4>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)4>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)4>(double)  | 
394  |  |  | 
395  |  | template <>  | 
396  |  | double inline filter<VIPS_KERNEL_LANCZOS3>(double x)  | 
397  | 0  | { | 
398  | 0  |   if (x >= -3 && x <= 3)  | 
399  | 0  |     return sinc_filter(x) * sinc_filter(x / 3);  | 
400  |  |  | 
401  | 0  |   return 0.0;  | 
402  | 0  | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)5>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)5>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)5>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)5>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)5>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)5>(double)  | 
403  |  |  | 
404  |  | template <>  | 
405  |  | double inline filter<VIPS_KERNEL_MKS2013>(double x)  | 
406  | 0  | { | 
407  | 0  |   x = VIPS_FABS(x);  | 
408  |  | 
  | 
409  | 0  |   if (x >= 2.5)  | 
410  | 0  |     return 0.0;  | 
411  |  |  | 
412  | 0  |   if (x >= 1.5)  | 
413  | 0  |     return (x - 5.0 / 2.0) * (x - 5.0 / 2.0) / -8.0;  | 
414  |  |  | 
415  | 0  |   if (x >= 0.5)  | 
416  | 0  |     return (4.0 * x * x - 11.0 * x + 7.0) / 4.0;  | 
417  |  |  | 
418  | 0  |   return 17.0 / 16.0 - 7.0 * x * x / 4.0;  | 
419  | 0  | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)6>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)6>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)6>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)6>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)6>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)6>(double)  | 
420  |  |  | 
421  |  | template <>  | 
422  |  | double inline filter<VIPS_KERNEL_MKS2021>(double x)  | 
423  | 0  | { | 
424  | 0  |   x = VIPS_FABS(x);  | 
425  |  | 
  | 
426  | 0  |   if (x >= 4.5)  | 
427  | 0  |     return 0.0;  | 
428  |  |  | 
429  | 0  |   if (x >= 3.5)  | 
430  | 0  |     return (4.0 * x * x - 36.0 * x + 81.0) / -1152.0;  | 
431  |  |  | 
432  | 0  |   if (x >= 2.5)  | 
433  | 0  |     return (4.0 * x * x - 27.0 * x + 45.0) / 144.0;  | 
434  |  |  | 
435  | 0  |   if (x >= 1.5)  | 
436  | 0  |     return (24.0 * x * x - 113.0 * x + 130.0) / -144.0;  | 
437  |  |  | 
438  | 0  |   if (x >= 0.5)  | 
439  | 0  |     return (140.0 * x * x - 379.0 * x + 239.0) / 144.0;  | 
440  |  |  | 
441  | 0  |   return 577.0 / 576.0 - 239.0 * x * x / 144.0;  | 
442  | 0  | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)7>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)7>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)7>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)7>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)7>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)7>(double)  | 
443  |  |  | 
444  |  | /* Given an x in [0,1] (we can have x == 1 when building tables),  | 
445  |  |  * calculate c0 .. c(@n_points), the coefficients. This is called  | 
446  |  |  * from the interpolator as well as from the table builder.  | 
447  |  |  *  | 
448  |  |  * @shrink is the reduction factor, so 1 for interpolation, 2 for a  | 
449  |  |  * x2 reduction, etc.  | 
450  |  |  */  | 
451  |  | template <typename T>  | 
452  |  | static void  | 
453  |  | calculate_coefficients(T *c, const int n_points,  | 
454  |  |   VipsFilterFn filter_fn, const double shrink, const double x)  | 
455  | 0  | { | 
456  | 0  |   const double half = x + n_points / 2.0 - 1;  | 
457  |  | 
  | 
458  | 0  |   int i;  | 
459  | 0  |   T sum;  | 
460  |  | 
  | 
461  | 0  |   sum = 0.0;  | 
462  | 0  |   for (i = 0; i < n_points; i++) { | 
463  | 0  |     const double xp = (i - half) / shrink;  | 
464  | 0  |     double l = filter_fn(xp);  | 
465  |  | 
  | 
466  | 0  |     c[i] = l;  | 
467  | 0  |     sum += l;  | 
468  | 0  |   }  | 
469  |  | 
  | 
470  | 0  |   for (i = 0; i < n_points; i++)  | 
471  | 0  |     c[i] /= sum;  | 
472  | 0  | } Unexecuted instantiation: reduceh.cpp:void calculate_coefficients<double>(double*, int, double (*)(double), double, double) Unexecuted instantiation: reduceh.cpp:void calculate_coefficients<long double>(long double*, int, double (*)(double), double, double) Unexecuted instantiation: reducev.cpp:void calculate_coefficients<double>(double*, int, double (*)(double), double, double) Unexecuted instantiation: reducev.cpp:void calculate_coefficients<long double>(long double*, int, double (*)(double), double, double)  | 
473  |  |  | 
474  |  | /* Calculate a mask element.  | 
475  |  |  */  | 
476  |  | template <typename T>  | 
477  |  | static void  | 
478  |  | vips_reduce_make_mask(T *c, VipsKernel kernel, const int n_points,  | 
479  |  |   const double shrink, const double x)  | 
480  | 0  | { | 
481  | 0  |   switch (kernel) { | 
482  | 0  |   case VIPS_KERNEL_NEAREST:  | 
483  | 0  |     c[0] = 1.0;  | 
484  | 0  |     break;  | 
485  |  |  | 
486  | 0  |   case VIPS_KERNEL_LINEAR:  | 
487  | 0  |     calculate_coefficients(c, n_points,  | 
488  | 0  |       filter<VIPS_KERNEL_LINEAR>, shrink, x);  | 
489  | 0  |     break;  | 
490  |  |  | 
491  | 0  |   case VIPS_KERNEL_CUBIC:  | 
492  | 0  |     calculate_coefficients(c, n_points,  | 
493  | 0  |       filter<VIPS_KERNEL_CUBIC>, shrink, x);  | 
494  | 0  |     break;  | 
495  |  |  | 
496  | 0  |   case VIPS_KERNEL_MITCHELL:  | 
497  | 0  |     calculate_coefficients(c, n_points,  | 
498  | 0  |       filter<VIPS_KERNEL_MITCHELL>, shrink, x);  | 
499  | 0  |     break;  | 
500  |  |  | 
501  | 0  |   case VIPS_KERNEL_LANCZOS2:  | 
502  | 0  |     calculate_coefficients(c, n_points,  | 
503  | 0  |       filter<VIPS_KERNEL_LANCZOS2>, shrink, x);  | 
504  | 0  |     break;  | 
505  |  |  | 
506  | 0  |   case VIPS_KERNEL_LANCZOS3:  | 
507  | 0  |     calculate_coefficients(c, n_points,  | 
508  | 0  |       filter<VIPS_KERNEL_LANCZOS3>, shrink, x);  | 
509  | 0  |     break;  | 
510  |  |  | 
511  | 0  |   case VIPS_KERNEL_MKS2013:  | 
512  | 0  |     calculate_coefficients(c, n_points,  | 
513  | 0  |       filter<VIPS_KERNEL_MKS2013>, shrink, x);  | 
514  | 0  |     break;  | 
515  |  |  | 
516  | 0  |   case VIPS_KERNEL_MKS2021:  | 
517  | 0  |     calculate_coefficients(c, n_points,  | 
518  | 0  |       filter<VIPS_KERNEL_MKS2021>, shrink, x);  | 
519  | 0  |     break;  | 
520  |  |  | 
521  | 0  |   default:  | 
522  | 0  |     g_assert_not_reached();  | 
523  | 0  |     break;  | 
524  | 0  |   }  | 
525  | 0  | } Unexecuted instantiation: reduceh.cpp:void vips_reduce_make_mask<double>(double*, VipsKernel, int, double, double) Unexecuted instantiation: reduceh.cpp:void vips_reduce_make_mask<long double>(long double*, VipsKernel, int, double, double) Unexecuted instantiation: reducev.cpp:void vips_reduce_make_mask<double>(double*, VipsKernel, int, double, double) Unexecuted instantiation: reducev.cpp:void vips_reduce_make_mask<long double>(long double*, VipsKernel, int, double, double)  | 
526  |  |  | 
527  |  | /* Machinery to promote type T to a larger data type, prevents an  | 
528  |  |  * overflow in reduce_sum(). Defaults to a 32-bit integral type.  | 
529  |  |  */  | 
530  |  | template <typename T>  | 
531  |  | struct LongT { | 
532  |  |   typedef int32_t type;  | 
533  |  | };  | 
534  |  |  | 
535  |  | /* 32-bit integral types needs a 64-bits intermediate.  | 
536  |  |  */  | 
537  |  | template <>  | 
538  |  | struct LongT<int32_t> { | 
539  |  |   typedef int64_t type;  | 
540  |  | };  | 
541  |  |  | 
542  |  | template <>  | 
543  |  | struct LongT<uint32_t> { | 
544  |  |   typedef int64_t type;  | 
545  |  | };  | 
546  |  |  | 
547  |  | /* 32-bit floating-point types needs a 64-bits intermediate.  | 
548  |  |  */  | 
549  |  | template <>  | 
550  |  | struct LongT<float> { | 
551  |  |   typedef double type;  | 
552  |  | };  | 
553  |  |  | 
554  |  | /* 64-bit floating-point types needs a 128-bits intermediate.  | 
555  |  |  */  | 
556  |  | template <>  | 
557  |  | struct LongT<double> { | 
558  |  |   typedef long double type;  | 
559  |  | };  | 
560  |  |  | 
561  |  | /* Our inner loop for resampling with a convolution of type CT. Operate on  | 
562  |  |  * elements of type T, gather results in an intermediate of type IT.  | 
563  |  |  */  | 
564  |  | template <typename T, typename CT, typename IT = typename LongT<T>::type>  | 
565  |  | static IT inline reduce_sum(const T *restrict in, int stride,  | 
566  |  |   const CT *restrict c, int n)  | 
567  | 0  | { | 
568  | 0  |   IT sum;  | 
569  |  | 
  | 
570  | 0  |   sum = 0;  | 
571  | 0  |   for (int i = 0; i < n; i++) { | 
572  | 0  |     sum += (IT) c[i] * in[0];  | 
573  | 0  |     in += stride;  | 
574  | 0  |   }  | 
575  |  | 
  | 
576  | 0  |   return sum;  | 
577  | 0  | } Unexecuted instantiation: reduceh.cpp:int reduce_sum<unsigned char, short, int>(unsigned char const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:int reduce_sum<signed char, short, int>(signed char const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:int reduce_sum<unsigned short, short, int>(unsigned short const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:int reduce_sum<short, short, int>(short const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:long reduce_sum<unsigned int, short, long>(unsigned int const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:long reduce_sum<int, short, long>(int const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:double reduce_sum<float, double, double>(float const*, int, double const*, int) Unexecuted instantiation: reduceh.cpp:long double reduce_sum<double, long double, long double>(double const*, int, long double const*, int) Unexecuted instantiation: reducev.cpp:int reduce_sum<unsigned char, short, int>(unsigned char const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:int reduce_sum<signed char, short, int>(signed char const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:int reduce_sum<unsigned short, short, int>(unsigned short const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:int reduce_sum<short, short, int>(short const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:long reduce_sum<unsigned int, short, long>(unsigned int const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:long reduce_sum<int, short, long>(int const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:double reduce_sum<float, double, double>(float const*, int, double const*, int) Unexecuted instantiation: reducev.cpp:long double reduce_sum<double, long double, long double>(double const*, int, long double const*, int)  |