annotate src/fftw-3.3.5/rdft/problem.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 2cd0e3b3e1fd
children
rev   line source
Chris@42 1 /*
Chris@42 2 * Copyright (c) 2003, 2007-14 Matteo Frigo
Chris@42 3 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
Chris@42 4 *
Chris@42 5 * This program is free software; you can redistribute it and/or modify
Chris@42 6 * it under the terms of the GNU General Public License as published by
Chris@42 7 * the Free Software Foundation; either version 2 of the License, or
Chris@42 8 * (at your option) any later version.
Chris@42 9 *
Chris@42 10 * This program is distributed in the hope that it will be useful,
Chris@42 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@42 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@42 13 * GNU General Public License for more details.
Chris@42 14 *
Chris@42 15 * You should have received a copy of the GNU General Public License
Chris@42 16 * along with this program; if not, write to the Free Software
Chris@42 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Chris@42 18 *
Chris@42 19 */
Chris@42 20
Chris@42 21
Chris@42 22 #include "rdft.h"
Chris@42 23 #include <stddef.h>
Chris@42 24
Chris@42 25 static void destroy(problem *ego_)
Chris@42 26 {
Chris@42 27 problem_rdft *ego = (problem_rdft *) ego_;
Chris@42 28 #if !defined(STRUCT_HACK_C99) && !defined(STRUCT_HACK_KR)
Chris@42 29 X(ifree0)(ego->kind);
Chris@42 30 #endif
Chris@42 31 X(tensor_destroy2)(ego->vecsz, ego->sz);
Chris@42 32 X(ifree)(ego_);
Chris@42 33 }
Chris@42 34
Chris@42 35 static void kind_hash(md5 *m, const rdft_kind *kind, int rnk)
Chris@42 36 {
Chris@42 37 int i;
Chris@42 38 for (i = 0; i < rnk; ++i)
Chris@42 39 X(md5int)(m, kind[i]);
Chris@42 40 }
Chris@42 41
Chris@42 42 static void hash(const problem *p_, md5 *m)
Chris@42 43 {
Chris@42 44 const problem_rdft *p = (const problem_rdft *) p_;
Chris@42 45 X(md5puts)(m, "rdft");
Chris@42 46 X(md5int)(m, p->I == p->O);
Chris@42 47 kind_hash(m, p->kind, p->sz->rnk);
Chris@42 48 X(md5int)(m, X(ialignment_of)(p->I));
Chris@42 49 X(md5int)(m, X(ialignment_of)(p->O));
Chris@42 50 X(tensor_md5)(m, p->sz);
Chris@42 51 X(tensor_md5)(m, p->vecsz);
Chris@42 52 }
Chris@42 53
Chris@42 54 static void recur(const iodim *dims, int rnk, R *I)
Chris@42 55 {
Chris@42 56 if (rnk == RNK_MINFTY)
Chris@42 57 return;
Chris@42 58 else if (rnk == 0)
Chris@42 59 I[0] = K(0.0);
Chris@42 60 else if (rnk > 0) {
Chris@42 61 INT i, n = dims[0].n, is = dims[0].is;
Chris@42 62
Chris@42 63 if (rnk == 1) {
Chris@42 64 /* this case is redundant but faster */
Chris@42 65 for (i = 0; i < n; ++i)
Chris@42 66 I[i * is] = K(0.0);
Chris@42 67 } else {
Chris@42 68 for (i = 0; i < n; ++i)
Chris@42 69 recur(dims + 1, rnk - 1, I + i * is);
Chris@42 70 }
Chris@42 71 }
Chris@42 72 }
Chris@42 73
Chris@42 74 void X(rdft_zerotens)(tensor *sz, R *I)
Chris@42 75 {
Chris@42 76 recur(sz->dims, sz->rnk, I);
Chris@42 77 }
Chris@42 78
Chris@42 79 #define KSTR_LEN 8
Chris@42 80
Chris@42 81 const char *X(rdft_kind_str)(rdft_kind kind)
Chris@42 82 {
Chris@42 83 static const char kstr[][KSTR_LEN] = {
Chris@42 84 "r2hc", "r2hc01", "r2hc10", "r2hc11",
Chris@42 85 "hc2r", "hc2r01", "hc2r10", "hc2r11",
Chris@42 86 "dht",
Chris@42 87 "redft00", "redft01", "redft10", "redft11",
Chris@42 88 "rodft00", "rodft01", "rodft10", "rodft11"
Chris@42 89 };
Chris@42 90 A(kind >= 0 && kind < sizeof(kstr) / KSTR_LEN);
Chris@42 91 return kstr[kind];
Chris@42 92 }
Chris@42 93
Chris@42 94 static void print(const problem *ego_, printer *p)
Chris@42 95 {
Chris@42 96 const problem_rdft *ego = (const problem_rdft *) ego_;
Chris@42 97 int i;
Chris@42 98 p->print(p, "(rdft %d %D %T %T",
Chris@42 99 X(ialignment_of)(ego->I),
Chris@42 100 (INT)(ego->O - ego->I),
Chris@42 101 ego->sz,
Chris@42 102 ego->vecsz);
Chris@42 103 for (i = 0; i < ego->sz->rnk; ++i)
Chris@42 104 p->print(p, " %d", (int)ego->kind[i]);
Chris@42 105 p->print(p, ")");
Chris@42 106 }
Chris@42 107
Chris@42 108 static void zero(const problem *ego_)
Chris@42 109 {
Chris@42 110 const problem_rdft *ego = (const problem_rdft *) ego_;
Chris@42 111 tensor *sz = X(tensor_append)(ego->vecsz, ego->sz);
Chris@42 112 X(rdft_zerotens)(sz, UNTAINT(ego->I));
Chris@42 113 X(tensor_destroy)(sz);
Chris@42 114 }
Chris@42 115
Chris@42 116 static const problem_adt padt =
Chris@42 117 {
Chris@42 118 PROBLEM_RDFT,
Chris@42 119 hash,
Chris@42 120 zero,
Chris@42 121 print,
Chris@42 122 destroy
Chris@42 123 };
Chris@42 124
Chris@42 125 /* Dimensions of size 1 that are not REDFT/RODFT are no-ops and can be
Chris@42 126 eliminated. REDFT/RODFT unit dimensions often have factors of 2.0
Chris@42 127 and suchlike from normalization and phases, although in principle
Chris@42 128 these constant factors from different dimensions could be combined. */
Chris@42 129 static int nontrivial(const iodim *d, rdft_kind kind)
Chris@42 130 {
Chris@42 131 return (d->n > 1 || kind == R2HC11 || kind == HC2R11
Chris@42 132 || (REODFT_KINDP(kind) && kind != REDFT01 && kind != RODFT01));
Chris@42 133 }
Chris@42 134
Chris@42 135 problem *X(mkproblem_rdft)(const tensor *sz, const tensor *vecsz,
Chris@42 136 R *I, R *O, const rdft_kind *kind)
Chris@42 137 {
Chris@42 138 problem_rdft *ego;
Chris@42 139 int rnk = sz->rnk;
Chris@42 140 int i;
Chris@42 141
Chris@42 142 A(X(tensor_kosherp)(sz));
Chris@42 143 A(X(tensor_kosherp)(vecsz));
Chris@42 144 A(FINITE_RNK(sz->rnk));
Chris@42 145
Chris@42 146 if (UNTAINT(I) == UNTAINT(O))
Chris@42 147 I = O = JOIN_TAINT(I, O);
Chris@42 148
Chris@42 149 if (I == O && !X(tensor_inplace_locations)(sz, vecsz))
Chris@42 150 return X(mkproblem_unsolvable)();
Chris@42 151
Chris@42 152 for (i = rnk = 0; i < sz->rnk; ++i) {
Chris@42 153 A(sz->dims[i].n > 0);
Chris@42 154 if (nontrivial(sz->dims + i, kind[i]))
Chris@42 155 ++rnk;
Chris@42 156 }
Chris@42 157
Chris@42 158 #if defined(STRUCT_HACK_KR)
Chris@42 159 ego = (problem_rdft *) X(mkproblem)(sizeof(problem_rdft)
Chris@42 160 + sizeof(rdft_kind)
Chris@42 161 * (rnk > 0 ? rnk - 1u : 0u), &padt);
Chris@42 162 #elif defined(STRUCT_HACK_C99)
Chris@42 163 ego = (problem_rdft *) X(mkproblem)(sizeof(problem_rdft)
Chris@42 164 + sizeof(rdft_kind) * (unsigned)rnk, &padt);
Chris@42 165 #else
Chris@42 166 ego = (problem_rdft *) X(mkproblem)(sizeof(problem_rdft), &padt);
Chris@42 167 ego->kind = (rdft_kind *) MALLOC(sizeof(rdft_kind) * (unsigned)rnk, PROBLEMS);
Chris@42 168 #endif
Chris@42 169
Chris@42 170 /* do compression and sorting as in X(tensor_compress), but take
Chris@42 171 transform kind into account (sigh) */
Chris@42 172 ego->sz = X(mktensor)(rnk);
Chris@42 173 for (i = rnk = 0; i < sz->rnk; ++i) {
Chris@42 174 if (nontrivial(sz->dims + i, kind[i])) {
Chris@42 175 ego->kind[rnk] = kind[i];
Chris@42 176 ego->sz->dims[rnk++] = sz->dims[i];
Chris@42 177 }
Chris@42 178 }
Chris@42 179 for (i = 0; i + 1 < rnk; ++i) {
Chris@42 180 int j;
Chris@42 181 for (j = i + 1; j < rnk; ++j)
Chris@42 182 if (X(dimcmp)(ego->sz->dims + i, ego->sz->dims + j) > 0) {
Chris@42 183 iodim dswap;
Chris@42 184 rdft_kind kswap;
Chris@42 185 dswap = ego->sz->dims[i];
Chris@42 186 ego->sz->dims[i] = ego->sz->dims[j];
Chris@42 187 ego->sz->dims[j] = dswap;
Chris@42 188 kswap = ego->kind[i];
Chris@42 189 ego->kind[i] = ego->kind[j];
Chris@42 190 ego->kind[j] = kswap;
Chris@42 191 }
Chris@42 192 }
Chris@42 193
Chris@42 194 for (i = 0; i < rnk; ++i)
Chris@42 195 if (ego->sz->dims[i].n == 2 && (ego->kind[i] == REDFT00
Chris@42 196 || ego->kind[i] == DHT
Chris@42 197 || ego->kind[i] == HC2R))
Chris@42 198 ego->kind[i] = R2HC; /* size-2 transforms are equivalent */
Chris@42 199
Chris@42 200 ego->vecsz = X(tensor_compress_contiguous)(vecsz);
Chris@42 201 ego->I = I;
Chris@42 202 ego->O = O;
Chris@42 203
Chris@42 204 A(FINITE_RNK(ego->sz->rnk));
Chris@42 205
Chris@42 206 return &(ego->super);
Chris@42 207 }
Chris@42 208
Chris@42 209 /* Same as X(mkproblem_rdft), but also destroy input tensors. */
Chris@42 210 problem *X(mkproblem_rdft_d)(tensor *sz, tensor *vecsz,
Chris@42 211 R *I, R *O, const rdft_kind *kind)
Chris@42 212 {
Chris@42 213 problem *p = X(mkproblem_rdft)(sz, vecsz, I, O, kind);
Chris@42 214 X(tensor_destroy2)(vecsz, sz);
Chris@42 215 return p;
Chris@42 216 }
Chris@42 217
Chris@42 218 /* As above, but for rnk <= 1 only and takes a scalar kind parameter */
Chris@42 219 problem *X(mkproblem_rdft_1)(const tensor *sz, const tensor *vecsz,
Chris@42 220 R *I, R *O, rdft_kind kind)
Chris@42 221 {
Chris@42 222 A(sz->rnk <= 1);
Chris@42 223 return X(mkproblem_rdft)(sz, vecsz, I, O, &kind);
Chris@42 224 }
Chris@42 225
Chris@42 226 problem *X(mkproblem_rdft_1_d)(tensor *sz, tensor *vecsz,
Chris@42 227 R *I, R *O, rdft_kind kind)
Chris@42 228 {
Chris@42 229 A(sz->rnk <= 1);
Chris@42 230 return X(mkproblem_rdft_d)(sz, vecsz, I, O, &kind);
Chris@42 231 }
Chris@42 232
Chris@42 233 /* create a zero-dimensional problem */
Chris@42 234 problem *X(mkproblem_rdft_0_d)(tensor *vecsz, R *I, R *O)
Chris@42 235 {
Chris@42 236 return X(mkproblem_rdft_d)(X(mktensor_0d)(), vecsz, I, O,
Chris@42 237 (const rdft_kind *)0);
Chris@42 238 }