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