32 #include <gsl/gsl_block_double.h>
33 #include <gsl/gsl_vector_double.h>
34 #include <gsl/gsl_matrix_double.h>
35 #include <gsl/gsl_multifit.h>
115 static double integer_power(
int x,
int y)
117 double dbl_x = (double)x;
127 double result = dbl_x * dbl_x;
129 while (2 * cur_power < y) {
135 result *= integer_power(x, y - cur_power);
146 size_t num_of_samples;
147 size_t num_of_coeffs;
148 gsl_multifit_linear_workspace* workspace;
152 gsl_matrix* cov_matrix;
174 size_t num_of_coeffs)
180 if (poly_fit == NULL)
183 poly_fit->num_of_samples = num_of_samples;
184 poly_fit->num_of_coeffs = num_of_coeffs;
186 = gsl_multifit_linear_alloc(num_of_samples, num_of_coeffs);
187 poly_fit->matrix = gsl_matrix_alloc(num_of_samples, num_of_coeffs);
188 poly_fit->y = gsl_vector_alloc(num_of_samples);
189 poly_fit->c = gsl_vector_alloc(num_of_coeffs);
191 = gsl_matrix_alloc(num_of_coeffs, num_of_coeffs);
193 for (i = 0; i < num_of_samples; ++i) {
194 for (j = 0; j < num_of_coeffs; ++j) {
195 gsl_matrix_set(poly_fit->matrix, i, j,
196 integer_power(i + 1, j));
212 if (poly_fit == NULL)
215 gsl_matrix_free(poly_fit->matrix);
216 gsl_vector_free(poly_fit->y);
217 gsl_vector_free(poly_fit->c);
218 gsl_matrix_free(poly_fit->cov_matrix);
219 gsl_multifit_linear_free(poly_fit->workspace);
236 if (poly_fit == NULL)
239 return poly_fit->num_of_samples;
255 if (poly_fit == NULL)
258 return poly_fit->num_of_coeffs;
302 const double* points)
307 if (poly_fit == NULL || coeffs == NULL || points == NULL)
310 for (idx = 0; idx < poly_fit->num_of_samples; ++idx) {
311 gsl_vector_set(poly_fit->y, idx, points[idx]);
314 if (gsl_multifit_linear(poly_fit->matrix, poly_fit->y, poly_fit->c,
315 poly_fit->cov_matrix, &chisq,
316 poly_fit->workspace) != 0) {
317 return PCOMP_STAT_INVALID_FIT;
320 for (idx = 0; idx < poly_fit->num_of_coeffs; ++idx) {
321 coeffs[idx] = gsl_vector_get(poly_fit->c, idx);
324 return PCOMP_STAT_SUCCESS;
334 size_t num_of_samples;
335 fftw_plan fftw_plan_ptr;
369 if (chebyshev == NULL)
372 chebyshev->input = fftw_alloc_real(num_of_samples);
373 chebyshev->output = fftw_alloc_real(num_of_samples);
374 chebyshev->num_of_samples = num_of_samples;
375 chebyshev->fftw_plan_ptr = fftw_plan_r2r_1d(
376 num_of_samples, chebyshev->input, chebyshev->output,
377 FFTW_REDFT00, FFTW_ESTIMATE);
378 chebyshev->dir = dir;
395 if (plan->input != NULL)
396 fftw_free(plan->input);
398 if (plan->output != NULL)
399 fftw_free(plan->output);
401 if (plan->fftw_plan_ptr != NULL)
402 fftw_destroy_plan(plan->fftw_plan_ptr);
421 return plan->num_of_samples;
444 size_t num_of_samples)
447 return 1.0 / (((double)num_of_samples) - 1.0);
502 for (idx = 0; idx < plan->num_of_samples; ++idx) {
503 plan->input[idx] = input[idx];
507 fftw_execute(plan->fftw_plan_ptr);
508 norm = chebyshev_normalization(dir, plan->num_of_samples);
510 for (idx = 0; idx < plan->num_of_samples; ++idx) {
511 plan->output[idx] *= norm;
514 if (output != NULL && output != plan->output) {
515 for (idx = 0; idx < plan->num_of_samples; ++idx) {
516 output[idx] = plan->output[idx];
520 return PCOMP_STAT_SUCCESS;
571 size_t samples_per_chunk;
575 double max_allowable_error;
599 pcomp_poly_size_t num_of_coeffs,
600 double max_allowable_error,
607 params->samples_per_chunk = samples_per_chunk;
612 params->inv_chebyshev
614 params->max_allowable_error = max_allowable_error;
615 params->algorithm = algorithm;
616 params->period = 0.0;
660 return params->samples_per_chunk;
679 if (params == NULL || params->poly_fit == NULL)
682 return params->poly_fit->num_of_coeffs;
700 return params->max_allowable_error;
719 return params->algorithm;
738 return params->chebyshev;
757 return params->inv_chebyshev;
778 return params->period;
804 params->period = period;
811 static double eval_poly(
double* coeffs,
size_t num_of_coeffs,
double x)
816 if (num_of_coeffs >= 1) {
817 size_t idx = num_of_coeffs - 1;
818 double result = coeffs[idx];
820 if (num_of_coeffs == 1)
825 result = result * x + coeffs[idx];
865 size_t num_of_samples,
double period)
869 if (input == NULL || output == NULL)
873 double half_period = period * 0.5;
876 output[0] = input[0];
878 for (idx = 1; idx < num_of_samples; ++idx) {
879 double diff_with_previous = input[idx] - input[idx - 1];
880 if (diff_with_previous > half_period)
882 else if (diff_with_previous < -half_period)
885 output[idx] = input[idx] + offset;
889 for (idx = 0; idx < num_of_samples; ++idx)
890 output[idx] = input[idx];
902 size_t num_of_samples;
910 double* uncompressed;
914 size_t num_of_poly_coeffs;
919 size_t num_of_cheby_coeffs;
922 double* cheby_coeffs;
943 chunk->num_of_samples = num_of_samples;
945 chunk->is_compressed = 0;
947 = malloc(
sizeof(
double) *
sizeof(chunk->num_of_samples));
949 chunk->num_of_poly_coeffs = 0;
950 chunk->poly_coeffs = NULL;
952 chunk->num_of_cheby_coeffs = 0;
953 chunk->cheby_coeffs = NULL;
954 chunk->cheby_mask = NULL;
976 const double* samples)
980 const size_t num_of_bytes =
sizeof(double) * num_of_samples;
984 chunk->num_of_samples = num_of_samples;
986 chunk->is_compressed = 0;
987 chunk->uncompressed = malloc(num_of_bytes);
988 if (chunk->uncompressed == NULL)
990 memcpy(chunk->uncompressed, samples, num_of_bytes);
992 chunk->num_of_poly_coeffs = 0;
993 chunk->poly_coeffs = NULL;
995 chunk->num_of_cheby_coeffs = 0;
996 chunk->cheby_coeffs = NULL;
997 chunk->cheby_mask = NULL;
1034 pcomp_chunk_size_t num_of_samples,
1035 pcomp_poly_size_t num_of_poly_coeffs,
const double* poly_coeffs,
1036 pcomp_chunk_size_t num_of_cheby_coeffs,
const uint8_t* cheby_mask,
1037 const double* cheby_coeffs)
1042 if (num_of_samples == 0 || poly_coeffs == NULL)
1049 chunk->num_of_samples = num_of_samples;
1050 chunk->is_compressed = 1;
1051 chunk->uncompressed = NULL;
1053 chunk->num_of_poly_coeffs = num_of_poly_coeffs;
1054 size = num_of_poly_coeffs *
sizeof(double);
1055 chunk->poly_coeffs = malloc(size);
1056 if (chunk->poly_coeffs == NULL)
1058 memcpy(chunk->poly_coeffs, poly_coeffs, size);
1060 chunk->num_of_cheby_coeffs = num_of_cheby_coeffs;
1061 if (num_of_cheby_coeffs > 0) {
1062 size = num_of_cheby_coeffs *
sizeof(double);
1063 chunk->cheby_coeffs = malloc(size);
1064 if (chunk->cheby_coeffs == NULL)
1066 memcpy(chunk->cheby_coeffs, cheby_coeffs, size);
1070 chunk->cheby_mask = malloc(size);
1071 if (chunk->cheby_mask == NULL)
1073 memcpy(chunk->cheby_mask, cheby_mask, size);
1076 chunk->cheby_mask = NULL;
1077 chunk->cheby_coeffs = NULL;
1100 if (chunk->uncompressed != NULL)
1101 free(chunk->uncompressed);
1103 if (chunk->poly_coeffs != NULL)
1104 free(chunk->poly_coeffs);
1106 if (chunk->cheby_coeffs != NULL)
1107 free(chunk->cheby_coeffs);
1109 if (chunk->cheby_mask != NULL)
1110 free(chunk->cheby_mask);
1129 return chunk->num_of_samples;
1148 if (chunk->is_compressed) {
1158 return sizeof(int8_t) +
sizeof(pcomp_chunk_size_t)
1159 +
sizeof(pcomp_poly_size_t)
1161 +
sizeof(pcomp_chunk_size_t)
1162 + (chunk->num_of_poly_coeffs
1163 + chunk->num_of_cheby_coeffs) *
sizeof(double);
1171 return sizeof(int8_t) +
sizeof(pcomp_chunk_size_t)
1172 + chunk->num_of_samples *
sizeof(double);
1185 return chunk->is_compressed;
1199 if (chunk->is_compressed)
1202 return chunk->uncompressed;
1217 if (!chunk->is_compressed)
1220 return chunk->num_of_poly_coeffs;
1235 if (!chunk->is_compressed || chunk->num_of_poly_coeffs == 0)
1238 return chunk->poly_coeffs;
1253 if (!chunk->is_compressed)
1256 return chunk->num_of_cheby_coeffs;
1271 if (!chunk->is_compressed || chunk->num_of_cheby_coeffs == 0)
1274 return chunk->cheby_coeffs;
1297 return chunk_size / CHAR_BIT
1298 + ((chunk_size % CHAR_BIT) > 0 ? 1 : 0);
1317 return chunk->cheby_mask;
1358 double* coeffs,
double* cheby_residuals,
1359 const double* input,
1360 double* max_residual)
1364 double running_max = -1.0;
1367 if (status != PCOMP_STAT_SUCCESS)
1370 for (idx = 0; idx < params->samples_per_chunk; ++idx) {
1371 double abs_residual;
1373 params->chebyshev->input[idx]
1375 - eval_poly(coeffs, params->poly_fit->num_of_coeffs,
1378 abs_residual = fabs(params->chebyshev->input[idx]);
1379 if (abs_residual > running_max || running_max < 0.0)
1380 running_max = abs_residual;
1383 if (max_residual != NULL)
1384 *max_residual = running_max;
1388 params->chebyshev, params->chebyshev->dir, NULL, NULL);
1390 if (cheby_residuals != NULL
1391 && cheby_residuals != params->chebyshev->output) {
1392 memcpy(cheby_residuals, params->chebyshev->output,
1393 sizeof(params->chebyshev->output[0])
1394 * params->chebyshev->num_of_samples);
1406 static void sort_positions(pcomp_chunk_size_t positions[],
1407 const double coeffs[],
size_t num)
1411 pcomp_chunk_size_t temp;
1416 pivot = fabs(coeffs[positions[num / 2]]);
1417 for (front = 0, back = num - 1;; front++, back--) {
1418 while (fabs(coeffs[positions[front]]) > pivot) {
1422 while (pivot > fabs(coeffs[positions[back]])) {
1431 temp = positions[front];
1432 positions[front] = positions[back];
1433 positions[back] = temp;
1435 sort_positions(positions, coeffs, front);
1436 sort_positions(positions + front, coeffs, num - front);
1452 return (mask[pos / CHAR_BIT] & (1 << (pos % CHAR_BIT))) != 0;
1469 mask[pos / CHAR_BIT] |= (1 << (pos % CHAR_BIT));
1472 mask[pos / CHAR_BIT] &= ~(((uint8_t)1) << (pos % CHAR_BIT));
1476 static double compute_discrepancy(
double a[],
double b[],
size_t num)
1480 for (idx = 0; idx < num; ++idx) {
1481 double cur_err = fabs(a[idx] - b[idx]);
1524 double max_allowable_error,
1525 uint8_t* mask,
double* max_error)
1528 size_t cur_coeff = 0;
1529 pcomp_chunk_size_t* positions;
1532 if (chebyshev == NULL || inv_chebyshev == NULL || mask == NULL
1533 || chebyshev->num_of_samples != inv_chebyshev->num_of_samples)
1536 if (max_allowable_error <= 0.0)
1556 positions = malloc(chebyshev->num_of_samples
1557 *
sizeof(pcomp_chunk_size_t));
1558 if (positions == NULL)
1560 for (idx = 0; idx < chebyshev->num_of_samples; ++idx) {
1561 positions[idx] = idx;
1563 sort_positions(positions, chebyshev->output,
1564 chebyshev->num_of_samples);
1567 memset(&inv_chebyshev->input[0], 0,
1568 chebyshev->num_of_samples *
sizeof(inv_chebyshev->input[0]));
1575 while (cur_coeff < chebyshev->num_of_samples) {
1577 inv_chebyshev->input[positions[cur_coeff]]
1578 = chebyshev->output[positions[cur_coeff]];
1584 err = compute_discrepancy(chebyshev->input,
1585 inv_chebyshev->output,
1586 chebyshev->num_of_samples);
1588 if (err < max_allowable_error)
1592 if (max_error != NULL)
1606 chunk->num_of_poly_coeffs = 0;
1607 if (chunk->poly_coeffs != NULL)
1608 free(chunk->poly_coeffs);
1610 chunk->num_of_cheby_coeffs = 0;
1611 if (chunk->cheby_coeffs != NULL)
1612 free(chunk->cheby_coeffs);
1667 const double* input,
1668 pcomp_chunk_size_t num_of_samples,
1672 uint8_t* mask = NULL;
1673 double* coeffs = NULL;
1674 size_t cheby_coeffs_to_retain = 0;
1675 int apply_chebyshev = 1;
1677 const double* straightened_input;
1679 if (chunk == NULL || input == NULL || params == NULL
1680 || params->poly_fit == NULL || params->chebyshev == NULL
1681 || params->inv_chebyshev == NULL)
1686 if (num_of_samples != params->samples_per_chunk)
1687 return PCOMP_STAT_INVALID_BUFFER;
1689 if (params->period > 0.0) {
1690 buf = malloc(num_of_samples *
sizeof(input[0]));
1694 straightened_input = buf;
1697 straightened_input = input;
1700 if (num_of_samples <= params->poly_fit->num_of_coeffs) {
1703 chunk->is_compressed = 0;
1706 double max_residual;
1711 = malloc(
sizeof(
double) * params->poly_fit->num_of_coeffs);
1715 straightened_input, &max_residual);
1717 = (max_residual >= params->max_allowable_error)
1722 if (apply_chebyshev) {
1727 params->chebyshev, params->inv_chebyshev,
1728 params->max_allowable_error, mask, max_error);
1730 chunk->is_compressed = (cheby_coeffs_to_retain
1731 + params->poly_fit->num_of_coeffs)
1733 if (!chunk->is_compressed) {
1740 chunk->is_compressed
1741 = (max_residual <= params->max_allowable_error);
1745 chunk->num_of_samples = num_of_samples;
1746 if (chunk->is_compressed) {
1749 chunk->num_of_poly_coeffs = params->poly_fit->num_of_coeffs;
1750 chunk->poly_coeffs = coeffs;
1751 if (apply_chebyshev) {
1754 chunk->num_of_cheby_coeffs = cheby_coeffs_to_retain;
1755 chunk->cheby_mask = mask;
1757 = malloc(
sizeof(
double) * cheby_coeffs_to_retain);
1758 if (chunk->cheby_coeffs == NULL)
1761 for (idx = 0; idx < params->chebyshev->num_of_samples;
1764 chunk->cheby_coeffs[cheby_idx++]
1765 = params->chebyshev->output[idx];
1770 chunk->num_of_cheby_coeffs = 0;
1771 chunk->cheby_mask = NULL;
1772 chunk->cheby_coeffs = NULL;
1781 chunk->uncompressed = malloc(
sizeof(
double) * num_of_samples);
1782 if (chunk->uncompressed == NULL)
1784 for (idx = 0; idx < num_of_samples; ++idx)
1785 chunk->uncompressed[idx] = input[idx];
1787 if (max_error != NULL)
1795 return PCOMP_STAT_SUCCESS;
1837 if (output == NULL || chunk == NULL || inv_chebyshev == NULL)
1840 if (chunk->is_compressed) {
1846 for (idx = 0; idx < chunk->num_of_samples; ++idx) {
1847 output[idx] = eval_poly(chunk->poly_coeffs,
1848 chunk->num_of_poly_coeffs, idx + 1);
1854 if (chunk->num_of_cheby_coeffs > 0) {
1855 size_t cur_cheby_idx = 0;
1856 if (chunk->cheby_coeffs == NULL)
1859 for (idx = 0; idx < chunk->num_of_samples; ++idx) {
1861 if (cur_cheby_idx >= chunk->num_of_cheby_coeffs) {
1865 inv_chebyshev->input[idx]
1866 = chunk->cheby_coeffs[cur_cheby_idx++];
1869 inv_chebyshev->input[idx] = 0.0;
1875 for (idx = 0; idx < chunk->num_of_samples; ++idx) {
1876 output[idx] += inv_chebyshev->output[idx];
1881 memcpy(output, chunk->uncompressed,
1882 sizeof(chunk->uncompressed[0]) * chunk->num_of_samples);
1885 return PCOMP_STAT_SUCCESS;
1952 size_t* num_of_chunks,
1953 const double* input_buf,
size_t input_size,
1957 const double* cur_input = input_buf;
1960 if (output_buf == NULL || num_of_chunks == NULL || input_buf == NULL
1961 || params == NULL || params->poly_fit == NULL)
1965 *num_of_chunks = input_size / params->samples_per_chunk;
1966 if (input_size % params->samples_per_chunk != 0)
1971 if (*output_buf == NULL)
1975 params->samples_per_chunk, params->poly_fit->num_of_coeffs,
1976 params->max_allowable_error, params->algorithm);
1981 for (idx = 0; idx < *num_of_chunks; ++idx) {
1982 size_t cur_chunk_size = params->samples_per_chunk;
1984 if ((cur_input - input_buf) + cur_chunk_size > input_size)
1986 = (size_t)(input_size - (cur_input - input_buf));
1988 if (cur_chunk_size != chunk_params->samples_per_chunk) {
1992 cur_chunk_size, params->poly_fit->num_of_coeffs,
1993 params->max_allowable_error, params->algorithm);
1998 cur_chunk_size, (*output_buf)[idx],
2001 cur_input += cur_chunk_size;
2004 return PCOMP_STAT_SUCCESS;
2023 size_t num_of_chunks)
2027 if (chunk_array == NULL)
2030 for (idx = 0; idx < num_of_chunks; ++idx) {
2031 if (chunk_array[idx] == NULL)
2034 total += chunk_array[idx]->num_of_samples;
2061 size_t num_of_chunks)
2064 double* cur_output_pos = output_buf;
2067 if (output_buf == NULL || chunk_array == NULL)
2070 for (idx = 0; idx < num_of_chunks; ++idx) {
2071 if (chunk_array[idx] == NULL)
2074 if (inv_chebyshev == NULL
2075 || inv_chebyshev->num_of_samples
2076 != chunk_array[idx]->num_of_samples) {
2086 cur_output_pos, chunk_array[idx], inv_chebyshev);
2088 cur_output_pos += chunk_array[idx]->num_of_samples;
2093 return PCOMP_STAT_SUCCESS;
2107 size_t num_of_chunks)
2111 if (chunk_array == NULL)
2114 for (idx = 0; idx < num_of_chunks; ++idx) {
2139 size_t num_of_chunks)
2141 size_t result =
sizeof(size_t);
2144 for (idx = 0; idx < num_of_chunks; ++idx) {
2156 #define SAVE_TO_PTR_AND_INCREMENT(buf, value, type) \
2158 *((type*)buf) = value; \
2159 buf = ((type*)buf) + 1; \
2195 size_t num_of_chunks)
2197 void* buf_ptr = buf;
2200 if (chunk_array == NULL || num_of_chunks == 0)
2203 SAVE_TO_PTR_AND_INCREMENT(buf_ptr, num_of_chunks,
size_t);
2205 for (chunk_idx = 0; chunk_idx < num_of_chunks; ++chunk_idx) {
2207 = chunk_array[chunk_idx];
2210 SAVE_TO_PTR_AND_INCREMENT(buf_ptr, cur_chunk->is_compressed,
2212 SAVE_TO_PTR_AND_INCREMENT(buf_ptr, cur_chunk->num_of_samples,
2213 pcomp_chunk_size_t);
2215 if (cur_chunk->is_compressed) {
2217 cur_chunk->num_of_samples);
2219 SAVE_TO_PTR_AND_INCREMENT(buf_ptr,
2220 cur_chunk->num_of_poly_coeffs,
2222 for (idx = 0; idx < cur_chunk->num_of_poly_coeffs; idx++) {
2223 SAVE_TO_PTR_AND_INCREMENT(
2224 buf_ptr, cur_chunk->poly_coeffs[idx],
double);
2227 SAVE_TO_PTR_AND_INCREMENT(buf_ptr,
2228 cur_chunk->num_of_cheby_coeffs,
2229 pcomp_chunk_size_t);
2230 if (cur_chunk->num_of_cheby_coeffs > 0) {
2232 for (idx = 0; idx < cheby_mask_size; ++idx) {
2233 SAVE_TO_PTR_AND_INCREMENT(
2234 buf_ptr, cur_chunk->cheby_mask[idx], uint8_t);
2237 for (idx = 0; idx < cur_chunk->num_of_cheby_coeffs;
2239 SAVE_TO_PTR_AND_INCREMENT(
2240 buf_ptr, cur_chunk->cheby_coeffs[idx],
double);
2245 for (idx = 0; idx < cur_chunk->num_of_samples; idx++) {
2246 SAVE_TO_PTR_AND_INCREMENT(
2247 buf_ptr, cur_chunk->uncompressed[idx],
double);
2252 *buf_size = ((uint8_t*)buf_ptr) - ((uint8_t*)buf);
2253 return PCOMP_STAT_SUCCESS;
2256 #define READ_FROM_PTR_AND_INCREMENT(var, pointer, type) \
2258 var = *((type*)(pointer)); \
2259 pointer = ((type*)(pointer)) + 1; \
2288 size_t* num_of_chunks,
const void* buf)
2290 const void* cur_ptr = buf;
2292 double* poly_buf = NULL;
2293 size_t poly_buf_size = 0;
2294 double* cheby_buf = NULL;
2295 size_t cheby_buf_size = 0;
2296 uint8_t* cheby_mask_buf = NULL;
2297 size_t cheby_mask_buf_size = 0;
2298 double* uncompr_buf = NULL;
2299 size_t uncompr_buf_size = 0;
2301 if (buf == NULL || chunk_array == NULL || num_of_chunks == NULL)
2304 READ_FROM_PTR_AND_INCREMENT(*num_of_chunks, cur_ptr,
size_t);
2307 if (*chunk_array == NULL)
2310 for (chunk_idx = 0; chunk_idx < *num_of_chunks; ++chunk_idx) {
2311 uint8_t is_compressed;
2312 size_t num_of_samples;
2315 READ_FROM_PTR_AND_INCREMENT(is_compressed, cur_ptr, uint8_t);
2316 READ_FROM_PTR_AND_INCREMENT(num_of_samples, cur_ptr,
2317 pcomp_chunk_size_t);
2319 if (is_compressed) {
2320 size_t num_of_poly_coeffs;
2321 size_t num_of_cheby_coeffs;
2322 size_t cheby_mask_size
2325 READ_FROM_PTR_AND_INCREMENT(num_of_poly_coeffs, cur_ptr,
2327 if (num_of_poly_coeffs > poly_buf_size) {
2328 poly_buf_size = num_of_poly_coeffs;
2330 = realloc(poly_buf, poly_buf_size *
sizeof(
double));
2332 for (idx = 0; idx < num_of_poly_coeffs; ++idx) {
2333 READ_FROM_PTR_AND_INCREMENT(poly_buf[idx], cur_ptr,
2337 READ_FROM_PTR_AND_INCREMENT(num_of_cheby_coeffs, cur_ptr,
2338 pcomp_chunk_size_t);
2339 if (num_of_cheby_coeffs > 0) {
2340 if (cheby_mask_size > cheby_mask_buf_size) {
2341 cheby_mask_buf_size = cheby_mask_size;
2342 cheby_mask_buf = realloc(cheby_mask_buf,
2346 for (idx = 0; idx < cheby_mask_size; ++idx) {
2347 READ_FROM_PTR_AND_INCREMENT(cheby_mask_buf[idx],
2351 if (num_of_cheby_coeffs > cheby_buf_size) {
2352 cheby_buf_size = num_of_cheby_coeffs;
2353 cheby_buf = realloc(
2354 cheby_buf, cheby_buf_size *
sizeof(
double));
2356 for (idx = 0; idx < num_of_cheby_coeffs; ++idx) {
2357 READ_FROM_PTR_AND_INCREMENT(cheby_buf[idx], cur_ptr,
2363 num_of_samples, num_of_poly_coeffs, poly_buf,
2364 num_of_cheby_coeffs, cheby_mask_buf, cheby_buf);
2367 if (num_of_samples > uncompr_buf_size) {
2368 uncompr_buf_size = num_of_samples;
2369 uncompr_buf = realloc(
2370 uncompr_buf, uncompr_buf_size *
sizeof(
double));
2372 for (idx = 0; idx < num_of_samples; ++idx) {
2373 READ_FROM_PTR_AND_INCREMENT(uncompr_buf[idx], cur_ptr,
2378 num_of_samples, uncompr_buf);
2382 if (poly_buf != NULL)
2385 if (cheby_buf != NULL)
2388 if (uncompr_buf != NULL)
2391 return PCOMP_STAT_SUCCESS;
const double * pcomp_chunk_cheby_coeffs(const pcomp_polycomp_chunk_t *chunk)
If the chunks contain compressed data, returns a pointer to the first element of the Chebyshev transf...
pcomp_chebyshev_t * pcomp_init_chebyshev(size_t num_of_samples, pcomp_transform_direction_t dir)
Allocate a new instance of the pcomp_chebyshev_t structure on the heap.
int pcomp_run_poly_fit(pcomp_poly_fit_data_t *poly_fit, double *coeffs, const double *points)
Calculates a polynomial least-squares fit.
double pcomp_polycomp_period(const pcomp_polycomp_t *params)
Return the period of the input data, or a number less than or equal to 0 if the data have no periodic...
pcomp_transform_direction_t pcomp_chebyshev_direction(const pcomp_chebyshev_t *plan)
Return the direction of a Chebyshev transform.
int pcomp_decompress_polycomp_chunk(double *output, const pcomp_polycomp_chunk_t *chunk, pcomp_chebyshev_t *inv_chebyshev)
Decompress the data in a chunk.
pcomp_poly_size_t pcomp_polycomp_num_of_poly_coeffs(const pcomp_polycomp_t *params)
Return the number of coefficients for the fitting polynomial used in the polynomial compression...
int pcomp_encode_chunks(void *buf, size_t *buf_size, pcomp_polycomp_chunk_t *const chunk_array[], size_t num_of_chunks)
Encode a list of chunks into a sequence of raw bytes.
Compute a backward Chebyshev transform, with a normalization factor equal to one. ...
pcomp_polycomp_algorithm_t
Kind of algorithm used for the polynomial compression.
int pcomp_decode_chunks(pcomp_polycomp_chunk_t **chunk_array[], size_t *num_of_chunks, const void *buf)
Decode a byte sequence created by pcomp_encode_chunks into an array of chunks.
Compute a forward Chebyshev transform, with a normalization factor 1/(N + 1)
const double * pcomp_chunk_poly_coeffs(const pcomp_polycomp_chunk_t *chunk)
If the chunks contain compressed data, returns a pointer to the first element of the array of coeffic...
pcomp_polycomp_chunk_t * pcomp_init_compressed_chunk(pcomp_chunk_size_t num_of_samples, pcomp_poly_size_t num_of_poly_coeffs, const double *poly_coeffs, pcomp_chunk_size_t num_of_cheby_coeffs, const uint8_t *cheby_mask, const double *cheby_coeffs)
Allocate memory for a pcomp_polycomp_chunk_t object and fill it with data compressed using the polyno...
double pcomp_polycomp_max_error(const pcomp_polycomp_t *params)
Return the upper bound on the error of the polynomial compression.
void pcomp_free_polycomp(pcomp_polycomp_t *params)
Free the memory allocated by pcomp_init_polycomp for a pcomp_polycomp_t structure.
pcomp_polycomp_chunk_t * pcomp_init_chunk(pcomp_chunk_size_t num_of_samples)
Allocate memory for a pcomp_polycomp_chunk_t object.
const double * pcomp_chunk_uncompressed_data(const pcomp_polycomp_chunk_t *chunk)
If the chunks contain uncompressed data, returns a pointer to the first element. Otherwise, return NULL.
pcomp_chunk_size_t pcomp_chunk_num_of_samples(const pcomp_polycomp_chunk_t *chunk)
Return the number of samples in a chunk.
pcomp_chebyshev_t * pcomp_polycomp_forward_cheby(const pcomp_polycomp_t *params)
Return a pointer to a pcomp_chebyshev_t structure representing the forward Chebyshev transform...
pcomp_chunk_size_t pcomp_polycomp_samples_per_chunk(const pcomp_polycomp_t *params)
Return the number of samples per chunk.
pcomp_poly_size_t pcomp_chunk_num_of_poly_coeffs(const pcomp_polycomp_chunk_t *chunk)
If the chunks contain compressed data, returns the number of polynomial coefficients used in the comp...
size_t pcomp_find_chebyshev_mask(pcomp_chebyshev_t *chebyshev, pcomp_chebyshev_t *inv_chebyshev, double max_allowable_error, uint8_t *mask, double *max_error)
Find the smallest subset of Chebyshev coefficients that can approximate a Chebyshev transform with an...
int pcomp_mask_get_bit(const uint8_t *mask, size_t pos)
Return the value of the bit at the position pos in the bitmask mask.
void pcomp_free_chebyshev(pcomp_chebyshev_t *plan)
Free the memory allocated by a previous call to pcomp_init_chebyshev.
size_t pcomp_chebyshev_num_of_samples(const pcomp_chebyshev_t *plan)
Return the number of samples in a Chebyshev transform.
const uint8_t * pcomp_chunk_cheby_mask(const pcomp_polycomp_chunk_t *chunk)
Return a pointer to the bitmask of nonzero Chebyshev coefficients for a chunk.
int pcomp_polyfit_and_chebyshev(pcomp_polycomp_t *params, double *coeffs, double *cheby_residuals, const double *input, double *max_residual)
Compute a polynomial fit of the data in input and a Chebyshev transform of the residuals.
const double * pcomp_chebyshev_output(const pcomp_chebyshev_t *plan)
Return the output (Chebyshev transform) of the last call to pcomp_run_chebyshev.
void pcomp_straighten(double *output, const double *input, size_t num_of_samples, double period)
Remove sudden jumps from input.
size_t pcomp_total_num_of_samples(pcomp_polycomp_chunk_t *const chunk_array[], size_t num_of_chunks)
Compute the sum of the number of samples encoded in chunk_array.
pcomp_polycomp_chunk_t * pcomp_init_uncompressed_chunk(pcomp_chunk_size_t num_of_samples, const double *samples)
Allocate memory for a pcomp_polycomp_chunk_t object and fill it with data in uncompressed form...
size_t pcomp_chunk_num_of_bytes(const pcomp_polycomp_chunk_t *chunk)
Return the number of bytes necessary to encode a chunk.
size_t pcomp_poly_fit_num_of_coeffs(const pcomp_poly_fit_data_t *poly_fit)
Return the number of coefficients of the least-squares fitting polynomial.
void pcomp_mask_set_bit(uint8_t *mask, size_t pos, int value)
Set the value of the bit at position pos in the bitmask .
int pcomp_run_polycomp_on_chunk(pcomp_polycomp_t *params, const double *input, pcomp_chunk_size_t num_of_samples, pcomp_polycomp_chunk_t *chunk, double *max_error)
Compress the first num_of_samples elements in input and store them in chunk.
size_t pcomp_chunk_cheby_mask_size(pcomp_chunk_size_t chunk_size)
Return the number of bytes required for the bitmask of nonzero Chebyshev coefficients.
pcomp_poly_fit_data_t * pcomp_init_poly_fit(size_t num_of_samples, size_t num_of_coeffs)
Allocate a new instance of the pcomp_poly_fit_data_t structure on the heap.
void pcomp_polycomp_set_period(pcomp_polycomp_t *params, double period)
Set the periodicity of the data to be compressed.
void pcomp_free_poly_fit(pcomp_poly_fit_data_t *poly_fit)
Free an instance of the pcomp_poly_fit_data_t that has been allocated via a call to pcomp_init_poly_f...
void pcomp_free_chunk(pcomp_polycomp_chunk_t *chunk)
Free memory associated with a pcomp_poly_chunk_t.
pcomp_chebyshev_t * pcomp_polycomp_backward_cheby(const pcomp_polycomp_t *params)
Return a pointer to a pcomp_chebyshev_t structure representing the forward Chebyshev transform...
pcomp_polycomp_t * pcomp_init_polycomp(pcomp_chunk_size_t samples_per_chunk, pcomp_poly_size_t num_of_coeffs, double max_allowable_error, pcomp_polycomp_algorithm_t algorithm)
Allocate space for a pcomp_polycomp_t structure.
int pcomp_decompress_polycomp(double *output_buf, pcomp_polycomp_chunk_t *const chunk_array[], size_t num_of_chunks)
Decompress a sequence of chunks.
pcomp_transform_direction_t
Direction of a Chebyshev transform.
pcomp_polycomp_algorithm_t pcomp_polycomp_algorithm(const pcomp_polycomp_t *params)
Return the kind of algorithm used for a polynomial compression.
int pcomp_compress_polycomp(pcomp_polycomp_chunk_t **output_buf[], size_t *num_of_chunks, const double *input_buf, size_t input_size, const pcomp_polycomp_t *params)
Compress the array input_buf using polynomial compression.
size_t pcomp_chunks_num_of_bytes(pcomp_polycomp_chunk_t *const chunks[], size_t num_of_chunks)
Number of bytes required by pcomp_encode_chunks.
int pcomp_chunk_is_compressed(const pcomp_polycomp_chunk_t *chunk)
Return nonzero if the chunk holds data in uncompressed form.
If the absolute value of the residuals of a polynomial fit are too large, store the data in uncompres...
size_t pcomp_poly_fit_num_of_samples(const pcomp_poly_fit_data_t *poly_fit)
Return the number of samples to be used in a polynomial fit.
void pcomp_free_chunks(pcomp_polycomp_chunk_t *chunk_array[], size_t num_of_chunks)
Free an array of chunks.
int pcomp_run_chebyshev(pcomp_chebyshev_t *plan, pcomp_transform_direction_t dir, double *output, const double *input)
Compute a forward/backward Chebyshev discrete transform.
const double * pcomp_chebyshev_input(const pcomp_chebyshev_t *plan)
Return the input data used in the last call to pcomp_run_chebyshev.
Header file for Libpolycomp.
pcomp_chunk_size_t pcomp_chunk_num_of_cheby_coeffs(const pcomp_polycomp_chunk_t *chunk)
If the chunks contain compressed data, returns the number of nonzero Chebyshev coefficients held in t...