The following file contains helper routines for AOCL-FFTZ examples, including macros/functions for preparing input data, setting default strides for dimensions and vectors, calculating buffer sizes and handling memory allocation.
1#ifndef HELPERS_H
2#define HELPERS_H
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include "aoclfftz.h"
8
9// 1 - for real problems, 2 - for complex problems
10#define DATA_STRIDE(fft_type) (((fft_type) == 1) ? 1 : 2)
11#define MAX(a, b) ((a) > (b) ? (a) : (b))
12
13#define ALLOC(ptr, type, n_ele) \
14{ \
15 ptr = (type *)malloc(sizeof(type) * n_ele); \
16 if(ptr == NULL) \
17 { \
18 printf("\nMemory allocation failed\n"); \
19 exit(EXIT_FAILURE); \
20 } \
21 else \
22 { \
23 memset(ptr, 0, sizeof(type) * n_ele); \
24 } \
25}
26
27#define PREPARE_RANDOM_INPUT(in, input_size, fft_type, data_type) \
28{ \
29 UINTP data_stride = DATA_STRIDE(fft_type); \
30 INTP idx = 0; \
31 for (idx = 0; idx < input_size * data_stride; ++idx) \
32 { \
33 in[idx] = (data_type)(20.0 / RAND_MAX) * rand() - 10.0; \
34 } \
35}
36
37/**
38 * @brief Set default stride values for dims and vecs.
39 *
40 * This function calculates appropriate default stride values for dims and vecs
41 * The stride calculations vary based on the FFT type and whether the operation
42 * is in-place or out-of-place.
43 *
44 * Stride Calculation Rules:
45 *
46 * For dims:
47 * - dims[0]: Unit stride (1) for both input and output
48 * - dims[1]: Stride calculations based on FFT type:
49 * * consider, n = n, is = in_stride, os = out_stride of dims[0]
50 * ------------------|--------------------|--------------------
51 * Type | in_stride | out_stride
52 * ------------------|--------------------|--------------------
53 * C2C | n * is | n * os
54 * R2C out-of-place | n * is | (n/2 + 1) * os
55 * R2C in-place | (n/2 + 1) * is * 2 | (n/2 + 1) * os (where is = os)
56 * C2R out-of-place | (n/2 + 1) * is | n * os
57 * C2R in-place | (n/2 + 1) * is | (n/2 + 1) * os * 2 (where is = os)
58 * ------------------|--------------------|--------------------
59 * - dims[2] or above: dims[i-1].n * dims[i-1].stride
60 * (where stride = in_stride or out_stride)
61 *
62 * For vecs:
63 *
64 * - vecs[0]: This is same as dims[1] configuration
65 * where, n = n, is = in_stride, os = out_stride of dims[dim_rank-1]
66 * - vecs[1] or above: vecs[i-1].n * vecs[i-1].stride
67 * (where stride = in_stride or out_stride)
68 *
69 * @param dim_rank rank of the dimensions
70 * @param vec_rank rank of the vectors
71 * @param dims dims structure to set default strides
72 * @param vecs vecs structure to set default strides
73 * @param flags fft configuration flags
74 * @return VOID
75 */
76VOID set_default_dims_vecs(aoclfftz_dim_t_64_ *dims, INT32 dim_rank,
77 aoclfftz_dim_t_64_ *vecs, INT32 vec_rank,
78 aoclfftz_flags_t flags)
79{
80 // Set default strides for dims if not explicitly provided
81 UINT8 is_in_place = !flags.fft_placement;
82 UINT8 is_backward = flags.fft_direction;
83 for (INT32 i = 0; i < dim_rank; i++)
84 {
85 INTP def_in_stride = 0;
86 INTP def_out_stride = 0;
87 if (i == 0)
88 {
89 def_in_stride = 1;
90 def_out_stride = 1;
91 }
92 else if (i == 1)
93 {
94 if (flags.fft_type == 1 /* Real */)
95 {
96 if (!is_backward && is_in_place)
97 {
98 def_in_stride = (dims[0].n / 2 + 1) * dims[0].in_stride * 2;
99 def_out_stride = (dims[0].n / 2 + 1) * dims[0].out_stride;
100 }
101 else if (!is_backward && !is_in_place)
102 {
103 def_in_stride = dims[0].n * dims[0].in_stride;
104 def_out_stride = (dims[0].n / 2 + 1) * dims[0].out_stride;
105 }
106 else if (is_backward && is_in_place)
107 {
108 def_in_stride = (dims[0].n / 2 + 1) * dims[0].in_stride;
109 def_out_stride = (dims[0].n / 2 + 1) * dims[0].out_stride * 2;
110 }
111 else if (is_backward && !is_in_place)
112 {
113 def_in_stride = (dims[0].n / 2 + 1) * dims[0].in_stride;
114 def_out_stride = dims[0].n * dims[0].out_stride;
115 }
116 }
117 else /* Complex */
118 {
119 def_in_stride = dims[0].n * dims[0].in_stride;
120 def_out_stride = dims[0].n * dims[0].out_stride;
121 }
122 }
123 else /* i > 1 */
124 {
125 def_in_stride = dims[i - 1].n * dims[i - 1].in_stride;
126 def_out_stride = dims[i - 1].n * dims[i - 1].out_stride;
127 }
128 if (dims[i].in_stride == 0)
129 {
130 /* in stride for dims[i] is set to default value */
131 dims[i].in_stride = def_in_stride;
132 }
133 if (dims[i].out_stride == 0)
134 {
135 /* out stride for dim[i] is set to default value */
136 dims[i].out_stride = def_out_stride;
137 }
138 }
139
140 // set strides for vecs if not provided
141 for (INT32 i = 0; i < vec_rank; i++)
142 {
143 INTP def_in_stride = 0;
144 INTP def_out_stride = 0;
145 if (i == 0)
146 {
147 aoclfftz_dim_t_64_ last_dim = dims[dim_rank - 1];
148 if (flags.fft_type == 1 /* Real */)
149 {
150 if (!is_backward && is_in_place)
151 {
152 def_in_stride = (last_dim.n / 2 + 1) * last_dim.in_stride * 2;
153 def_out_stride = (last_dim.n / 2 + 1) * last_dim.out_stride;
154 }
155 else if (!is_backward && !is_in_place)
156 {
157 def_in_stride = last_dim.n * last_dim.in_stride;
158 def_out_stride = (last_dim.n / 2 + 1) * last_dim.out_stride;
159 }
160 else if (is_backward && is_in_place)
161 {
162 def_in_stride = (last_dim.n / 2 + 1) * last_dim.in_stride;
163 def_out_stride = (last_dim.n / 2 + 1) * last_dim.out_stride * 2;
164 }
165 else if (is_backward && !is_in_place)
166 {
167 def_in_stride = (last_dim.n / 2 + 1) * last_dim.in_stride;
168 def_out_stride = last_dim.n * last_dim.out_stride;
169 }
170 }
171 else /* Complex */
172 {
173 def_in_stride = last_dim.n * last_dim.in_stride;
174 def_out_stride = last_dim.n * last_dim.out_stride;
175 }
176 }
177 else /* i > 0 */
178 {
179 def_in_stride = vecs[i - 1].n * vecs[i - 1].in_stride;
180 def_out_stride = vecs[i - 1].n * vecs[i - 1].out_stride;
181 }
182 if (vecs[i].in_stride == 0)
183 {
184 /* in stride for vec[i] is set to default value */
185 vecs[i].in_stride = def_in_stride;
186 }
187 if (vecs[i].out_stride == 0)
188 {
189 /* out stride for vec[i] is set to default value */
190 vecs[i].out_stride = def_out_stride;
191 }
192 }
193}
194
195/**
196 * @brief calculate the buffer sizes for input and output
197 *
198 * @param dims dims structure to set default strides
199 * @param dim_rank rank of the dimensions
200 * @param vecs vecs structure to set default strides
201 * @param vec_rank rank of the vectors
202 * @param in_buffer_size calculated size of input
203 * @param out_buffer_size calculated size of output
204 * @return VOID
205 */
206VOID calculate_buffer_sizes(aoclfftz_dim_t_64_ *dims, INT32 dim_rank,
207 aoclfftz_dim_t_64_ *vecs, INT32 vec_rank,
208 UINTP *in_buffer_size, UINTP *out_buffer_size)
209{
210 // Example: for an 1D problem with 1D batch
211 // Problem size : 3:6:6v4:1:1
212 // Data arrangement considered :
213 // [1, 2, 3, 4]<0, 0>[5, 6, 7, 8]<0, 0>[9, 10, 11, 12]
214 // <---vec stride--->
215 // <-------------(Batches -1)---------><--- Problem size * dim_stride --->
216 // ((Batches -1) * (vec_stride)) + (Problem size * dim stride)
217 UINTP in_size = 1;
218 UINTP out_size = 1;
219 for (INT32 i = 0; i < dim_rank; i++)
220 {
221 in_size += ((dims[i].n - 1) * (dims[i].in_stride));
222 out_size += ((dims[i].n - 1) * (dims[i].out_stride));
223 }
224 for (INT32 i = 0; i < vec_rank; i++)
225 {
226 in_size += ((vecs[i].n - 1) * (vecs[i].in_stride));
227 out_size += ((vecs[i].n - 1) * (vecs[i].out_stride));
228 }
229 *in_buffer_size = in_size;
230 *out_buffer_size = out_size;
231}
232
233#endif // HELPERS_H