Coverage Report

Created: 2025-01-28 06:34

/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)