annotate src/fftw-3.3.3/rdft/problem2.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 37bf6b4a2645
children
rev   line source
Chris@10 1 /*
Chris@10 2 * Copyright (c) 2003, 2007-11 Matteo Frigo
Chris@10 3 * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology
Chris@10 4 *
Chris@10 5 * This program is free software; you can redistribute it and/or modify
Chris@10 6 * it under the terms of the GNU General Public License as published by
Chris@10 7 * the Free Software Foundation; either version 2 of the License, or
Chris@10 8 * (at your option) any later version.
Chris@10 9 *
Chris@10 10 * This program is distributed in the hope that it will be useful,
Chris@10 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@10 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@10 13 * GNU General Public License for more details.
Chris@10 14 *
Chris@10 15 * You should have received a copy of the GNU General Public License
Chris@10 16 * along with this program; if not, write to the Free Software
Chris@10 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Chris@10 18 *
Chris@10 19 */
Chris@10 20
Chris@10 21
Chris@10 22 #include "dft.h"
Chris@10 23 #include "rdft.h"
Chris@10 24 #include <stddef.h>
Chris@10 25
Chris@10 26 static void destroy(problem *ego_)
Chris@10 27 {
Chris@10 28 problem_rdft2 *ego = (problem_rdft2 *) ego_;
Chris@10 29 X(tensor_destroy2)(ego->vecsz, ego->sz);
Chris@10 30 X(ifree)(ego_);
Chris@10 31 }
Chris@10 32
Chris@10 33 static void hash(const problem *p_, md5 *m)
Chris@10 34 {
Chris@10 35 const problem_rdft2 *p = (const problem_rdft2 *) p_;
Chris@10 36 X(md5puts)(m, "rdft2");
Chris@10 37 X(md5int)(m, p->r0 == p->cr);
Chris@10 38 X(md5INT)(m, p->r1 - p->r0);
Chris@10 39 X(md5INT)(m, p->ci - p->cr);
Chris@10 40 X(md5int)(m, X(alignment_of)(p->r0));
Chris@10 41 X(md5int)(m, X(alignment_of)(p->r1));
Chris@10 42 X(md5int)(m, X(alignment_of)(p->cr));
Chris@10 43 X(md5int)(m, X(alignment_of)(p->ci));
Chris@10 44 X(md5int)(m, p->kind);
Chris@10 45 X(tensor_md5)(m, p->sz);
Chris@10 46 X(tensor_md5)(m, p->vecsz);
Chris@10 47 }
Chris@10 48
Chris@10 49 static void print(const problem *ego_, printer *p)
Chris@10 50 {
Chris@10 51 const problem_rdft2 *ego = (const problem_rdft2 *) ego_;
Chris@10 52 p->print(p, "(rdft2 %d %d %T %T)",
Chris@10 53 (int)(ego->cr == ego->r0),
Chris@10 54 (int)(ego->kind),
Chris@10 55 ego->sz,
Chris@10 56 ego->vecsz);
Chris@10 57 }
Chris@10 58
Chris@10 59 static void recur(const iodim *dims, int rnk, R *I0, R *I1)
Chris@10 60 {
Chris@10 61 if (rnk == RNK_MINFTY)
Chris@10 62 return;
Chris@10 63 else if (rnk == 0)
Chris@10 64 I0[0] = K(0.0);
Chris@10 65 else if (rnk > 0) {
Chris@10 66 INT i, n = dims[0].n, is = dims[0].is;
Chris@10 67
Chris@10 68 if (rnk == 1) {
Chris@10 69 for (i = 0; i < n - 1; i += 2) {
Chris@10 70 *I0 = *I1 = K(0.0);
Chris@10 71 I0 += is; I1 += is;
Chris@10 72 }
Chris@10 73 if (i < n)
Chris@10 74 *I0 = K(0.0);
Chris@10 75 } else {
Chris@10 76 for (i = 0; i < n; ++i)
Chris@10 77 recur(dims + 1, rnk - 1, I0 + i * is, I1 + i * is);
Chris@10 78 }
Chris@10 79 }
Chris@10 80 }
Chris@10 81
Chris@10 82 static void vrecur(const iodim *vdims, int vrnk,
Chris@10 83 const iodim *dims, int rnk, R *I0, R *I1)
Chris@10 84 {
Chris@10 85 if (vrnk == RNK_MINFTY)
Chris@10 86 return;
Chris@10 87 else if (vrnk == 0)
Chris@10 88 recur(dims, rnk, I0, I1);
Chris@10 89 else if (vrnk > 0) {
Chris@10 90 INT i, n = vdims[0].n, is = vdims[0].is;
Chris@10 91
Chris@10 92 for (i = 0; i < n; ++i)
Chris@10 93 vrecur(vdims + 1, vrnk - 1,
Chris@10 94 dims, rnk, I0 + i * is, I1 + i * is);
Chris@10 95 }
Chris@10 96 }
Chris@10 97
Chris@10 98 INT X(rdft2_complex_n)(INT real_n, rdft_kind kind)
Chris@10 99 {
Chris@10 100 switch (kind) {
Chris@10 101 case R2HC:
Chris@10 102 case HC2R:
Chris@10 103 return (real_n / 2) + 1;
Chris@10 104 case R2HCII:
Chris@10 105 case HC2RIII:
Chris@10 106 return (real_n + 1) / 2;
Chris@10 107 default:
Chris@10 108 /* can't happen */
Chris@10 109 A(0);
Chris@10 110 return 0;
Chris@10 111 }
Chris@10 112 }
Chris@10 113
Chris@10 114 static void zero(const problem *ego_)
Chris@10 115 {
Chris@10 116 const problem_rdft2 *ego = (const problem_rdft2 *) ego_;
Chris@10 117 if (R2HC_KINDP(ego->kind)) {
Chris@10 118 /* FIXME: can we avoid the double recursion somehow? */
Chris@10 119 vrecur(ego->vecsz->dims, ego->vecsz->rnk,
Chris@10 120 ego->sz->dims, ego->sz->rnk,
Chris@10 121 UNTAINT(ego->r0), UNTAINT(ego->r1));
Chris@10 122 } else {
Chris@10 123 tensor *sz;
Chris@10 124 tensor *sz2 = X(tensor_copy)(ego->sz);
Chris@10 125 int rnk = sz2->rnk;
Chris@10 126 if (rnk > 0) /* ~half as many complex outputs */
Chris@10 127 sz2->dims[rnk-1].n =
Chris@10 128 X(rdft2_complex_n)(sz2->dims[rnk-1].n, ego->kind);
Chris@10 129 sz = X(tensor_append)(ego->vecsz, sz2);
Chris@10 130 X(tensor_destroy)(sz2);
Chris@10 131 X(dft_zerotens)(sz, UNTAINT(ego->cr), UNTAINT(ego->ci));
Chris@10 132 X(tensor_destroy)(sz);
Chris@10 133 }
Chris@10 134 }
Chris@10 135
Chris@10 136 static const problem_adt padt =
Chris@10 137 {
Chris@10 138 PROBLEM_RDFT2,
Chris@10 139 hash,
Chris@10 140 zero,
Chris@10 141 print,
Chris@10 142 destroy
Chris@10 143 };
Chris@10 144
Chris@10 145 problem *X(mkproblem_rdft2)(const tensor *sz, const tensor *vecsz,
Chris@10 146 R *r0, R *r1, R *cr, R *ci,
Chris@10 147 rdft_kind kind)
Chris@10 148 {
Chris@10 149 problem_rdft2 *ego;
Chris@10 150
Chris@10 151 A(kind == R2HC || kind == R2HCII || kind == HC2R || kind == HC2RIII);
Chris@10 152 A(X(tensor_kosherp)(sz));
Chris@10 153 A(X(tensor_kosherp)(vecsz));
Chris@10 154 A(FINITE_RNK(sz->rnk));
Chris@10 155
Chris@10 156 /* require in-place problems to use r0 == cr */
Chris@10 157 if (UNTAINT(r0) == UNTAINT(ci))
Chris@10 158 return X(mkproblem_unsolvable)();
Chris@10 159
Chris@10 160 /* FIXME: should check UNTAINT(r1) == UNTAINT(cr) but
Chris@10 161 only if odd elements exist, which requires compressing the
Chris@10 162 tensors first */
Chris@10 163
Chris@10 164 if (UNTAINT(r0) == UNTAINT(cr))
Chris@10 165 r0 = cr = JOIN_TAINT(r0, cr);
Chris@10 166
Chris@10 167 ego = (problem_rdft2 *)X(mkproblem)(sizeof(problem_rdft2), &padt);
Chris@10 168
Chris@10 169 if (sz->rnk > 1) { /* have to compress rnk-1 dims separately, ugh */
Chris@10 170 tensor *szc = X(tensor_copy_except)(sz, sz->rnk - 1);
Chris@10 171 tensor *szr = X(tensor_copy_sub)(sz, sz->rnk - 1, 1);
Chris@10 172 tensor *szcc = X(tensor_compress)(szc);
Chris@10 173 if (szcc->rnk > 0)
Chris@10 174 ego->sz = X(tensor_append)(szcc, szr);
Chris@10 175 else
Chris@10 176 ego->sz = X(tensor_compress)(szr);
Chris@10 177 X(tensor_destroy2)(szc, szr); X(tensor_destroy)(szcc);
Chris@10 178 } else {
Chris@10 179 ego->sz = X(tensor_compress)(sz);
Chris@10 180 }
Chris@10 181 ego->vecsz = X(tensor_compress_contiguous)(vecsz);
Chris@10 182 ego->r0 = r0;
Chris@10 183 ego->r1 = r1;
Chris@10 184 ego->cr = cr;
Chris@10 185 ego->ci = ci;
Chris@10 186 ego->kind = kind;
Chris@10 187
Chris@10 188 A(FINITE_RNK(ego->sz->rnk));
Chris@10 189 return &(ego->super);
Chris@10 190
Chris@10 191 }
Chris@10 192
Chris@10 193 /* Same as X(mkproblem_rdft2), but also destroy input tensors. */
Chris@10 194 problem *X(mkproblem_rdft2_d)(tensor *sz, tensor *vecsz,
Chris@10 195 R *r0, R *r1, R *cr, R *ci, rdft_kind kind)
Chris@10 196 {
Chris@10 197 problem *p = X(mkproblem_rdft2)(sz, vecsz, r0, r1, cr, ci, kind);
Chris@10 198 X(tensor_destroy2)(vecsz, sz);
Chris@10 199 return p;
Chris@10 200 }
Chris@10 201
Chris@10 202 /* Same as X(mkproblem_rdft2_d), but with only one R pointer.
Chris@10 203 Used by the API. */
Chris@10 204 problem *X(mkproblem_rdft2_d_3pointers)(tensor *sz, tensor *vecsz,
Chris@10 205 R *r0, R *cr, R *ci, rdft_kind kind)
Chris@10 206 {
Chris@10 207 problem *p;
Chris@10 208 int rnk = sz->rnk;
Chris@10 209 R *r1;
Chris@10 210
Chris@10 211 if (rnk == 0)
Chris@10 212 r1 = r0;
Chris@10 213 else if (R2HC_KINDP(kind)) {
Chris@10 214 r1 = r0 + sz->dims[rnk-1].is;
Chris@10 215 sz->dims[rnk-1].is *= 2;
Chris@10 216 } else {
Chris@10 217 r1 = r0 + sz->dims[rnk-1].os;
Chris@10 218 sz->dims[rnk-1].os *= 2;
Chris@10 219 }
Chris@10 220
Chris@10 221 p = X(mkproblem_rdft2)(sz, vecsz, r0, r1, cr, ci, kind);
Chris@10 222 X(tensor_destroy2)(vecsz, sz);
Chris@10 223 return p;
Chris@10 224 }