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