1 /*
2 Teem: Tools to process and visualize scientific data and images .
3 Copyright (C) 2012, 2011, 2010, 2009 University of Chicago
4 Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann
5 Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 (LGPL) as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11 The terms of redistributing and/or modifying this software also
12 include exceptions to the LGPL that facilitate static linking.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with this library; if not, write to Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include "pull.h"
25 #include "privatePull.h"
26
27 pullTask *
_pullTaskNew(pullContext * pctx,int threadIdx)28 _pullTaskNew(pullContext *pctx, int threadIdx) {
29 static const char me[]="_pullTaskNew";
30 pullTask *task;
31 unsigned int ii;
32 pullPtrPtrUnion pppu;
33
34 task = AIR_CALLOC(1, pullTask);
35 if (!task) {
36 biffAddf(PULL, "%s: couldn't allocate task", me);
37 return NULL;
38 }
39
40 task->pctx = pctx;
41 for (ii=0; ii<pctx->volNum; ii++) {
42 if (!(task->vol[ii] = _pullVolumeCopy(pctx->vol[ii]))) {
43 biffAddf(PULL, "%s: trouble copying vol %u/%u", me, ii, pctx->volNum);
44 return NULL;
45 }
46 }
47 if (0) {
48 gagePerVolume *pvl;
49 const double *ans;
50 double pos[3];
51 int gret;
52 for (ii=0; ii<pctx->volNum; ii++) {
53 pvl = task->vol[ii]->gctx->pvl[0];
54 printf("!%s: vol[%u] query:\n", me, ii);
55 gageQueryPrint(stdout, pvl->kind, pvl->query);
56 ans = gageAnswerPointer(task->vol[ii]->gctx, pvl, gageSclValue);
57 ELL_3V_SET(pos, 0.6, 0.6, 0.3);
58 gret = gageProbeSpace(task->vol[ii]->gctx, pos[0], pos[1], pos[2],
59 AIR_FALSE, AIR_TRUE);
60 printf("!%s: (%d) val(%g,%g,%g) = %g\n", me, gret,
61 pos[0], pos[1], pos[2], *ans);
62 ELL_3V_SET(pos, 0.5, 0.0, 0.0);
63 gret = gageProbeSpace(task->vol[ii]->gctx, pos[0], pos[1], pos[2],
64 AIR_FALSE, AIR_TRUE);
65 printf("!%s: (%d) val(%g,%g,%g) = %g\n", me, gret,
66 pos[0], pos[1], pos[2], *ans);
67 }
68 }
69 /* now set up all pointers for per-task pullInfos */
70 for (ii=0; ii<=PULL_INFO_MAX; ii++) {
71 const pullVolume *vol;
72 if (pctx->ispec[ii]) {
73 if (pullSourceGage == pctx->ispec[ii]->source) {
74 vol = task->vol[pctx->ispec[ii]->volIdx];
75 task->ans[ii] = gageAnswerPointer(vol->gctx, vol->gpvl,
76 pctx->ispec[ii]->item);
77 if (pctx->verbose) {
78 printf("%s: task->ans[%u] = (%s) %p\n", me, ii,
79 vol->kind->name, AIR_CVOIDP(task->ans[ii]));
80 }
81 } else {
82 task->ans[ii] = NULL;
83 }
84 } else {
85 task->ans[ii] = NULL;
86 }
87 }
88 /* HEY: any idea why there is so little error checking in the below? */
89 /* initialize to descent because that's what's needed for the end of point
90 initialization, when initial energy must be learned */
91 task->processMode = pullProcessModeDescent;
92 task->probeSeedPreThreshOnly = AIR_FALSE;
93 if (pctx->threadNum > 1) {
94 task->thread = airThreadNew();
95 }
96 task->threadIdx = threadIdx;
97 task->rng = airRandMTStateNew(pctx->rngSeed + threadIdx);
98 task->pointBuffer = pullPointNew(pctx);
99 pctx->idtagNext = 0; /* because pullPointNew incremented it */
100 task->neighPoint = AIR_CAST(pullPoint **, calloc(_PULL_NEIGH_MAXNUM,
101 sizeof(pullPoint*)));
102 task->addPoint = NULL;
103 task->addPointNum = 0;
104 pppu.points = &(task->addPoint);
105 task->addPointArr = airArrayNew(pppu.v, &(task->addPointNum),
106 sizeof(pullPoint*),
107 /* not exactly the right semantics . . . */
108 PULL_POINT_NEIGH_INCR);
109 task->nixPoint = NULL;
110 task->nixPointNum = 0;
111 pppu.points = &(task->nixPoint);
112 task->nixPointArr = airArrayNew(pppu.v, &(task->nixPointNum),
113 sizeof(pullPoint*),
114 /* not exactly the right semantics . . . */
115 PULL_POINT_NEIGH_INCR);
116 task->returnPtr = NULL;
117 task->stuckNum = 0;
118 return task;
119 }
120
121 pullTask *
_pullTaskNix(pullTask * task)122 _pullTaskNix(pullTask *task) {
123 unsigned int ii;
124
125 if (task) {
126 for (ii=0; ii<task->pctx->volNum; ii++) {
127 task->vol[ii] = pullVolumeNix(task->vol[ii]);
128 }
129 if (task->pctx->threadNum > 1) {
130 task->thread = airThreadNix(task->thread);
131 }
132 task->rng = airRandMTStateNix(task->rng);
133 task->pointBuffer = pullPointNix(task->pointBuffer);
134 airFree(task->neighPoint);
135 task->addPointArr = airArrayNuke(task->addPointArr);
136 task->nixPointArr = airArrayNuke(task->nixPointArr);
137 airFree(task);
138 }
139 return NULL;
140 }
141
142 /*
143 ** _pullTaskSetup sets:
144 **** pctx->task
145 **** pctx->task[]
146 */
147 int
_pullTaskSetup(pullContext * pctx)148 _pullTaskSetup(pullContext *pctx) {
149 static const char me[]="_pullTaskSetup";
150 unsigned int tidx;
151
152 pctx->task = (pullTask **)calloc(pctx->threadNum, sizeof(pullTask *));
153 if (!(pctx->task)) {
154 biffAddf(PULL, "%s: couldn't allocate array of tasks", me);
155 return 1;
156 }
157 for (tidx=0; tidx<pctx->threadNum; tidx++) {
158 if (pctx->verbose) {
159 printf("%s: creating task %u/%u\n", me, tidx, pctx->threadNum);
160 }
161 pctx->task[tidx] = _pullTaskNew(pctx, tidx);
162 if (!(pctx->task[tidx])) {
163 biffAddf(PULL, "%s: couldn't allocate task %d", me, tidx);
164 return 1;
165 }
166 }
167 return 0;
168 }
169
170 void
_pullTaskFinish(pullContext * pctx)171 _pullTaskFinish(pullContext *pctx) {
172 unsigned int tidx;
173
174 for (tidx=0; tidx<pctx->threadNum; tidx++) {
175 pctx->task[tidx] = _pullTaskNix(pctx->task[tidx]);
176 }
177 airFree(pctx->task);
178 pctx->task = NULL;
179 return;
180 }
181