Skip to content

Commit 2fea8ac

Browse files
Mark Poscabloumar456
authored andcommitted
Restore behaviour of af_approx* functions. Rename new function to af_approx*_v2
* Restore af_approx1's old output array allocation, rename new functionality as v2 * Consolidate the two af_approx1_uniforms into af_approx1_common * Add docs for approx _v2 functions * Add tests for af_approx_uniform_v2 * Make tests for special output arrays into typed tests * Make tests for special output arrays for uniform approx typed
1 parent f4c4c45 commit 2fea8ac

3 files changed

Lines changed: 337 additions & 52 deletions

File tree

include/af/signal.h

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,31 @@ extern "C" {
753753
/**
754754
C Interface for signals interpolation on one dimensional signals.
755755
756-
\param[in,out] out is the interpolated array.
756+
\param[out] out is the interpolated array.
757+
\param[in] in is the multidimensional input array. Values assumed to
758+
lie uniformly spaced indices in the range of `[0, n)`,
759+
where `n` is the number of elements in the array.
760+
\param[in] pos positions of the interpolation points along the first
761+
dimension.
762+
\param[in] method is the interpolation method to be used. The following
763+
types (defined in enum \ref af_interp_type)
764+
are supported: nearest neighbor, linear, and cubic.
765+
\param[in] off_grid is the default value for any indices outside the
766+
valid range of indices.
767+
\return \ref AF_SUCCESS if the interpolation operation is successful,
768+
otherwise an appropriate error code is returned.
769+
770+
\ingroup signal_func_approx1
771+
*/
772+
AFAPI af_err af_approx1(af_array *out, const af_array in, const af_array pos,
773+
const af_interp_type method, const float off_grid);
774+
775+
#if AF_API_VERSION >= 37
776+
/**
777+
C Interface for the version of \ref af_approx1 that accepts a preallocated
778+
output array
779+
780+
\param[in,out] out is the interpolated array (can be preallocated).
757781
\param[in] in is the multidimensional input array. Values assumed to
758782
lie uniformly spaced indices in the range of `[0, n)`,
759783
where `n` is the number of elements in the array.
@@ -770,11 +794,14 @@ extern "C" {
770794
\note \p out can either be a null or existing `af_array` object. If it is a
771795
sub-array of an existing `af_array`, only the corresponding portion of
772796
the `af_array` will be overwritten
797+
\note Passing an `af_array` that has not been initialized to \p out will cause
798+
undefined behavior.
773799
774800
\ingroup signal_func_approx1
775801
*/
776-
AFAPI af_err af_approx1(af_array *out, const af_array in, const af_array pos,
777-
const af_interp_type method, const float off_grid);
802+
AFAPI af_err af_approx1_v2(af_array *out, const af_array in, const af_array pos,
803+
const af_interp_type method, const float off_grid);
804+
#endif
778805

779806
/**
780807
C Interface for signals interpolation on two dimensional signals.
@@ -810,7 +837,7 @@ AFAPI af_err af_approx2(af_array *out, const af_array in, const af_array pos0, c
810837
The blue dots represent indices whose values are known. The red dots
811838
represent indices whose values are unknown.
812839
813-
\param[in,out] out the interpolated array.
840+
\param[out] out the interpolated array.
814841
\param[in] in is the multidimensional input array. Values lie on
815842
uniformly spaced indices determined by `idx_start`
816843
and `idx_step`.
@@ -829,17 +856,49 @@ AFAPI af_err af_approx2(af_array *out, const af_array in, const af_array pos0, c
829856
\return \ref AF_SUCCESS if the interpolation operation is successful,
830857
otherwise an appropriate error code is returned.
831858
832-
\note \p out can either be a null or existing `af_array` object. If it is a
833-
sub-array of an existing `af_array`, only the corresponding portion of
834-
the `af_array` will be overwritten
835-
836859
\ingroup signal_func_approx1
837860
*/
838861
AFAPI af_err af_approx1_uniform(af_array *out, const af_array in,
839862
const af_array pos, const int interp_dim,
840863
const double idx_start, const double idx_step,
841864
const af_interp_type method, const float off_grid);
842865

866+
/**
867+
C Interface for the version of \ref af_approx1_uniform that accepts a
868+
preallocated output array
869+
870+
\param[in,out] out the interpolated array (can be preallocated).
871+
\param[in] in is the multidimensional input array. Values lie on
872+
uniformly spaced indices determined by `idx_start`
873+
and `idx_step`.
874+
\param[in] pos positions of the interpolation points along
875+
`interp_dim`.
876+
\param[in] interp_dim is the dimension to perform interpolation across.
877+
\param[in] idx_start is the first index value along `interp_dim`.
878+
\param[in] idx_step is the uniform spacing value between subsequent
879+
indices along `interp_dim`.
880+
\param[in] method is the interpolation method to be used. The
881+
following types (defined in enum
882+
\ref af_interp_type) are supported: nearest
883+
neighbor, linear, and cubic.
884+
\param[in] off_grid is the default value for any indices outside the
885+
valid range of indices.
886+
\return \ref AF_SUCCESS if the interpolation operation is successful,
887+
otherwise an appropriate error code is returned.
888+
889+
\note \p out can either be a null or existing `af_array` object. If it is a
890+
sub-array of an existing `af_array`, only the corresponding portion of
891+
the `af_array` will be overwritten
892+
\note Passing an `af_array` to \p out that has not been initialized will cause
893+
undefined behavior.
894+
895+
\ingroup signal_func_approx1
896+
*/
897+
AFAPI af_err af_approx1_uniform_v2(af_array *out, const af_array in,
898+
const af_array pos, const int interp_dim,
899+
const double idx_start, const double idx_step,
900+
const af_interp_type method, const float off_grid);
901+
843902
/**
844903
C Interface for signals interpolation on two dimensional signals alog specified dimensions.
845904

src/api/c/approx.cpp

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,48 +43,51 @@ static inline af_array approx2(const af_array zi, const af_array xo,
4343
yi_beg, yi_step, method, offGrid));
4444
}
4545

46-
af_err af_approx1_uniform(af_array *yo, const af_array yi, const af_array xo,
47-
const int xdim, const double xi_beg,
48-
const double xi_step, const af_interp_type method,
49-
const float offGrid) {
46+
af_err af_approx1_common(af_array *yo, const af_array yi, const af_array xo,
47+
const int xdim, const double xi_beg,
48+
const double xi_step, const af_interp_type method,
49+
const float offGrid, const bool allocate_yo) {
5050
try {
51+
ARG_ASSERT(0, yo != 0);
52+
ARG_ASSERT(1, yi != 0);
53+
ARG_ASSERT(2, xo != 0);
54+
5155
const ArrayInfo &yi_info = getInfo(yi);
5256
const ArrayInfo &xo_info = getInfo(xo);
5357

5458
const dim4 yi_dims = yi_info.dims();
5559
const dim4 xo_dims = xo_info.dims();
60+
dim4 yo_dims = yi_dims;
61+
yo_dims[xdim] = xo_dims[xdim];
5662

57-
ARG_ASSERT(1, yi_info.isFloating()); // Only floating and complex types
58-
ARG_ASSERT(2, xo_info.isRealFloating()); // Only floating types
59-
ARG_ASSERT(1, yi_info.isSingle() ==
60-
xo_info.isSingle()); // Must have same precision
61-
ARG_ASSERT(1, yi_info.isDouble() ==
62-
xo_info.isDouble()); // Must have same precision
63+
ARG_ASSERT(1, yi_info.isFloating()); // Only floating and complex types
64+
ARG_ASSERT(2, xo_info.isRealFloating()) ; // Only floating types
65+
ARG_ASSERT(1, yi_info.isSingle() == xo_info.isSingle()); // Must have same precision
66+
ARG_ASSERT(1, yi_info.isDouble() == xo_info.isDouble()); // Must have same precision
6367
ARG_ASSERT(3, xdim >= 0 && xdim < 4);
6468

65-
// POS should either be (x, 1, 1, 1) or (1, yi_dims[1], yi_dims[2],
66-
// yi_dims[3])
69+
// POS should either be (x, 1, 1, 1) or (1, yi_dims[1], yi_dims[2], yi_dims[3])
6770
if (xo_dims[xdim] != xo_dims.elements()) {
6871
for (int i = 0; i < 4; i++) {
6972
if (xdim != i) DIM_ASSERT(2, xo_dims[i] == yi_dims[i]);
7073
}
7174
}
7275

7376
ARG_ASSERT(5, xi_step != 0);
74-
ARG_ASSERT(
75-
6,
76-
(method == AF_INTERP_CUBIC || method == AF_INTERP_CUBIC_SPLINE ||
77-
method == AF_INTERP_LINEAR || method == AF_INTERP_LINEAR_COSINE ||
78-
method == AF_INTERP_LOWER || method == AF_INTERP_NEAREST));
77+
ARG_ASSERT(6, (method == AF_INTERP_CUBIC ||
78+
method == AF_INTERP_CUBIC_SPLINE ||
79+
method == AF_INTERP_LINEAR ||
80+
method == AF_INTERP_LINEAR_COSINE ||
81+
method == AF_INTERP_LOWER ||
82+
method == AF_INTERP_NEAREST));
7983

8084
if (yi_dims.ndims() == 0 || xo_dims.ndims() == 0) {
81-
*yo = createHandle(dim4(0, 0, 0, 0), yi_info.getType());
82-
return AF_SUCCESS;
85+
return af_create_handle(yo, 0, nullptr, yi_info.getType());
8386
}
8487

85-
dim4 yo_dims = yi_dims;
86-
yo_dims[xdim] = xo_dims[xdim];
87-
if (*yo == 0) { *yo = createHandle(yo_dims, yi_info.getType()); }
88+
if (allocate_yo) {
89+
*yo = createHandle(yo_dims, yi_info.getType());
90+
}
8891

8992
DIM_ASSERT(1, getInfo(*yo).dims() == yo_dims);
9093

@@ -113,9 +116,37 @@ af_err af_approx1_uniform(af_array *yo, const af_array yi, const af_array xo,
113116
return AF_SUCCESS;
114117
}
115118

119+
af_err af_approx1_uniform(af_array *yo, const af_array yi, const af_array xo,
120+
const int xdim, const double xi_beg,
121+
const double xi_step, const af_interp_type method,
122+
const float offGrid) {
123+
return af_approx1_common(yo, yi, xo, xdim, xi_beg, xi_step, method, offGrid,
124+
true);
125+
}
126+
127+
af_err af_approx1_uniform_v2(af_array *yo, const af_array yi, const af_array xo,
128+
const int xdim, const double xi_beg,
129+
const double xi_step, const af_interp_type method,
130+
const float offGrid) {
131+
if (yo == 0) return AF_ERR_ARG;
132+
// Since this v2, assume that the output has already been initialized
133+
// either to null or an existing af_array
134+
return af_approx1_common(yo, yi, xo, xdim, xi_beg, xi_step, method, offGrid,
135+
*yo == 0);
136+
}
137+
116138
af_err af_approx1(af_array *yo, const af_array yi, const af_array xo,
117139
const af_interp_type method, const float offGrid) {
118-
return af_approx1_uniform(yo, yi, xo, 0, 0.0, 1.0, method, offGrid);
140+
return af_approx1_common(yo, yi, xo, 0, 0.0, 1.0, method, offGrid, true);
141+
}
142+
143+
af_err af_approx1_v2(af_array *yo, const af_array yi, const af_array xo,
144+
const af_interp_type method, const float offGrid) {
145+
if (yo == 0) return AF_ERR_ARG;
146+
// Since this is v2, assume that the output has already been initialized
147+
// either to null or an existing af_array
148+
return af_approx1_common(yo, yi, xo, 0, 0.0, 1.0, method, offGrid,
149+
*yo == 0);
119150
}
120151

121152
af_err af_approx2_uniform(af_array *zo, const af_array zi, const af_array xo,

0 commit comments

Comments
 (0)