DLL_PUBLIC fastfilters_array3d_t *fastfilters_array3d_alloc(size_t n_x, size_t n_y, size_t n_z, size_t channels) { fastfilters_array3d_t *result = NULL; result = fastfilters_memory_alloc(sizeof(*result)); if (!result) goto error_out; result->n_x = n_x; result->n_y = n_y; result->n_z = n_z; result->stride_x = channels; result->stride_y = channels * n_x; result->stride_z = channels * n_x * n_y; result->n_channels = channels; result->ptr = fastfilters_memory_alloc(channels * n_y * n_x * n_z * sizeof(float)); if (!result->ptr) goto error_out; return result; error_out: if (result) { if (result->ptr) fastfilters_memory_free(result->ptr); fastfilters_memory_free(result); } return NULL; }
void *fastfilters_memory_align(size_t alignment, size_t size) { assert(alignment < 0xff); void *ptr = fastfilters_memory_alloc(size + alignment + 8); if (!ptr) return NULL; uintptr_t ptr_i = (uintptr_t)ptr; ptr_i += 8 + alignment - 1; ptr_i &= ~(alignment - 1); uintptr_t ptr_diff = ptr_i - (uintptr_t)ptr; void *ptr_aligned = (void *)ptr_i; uint64_t *ptr_magic = (uint64_t *)(ptr_i - 8); *ptr_magic = ALIGN_MAGIC | (ptr_diff & 0xff); return ptr_aligned; }
fastfilters_kernel_fir_t DLL_PUBLIC fastfilters_kernel_fir_gaussian(unsigned int order, double sigma, float window_ratio) { double norm; double sigma2 = -0.5 / sigma / sigma; if (order > 2) return NULL; if (sigma < 0) return NULL; fastfilters_kernel_fir_t kernel = fastfilters_memory_alloc(sizeof(struct _fastfilters_kernel_fir_t)); if (!kernel) return NULL; if (window_ratio > 0) kernel->len = floor(window_ratio * sigma + 0.5); else kernel->len = ceil((3.0 + 0.5 * (double)order) * sigma); if (fabs(sigma) < 1e-6) kernel->len = 0; kernel->coefs = fastfilters_memory_alloc(sizeof(float) * (kernel->len + 1)); if (!kernel->coefs) { fastfilters_memory_free(kernel); return NULL; } if (order == 1) kernel->is_symmetric = false; else kernel->is_symmetric = true; switch (order) { case 1: case 2: norm = -1.0 / (sqrt(2.0 * M_PI) * pow(sigma, 3)); break; default: norm = 1.0 / (sqrt(2.0 * M_PI) * sigma); break; } for (unsigned int x = 0; x <= kernel->len; ++x) { double x2 = x * x; double g = norm * exp(x2 * sigma2); switch (order) { case 0: kernel->coefs[x] = g; break; case 1: kernel->coefs[x] = x * g; break; case 2: kernel->coefs[x] = (1.0 - (x / sigma) * (x / sigma)) * g; break; } } if (order == 2) { double dc = kernel->coefs[0]; for (unsigned int x = 1; x <= kernel->len; ++x) dc += 2 * kernel->coefs[x]; dc /= (2.0 * (double)kernel->len + 1.0); for (unsigned int x = 0; x <= kernel->len; ++x) kernel->coefs[x] -= dc; } double sum = 0.0; if (order == 0) { sum = kernel->coefs[0]; for (unsigned int x = 1; x <= kernel->len; ++x) sum += 2 * kernel->coefs[x]; } else { unsigned int faculty = 1; int sign; if (kernel->is_symmetric) sign = 1; else sign = -1; for (unsigned int i = 2; i <= order; ++i) faculty *= i; sum = 0.0; for (unsigned int x = 1; x <= kernel->len; ++x) { sum += kernel->coefs[x] * pow(-(double)x, (int)order) / (double)faculty; sum += sign * kernel->coefs[x] * pow((double)x, (int)order) / (double)faculty; } } for (unsigned int x = 0; x <= kernel->len; ++x) kernel->coefs[x] /= sum; if (!kernel->is_symmetric) for (unsigned int x = 0; x <= kernel->len; ++x) kernel->coefs[x] *= -1; kernel->fn_inner_mirror = NULL; kernel->fn_inner_ptr = NULL; kernel->fn_inner_optimistic = NULL; kernel->fn_outer_mirror = NULL; kernel->fn_outer_ptr = NULL; kernel->fn_outer_optimistic = NULL; return kernel; }