removed junk under dft/simd/nonportable
[gsoc2010-fftw-neon:gsoc2010-fftw-neon.git] / api / apiplan.c
1 /*
2  * Copyright (c) 2003, 2007-8 Matteo Frigo
3  * Copyright (c) 2003, 2007-8 Massachusetts Institute of Technology
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 #include "api.h"
22
23 static plan *mkplan0(planner *plnr, unsigned flags, 
24                      const problem *prb, int hash_info, 
25                      wisdom_state_t wisdom_state)
26 WITH_ALIGNED_STACK({
27      /* map API flags into FFTW flags */
28      X(mapflags)(plnr, flags);
29
30      plnr->flags.hash_info = hash_info;
31      plnr->wisdom_state = wisdom_state;
32
33      /* create plan */
34      return plnr->adt->mkplan(plnr, prb);
35 })
36
37 static void aligned_awake(plan *ego, enum wakefulness wakefulness)
38 WITH_ALIGNED_STACK({
39      X(plan_awake)(ego, wakefulness);
40 })
41
42 static unsigned force_estimator(unsigned flags)
43 {
44      flags &= ~(FFTW_MEASURE | FFTW_PATIENT | FFTW_EXHAUSTIVE);
45      return (flags | FFTW_ESTIMATE);
46 }
47
48 static plan *mkplan(planner *plnr, unsigned flags, 
49                     const problem *prb, int hash_info)
50 {
51      plan *pln;
52
53      pln = mkplan0(plnr, flags, prb, hash_info, WISDOM_NORMAL);
54
55      if (plnr->wisdom_state == WISDOM_NORMAL && !pln) {
56           /* maybe the planner failed because of inconsistent wisdom;
57              plan again ignoring infeasible wisdom */
58           pln = mkplan0(plnr, force_estimator(flags), prb, 
59                         hash_info, WISDOM_IGNORE_INFEASIBLE);
60      }
61
62      if (plnr->wisdom_state == WISDOM_IS_BOGUS) {
63           /* if the planner detected a wisdom inconsistency,
64              forget all wisdom and plan again */
65           plnr->adt->forget(plnr, FORGET_EVERYTHING);
66
67           A(!pln);
68           pln = mkplan0(plnr, flags, prb, hash_info, WISDOM_NORMAL);
69
70           if (plnr->wisdom_state == WISDOM_IS_BOGUS) {
71                /* if it still fails, plan without wisdom */
72                plnr->adt->forget(plnr, FORGET_EVERYTHING);
73
74                A(!pln);
75                pln = mkplan0(plnr, force_estimator(flags), 
76                              prb, hash_info, WISDOM_IGNORE_ALL);
77           }
78      }
79
80      return pln;
81 }
82
83 apiplan *X(mkapiplan)(int sign, unsigned flags, problem *prb)
84 {
85      apiplan *p = 0;
86      plan *pln;
87      unsigned flags_used_for_planning;
88      planner *plnr = X(the_planner)();
89      unsigned int pats[] = {FFTW_ESTIMATE, FFTW_MEASURE,
90                             FFTW_PATIENT, FFTW_EXHAUSTIVE};
91      int pat, pat_max;
92
93      if (flags & FFTW_WISDOM_ONLY) {
94           /* Special mode that returns a plan only if wisdom is present,
95              and returns 0 otherwise.  This is now documented in the manual,
96              as a way to detect whether wisdom is available for a problem. */
97           flags_used_for_planning = flags;
98           pln = mkplan0(plnr, flags, prb, 0, WISDOM_ONLY);
99      } else {
100           pat_max = flags & FFTW_ESTIMATE ? 0 :
101                (flags & FFTW_EXHAUSTIVE ? 3 :
102                 (flags & FFTW_PATIENT ? 2 : 1));
103           pat = plnr->timelimit >= 0 ? 0 : pat_max;
104
105           flags &= ~(FFTW_ESTIMATE | FFTW_MEASURE | 
106                      FFTW_PATIENT | FFTW_EXHAUSTIVE);
107
108           plnr->start_time = X(get_crude_time)();
109           
110           /* plan at incrementally increasing patience until we run
111              out of time */
112           for (pln = 0, flags_used_for_planning = 0; pat <= pat_max; ++pat) {
113                plan *pln1;
114                unsigned tmpflags = flags | pats[pat];
115                pln1 = mkplan(plnr, tmpflags, prb, 0);
116
117                if (!pln1) {
118                     /* don't bother continuing if planner failed or timed out */
119                     A(!pln || plnr->timed_out);
120                     break;
121                }
122
123                X(plan_destroy_internal)(pln);
124                pln = pln1;
125                flags_used_for_planning = tmpflags;
126           }
127      }
128
129      if (pln) {
130           /* build apiplan */
131           p = (apiplan *) MALLOC(sizeof(apiplan), PLANS);
132           p->prb = prb;
133           p->sign = sign; /* cache for execute_dft */
134           
135           /* re-create plan from wisdom, adding blessing */
136           p->pln = mkplan(plnr, flags_used_for_planning, prb, BLESSING);
137
138           if (sizeof(trigreal) > sizeof(R)) {
139                /* this is probably faster, and we have enough trigreal
140                   bits to maintain accuracy */
141                aligned_awake(p->pln, AWAKE_SQRTN_TABLE);
142           } else {
143                /* more accurate */
144                aligned_awake(p->pln, AWAKE_SINCOS);
145           }
146           
147           /* we don't use pln for p->pln, above, since by re-creating the
148              plan we might use more patient wisdom from a timed-out mkplan */
149           X(plan_destroy_internal)(pln);
150      } else
151           X(problem_destroy)(prb);
152      
153      /* discard all information not necessary to reconstruct the plan */
154      plnr->adt->forget(plnr, FORGET_ACCURSED);
155      
156      return p;
157 }
158
159 void X(destroy_plan)(X(plan) p)
160 {
161      if (p) {
162           X(plan_awake)(p->pln, SLEEPY);
163           X(plan_destroy_internal)(p->pln);
164           X(problem_destroy)(p->prb);
165           X(ifree)(p);
166      }
167 }