00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <float.h>
00040 #include <math.h>
00041 #include <stddef.h>
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044
00045
00046
00047 #include "bspline_coeff.h"
00048
00049
00050 #define BLKSZ_FLT 18
00051 #define BLKSZ_DBL 8
00052
00053 #define HORIZON (18)
00054
00055
00056
00057
00058
00059
00060
00061 static void fConvertToInterpolationCoefficients
00062 (
00063 float c[],
00064 long DataLength,
00065 float z[],
00066 long NbPoles,
00067 float Tolerance
00068 );
00069
00070 static inline float fInitialCausalCoefficient
00071 (
00072 float c[],
00073 long DataLength,
00074 float z,
00075 float Tolerance
00076 );
00077
00078
00079
00080
00081 static void fConvertToInterpolationCoefficients
00082 (
00083 float c[],
00084 long DataLength,
00085 float z[],
00086 long NbPoles,
00087 float Tolerance
00088 )
00089 {
00090 float Lambda = 1.0f;
00091 long n, k;
00092
00093 if (DataLength == 1L) {
00094 return;
00095 }
00096
00097 for (k = 0L; k < NbPoles; k++) {
00098 Lambda = Lambda * (1.0f - z[k]) * (1.0f - 1.0f / z[k]);
00099 }
00100
00101 for (n = 0L; n < DataLength; n++) {
00102 c[n] *= Lambda;
00103 }
00104
00105
00106 for (k = 0L; k < NbPoles; k++) {
00107
00108 c[0] = fInitialCausalCoefficient(c, DataLength, z[k], Tolerance);
00109
00110 for (n = 1L; n < DataLength; n++) {
00111 c[n] += z[k] * c[n - 1L];
00112 }
00113
00114 c[DataLength - 1L] = (z[k] / (z[k] * z[k] - 1.0f)) *
00115 (z[k] * c[DataLength - 2L] + c[DataLength - 1L]);
00116
00117 for (n = DataLength - 2L; 0 <= n; n--) {
00118 c[n] = z[k] * (c[n + 1L] - c[n]);
00119 }
00120 }
00121 }
00122
00123 static inline float fInitialCausalCoefficient
00124 (
00125 float c[],
00126 long DataLength,
00127 float z,
00128 float Tolerance
00129 )
00130 {
00131 float Sum, zn, z2n, iz;
00132 long n, Horizon;
00133
00134 Horizon = DataLength;
00135 if (Tolerance > 0.0f) {
00136 Horizon = (long)ceilf(logf(Tolerance) / logf(fabsf(z)));
00137 }
00138
00139 if (Horizon < DataLength) {
00140
00141 Sum = 0.0f;
00142 for (n = Horizon-1; n >= 0; n--)
00143 Sum = z * Sum + c[n];
00144 return(Sum);
00145 }
00146 else {
00147
00148 zn = z;
00149 iz = 1.0f / z;
00150 z2n = powf(z, (float)(DataLength - 1L));
00151 Sum = c[0] + z2n * c[DataLength - 1L];
00152 z2n *= z2n * iz;
00153 for (n = 1L; n <= DataLength - 2L; n++) {
00154 Sum += (zn + z2n) * c[n];
00155 zn *= z;
00156 z2n *= iz;
00157 }
00158 return(Sum / (1.0f - zn * zn));
00159 }
00160 }
00161
00162
00163
00164
00165
00166 extern int fSamplesToCoefficients
00167 (
00168 float *Image,
00169 long Width,
00170 long Height,
00171 long SplineDegree
00172 )
00173 {
00174 float *Line;
00175 float Pole[2];
00176 long NbPoles;
00177 long x, y,xb,xmax;
00178
00179 switch (SplineDegree) {
00180 case 2L:
00181 NbPoles = 1L;
00182 Pole[0] = sqrtf(8.0f) - 3.0f;
00183 break;
00184 case 3L:
00185 NbPoles = 1L;
00186 Pole[0] = sqrtf(3.0f) - 2.0f;
00187 break;
00188 case 4L:
00189 NbPoles = 2L;
00190 Pole[0] = sqrtf(664.0f - sqrtf(438976.0f)) + sqrtf(304.0f) - 19.0f;
00191 Pole[1] = sqrtf(664.0f + sqrtf(438976.0f)) - sqrtf(304.0f) - 19.0f;
00192 break;
00193 case 5L:
00194 NbPoles = 2L;
00195 Pole[0] = sqrtf(135.0f / 2.0f - sqrtf(17745.0f / 4.0f)) +
00196 sqrtf(105.0f / 4.0f) - 13.0f / 2.0f;
00197 Pole[1] = sqrtf(135.0f / 2.0f + sqrtf(17745.0f / 4.0f)) -
00198 sqrtf(105.0f / 4.0f) - 13.0f / 2.0f;
00199 break;
00200 default:
00201 printf("Invalid spline degree\n");
00202 return(1);
00203 }
00204
00205
00206 for (y = 0L; y < Height; y++) {
00207 fConvertToInterpolationCoefficients(&Image[y*Width], Width, Pole, NbPoles,
00208 FLT_EPSILON);
00209 }
00210
00211
00212 Line = (float *) malloc((size_t)(BLKSZ_FLT*Height * (long)sizeof(float)));
00213 if (Line == (float *)NULL) {
00214 printf("Workspace allocation failed\n");
00215 return(1);
00216 }
00217
00218 for (xb = 0L; xb<Width; xb += BLKSZ_FLT)
00219 {
00220 xmax = (xb+BLKSZ_FLT>Width?Width:xb+BLKSZ_FLT);
00221 for (x = xb; x < xmax; x++)
00222 {
00223 for (y = 0L; y < Height; y++)
00224 Line[y+(x-xb)*Height] = Image[y*Width+x];
00225 fConvertToInterpolationCoefficients(&Line[(x-xb)*Height], Height, Pole,
00226 NbPoles, FLT_EPSILON);
00227 }
00228
00229 for (y = 0L; y < Height; y++)
00230 for (x = xb; x < xmax; x++)
00231 Image[y*Width+x] = Line[y+(x-xb)*Height];
00232 }
00233 free(Line);
00234 return(0);
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 static void dConvertToInterpolationCoefficients
00248 (
00249 double c[],
00250 long DataLength,
00251 double z[],
00252 long NbPoles,
00253 double Tolerance
00254 );
00255
00256 static inline double dInitialCausalCoefficient
00257 (
00258 double c[],
00259 long DataLength,
00260 double z,
00261 double Tolerance
00262 );
00263
00264 static inline double dInitialAntiCausalCoefficient
00265 (
00266 double c[],
00267 long DataLength,
00268 double z
00269 );
00270
00271
00272
00273
00274 static void dConvertToInterpolationCoefficients
00275 (
00276 double c[],
00277 long DataLength,
00278 double z[],
00279 long NbPoles,
00280 double Tolerance
00281 )
00282 {
00283 double Lambda = 1.0;
00284 long n, k;
00285
00286 if (DataLength == 1L) {
00287 return;
00288 }
00289
00290 for (k = 0L; k < NbPoles; k++) {
00291 Lambda = Lambda * (1.0 - z[k]) * (1.0 - 1.0 / z[k]);
00292 }
00293
00294 for (n = 0L; n < DataLength; n++) {
00295 c[n] *= Lambda;
00296 }
00297
00298 for (k = 0L; k < NbPoles; k++) {
00299
00300 c[0] = dInitialCausalCoefficient(c, DataLength, z[k], Tolerance);
00301
00302 for (n = 1L; n < DataLength; n++) {
00303 c[n] += z[k] * c[n - 1L];
00304 }
00305
00306 c[DataLength - 1L] = dInitialAntiCausalCoefficient(c, DataLength, z[k]);
00307
00308 for (n = DataLength - 2L; 0 <= n; n--) {
00309 c[n] = z[k] * (c[n + 1L] - c[n]);
00310 }
00311 }
00312 }
00313
00314 static double dInitialCausalCoefficient
00315 (
00316 double c[],
00317 long DataLength,
00318 double z,
00319 double Tolerance
00320 )
00321 {
00322 double Sum, zn, z2n, iz;
00323 long n, Horizon;
00324
00325 Horizon = DataLength;
00326 if (Tolerance > 0.0) {
00327 Horizon = (long)ceil(log(Tolerance) / log(fabs(z)));
00328 }
00329 if (Horizon < DataLength) {
00330
00331 Sum = 0.0;
00332 for (n = Horizon-1; n >= 0; n--)
00333 Sum = z * Sum + c[n];
00334 return(Sum);
00335 }
00336 else {
00337
00338 zn = z;
00339 iz = 1.0 / z;
00340 z2n = pow(z, (double)(DataLength - 1L));
00341 Sum = c[0] + z2n * c[DataLength - 1L];
00342 z2n *= z2n * iz;
00343 for (n = 1L; n <= DataLength - 2L; n++) {
00344 Sum += (zn + z2n) * c[n];
00345 zn *= z;
00346 z2n *= iz;
00347 }
00348 return(Sum / (1.0 - zn * zn));
00349 }
00350 }
00351
00352 static double dInitialAntiCausalCoefficient
00353 (
00354 double c[],
00355 long DataLength,
00356 double z
00357 )
00358 {
00359
00360 return((z / (z * z - 1.0)) * (z * c[DataLength - 2L] + c[DataLength - 1L]));
00361 }
00362
00363
00364
00365
00366
00367 extern int dSamplesToCoefficients
00368 (
00369 double *Image,
00370 long Width,
00371 long Height,
00372 long SplineDegree
00373 )
00374 {
00375 double *Line;
00376 double Pole[2];
00377 long NbPoles;
00378 long x, y,xb,xmax;
00379
00380 switch (SplineDegree) {
00381 case 2L:
00382 NbPoles = 1L;
00383 Pole[0] = sqrt(8.0) - 3.0;
00384 break;
00385 case 3L:
00386 NbPoles = 1L;
00387 Pole[0] = sqrt(3.0) - 2.0;
00388 break;
00389 case 4L:
00390 NbPoles = 2L;
00391 Pole[0] = sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0;
00392 Pole[1] = sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0;
00393 break;
00394 case 5L:
00395 NbPoles = 2L;
00396 Pole[0] = sqrt(135.0 / 2.0 - sqrt(17745.0 / 4.0)) +
00397 sqrt(105.0 / 4.0) - 13.0 / 2.0;
00398 Pole[1] = sqrt(135.0 / 2.0 + sqrt(17745.0 / 4.0)) -
00399 sqrt(105.0 / 4.0) - 13.0 / 2.0;
00400 break;
00401 default:
00402 printf("Invalid spline degree\n");
00403 return(1);
00404 }
00405
00406
00407 for (y = 0L; y < Height; y++) {
00408 dConvertToInterpolationCoefficients(&Image[y*Width], Width, Pole, NbPoles,
00409 DBL_EPSILON);
00410 }
00411
00412
00413 Line = (double *) malloc((size_t)(BLKSZ_DBL*Height * (long)sizeof(double)));
00414 if (Line == (double *)NULL) {
00415 printf("Workspace allocation failed\n");
00416 return(1);
00417 }
00418
00419 for (xb = 0L; xb<Width; xb += BLKSZ_DBL)
00420 {
00421 xmax = (xb+BLKSZ_DBL>Width?Width:xb+BLKSZ_DBL);
00422 for (x = xb; x < xmax; x++)
00423 {
00424 for (y = 0L; y < Height; y++)
00425 Line[y+(x-xb)*Height] = Image[y*Width+x];
00426 dConvertToInterpolationCoefficients(&Line[(x-xb)*Height], Height, Pole,
00427 NbPoles, DBL_EPSILON);
00428 }
00429
00430 for (y = 0L; y < Height; y++)
00431 for (x = xb; x < xmax; x++)
00432 Image[y*Width+x] = Line[y+(x-xb)*Height];
00433 }
00434 free(Line);
00435 return(0);
00436 }