diff --git a/contrib/Snaphu/include/snaphu.h b/contrib/Snaphu/include/snaphu.h index 99fc3f90..d45514ba 100644 --- a/contrib/Snaphu/include/snaphu.h +++ b/contrib/Snaphu/include/snaphu.h @@ -14,7 +14,8 @@ /**********************/ #define PROGRAMNAME "snaphu" -#define VERSION "1.4.2" +#define VERSION "2.0.6" +#define BUGREPORTEMAIL "snaphu@gmail.com" #ifdef PI #undef PI #endif @@ -27,16 +28,24 @@ #define TRUE 1 #define FALSE 0 #define LARGESHORT 32000 -#define LARGELONG 2000000000 -#define LARGELONGLONG 9000000000000000000 +#define LARGEINT 2000000000 #define LARGEFLOAT 1.0e35 -#define VERYFAR LARGELONG +#define VERYFAR LARGEINT #define GROUNDROW -2 #define GROUNDCOL -2 -#define MAXGROUPBASE LARGELONG -#define ONTREE 1 -#define INBUCKET 2 -#define NOTINBUCKET 3 +#define BOUNDARYROW -4 +#define BOUNDARYCOL -4 +#define MAXGROUPBASE LARGEINT +#define ONTREE -1 +#define INBUCKET -2 +#define NOTINBUCKET -3 +#define PRUNED -4 +#define MASKED -5 +#define BOUNDARYPTR -6 +#define BOUNDARYCANDIDATE -7 +#define BOUNDARYLEVEL LARGEINT +#define INTERIORLEVEL (BOUNDARYLEVEL-1) +#define MINBOUNDARYSIZE 100 #define POSINCR 0 #define NEGINCR 1 #define NOCOSTSHELF -LARGESHORT @@ -47,6 +56,8 @@ #define NEGBUCKETFRACTION 1.0 #define POSBUCKETFRACTION 1.0 #define CLIPFACTOR 0.6666666667 +#define NSOURCELISTMEMINCR 1024 +#define NLISTMEMINCR 1024 #define DEF_OUTFILE "snaphu.out" #define DEF_SYSCONFFILE "" /* "/usr/local/snaphu/snaphu.conf" */ #define DEF_WEIGHTFILE "" /* "snaphu.weight" */ @@ -56,6 +67,8 @@ #define DEF_CORRFILE "" /* "snaphu.corr" */ #define DEF_ESTFILE "" /* "snaphu.est" */ #define DEF_COSTINFILE "" +#define DEF_BYTEMASKFILE "" +#define DEF_DOTILEMASKFILE "" #define DEF_INITFILE "" #define DEF_FLOWFILE "" #define DEF_EIFILE "" @@ -74,7 +87,7 @@ #define POSSHORTRANGE SHRT_MAX #define MAXRES SCHAR_MAX #define MINRES SCHAR_MIN -#define PROBCOSTP (-16) +#define PROBCOSTP (-99.999) #define NULLFILE "/dev/null" #define DEF_ERRORSTREAM stderr #define DEF_OUTPUTSTREAM stdout @@ -90,11 +103,14 @@ #define DEF_VERBOSE FALSE #define DEF_AMPLITUDE TRUE #define AUTOCALCSTATMAX 0 +#define MAXNSHORTCYCLE 8192 #define USEMAXCYCLEFRACTION (-123) #define COMPLEX_DATA 1 /* file format */ #define FLOAT_DATA 2 /* file format */ #define ALT_LINE_DATA 3 /* file format */ #define ALT_SAMPLE_DATA 4 /* file format */ +#define TILEINITFILEFORMAT ALT_LINE_DATA +#define TILEINITFILEROOT "snaphu_tileinit_" #define ABNORMAL_EXIT 1 /* exit code */ #define NORMAL_EXIT 0 /* exit code */ #define DUMP_PATH "/tmp/" /* default location for writing dumps */ @@ -119,13 +135,16 @@ #define LEFT 3 #define UP 4 #define TILEDPSICOLFACTOR 0.8 -#define ZEROCOSTARC -LARGELONG +#define TILEOVRLPWARNTHRESH 400 +#define ZEROCOSTARC -LARGEINT #define PINGPONG 2 #define SINGLEANTTRANSMIT 1 #define NOSTATCOSTS 0 #define TOPO 1 #define DEFO 2 #define SMOOTH 3 +#define CONNCOMPOUTTYPEUCHAR 1 +#define CONNCOMPOUTTYPEUINT 4 /* SAR and geometry parameter defaults */ @@ -201,6 +220,8 @@ /* algorithm parameters */ #define DEF_FLIPPHASESIGN FALSE +#define DEF_ONETILEREOPT FALSE +#define DEF_RMTILEINIT TRUE #define DEF_MAXFLOW 4 #define DEF_KROWEI 65 #define DEF_KCOLEI 257 @@ -216,10 +237,11 @@ #define DEF_SRCROW -1 #define DEF_SRCCOL -1 #define DEF_P PROBCOSTP +#define DEF_BIDIRLPN TRUE #define DEF_NSHORTCYCLE 200 #define DEF_MAXNEWNODECONST 0.0008 #define DEF_MAXCYCLEFRACTION 0.00001 -#define DEF_SOURCEMODE 0 +#define DEF_NCONNNODEMIN 0 #define DEF_MAXNFLOWCYCLES USEMAXCYCLEFRACTION #define DEF_INITMAXFLOW 9999 #define INITMAXCOSTINCR 200 @@ -239,6 +261,13 @@ #define INCRCOSTFILEPOS "snaphu.incrcostpos" #define INCRCOSTFILENEG "snaphu.incrcostneg" #define DEF_CS2SCALEFACTOR 8 +#define DEF_NMAJORPRUNE LARGEINT +#define DEF_PRUNECOSTTHRESH LARGEINT +#define DEF_EDGEMASKTOP 0 +#define DEF_EDGEMASKBOT 0 +#define DEF_EDGEMASKLEFT 0 +#define DEF_EDGEMASKRIGHT 0 +#define CONNCOMPMEMINCR 1024 /* default tile parameters */ @@ -256,14 +285,16 @@ #define DEF_NTHREADS 1 #define DEF_SCNDRYARCFLOWMAX 8 #define DEF_TILEEDGEWEIGHT 2.5 +#define DEF_TILEDIR "" #define DEF_ASSEMBLEONLY FALSE -#define DEF_RMTMPTILE FALSE +#define DEF_RMTMPTILE TRUE /* default connected component parameters */ #define DEF_MINCONNCOMPFRAC 0.01 #define DEF_CONNCOMPTHRESH 300 #define DEF_MAXNCOMPS 32 +#define DEF_CONNCOMPOUTTYPE CONNCOMPOUTTYPEUCHAR /* default file formats */ @@ -284,11 +315,13 @@ " -t use topography mode costs (default)\n"\ " -d use deformation mode costs\n"\ " -s use smooth-solution mode costs\n"\ + " -C parse argument string as config line as from conf file\n"\ " -f read configuration parameters from file\n"\ " -o write output to file\n"\ " -a read amplitude data from file\n"\ " -A read power data from file\n"\ " -m read interferogram magnitude data from file\n"\ + " -M read byte mask data from file\n"\ " -c read correlation data from file\n"\ " -e read coarse unwrapped-phase estimate from file\n"\ " -w read scalar weights from file\n"\ @@ -300,6 +333,8 @@ " -q quantify cost of unwrapped input file then exit\n"\ " -g grow connected components mask and write to file\n"\ " -G grow connected components mask for unwrapped input\n"\ + " -S single-tile reoptimization after multi-tile init\n"\ + " -k keep temporary tile outputs\n"\ " -l log runtime parameters to file\n"\ " -v give verbose output\n"\ " --mst use MST algorithm for initialization (default)\n"\ @@ -310,7 +345,8 @@ " --costoutfile write statistical costs to file\n"\ " --tile unwrap as nrow x ncol tiles\n"\ " --nproc number of processors used in tile mode\n"\ - " --assemble assemble unwrapped tiles in dir\n"\ + " --tiledir use specified directory for tiles\n"\ + " --assemble assemble unwrapped tiles in tiledir\n"\ " --piece unwrap subset of image\n" \ " --debug, --dumpall dump all intermediate data arrays\n"\ " --copyright, --info print copyright and bug report info\n"\ @@ -323,22 +359,29 @@ " -t use topography mode costs (default)\n"\ " -d use deformation mode costs\n"\ " -s use smooth-solution mode costs\n"\ + " -C parse argument string as config line as from conf file\n"\ " -f read configuration parameters from file\n"\ " -o write output to file\n"\ " -a read amplitude data from file\n"\ " -c read correlation data from file\n"\ + " -M read byte mask data from file\n"\ " -b perpendicular baseline (meters)\n"\ " -i do initialization and exit\n"\ + " -S single-tile reoptimization after multi-tile init\n"\ " -l log runtime parameters to file\n"\ + " -u infile is already unwrapped; initialization not needed\n"\ " -v give verbose output\n"\ " --mst use MST algorithm for initialization (default)\n"\ " --mcf use MCF algorithm for initialization\n"\ + " --tile unwrap as nrow x ncol tiles\n"\ + " --nproc number of processors used in tile mode\n"\ "\n"\ "type snaphu -h for a complete list of options\n"\ "\n" #define COPYRIGHT\ - "Copyright 2002 Board of Trustees, Leland Stanford Jr. University\n"\ + "Written by Curtis W. Chen\n"\ + "Copyright 2002,2017 Board of Trustees, Leland Stanford Jr. University\n"\ "\n"\ "Except as noted below, permission to use, copy, modify, and\n"\ "distribute, this software and its documentation for any purpose is\n"\ @@ -372,7 +415,7 @@ " COPYRIGHT C 1995 IG Systems, Inc. Permission to use for\n"\ " evaluation purposes is granted provided that proper\n"\ " acknowledgments are given. For a commercial licence, contact\n"\ - " igsys@eclipse.net.\n"\ + " igsys@eclipse.net (http://www.igsystems.com/cs2).\n"\ "\n"\ " This software comes with NO WARRANTY, expressed or implied. By way\n"\ " of example, but not limitation, we make no representations of\n"\ @@ -381,10 +424,8 @@ " documentation will not infringe any patents, copyrights,\n"\ " trademarks, or other rights.\n"\ "\n"\ - " http://www.igsystems.com/cs2\n"\ "\n"\ - "\n"\ - "Send snaphu bug reports to Curtis W. Chen (curtis@nova.stanford.edu).\n"\ + "Please send snaphu bug reports to " BUGREPORTEMAIL "\n"\ "\n" @@ -394,16 +435,35 @@ /* node data structure */ typedef struct nodeST{ - short row,col; /* row, col of this node */ - unsigned long level; /* tree level */ + int row,col; /* row, col of this node */ struct nodeST *next; /* ptr to next node in thread or bucket */ struct nodeST *prev; /* ptr to previous node in thread or bucket */ struct nodeST *pred; /* parent node in tree */ - long group; /* for marking label */ - long incost,outcost; /* costs to, from root of tree */ + unsigned int level; /* tree level */ + int group; /* for marking label */ + int incost,outcost; /* costs to, from root of tree */ }nodeT; +/* boundary neighbor structure */ +typedef struct neighborST{ + nodeT *neighbor; /* neighbor node pointer */ + int arcrow; /* row of arc to neighbor */ + int arccol; /* col of arc to neighbor */ + int arcdir; /* direction of arc to neighbor */ +}neighborT; + + +/* boundary data structure */ +typedef struct boundaryST{ + nodeT node[1]; /* ground node pointed to by this boundary */ + neighborT* neighborlist; /* list of neighbors of common boundary */ + nodeT **boundarylist; /* list of nodes covered by common boundary */ + long nneighbor; /* number of neighbor nodes of boundary */ + long nboundary; /* number of nodes covered by boundary */ +}boundaryT; + + /* arc cost data structure */ typedef struct costST{ short offset; /* offset of wrapped phase gradient from 0 */ @@ -420,6 +480,13 @@ typedef struct smoothcostST{ }smoothcostT; +/* arc cost data structure for bidirectional scalar costs */ +typedef struct bidircostST{ + short posweight; /* weight for positive flows */ + short negweight; /* weight for negative flows */ +}bidircostT; + + /* incremental cost data structure */ typedef struct incrcostST{ short poscost; /* cost for positive flow increment */ @@ -431,7 +498,7 @@ typedef struct incrcostST{ typedef struct candidateST{ nodeT *from, *to; /* endpoints of candidate arc */ long violation; /* magnitude of arc violation */ - short arcrow,arccol; /* indexes into arc arrays */ + int arcrow,arccol; /* indexes into arc arrays */ signed char arcdir; /* direction of arc (1=fwd, -1=rev) */ }candidateT; @@ -450,8 +517,8 @@ typedef struct bucketST{ /* secondary arc data structure */ typedef struct scndryarcST{ - short arcrow; /* row of arc in secondary network array */ - short arccol; /* col of arc in secondary network array */ + int arcrow; /* row of arc in secondary network array */ + int arccol; /* col of arc in secondary network array */ nodeT *from; /* secondary node at tail of arc */ nodeT *to; /* secondary node at head of arc */ signed char fromdir; /* direction from which arc enters head */ @@ -460,11 +527,11 @@ typedef struct scndryarcST{ /* supplementary data structure for secondary nodes */ typedef struct nodesuppST{ - short row; /* row of node in primary network problem */ - short col; /* col of node in primary network problem */ + int row; /* row of node in primary network problem */ + int col; /* col of node in primary network problem */ nodeT **neighbornodes; /* pointers to neighboring secondary nodes */ scndryarcT **outarcs; /* pointers to secondary arcs to neighbors */ - short noutarcs; /* number of arcs from this node */ + int noutarcs; /* number of arcs from this node */ }nodesuppT; @@ -538,8 +605,10 @@ typedef struct paramST{ signed char dumpall; /* dump intermediate files */ signed char verbose; /* print verbose output */ signed char amplitude; /* intensity data is amplitude, not power */ - signed char havemagnitude; /* flag to create correlation from other inputs */ - signed char flipphasesign; /* flag to flip phase and flow array signs */ + signed char havemagnitude; /* flag: create correlation from other inputs */ + signed char flipphasesign; /* flag: flip phase and flow array signs */ + signed char onetilereopt; /* flag: reoptimize full input after tile init */ + signed char rmtileinit; /* flag to remove temporary tile unw init soln */ long initmaxflow; /* maximum flow for initialization */ long arcmaxflowconst; /* units of flow past dzmax to use for initmaxflow */ long maxflow; /* max flow for tree solve looping */ @@ -555,12 +624,20 @@ typedef struct paramST{ double dnomincangle; /* step size for range-varying param lookup table */ long srcrow,srccol; /* source node location */ double p; /* power for Lp-norm solution (less than 0 is MAP) */ + signed char bidirlpn; /* use bidirectional Lp costs if TRUE */ long nshortcycle; /* number of points for one cycle in short int dz */ double maxnewnodeconst; /* number of nodes added to tree on each iteration */ long maxnflowcycles; /* max number of cycles to consider nflow done */ double maxcyclefraction;/* ratio of max cycles to pixels */ - long sourcemode; /* 0, -1, or 1, determines how tree root is chosen */ + long nconnnodemin; /* min number of nodes to keep in connected set */ long cs2scalefactor; /* scale factor for cs2 initialization (eg, 3-30) */ + long nmajorprune; /* number of major iterations between tree pruning */ + long prunecostthresh; /* cost threshold for pruning */ + long edgemasktop; /* number of pixels to mask at top edge of input */ + long edgemaskbot; /* number of pixels to mask at bottom edge */ + long edgemaskleft; /* number of pixels to mask at left edge */ + long edgemaskright; /* number of pixels to mask at right edge */ + long parentpid; /* process identification number of parent */ /* tiling parameters */ long ntilerow; /* number of tiles in azimuth */ @@ -570,7 +647,7 @@ typedef struct paramST{ long piecefirstrow; /* first row (indexed from 1) for piece mode */ long piecefirstcol; /* first column (indexed from 1) for piece mode */ long piecenrow; /* number of rows for piece mode */ - long piecencol; /* number of rows for piece mode */ + long piecencol; /* number of cols for piece mode */ long tilecostthresh; /* maximum cost within single reliable tile region */ long minregionsize; /* minimum number of pixels in a region */ long nthreads; /* number of parallel processes to run */ @@ -584,7 +661,7 @@ typedef struct paramST{ double minconncompfrac; /* min fraction of pixels in connected component */ long conncompthresh; /* cost threshold for connected component */ long maxncomps; /* max number of connected components */ - + int conncompouttype; /* flag for type of connected component output file */ }paramT; @@ -599,6 +676,8 @@ typedef struct infileST{ char corrfile[MAXSTRLEN]; /* correlation file */ char estfile[MAXSTRLEN]; /* unwrapped estimate */ char costinfile[MAXSTRLEN]; /* file from which cost data is read */ + char bytemaskfile[MAXSTRLEN]; /* signed char valid pixel mask */ + char dotilemaskfile[MAXSTRLEN]; /* signed char tile unwrap mask file */ signed char infileformat; /* input file format */ signed char unwrappedinfileformat; /* input file format if unwrapped */ signed char magfileformat; /* interferogram magnitude file format */ @@ -638,9 +717,18 @@ typedef struct tileparamST{ }tileparamT; +/* connectected component size structure */ +typedef struct conncompsizeST{ + unsigned int tilenum; /* tile index */ + unsigned int icomptile; /* conn comp index in tile */ + unsigned int icompfull; /* conn comp index in full array */ + long npix; /* number of pixels in conn comp */ +}conncompsizeT; + + /* type for total cost of solution (may overflow long) */ -typedef double totalcostT; /* typedef long long totalcostT; */ -#define INITTOTALCOST LARGEFLOAT /* #define INITTOTALCOST LARGELONGLONG */ +typedef double totalcostT; +#define INITTOTALCOST LARGEFLOAT @@ -648,440 +736,269 @@ typedef double totalcostT; /* typedef long long totalcostT; */ /* function prototypes */ /***********************/ -/* functions in snaphu.c */ - -void Unwrap(infileT *infiles, outfileT *outfiles, paramT *params, - long linelen, long nlines); -void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, - tileparamT *tileparams, long nlines, long linelen); - - /* functions in snaphu_tile.c */ -void SetupTile(long nlines, long linelen, paramT *params, - tileparamT *tileparams, outfileT *outfiles, - outfileT *tileoutfiles, long tilerow, long tilecol); -void GrowRegions(void **costs, short **flows, long nrow, long ncol, - incrcostT **incrcosts, outfileT *outfiles, paramT *params); -void GrowConnCompsMask(void **costs, short **flows, long nrow, long ncol, - incrcostT **incrcosts, outfileT *outfiles, - paramT *params); -long ThickenCosts(incrcostT **incrcosts, long nrow, long ncol); -nodeT *RegionsNeighborNode(nodeT *node1, long *arcnumptr, nodeT **nodes, - long *arcrowptr, long *arccolptr, - long nrow, long ncol); -void ClearBuckets(bucketT *bkts); -void MergeRegions(nodeT **nodes, nodeT *source, long *regionsizes, - long closestregion, long nrow, long ncol); -void RenumberRegion(nodeT **nodes, nodeT *source, long newnum, - long nrow, long ncol); -void AssembleTiles(outfileT *outfiles, paramT *params, - long nlines, long linelen); -void ReadNextRegion(long tilerow, long tilecol, long nlines, long linelen, - outfileT *outfiles, paramT *params, - short ***nextregionsptr, float ***nextunwphaseptr, - void ***nextcostsptr, - long *nextnrowptr, long *nextncolptr); -void SetTileReadParams(tileparamT *tileparams, long nexttilenlines, - long nexttilelinelen, long tilerow, long tilecol, - long nlines, long linelen, paramT *params); -void ReadEdgesAboveAndBelow(long tilerow, long tilecol, long nlines, - long linelen, paramT *params, outfileT *outfiles, - short *regionsabove, short *regionsbelow, - float *unwphaseabove, float *unwphasebelow, - void *costsabove, void *costsbelow); -void TraceRegions(short **regions, short **nextregions, short **lastregions, - short *regionsabove, short *regionsbelow, float **unwphase, - float **nextunwphase, float **lastunwphase, - float *unwphaseabove, float *unwphasebelow, void **costs, - void **nextcosts, void **lastcosts, void *costsabove, - void *costsbelow, long prevnrow, long prevncol, long tilerow, - long tilecol, long nrow, long ncol, nodeT **scndrynodes, - nodesuppT **nodesupp, scndryarcT **scndryarcs, - long ***scndrycosts, short *nscndrynodes, - short *nscndryarcs, long *totarclens, short **bulkoffsets, - paramT *params); -long FindNumPathsOut(nodeT *from, paramT *params, long tilerow, long tilecol, - long nnrow, long nncol, short **regions, - short **nextregions, short **lastregions, - short *regionsabove, short *regionsbelow, long prevncol); -void RegionTraceCheckNeighbors(nodeT *from, nodeT **nextnodeptr, - nodeT **primarynodes, short **regions, - short **nextregions, short **lastregions, - short *regionsabove, short *regionsbelow, - long tilerow, long tilecol, long nnrow, - long nncol, nodeT **scndrynodes, - nodesuppT **nodesupp, scndryarcT **scndryarcs, - long *nnewnodesptr, long *nnewarcsptr, - long flowmax, long nrow, long ncol, - long prevnrow, long prevncol, paramT *params, - void **costs, void **rightedgecosts, - void **loweredgecosts, void **leftedgecosts, - void **upperedgecosts, short **flows, - short **rightedgeflows, short **loweredgeflows, - short **leftedgeflows, short **upperedgeflows, - long ***scndrycosts, - nodeT ***updatednontilenodesptr, - long *nupdatednontilenodesptr, - long *updatednontilenodesizeptr, - short **inontilenodeoutarcptr, - long *totarclenptr); -void SetUpperEdge(long ncol, long tilerow, long tilecol, void **voidcosts, - void *voidcostsabove, float **unwphase, - float *unwphaseabove, void **voidupperedgecosts, - short **upperedgeflows, paramT *params, short **bulkoffsets); -void SetLowerEdge(long nrow, long ncol, long tilerow, long tilecol, - void **voidcosts, void *voidcostsbelow, - float **unwphase, float *unwphasebelow, - void **voidloweredgecosts, short **loweredgeflows, - paramT *params, short **bulkoffsets); -void SetLeftEdge(long nrow, long prevncol, long tilerow, long tilecol, - void **voidcosts, void **voidlastcosts, float **unwphase, - float **lastunwphase, void **voidleftedgecosts, - short **leftedgeflows, paramT *params, short **bulkoffsets); -void SetRightEdge(long nrow, long ncol, long tilerow, long tilecol, - void **voidcosts, void **voidnextcosts, - float **unwphase, float **nextunwphase, - void **voidrightedgecosts, short **rightedgeflows, - paramT *params, short **bulkoffsets); -void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, - nodesuppT **nodesupp, scndryarcT **scndryarcs, - long ***scndrycosts, long *nnewnodesptr, - long *nnewarcsptr, long tilerow, long tilecol, - long flowmax, long nrow, long ncol, - long prevnrow, long prevncol, paramT *params, - void **tilecosts, void **rightedgecosts, - void **loweredgecosts, void **leftedgecosts, - void **upperedgecosts, short **tileflows, - short **rightedgeflows, short **loweredgeflows, - short **leftedgeflows, short **upperedgeflows, - nodeT ***updatednontilenodesptr, - long *nupdatednontilenodesptr, - long *updatednontilenodesizeptr, - short **inontilenodeoutarcptr, long *totarclenptr); -nodeT *FindScndryNode(nodeT **scndrynodes, nodesuppT **nodesupp, - long tilenum, long primaryrow, long primarycol); -void IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes, - nodesuppT **nodesupp, scndryarcT **scndryarcs, - short *nscndryarcs, short **scndryflows, - short **bulkoffsets, outfileT *outfiles, - paramT *params); -void ParseSecondaryFlows(long tilenum, short *nscndryarcs, short **tileflows, - short **regions, short **scndryflows, - nodesuppT **nodesupp, scndryarcT **scndryarcs, - long nrow, long ncol, long ntilerow, long ntilecol, - paramT *params); +int SetupTile(long nlines, long linelen, paramT *params, + tileparamT *tileparams, outfileT *outfiles, + outfileT *tileoutfiles, long tilerow, long tilecol); +signed char **SetUpDoTileMask(infileT *infiles, long ntilerow, long ntilecol); +int GrowRegions(void **costs, short **flows, long nrow, long ncol, + incrcostT **incrcosts, outfileT *outfiles, + tileparamT *tileparams, paramT *params); +int GrowConnCompsMask(void **costs, short **flows, long nrow, long ncol, + incrcostT **incrcosts, outfileT *outfiles, + paramT *params); +int AssembleTiles(outfileT *outfiles, paramT *params, + long nlines, long linelen); /* functions in snaphu_solver.c */ +int SetGridNetworkFunctionPointers(void); +int SetNonGridNetworkFunctionPointers(void); long TreeSolve(nodeT **nodes, nodesuppT **nodesupp, nodeT *ground, - nodeT *source, candidateT **candidatelistptr, - candidateT **candidatebagptr, long *candidatelistsizeptr, - long *candidatebagsizeptr, bucketT *bkts, short **flows, - void **costs, incrcostT **incrcosts, nodeT ***apexes, - signed char **iscandidate, long ngroundarcs, long nflow, - float **mag, float **wrappedphase, char *outfile, - long nnoderow, short *nnodesperrow, long narcrow, - short *narcsperrow, long nrow, long ncol, - outfileT *outfiles, paramT *params); -void AddNewNode(nodeT *from, nodeT *to, long arcdir, bucketT *bkts, - long nflow, incrcostT **incrcosts, long arcrow, long arccol, - paramT *params); -void CheckArcReducedCost(nodeT *from, nodeT *to, nodeT *apex, - long arcrow, long arccol, long arcdir, - long nflow, nodeT **nodes, nodeT *ground, - candidateT **candidatebagptr, - long *candidatebagnextptr, - long *candidatebagsizeptr, incrcostT **incrcosts, - signed char **iscandidate, paramT *params); -long InitTree(nodeT *source, nodeT **nodes, nodesuppT **nodesupp, - nodeT *ground, long ngroundarcs, bucketT *bkts, long nflow, - incrcostT **incrcosts, nodeT ***apexes, - signed char **iscandidate, long nnoderow, short *nnodesperrow, - long narcrow, short *narcsperrow, long nrow, long ncol, - paramT *params); -nodeT *FindApex(nodeT *from, nodeT *to); -int CandidateCompare(const void *c1, const void *c2); -nodeT *NeighborNodeGrid(nodeT *node1, long arcnum, long *upperarcnumptr, - nodeT **nodes, nodeT *ground, long *arcrowptr, - long *arccolptr, long *arcdirptr, long nrow, - long ncol, nodesuppT **nodesupp); -nodeT *NeighborNodeNonGrid(nodeT *node1, long arcnum, long *upperarcnumptr, - nodeT **nodes, nodeT *ground, long *arcrowptr, - long *arccolptr, long *arcdirptr, long nrow, - long ncol, nodesuppT **nodesupp); -void GetArcGrid(nodeT *from, nodeT *to, long *arcrow, long *arccol, - long *arcdir, long nrow, long ncol, nodesuppT **nodesupp); -void GetArcNonGrid(nodeT *from, nodeT *to, long *arcrow, long *arccol, - long *arcdir, long nrow, long ncol, nodesuppT **nodesupp); -void NonDegenUpdateChildren(nodeT *startnode, nodeT *lastnode, - nodeT *nextonpath, long dgroup, - long ngroundarcs, long nflow, nodeT **nodes, - nodesuppT **nodesupp, nodeT *ground, - nodeT ***apexes, incrcostT **incrcosts, - long nrow, long ncol, paramT *params); -void InitNetwork(short **flows, long *ngroundarcsptr, long *ncycleptr, - long *nflowdoneptr, long *mostflowptr, long *nflowptr, - long *candidatebagsizeptr, candidateT **candidatebagptr, - long *candidatelistsizeptr, candidateT **candidatelistptr, - signed char ***iscandidateptr, nodeT ****apexesptr, - bucketT **bktsptr, long *iincrcostfileptr, - incrcostT ***incrcostsptr, nodeT ***nodesptr, nodeT *ground, - long *nnoderowptr, short **nnodesperrowptr, long *narcrowptr, - short **narcsperrowptr, long nrow, long ncol, - signed char *notfirstloopptr, totalcostT *totalcostptr, - paramT *params); -void InitNodeNums(long nrow, long ncol, nodeT **nodes, nodeT *ground); -void InitBuckets(bucketT *bkts, nodeT *source, long nbuckets); -void InitNodes(long nrow, long ncol, nodeT **nodes, nodeT *ground); + nodeT *source, candidateT **candidatelistptr, + candidateT **candidatebagptr, long *candidatelistsizeptr, + long *candidatebagsizeptr, bucketT *bkts, short **flows, + void **costs, incrcostT **incrcosts, nodeT ***apexes, + signed char **iscandidate, long ngroundarcs, long nflow, + float **mag, float **wrappedphase, char *outfile, + long nnoderow, int *nnodesperrow, long narcrow, + int *narcsperrow, long nrow, long ncol, + outfileT *outfiles, long nconnected, paramT *params); +int InitNetwork(short **flows, long *ngroundarcsptr, long *ncycleptr, + long *nflowdoneptr, long *mostflowptr, long *nflowptr, + long *candidatebagsizeptr, candidateT **candidatebagptr, + long *candidatelistsizeptr, candidateT **candidatelistptr, + signed char ***iscandidateptr, nodeT ****apexesptr, + bucketT **bktsptr, long *iincrcostfileptr, + incrcostT ***incrcostsptr, nodeT ***nodesptr, nodeT *ground, + long *nnoderowptr, int **nnodesperrowptr, long *narcrowptr, + int **narcsperrowptr, long nrow, long ncol, + signed char *notfirstloopptr, totalcostT *totalcostptr, + paramT *params); +long SetupTreeSolveNetwork(nodeT **nodes, nodeT *ground, nodeT ***apexes, + signed char **iscandidate, long nnoderow, + int *nnodesperrow, long narcrow, int *narcsperrow, + long nrow, long ncol); +signed char CheckMagMasking(float **mag, long nrow, long ncol); +int MaskNodes(long nrow, long ncol, nodeT **nodes, nodeT *ground, + float **mag); +long MaxNonMaskFlow(short **flows, float **mag, long nrow, long ncol); +int InitNodeNums(long nrow, long ncol, nodeT **nodes, nodeT *ground); +int InitNodes(long nrow, long ncol, nodeT **nodes, nodeT *ground); void BucketInsert(nodeT *node, long ind, bucketT *bkts); void BucketRemove(nodeT *node, long ind, bucketT *bkts); nodeT *ClosestNode(bucketT *bkts); -nodeT *ClosestNodeCircular(bucketT *bkts); -nodeT *MinOutCostNode(bucketT *bkts); -nodeT *SelectSource(nodeT **nodes, nodeT *ground, long nflow, - short **flows, long ngroundarcs, - long nrow, long ncol, paramT *params); -short GetCost(incrcostT **incrcosts, long arcrow, long arccol, - long arcdir); +long SelectSources(nodeT **nodes, float **mag, nodeT *ground, long nflow, + short **flows, long ngroundarcs, + long nrow, long ncol, paramT *params, + nodeT ***sourcelistptr, long **nconnectedarrptr); long ReCalcCost(void **costs, incrcostT **incrcosts, long flow, - long arcrow, long arccol, long nflow, long nrow, - paramT *params); -void SetupIncrFlowCosts(void **costs, incrcostT **incrcosts, short **flows, - long nflow, long nrow, long narcrow, - short *narcsperrow, paramT *params); + long arcrow, long arccol, long nflow, long nrow, + paramT *params); +int SetupIncrFlowCosts(void **costs, incrcostT **incrcosts, short **flows, + long nflow, long nrow, long narcrow, + int *narcsperrow, paramT *params); totalcostT EvaluateTotalCost(void **costs, short **flows, long nrow, long ncol, - short *narcsperrow,paramT *params); -void MSTInitFlows(float **wrappedphase, short ***flowsptr, - short **mstcosts, long nrow, long ncol, - nodeT ***nodes, nodeT *ground, long maxflow); -void SolveMST(nodeT **nodes, nodeT *source, nodeT *ground, - bucketT *bkts, short **mstcosts, signed char **residue, - signed char **arcstatus, long nrow, long ncol); -long DischargeTree(nodeT *source, short **mstcosts, short **flows, - signed char **residue, signed char **arcstatus, - nodeT **nodes, nodeT *ground, long nrow, long ncol); -signed char ClipFlow(signed char **residue, short **flows, - short **mstcosts, long nrow, long ncol, - long maxflow); -void MCFInitFlows(float **wrappedphase, short ***flowsptr, short **mstcosts, - long nrow, long ncol, long cs2scalefactor); + int *narcsperrow,paramT *params); +int MSTInitFlows(float **wrappedphase, short ***flowsptr, + short **mstcosts, long nrow, long ncol, + nodeT ***nodes, nodeT *ground, long maxflow); +int MCFInitFlows(float **wrappedphase, short ***flowsptr, short **mstcosts, + long nrow, long ncol, long cs2scalefactor); /* functions in snaphu_cost.c */ - -void BuildCostArrays(void ***costsptr, short ***mstcostsptr, - float **mag, float **wrappedphase, - float **unwrappedest, long linelen, long nlines, - long nrow, long ncol, paramT *params, - tileparamT *tileparams, infileT *infiles, - outfileT *outfiles); -void **BuildStatCostsTopo(float **wrappedphase, float **mag, - float **unwrappedest, float **pwr, - float **corr, short **rowweight, short **colweight, - long nrow, long ncol, tileparamT *tileparams, - outfileT *outfiles, paramT *params); -void **BuildStatCostsDefo(float **wrappedphase, float **mag, - float **unwrappedest, float **corr, - short **rowweight, short **colweight, - long nrow, long ncol, tileparamT *tileparams, - outfileT *outfiles, paramT *params); -void **BuildStatCostsSmooth(float **wrappedphase, float **mag, - float **unwrappedest, float **corr, - short **rowweight, short **colweight, - long nrow, long ncol, tileparamT *tileparams, - outfileT *outfiles, paramT *params); -void GetIntensityAndCorrelation(float **mag, float **wrappedphase, - float ***pwrptr, float ***corrptr, - infileT *infiles, long linelen, long nlines, - long nrow, long ncol, outfileT *outfiles, - paramT *params, tileparamT *tileparams); -void RemoveMean(float **ei, long nrow, long ncol, - long krowei, long kcolei); -float *BuildDZRCritLookupTable(double *nominc0ptr, double *dnomincptr, - long *tablesizeptr, tileparamT *tileparams, - paramT *params); -double SolveDZRCrit(double sinnomincangle, double cosnomincangle, - paramT *params, double threshold); -void SolveEIModelParams(double *slope1ptr, double *slope2ptr, - double *const1ptr, double *const2ptr, - double dzrcrit, double dzr0, double sinnomincangle, - double cosnomincangle, paramT *params); -double EIofDZR(double dzr, double sinnomincangle, double cosnomincangle, - paramT *params); -float **BuildDZRhoMaxLookupTable(double nominc0, double dnominc, - long nominctablesize, double rhomin, - double drho, long nrho, paramT *params); -double CalcDZRhoMax(double rho, double nominc, paramT *params, - double threshold); +int BuildCostArrays(void ***costsptr, short ***mstcostsptr, + float **mag, float **wrappedphase, + float **unwrappedest, long linelen, long nlines, + long nrow, long ncol, paramT *params, + tileparamT *tileparams, infileT *infiles, + outfileT *outfiles); void CalcCostTopo(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr); + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); void CalcCostDefo(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr); + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); void CalcCostSmooth(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr); + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); void CalcCostL0(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr); + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); void CalcCostL1(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr); + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); void CalcCostL2(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr); + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); void CalcCostLP(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr); + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); +void CalcCostL0BiDir(void **costs, long flow, long arcrow, long arccol, + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); +void CalcCostL1BiDir(void **costs, long flow, long arcrow, long arccol, + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); +void CalcCostL2BiDir(void **costs, long flow, long arcrow, long arccol, + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); +void CalcCostLPBiDir(void **costs, long flow, long arcrow, long arccol, + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); void CalcCostNonGrid(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr); + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr); long EvalCostTopo(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params); + long nrow, paramT *params); long EvalCostDefo(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params); + long nrow, paramT *params); long EvalCostSmooth(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params); + long nrow, paramT *params); long EvalCostL0(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params); + long nrow, paramT *params); long EvalCostL1(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params); + long nrow, paramT *params); long EvalCostL2(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params); + long nrow, paramT *params); long EvalCostLP(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params); + long nrow, paramT *params); +long EvalCostL0BiDir(void **costs, short **flows, long arcrow, long arccol, + long nrow, paramT *params); +long EvalCostL1BiDir(void **costs, short **flows, long arcrow, long arccol, + long nrow, paramT *params); +long EvalCostL2BiDir(void **costs, short **flows, long arcrow, long arccol, + long nrow, paramT *params); +long EvalCostLPBiDir(void **costs, short **flows, long arcrow, long arccol, + long nrow, paramT *params); long EvalCostNonGrid(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params); -void CalcInitMaxFlow(paramT *params, void **costs, long nrow, long ncol); + long nrow, paramT *params); /* functions in snaphu_util.c */ -int IsTrue(char *str); -int IsFalse(char *str); signed char SetBooleanSignedChar(signed char *boolptr, char *str); -double ModDiff(double f1, double f2); -void WrapPhase(float **wrappedphase, long nrow, long ncol); -void CalcWrappedRangeDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, - long kperpdpsi, long kpardpsi, - long nrow, long ncol); -void CalcWrappedAzDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, - long kperpdpsi, long kpardpsi, long nrow, long ncol); -void CycleResidue(float **phase, signed char **residue, - int nrow, int ncol); -void CalcFlow(float **phase, short ***flowsptr, long nrow, long ncol); -void IntegratePhase(float **psi, float **phi, short **flows, - long nrow, long ncol); +int WrapPhase(float **wrappedphase, long nrow, long ncol); +int CalcWrappedRangeDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, + long kperpdpsi, long kpardpsi, + long nrow, long ncol); +int CalcWrappedAzDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, + long kperpdpsi, long kpardpsi, long nrow, long ncol); +int CycleResidue(float **phase, signed char **residue, + int nrow, int ncol); +int NodeResidue(float **wphase, long row, long col); +int CalcFlow(float **phase, short ***flowsptr, long nrow, long ncol); +int IntegratePhase(float **psi, float **phi, short **flows, + long nrow, long ncol); float **ExtractFlow(float **unwrappedphase, short ***flowsptr, - long nrow, long ncol); -void FlipPhaseArraySign(float **arr, paramT *params, long nrow, long ncol); -void FlipFlowArraySign(short **arr, paramT *params, long nrow, long ncol); + long nrow, long ncol); +int FlipPhaseArraySign(float **arr, paramT *params, long nrow, long ncol); +int FlipFlowArraySign(short **arr, paramT *params, long nrow, long ncol); void **Get2DMem(int nrow, int ncol, int psize, size_t size); void **Get2DRowColMem(long nrow, long ncol, int psize, size_t size); void **Get2DRowColZeroMem(long nrow, long ncol, int psize, size_t size); void *MAlloc(size_t size); void *CAlloc(size_t nitems, size_t size); void *ReAlloc(void *ptr, size_t size); -void Free2DArray(void **array, unsigned int nrow); -void Set2DShortArray(short **arr, long nrow, long ncol, long value); +int Free2DArray(void **array, unsigned int nrow); +int Set2DShortArray(short **arr, long nrow, long ncol, long value); signed char ValidDataArray(float **arr, long nrow, long ncol); +signed char NonNegDataArray(float **arr, long nrow, long ncol); signed char IsFinite(double d); long LRound(double a); +long LMin(long a, long b); +long LClip(long a, long minval, long maxval); long Short2DRowColAbsMax(short **arr, long nrow, long ncol); float LinInterp1D(float *arr, double index, long nelem); float LinInterp2D(float **arr, double rowind, double colind , long nrow, long ncol); -void Despeckle(float **mag, float ***ei, long nrow, long ncol); +int Despeckle(float **mag, float ***ei, long nrow, long ncol); float **MirrorPad(float **array1, long nrow, long ncol, long krow, long kcol); -void BoxCarAvg(float **avgarr, float **padarr, long nrow, long ncol, - long krow, long kcol); +int BoxCarAvg(float **avgarr, float **padarr, long nrow, long ncol, + long krow, long kcol); char *StrNCopy(char *dest, const char *src, size_t n); -void FlattenWrappedPhase(float **wrappedphase, float **unwrappedest, - long nrow, long ncol); -void Add2DFloatArrays(float **arr1, float **arr2, long nrow, long ncol); +int FlattenWrappedPhase(float **wrappedphase, float **unwrappedest, + long nrow, long ncol); +int Add2DFloatArrays(float **arr1, float **arr2, long nrow, long ncol); int StringToDouble(char *str, double *d); int StringToLong(char *str, long *l); -void CatchSignals(void (*SigHandler)(int)); +int CatchSignals(void (*SigHandler)(int)); void SetDump(int signum); void KillChildrenExit(int signum); void SignalExit(int signum); -void StartTimers(time_t *tstart, double *cputimestart); -void DisplayElapsedTime(time_t tstart, double cputimestart); +int StartTimers(time_t *tstart, double *cputimestart); +int DisplayElapsedTime(time_t tstart, double cputimestart); int LongCompare(const void *c1, const void *c2); /* functions in snaphu_io.c */ -void SetDefaults(infileT *infiles, outfileT *outfiles, paramT *params); -void ProcessArgs(int argc, char *argv[], infileT *infiles, outfileT *outfiles, - long *ncolptr, paramT *params); -void CheckParams(infileT *infiles, outfileT *outfiles, - long linelen, long nlines, paramT *params); -void ReadConfigFile(char *conffile, infileT *infiles, outfileT *outfiles, - long *ncolptr, paramT *params); -void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, - outfileT *outfiles, long linelen, paramT *params); -void LogStringParam(FILE *fp, char *key, char *value); -void LogBoolParam(FILE *fp, char *key, signed char boolvalue); -void LogFileFormat(FILE *fp, char *key, signed char fileformat); -long GetNLines(infileT *infiles, long linelen); -void WriteOutputFile(float **mag, float **unwrappedphase, char *outfile, - outfileT *outfiles, long nrow, long ncol); +int SetDefaults(infileT *infiles, outfileT *outfiles, paramT *params); +int ProcessArgs(int argc, char *argv[], infileT *infiles, outfileT *outfiles, + long *ncolptr, paramT *params); +int CheckParams(infileT *infiles, outfileT *outfiles, + long linelen, long nlines, paramT *params); +int ReadConfigFile(char *conffile, infileT *infiles, outfileT *outfiles, + long *ncolptr, paramT *params); +int WriteConfigLogFile(int argc, char *argv[], infileT *infiles, + outfileT *outfiles, long linelen, paramT *params); +long GetNLines(infileT *infiles, long linelen, paramT *params); +int WriteOutputFile(float **mag, float **unwrappedphase, char *outfile, + outfileT *outfiles, long nrow, long ncol); FILE *OpenOutputFile(char *outfile, char *realoutfile); -void WriteAltLineFile(float **mag, float **phase, char *outfile, - long nrow, long ncol); -void WriteAltSampFile(float **arr1, float **arr2, char *outfile, - long nrow, long ncol); -void Write2DArray(void **array, char *filename, long nrow, long ncol, - size_t size); -void Write2DRowColArray(void **array, char *filename, long nrow, - long ncol, size_t size); -void ReadInputFile(infileT *infiles, float ***magptr, float ***wrappedphaseptr, - short ***flowsptr, long linelen, long nlines, - paramT *params, tileparamT *tileparams); -void ReadMagnitude(float **mag, infileT *infiles, long linelen, long nlines, - tileparamT *tileparams); -void ReadUnwrappedEstimateFile(float ***unwrappedestptr, infileT *infiles, - long linelen, long nlines, - paramT *params, tileparamT *tileparams); -void ReadWeightsFile(short ***weightsptr,char *weightfile, - long linelen, long nlines, tileparamT *tileparams); -void ReadIntensity(float ***pwrptr, float ***pwr1ptr, float ***pwr2ptr, - infileT *infiles, long linelen, long nlines, - paramT *params, tileparamT *tileparams); -void ReadCorrelation(float ***corrptr, infileT *infiles, - long linelen, long nlines, tileparamT *tileparams); -void ReadAltLineFile(float ***mag, float ***phase, char *alfile, - long linelen, long nlines, tileparamT *tileparams); -void ReadAltLineFilePhase(float ***phase, char *alfile, - long linelen, long nlines, tileparamT *tileparams); -void ReadComplexFile(float ***mag, float ***phase, char *rifile, - long linelen, long nlines, tileparamT *tileparams); -void Read2DArray(void ***arr, char *infile, long linelen, long nlines, - tileparamT *tileparams, size_t elptrsize, size_t elsize); -void ReadAltSampFile(float ***arr1, float ***arr2, char *infile, - long linelen, long nlines, tileparamT *tileparams); -void Read2DRowColFile(void ***arr, char *filename, long linelen, long nlines, - tileparamT *tileparams, size_t size); -void Read2DRowColFileRows(void ***arr, char *filename, long linelen, - long nlines, tileparamT *tileparams, size_t size); -void SetDumpAll(outfileT *outfiles, paramT *params); -void SetStreamPointers(void); -void SetVerboseOut(paramT *params); -void ChildResetStreamPointers(pid_t pid, long tilerow, long tilecol, - paramT *params); -void DumpIncrCostFiles(incrcostT **incrcosts, long iincrcostfile, - long nflow, long nrow, long ncol); -void MakeTileDir(paramT *params, outfileT *outfiles); -void ParseFilename(char *filename, char *path, char *basename); +int Write2DArray(void **array, char *filename, long nrow, long ncol, + size_t size); +int Write2DRowColArray(void **array, char *filename, long nrow, + long ncol, size_t size); +int ReadInputFile(infileT *infiles, float ***magptr, float ***wrappedphaseptr, + short ***flowsptr, long linelen, long nlines, + paramT *params, tileparamT *tileparams); +int ReadMagnitude(float **mag, infileT *infiles, long linelen, long nlines, + tileparamT *tileparams); +int ReadByteMask(float **mag, infileT *infiles, long linelen, long nlines, + tileparamT *tileparams, paramT *params); +int ReadUnwrappedEstimateFile(float ***unwrappedestptr, infileT *infiles, + long linelen, long nlines, + paramT *params, tileparamT *tileparams); +int ReadWeightsFile(short ***weightsptr,char *weightfile, + long linelen, long nlines, tileparamT *tileparams); +int ReadIntensity(float ***pwrptr, float ***pwr1ptr, float ***pwr2ptr, + infileT *infiles, long linelen, long nlines, + paramT *params, tileparamT *tileparams); +int ReadCorrelation(float ***corrptr, infileT *infiles, + long linelen, long nlines, tileparamT *tileparams); +int ReadAltLineFile(float ***mag, float ***phase, char *alfile, + long linelen, long nlines, tileparamT *tileparams); +int ReadAltLineFilePhase(float ***phase, char *alfile, + long linelen, long nlines, tileparamT *tileparams); +int ReadComplexFile(float ***mag, float ***phase, char *rifile, + long linelen, long nlines, tileparamT *tileparams); +int Read2DArray(void ***arr, char *infile, long linelen, long nlines, + tileparamT *tileparams, size_t elptrsize, size_t elsize); +int ReadAltSampFile(float ***arr1, float ***arr2, char *infile, + long linelen, long nlines, tileparamT *tileparams); +int Read2DRowColFile(void ***arr, char *filename, long linelen, long nlines, + tileparamT *tileparams, size_t size); +int Read2DRowColFileRows(void ***arr, char *filename, long linelen, + long nlines, tileparamT *tileparams, size_t size); +int SetDumpAll(outfileT *outfiles, paramT *params); +int SetStreamPointers(void); +int SetVerboseOut(paramT *params); +int ChildResetStreamPointers(pid_t pid, long tilerow, long tilecol, + paramT *params); +int DumpIncrCostFiles(incrcostT **incrcosts, long iincrcostfile, + long nflow, long nrow, long ncol); +int MakeTileDir(paramT *params, outfileT *outfiles); +int ParseFilename(char *filename, char *path, char *basename); +int SetTileInitOutfile(char *outfile, long pid); /* functions in snaphu_cs2.c */ void SolveCS2(signed char **residue, short **mstcosts, long nrow, long ncol, - long cs2scalefactor, short ***flowsptr); + long cs2scalefactor, short ***flowsptr); @@ -1102,12 +1019,9 @@ extern FILE *sp0, *sp1, *sp2, *sp3; extern nodeT NONTREEARC[1]; /* pointers to functions which calculate arc costs */ -extern void (*CalcCost)(); -extern long (*EvalCost)(); - -/* pointers to functions for tailoring network solver to specific topologies */ -extern nodeT *(*NeighborNode)(); -extern void (*GetArc)(); +extern void (*CalcCost)(void **, long, long, long, long, long, + paramT *, long *, long *); +extern long (*EvalCost)(void **, short **, long, long, long, paramT *); /* end of snaphu.h */ diff --git a/contrib/Snaphu/include/snaphu_cs2types.h b/contrib/Snaphu/include/snaphu_cs2types.h index 5ba9c04f..1ebd2fee 100644 --- a/contrib/Snaphu/include/snaphu_cs2types.h +++ b/contrib/Snaphu/include/snaphu_cs2types.h @@ -2,14 +2,14 @@ This code is derived from cs2 v3.7 Written by Andrew V. Goldberg and Boris Cherkassky - Modifications for use in snaphu by Curtis W. Chen + Modifications for use in snaphu by Curtis W. Chen Header for cs2 minimum cost flow solver. This file is included with a #include from snaphu_cs2.c. The cs2 code is used here with permission for strictly noncommerical use. The original cs2 source code can be downloaded from - + http://www.igsystems.com/cs2 The original cs2 copyright is stated as follows: @@ -18,7 +18,7 @@ evaluation purposes is granted provided that proper acknowledgments are given. For a commercial licence, contact igsys@eclipse.net. - + This software comes with NO WARRANTY, expressed or implied. By way of example, but not limitation, we make no representations of warranties of merchantability or fitness for any particular @@ -31,8 +31,7 @@ *************************************************************************/ /* defs.h */ -#ifndef CSTYPES_H -#define CSTYPES_H + typedef long excess_t; @@ -64,8 +63,7 @@ typedef /* node */ typedef /* bucket */ struct bucket_st { - node *p_first; /* 1st node with positive excess + node *p_first; /* 1st node with positive excess or simply 1st node in the buket */ } bucket; -#endif //CSTYPES_H diff --git a/contrib/Snaphu/src/snaphu.c b/contrib/Snaphu/src/snaphu.c index ffa385d6..8ac07873 100644 --- a/contrib/Snaphu/src/snaphu.c +++ b/contrib/Snaphu/src/snaphu.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -31,24 +32,34 @@ /* global (external) variable definitions */ /* flags used for signal handling */ -char dumpresults_global; -char requestedstop_global; +char dumpresults_global = FALSE; +char requestedstop_global = FALSE; /* ouput stream pointers */ /* sp0=error messages, sp1=status output, sp2=verbose, sp3=verbose counter */ -FILE *sp0, *sp1, *sp2, *sp3; +FILE *sp0 = NULL; +FILE *sp1 = NULL; +FILE *sp2 = NULL; +FILE *sp3 = NULL; /* node pointer for marking arc not on tree in apex array */ /* this should be treated as a constant */ nodeT NONTREEARC[1]; /* pointers to functions which calculate arc costs */ -void (*CalcCost)(); -long (*EvalCost)(); +void (*CalcCost)(void **, long, long, long, long, long, + paramT *, long *, long *) = NULL; +long (*EvalCost)(void **, short **, long, long, long, paramT *) = NULL; + + +/* static (local) function prototypes */ +static +int Unwrap(infileT *infiles, outfileT *outfiles, paramT *params, + long linelen, long nlines); +static +int UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, + tileparamT *tileparams, long nlines, long linelen); -/* pointers to functions for tailoring network solver to specific topologies */ -nodeT *(*NeighborNode)(); -void (*GetArc)(); /***************************/ @@ -80,8 +91,8 @@ int snaphu(infileT *infiles,outfileT *outfiles, paramT *params,long linelen) { /*SetDefaults(infiles,outfiles,params); ReadConfigFile(DEF_SYSCONFFILE,infiles,outfiles,&linelen,params);*/ - /* parse the command line inputs - ProcessArgs(argc,argv,infiles,outfiles,&linelen,params);*/ + /* parse the command line inputs */ + /*ProcessArgs(argc,argv,infiles,outfiles,&linelen,params);*/ /* set verbose output if specified */ SetVerboseOut(params); @@ -90,23 +101,24 @@ int snaphu(infileT *infiles,outfileT *outfiles, paramT *params,long linelen) { SetDumpAll(outfiles,params); /* get number of lines in file */ - nlines=GetNLines(infiles,linelen); + nlines=GetNLines(infiles,linelen,params); /* check validity of parameters */ CheckParams(infiles,outfiles,linelen,nlines,params); - /* log the runtime parameters - WriteConfigLogFile(argc,argv,infiles,outfiles,linelen,params);*/ + /* log the runtime parameters */ + /*WriteConfigLogFile(argc,argv,infiles,outfiles,linelen,params);*/ /* unwrap, forming tiles and reassembling if necessary */ Unwrap(infiles,outfiles,params,linelen,nlines); - + /* finish up fprintf(sp1,"Program %s done\n",PROGRAMNAME); DisplayElapsedTime(tstart,cputimestart); exit(NORMAL_EXIT);*/ return EXIT_SUCCESS; + } /* end of main() */ @@ -115,177 +127,282 @@ int snaphu(infileT *infiles,outfileT *outfiles, paramT *params,long linelen) { * Sets parameters for each tile and calls UnwrapTile() to do the * unwrapping. */ -void Unwrap(infileT *infiles, outfileT *outfiles, paramT *params, - long linelen, long nlines){ +static +int Unwrap(infileT *infiles, outfileT *outfiles, paramT *params, + long linelen, long nlines){ + long optiter, noptiter; long nexttilerow, nexttilecol, ntilerow, ntilecol, nthreads, nchildren; long sleepinterval; tileparamT tileparams[1]; + infileT iterinfiles[1]; + outfileT iteroutfiles[1]; outfileT tileoutfiles[1]; + paramT iterparams[1]; + char tileinitfile[MAXSTRLEN]; pid_t pid; int childstatus; double tilecputimestart; time_t tiletstart; + signed char **dotilemask; - /* set up */ - ntilerow=params->ntilerow; - ntilecol=params->ntilecol; - nthreads=params->nthreads; - dumpresults_global=FALSE; - requestedstop_global=FALSE; - - - /* do the unwrapping */ - if(ntilerow==1 && ntilecol==1){ - - /* only single tile */ - - /* do the unwrapping */ - tileparams->firstrow=params->piecefirstrow; - tileparams->firstcol=params->piecefirstcol; - tileparams->nrow=params->piecenrow; - tileparams->ncol=params->piecencol; - UnwrapTile(infiles,outfiles,params,tileparams,nlines,linelen); + /* initialize structure stack memory to zero for extra robustness */ + memset(tileparams,0,sizeof(tileparamT)); + memset(iterinfiles,0,sizeof(infileT)); + memset(iteroutfiles,0,sizeof(outfileT)); + memset(tileoutfiles,0,sizeof(outfileT)); + memset(iterparams,0,sizeof(paramT)); + memset(tileinitfile,0,MAXSTRLEN); + /* see if we need to do single-tile reoptimization and set up if so */ + if(params->onetilereopt){ + noptiter=2; }else{ + noptiter=1; + } + + /* iterate if necessary for single-tile reoptimization */ + for(optiter=0;optiter1){ + + /* set up to write tile-mode unwrapped result to temporary file */ + SetTileInitOutfile(iteroutfiles->outfile,iterparams->parentpid); + StrNCopy(tileinitfile,iteroutfiles->outfile,MAXSTRLEN); + iteroutfiles->outfileformat=TILEINITFILEFORMAT; + fprintf(sp1,"Starting first-round tile-mode unwrapping\n"); + + } + + }else if(optiter==1){ + + /* second iteration */ + /* set up to read unwrapped tile-mode result as single tile */ + StrNCopy(iterinfiles->infile,tileinitfile,MAXSTRLEN); + iterinfiles->unwrappedinfileformat=TILEINITFILEFORMAT; + iterparams->unwrapped=TRUE; + iterparams->ntilerow=1; + iterparams->ntilecol=1; + iterparams->rowovrlp=0; + iterparams->colovrlp=0; + fprintf(sp1,"Starting second-round single-tile unwrapping\n"); + + }else{ + fprintf(sp0,"ERROR: illegal optiter value in Unwrap()\n"); + exit(ABNORMAL_EXIT); + } + + /* set up for unwrapping */ + ntilerow=iterparams->ntilerow; + ntilecol=iterparams->ntilecol; + nthreads=iterparams->nthreads; + dumpresults_global=FALSE; + requestedstop_global=FALSE; - /* don't unwrap if in assemble-only mode */ - if(!params->assembleonly){ - - /* make a temporary directory into which tile files will be written */ - MakeTileDir(params,outfiles); - - /* different code for parallel or nonparallel operation */ - if(nthreads>1){ - - /* parallel code */ - - /* initialize */ - nexttilerow=0; - nexttilecol=0; - nchildren=0; - sleepinterval=LRound(nlines*linelen/ntilerow/ntilecol*SECONDSPERPIXEL); - - /* trap signals so children get killed if parent dies */ - CatchSignals(KillChildrenExit); - - /* loop until we're done unwrapping */ - while(TRUE){ - - /* unwrap next tile if there are free processors and tiles left */ - if(nchildrenfirstrow=iterparams->piecefirstrow; + tileparams->firstcol=iterparams->piecefirstcol; + tileparams->nrow=iterparams->piecenrow; + tileparams->ncol=iterparams->piecencol; + UnwrapTile(iterinfiles,iteroutfiles,iterparams,tileparams,nlines,linelen); - /* make sure child exited cleanly */ - if(!(WIFEXITED(childstatus)) || (WEXITSTATUS(childstatus))!=0){ - fprintf(sp0,"Unexpected or abnormal exit of child process %ld\n" - "Abort\n",(long )pid); - signal(SIGTERM,SIG_IGN); - kill(0,SIGTERM); - exit(ABNORMAL_EXIT); - } + }else{ - /* we're done if there are no more active children */ - if(--nchildren==0){ - break; - } + /* don't unwrap if in assemble-only mode */ + if(!iterparams->assembleonly){ - } /* end if free processor and tiles remaining */ - } /* end while loop */ + /* set up mask for which tiles should be unwrapped */ + dotilemask=SetUpDoTileMask(iterinfiles,ntilerow,ntilecol); - /* return signal handlers to default behavior */ - CatchSignals(SIG_DFL); + /* make a temporary directory into which tile files will be written */ + MakeTileDir(iterparams,iteroutfiles); - }else{ + /* different code for parallel or nonparallel operation */ + if(nthreads>1){ - /* nonparallel code */ + /* parallel code */ - /* loop over all tiles */ - for(nexttilerow=0;nexttilerow1 */ + /* wait to make sure file i/o, threads, and OS are synched */ + sleep(sleepinterval); + + /* fork to create new process */ + fflush(NULL); + pid=fork(); - } /* end if !params->assembleonly */ + }else{ - /* reassemble tiles */ - AssembleTiles(outfiles,params,nlines,linelen); + /* tile did not need unwrapping, so set pid to parent pid */ + pid=iterparams->parentpid; - } /* end if multiple tiles */ + } + + /* see if parent or child (or error) */ + if(pid<0){ + + /* parent kills children and exits if there was a fork error */ + fflush(NULL); + fprintf(sp0,"Error while forking\nAbort\n"); + kill(0,SIGKILL); + exit(ABNORMAL_EXIT); + + }else if(pid==0){ + + /* child executes this code after fork */ + + /* reset signal handlers so that children exit nicely */ + CatchSignals(SignalExit); + + /* start timers for this tile */ + StartTimers(&tiletstart,&tilecputimestart); + + /* set up tile parameters */ + pid=getpid(); + fprintf(sp1, + "Unwrapping tile at row %ld, column %ld (pid %ld)\n", + nexttilerow,nexttilecol,(long )pid); + SetupTile(nlines,linelen,iterparams,tileparams, + iteroutfiles,tileoutfiles, + nexttilerow,nexttilecol); + + /* reset stream pointers for logging */ + ChildResetStreamPointers(pid,nexttilerow,nexttilecol, + iterparams); + + /* unwrap the tile */ + UnwrapTile(iterinfiles,tileoutfiles,iterparams,tileparams, + nlines,linelen); + + /* log elapsed time */ + DisplayElapsedTime(tiletstart,tilecputimestart); + + /* child exits when done unwrapping */ + exit(NORMAL_EXIT); + + } + + /* parent executes this code after fork */ + + /* increment tile counters */ + if(++nexttilecol==ntilecol){ + nexttilecol=0; + nexttilerow++; + } + + /* increment counter of running child processes */ + if(pid!=iterparams->parentpid){ + nchildren++; + } + + }else{ + + /* wait for a child to finish (only parent gets here) */ + pid=wait(&childstatus); + + /* make sure child exited cleanly */ + if(!(WIFEXITED(childstatus)) || (WEXITSTATUS(childstatus))!=0){ + fflush(NULL); + fprintf(sp0,"Unexpected or abnormal exit of child process %ld\n" + "Abort\n",(long )pid); + signal(SIGTERM,SIG_IGN); + kill(0,SIGTERM); + exit(ABNORMAL_EXIT); + } + + /* we're done if there are no more active children */ + /* shouldn't really need this sleep(), but be extra sure child */ + /* outputs are really flushed and written to disk by OS */ + if(--nchildren==0){ + sleep(sleepinterval); + break; + } + + } /* end if free processor and tiles remaining */ + } /* end while loop */ + + /* return signal handlers to default behavior */ + CatchSignals(SIG_DFL); + + }else{ + + /* nonparallel code */ + + /* loop over all tiles */ + for(nexttilerow=0;nexttilerow1 */ + + /* free tile mask memory */ + Free2DArray((void **)dotilemask,ntilerow); + + } /* end if !iterparams->assembleonly */ + + /* reassemble tiles */ + AssembleTiles(iteroutfiles,iterparams,nlines,linelen); + + } /* end if multiple tiles */ + /* remove temporary tile file if desired at end of second iteration */ + if(iterparams->rmtileinit && optiter>0){ + unlink(tileinitfile); + } + + } /* end of optiter loop */ + + /* done */ + return(0); + } /* end of Unwrap() */ @@ -293,24 +410,29 @@ void Unwrap(infileT *infiles, outfileT *outfiles, paramT *params, * ---------------------- * This is the main phase unwrapping function for a single tile. */ -void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, - tileparamT *tileparams, long nlines, long linelen){ +static +int UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, + tileparamT *tileparams, long nlines, long linelen){ /* variable declarations */ long nrow, ncol, nnoderow, narcrow, n, ngroundarcs, iincrcostfile; long nflow, ncycle, mostflow, nflowdone; long candidatelistsize, candidatebagsize; - short *nnodesperrow, *narcsperrow; + long isource, nsource; + long nnondecreasedcostiter; + long *nconnectedarr; + int *nnodesperrow, *narcsperrow; short **flows, **mstcosts; float **wrappedphase, **unwrappedphase, **mag, **unwrappedest; incrcostT **incrcosts; void **costs; - totalcostT totalcost, oldtotalcost; + totalcostT totalcost, oldtotalcost, mintotalcost; + nodeT **sourcelist; nodeT *source, ***apexes; nodeT **nodes, ground[1]; candidateT *candidatebag, *candidatelist; signed char **iscandidate; - signed char notfirstloop; + signed char notfirstloop, allmasked; bucketT *bkts; @@ -320,16 +442,22 @@ void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, /* read input file (memory allocated by read function) */ ReadInputFile(infiles,&mag,&wrappedphase,&flows,linelen,nlines, - params,tileparams); + params,tileparams); /* read interferogram magnitude if specified separately */ ReadMagnitude(mag,infiles,linelen,nlines,tileparams); + /* read mask file and apply to magnitude */ + ReadByteMask(mag,infiles,linelen,nlines,tileparams,params); + + /* make sure we have at least one pixel that is not masked */ + allmasked=CheckMagMasking(mag,nrow,ncol); + /* read the coarse unwrapped estimate, if provided */ unwrappedest=NULL; if(strlen(infiles->estfile)){ ReadUnwrappedEstimateFile(&unwrappedest,infiles,linelen,nlines, - params,tileparams); + params,tileparams); /* subtract the estimate from the wrapped phase (and re-wrap) */ FlattenWrappedPhase(wrappedphase,unwrappedest,nrow,ncol); @@ -338,7 +466,7 @@ void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, /* build the cost arrays */ BuildCostArrays(&costs,&mstcosts,mag,wrappedphase,unwrappedest, - linelen,nlines,nrow,ncol,params,tileparams,infiles,outfiles); + linelen,nlines,nrow,ncol,params,tileparams,infiles,outfiles); /* if in quantify-only mode, evaluate cost of unwrapped input then return */ if(params->eval){ @@ -350,12 +478,11 @@ void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, Free2DArray((void **)mag,nrow); Free2DArray((void **)wrappedphase,nrow); Free2DArray((void **)flows,2*nrow-1); - return; + return(1); } /* set network function pointers for grid network */ - NeighborNode=NeighborNodeGrid; - GetArc=GetArcGrid; + SetGridNetworkFunctionPointers(); /* initialize the flows (find simple unwrapping to get a feasible flow) */ unwrappedphase=NULL; @@ -367,15 +494,16 @@ void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, /* use minimum spanning tree (MST) algorithm */ MSTInitFlows(wrappedphase,&flows,mstcosts,nrow,ncol, - &nodes,ground,params->initmaxflow); + &nodes,ground,params->initmaxflow); }else if(params->initmethod==MCFINIT){ /* use minimum cost flow (MCF) algorithm */ MCFInitFlows(wrappedphase,&flows,mstcosts,nrow,ncol, - params->cs2scalefactor); + params->cs2scalefactor); }else{ + fflush(NULL); fprintf(sp0,"Illegal initialization method\nAbort\n"); exit(ABNORMAL_EXIT); } @@ -384,41 +512,44 @@ void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, if(params->initonly || strlen(outfiles->initfile)){ fprintf(sp1,"Integrating phase\n"); unwrappedphase=(float **)Get2DMem(nrow,ncol, - sizeof(float *),sizeof(float)); + sizeof(float *),sizeof(float)); IntegratePhase(wrappedphase,unwrappedphase,flows,nrow,ncol); if(unwrappedest!=NULL){ - Add2DFloatArrays(unwrappedphase,unwrappedest,nrow,ncol); + Add2DFloatArrays(unwrappedphase,unwrappedest,nrow,ncol); } FlipPhaseArraySign(unwrappedphase,params,nrow,ncol); /* return if called in init only; otherwise, free memory and continue */ if(params->initonly){ - fprintf(sp1,"Writing output to file %s\n",outfiles->outfile); - WriteOutputFile(mag,unwrappedphase,outfiles->outfile,outfiles, - nrow,ncol); - Free2DArray((void **)mag,nrow); - Free2DArray((void **)wrappedphase,nrow); - Free2DArray((void **)unwrappedphase,nrow); - if(nodes!=NULL){ - Free2DArray((void **)nodes,nrow-1); - } - Free2DArray((void **)flows,2*nrow-1); - return; + fprintf(sp1,"Writing output to file %s\n",outfiles->outfile); + WriteOutputFile(mag,unwrappedphase,outfiles->outfile,outfiles, + nrow,ncol); + Free2DArray((void **)mag,nrow); + Free2DArray((void **)wrappedphase,nrow); + Free2DArray((void **)unwrappedphase,nrow); + if(nodes!=NULL){ + Free2DArray((void **)nodes,nrow-1); + } + Free2DArray((void **)flows,2*nrow-1); + return(1); }else{ - fprintf(sp2,"Writing initialization to file %s\n",outfiles->initfile); - WriteOutputFile(mag,unwrappedphase,outfiles->initfile,outfiles, - nrow,ncol); - Free2DArray((void **)unwrappedphase,nrow); + fprintf(sp2,"Writing initialization to file %s\n",outfiles->initfile); + WriteOutputFile(mag,unwrappedphase,outfiles->initfile,outfiles, + nrow,ncol); + Free2DArray((void **)unwrappedphase,nrow); } } } /* initialize network variables */ InitNetwork(flows,&ngroundarcs,&ncycle,&nflowdone,&mostflow,&nflow, - &candidatebagsize,&candidatebag,&candidatelistsize, - &candidatelist,&iscandidate,&apexes,&bkts,&iincrcostfile, - &incrcosts,&nodes,ground,&nnoderow,&nnodesperrow,&narcrow, - &narcsperrow,nrow,ncol,¬firstloop,&totalcost,params); + &candidatebagsize,&candidatebag,&candidatelistsize, + &candidatelist,&iscandidate,&apexes,&bkts,&iincrcostfile, + &incrcosts,&nodes,ground,&nnoderow,&nnodesperrow,&narcrow, + &narcsperrow,nrow,ncol,¬firstloop,&totalcost,params); + oldtotalcost=totalcost; + mintotalcost=totalcost; + nnondecreasedcostiter=0; /* regrow regions with -G parameter */ if(params->regrowconncomps){ @@ -442,9 +573,11 @@ void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, Free2DArray((void **)flows,2*nrow-1); free(nnodesperrow); free(narcsperrow); - return; + return(1); } + /* mask zero-magnitude nodes so they are not considered in optimization */ + MaskNodes(nrow,ncol,nodes,ground,mag); /* if we have a single tile, trap signals for dumping results */ if(params->ntilerow==1 && params->ntilecol==1){ @@ -453,77 +586,123 @@ void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, } /* main loop: loop over flow increments and sources */ - fprintf(sp1,"Running nonlinear network flow optimizer\n"); - fprintf(sp1,"Maximum flow on network: %ld\n",mostflow); - fprintf(sp2,"Number of nodes in network: %ld\n",(nrow-1)*(ncol-1)+1); - while(TRUE){ + if(!allmasked){ + fprintf(sp1,"Running nonlinear network flow optimizer\n"); + fprintf(sp1,"Maximum flow on network: %ld\n",mostflow); + fprintf(sp2,"Number of nodes in network: %ld\n",(nrow-1)*(ncol-1)+1); + while(TRUE){ - fprintf(sp1,"Flow increment: %ld (Total improvements: %ld)\n", - nflow,ncycle); - - /* set up the incremental (residual) cost arrays */ - SetupIncrFlowCosts(costs,incrcosts,flows,nflow,nrow,narcrow,narcsperrow, - params); - if(params->dumpall && params->ntilerow==1 && params->ntilecol==1){ - DumpIncrCostFiles(incrcosts,++iincrcostfile,nflow,nrow,ncol); - } + fprintf(sp1,"Flow increment: %ld (Total improvements: %ld)\n", + nflow,ncycle); + + /* set up the incremental (residual) cost arrays */ + SetupIncrFlowCosts(costs,incrcosts,flows,nflow,nrow,narcrow,narcsperrow, + params); + if(params->dumpall && params->ntilerow==1 && params->ntilecol==1){ + DumpIncrCostFiles(incrcosts,++iincrcostfile,nflow,nrow,ncol); + } - /* set the tree root (equivalent to source of shortest path problem) */ - source=SelectSource(nodes,ground,nflow,flows,ngroundarcs, - nrow,ncol,params); - - /* run the solver, and increment nflowdone if no cycles are found */ - n=TreeSolve(nodes,NULL,ground,source,&candidatelist,&candidatebag, - &candidatelistsize,&candidatebagsize, - bkts,flows,costs,incrcosts,apexes,iscandidate, - ngroundarcs,nflow,mag,wrappedphase,outfiles->outfile, - nnoderow,nnodesperrow,narcrow,narcsperrow,nrow,ncol, - outfiles,params); - - /* evaluate and save the total cost (skip if first loop through nflow) */ - if(notfirstloop){ - oldtotalcost=totalcost; - totalcost=EvaluateTotalCost(costs,flows,nrow,ncol,NULL,params); - if(totalcost>oldtotalcost || (n>0 && totalcost==oldtotalcost)){ - fprintf(sp0,"Unexpected increase in total cost. Breaking loop\n"); - break; + /* set the tree root (equivalent to source of shortest path problem) */ + sourcelist=NULL; + nconnectedarr=NULL; + nsource=SelectSources(nodes,mag,ground,nflow,flows,ngroundarcs, + nrow,ncol,params,&sourcelist,&nconnectedarr); + + /* set up network variables for tree solver */ + SetupTreeSolveNetwork(nodes,ground,apexes,iscandidate, + nnoderow,nnodesperrow,narcrow,narcsperrow, + nrow,ncol); + + /* loop over sources */ + n=0; + for(isource=0;isourcerow==GROUNDROW){ + fprintf(sp3,"Source %ld: (edge ground)\n",isource); + }else{ + fprintf(sp3,"Source %ld: row, col = %d, %d\n", + isource,source->row,source->col); + } + + /* run the solver, and increment nflowdone if no cycles are found */ + n+=TreeSolve(nodes,NULL,ground,source, + &candidatelist,&candidatebag, + &candidatelistsize,&candidatebagsize, + bkts,flows,costs,incrcosts,apexes,iscandidate, + ngroundarcs,nflow,mag,wrappedphase,outfiles->outfile, + nnoderow,nnodesperrow,narcrow,narcsperrow,nrow,ncol, + outfiles,nconnectedarr[isource],params); } - } - /* consider this flow increment done if not too many neg cycles found */ - ncycle+=n; - if(n<=params->maxnflowcycles){ - nflowdone++; - }else{ - nflowdone=1; - } + /* free temporary memory */ + free(sourcelist); + free(nconnectedarr); + + /* evaluate and save the total cost (skip if first loop through nflow) */ + fprintf(sp2,"Current solution cost: %.16g\n", + (double )EvaluateTotalCost(costs,flows,nrow,ncol,NULL,params)); + fflush(NULL); + if(notfirstloop){ + oldtotalcost=totalcost; + totalcost=EvaluateTotalCost(costs,flows,nrow,ncol,NULL,params); + if(totalcostoldtotalcost || (n>0 && totalcost==oldtotalcost)){ + fflush(NULL); + fprintf(sp1,"Caution: Unexpected increase in total cost\n"); + } + if(totalcost > mintotalcost){ + nnondecreasedcostiter++; + }else{ + nnondecreasedcostiter=0; + } + } - /* find maximum flow on network */ - mostflow=Short2DRowColAbsMax(flows,nrow,ncol); + /* consider this flow increment done if not too many neg cycles found */ + ncycle+=n; + if(n<=params->maxnflowcycles){ + nflowdone++; + }else{ + nflowdone=1; + } - /* break if we're done with all flow increments or problem is convex */ - if(nflowdone>=params->maxflow || nflowdone>=mostflow || params->p>=1.0){ - break; - } + /* find maximum flow on network, excluding arcs affected by masking */ + mostflow=MaxNonMaskFlow(flows,mag,nrow,ncol); + if(nnondecreasedcostiter>=2*mostflow){ + fflush(NULL); + fprintf(sp0,"WARNING: No overall cost reduction for too many iterations." + " Breaking loop\n"); + break; + } - /* update flow increment */ - nflow++; - if(nflow>params->maxflow || nflow>mostflow){ - nflow=1; - notfirstloop=TRUE; - } - fprintf(sp2,"Maximum flow on network: %ld\n",mostflow); - - /* dump flow arrays if necessary */ - if(strlen(outfiles->flowfile)){ - FlipFlowArraySign(flows,params,nrow,ncol); - Write2DRowColArray((void **)flows,outfiles->flowfile,nrow,ncol, - sizeof(short)); - FlipFlowArraySign(flows,params,nrow,ncol); - } + /* break if we're done with all flow increments or problem is convex */ + if(nflowdone>=params->maxflow || nflowdone>=mostflow || params->p>=1.0){ + break; + } - } /* end loop until no more neg cycles */ + /* update flow increment */ + nflow++; + if(nflow>params->maxflow || nflow>mostflow){ + nflow=1; + notfirstloop=TRUE; + } + fprintf(sp2,"Maximum valid flow on network: %ld\n",mostflow); + + /* dump flow arrays if necessary */ + if(strlen(outfiles->flowfile)){ + FlipFlowArraySign(flows,params,nrow,ncol); + Write2DRowColArray((void **)flows,outfiles->flowfile,nrow,ncol, + sizeof(short)); + FlipFlowArraySign(flows,params,nrow,ncol); + } + } /* end loop until no more neg cycles */ + } /* end if all pixels masked */ /* if we have single tile, return signal handlers to default behavior */ if(params->ntilerow==1 && params->ntilecol==1){ @@ -546,7 +725,7 @@ void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, /* grow regions for tiling */ if(params->ntilerow!=1 || params->ntilecol!=1){ - GrowRegions(costs,flows,nrow,ncol,incrcosts,outfiles,params); + GrowRegions(costs,flows,nrow,ncol,incrcosts,outfiles,tileparams,params); } /* free some more memory */ @@ -574,7 +753,7 @@ void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, /* write the unwrapped output */ fprintf(sp1,"Writing output to file %s\n",outfiles->outfile); WriteOutputFile(mag,unwrappedphase,outfiles->outfile,outfiles, - nrow,ncol); + nrow,ncol); /* free remaining memory and return */ Free2DArray((void **)costs,2*nrow-1); @@ -584,6 +763,6 @@ void UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params, Free2DArray((void **)flows,2*nrow-1); free(nnodesperrow); free(narcsperrow); - return; + return(0); } /* end of UnwrapTile() */ diff --git a/contrib/Snaphu/src/snaphu_cost.c b/contrib/Snaphu/src/snaphu_cost.c index f7a14e18..9dff9e9f 100644 --- a/contrib/Snaphu/src/snaphu_cost.c +++ b/contrib/Snaphu/src/snaphu_cost.c @@ -21,30 +21,146 @@ #include #include #include +#include #include #include #include "snaphu.h" +/* static (local) function prototypes */ +static +void **BuildStatCostsTopo(float **wrappedphase, float **mag, + float **unwrappedest, float **pwr, + float **corr, short **rowweight, short **colweight, + long nrow, long ncol, tileparamT *tileparams, + outfileT *outfiles, paramT *params); +static +void **BuildStatCostsDefo(float **wrappedphase, float **mag, + float **unwrappedest, float **corr, + short **rowweight, short **colweight, + long nrow, long ncol, tileparamT *tileparams, + outfileT *outfiles, paramT *params); +static +void **BuildStatCostsSmooth(float **wrappedphase, float **mag, + float **unwrappedest, float **corr, + short **rowweight, short **colweight, + long nrow, long ncol, tileparamT *tileparams, + outfileT *outfiles, paramT *params); +static +void MaskCost(costT *costptr); +static +void MaskSmoothCost(smoothcostT *smoothcostptr); +static +int MaskPrespecifiedArcCosts(void **costsptr, short **weights, + long nrow, long ncol, paramT *params); +static +int GetIntensityAndCorrelation(float **mag, float **wrappedphase, + float ***pwrptr, float ***corrptr, + infileT *infiles, long linelen, long nlines, + long nrow, long ncol, outfileT *outfiles, + paramT *params, tileparamT *tileparams); +static +int RemoveMean(float **ei, long nrow, long ncol, + long krowei, long kcolei); +static +float *BuildDZRCritLookupTable(double *nominc0ptr, double *dnomincptr, + long *tablesizeptr, tileparamT *tileparams, + paramT *params); +static +double SolveDZRCrit(double sinnomincangle, double cosnomincangle, + paramT *params, double threshold); +static +int SolveEIModelParams(double *slope1ptr, double *slope2ptr, + double *const1ptr, double *const2ptr, + double dzrcrit, double dzr0, double sinnomincangle, + double cosnomincangle, paramT *params); +static +double EIofDZR(double dzr, double sinnomincangle, double cosnomincangle, + paramT *params); +static +float **BuildDZRhoMaxLookupTable(double nominc0, double dnominc, + long nominctablesize, double rhomin, + double drho, long nrho, paramT *params); +static +double CalcDZRhoMax(double rho, double nominc, paramT *params, + double threshold); +static +int CalcInitMaxFlow(paramT *params, void **costs, long nrow, long ncol); + + + /* function: BuildCostArrays() * --------------------------- * Builds cost arrays for arcs based on interferogram intensity * and correlation, depending on options and passed parameters. */ -void BuildCostArrays(void ***costsptr, short ***mstcostsptr, - float **mag, float **wrappedphase, - float **unwrappedest, long linelen, long nlines, - long nrow, long ncol, paramT *params, - tileparamT *tileparams, infileT *infiles, - outfileT *outfiles){ +int BuildCostArrays(void ***costsptr, short ***mstcostsptr, + float **mag, float **wrappedphase, + float **unwrappedest, long linelen, long nlines, + long nrow, long ncol, paramT *params, + tileparamT *tileparams, infileT *infiles, + outfileT *outfiles){ long row, col, maxcol, tempcost; long poscost, negcost, costtypesize; float **pwr, **corr; short **weights, **rowweight, **colweight, **scalarcosts; + bidircostT **bidircosts; void **costs, **rowcost, **colcost; - void (*CalcStatCost)(); + void (*CalcStatCost)(void **, long, long, long, long, long, + paramT *, long *, long *); + + + + /* initializations to silence compiler warnings */ + costtypesize=0; + bidircosts=NULL; + scalarcosts=NULL; + + /* set global pointers to functions for calculating and evaluating costs */ + if(params->p<0){ + if(params->costmode==TOPO){ + CalcCost=CalcCostTopo; + EvalCost=EvalCostTopo; + }else if(params->costmode==DEFO){ + CalcCost=CalcCostDefo; + EvalCost=EvalCostDefo; + }else if(params->costmode==SMOOTH){ + CalcCost=CalcCostSmooth; + EvalCost=EvalCostSmooth; + } + }else{ + if(params->bidirlpn){ + if(params->p==0){ + CalcCost=CalcCostL0BiDir; + EvalCost=EvalCostL0BiDir; + }else if(params->p==1){ + CalcCost=CalcCostL1BiDir; + EvalCost=EvalCostL1BiDir; + }else if(params->p==2){ + CalcCost=CalcCostL2BiDir; + EvalCost=EvalCostL2BiDir; + }else{ + CalcCost=CalcCostLPBiDir; + EvalCost=EvalCostLPBiDir; + } + }else{ + if(params->p==0){ + CalcCost=CalcCostL0; + EvalCost=EvalCostL0; + }else if(params->p==1){ + CalcCost=CalcCostL1; + EvalCost=EvalCostL1; + }else if(params->p==2){ + CalcCost=CalcCostL2; + EvalCost=EvalCostL2; + }else{ + CalcCost=CalcCostLP; + EvalCost=EvalCostLP; + } + } + } /* read weights */ weights=NULL; @@ -52,10 +168,32 @@ void BuildCostArrays(void ***costsptr, short ***mstcostsptr, rowweight=weights; colweight=&weights[nrow-1]; + /* set weights to zero for arcs adjacent to zero-magnitude pixels */ + if(mag!=NULL){ + for(row=0;row0){ + rowweight[row-1][col]=0; + } + if(row0){ + colweight[row][col-1]=0; + } + if(colinitonly && params->costmode==NOSTATCOSTS){ *mstcostsptr=weights; - return; + return(0); } /* size of the data type for holding cost data depends on cost mode */ @@ -69,38 +207,48 @@ void BuildCostArrays(void ***costsptr, short ***mstcostsptr, /* build or read the statistical cost arrays unless we were told not to */ if(strlen(infiles->costinfile)){ + + /* read cost info from file */ fprintf(sp1,"Reading cost information from file %s\n",infiles->costinfile); costs=NULL; Read2DRowColFile((void ***)&costs,infiles->costinfile, - linelen,nlines,tileparams,costtypesize); + linelen,nlines,tileparams,costtypesize); (*costsptr)=costs; + /* weights of arcs next to masked pixels are set to zero */ + /* make sure corresponding costs are nulled when costs are read from */ + /* file rather than internally generated since read costs are not */ + /* multiplied by weights */ + MaskPrespecifiedArcCosts(costs,weights,nrow,ncol,params); + }else if(params->costmode!=NOSTATCOSTS){ /* get intensity and correlation info */ /* correlation generated from interferogram and amplitude if not given */ GetIntensityAndCorrelation(mag,wrappedphase,&pwr,&corr,infiles, - linelen,nlines,nrow,ncol,outfiles, - params,tileparams); + linelen,nlines,nrow,ncol,outfiles, + params,tileparams); /* call specific functions for building cost array and */ /* set global pointers to functions for calculating and evaluating costs */ if(params->costmode==TOPO){ fprintf(sp1,"Calculating topography-mode cost parameters\n"); costs=BuildStatCostsTopo(wrappedphase,mag,unwrappedest,pwr,corr, - rowweight,colweight,nrow,ncol,tileparams, - outfiles,params); + rowweight,colweight,nrow,ncol,tileparams, + outfiles,params); }else if(params->costmode==DEFO){ fprintf(sp1,"Calculating deformation-mode cost parameters\n"); costs=BuildStatCostsDefo(wrappedphase,mag,unwrappedest,corr, - rowweight,colweight,nrow,ncol,tileparams, - outfiles,params); + rowweight,colweight,nrow,ncol,tileparams, + outfiles,params); }else if(params->costmode==SMOOTH){ fprintf(sp1,"Calculating smooth-solution cost parameters\n"); costs=BuildStatCostsSmooth(wrappedphase,mag,unwrappedest,corr, - rowweight,colweight,nrow,ncol,tileparams, - outfiles,params); + rowweight,colweight,nrow,ncol,tileparams, + outfiles,params); }else{ + costs=NULL; + fflush(NULL); fprintf(sp0,"unrecognized cost mode\n"); exit(ABNORMAL_EXIT); } @@ -122,30 +270,44 @@ void BuildCostArrays(void ***costsptr, short ***mstcostsptr, rowcost=costs; colcost=(void **)&(((smoothcostT **)costs)[nrow-1]); CalcStatCost=CalcCostSmooth; + }else{ + rowcost=NULL; + colcost=NULL; + CalcStatCost=NULL; + fflush(NULL); + fprintf(sp0,"unrecognized cost mode\n"); + exit(ABNORMAL_EXIT); } + /* dump statistical cost arrays */ if(strlen(infiles->costinfile) || params->costmode!=NOSTATCOSTS){ if(strlen(outfiles->costoutfile)){ Write2DRowColArray((void **)costs,outfiles->costoutfile, - nrow,ncol,costtypesize); + nrow,ncol,costtypesize); }else{ if(strlen(outfiles->rowcostfile)){ - Write2DArray((void **)rowcost,outfiles->rowcostfile, - nrow-1,ncol,costtypesize); + Write2DArray((void **)rowcost,outfiles->rowcostfile, + nrow-1,ncol,costtypesize); } if(strlen(outfiles->colcostfile)){ - Write2DArray((void **)colcost,outfiles->colcostfile, - nrow,ncol-1,costtypesize); + Write2DArray((void **)colcost,outfiles->colcostfile, + nrow,ncol-1,costtypesize); } } } /* get memory for scalar costs if in Lp mode */ if(params->p>=0){ - scalarcosts=(short **)Get2DRowColMem(nrow,ncol, - sizeof(short *),sizeof(short)); - (*costsptr)=(void **)scalarcosts; + if(params->bidirlpn){ + bidircosts=(bidircostT **)Get2DRowColMem(nrow,ncol,sizeof(bidircostT *), + sizeof(bidircostT)); + (*costsptr)=(void **)bidircosts; + }else{ + scalarcosts=(short **)Get2DRowColMem(nrow,ncol,sizeof(short *), + sizeof(short)); + (*costsptr)=(void **)scalarcosts; + } } /* now, set scalar costs for MST initialization or optimization if needed */ @@ -154,14 +316,19 @@ void BuildCostArrays(void ***costsptr, short ***mstcostsptr, /* if in no-statistical-costs mode, copy weights to scalarcosts array */ if(!params->initonly){ for(row=0;row<2*nrow-1;row++){ - if(rowbidirlpn){ + bidircosts[row][col].posweight=weights[row][col]; + bidircosts[row][col].negweight=weights[row][col]; + }else{ + scalarcosts[row][col]=weights[row][col]; + } + } } } @@ -179,36 +346,42 @@ void BuildCostArrays(void ***costsptr, short ***mstcostsptr, /* from them for MST initialization or for Lp optimization */ for(row=0;row<2*nrow-1;row++){ if(rowmaxcost */ - if(tempcostmaxcost){ - if(tempcost>MINSCALARCOST){ - weights[row][col]=tempcost; - }else{ - weights[row][col]=MINSCALARCOST; - } - }else{ - weights[row][col]=params->maxcost; - } - if(params->p>=0){ - scalarcosts[row][col]=weights[row][col]; - } + /* calculate incremental costs for flow=0, nflow=1 */ + CalcStatCost((void **)costs,0,row,col,1,nrow,params, + &poscost,&negcost); + + /* take smaller of positive and negative incremental cost */ + if(poscostmaxcost */ + /* note: weights used for MST algorithm will not be zero along */ + /* masked edges since they are clipped to 1, but MST is run */ + /* once on entire network, not just non-masked regions */ + weights[row][col]=LClip(tempcost,MINSCALARCOST,params->maxcost); + + /* assign Lp costs if in Lp mode */ + /* let scalar cost be zero if costs in both directions are zero */ + if(params->p>=0){ + if(params->bidirlpn){ + bidircosts[row][col].posweight=LClip(poscost,0,params->maxcost); + bidircosts[row][col].negweight=LClip(negcost,0,params->maxcost); + }else{ + scalarcosts[row][col]=weights[row][col]; + if(poscost==0 && negcost==0){ + scalarcosts[row][col]=0; + } + } + } } } @@ -218,24 +391,35 @@ void BuildCostArrays(void ***costsptr, short ***mstcostsptr, weights[2*nrow-2][0]=LARGESHORT; weights[2*nrow-2][ncol-2]=LARGESHORT; if(params->p>=0){ - scalarcosts[nrow-1][0]=LARGESHORT; - scalarcosts[nrow-1][ncol-2]=LARGESHORT; - scalarcosts[2*nrow-2][0]=LARGESHORT; - scalarcosts[2*nrow-2][ncol-2]=LARGESHORT; + if(params->bidirlpn){ + bidircosts[nrow-1][0].posweight=LARGESHORT; + bidircosts[nrow-1][0].negweight=LARGESHORT; + bidircosts[nrow-1][ncol-2].posweight=LARGESHORT; + bidircosts[nrow-1][ncol-2].negweight=LARGESHORT; + bidircosts[2*nrow-2][0].posweight=LARGESHORT; + bidircosts[2*nrow-2][0].negweight=LARGESHORT; + bidircosts[2*nrow-2][ncol-2].posweight=LARGESHORT; + bidircosts[2*nrow-2][ncol-2].negweight=LARGESHORT; + }else{ + scalarcosts[nrow-1][0]=LARGESHORT; + scalarcosts[nrow-1][ncol-2]=LARGESHORT; + scalarcosts[2*nrow-2][0]=LARGESHORT; + scalarcosts[2*nrow-2][ncol-2]=LARGESHORT; + } } /* dump mst initialization costs */ if(strlen(outfiles->mstrowcostfile)){ Write2DArray((void **)rowweight,outfiles->mstrowcostfile, - nrow-1,ncol,sizeof(short)); + nrow-1,ncol,sizeof(short)); } if(strlen(outfiles->mstcolcostfile)){ Write2DArray((void **)colweight,outfiles->mstcolcostfile, - nrow,ncol-1,sizeof(short)); + nrow,ncol-1,sizeof(short)); } if(strlen(outfiles->mstcostsfile)){ Write2DRowColArray((void **)rowweight,outfiles->mstcostsfile, - nrow,ncol,sizeof(short)); + nrow,ncol,sizeof(short)); } /* unless input is unwrapped, calculate initialization max flow */ @@ -259,6 +443,9 @@ void BuildCostArrays(void ***costsptr, short ***mstcostsptr, Free2DArray((void **)weights,2*nrow-1); } + /* done */ + return(0); + } @@ -266,11 +453,12 @@ void BuildCostArrays(void ***costsptr, short ***mstcostsptr, * ------------------------------ * Builds statistical cost arrays for topography mode. */ +static void **BuildStatCostsTopo(float **wrappedphase, float **mag, - float **unwrappedest, float **pwr, - float **corr, short **rowweight, short **colweight, - long nrow, long ncol, tileparamT *tileparams, - outfileT *outfiles, paramT *params){ + float **unwrappedest, float **pwr, + float **corr, short **rowweight, short **colweight, + long nrow, long ncol, tileparamT *tileparams, + outfileT *outfiles, paramT *params){ long row, col, iei, nrho, nominctablesize; long kperpdpsi, kpardpsi, sigsqshortmin; @@ -338,7 +526,7 @@ void **BuildStatCostsTopo(float **wrappedphase, float **mag, /* compute some midswath parameters */ slantrange=nearrange+ncol/2*dr; sinnomincangle=sin(acos((a*a-slantrange*slantrange-re*re) - /(2*slantrange*re))); + /(2*slantrange*re))); lookangle=asin(re/a*sinnomincangle); /* see if we were passed bperp rather than baseline and baselineangle */ @@ -360,11 +548,11 @@ void **BuildStatCostsTopo(float **wrappedphase, float **mag, /* build lookup table for dzrcrit vs incidence angle */ dzrcrittable=BuildDZRCritLookupTable(&nominc0,&dnominc,&nominctablesize, - tileparams,params); + tileparams,params); /* build lookup table for dzrhomax vs incidence angle */ dzrhomaxtable=BuildDZRhoMaxLookupTable(nominc0,dnominc,nominctablesize, - rhomin,drho,nrho,params); + rhomin,drho,nrho,params); /* set cost autoscale factor based on midswath parameters */ bperp=baseline*cos(lookangle-baselineangle); @@ -381,7 +569,7 @@ void **BuildStatCostsTopo(float **wrappedphase, float **mag, /* differences usually near zero, so don't bother with complex average */ fprintf(sp2,"Building range cost arrays\n"); CalcWrappedRangeDiffs(dpsi,avgdpsi,wrappedphase,kperpdpsi,kpardpsi, - nrow,ncol); + nrow,ncol); /* build colcost array (range slopes) */ /* loop over range */ @@ -405,118 +593,115 @@ void **BuildStatCostsTopo(float **wrappedphase, float **mag, nomincind=(nomincangle-nominc0)/dnominc; dzrcrit=LinInterp1D(dzrcrittable,nomincind,nominctablesize); SolveEIModelParams(&slope1,&slope2,&const1,&const2,dzrcrit,dzr0, - sinnomincangle,cosnomincangle,params); + sinnomincangle,cosnomincangle,params); eicrit=(dzrcrit-const1)/slope1; dphilaypeak=params->dzlaypeak/ambiguityheight; /* loop over azimuth */ for(row=0;roweicrit){ - dzei=(slope2*ei[row][col]+const2)*dzeifactor; - }else{ - dzei=(slope1*ei[row][col]+const1)*dzeifactor; - } - if(noshadow && dzeilayminei){ - for(iei=0;ieieicrit){ - dzlay+=slope2*ei[row][col+iei]+const2; - }else{ - dzlay+=slope1*ei[row][col+iei]+const1; - } - if(col+iei>ncol-2){ - break; - } - } - } - if(dzlay){ - dzlay=(dzlay+iei*(-2.0*dzr0))*dzlayfactor; - } - - /* set maximum dz based on unbiased correlation and layover max */ - if(rho>0){ - dzrhomax=LinInterp2D(dzrhomaxtable,nomincind,(rho-rhomin)/drho, - nominctablesize,nrho); - if(dzrhomax0){ - colcost[row][col].offset=nshortcycle* - (dpsi[row][col]-0.5*(avgdpsi[row][col]+dphilaypeak)); - }else{ - colcost[row][col].offset=nshortcycle* - (dpsi[row][col]-0.25*avgdpsi[row][col]-0.75*dphilaypeak); - } - colcost[row][col].sigsq=(sigsqrho+sigsqei+sigsqlay)*ztoshortsq - /(costscale*colweight[row][col]); - if(colcost[row][col].sigsqfloor(sqrt(colcost[row][col].laycost*colcost[row][col].sigsq))){ - nolayover=FALSE; - } - } - if(nolayover){ - colcost[row][col].sigsq=(sigsqrho+sigsqei)*ztoshortsq - /(costscale*colweight[row][col]); - if(colcost[row][col].sigsq0){ - colcost[row][col].offset=ztoshort* - (ambiguityheight*(dpsi[row][col]-0.5*avgdpsi[row][col]) - -0.5*dzeiweight*dzei); - }else{ - colcost[row][col].offset=ztoshort* - (ambiguityheight*(dpsi[row][col]-0.25*avgdpsi[row][col]) - -0.75*dzeiweight*dzei); - } - colcost[row][col].laycost=NOCOSTSHELF; - colcost[row][col].dzmax=LARGESHORT; - } - - /* shift PDF to account for flattening by coarse unwrapped estimate */ - if(unwrappedest!=NULL){ - colcost[row][col].offset+=(nshortcycle/TWOPI* - (unwrappedest[row][col+1] - -unwrappedest[row][col])); - } + /* topography-mode costs */ + + /* calculate variance due to decorrelation */ + /* factor of 2 in sigsqrhoconst for pdf convolution */ + rho=corr[row][col]; + if(rhoeicrit){ + dzei=(slope2*ei[row][col]+const2)*dzeifactor; + }else{ + dzei=(slope1*ei[row][col]+const1)*dzeifactor; + } + if(noshadow && dzeilayminei){ + for(iei=0;ieieicrit){ + dzlay+=slope2*ei[row][col+iei]+const2; + }else{ + dzlay+=slope1*ei[row][col+iei]+const1; + } + if(col+iei>ncol-2){ + break; + } + } + } + if(dzlay){ + dzlay=(dzlay+iei*(-2.0*dzr0))*dzlayfactor; + } + + /* set maximum dz based on unbiased correlation and layover max */ + if(rho>0){ + dzrhomax=LinInterp2D(dzrhomaxtable,nomincind,(rho-rhomin)/drho, + nominctablesize,nrho); + if(dzrhomax0){ + colcost[row][col].offset=nshortcycle* + (dpsi[row][col]-0.5*(avgdpsi[row][col]+dphilaypeak)); + }else{ + colcost[row][col].offset=nshortcycle* + (dpsi[row][col]-0.25*avgdpsi[row][col]-0.75*dphilaypeak); + } + colcost[row][col].sigsq=(sigsqrho+sigsqei+sigsqlay)*ztoshortsq + /(costscale*colweight[row][col]); + if(colcost[row][col].sigsqfloor(sqrt(colcost[row][col].laycost*colcost[row][col].sigsq))){ + nolayover=FALSE; + } + } + if(nolayover){ + colcost[row][col].sigsq=(sigsqrho+sigsqei)*ztoshortsq + /(costscale*colweight[row][col]); + if(colcost[row][col].sigsq0){ + colcost[row][col].offset=ztoshort* + (ambiguityheight*(dpsi[row][col]-0.5*avgdpsi[row][col]) + -0.5*dzeiweight*dzei); + }else{ + colcost[row][col].offset=ztoshort* + (ambiguityheight*(dpsi[row][col]-0.25*avgdpsi[row][col]) + -0.75*dzeiweight*dzei); + } + colcost[row][col].laycost=NOCOSTSHELF; + colcost[row][col].dzmax=LARGESHORT; + } + + /* shift PDF to account for flattening by coarse unwrapped estimate */ + if(unwrappedest!=NULL){ + colcost[row][col].offset+=(nshortcycle/TWOPI* + (unwrappedest[row][col+1] + -unwrappedest[row][col])); + } } } @@ -529,7 +714,7 @@ void **BuildStatCostsTopo(float **wrappedphase, float **mag, /* biased, but not much, so don't bother with complex averaging */ fprintf(sp2,"Building azimuth cost arrays\n"); CalcWrappedAzDiffs(dpsi,avgdpsi,wrappedphase,kperpdpsi,kpardpsi, - nrow,ncol); + nrow,ncol); /* build rowcost array */ /* for the rowcost array, there is symmetry between positive and */ @@ -555,104 +740,101 @@ void **BuildStatCostsTopo(float **wrappedphase, float **mag, nomincind=(nomincangle-nominc0)/dnominc; dzrcrit=LinInterp1D(dzrcrittable,nomincind,nominctablesize); SolveEIModelParams(&slope1,&slope2,&const1,&const2,dzrcrit,dzr0, - sinnomincangle,cosnomincangle,params); + sinnomincangle,cosnomincangle,params); eicrit=(dzrcrit-const1)/slope1; dphilaypeak=params->dzlaypeak/ambiguityheight; /* loop over azimuth */ for(row=0;rowlayminei){ - for(iei=0;ieieicrit){ - dzlay+=slope2*avgei+const2; - }else{ - dzlay+=slope1*avgei+const1; - } - if(col+iei>ncol-2){ - break; - } - } - } - if(dzlay){ - dzlay=(dzlay+iei*(-2.0*dzr0))*dzlayfactor; - } - - /* set maximum dz based on correlation max and layover max */ - if(rho>0){ - dzrhomax=LinInterp2D(dzrhomaxtable,nomincind,(rho-rhomin)/drho, - nominctablesize,nrho); - if(dzrhomax0){ - rowcost[row][col].offset=nshortcycle* - (dpsi[row][col]-avgdpsi[row][col]); - }else{ - rowcost[row][col].offset=nshortcycle* - (dpsi[row][col]-0.5*avgdpsi[row][col]); - } - nolayover=TRUE; - if(dzlay){ - rowcost[row][col].sigsq=(sigsqrho+sigsqei+sigsqlay)*ztoshortsq - /(costscale*rowweight[row][col]); - if(rowcost[row][col].sigsqfloor(sqrt(rowcost[row][col].laycost*rowcost[row][col].sigsq))){ - nolayover=FALSE; - } - } - if(nolayover){ - rowcost[row][col].sigsq=(sigsqrho+sigsqei)*ztoshortsq - /(costscale*rowweight[row][col]); - if(rowcost[row][col].sigsqlayminei){ + for(iei=0;ieieicrit){ + dzlay+=slope2*avgei+const2; + }else{ + dzlay+=slope1*avgei+const1; + } + if(col+iei>ncol-2){ + break; + } + } + } + if(dzlay){ + dzlay=(dzlay+iei*(-2.0*dzr0))*dzlayfactor; + } + + /* set maximum dz based on correlation max and layover max */ + if(rho>0){ + dzrhomax=LinInterp2D(dzrhomaxtable,nomincind,(rho-rhomin)/drho, + nominctablesize,nrho); + if(dzrhomax0){ + rowcost[row][col].offset=nshortcycle* + (dpsi[row][col]-avgdpsi[row][col]); + }else{ + rowcost[row][col].offset=nshortcycle* + (dpsi[row][col]-0.5*avgdpsi[row][col]); + } + nolayover=TRUE; + if(dzlay){ + rowcost[row][col].sigsq=(sigsqrho+sigsqei+sigsqlay)*ztoshortsq + /(costscale*rowweight[row][col]); + if(rowcost[row][col].sigsqfloor(sqrt(rowcost[row][col].laycost*rowcost[row][col].sigsq))){ + nolayover=FALSE; + } + } + if(nolayover){ + rowcost[row][col].sigsq=(sigsqrho+sigsqei)*ztoshortsq + /(costscale*rowweight[row][col]); + if(rowcost[row][col].sigsq0){ - colcost[row][col].offset=nshortcycle* - (dpsi[row][col]-avgdpsi[row][col]); - }else{ - colcost[row][col].offset=nshortcycle* - (dpsi[row][col]-0.5*avgdpsi[row][col]); - } - colcost[row][col].sigsq=sigsqrho/(costscale*colweight[row][col]); - if(colcost[row][col].sigsq0){ + colcost[row][col].offset=nshortcycle* + (dpsi[row][col]-avgdpsi[row][col]); + }else{ + colcost[row][col].offset=nshortcycle* + (dpsi[row][col]-0.5*avgdpsi[row][col]); + } + colcost[row][col].sigsq=sigsqrho/(costscale*colweight[row][col]); + if(colcost[row][col].sigsq0){ - rowcost[row][col].offset=nshortcycle* - (dpsi[row][col]-avgdpsi[row][col]); - }else{ - rowcost[row][col].offset=nshortcycle* - (dpsi[row][col]-0.5*avgdpsi[row][col]); - } - rowcost[row][col].sigsq=sigsqrho/(costscale*rowweight[row][col]); - if(rowcost[row][col].sigsq0){ + rowcost[row][col].offset=nshortcycle* + (dpsi[row][col]-avgdpsi[row][col]); + }else{ + rowcost[row][col].offset=nshortcycle* + (dpsi[row][col]-0.5*avgdpsi[row][col]); + } + rowcost[row][col].sigsq=sigsqrho/(costscale*rowweight[row][col]); + if(rowcost[row][col].sigsq0){ - colcost[row][col].offset=nshortcycle* - (dpsi[row][col]-avgdpsi[row][col]); - }else{ - colcost[row][col].offset=nshortcycle* - (dpsi[row][col]-0.5*avgdpsi[row][col]); - } - colcost[row][col].sigsq=sigsqrho/(costscale*colweight[row][col]); - if(colcost[row][col].sigsq0){ + colcost[row][col].offset=nshortcycle* + (dpsi[row][col]-avgdpsi[row][col]); + }else{ + colcost[row][col].offset=nshortcycle* + (dpsi[row][col]-0.5*avgdpsi[row][col]); + } + colcost[row][col].sigsq=sigsqrho/(costscale*colweight[row][col]); + if(colcost[row][col].sigsq0){ - rowcost[row][col].offset=nshortcycle* - (dpsi[row][col]-avgdpsi[row][col]); - }else{ - rowcost[row][col].offset=nshortcycle* - (dpsi[row][col]-0.5*avgdpsi[row][col]); - } - rowcost[row][col].sigsq=sigsqrho/(costscale*rowweight[row][col]); - if(rowcost[row][col].sigsq0){ + rowcost[row][col].offset=nshortcycle* + (dpsi[row][col]-avgdpsi[row][col]); + }else{ + rowcost[row][col].offset=nshortcycle* + (dpsi[row][col]-0.5*avgdpsi[row][col]); + } + rowcost[row][col].sigsq=sigsqrho/(costscale*rowweight[row][col]); + if(rowcost[row][col].sigsqlaycost=0; + costptr->offset=LARGESHORT/2; + costptr->dzmax=LARGESHORT; + costptr->sigsq=LARGESHORT; + +} + + +/* function: MaskSmoothCost() + * -------------------------- + * Set values of smoothcostT structure pointed to by input pointer to give zero + * cost, as for arcs next to masked pixels. + */ +static +void MaskSmoothCost(smoothcostT *smoothcostptr){ + + /* set to special values */ + smoothcostptr->offset=LARGESHORT/2; + smoothcostptr->sigsq=LARGESHORT; + +} + + +/* function: MaskPrespecifiedArcCosts() + * ------------------------------------ + * Loop over grid arcs and set costs to null if corresponding weights + * are null. + */ +static +int MaskPrespecifiedArcCosts(void **costsptr, short **weights, + long nrow, long ncol, paramT *params){ + + long row, col, maxcol; + costT **costs; + smoothcostT **smoothcosts; + + + /* set up pointers */ + costs=NULL; + smoothcosts=NULL; + if(params->costmode==TOPO || params->costmode==DEFO){ + costs=(costT **)costsptr; + }else if(params->costmode==SMOOTH){ + smoothcosts=(smoothcostT **)costsptr; + }else{ + fprintf(sp0,"illegal cost mode in MaskPrespecifiedArcCosts()\n"); + exit(ABNORMAL_EXIT); + } + + /* loop over all arcs */ + for(row=0;row<2*nrow-1;row++){ + if(rowncorrlooks=(kcolcorr*(params->dr/params->rangeres)) *(krowcorr*(params->da/params->azres))*params->nlooksother; fprintf(sp1," (%.1f equivalent independent looks)\n", - params->ncorrlooks); + params->ncorrlooks); /* get real and imaginary parts of interferogram */ realcomp=(float **)Get2DMem(nrow,ncol,sizeof(float *),sizeof(float)); imagcomp=(float **)Get2DMem(nrow,ncol,sizeof(float *),sizeof(float)); for(row=0;rowdefaultcorr); + params->defaultcorr); rho0=(params->rhosconst1)/(params->ncorrlooks)+(params->rhosconst2); rhomin=params->rhominfactor*rho0; if(params->defaultcorr>rhomin){ @@ -1152,7 +1413,7 @@ void GetIntensityAndCorrelation(float **mag, float **wrappedphase, } for(row=0;rowrawcorrdumpfile)){ Write2DArray((void **)corr,outfiles->rawcorrdumpfile, - nrow,ncol,sizeof(float)); + nrow,ncol,sizeof(float)); } /* check correlation data validity */ @@ -1168,30 +1429,32 @@ void GetIntensityAndCorrelation(float **mag, float **wrappedphase, for(row=0;row1.0){ - if(corr[row][col]>1.001){ - iclipped++; /* don't warn for minor numerical errors */ - } - corr[row][col]=1.0; + if(corr[row][col]>1.001){ + iclipped++; /* don't warn for minor numerical errors */ + } + corr[row][col]=1.0; }else if(corr[row][col]<0.0){ - if(corr[row][col]<-0.001){ - iclipped++; /* don't warn for minor numerical errors */ - } - corr[row][col]=0.0; + if(corr[row][col]<-0.001){ + iclipped++; /* don't warn for minor numerical errors */ + } + corr[row][col]=0.0; } } } if(iclipped){ + fflush(NULL); fprintf(sp0,"WARNING: %ld illegal correlation values clipped to [0,1]\n", - iclipped); + iclipped); } /* dump correlation data if necessary */ if(strlen(outfiles->corrdumpfile)){ Write2DArray((void **)corr,outfiles->corrdumpfile, - nrow,ncol,sizeof(float)); + nrow,ncol,sizeof(float)); } /* free memory and set output pointers */ @@ -1208,6 +1471,9 @@ void GetIntensityAndCorrelation(float **mag, float **wrappedphase, *pwrptr=pwr; *corrptr=corr; + /* done */ + return(0); + } @@ -1215,8 +1481,9 @@ void GetIntensityAndCorrelation(float **mag, float **wrappedphase, * ------------------------- * Divides intensity by average over sliding window. */ -void RemoveMean(float **ei, long nrow, long ncol, - long krowei, long kcolei){ +static +int RemoveMean(float **ei, long nrow, long ncol, + long krowei, long kcolei){ float **avgei, **padei; long row, col; @@ -1235,8 +1502,9 @@ void RemoveMean(float **ei, long nrow, long ncol, /* pad ei in new array */ padei=MirrorPad(ei,nrow,ncol,(krowei-1)/2,(kcolei-1)/2); if(padei==ei){ + fflush(NULL); fprintf(sp0,"Intensity-normalization averaging box too large " - "for input array size\nAbort\n"); + "for input array size\nAbort\n"); exit(ABNORMAL_EXIT); } @@ -1247,7 +1515,7 @@ void RemoveMean(float **ei, long nrow, long ncol, for(row=0;rowdr*tileparams->ncol; nomincmax=acos((a*a-slantrange*slantrange-re*re)/(2*slantrange*re)); if(!IsFinite(nominc0) || !IsFinite(nomincmax)){ + fflush(NULL); fprintf(sp0,"Geometry error detected. " - "Check altitude, near range, and earth radius parameters\n" - "Abort\n"); + "Check altitude, near range, and earth radius parameters\n" + "Abort\n"); exit(ABNORMAL_EXIT); } @@ -1294,7 +1565,7 @@ float *BuildDZRCritLookupTable(double *nominc0ptr, double *dnomincptr, nominc=nominc0; for(k=0;kthreshold); + params->threshold); nominc+=dnominc; if(nominc>PI/2.0){ nominc-=dnominc; @@ -1315,8 +1586,9 @@ float *BuildDZRCritLookupTable(double *nominc0ptr, double *dnomincptr, * Numerically solve for the transition point of the linearized scattering * model. */ +static double SolveDZRCrit(double sinnomincangle, double cosnomincangle, - paramT *params, double threshold){ + paramT *params, double threshold){ double residual, thetai, kds, n, dr, dzr, dx; double costhetai, cos2thetai, step; @@ -1349,6 +1621,7 @@ double SolveDZRCrit(double sinnomincangle, double cosnomincangle, } step/=2.0; if(++i>MAXITERATION){ + fflush(NULL); fprintf(sp0,"Couldn't find critical incidence angle "); fprintf(sp0,"(check scattering parameters)\nAbort\n"); exit(ABNORMAL_EXIT); @@ -1363,7 +1636,7 @@ double SolveDZRCrit(double sinnomincangle, double cosnomincangle, while(TRUE){ dx=(dr+dzr*cosnomincangle)/sinnomincangle; if(fabs(residual=costhetai-(dzr*sinnomincangle+dx*cosnomincangle) - /sqrt(dzr*dzr+dx*dx)) + /sqrt(dzr*dzr+dx*dx)) MAXITERATION){ + fflush(NULL); fprintf(sp0,"Couldn't find critical slope "); fprintf(sp0,"(check geometry parameters)\nAbort\n"); exit(ABNORMAL_EXIT); @@ -1387,11 +1661,11 @@ double SolveDZRCrit(double sinnomincangle, double cosnomincangle, * Calculates parameters for linearized model of EI vs. range slope * relationship. */ -void SolveEIModelParams(double *slope1ptr, double *slope2ptr, - double *const1ptr, double *const2ptr, - double dzrcrit, double dzr0, double sinnomincangle, - double cosnomincangle, paramT *params){ - +int SolveEIModelParams(double *slope1ptr, double *slope2ptr, + double *const1ptr, double *const2ptr, + double dzrcrit, double dzr0, double sinnomincangle, + double cosnomincangle, paramT *params){ + double slope1, slope2, const1, const2, sloperatio; double dzr3, ei3; @@ -1414,7 +1688,8 @@ void SolveEIModelParams(double *slope1ptr, double *slope2ptr, *slope2ptr=slope2; *const1ptr=const1; *const2ptr=const2; - + return(0); + } @@ -1423,8 +1698,9 @@ void SolveEIModelParams(double *slope1ptr, double *slope2ptr, * Calculates expected value of intensity with arbitrary units for given * parameters. Assumes azimuth slope is zero. */ +static double EIofDZR(double dzr, double sinnomincangle, double cosnomincangle, - paramT *params){ + paramT *params){ double dr, da, dx, kds, n, dzr0, projarea; double costhetai, cos2thetai, sigma0; @@ -1453,22 +1729,23 @@ double EIofDZR(double dzr, double sinnomincangle, double cosnomincangle, * Builds a 2-D lookup table of dzrhomax values vs nominal incidence angle * (rad) and correlation. */ +static float **BuildDZRhoMaxLookupTable(double nominc0, double dnominc, - long nominctablesize, double rhomin, - double drho, long nrho, paramT *params){ + long nominctablesize, double rhomin, + double drho, long nrho, paramT *params){ long krho, knominc; double nominc, rho; float **dzrhomaxtable; dzrhomaxtable=(float **)Get2DMem(nominctablesize,nrho, - sizeof(float *),sizeof(float)); + sizeof(float *),sizeof(float)); nominc=nominc0; for(knominc=0;knomincthreshold); + params->threshold); rho+=drho; } nominc+=dnominc; @@ -1484,8 +1761,9 @@ float **BuildDZRhoMaxLookupTable(double nominc0, double dnominc, * using spatial decorrelation as an upper limit (Zebker & Villasenor, * 1992). */ +static double CalcDZRhoMax(double rho, double nominc, paramT *params, - double threshold){ + double threshold){ long i; double dx, dr, dz, dzstep, rhos, sintheta, costheta, numerator; @@ -1546,6 +1824,7 @@ double CalcDZRhoMax(double rho, double nominc, paramT *params, rhos=0; } if(++i>MAXITERATION){ + fflush(NULL); fprintf(sp0,"Couldn't find slope for correlation of %f\n",rho); fprintf(sp0,"(check geometry and spatial decorrelation parameters)\n"); fprintf(sp0,"Abort\n"); @@ -1562,8 +1841,8 @@ double CalcDZRhoMax(double rho, double nominc, paramT *params, * Calculates topography arc distance given an array of cost data structures. */ void CalcCostTopo(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr){ + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ long idz1, idz2pos, idz2neg, cost1, nflowsq, poscost, negcost; long nshortcycle, layfalloffconst; @@ -1573,10 +1852,19 @@ void CalcCostTopo(void **costs, long flow, long arcrow, long arccol, /* get arc info */ cost=&((costT **)(costs))[arcrow][arccol]; - dzmax=cost->dzmax; offset=cost->offset; sigsq=cost->sigsq; + dzmax=cost->dzmax; laycost=cost->laycost; + + /* just return 0 if we have zero cost arc */ + if(sigsq==LARGESHORT){ + (*poscostptr)=0; + (*negcostptr)=0; + return; + } + + /* compute argument to cost function */ nshortcycle=params->nshortcycle; layfalloffconst=params->layfalloffconst; if(arcrow0){ - *poscostptr=(long )ceil((float )poscost/nflowsq); + *poscostptr=(long )ceil((double )poscost/nflowsq); }else{ - *poscostptr=(long )floor((float )poscost/nflowsq); + *poscostptr=(long )floor((double )poscost/nflowsq); } if(negcost>0){ - *negcostptr=(long )ceil((float )negcost/nflowsq); + *negcostptr=(long )ceil((double )negcost/nflowsq); }else{ - *negcostptr=(long )floor((float )negcost/nflowsq); + *negcostptr=(long )floor((double )negcost/nflowsq); } + /* done */ + return; + } @@ -1663,8 +1954,8 @@ void CalcCostTopo(void **costs, long flow, long arcrow, long arccol, * Calculates deformation arc distance given an array of cost data structures. */ void CalcCostDefo(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr){ + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ long idz1, idz2pos, idz2neg, cost1, nflowsq, poscost, negcost; long nshortcycle, layfalloffconst; @@ -1673,6 +1964,15 @@ void CalcCostDefo(void **costs, long flow, long arcrow, long arccol, /* get arc info */ cost=&((costT **)(costs))[arcrow][arccol]; + + /* just return 0 if we have zero cost arc */ + if(cost->sigsq==LARGESHORT){ + (*poscostptr)=0; + (*negcostptr)=0; + return; + } + + /* compute argument to cost function */ nshortcycle=params->nshortcycle; layfalloffconst=params->layfalloffconst; idz1=labs(flow*nshortcycle+cost->offset); @@ -1721,16 +2021,19 @@ void CalcCostDefo(void **costs, long flow, long arcrow, long arccol, /* scale costs for this nflow */ nflowsq=nflow*nflow; if(poscost>0){ - *poscostptr=(long )ceil((float )poscost/nflowsq); + *poscostptr=(long )ceil((double )poscost/nflowsq); }else{ - *poscostptr=(long )floor((float )poscost/nflowsq); + *poscostptr=(long )floor((double )poscost/nflowsq); } if(negcost>0){ - *negcostptr=(long )ceil((float )negcost/nflowsq); + *negcostptr=(long )ceil((double )negcost/nflowsq); }else{ - *negcostptr=(long )floor((float )negcost/nflowsq); + *negcostptr=(long )floor((double )negcost/nflowsq); } + /* done */ + return; + } @@ -1740,8 +2043,8 @@ void CalcCostDefo(void **costs, long flow, long arcrow, long arccol, * data structures. */ void CalcCostSmooth(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr){ + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ long idz1, idz2pos, idz2neg, cost1, nflowsq, poscost, negcost; long nshortcycle; @@ -1750,6 +2053,15 @@ void CalcCostSmooth(void **costs, long flow, long arcrow, long arccol, /* get arc info */ cost=&((smoothcostT **)(costs))[arcrow][arccol]; + + /* just return 0 if we have zero cost arc */ + if(cost->sigsq==LARGESHORT){ + (*poscostptr)=0; + (*negcostptr)=0; + return; + } + + /* compute argument to cost function */ nshortcycle=params->nshortcycle; idz1=labs(flow*nshortcycle+cost->offset); idz2pos=labs((flow+nflow)*nshortcycle+cost->offset); @@ -1767,16 +2079,19 @@ void CalcCostSmooth(void **costs, long flow, long arcrow, long arccol, /* scale costs for this nflow */ nflowsq=nflow*nflow; if(poscost>0){ - *poscostptr=(long )ceil((float )poscost/nflowsq); + *poscostptr=(long )ceil((double )poscost/nflowsq); }else{ - *poscostptr=(long )floor((float )poscost/nflowsq); + *poscostptr=(long )floor((double )poscost/nflowsq); } if(negcost>0){ - *negcostptr=(long )ceil((float )negcost/nflowsq); + *negcostptr=(long )ceil((double )negcost/nflowsq); }else{ - *negcostptr=(long )floor((float )negcost/nflowsq); + *negcostptr=(long )floor((double )negcost/nflowsq); } + /* done */ + return; + } @@ -1785,8 +2100,8 @@ void CalcCostSmooth(void **costs, long flow, long arcrow, long arccol, * Calculates the L0 arc distance given an array of short integer weights. */ void CalcCostL0(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr){ + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ /* L0-norm */ if(flow){ @@ -1804,6 +2119,10 @@ void CalcCostL0(void **costs, long flow, long arcrow, long arccol, *poscostptr=((short **)costs)[arcrow][arccol]; *negcostptr=((short **)costs)[arcrow][arccol]; } + + /* done */ + return; + } @@ -1812,13 +2131,16 @@ void CalcCostL0(void **costs, long flow, long arcrow, long arccol, * Calculates the L1 arc distance given an array of short integer weights. */ void CalcCostL1(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr){ + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ /* L1-norm */ *poscostptr=((short **)costs)[arcrow][arccol]*(labs(flow+nflow)-labs(flow)); *negcostptr=((short **)costs)[arcrow][arccol]*(labs(flow-nflow)-labs(flow)); + /* done */ + return; + } @@ -1827,8 +2149,8 @@ void CalcCostL1(void **costs, long flow, long arcrow, long arccol, * Calculates the L2 arc distance given an array of short integer weights. */ void CalcCostL2(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr){ + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ long flow2, flowsq; @@ -1838,6 +2160,9 @@ void CalcCostL2(void **costs, long flow, long arcrow, long arccol, *poscostptr=((short **)costs)[arcrow][arccol]*(flow2*flow2-flowsq); flow2=flow-nflow; *negcostptr=((short **)costs)[arcrow][arccol]*(flow2*flow2-flowsq); + + /* done */ + return; } @@ -1846,35 +2171,213 @@ void CalcCostL2(void **costs, long flow, long arcrow, long arccol, * Calculates the Lp arc distance given an array of short integer weights. */ void CalcCostLP(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr){ + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ - long p; + double p; short flow2; /* Lp-norm */ flow2=flow+nflow; p=params->p; *poscostptr=LRound(((short **)costs)[arcrow][arccol]* - (pow(labs(flow2),p)-pow(labs(flow),p))); + (pow(labs(flow2),p)-pow(labs(flow),p))); flow2=flow-nflow; *negcostptr=LRound(((short **)costs)[arcrow][arccol]* - (pow(labs(flow2),p)-pow(labs(flow),p))); + (pow(labs(flow2),p)-pow(labs(flow),p))); + + /* done */ + return; +} + + +/* function: CalcCostL0BiDir() + * --------------------------- + * Calculates the L0 arc cost given an array of bidirectional cost weights. + */ +void CalcCostL0BiDir(void **costs, long flow, long arcrow, long arccol, + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ + + long newflow, cost0; + + /* L0-norm */ + if(flow>0){ + cost0=((bidircostT **)costs)[arcrow][arccol].posweight; + }else if(flow<0){ + cost0=((bidircostT **)costs)[arcrow][arccol].negweight; + }else{ + cost0=0; + } + newflow=flow+nflow; + if(newflow>0){ + *poscostptr=((bidircostT **)costs)[arcrow][arccol].posweight-cost0; + }else if(newflow<0){ + *poscostptr=((bidircostT **)costs)[arcrow][arccol].negweight-cost0; + }else{ + *poscostptr=-cost0; + } + newflow=flow-nflow; + if(newflow>0){ + *negcostptr=((bidircostT **)costs)[arcrow][arccol].posweight-cost0; + }else if(newflow<0){ + *negcostptr=((bidircostT **)costs)[arcrow][arccol].negweight-cost0; + }else{ + *negcostptr=-cost0; + } + + /* done */ + return; +} + + +/* function: CalcCostL1BiDir() + * --------------------------- + * Calculates the L1 arc cost given an array of bidirectional cost weights. + */ +void CalcCostL1BiDir(void **costs, long flow, long arcrow, long arccol, + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ + + long newflow, cost0; + + /* L1-norm */ + if(flow>0){ + cost0=((bidircostT **)costs)[arcrow][arccol].posweight*flow; + }else{ + cost0=-((bidircostT **)costs)[arcrow][arccol].negweight*flow; + } + newflow=flow+nflow; + if(newflow>0){ + *poscostptr=(((bidircostT **)costs)[arcrow][arccol].posweight*newflow + -cost0); + }else{ + *poscostptr=(-((bidircostT **)costs)[arcrow][arccol].negweight*newflow + -cost0); + } + newflow=flow-nflow; + if(newflow>0){ + *negcostptr=(((bidircostT **)costs)[arcrow][arccol].posweight*newflow + -cost0); + }else{ + *negcostptr=(-((bidircostT **)costs)[arcrow][arccol].negweight*newflow + -cost0); + } + + /* done */ + return; + +} + + +/* function: CalcCostL2BiDir() + * --------------------------- + * Calculates the L2 arc cost given an array of bidirectional cost weights. + */ +void CalcCostL2BiDir(void **costs, long flow, long arcrow, long arccol, + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ + + long newflow, cost0; + + /* L2-norm */ + if(flow>0){ + cost0=((bidircostT **)costs)[arcrow][arccol].posweight*flow*flow; + }else{ + cost0=((bidircostT **)costs)[arcrow][arccol].negweight*flow*flow; + } + newflow=flow+nflow; + if(newflow>0){ + *poscostptr=(((bidircostT **)costs)[arcrow][arccol].posweight + *newflow*newflow-cost0); + }else{ + *poscostptr=(((bidircostT **)costs)[arcrow][arccol].negweight + *newflow*newflow-cost0); + } + newflow=flow-nflow; + if(newflow>0){ + *negcostptr=(((bidircostT **)costs)[arcrow][arccol].posweight + *newflow*newflow-cost0); + }else{ + *negcostptr=(((bidircostT **)costs)[arcrow][arccol].negweight + *newflow*newflow-cost0); + } + + /* done */ + return; +} + + +/* function: CalcCostLPBiDir() + * --------------------------- + * Calculates the Lp arc cost given an array of bidirectional cost weights. + */ +void CalcCostLPBiDir(void **costs, long flow, long arcrow, long arccol, + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ + + long newflow; + double p, cost0; + + /* Lp-norm */ + p=params->p; + if(flow>0){ + cost0=((bidircostT **)costs)[arcrow][arccol].posweight*pow(flow,p); + }else{ + cost0=((bidircostT **)costs)[arcrow][arccol].negweight*pow(-flow,p); + } + newflow=flow+nflow; + if(newflow>0){ + *poscostptr=LRound(((bidircostT **)costs)[arcrow][arccol].posweight + *pow(newflow,p)-cost0); + }else{ + *poscostptr=LRound(((bidircostT **)costs)[arcrow][arccol].negweight + *pow(newflow,p)-cost0); + } + newflow=flow-nflow; + if(newflow>0){ + *negcostptr=LRound(((bidircostT **)costs)[arcrow][arccol].posweight + *pow(newflow,p)-cost0); + }else{ + *negcostptr=LRound(((bidircostT **)costs)[arcrow][arccol].negweight + *pow(newflow,p)-cost0); + } + + /* done */ + return; } /* function: CalcCostNonGrid() * --------------------------- * Calculates the arc cost given an array of long integer cost lookup tables. + * + * The cost array for each arc gives the cost for +/-flowmax units of + * flow around the flow value with minimum cost, which is not + * necessarily flow == 0. The offset between the flow value with + * minimum cost and flow == 0 is given by arroffset = costarr[0]. + * Positive flow values k for k = 1 to flowmax relative to this min + * cost flow value are in costarr[k]. Negative flow values k relative + * to the min cost flow from k = -1 to -flowmax costarr[flowmax-k]. + * costarr[2*flowmax+1] contains a scaling factor for extrapolating + * beyond the ends of the cost table, assuming quadratically (with an offset) + * increasing cost (subject to rounding and scaling). + * + * As of summer 2019, the rationale for how seconeary costs are + * extrapolated beyond the end of the table has been lost to time, but + * the logic at least does give a self-consistent cost function that + * is continuous at +/-flowmax and quadratically increases beyond, + * albeit not necessarily with a starting slope that has an easily + * intuitive basis. */ void CalcCostNonGrid(void **costs, long flow, long arcrow, long arccol, - long nflow, long nrow, paramT *params, - long *poscostptr, long *negcostptr){ + long nflow, long nrow, paramT *params, + long *poscostptr, long *negcostptr){ long xflow, flowmax, poscost, negcost, nflowsq, arroffset, sumsigsqinv; long abscost0; long *costarr; - float c1; + double c1; /* set up */ @@ -1893,10 +2396,10 @@ void CalcCostNonGrid(void **costs, long flow, long arcrow, long arccol, /* compute cost of current flow */ xflow=flow+arroffset; if(xflow>flowmax){ - c1=costarr[flowmax]/(float )flowmax-sumsigsqinv*flowmax; + c1=costarr[flowmax]/(double )flowmax-sumsigsqinv*flowmax; abscost0=(sumsigsqinv*xflow+LRound(c1))*xflow; }else if(xflow<-flowmax){ - c1=costarr[2*flowmax]/(float )flowmax-sumsigsqinv*flowmax; + c1=costarr[2*flowmax]/(double )flowmax-sumsigsqinv*flowmax; abscost0=(sumsigsqinv*xflow+LRound(c1))*xflow; }else{ if(xflow>0){ @@ -1911,10 +2414,10 @@ void CalcCostNonGrid(void **costs, long flow, long arcrow, long arccol, /* compute costs of positive and negative flow increments */ xflow=flow+arroffset+nflow; if(xflow>flowmax){ - c1=costarr[flowmax]/(float )flowmax-sumsigsqinv*flowmax; + c1=costarr[flowmax]/(double )flowmax-sumsigsqinv*flowmax; poscost=((sumsigsqinv*xflow+LRound(c1))*xflow)-abscost0; }else if(xflow<-flowmax){ - c1=costarr[2*flowmax]/(float )flowmax-sumsigsqinv*flowmax; + c1=costarr[2*flowmax]/(double )flowmax-sumsigsqinv*flowmax; poscost=((sumsigsqinv*xflow+LRound(c1))*xflow)-abscost0; }else{ if(xflow>0){ @@ -1927,10 +2430,10 @@ void CalcCostNonGrid(void **costs, long flow, long arcrow, long arccol, } xflow=flow+arroffset-nflow; if(xflow>flowmax){ - c1=costarr[flowmax]/(float )flowmax-sumsigsqinv*flowmax; + c1=costarr[flowmax]/(double )flowmax-sumsigsqinv*flowmax; negcost=((sumsigsqinv*xflow+LRound(c1))*xflow)-abscost0; }else if(xflow<-flowmax){ - c1=costarr[2*flowmax]/(float )flowmax-sumsigsqinv*flowmax; + c1=costarr[2*flowmax]/(double )flowmax-sumsigsqinv*flowmax; negcost=((sumsigsqinv*xflow+LRound(c1))*xflow)-abscost0; }else{ if(xflow>0){ @@ -1945,16 +2448,19 @@ void CalcCostNonGrid(void **costs, long flow, long arcrow, long arccol, /* scale for this flow increment and set output values */ nflowsq=nflow*nflow; if(poscost>0){ - *poscostptr=(long )ceil((float )poscost/nflowsq); + *poscostptr=(long )ceil((double )poscost/nflowsq); }else{ - *poscostptr=(long )floor((float )poscost/nflowsq); + *poscostptr=(long )floor((double )poscost/nflowsq); } if(negcost>0){ - *negcostptr=(long )ceil((float )negcost/nflowsq); + *negcostptr=(long )ceil((double )negcost/nflowsq); }else{ - *negcostptr=(long )floor((float )negcost/nflowsq); + *negcostptr=(long )floor((double )negcost/nflowsq); } + /* done */ + return; + } @@ -1963,13 +2469,20 @@ void CalcCostNonGrid(void **costs, long flow, long arcrow, long arccol, * Calculates topography arc cost given an array of cost data structures. */ long EvalCostTopo(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params){ + long nrow, paramT *params){ long idz1, cost1, dzmax; costT *cost; /* get arc info */ cost=&((costT **)(costs))[arcrow][arccol]; + + /* just return 0 if we have zero cost arc */ + if(cost->sigsq==LARGESHORT){ + return(0); + } + + /* compute argument to cost function */ if(arcrowsigsq==LARGESHORT){ + return(0); + } + + /* compute argument to cost function */ idz1=labs(flows[arcrow][arccol]*(params->nshortcycle)+cost->offset); /* calculate and return cost */ @@ -2035,13 +2555,20 @@ long EvalCostDefo(void **costs, short **flows, long arcrow, long arccol, * smoothcost data structures. */ long EvalCostSmooth(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params){ + long nrow, paramT *params){ long idz1; smoothcostT *cost; /* get arc info */ cost=&((smoothcostT **)(costs))[arcrow][arccol]; + + /* just return 0 if we have zero cost arc */ + if(cost->sigsq==LARGESHORT){ + return(0); + } + + /* compute argument to cost function */ idz1=labs(flows[arcrow][arccol]*(params->nshortcycle)+cost->offset); /* calculate and return cost */ @@ -2055,7 +2582,7 @@ long EvalCostSmooth(void **costs, short **flows, long arcrow, long arccol, * Calculates the L0 arc cost given an array of cost data structures. */ long EvalCostL0(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params){ + long nrow, paramT *params){ /* L0-norm */ if(flows[arcrow][arccol]){ @@ -2071,10 +2598,11 @@ long EvalCostL0(void **costs, short **flows, long arcrow, long arccol, * Calculates the L1 arc cost given an array of cost data structures. */ long EvalCostL1(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params){ + long nrow, paramT *params){ /* L1-norm */ - return( (((short **)costs)[arcrow][arccol]) * labs(flows[arcrow][arccol]) ); + return((long )((((short **)costs)[arcrow][arccol]) + *labs(flows[arcrow][arccol]))); } @@ -2083,11 +2611,11 @@ long EvalCostL1(void **costs, short **flows, long arcrow, long arccol, * Calculates the L2 arc cost given an array of cost data structures. */ long EvalCostL2(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params){ + long nrow, paramT *params){ /* L2-norm */ - return( (((short **)costs)[arcrow][arccol]) * - (flows[arcrow][arccol]*flows[arcrow][arccol]) ); + return((long )((((short **)costs)[arcrow][arccol]) + *(flows[arcrow][arccol]*flows[arcrow][arccol]))); } @@ -2096,11 +2624,83 @@ long EvalCostL2(void **costs, short **flows, long arcrow, long arccol, * Calculates the Lp arc cost given an array of cost data structures. */ long EvalCostLP(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params){ + long nrow, paramT *params){ + + /* Lp-norm */ + return(LRound((((short **)costs)[arcrow][arccol]) * + pow(labs(flows[arcrow][arccol]),params->p))); +} + + +/* function: EvalCostL0BiDir() + * --------------------------- + * Calculates the L0 arc cost given an array of bidirectional cost structures. + */ +long EvalCostL0BiDir(void **costs, short **flows, long arcrow, long arccol, + long nrow, paramT *params){ + + /* L0-norm */ + if(flows[arcrow][arccol]>0){ + return((long )((bidircostT **)costs)[arcrow][arccol].posweight); + }else if(flows[arcrow][arccol]<0){ + return((long )((bidircostT **)costs)[arcrow][arccol].negweight); + }else{ + return(0); + } +} + + +/* function: EvalCostL1BiDir() + * --------------------------- + * Calculates the L1 arc cost given an array of bidirectional cost structures. + */ +long EvalCostL1BiDir(void **costs, short **flows, long arcrow, long arccol, + long nrow, paramT *params){ + + /* L1-norm */ + if(flows[arcrow][arccol]>0){ + return((long )((((bidircostT **)costs)[arcrow][arccol].posweight) + *(flows[arcrow][arccol]))); + }else{ + return((long )((((bidircostT **)costs)[arcrow][arccol].negweight) + *(-flows[arcrow][arccol]))); + } +} + + +/* function: EvalCostL2BiDir() + * --------------------------- + * Calculates the L2 arc cost given an array of bidirectional cost structures. + */ +long EvalCostL2BiDir(void **costs, short **flows, long arcrow, long arccol, + long nrow, paramT *params){ + + /* L2-norm */ + if(flows[arcrow][arccol]>0){ + return((long )((((bidircostT **)costs)[arcrow][arccol].posweight) + *(flows[arcrow][arccol]*flows[arcrow][arccol]))); + }else{ + return((long )((((bidircostT **)costs)[arcrow][arccol].negweight) + *(flows[arcrow][arccol]*flows[arcrow][arccol]))); + } +} + + +/* function: EvalCostLPBiDir() + * --------------------------- + * Calculates the Lp arc cost given an array of bidirectional cost structures. + */ +long EvalCostLPBiDir(void **costs, short **flows, long arcrow, long arccol, + long nrow, paramT *params){ /* Lp-norm */ - return( (((short **)costs)[arcrow][arccol]) * - pow(labs(flows[arcrow][arccol]),params->p) ); + if(flows[arcrow][arccol]>0){ + return(LRound((((bidircostT **)costs)[arcrow][arccol].posweight) + *pow(flows[arcrow][arccol],params->p))); + }else{ + return(LRound((((bidircostT **)costs)[arcrow][arccol].posweight) + *pow(-flows[arcrow][arccol],params->p))); + } } @@ -2109,11 +2709,11 @@ long EvalCostLP(void **costs, short **flows, long arcrow, long arccol, * Calculates the arc cost given an array of long integer cost lookup tables. */ long EvalCostNonGrid(void **costs, short **flows, long arcrow, long arccol, - long nrow, paramT *params){ + long nrow, paramT *params){ long flow, xflow, flowmax, arroffset, sumsigsqinv; long *costarr; - float c1; + double c1; /* set up */ flow=flows[arcrow][arccol]; @@ -2130,10 +2730,10 @@ long EvalCostNonGrid(void **costs, short **flows, long arcrow, long arccol, /* compute cost of current flow */ xflow=flow+arroffset; if(xflow>flowmax){ - c1=costarr[flowmax]/(float )flowmax-sumsigsqinv*flowmax; + c1=costarr[flowmax]/(double )flowmax-sumsigsqinv*flowmax; return((sumsigsqinv*xflow+LRound(c1))*xflow); }else if(xflow<-flowmax){ - c1=costarr[2*flowmax]/(float )flowmax-sumsigsqinv*flowmax; + c1=costarr[2*flowmax]/(double )flowmax-sumsigsqinv*flowmax; return((sumsigsqinv*xflow+LRound(c1))*xflow); }else{ if(xflow>0){ @@ -2152,7 +2752,8 @@ long EvalCostNonGrid(void **costs, short **flows, long arcrow, long arccol, * Calculates the maximum flow magnitude to allow in the initialization * by examining the dzmax members of arc statistical cost data structures. */ -void CalcInitMaxFlow(paramT *params, void **costs, long nrow, long ncol){ +static +int CalcInitMaxFlow(paramT *params, void **costs, long nrow, long ncol){ long row, col, maxcol, initmaxflow, arcmaxflow; @@ -2161,28 +2762,29 @@ void CalcInitMaxFlow(paramT *params, void **costs, long nrow, long ncol){ params->initmaxflow=NOSTATINITMAXFLOW; }else{ if(params->costmode==TOPO || params->costmode==DEFO){ - initmaxflow=0; - for(row=0;row<2*nrow-1;row++){ - if(rownshortcycle) - +params->arcmaxflowconst); - if(arcmaxflow>initmaxflow){ - initmaxflow=arcmaxflow; - } - } - } - } - params->initmaxflow=initmaxflow; + initmaxflow=0; + for(row=0;row<2*nrow-1;row++){ + if(rownshortcycle) + +params->arcmaxflowconst); + if(arcmaxflow>initmaxflow){ + initmaxflow=arcmaxflow; + } + } + } + } + params->initmaxflow=initmaxflow; }else{ - params->initmaxflow=DEF_INITMAXFLOW; + params->initmaxflow=DEF_INITMAXFLOW; } } } + return(0); } diff --git a/contrib/Snaphu/src/snaphu_cs2.c b/contrib/Snaphu/src/snaphu_cs2.c index 42777421..76891a0c 100644 --- a/contrib/Snaphu/src/snaphu_cs2.c +++ b/contrib/Snaphu/src/snaphu_cs2.c @@ -143,7 +143,7 @@ {\ for ( ; excq_first != NULL; excq_first = excq_last )\ {\ - excq_last = excq_first -> q_next;\ + excq_last = excq_first -> q_next;\ excq_first -> q_next = sentinel_node;\ }\ } @@ -233,17 +233,17 @@ if ( i == ( b -> p_first ) )\ {\ if (n_bad_pricein + n_bad_relabel == 0) \ {\ - cut_off_factor = CUT_OFF_COEF2 * pow ( (double)n, CUT_OFF_POWER2 );\ + cut_off_factor = CUT_OFF_COEF2 * pow ( (double)n, CUT_OFF_POWER2 );\ cut_off_factor = GREATEROF ( cut_off_factor, CUT_OFF_MIN );\ cut_off = cut_off_factor * epsilon;\ cut_on = cut_off * CUT_OFF_GAP;\ }\ else\ {\ - cut_off_factor *= CUT_OFF_INCREASE;\ + cut_off_factor *= CUT_OFF_INCREASE;\ cut_off = cut_off_factor * epsilon;\ cut_on = cut_off * CUT_OFF_GAP;\ - }\ + }\ } #define TIME_FOR_UPDATE \ @@ -285,10 +285,10 @@ if ( a != b )\ \ if ( a != sb )\ {\ - b -> sister = sa;\ - a -> sister = sb;\ - sa -> sister = b;\ - sb -> sister = a;\ + b -> sister = sa;\ + a -> sister = sb;\ + sa -> sister = b;\ + sb -> sister = a;\ }\ \ d_cap = cap[a-arcs];\ @@ -340,7 +340,7 @@ double epsilon, /* optimality bound */ dn, /* cost multiplier - number of nodes + 1 */ mmc, /* multiplied maximal cost */ cut_off_factor, /* multiplier to produce cut_on and cut_off - from n and epsilon */ + from n and epsilon */ cut_on, /* the bound for returning suspended arcs */ cut_off; /* the bound for suspending arcs */ @@ -351,11 +351,11 @@ long n_rel, /* number of relabels from last price update */ n_src; /* current number of nodes with excess */ int flag_price = 0, /* if = 1 - signal to start price-in ASAP - - maybe there is infeasibility because of - susoended arcs */ + maybe there is infeasibility because of + susoended arcs */ flag_updt = 0; /* if = 1 - update failed some sources are - unreachable: either the problem is - unfeasible or you have to return + unreachable: either the problem is + unfeasible or you have to return suspended arcs */ long empty_push_bound; /* maximal possible number of zero pushes @@ -509,35 +509,35 @@ FOR_ALL_ARCS_a_FROM_i if ( OPEN ( ra ) ) { - j = a -> head; - j_rank = j -> rank; - - if ( j_rank > i_rank ) - { - if ( ( rc = REDUCED_COST ( j, i, ra ) ) < 0 ) - j_new_rank = i_rank; - else - { - dr = rc / epsilon; - j_new_rank = ( dr < dlinf ) ? i_rank + (long)dr + 1 - : linf; - } - - if ( j_rank > j_new_rank ) - { - j -> rank = j_new_rank; - j -> current = ra; - - if ( j_rank < linf ) - { - b_old = buckets + j_rank; - REMOVE_FROM_BUCKET ( j, b_old ) - } - - b_new = buckets + j_new_rank; - INSERT_TO_BUCKET ( j, b_new ) - } - } + j = a -> head; + j_rank = j -> rank; + + if ( j_rank > i_rank ) + { + if ( ( rc = REDUCED_COST ( j, i, ra ) ) < 0 ) + j_new_rank = i_rank; + else + { + dr = rc / epsilon; + j_new_rank = ( dr < dlinf ) ? i_rank + (long)dr + 1 + : linf; + } + + if ( j_rank > j_new_rank ) + { + j -> rank = j_new_rank; + j -> current = ra; + + if ( j_rank < linf ) + { + b_old = buckets + j_rank; + REMOVE_FROM_BUCKET ( j, b_old ) + } + + b_new = buckets + j_new_rank; + INSERT_TO_BUCKET ( j, b_new ) + } + } } } /* end of scanning arcs */ @@ -566,8 +566,8 @@ FOR_ALL_NODES_i if ( i -> excess < 0 ) { - INSERT_TO_BUCKET ( i, buckets ); - i -> rank = 0; + INSERT_TO_BUCKET ( i, buckets ); + i -> rank = 0; } else { @@ -585,15 +585,15 @@ for ( b = buckets; b != l_bucket; b ++ ) while ( NONEMPTY_BUCKET ( b ) ) { - GET_FROM_BUCKET ( i, b ) + GET_FROM_BUCKET ( i, b ) - up_node_scan ( i ); + up_node_scan ( i ); - if ( i -> excess > 0 ) - { - remain -= (double)(i -> excess); + if ( i -> excess > 0 ) + { + remain -= (double)(i -> excess); if ( remain <= 0 ) break; - } + } } /* end of scanning the bucket */ @@ -613,10 +613,10 @@ FOR_ALL_NODES_i if ( i -> rank >= 0 ) { if ( i -> rank < linf ) - REMOVE_FROM_BUCKET ( i, (buckets + i -> rank) ); + REMOVE_FROM_BUCKET ( i, (buckets + i -> rank) ); if ( i -> price > price_min ) - i -> price -= dp; + i -> price -= dp; } } @@ -648,18 +648,18 @@ for ( ) { if ( OPEN ( a ) - && - ( ( dp = ( ( a -> head ) -> price ) - dn*( a -> cost ) ) > p_max ) + && + ( ( dp = ( ( a -> head ) -> price ) - dn*( a -> cost ) ) > p_max ) ) { - if ( i_price < dp ) - { - i -> current = a; - return ( 1 ); - } - - p_max = dp; - a_max = a; + if ( i_price < dp ) + { + i -> current = a; + return ( 1 ); + } + + p_max = dp; + a_max = a; } } /* 1/2 arcs are scanned */ @@ -671,18 +671,18 @@ for ( ) { if ( OPEN ( a ) - && - ( ( dp = ( ( a -> head ) -> price ) - dn*( a -> cost ) ) > p_max ) + && + ( ( dp = ( ( a -> head ) -> price ) - dn*( a -> cost ) ) > p_max ) ) { - if ( i_price < dp ) - { - i -> current = a; - return ( 1 ); - } - - p_max = dp; - a_max = a; + if ( i_price < dp ) + { + i -> current = a; + return ( 1 ); + } + + p_max = dp; + a_max = a; } } /* 2/2 arcs are scanned */ @@ -697,25 +697,25 @@ else { /* node can't be relabelled */ if ( i -> suspended == i -> first ) { - if ( i -> excess == 0 ) - { - i -> price = price_min; - } - else - { - if ( n_ref == 1 ) - { - err_end ( UNFEASIBLE ); - } - else - { - err_end ( PRICE_OFL ); - } - } + if ( i -> excess == 0 ) + { + i -> price = price_min; + } + else + { + if ( n_ref == 1 ) + { + err_end ( UNFEASIBLE ); + } + else + { + err_end ( PRICE_OFL ); + } + } } else /* node can't be relabelled because of suspended arcs */ { - flag_price = 1; + flag_price = 1; } } @@ -770,36 +770,36 @@ while ( 1 ) { b = j -> current; if ( ADMISSIBLE ( j, b -> head, b ) || relabel ( j ) ) - { /* exit from j exists */ + { /* exit from j exists */ - df = LESSEROF ( i -> excess, a -> r_cap ); - if (j_exc == 0) n_src++; - INCREASE_FLOW ( i, j, a, df ) + df = LESSEROF ( i -> excess, a -> r_cap ); + if (j_exc == 0) n_src++; + INCREASE_FLOW ( i, j, a, df ) n_push ++; - if ( OUT_OF_EXCESS_Q ( j ) ) - { - INSERT_TO_EXCESS_Q ( j ); - } - } + if ( OUT_OF_EXCESS_Q ( j ) ) + { + INSERT_TO_EXCESS_Q ( j ); + } + } else - { - /* push back */ - ra = a -> sister; - df = LESSEROF ( j -> excess, ra -> r_cap ); - if ( df > 0 ) - { - INCREASE_FLOW ( j, i, ra, df ); - if (j->excess == 0) n_src--; + { + /* push back */ + ra = a -> sister; + df = LESSEROF ( j -> excess, ra -> r_cap ); + if ( df > 0 ) + { + INCREASE_FLOW ( j, i, ra, df ); + if (j->excess == 0) n_src--; n_push ++; - } - - if ( empty_push ++ >= empty_push_bound ) - { - flag_price = 1; - return; - } - } + } + + if ( empty_push ++ >= empty_push_bound ) + { + flag_price = 1; + return; + } + } } else /* j_exc < 0 */ { @@ -808,17 +808,17 @@ n_push ++; n_push ++; if ( j -> excess >= 0 ) - { - if ( j -> excess > 0 ) - { + { + if ( j -> excess > 0 ) + { n_src++; - relabel ( j ); - INSERT_TO_EXCESS_Q ( j ); - } - total_excess += j_exc; - } + relabel ( j ); + INSERT_TO_EXCESS_Q ( j ); + } + total_excess += j_exc; + } else - total_excess -= df; + total_excess -= df; } @@ -852,7 +852,7 @@ arc *a, /* current arc from i */ double rc; /* reduced cost */ int n_in_bad, /* number of priced_in arcs with - negative reduced cost */ + negative reduced cost */ bad_found; /* if 1 we are at the second scan if 0 we are at the first scan */ @@ -870,40 +870,40 @@ FOR_ALL_NODES_i for ( a = ( i -> first ) - 1, a_stop = ( i -> suspended ) - 1; a != a_stop; a -- ) { - rc = REDUCED_COST ( i, a -> head, a ); + rc = REDUCED_COST ( i, a -> head, a ); - if ( (rc < 0) && ( a -> r_cap > 0) ) - { /* bad case */ - if ( bad_found == 0 ) - { - bad_found = 1; - UPDATE_CUT_OFF; - goto restart; + if ( (rc < 0) && ( a -> r_cap > 0) ) + { /* bad case */ + if ( bad_found == 0 ) + { + bad_found = 1; + UPDATE_CUT_OFF; + goto restart; - } - df = a -> r_cap; - INCREASE_FLOW ( i, a -> head, a, df ); + } + df = a -> r_cap; + INCREASE_FLOW ( i, a -> head, a, df ); ra = a -> sister; - j = a -> head; - - b = -- ( i -> first ); - EXCHANGE ( a, b ); - - if ( SUSPENDED ( j, ra ) ) - { - rb = -- ( j -> first ); - EXCHANGE ( ra, rb ); - } - - n_in_bad ++; - } - else - if ( ( rc < cut_on ) && ( rc > -cut_on ) ) - { - b = -- ( i -> first ); - EXCHANGE ( a, b ); - } + j = a -> head; + + b = -- ( i -> first ); + EXCHANGE ( a, b ); + + if ( SUSPENDED ( j, ra ) ) + { + rb = -- ( j -> first ); + EXCHANGE ( ra, rb ); + } + + n_in_bad ++; + } + else + if ( ( rc < cut_on ) && ( rc > -cut_on ) ) + { + b = -- ( i -> first ); + EXCHANGE ( a, b ); + } } } @@ -918,16 +918,16 @@ if ( n_in_bad != 0 ) RESET_EXCESS_Q; FOR_ALL_NODES_i - { - i -> current = i -> first; - i_exc = i -> excess; - if ( i_exc > 0 ) - { /* i is a source */ - total_excess += i_exc; - n_src++; - INSERT_TO_EXCESS_Q ( i ); - } - } + { + i -> current = i -> first; + i_exc = i -> excess; + if ( i_exc > 0 ) + { /* i is a source */ + total_excess += i_exc; + n_src++; + INSERT_TO_EXCESS_Q ( i ); + } + } INSERT_TO_EXCESS_Q ( dummy_node ); } @@ -979,9 +979,9 @@ FOR_ALL_NODES_i i_exc = i -> excess; if ( i_exc > 0 ) { /* i is a source */ - total_excess += i_exc; + total_excess += i_exc; n_src++; - INSERT_TO_EXCESS_Q ( i ) + INSERT_TO_EXCESS_Q ( i ) } } @@ -994,12 +994,12 @@ while ( 1 ) { if ( EMPTY_EXCESS_Q ) { - if ( n_ref > PRICE_OUT_START ) - { - price_in (); - } - - if ( EMPTY_EXCESS_Q ) break; + if ( n_ref > PRICE_OUT_START ) + { + price_in (); + } + + if ( EMPTY_EXCESS_Q ) break; } REMOVE_FROM_EXCESS_Q ( i ); @@ -1011,51 +1011,51 @@ while ( 1 ) discharge ( i ); if ( TIME_FOR_UPDATE || flag_price ) - { - if ( i -> excess > 0 ) - { - INSERT_TO_EXCESS_Q ( i ); - } - - if ( flag_price && ( n_ref > PRICE_OUT_START ) ) - { - pr_in_int = 0; - price_in (); - flag_price = 0; - } - - price_update(); - - while ( flag_updt ) - { - if ( n_ref == 1 ) - { - err_end ( UNFEASIBLE ); - } - else - { - flag_updt = 0; - UPDATE_CUT_OFF; - n_bad_relabel++; - - pr_in_int = 0; - price_in (); - - price_update (); - } - } - - n_rel = 0; - - if ( n_ref > PRICE_OUT_START && - (pr_in_int ++ > time_for_price_in) - ) - { - pr_in_int = 0; - price_in (); - } - - } /* time for update */ + { + if ( i -> excess > 0 ) + { + INSERT_TO_EXCESS_Q ( i ); + } + + if ( flag_price && ( n_ref > PRICE_OUT_START ) ) + { + pr_in_int = 0; + price_in (); + flag_price = 0; + } + + price_update(); + + while ( flag_updt ) + { + if ( n_ref == 1 ) + { + err_end ( UNFEASIBLE ); + } + else + { + flag_updt = 0; + UPDATE_CUT_OFF; + n_bad_relabel++; + + pr_in_int = 0; + price_in (); + + price_update (); + } + } + + n_rel = 0; + + if ( n_ref > PRICE_OUT_START && + (pr_in_int ++ > time_for_price_in) + ) + { + pr_in_int = 0; + price_in (); + } + + } /* time for update */ } } /* end of main loop */ @@ -1093,7 +1093,7 @@ int cc; /* return code: 1 - flow is epsilon optimal long df; /* cycle capacity */ int nnc, /* number of negative cycles cancelled during - one iteration */ + one iteration */ snc; /* total number of negative cycle cancelled */ n_prefine ++; @@ -1130,89 +1130,89 @@ FOR_ALL_NODES_i /* deapth first search */ while ( 1 ) { - i -> inp = GREY; - - /* scanning arcs from node i starting from current */ - FOR_ALL_CURRENT_ARCS_a_FROM_i - { - if ( OPEN ( a ) ) - { - j = a -> head; - if ( REDUCED_COST ( i, j, a ) < 0 ) - { - if ( j -> inp == WHITE ) - { /* fresh node - step forward */ - i -> current = a; - j -> b_next = i; - i = j; - a = j -> current; + i -> inp = GREY; + + /* scanning arcs from node i starting from current */ + FOR_ALL_CURRENT_ARCS_a_FROM_i + { + if ( OPEN ( a ) ) + { + j = a -> head; + if ( REDUCED_COST ( i, j, a ) < 0 ) + { + if ( j -> inp == WHITE ) + { /* fresh node - step forward */ + i -> current = a; + j -> b_next = i; + i = j; + a = j -> current; a_stop = (j+1) -> suspended; - break; - } - - if ( j -> inp == GREY ) - { /* cycle detected */ - cc = 0; - nnc++; - - i -> current = a; - is = ir = i; - df = BIGGEST_FLOW; - - while ( 1 ) - { - ar = ir -> current; - if ( ar -> r_cap <= df ) - { - df = ar -> r_cap; - is = ir; - } - if ( ir == j ) break; - ir = ir -> b_next; - } - - - ir = i; - - while ( 1 ) - { - ar = ir -> current; - INCREASE_FLOW( ir, ar -> head, ar, df) - - if ( ir == j ) break; - ir = ir -> b_next; - } - - - if ( is != i ) - { - for ( ir = i; ir != is; ir = ir -> b_next ) - ir -> inp = WHITE; - - i = is; - a = (is -> current) + 1; + break; + } + + if ( j -> inp == GREY ) + { /* cycle detected */ + cc = 0; + nnc++; + + i -> current = a; + is = ir = i; + df = BIGGEST_FLOW; + + while ( 1 ) + { + ar = ir -> current; + if ( ar -> r_cap <= df ) + { + df = ar -> r_cap; + is = ir; + } + if ( ir == j ) break; + ir = ir -> b_next; + } + + + ir = i; + + while ( 1 ) + { + ar = ir -> current; + INCREASE_FLOW( ir, ar -> head, ar, df) + + if ( ir == j ) break; + ir = ir -> b_next; + } + + + if ( is != i ) + { + for ( ir = i; ir != is; ir = ir -> b_next ) + ir -> inp = WHITE; + + i = is; + a = (is -> current) + 1; a_stop = (is+1) -> suspended; - break; - } - - } - } - /* if j-color is BLACK - continue search from i */ - } - } /* all arcs from i are scanned */ - - if ( a == a_stop ) - { - /* step back */ - i -> inp = BLACK; + break; + } + + } + } + /* if j-color is BLACK - continue search from i */ + } + } /* all arcs from i are scanned */ + + if ( a == a_stop ) + { + /* step back */ + i -> inp = BLACK; n_prscan1++; - j = i -> b_next; - STACKQ_PUSH ( i ); + j = i -> b_next; + STACKQ_PUSH ( i ); - if ( j == NULL ) break; - i = j; - i -> current ++; - } + if ( j == NULL ) break; + i = j; + i -> current ++; + } } /* end of deapth first search */ } /* all nodes are scanned */ @@ -1236,29 +1236,29 @@ n_prscan2++; i_rank = i -> rank; FOR_ALL_ARCS_a_FROM_i { - if ( OPEN ( a ) ) - { - j = a -> head; - rc = REDUCED_COST ( i, j, a ); - - - if ( rc < 0 ) /* admissible arc */ - { - dr = ( - rc - 0.5 ) / epsilon; - if (( j_rank = dr + i_rank ) < dlinf ) - { - if ( j_rank > j -> rank ) - j -> rank = j_rank; - } - } - } + if ( OPEN ( a ) ) + { + j = a -> head; + rc = REDUCED_COST ( i, j, a ); + + + if ( rc < 0 ) /* admissible arc */ + { + dr = ( - rc - 0.5 ) / epsilon; + if (( j_rank = dr + i_rank ) < dlinf ) + { + if ( j_rank > j -> rank ) + j -> rank = j_rank; + } + } + } } /* all arcs from i are scanned */ if ( i_rank > 0 ) { - if ( i_rank > bmax ) bmax = i_rank; - b = buckets + i_rank; - INSERT_TO_BUCKET ( i, b ) + if ( i_rank > bmax ) bmax = i_rank; + b = buckets + i_rank; + INSERT_TO_BUCKET ( i, b ) } } /* end of while-cycle: all nodes are scanned - longest distancess are computed */ @@ -1274,53 +1274,53 @@ for ( b = buckets + bmax; b != buckets; b -- ) while ( NONEMPTY_BUCKET( b ) ) { - GET_FROM_BUCKET ( i, b ); - - n_prscan++; - FOR_ALL_ARCS_a_FROM_i - { - if ( OPEN ( a ) ) - { - j = a -> head; - j_rank = j -> rank; - if ( j_rank < i_rank ) - { - rc = REDUCED_COST ( i, j, a ); + GET_FROM_BUCKET ( i, b ); + + n_prscan++; + FOR_ALL_ARCS_a_FROM_i + { + if ( OPEN ( a ) ) + { + j = a -> head; + j_rank = j -> rank; + if ( j_rank < i_rank ) + { + rc = REDUCED_COST ( i, j, a ); - if ( rc < 0 ) - j_new_rank = i_rank; - else - { - dr = rc / epsilon; - j_new_rank = ( dr < dlinf ) ? i_rank - ( (long)dr + 1 ) - : 0; - } - if ( j_rank < j_new_rank ) - { - if ( cc == 1 ) - { - j -> rank = j_new_rank; - - if ( j_rank > 0 ) - { - b_old = buckets + j_rank; - REMOVE_FROM_BUCKET ( j, b_old ) - } - - b_new = buckets + j_new_rank; - INSERT_TO_BUCKET ( j, b_new ) - } - else - { - df = a -> r_cap; - INCREASE_FLOW ( i, j, a, df ) - } - } - } - } /* end if opened arc */ - } /* all arcs are scanned */ - - i -> price -= dp; + if ( rc < 0 ) + j_new_rank = i_rank; + else + { + dr = rc / epsilon; + j_new_rank = ( dr < dlinf ) ? i_rank - ( (long)dr + 1 ) + : 0; + } + if ( j_rank < j_new_rank ) + { + if ( cc == 1 ) + { + j -> rank = j_new_rank; + + if ( j_rank > 0 ) + { + b_old = buckets + j_rank; + REMOVE_FROM_BUCKET ( j, b_old ) + } + + b_new = buckets + j_new_rank; + INSERT_TO_BUCKET ( j, b_new ) + } + else + { + df = a -> r_cap; + INCREASE_FLOW ( i, j, a, df ) + } + } + } + } /* end if opened arc */ + } /* all arcs are scanned */ + + i -> price -= dp; } /* end of while-cycle: the bucket is scanned */ } /* end of for-cycle: all buckets are scanned */ @@ -1339,13 +1339,13 @@ FOR_ALL_NODES_i { FOR_ALL_ARCS_a_FROM_i { - if ( REDUCED_COST ( i, a -> head, a ) < -epsilon ) - { - if ( ( df = a -> r_cap ) > 0 ) - { - INCREASE_FLOW ( i, a -> head, a, df ) - } - } + if ( REDUCED_COST ( i, a -> head, a ) < -epsilon ) + { + if ( ( df = a -> r_cap ) > 0 ) + { + INCREASE_FLOW ( i, a -> head, a, df ) + } + } } } @@ -1411,47 +1411,47 @@ FOR_ALL_NODES_i /* deapth first search */ while ( 1 ) { - i -> inp = GREY; - - /* scanning arcs from node i */ - FOR_ALL_ARCS_a_FROM_i - { - if ( OPEN ( a ) ) - { - j = a -> head; - if ( REDUCED_COST ( i, j, a ) < 0 ) - { - if ( j -> inp == WHITE ) - { /* fresh node - step forward */ - i -> current = a; - j -> b_next = i; - i = j; - a = j -> current; + i -> inp = GREY; + + /* scanning arcs from node i */ + FOR_ALL_ARCS_a_FROM_i + { + if ( OPEN ( a ) ) + { + j = a -> head; + if ( REDUCED_COST ( i, j, a ) < 0 ) + { + if ( j -> inp == WHITE ) + { /* fresh node - step forward */ + i -> current = a; + j -> b_next = i; + i = j; + a = j -> current; a_stop = (j+1) -> suspended; - break; - } - - if ( j -> inp == GREY ) - { /* cycle detected; should not happen */ - cc = 0; - } - } - /* if j-color is BLACK - continue search from i */ - } - } /* all arcs from i are scanned */ - - if ( a == a_stop ) - { - /* step back */ - i -> inp = BLACK; - n_prscan1++; - j = i -> b_next; - STACKQ_PUSH ( i ); - - if ( j == NULL ) break; - i = j; - i -> current ++; - } + break; + } + + if ( j -> inp == GREY ) + { /* cycle detected; should not happen */ + cc = 0; + } + } + /* if j-color is BLACK - continue search from i */ + } + } /* all arcs from i are scanned */ + + if ( a == a_stop ) + { + /* step back */ + i -> inp = BLACK; + n_prscan1++; + j = i -> b_next; + STACKQ_PUSH ( i ); + + if ( j == NULL ) break; + i = j; + i -> current ++; + } } /* end of deapth first search */ } /* all nodes are scanned */ @@ -1470,29 +1470,29 @@ while ( NONEMPTY_STACKQ ) i_rank = i -> rank; FOR_ALL_ARCS_a_FROM_i { - if ( OPEN ( a ) ) - { - j = a -> head; - rc = REDUCED_COST ( i, j, a ); - - - if ( rc < 0 ) /* admissible arc */ - { - dr = - rc; - if (( j_rank = dr + i_rank ) < dlinf ) - { - if ( j_rank > j -> rank ) - j -> rank = j_rank; - } - } - } + if ( OPEN ( a ) ) + { + j = a -> head; + rc = REDUCED_COST ( i, j, a ); + + + if ( rc < 0 ) /* admissible arc */ + { + dr = - rc; + if (( j_rank = dr + i_rank ) < dlinf ) + { + if ( j_rank > j -> rank ) + j -> rank = j_rank; + } + } + } } /* all arcs from i are scanned */ if ( i_rank > 0 ) { - if ( i_rank > bmax ) bmax = i_rank; - b = buckets + i_rank; - INSERT_TO_BUCKET ( i, b ) + if ( i_rank > bmax ) bmax = i_rank; + b = buckets + i_rank; + INSERT_TO_BUCKET ( i, b ) } } /* end of while-cycle: all nodes are scanned - longest distancess are computed */ @@ -1508,48 +1508,48 @@ for ( b = buckets + bmax; b != buckets; b -- ) while ( NONEMPTY_BUCKET( b ) ) { - GET_FROM_BUCKET ( i, b ) - - n_prscan++; - FOR_ALL_ARCS_a_FROM_i - { - if ( OPEN ( a ) ) - { - j = a -> head; - j_rank = j -> rank; - if ( j_rank < i_rank ) - { - rc = REDUCED_COST ( i, j, a ); + GET_FROM_BUCKET ( i, b ) + + n_prscan++; + FOR_ALL_ARCS_a_FROM_i + { + if ( OPEN ( a ) ) + { + j = a -> head; + j_rank = j -> rank; + if ( j_rank < i_rank ) + { + rc = REDUCED_COST ( i, j, a ); - if ( rc < 0 ) - j_new_rank = i_rank; - else - { - dr = rc; - j_new_rank = ( dr < dlinf ) ? i_rank - ( (long)dr + 1 ) - : 0; - } - if ( j_rank < j_new_rank ) - { - if ( cc == 1 ) - { - j -> rank = j_new_rank; - - if ( j_rank > 0 ) - { - b_old = buckets + j_rank; - REMOVE_FROM_BUCKET ( j, b_old ) - } - - b_new = buckets + j_new_rank; - INSERT_TO_BUCKET ( j, b_new ) - } - } - } - } /* end if opened arc */ - } /* all arcs are scanned */ - - i -> price -= dp; + if ( rc < 0 ) + j_new_rank = i_rank; + else + { + dr = rc; + j_new_rank = ( dr < dlinf ) ? i_rank - ( (long)dr + 1 ) + : 0; + } + if ( j_rank < j_new_rank ) + { + if ( cc == 1 ) + { + j -> rank = j_new_rank; + + if ( j_rank > 0 ) + { + b_old = buckets + j_rank; + REMOVE_FROM_BUCKET ( j, b_old ) + } + + b_new = buckets + j_new_rank; + INSERT_TO_BUCKET ( j, b_new ) + } + } + } + } /* end if opened arc */ + } /* all arcs are scanned */ + + i -> price -= dp; } /* end of while-cycle: the bucket is scanned */ } /* end of for-cycle: all buckets are scanned */ @@ -1581,17 +1581,17 @@ FOR_ALL_NODES_i { FOR_ALL_ARCS_a_FROM_i { - rc = REDUCED_COST ( i, a -> head, a ); + rc = REDUCED_COST ( i, a -> head, a ); - if (((rc > cut_off) && (CLOSED(a -> sister))) + if (((rc > cut_off) && (CLOSED(a -> sister))) || ((rc < n_cut_off) && (CLOSED(a))) ) - { /* suspend the arc */ - b = ( i -> first ) ++ ; + { /* suspend the arc */ + b = ( i -> first ) ++ ; - EXCHANGE ( a, b ); - } + EXCHANGE ( a, b ); + } } } @@ -1635,7 +1635,7 @@ for ( a = arcs, na = 0; a != sentinel_arc ; a ++, na ++ ) cs = a -> cost; if ( cap[na] > 0 && ( flow = cap[na] - (a -> r_cap) ) != 0 ) - obj_internal += cs * (double) flow; + obj_internal += cs * (double) flow; /* a -> cost = cs; */ } @@ -1658,12 +1658,12 @@ for ( a = arcs, na = 0; a != sentinel_arc ; a ++, na ++ ) /* for ( a = arcs; a != sentinel_arc ; a ++ ) */ /* { */ /* if ( a -> r_cap > 0 && a -> cost < 0 ) */ -/* { */ -/* df = a -> r_cap; */ -/* i = ( a -> sister ) -> head; */ +/* { */ +/* df = a -> r_cap; */ +/* i = ( a -> sister ) -> head; */ /* j = a -> head; */ -/* INCREASE_FLOW ( i, j, a, df ); */ -/* } */ +/* INCREASE_FLOW ( i, j, a, df ); */ +/* } */ /* } */ /* } */ @@ -1677,7 +1677,7 @@ for ( a = arcs, na = 0; a != sentinel_arc ; a ++, na ++ ) /* FOR_ALL_NODES_i */ /* FOR_ALL_ARCS_a_FROM_i */ /* if (OPEN(a) && (REDUCED_COST(i, a->head, a) < 0)) */ -/* assert(0); */ +/* assert(0); */ /* return(1); */ /* } */ @@ -1710,7 +1710,7 @@ do{ /* scaling loop */ if ( n_ref >= PRICE_OUT_START ) { - price_out ( ); + price_out ( ); } if ( update_epsilon () ) break; @@ -1719,14 +1719,14 @@ do{ /* scaling loop */ { if ( ! price_refine () ) break; - if ( n_ref >= PRICE_OUT_START ) - { - if ( price_in () ) - { - break; - } - } - if ((cc = update_epsilon ())) break; + if ( n_ref >= PRICE_OUT_START ) + { + if ( price_in () ) + { + break; + } + } + if ((cc = update_epsilon ())) break; } } while ( cc == 0 ); @@ -1739,7 +1739,7 @@ finishup ( obj_ad ); /* SolveCS2-- formerly main() */ void SolveCS2(signed char **residue, short **mstcosts, long nrow, long ncol, - long cs2scalefactor, short ***flowsptr) + long cs2scalefactor, short ***flowsptr) { /* double t; */ @@ -1756,8 +1756,6 @@ void SolveCS2(signed char **residue, short **mstcosts, long nrow, long ncol, double cost, c_max; short *cap; /* cap changed to short by CWC */ - long row_index, col_index; /* report out-of-bounds index by Cunren, 18-aug-2020 */ - short **rowcost, **colcost; short **rowflow, **colflow; @@ -1771,7 +1769,7 @@ void SolveCS2(signed char **residue, short **mstcosts, long nrow, long ncol, colcost=&(mstcosts[nrow-1]); f_sc=cs2scalefactor; cs2mcfparse( residue,rowcost,colcost,nNrow,nNcol, - &n,&m,&ndp,&arp,&nmin,&c_max,&cap ); + &n,&m,&ndp,&arp,&nmin,&c_max,&cap ); /* free memory that is no longer needed */ Free2DArray((void **)residue,nrow-1); @@ -1787,7 +1785,7 @@ void SolveCS2(signed char **residue, short **mstcosts, long nrow, long ncol, /* get memory for flow arrays */ (*flowsptr)=(short **)Get2DRowColZeroMem(nrow,ncol, - sizeof(short *),sizeof(short)); + sizeof(short *),sizeof(short)); rowflow=(*flowsptr); colflow=&((*flowsptr)[nrow-1]); @@ -1800,95 +1798,55 @@ void SolveCS2(signed char **residue, short **mstcosts, long nrow, long ncol, /* if finite (non-zero) flow */ if ( cap[ N_ARC (a) ] > 0 && (cap[ N_ARC (a) ] - ( a -> r_cap ) ) ){ - - /* get to, from nodes and flow amount */ - from=ni; - to=N_NODE( a -> head ); - flow=cap[ N_ARC (a) ] - ( a -> r_cap ); + + /* get to, from nodes and flow amount */ + from=ni; + to=N_NODE( a -> head ); + flow=cap[ N_ARC (a) ] - ( a -> r_cap ); - if(flow>LARGESHORT || flow<-LARGESHORT){ - fprintf(sp0,"Flow will overflow short data type\nAbort\n"); - exit(ABNORMAL_EXIT); - } + if(flow>LARGESHORT || flow<-LARGESHORT){ + fprintf(sp0,"Flow will overflow short data type\nAbort\n"); + exit(ABNORMAL_EXIT); + } /* node indices are indexed from 1, not 0 */ /* node indices are in column major order, not row major */ /* handle flow to/from ground first */ if((from==ground) || (to==ground)){ - if(to==ground){ - num=to; - to=from; - from=num; - flow=-flow; - } - if(!((to-1) % nNrow)){ - row_index = 0; - col_index = (int )((to-1)/nNrow); - if (0 <= row_index && row_index <= nrow-1 && 0 <= col_index && col_index <= ncol-2) - colflow[row_index][col_index]+=flow; - else - fprintf(sp0,"Warning: out-of-bounds index in computing flow\n"); - }else if(to<=nNrow){ - row_index = to-1; - col_index = 0; - if (0 <= row_index && row_index <= nrow-2 && 0 <= col_index && col_index <= ncol-1) - rowflow[row_index][col_index]+=flow; - else - fprintf(sp0,"Warning: out-of-bounds index in computing flow\n"); - }else if(to>=(ground-nNrow-1)){ - row_index = (to-1) % nNrow; - col_index = nNcol; - if (0 <= row_index && row_index <= nrow-2 && 0 <= col_index && col_index <= ncol-1) - rowflow[row_index][col_index]-=flow; - else - fprintf(sp0,"Warning: out-of-bounds index in computing flow\n"); - }else if(!(to % nNrow)){ - row_index = nNrow; - col_index = (int )((to/nNrow)-1); - if (0 <= row_index && row_index <= nrow-1 && 0 <= col_index && col_index <= ncol-2) - colflow[row_index][col_index]-=flow; - else - fprintf(sp0,"Warning: out-of-bounds index in computing flow\n"); - }else{ - fprintf(sp0,"Unassigned ground arc parsing cs2 solution\nAbort\n"); - exit(ABNORMAL_EXIT); - } + if(to==ground){ + num=to; + to=from; + from=num; + flow=-flow; + } + if(!((to-1) % nNrow)){ + colflow[0][(int )((to-1)/nNrow)]+=flow; + }else if(to<=nNrow){ + rowflow[to-1][0]+=flow; + }else if(to>=(ground-nNrow-1)){ + rowflow[(to-1) % nNrow][nNcol]-=flow; + }else if(!(to % nNrow)){ + colflow[nNrow][(int )((to/nNrow)-1)]-=flow; + }else{ + fprintf(sp0,"Unassigned ground arc parsing cs2 solution\nAbort\n"); + exit(ABNORMAL_EXIT); + } }else if(from==(to+1)){ - num=from+(int )((from-1)/nNrow); - row_index = (num-1) % (nNrow+1); - col_index = (int )(num-1)/(nNrow+1); - if (0 <= row_index && row_index <= nrow-1 && 0 <= col_index && col_index <= ncol-2) - colflow[row_index][col_index]-=flow; - else - fprintf(sp0,"Warning: out-of-bounds index in computing flow\n"); - }else if(from==(to-1)){ - num=from+(int )((from-1)/nNrow)+1; - row_index = (num-1) % (nNrow+1); - col_index = (int )(num-1)/(nNrow+1); - if (0 <= row_index && row_index <= nrow-1 && 0 <= col_index && col_index <= ncol-2) - colflow[row_index][col_index]+=flow; - else - fprintf(sp0,"Warning: out-of-bounds index in computing flow\n"); - }else if(from==(to-nNrow)){ - num=from+nNrow; - row_index = (num-1) % nNrow; - col_index = (int )((num-1)/nNrow); - if (0 <= row_index && row_index <= nrow-2 && 0 <= col_index && col_index <= ncol-1) - rowflow[row_index][col_index]+=flow; - else - fprintf(sp0,"Warning: out-of-bounds index in computing flow\n"); - }else if(from==(to+nNrow)){ - num=from; - row_index = (num-1) % nNrow; - col_index = (int )((num-1)/nNrow); - if (0 <= row_index && row_index <= nrow-2 && 0 <= col_index && col_index <= ncol-1) - rowflow[row_index][col_index]-=flow; - else - fprintf(sp0,"Warning: out-of-bounds index in computing flow\n"); - }else{ - fprintf(sp0,"Non-grid arc parsing cs2 solution\nAbort\n"); - exit(ABNORMAL_EXIT); - } + num=from+(int )((from-1)/nNrow); + colflow[(num-1) % (nNrow+1)][(int )(num-1)/(nNrow+1)]-=flow; + }else if(from==(to-1)){ + num=from+(int )((from-1)/nNrow)+1; + colflow[(num-1) % (nNrow+1)][(int )(num-1)/(nNrow+1)]+=flow; + }else if(from==(to-nNrow)){ + num=from+nNrow; + rowflow[(num-1) % nNrow][(int )((num-1)/nNrow)]+=flow; + }else if(from==(to+nNrow)){ + num=from; + rowflow[(num-1) % nNrow][(int )((num-1)/nNrow)]-=flow; + }else{ + fprintf(sp0,"Non-grid arc parsing cs2 solution\nAbort\n"); + exit(ABNORMAL_EXIT); + } } /* end if flow on arc */ } /* end for loop over arcs of node */ diff --git a/contrib/Snaphu/src/snaphu_cs2parse.c b/contrib/Snaphu/src/snaphu_cs2parse.c index 4c13a1ad..31985b49 100644 --- a/contrib/Snaphu/src/snaphu_cs2parse.c +++ b/contrib/Snaphu/src/snaphu_cs2parse.c @@ -192,12 +192,12 @@ arc_first= (long*) CAlloc ( n+2, sizeof(long) ); for ( in = nodes; in <= nodes + n; in ++ ) in -> excess = 0; - + if ( nodes == NULL || arcs == NULL || arc_first == NULL || arc_tail == NULL ) /* memory is not allocated */ { err_no = EN6; goto error; } - + /* setting pointer to the first arc */ arc_current = arcs; node_max = 0; @@ -368,53 +368,53 @@ for ( i = node_min; i < node_max; i ++ ) /* scanning all the nodes for ( arc_num = arc_first[i]; arc_num < last; arc_num ++ ) { tail = arc_tail[arc_num]; - while ( tail != i ) + while ( tail != i ) /* the arc no arc_num is not in place because arc cited here must go out from i; we'll put it to its place and continue this process until an arc in this position would go out from i */ - { arc_new_num = arc_first[tail]; - arc_current = arcs + arc_num; - arc_new = arcs + arc_new_num; - - /* arc_current must be cited in the position arc_new - swapping these arcs: */ + { arc_new_num = arc_first[tail]; + arc_current = arcs + arc_num; + arc_new = arcs + arc_new_num; + + /* arc_current must be cited in the position arc_new + swapping these arcs: */ - head_p = arc_new -> head; - arc_new -> head = arc_current -> head; - arc_current -> head = head_p; + head_p = arc_new -> head; + arc_new -> head = arc_current -> head; + arc_current -> head = head_p; - acap = cap[arc_new_num]; - cap[arc_new_num] = cap[arc_num]; - cap[arc_num] = acap; + acap = cap[arc_new_num]; + cap[arc_new_num] = cap[arc_num]; + cap[arc_num] = acap; - acap = arc_new -> r_cap; - arc_new -> r_cap = arc_current -> r_cap; - arc_current -> r_cap = acap; + acap = arc_new -> r_cap; + arc_new -> r_cap = arc_current -> r_cap; + arc_current -> r_cap = acap; - dcost = arc_new -> cost; - arc_new -> cost = arc_current -> cost; - arc_current -> cost = dcost; + dcost = arc_new -> cost; + arc_new -> cost = arc_current -> cost; + arc_current -> cost = dcost; - if ( arc_new != arc_current -> sister ) - { - arc_tmp = arc_new -> sister; - arc_new -> sister = arc_current -> sister; - arc_current -> sister = arc_tmp; + if ( arc_new != arc_current -> sister ) + { + arc_tmp = arc_new -> sister; + arc_new -> sister = arc_current -> sister; + arc_current -> sister = arc_tmp; ( arc_current -> sister ) -> sister = arc_current; - ( arc_new -> sister ) -> sister = arc_new; - } + ( arc_new -> sister ) -> sister = arc_new; + } - arc_tail[arc_num] = arc_tail[arc_new_num]; - arc_tail[arc_new_num] = tail; + arc_tail[arc_num] = arc_tail[arc_new_num]; + arc_tail[arc_new_num] = tail; - /* we increase arc_first[tail] */ - arc_first[tail] ++ ; + /* we increase arc_first[tail] */ + arc_first[tail] ++ ; tail = arc_tail[arc_num]; - } + } } /* all arcs outgoing from i are in place */ } @@ -430,10 +430,10 @@ for ( ndp = nodes + node_min; ndp <= nodes + node_max; ndp ++ ) for ( arc_current = ndp -> first; arc_current != (ndp+1) -> first; arc_current ++ ) { - arc_num = arc_current - arcs; - if ( cap[arc_num] > 0 ) cap_out += cap[arc_num]; - if ( cap[arc_num] == 0 ) - cap_in += cap[( arc_current -> sister )-arcs]; + arc_num = arc_current - arcs; + if ( cap[arc_num] > 0 ) cap_out += cap[arc_num]; + if ( cap[arc_num] == 0 ) + cap_in += cap[( arc_current -> sister )-arcs]; } /* diff --git a/contrib/Snaphu/src/snaphu_io.c b/contrib/Snaphu/src/snaphu_io.c index 8fa2bbd7..796f17d3 100644 --- a/contrib/Snaphu/src/snaphu_io.c +++ b/contrib/Snaphu/src/snaphu_io.c @@ -1,7 +1,6 @@ /************************************************************************* snaphu input/output source file - Written by Curtis W. Chen Copyright 2002 Board of Trustees, Leland Stanford Jr. University Please see the supporting documentation for terms of use. @@ -22,19 +21,45 @@ #include #include #include +#include #include #include #include "snaphu.h" +/* static (local) function prototypes */ +static +int ParseConfigLine(char *buf, char *conffile, long nlines, + infileT *infiles, outfileT *outfiles, + long *linelenptr, paramT *params); +static +int LogStringParam(FILE *fp, char *key, char *value); +static +int LogBoolParam(FILE *fp, char *key, signed char boolvalue); +static +int LogFileFormat(FILE *fp, char *key, signed char fileformat); +static +int WriteAltLineFile(float **mag, float **phase, char *outfile, + long nrow, long ncol); +static +int WriteAltSampFile(float **arr1, float **arr2, char *outfile, + long nrow, long ncol); + + + /* function: SetDefaults() * ----------------------- * Sets all parameters to their initial default values. */ -void SetDefaults(infileT *infiles, outfileT *outfiles, paramT *params){ +int SetDefaults(infileT *infiles, outfileT *outfiles, paramT *params){ + /* initialize to all zero to start for extra robustness */ + memset(infiles,0,sizeof(infileT)); + memset(outfiles,0,sizeof(outfileT)); + memset(params,0,sizeof(paramT)); + /* input files */ StrNCopy(infiles->weightfile,DEF_WEIGHTFILE,MAXSTRLEN); StrNCopy(infiles->corrfile,DEF_CORRFILE,MAXSTRLEN); @@ -43,6 +68,8 @@ void SetDefaults(infileT *infiles, outfileT *outfiles, paramT *params){ StrNCopy(infiles->estfile,DEF_ESTFILE,MAXSTRLEN); StrNCopy(infiles->magfile,DEF_MAGFILE,MAXSTRLEN); StrNCopy(infiles->costinfile,DEF_COSTINFILE,MAXSTRLEN); + StrNCopy(infiles->bytemaskfile,DEF_BYTEMASKFILE,MAXSTRLEN); + StrNCopy(infiles->dotilemaskfile,DEF_DOTILEMASKFILE,MAXSTRLEN); /* output and dump files */ StrNCopy(outfiles->initfile,DEF_INITFILE,MAXSTRLEN); @@ -141,6 +168,8 @@ void SetDefaults(infileT *infiles, outfileT *outfiles, paramT *params){ /* algorithm parameters */ params->flipphasesign=DEF_FLIPPHASESIGN; + params->onetilereopt=DEF_ONETILEREOPT; + params->rmtileinit=DEF_RMTILEINIT; params->initmaxflow=DEF_INITMAXFLOW; params->arcmaxflowconst=DEF_ARCMAXFLOWCONST; params->maxflow=DEF_MAXFLOW; @@ -158,13 +187,21 @@ void SetDefaults(infileT *infiles, outfileT *outfiles, paramT *params){ params->srcrow=DEF_SRCROW; params->srccol=DEF_SRCCOL; params->p=DEF_P; + params->bidirlpn=DEF_BIDIRLPN; params->nshortcycle=DEF_NSHORTCYCLE; params->maxnewnodeconst=DEF_MAXNEWNODECONST; params->maxcyclefraction=DEF_MAXCYCLEFRACTION; - params->sourcemode=DEF_SOURCEMODE; + params->nconnnodemin=DEF_NCONNNODEMIN; params->maxnflowcycles=DEF_MAXNFLOWCYCLES; params->dumpall=DEF_DUMPALL; params->cs2scalefactor=DEF_CS2SCALEFACTOR; + params->nmajorprune=DEF_NMAJORPRUNE; + params->prunecostthresh=DEF_PRUNECOSTTHRESH; + params->edgemasktop=DEF_EDGEMASKTOP; + params->edgemaskbot=DEF_EDGEMASKBOT; + params->edgemaskleft=DEF_EDGEMASKLEFT; + params->edgemaskright=DEF_EDGEMASKRIGHT; + params->parentpid=(long )getpid(); /* tile parameters */ params->ntilerow=DEF_NTILEROW; @@ -179,6 +216,7 @@ void SetDefaults(infileT *infiles, outfileT *outfiles, paramT *params){ params->minregionsize=DEF_MINREGIONSIZE; params->nthreads=DEF_NTHREADS; params->scndryarcflowmax=DEF_SCNDRYARCFLOWMAX; + StrNCopy(params->tiledir,DEF_TILEDIR,MAXSTRLEN); params->assembleonly=DEF_ASSEMBLEONLY; params->rmtmptile=DEF_RMTMPTILE; params->tileedgeweight=DEF_TILEEDGEWEIGHT; @@ -187,6 +225,10 @@ void SetDefaults(infileT *infiles, outfileT *outfiles, paramT *params){ params->minconncompfrac=DEF_MINCONNCOMPFRAC; params->conncompthresh=DEF_CONNCOMPTHRESH; params->maxncomps=DEF_MAXNCOMPS; + params->conncompouttype=DEF_CONNCOMPOUTTYPE; + + /* done */ + return(0); } @@ -195,8 +237,8 @@ void SetDefaults(infileT *infiles, outfileT *outfiles, paramT *params){ * ----------------------- * Parses command line inputs passed to main(). */ -void ProcessArgs(int argc, char *argv[], infileT *infiles, outfileT *outfiles, - long *linelenptr, paramT *params){ +int ProcessArgs(int argc, char *argv[], infileT *infiles, outfileT *outfiles, + long *linelenptr, paramT *params){ long i,j; signed char noarg_exit; @@ -215,265 +257,305 @@ void ProcessArgs(int argc, char *argv[], infileT *infiles, outfileT *outfiles, /* if argument is an option */ if(argv[i][0]=='-'){ if(strlen(argv[i])==1){ - fprintf(sp0,"invalid command line argument -\n"); - exit(ABNORMAL_EXIT); + fflush(NULL); + fprintf(sp0,"invalid command line argument -\n"); + exit(ABNORMAL_EXIT); }else if(argv[i][1]!='-'){ - for(j=1;junwrapped=TRUE; - }else if(argv[i][j]=='t'){ - params->costmode=TOPO; - }else if(argv[i][j]=='d'){ - params->costmode=DEFO; - }else if(argv[i][j]=='s'){ - params->costmode=SMOOTH; - params->defomax=0.0; - }else if(argv[i][j]=='q'){ - params->eval=TRUE; - params->unwrapped=TRUE; - }else if(argv[i][j]=='f'){ - if(++ioutfile,argv[i],MAXSTRLEN); - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='c'){ - if(++icorrfile,argv[i],MAXSTRLEN); - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='m'){ - if(++imagfile,argv[i],MAXSTRLEN); - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='a'){ - if(++iampfile,argv[i],MAXSTRLEN); - params->amplitude=TRUE; - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='A'){ - if(++iampfile,argv[i],MAXSTRLEN); - params->amplitude=FALSE; - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='e'){ - if(++iestfile,argv[i],MAXSTRLEN); - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='w'){ - if(++iweightfile,argv[i],MAXSTRLEN); - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='g'){ - if(++iconncompfile,argv[i],MAXSTRLEN); - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='G'){ - params->regrowconncomps=TRUE; - if(++iconncompfile,argv[i],MAXSTRLEN); - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='b'){ - if(++ibperp)) || !(params->bperp)){ - fprintf(sp0,"option -%c requires non-zero decimal argument\n", - argv[i-1][j]); - exit(ABNORMAL_EXIT); - } - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='p'){ - if(++ip))){ - fprintf(sp0,"option -%c requires decimal argument\n", - argv[i-1][j]); - exit(ABNORMAL_EXIT); - } - break; - }else{ - noarg_exit=TRUE; - } - }else if(argv[i][j]=='i'){ - params->initonly=TRUE; - }else if(argv[i][j]=='n'){ - params->costmode=NOSTATCOSTS; - }else if(argv[i][j]=='v'){ - params->verbose=TRUE; - }else if(argv[i][j]=='l'){ - if(++ilogfile,argv[i],MAXSTRLEN); - break; - }else{ - noarg_exit=TRUE; - } - }else{ - fprintf(sp0,"unrecognized option -%c\n",argv[i][j]); - exit(ABNORMAL_EXIT); - } - if(noarg_exit){ - fprintf(sp0,"option -%c requires an argument\n",argv[i-1][j]); - exit(ABNORMAL_EXIT); - } - } + for(j=1;junwrapped=TRUE; + }else if(argv[i][j]=='t'){ + params->costmode=TOPO; + }else if(argv[i][j]=='d'){ + params->costmode=DEFO; + }else if(argv[i][j]=='s'){ + params->costmode=SMOOTH; + params->defomax=0.0; + }else if(argv[i][j]=='q'){ + params->eval=TRUE; + params->unwrapped=TRUE; + }else if(argv[i][j]=='C'){ + if(++ioutfile,argv[i],MAXSTRLEN); + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='c'){ + if(++icorrfile,argv[i],MAXSTRLEN); + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='m'){ + if(++imagfile,argv[i],MAXSTRLEN); + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='M'){ + if(++ibytemaskfile,argv[i],MAXSTRLEN); + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='a'){ + if(++iampfile,argv[i],MAXSTRLEN); + params->amplitude=TRUE; + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='A'){ + if(++iampfile,argv[i],MAXSTRLEN); + params->amplitude=FALSE; + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='e'){ + if(++iestfile,argv[i],MAXSTRLEN); + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='w'){ + if(++iweightfile,argv[i],MAXSTRLEN); + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='g'){ + if(++iconncompfile,argv[i],MAXSTRLEN); + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='G'){ + params->regrowconncomps=TRUE; + if(++iconncompfile,argv[i],MAXSTRLEN); + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='b'){ + if(++ibperp)) || !(params->bperp)){ + fflush(NULL); + fprintf(sp0,"option -%c requires non-zero decimal argument\n", + argv[i-1][j]); + exit(ABNORMAL_EXIT); + } + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='p'){ + if(++ip))){ + fflush(NULL); + fprintf(sp0,"option -%c requires decimal argument\n", + argv[i-1][j]); + exit(ABNORMAL_EXIT); + } + break; + }else{ + noarg_exit=TRUE; + } + }else if(argv[i][j]=='i'){ + params->initonly=TRUE; + }else if(argv[i][j]=='S'){ + params->onetilereopt=TRUE; + }else if(argv[i][j]=='k'){ + params->rmtmptile=FALSE; + params->rmtileinit=FALSE; + }else if(argv[i][j]=='n'){ + params->costmode=NOSTATCOSTS; + }else if(argv[i][j]=='v'){ + params->verbose=TRUE; + }else if(argv[i][j]=='l'){ + if(++ilogfile,argv[i],MAXSTRLEN); + break; + }else{ + noarg_exit=TRUE; + } + }else{ + fflush(NULL); + fprintf(sp0,"unrecognized option -%c\n",argv[i][j]); + exit(ABNORMAL_EXIT); + } + if(noarg_exit){ + fflush(NULL); + fprintf(sp0,"option -%c requires an argument\n",argv[i-1][j]); + exit(ABNORMAL_EXIT); + } + } }else{ - /* argument is a "--" option */ - if(!strcmp(argv[i],"--costinfile")){ - if(++icostinfile,argv[i],MAXSTRLEN); - }else{ - noarg_exit=TRUE; - } - }else if(!strcmp(argv[i],"--costoutfile")){ - if(++icostoutfile,argv[i],MAXSTRLEN); - }else{ - noarg_exit=TRUE; - } - }else if(!strcmp(argv[i],"--debug") || !strcmp(argv[i],"--dumpall")){ - params->dumpall=TRUE; - }else if(!strcmp(argv[i],"--mst")){ - params->initmethod=MSTINIT; - }else if(!strcmp(argv[i],"--mcf")){ - params->initmethod=MCFINIT; - }else if(!strcmp(argv[i],"--aa")){ - if(i+2ampfile,argv[++i],MAXSTRLEN); - StrNCopy(infiles->ampfile2,argv[++i],MAXSTRLEN); - infiles->ampfileformat=FLOAT_DATA; - params->amplitude=TRUE; - }else{ - noarg_exit=TRUE; - } - }else if(!strcmp(argv[i],"--AA")){ - if(++i+1ampfile,argv[i++],MAXSTRLEN); - StrNCopy(infiles->ampfile2,argv[i],MAXSTRLEN); - infiles->ampfileformat=FLOAT_DATA; - params->amplitude=FALSE; - }else{ - noarg_exit=TRUE; - } - }else if(!strcmp(argv[i],"--tile")){ - if(++i+3ntilerow)) - || StringToLong(argv[i++],&(params->ntilecol)) - || StringToLong(argv[i++],&(params->rowovrlp)) - || StringToLong(argv[i],&(params->colovrlp))){ - fprintf(sp0,"option %s requires four integer arguments\n", - argv[i-4]); - exit(ABNORMAL_EXIT); - } - }else{ - noarg_exit=TRUE; - } - }else if(!strcmp(argv[i],"--piece")){ - if(++i+3piecefirstrow)) - || StringToLong(argv[i++],&(params->piecefirstcol)) - || StringToLong(argv[i++],&(params->piecenrow)) - || StringToLong(argv[i],&(params->piecencol))){ - fprintf(sp0,"option %s requires four integer arguments\n", - argv[i-4]); - exit(ABNORMAL_EXIT); - } - }else{ - noarg_exit=TRUE; - } - }else if(!strcmp(argv[i],"--nproc")){ - if(++inthreads))){ - fprintf(sp0,"option %s requires an integer arguemnt\n", - argv[i-1]); - exit(ABNORMAL_EXIT); - } - }else{ - noarg_exit=TRUE; - } - }else if(!strcmp(argv[i],"--assemble")){ - params->assembleonly=TRUE; - if(++itiledir,argv[i],MAXSTRLEN); - }else{ - noarg_exit=TRUE; - } - }else if(!strcmp(argv[i],"--copyright") || !strcmp(argv[i],"--info")){ - fprintf(sp1,COPYRIGHT); - exit(ABNORMAL_EXIT); - }else if(!strcmp(argv[i],"--help")){ - fprintf(sp1,OPTIONSHELPFULL); - exit(ABNORMAL_EXIT); - }else{ - fprintf(sp0,"unrecognized option %s\n",argv[i]); - exit(ABNORMAL_EXIT); - } - if(noarg_exit){ - fprintf(sp0,"incorrect number of arguments for option %s\n", - argv[i-1]); - exit(ABNORMAL_EXIT); - } + /* argument is a "--" option */ + if(!strcmp(argv[i],"--costinfile")){ + if(++icostinfile,argv[i],MAXSTRLEN); + }else{ + noarg_exit=TRUE; + } + }else if(!strcmp(argv[i],"--costoutfile")){ + if(++icostoutfile,argv[i],MAXSTRLEN); + }else{ + noarg_exit=TRUE; + } + }else if(!strcmp(argv[i],"--debug") || !strcmp(argv[i],"--dumpall")){ + params->dumpall=TRUE; + }else if(!strcmp(argv[i],"--mst")){ + params->initmethod=MSTINIT; + }else if(!strcmp(argv[i],"--mcf")){ + params->initmethod=MCFINIT; + }else if(!strcmp(argv[i],"--aa")){ + if(i+2ampfile,argv[++i],MAXSTRLEN); + StrNCopy(infiles->ampfile2,argv[++i],MAXSTRLEN); + infiles->ampfileformat=FLOAT_DATA; + params->amplitude=TRUE; + }else{ + noarg_exit=TRUE; + } + }else if(!strcmp(argv[i],"--AA")){ + if(++i+1ampfile,argv[i++],MAXSTRLEN); + StrNCopy(infiles->ampfile2,argv[i],MAXSTRLEN); + infiles->ampfileformat=FLOAT_DATA; + params->amplitude=FALSE; + }else{ + noarg_exit=TRUE; + } + }else if(!strcmp(argv[i],"--tile")){ + if(++i+3ntilerow)) + || StringToLong(argv[i++],&(params->ntilecol)) + || StringToLong(argv[i++],&(params->rowovrlp)) + || StringToLong(argv[i],&(params->colovrlp))){ + fflush(NULL); + fprintf(sp0,"option %s requires four integer arguments\n", + argv[i-4]); + exit(ABNORMAL_EXIT); + } + }else{ + noarg_exit=TRUE; + } + }else if(!strcmp(argv[i],"--piece")){ + if(++i+3piecefirstrow)) + || StringToLong(argv[i++],&(params->piecefirstcol)) + || StringToLong(argv[i++],&(params->piecenrow)) + || StringToLong(argv[i],&(params->piecencol))){ + fflush(NULL); + fprintf(sp0,"option %s requires four integer arguments\n", + argv[i-4]); + exit(ABNORMAL_EXIT); + } + }else{ + noarg_exit=TRUE; + } + }else if(!strcmp(argv[i],"--nproc")){ + if(++inthreads))){ + fflush(NULL); + fprintf(sp0,"option %s requires an integer arguemnt\n", + argv[i-1]); + exit(ABNORMAL_EXIT); + } + }else{ + noarg_exit=TRUE; + } + }else if(!strcmp(argv[i],"--tiledir")){ + if(++itiledir,argv[i],MAXSTRLEN); + }else{ + noarg_exit=TRUE; + } + }else if(!strcmp(argv[i],"--assemble")){ + params->assembleonly=TRUE; + }else if(!strcmp(argv[i],"--copyright") || !strcmp(argv[i],"--info")){ + fprintf(sp1,COPYRIGHT); + exit(ABNORMAL_EXIT); + }else if(!strcmp(argv[i],"--help")){ + fflush(NULL); + fprintf(sp1,OPTIONSHELPFULL); + exit(ABNORMAL_EXIT); + }else{ + fflush(NULL); + fprintf(sp0,"unrecognized option %s\n",argv[i]); + exit(ABNORMAL_EXIT); + } + if(noarg_exit){ + fflush(NULL); + fprintf(sp0,"incorrect number of arguments for option %s\n", + argv[i-1]); + exit(ABNORMAL_EXIT); + } } }else{ /* argument is not an option */ if(!strlen(infiles->infile)){ StrNCopy(infiles->infile,argv[i],MAXSTRLEN); }else if(*linelenptr==0){ - if(StringToLong(argv[i],linelenptr) || *linelenptr<=0){ - fprintf(sp0,"line length must be positive integer\n"); - exit(ABNORMAL_EXIT); - } + if(StringToLong(argv[i],linelenptr) || *linelenptr<=0){ + fflush(NULL); + fprintf(sp0,"line length must be positive integer\n"); + exit(ABNORMAL_EXIT); + } }else{ + fflush(NULL); fprintf(sp0,"multiple input files: %s and %s\n", - infiles->infile,argv[i]); - exit(ABNORMAL_EXIT); + infiles->infile,argv[i]); + exit(ABNORMAL_EXIT); } } } /* end for loop over arguments */ /* check to make sure we have required arguments */ if(!strlen(infiles->infile) || !(*linelenptr)){ + fflush(NULL); fprintf(sp0,"not enough input arguments. type %s -h for help\n", - PROGRAMNAME); + PROGRAMNAME); exit(ABNORMAL_EXIT); } + /* done */ + return(0); + } /* end of ProcessArgs */ @@ -482,8 +564,8 @@ void ProcessArgs(int argc, char *argv[], infileT *infiles, outfileT *outfiles, * Checks all parameters to make sure they are valid. This is just a boring * function with lots of checks in it. */ -void CheckParams(infileT *infiles, outfileT *outfiles, - long linelen, long nlines, paramT *params){ +int CheckParams(infileT *infiles, outfileT *outfiles, + long linelen, long nlines, paramT *params){ long ni, nj, n; FILE *fp; @@ -491,6 +573,7 @@ void CheckParams(infileT *infiles, outfileT *outfiles, /* make sure output file is writable (try opening in append mode) */ /* file will be opened in write mode later, clobbering existing file */ if((fp=fopen(outfiles->outfile,"a"))==NULL){ + fflush(NULL); fprintf(sp0,"file %s is not writable\n",outfiles->outfile); exit(ABNORMAL_EXIT); }else{ @@ -502,30 +585,36 @@ void CheckParams(infileT *infiles, outfileT *outfiles, } if(!strcmp(outfiles->outfile,infiles->infile) && !params->eval && !params->regrowconncomps){ + fflush(NULL); fprintf(sp0,"WARNING: output will overwrite input\n"); } } /* make sure options aren't contradictory */ if(params->initonly && params->unwrapped){ + fflush(NULL); fprintf(sp0,"cannot use initialize-only mode with unwrapped input\n"); exit(ABNORMAL_EXIT); } if(params->initonly && params->p>=0){ + fflush(NULL); fprintf(sp0,"cannot use initialize-only mode with Lp costs\n"); exit(ABNORMAL_EXIT); } if(params->costmode==NOSTATCOSTS && !(params->initonly || params->p>=0)){ + fflush(NULL); fprintf(sp0,"no-statistical-costs option can only be used in\n"); fprintf(sp0," initialize-only or Lp-norm modes\n"); exit(ABNORMAL_EXIT); } if(strlen(infiles->costinfile) && params->costmode==NOSTATCOSTS){ + fflush(NULL); fprintf(sp0,"no-statistical-costs option cannot be given\n"); fprintf(sp0," if input cost file is specified\n"); exit(ABNORMAL_EXIT); } if(strlen(outfiles->costoutfile) && params->costmode==NOSTATCOSTS){ + fflush(NULL); fprintf(sp0,"no-statistical-costs option cannot be given\n"); fprintf(sp0," if output cost file is specified\n"); exit(ABNORMAL_EXIT); @@ -533,6 +622,7 @@ void CheckParams(infileT *infiles, outfileT *outfiles, /* check geometry parameters */ if(params->earthradius<=0){ + fflush(NULL); fprintf(sp0,"earth radius must be nonnegative\n"); exit(ABNORMAL_EXIT); } @@ -540,29 +630,36 @@ void CheckParams(infileT *infiles, outfileT *outfiles, if(params->altitude>0){ params->orbitradius=params->earthradius+params->altitude; }else{ + fflush(NULL); fprintf(sp0,"platform altitude must be positive\n"); exit(ABNORMAL_EXIT); } }else if(params->orbitradius < params->earthradius){ + fflush(NULL); fprintf(sp0,"platform orbit radius must be greater than earth radius\n"); exit(ABNORMAL_EXIT); } if(params->costmode==TOPO && params->baseline<0){ + fflush(NULL); fprintf(sp0,"baseline length must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->costmode==TOPO && params->baseline==0){ + fflush(NULL); fprintf(sp0,"WARNING: zero baseline may give unpredictable results\n"); } if(params->ncorrlooks<=0){ + fflush(NULL); fprintf(sp0,"number of looks ncorrlooks must be positive\n"); exit(ABNORMAL_EXIT); } if(params->nearrange<=0){ + fflush(NULL); fprintf(sp0,"slant range parameter nearrange must be positive (meters)\n"); exit(ABNORMAL_EXIT); } if(params->dr<=0 || params->da<=0){ + fflush(NULL); fprintf(sp0,"pixel spacings dr and da must be positive (meters)\n"); exit(ABNORMAL_EXIT); } @@ -570,76 +667,92 @@ void CheckParams(infileT *infiles, outfileT *outfiles, /* if(params->rangeres<=(params->dr) || params->azres<=(params->da)){ + fflush(NULL); fprintf(sp0,"resolutions parameters must be larger than pixel spacings\n"); exit(ABNORMAL_EXIT); } */ if(params->lambda<=0){ + fflush(NULL); fprintf(sp0,"wavelength lambda must be positive (meters)\n"); exit(ABNORMAL_EXIT); } /* check scattering model defaults */ if(params->kds<=0){ + fflush(NULL); fprintf(sp0,"scattering model parameter kds must be positive\n"); exit(ABNORMAL_EXIT); } if(params->specularexp<=0){ + fflush(NULL); fprintf(sp0,"scattering model parameter SPECULAREXP must be positive\n"); exit(ABNORMAL_EXIT); } if(params->dzrcritfactor<0){ + fflush(NULL); fprintf(sp0,"dzrcritfactor must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->laywidth<1){ + fflush(NULL); fprintf(sp0,"layover window width laywidth must be positive\n"); exit(ABNORMAL_EXIT); } if(params->layminei<0){ + fflush(NULL); fprintf(sp0,"layover minimum brightness must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->sloperatiofactor<0){ + fflush(NULL); fprintf(sp0,"slope ratio fudge factor must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->sigsqei<=0){ + fflush(NULL); fprintf(sp0,"intensity estimate variance must be positive\n"); exit(ABNORMAL_EXIT); } /* check decorrelation model defaults */ if(params->drho<=0){ + fflush(NULL); fprintf(sp0,"correlation step size drho must be positive\n"); exit(ABNORMAL_EXIT); } if(params->rhosconst1<=0 || params->rhosconst2<=0){ + fflush(NULL); fprintf(sp0,"parameters rhosconst1 and rhosconst2 must be positive\n"); exit(ABNORMAL_EXIT); } if(!strlen(infiles->corrfile) && (params->defaultcorr<0 || params->defaultcorr>1)){ + fflush(NULL); fprintf(sp0,"default correlation must be between 0 and 1\n"); exit(ABNORMAL_EXIT); } if(params->rhominfactor<0){ + fflush(NULL); fprintf(sp0,"parameter rhominfactor must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->ncorrlooksaz<1 || params->ncorrlooksrange<1 || params->nlooksaz<1 || params->nlooksrange<1 || params->nlooksother<1){ + fflush(NULL); fprintf(sp0,"numbers of looks must be positive integer\n"); exit(ABNORMAL_EXIT); } if(!strlen(infiles->corrfile)){ if(params->ncorrlooksaznlooksaz){ + fflush(NULL); fprintf(sp0,"NCORRLOOKSAZ cannot be smaller than NLOOKSAZ\n"); fprintf(sp0," setting NCORRLOOKSAZ to equal NLOOKSAZ\n"); params->ncorrlooksaz=params->nlooksaz; } if(params->ncorrlooksrangenlooksrange){ + fflush(NULL); fprintf(sp0,"NCORRLOOKSRANGE cannot be smaller than NLOOKSRANGE\n"); fprintf(sp0," setting NCORRLOOKSRANGE to equal NLOOKSRANGE\n"); params->ncorrlooksrange=params->nlooksrange; @@ -648,56 +761,69 @@ void CheckParams(infileT *infiles, outfileT *outfiles, /* check pdf model parameters */ if(params->azdzfactor<0){ + fflush(NULL); fprintf(sp0,"parameter azdzfactor must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->dzeifactor<0){ + fflush(NULL); fprintf(sp0,"parameter dzeifactor must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->dzeiweight<0 || params->dzeiweight>1.0){ + fflush(NULL); fprintf(sp0,"parameter dzeiweight must be between 0 and 1\n"); exit(ABNORMAL_EXIT); } if(params->dzlayfactor<0){ + fflush(NULL); fprintf(sp0,"parameter dzlayfactor must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->layconst<=0){ + fflush(NULL); fprintf(sp0,"parameter layconst must be positive\n"); exit(ABNORMAL_EXIT); } if(params->layfalloffconst<0){ + fflush(NULL); fprintf(sp0,"parameter layfalloffconst must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->sigsqshortmin<=0){ + fflush(NULL); fprintf(sp0,"parameter sigsqshortmin must be positive\n"); exit(ABNORMAL_EXIT); } if(params->sigsqlayfactor<0){ + fflush(NULL); fprintf(sp0,"parameter sigsqlayfactor must be nonnegative\n"); exit(ABNORMAL_EXIT); } /* check deformation mode parameters */ if(params->defoazdzfactor<0){ + fflush(NULL); fprintf(sp0,"parameter defoazdzfactor must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->defothreshfactor<0){ + fflush(NULL); fprintf(sp0,"parameter defothreshfactor must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->defomax<0){ + fflush(NULL); fprintf(sp0,"parameter defomax must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->sigsqcorr<0){ + fflush(NULL); fprintf(sp0,"parameter sigsqcorr must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->defolayconst<=0){ + fflush(NULL); fprintf(sp0,"parameter defolayconst must be positive\n"); exit(ABNORMAL_EXIT); } @@ -706,66 +832,86 @@ void CheckParams(infileT *infiles, outfileT *outfiles, /* be sure to check for things that will cause type overflow */ /* or floating point exception */ if((params->initmaxflow)<1 && (params->initmaxflow)!=AUTOCALCSTATMAX){ + fflush(NULL); fprintf(sp0,"initialization maximum flow must be positive\n"); exit(ABNORMAL_EXIT); } if((params->arcmaxflowconst)<1){ + fflush(NULL); fprintf(sp0,"arcmaxflowconst must be positive\n"); exit(ABNORMAL_EXIT); } if((params->maxflow)<1){ + fflush(NULL); fprintf(sp0,"maxflow must be positive\n"); exit(ABNORMAL_EXIT); } if(params->krowei<=0 || params->kcolei<=0){ + fflush(NULL); fprintf(sp0,"averaging window sizes krowei and kcolei must be positive\n"); exit(ABNORMAL_EXIT); } if(params->kperpdpsi<=0 || params->kpardpsi<=0){ + fflush(NULL); fprintf(sp0, - "averaging window sizes kperpdpsi and kpardpsi must be positive\n"); + "averaging window sizes kperpdpsi and kpardpsi must be positive\n"); exit(ABNORMAL_EXIT); } if(params->threshold<=0){ + fflush(NULL); fprintf(sp0,"numerical solver threshold must be positive\n"); exit(ABNORMAL_EXIT); } if(params->initdzr<=0){ + fflush(NULL); fprintf(sp0,"initdzr must be positive\n"); exit(ABNORMAL_EXIT); } if(params->initdzstep<=0){ + fflush(NULL); fprintf(sp0,"initdzstep must be positive\n"); exit(ABNORMAL_EXIT); } if(params->maxcost>POSSHORTRANGE || params->maxcost<=0){ + fflush(NULL); fprintf(sp0,"maxcost must be positive and within range or short int\n"); exit(ABNORMAL_EXIT); } if(params->costscale<=0){ + fflush(NULL); fprintf(sp0,"cost scale factor costscale must be positive\n"); exit(ABNORMAL_EXIT); } if(params->p<0 && params->p!=PROBCOSTP){ + fflush(NULL); fprintf(sp0,"Lp-norm parameter p should be nonnegative\n"); exit(ABNORMAL_EXIT); } - if((params->costmode==TOPO && params->maxflow*params->nshortcycle) + if(params->costmode==TOPO && (params->maxflow*params->nshortcycle) >POSSHORTRANGE){ + fflush(NULL); fprintf(sp0,"maxflow exceeds range of short int for given nshortcycle\n"); exit(ABNORMAL_EXIT); } if(params->costmode==DEFO && ceil(params->defomax*params->nshortcycle) >POSSHORTRANGE){ + fflush(NULL); fprintf(sp0,"defomax exceeds range of short int for given nshortcycle\n"); exit(ABNORMAL_EXIT); } + if(params->nshortcycle < 1 || params->nshortcycle > MAXNSHORTCYCLE){ + fflush(NULL); + fprintf(sp0,"illegal value for nshortcycle\n"); + exit(ABNORMAL_EXIT); + } if(params->maxnewnodeconst<=0 || params->maxnewnodeconst>1){ + fflush(NULL); fprintf(sp0,"maxnewnodeconst must be between 0 and 1\n"); exit(ABNORMAL_EXIT); } - if(params->sourcemode>1 || params->sourcemode<-1){ - fprintf(sp0,"sourcemode must be -1, 0, or 1\n"); + if(params->nconnnodemin<0){ + fflush(NULL); + fprintf(sp0,"nconnnodemin must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(infiles->infileformat!=FLOAT_DATA || strlen(infiles->magfile)){ @@ -775,187 +921,230 @@ void CheckParams(infileT *infiles, outfileT *outfiles, } if(params->maxnflowcycles==USEMAXCYCLEFRACTION){ params->maxnflowcycles=LRound(params->maxcyclefraction - *nlines/(double )params->ntilerow - *linelen/(double )params->ntilecol); + *nlines/(double )params->ntilerow + *linelen/(double )params->ntilecol); } if(params->initmaxflow==AUTOCALCSTATMAX && !(params->ntilerow==1 && params->ntilecol==1)){ + fflush(NULL); fprintf(sp0,"initial maximum flow cannot be calculated automatically in " - "tile mode\n"); + "tile mode\n"); exit(ABNORMAL_EXIT); } #ifdef NO_CS2 if(params->initmethod==MCFINIT && !params->unwrapped){ + fflush(NULL); fprintf(sp0,"program not compiled with cs2 MCF solver module\n"); exit(ABNORMAL_EXIT); } #endif + /* masking parameters */ + if(strlen(infiles->bytemaskfile) + || params->edgemasktop || params->edgemaskbot + || params->edgemaskleft || params->edgemaskright){ + if(params->initonly){ + fflush(NULL); + fprintf(sp0,"masking not applicable for initialize-only mode\n"); + exit(ABNORMAL_EXIT); + } + } + if(params->edgemasktop<0 || params->edgemaskbot<0 + || params->edgemaskleft<0 || params->edgemaskright<0){ + fflush(NULL); + fprintf(sp0,"edgemask parameters cannot be negative\n"); + exit(ABNORMAL_EXIT); + } + if(params->edgemasktop+params->edgemaskbot>=nlines + || params->edgemaskleft+params->edgemaskright>=linelen){ + fflush(NULL); + fprintf(sp0,"edge masks cannot exceed input array size\n"); + exit(ABNORMAL_EXIT); + } + /* tile parameters */ if(params->ntilerow<1 || params->ntilecol<1){ + fflush(NULL); fprintf(sp0,"numbers of tile rows and columns must be positive\n"); exit(ABNORMAL_EXIT); } if(params->rowovrlp<0 || params->colovrlp<0){ + fflush(NULL); fprintf(sp0,"tile overlaps must be nonnegative\n"); exit(ABNORMAL_EXIT); } if(params->ntilerow>1 || params->ntilecol>1){ ni=ceil((nlines+(params->ntilerow-1)*params->rowovrlp) - /(double )params->ntilerow); + /(double )params->ntilerow); nj=ceil((linelen+(params->ntilecol-1)*params->colovrlp) - /(double )params->ntilecol); - if(params->p>=0){ - fprintf(sp0,"tile mode not enabled for Lp costs\n"); - exit(ABNORMAL_EXIT); - } + /(double )params->ntilecol); if(params->ntilerow+params->rowovrlp > nlines || params->ntilecol+params->colovrlp > linelen || params->ntilerow*params->ntilerow > nlines || params->ntilecol*params->ntilecol > linelen){ + fflush(NULL); fprintf(sp0,"tiles too small or overlap too large for given input\n"); exit(ABNORMAL_EXIT); } if(params->minregionsize > ((nlines-(params->ntilerow-1)*(ni-params->rowovrlp)) - *(linelen-(params->ntilecol-1)*(nj-params->colovrlp)))){ + *(linelen-(params->ntilecol-1)*(nj-params->colovrlp)))){ + fflush(NULL); fprintf(sp0,"minimum region size too large for given tile parameters\n"); exit(ABNORMAL_EXIT); } if(TMPTILEOUTFORMAT!=ALT_LINE_DATA && TMPTILEOUTFORMAT!=FLOAT_DATA){ + fflush(NULL); fprintf(sp0,"unsupported TMPTILEOUTFORMAT value in complied binary\n"); exit(ABNORMAL_EXIT); } if(TMPTILEOUTFORMAT==FLOAT_DATA && outfiles->outfileformat!=FLOAT_DATA){ + fflush(NULL); fprintf(sp0,"precompiled tile format precludes given output format\n"); exit(ABNORMAL_EXIT); } if(params->scndryarcflowmax<1){ + fflush(NULL); fprintf(sp0,"parameter scndryarcflowmax too small\n"); exit(ABNORMAL_EXIT); } if(params->initonly){ + fflush(NULL); fprintf(sp0, - "initialize-only mode and tile mode are mutually exclusive\n"); - exit(ABNORMAL_EXIT); - } - if(strlen(outfiles->conncompfile)){ - fprintf(sp0, - "connected components output not yet supported for tile mode\n"); + "initialize-only mode and tile mode are mutually exclusive\n"); exit(ABNORMAL_EXIT); } if(params->assembleonly){ n=strlen(params->tiledir); while(--n>0 && params->tiledir[n]=='/'){ - params->tiledir[n]='\0'; + params->tiledir[n]='\0'; } if(!strlen(params->tiledir)){ - fprintf(sp0,"tile directory name cannot have zero length\n"); - exit(ABNORMAL_EXIT); + fflush(NULL); + fprintf(sp0,"tile directory name must be specified\n"); + exit(ABNORMAL_EXIT); } if(!strcmp(params->tiledir,"/")){ - StrNCopy(params->tiledir,"",MAXSTRLEN); + StrNCopy(params->tiledir,"",MAXSTRLEN); } + params->rmtmptile=FALSE; /* cowardly avoid removing tile dir input */ } if(params->piecefirstrow!=DEF_PIECEFIRSTROW || params->piecefirstcol!=DEF_PIECEFIRSTCOL || params->piecenrow!=DEF_PIECENROW || params->piecencol!=DEF_PIECENCOL){ + fflush(NULL); fprintf(sp0,"piece-only mode cannot be used with multiple tiles\n"); exit(ABNORMAL_EXIT); } + if(params->costmode==NOSTATCOSTS){ + fflush(NULL); + fprintf(sp0,"no-statistical-costs option cannot be used in tile mode\n"); + exit(ABNORMAL_EXIT); + } + if(params->rowovrlpcolovrlpassembleonly){ + fflush(NULL); fprintf(sp0,"assemble-only mode can only be used with multiple tiles\n"); exit(ABNORMAL_EXIT); } if(params->nthreads>1){ + fflush(NULL); fprintf(sp0,"only one tile--disregarding multiprocessor option\n"); } if(params->rowovrlp || params->colovrlp){ + fflush(NULL); fprintf(sp0,"only one tile--disregarding tile overlap values\n"); } - params->piecefirstrow--; /* index from 0 instead of 1 */ - params->piecefirstcol--; /* index from 0 instead of 1 */ - if(!params->piecenrow){ - params->piecenrow=nlines; - } - if(!params->piecencol){ - params->piecencol=linelen; - } - if(params->piecefirstrow<0 || params->piecefirstcol<0 - || params->piecenrow<1 || params->piecencol<1 - || params->piecefirstrow+params->piecenrow>nlines - || params->piecefirstcol+params->piecencol>linelen){ - fprintf(sp0,"illegal values for piece of interferogram to unwrap\n"); + if(params->onetilereopt){ + fprintf(sp0, + "cannot do single-tile reoptimization without tiling params\n"); exit(ABNORMAL_EXIT); } } if(params->nthreads<1){ + fflush(NULL); fprintf(sp0,"number of processors must be at least one\n"); exit(ABNORMAL_EXIT); }else if(params->nthreads>MAXTHREADS){ + fflush(NULL); fprintf(sp0,"number of processors exceeds precomplied limit of %d\n", - MAXTHREADS); + MAXTHREADS); + exit(ABNORMAL_EXIT); + } + + /* piece params */ + params->piecefirstrow--; /* index from 0 instead of 1 */ + params->piecefirstcol--; /* index from 0 instead of 1 */ + if(!params->piecenrow){ + params->piecenrow=nlines; + } + if(!params->piecencol){ + params->piecencol=linelen; + } + if(params->piecefirstrow<0 || params->piecefirstcol<0 + || params->piecenrow<1 || params->piecencol<1 + || params->piecefirstrow+params->piecenrow>nlines + || params->piecefirstcol+params->piecencol>linelen){ + fflush(NULL); + fprintf(sp0,"illegal values for piece of interferogram to unwrap\n"); exit(ABNORMAL_EXIT); } /* connected component parameters */ if(params->regrowconncomps){ if(!strlen(outfiles->conncompfile)){ + fflush(NULL); fprintf(sp0,"no connected component output file specified\n"); exit(ABNORMAL_EXIT); } params->unwrapped=TRUE; } if(params->minconncompfrac<0 || params->minconncompfrac>1){ + fflush(NULL); fprintf(sp0,"illegal value for minimum connected component fraction\n"); exit(ABNORMAL_EXIT); } if(params->maxncomps<=0){ - fprintf(sp0,"illegal value for maximum number of connected components\n"); + fflush(NULL); + fprintf(sp0,"illegal value for maximum number of connected components\n"); exit(ABNORMAL_EXIT); } + if(params->maxncomps>UCHAR_MAX + && params->conncompouttype==CONNCOMPOUTTYPEUCHAR){ + fflush(NULL); + fprintf(sp0,"WARNING: clipping max num conn comps to fit uchar out type\n"); + params->maxncomps=UCHAR_MAX; + } + if(params->maxncomps>UINT_MAX + && params->conncompouttype==CONNCOMPOUTTYPEUINT){ + fflush(NULL); + fprintf(sp0,"WARNING: clipping max num conn comps to fit uint out type\n"); + params->maxncomps=UINT_MAX; + } if(strlen(outfiles->conncompfile)){ if(params->initonly){ + fflush(NULL); fprintf(sp0,"WARNING: connected component mask cannot be generated " - "in initialize-only mode\n mask will not be output\n"); + "in initialize-only mode\n mask will not be output\n"); StrNCopy(outfiles->conncompfile,"",MAXSTRLEN); } if(params->costmode==NOSTATCOSTS){ + fflush(NULL); fprintf(sp0,"WARNING: connected component mask cannot be generated " - "without statistical costs\n mask will not be output\n"); + "without statistical costs\n mask will not be output\n"); StrNCopy(outfiles->conncompfile,"",MAXSTRLEN); } } - /* set global pointers to functions for calculating and evaluating costs */ - if(params->p<0){ - if(params->costmode==TOPO){ - CalcCost=CalcCostTopo; - EvalCost=EvalCostTopo; - }else if(params->costmode==DEFO){ - CalcCost=CalcCostDefo; - EvalCost=EvalCostDefo; - }else if(params->costmode==SMOOTH){ - CalcCost=CalcCostSmooth; - EvalCost=EvalCostSmooth; - } - }else{ - if(params->p==0){ - CalcCost=CalcCostL0; - EvalCost=EvalCostL0; - }else if(params->p==1){ - CalcCost=CalcCostL1; - EvalCost=EvalCostL1; - }else if(params->p==2){ - CalcCost=CalcCostL2; - EvalCost=EvalCostL2; - }else{ - CalcCost=CalcCostLP; - EvalCost=EvalCostLP; - } - } + /* done */ + return(0); + } @@ -963,34 +1152,34 @@ void CheckParams(infileT *infiles, outfileT *outfiles, * -------------------------- * Read in parameter values from a file, overriding existing parameters. */ -void ReadConfigFile(char *conffile, infileT *infiles, outfileT *outfiles, - long *linelenptr, paramT *params){ - - long nlines, nparams, nfields; - FILE *fp; - char buf[MAXLINELEN]; - char str1[MAXLINELEN], str2[MAXLINELEN]; +int ReadConfigFile(char *conffile, infileT *infiles, outfileT *outfiles, + long *linelenptr, paramT *params){ + + int parsestatus; + long nlines, nparams; char *ptr; - signed char badparam; + char buf[MAXLINELEN]; + FILE *fp; + /* open input config file */ if(strlen(conffile)){ if((fp=fopen(conffile,"r"))==NULL){ /* abort if we were given a non-zero length name that is unreadable */ + fflush(NULL); fprintf(sp0,"unable to read configuration file %s\n",conffile); exit(ABNORMAL_EXIT); } }else{ /* if we were given a zero-length name, just ignore it and go on */ - return; + return(0); } /* read each line and convert the first two fields */ nlines=0; nparams=0; - badparam=FALSE; while(TRUE){ /* read a line from the file and store it in buffer buf */ @@ -1005,443 +1194,520 @@ void ReadConfigFile(char *conffile, infileT *infiles, outfileT *outfiles, /* make sure we got the whole line */ if(strlen(buf)>=MAXLINELEN-1){ + fflush(NULL); fprintf(sp0,"line %ld in file %s exceeds maximum line length\n", - nlines,conffile); + nlines,conffile); exit(ABNORMAL_EXIT); } - - /* read the first two fields */ - /* (str1, str2 same size as buf, so can't overflow them */ - nfields=sscanf(buf,"%s %s",str1,str2); - - /* if only one field is read, and it is not a comment, we have an error */ - if(nfields==1 && isalnum(str1[0])){ - fprintf(sp0,"unrecognized configuration parameter '%s' (%s:%ld)\n", - str1,conffile,nlines); - exit(ABNORMAL_EXIT); - } - - /* if we have (at least) two non-comment fields */ - if(nfields==2 && isalnum(str1[0])){ - /* do the conversions */ + /* parse config line */ + parsestatus=ParseConfigLine(buf,conffile,nlines, + infiles,outfiles,linelenptr,params); + if(parsestatus>0){ nparams++; - if(!strcmp(str1,"INFILE")){ - StrNCopy(infiles->infile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"OUTFILE")){ - StrNCopy(outfiles->outfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"WEIGHTFILE")){ - StrNCopy(infiles->weightfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"AMPFILE") || !strcmp(str1,"AMPFILE1")){ - if(strlen(infiles->ampfile2) && !params->amplitude){ - fprintf(sp0,"cannot specify both amplitude and power\n"); - exit(ABNORMAL_EXIT); - } - StrNCopy(infiles->ampfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"AMPFILE2")){ - if(strlen(infiles->ampfile) && !params->amplitude){ - fprintf(sp0,"cannot specify both amplitude and power\n"); - exit(ABNORMAL_EXIT); - } - StrNCopy(infiles->ampfile2,str2,MAXSTRLEN); - infiles->ampfileformat=FLOAT_DATA; - }else if(!strcmp(str1,"PWRFILE") || !strcmp(str1,"PWRFILE1")){ - if(strlen(infiles->ampfile2) && params->amplitude){ - fprintf(sp0,"cannot specify both amplitude and power\n"); - exit(ABNORMAL_EXIT); - } - StrNCopy(infiles->ampfile,str2,MAXSTRLEN); - params->amplitude=FALSE; - }else if(!strcmp(str1,"PWRFILE2")){ - if(strlen(infiles->ampfile) && params->amplitude){ - fprintf(sp0,"cannot specify both amplitude and power\n"); - exit(ABNORMAL_EXIT); - } - StrNCopy(infiles->ampfile2,str2,MAXSTRLEN); - params->amplitude=FALSE; - infiles->ampfileformat=FLOAT_DATA; - }else if(!strcmp(str1,"MAGFILE")){ - StrNCopy(infiles->magfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"CORRFILE")){ - StrNCopy(infiles->corrfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"ESTIMATEFILE")){ - StrNCopy(infiles->estfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"LINELENGTH") || !strcmp(str1,"LINELEN")){ - badparam=StringToLong(str2,linelenptr); - }else if(!strcmp(str1,"STATCOSTMODE")){ - if(!strcmp(str2,"TOPO")){ - params->costmode=TOPO; - }else if(!strcmp(str2,"DEFO")){ - params->costmode=DEFO; - }else if(!strcmp(str2,"SMOOTH")){ - params->costmode=SMOOTH; - }else if(!strcmp(str2,"NOSTATCOSTS")){ - params->costmode=NOSTATCOSTS; - }else{ - badparam=TRUE; - } - }else if(!strcmp(str1,"INITONLY")){ - badparam=SetBooleanSignedChar(&(params->initonly),str2); - }else if(!strcmp(str1,"UNWRAPPED_IN")){ - badparam=SetBooleanSignedChar(&(params->unwrapped),str2); - }else if(!strcmp(str1,"DEBUG") || !strcmp(str1,"DUMPALL")){ - badparam=SetBooleanSignedChar(&(params->dumpall),str2); - }else if(!strcmp(str1,"VERBOSE")){ - badparam=SetBooleanSignedChar(&(params->verbose),str2); - }else if(!strcmp(str1,"INITMETHOD")){ - if(!strcmp(str2,"MST") || !strcmp(str2,"mst")){ - params->initmethod=MSTINIT; - }else if(!strcmp(str2,"MCF") || !strcmp(str2,"mcf") - || !strcmp(str2,"CS2") || !strcmp(str2,"cs2")){ - params->initmethod=MCFINIT; - }else{ - badparam=TRUE; - } - }else if(!strcmp(str1,"ORBITRADIUS")){ - if(!(badparam=StringToDouble(str2,&(params->orbitradius)))){ - params->altitude=0; - } - }else if(!strcmp(str1,"ALTITUDE")){ - if(!(badparam=StringToDouble(str2,&(params->altitude)))){ - params->orbitradius=0; - } - }else if(!strcmp(str1,"EARTHRADIUS")){ - badparam=StringToDouble(str2,&(params->earthradius)); - }else if(!strcmp(str1,"BPERP")){ - badparam=StringToDouble(str2,&(params->bperp)); - }else if(!strcmp(str1,"TRANSMITMODE")){ - if(!strcmp(str2,"PINGPONG") || !strcmp(str2,"REPEATPASS")){ - params->transmitmode=PINGPONG; - }else if(!strcmp(str2,"SINGLEANTENNATRANSMIT") || !strcmp(str2,"SAT") - || !strcmp(str2,"SINGLEANTTRANSMIT")){ - params->transmitmode=SINGLEANTTRANSMIT; - }else{ - badparam=TRUE; - } - }else if(!strcmp(str1,"BASELINE")){ - if(!(badparam=StringToDouble(str2,&(params->baseline)))){ - params->bperp=0; - } - }else if(!strcmp(str1,"BASELINEANGLE_RAD")){ - if(!(badparam=StringToDouble(str2,&(params->baselineangle)))){ - params->bperp=0; - } - }else if(!strcmp(str1,"BASELINEANGLE_DEG")){ - if(!(badparam=StringToDouble(str2,&(params->baselineangle)))){ - (params->baselineangle)*=(PI/180.0); - params->bperp=0; - } - }else if(!strcmp(str1,"NLOOKSRANGE")){ - badparam=StringToLong(str2,&(params->nlooksrange)); - }else if(!strcmp(str1,"NLOOKSAZ")){ - badparam=StringToLong(str2,&(params->nlooksaz)); - }else if(!strcmp(str1,"NLOOKSOTHER")){ - badparam=StringToLong(str2,&(params->nlooksother)); - }else if(!strcmp(str1,"NCORRLOOKS")){ - badparam=StringToDouble(str2,&(params->ncorrlooks)); - }else if(!strcmp(str1,"NCORRLOOKSRANGE")){ - badparam=StringToLong(str2,&(params->ncorrlooksrange)); - }else if(!strcmp(str1,"NCORRLOOKSAZ")){ - badparam=StringToLong(str2,&(params->ncorrlooksaz)); - }else if(!strcmp(str1,"NEARRANGE") || !strcmp(str1,"NOMRANGE")){ - badparam=StringToDouble(str2,&(params->nearrange)); - }else if(!strcmp(str1,"DR")){ - badparam=StringToDouble(str2,&(params->dr)); - }else if(!strcmp(str1,"DA")){ - badparam=StringToDouble(str2,&(params->da)); - }else if(!strcmp(str1,"RANGERES")){ - badparam=StringToDouble(str2,&(params->rangeres)); - }else if(!strcmp(str1,"AZRES")){ - badparam=StringToDouble(str2,&(params->azres)); - }else if(!strcmp(str1,"LAMBDA")){ - badparam=StringToDouble(str2,&(params->lambda)); - }else if(!strcmp(str1,"KDS") || !strcmp(str1,"KSD")){ - if(!strcmp(str1,"KSD")){ - fprintf(sp0,"WARNING: parameter KSD interpreted as KDS (%s:%ld)\n", - conffile,nlines); - } - badparam=StringToDouble(str2,&(params->kds)); - }else if(!strcmp(str1,"SPECULAREXP") || !strcmp(str1,"N")){ - badparam=StringToDouble(str2,&(params->specularexp)); - }else if(!strcmp(str1,"DZRCRITFACTOR")){ - badparam=StringToDouble(str2,&(params->dzrcritfactor)); - }else if(!strcmp(str1,"SHADOW")){ - badparam=SetBooleanSignedChar(&(params->shadow),str2); - }else if(!strcmp(str1,"DZEIMIN")){ - badparam=StringToDouble(str2,&(params->dzeimin)); - }else if(!strcmp(str1,"LAYWIDTH")){ - badparam=StringToLong(str2,&(params->laywidth)); - }else if(!strcmp(str1,"LAYMINEI")){ - badparam=StringToDouble(str2,&(params->layminei)); - }else if(!strcmp(str1,"SLOPERATIOFACTOR")){ - badparam=StringToDouble(str2,&(params->sloperatiofactor)); - }else if(!strcmp(str1,"SIGSQEI")){ - badparam=StringToDouble(str2,&(params->sigsqei)); - }else if(!strcmp(str1,"DRHO")){ - badparam=StringToDouble(str2,&(params->drho)); - }else if(!strcmp(str1,"RHOSCONST1")){ - badparam=StringToDouble(str2,&(params->rhosconst1)); - }else if(!strcmp(str1,"RHOSCONST2")){ - badparam=StringToDouble(str2,&(params->rhosconst2)); - }else if(!strcmp(str1,"CSTD1")){ - badparam=StringToDouble(str2,&(params->cstd1)); - }else if(!strcmp(str1,"CSTD2")){ - badparam=StringToDouble(str2,&(params->cstd2)); - }else if(!strcmp(str1,"CSTD3")){ - badparam=StringToDouble(str2,&(params->cstd3)); - }else if(!strcmp(str1,"DEFAULTCORR")){ - badparam=StringToDouble(str2,&(params->defaultcorr)); - }else if(!strcmp(str1,"RHOMINFACTOR")){ - badparam=StringToDouble(str2,&(params->rhominfactor)); - }else if(!strcmp(str1,"DZLAYPEAK")){ - badparam=StringToDouble(str2,&(params->dzlaypeak)); - }else if(!strcmp(str1,"AZDZFACTOR")){ - badparam=StringToDouble(str2,&(params->azdzfactor)); - }else if(!strcmp(str1,"DZEIFACTOR")){ - badparam=StringToDouble(str2,&(params->dzeifactor)); - }else if(!strcmp(str1,"DZEIWEIGHT")){ - badparam=StringToDouble(str2,&(params->dzeiweight)); - }else if(!strcmp(str1,"DZLAYFACTOR")){ - badparam=StringToDouble(str2,&(params->dzlayfactor)); - }else if(!strcmp(str1,"LAYCONST")){ - badparam=StringToDouble(str2,&(params->layconst)); - }else if(!strcmp(str1,"LAYFALLOFFCONST")){ - badparam=StringToDouble(str2,&(params->layfalloffconst)); - }else if(!strcmp(str1,"SIGSQSHORTMIN")){ - badparam=StringToLong(str2,&(params->sigsqshortmin)); - }else if(!strcmp(str1,"SIGSQLAYFACTOR")){ - badparam=StringToDouble(str2,&(params->sigsqlayfactor)); - }else if(!strcmp(str1,"DEFOAZDZFACTOR")){ - badparam=StringToDouble(str2,&(params->defoazdzfactor)); - }else if(!strcmp(str1,"DEFOTHRESHFACTOR")){ - badparam=StringToDouble(str2,&(params->defothreshfactor)); - }else if(!strcmp(str1,"DEFOMAX_CYCLE")){ - badparam=StringToDouble(str2,&(params->defomax)); - }else if(!strcmp(str1,"DEFOMAX_RAD")){ - if(!(badparam=StringToDouble(str2,&(params->defomax)))){ - params->defomax/=TWOPI; - } - }else if(!strcmp(str1,"SIGSQCORR")){ - badparam=StringToDouble(str2,&(params->sigsqcorr)); - }else if(!strcmp(str1,"DEFOLAYCONST") || !strcmp(str1,"DEFOCONST")){ - badparam=StringToDouble(str2,&(params->defolayconst)); - }else if(!strcmp(str1,"INITMAXFLOW")){ - badparam=StringToLong(str2,&(params->initmaxflow)); - }else if(!strcmp(str1,"ARCMAXFLOWCONST")){ - badparam=StringToLong(str2,&(params->arcmaxflowconst)); - }else if(!strcmp(str1,"MAXFLOW")){ - badparam=StringToLong(str2,&(params->maxflow)); - }else if(!strcmp(str1,"KROWEI") || !strcmp(str1,"KROW")){ - badparam=StringToLong(str2,&(params->krowei)); - }else if(!strcmp(str1,"KCOLEI") || !strcmp(str1,"KCOL")){ - badparam=StringToLong(str2,&(params->kcolei)); - }else if(!strcmp(str1,"KPERPDPSI")){ - badparam=StringToLong(str2,&(params->kperpdpsi)); - }else if(!strcmp(str1,"KPARDPSI")){ - badparam=StringToLong(str2,&(params->kpardpsi)); - }else if(!strcmp(str1,"THRESHOLD")){ - badparam=StringToDouble(str2,&(params->threshold)); - }else if(!strcmp(str1,"INITDZR")){ - badparam=StringToDouble(str2,&(params->initdzr)); - }else if(!strcmp(str1,"INITDZSTEP")){ - badparam=StringToDouble(str2,&(params->initdzstep)); - }else if(!strcmp(str1,"MAXCOST")){ - badparam=StringToDouble(str2,&(params->maxcost)); - }else if(!strcmp(str1,"COSTSCALE")){ - badparam=StringToDouble(str2,&(params->costscale)); - }else if(!strcmp(str1,"COSTSCALEAMBIGHT")){ - badparam=StringToDouble(str2,&(params->costscaleambight)); - }else if(!strcmp(str1,"DNOMINCANGLE")){ - badparam=StringToDouble(str2,&(params->dnomincangle)); - }else if(!strcmp(str1,"CS2SCALEFACTOR")){ - badparam=StringToLong(str2,&(params->cs2scalefactor)); - }else if(!strcmp(str1,"PIECEFIRSTROW")){ - badparam=StringToLong(str2,&(params->piecefirstrow)); - }else if(!strcmp(str1,"PIECEFIRSTCOL")){ - badparam=StringToLong(str2,&(params->piecefirstcol)); - }else if(!strcmp(str1,"PIECENROW")){ - badparam=StringToLong(str2,&(params->piecenrow)); - }else if(!strcmp(str1,"PIECENCOL")){ - badparam=StringToLong(str2,&(params->piecencol)); - }else if(!strcmp(str1,"NTILEROW")){ - badparam=StringToLong(str2,&(params->ntilerow)); - }else if(!strcmp(str1,"NTILECOL")){ - badparam=StringToLong(str2,&(params->ntilecol)); - }else if(!strcmp(str1,"ROWOVRLP")){ - badparam=StringToLong(str2,&(params->rowovrlp)); - }else if(!strcmp(str1,"COLOVRLP")){ - badparam=StringToLong(str2,&(params->colovrlp)); - }else if(!strcmp(str1,"TILECOSTTHRESH")){ - badparam=StringToLong(str2,&(params->tilecostthresh)); - }else if(!strcmp(str1,"MINREGIONSIZE")){ - badparam=StringToLong(str2,&(params->minregionsize)); - }else if(!strcmp(str1,"TILEEDGEWEIGHT")){ - badparam=StringToDouble(str2,&(params->tileedgeweight)); - }else if(!strcmp(str1,"SCNDRYARCFLOWMAX")){ - badparam=StringToLong(str2,&(params->scndryarcflowmax)); - }else if(!strcmp(str1,"ASSEMBLEONLY")){ - if(!strcmp(str2,"FALSE")){ - params->assembleonly=FALSE; - }else{ - params->assembleonly=TRUE; - StrNCopy(params->tiledir,str2,MAXSTRLEN); - } - }else if(!strcmp(str1,"RMTMPTILE")){ - badparam=SetBooleanSignedChar(&(params->rmtmptile),str2); - }else if(!strcmp(str1,"MINCONNCOMPFRAC")){ - badparam=StringToDouble(str2,&(params->minconncompfrac)); - }else if(!strcmp(str1,"CONNCOMPTHRESH")){ - badparam=StringToLong(str2,&(params->conncompthresh)); - }else if(!strcmp(str1,"MAXNCOMPS")){ - badparam=StringToLong(str2,&(params->maxncomps)); - }else if(!strcmp(str1,"NSHORTCYCLE")){ - badparam=StringToLong(str2,&(params->nshortcycle)); - }else if(!strcmp(str1,"MAXNEWNODECONST")){ - badparam=StringToDouble(str2,&(params->maxnewnodeconst)); - }else if(!strcmp(str1,"MAXNFLOWCYCLES")){ - badparam=StringToLong(str2,&(params->maxnflowcycles)); - }else if(!strcmp(str1,"MAXCYCLEFRACTION")){ - badparam=StringToDouble(str2,&(params->maxcyclefraction)); - params->maxnflowcycles=USEMAXCYCLEFRACTION; - }else if(!strcmp(str1,"SOURCEMODE")){ - badparam=StringToLong(str2,&(params->sourcemode)); - }else if(!strcmp(str1,"NPROC") || !strcmp(str1,"NTHREADS")){ - badparam=StringToLong(str2,&(params->nthreads)); - }else if(!strcmp(str1,"COSTINFILE")){ - StrNCopy(infiles->costinfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"COSTOUTFILE")){ - StrNCopy(outfiles->costoutfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"LOGFILE")){ - StrNCopy(outfiles->logfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"INFILEFORMAT")){ - if(!strcmp(str2,"COMPLEX_DATA")){ - infiles->infileformat=COMPLEX_DATA; - }else if(!strcmp(str2,"FLOAT_DATA")){ - infiles->infileformat=FLOAT_DATA; - }else if(!strcmp(str2,"ALT_LINE_DATA")){ - infiles->infileformat=ALT_LINE_DATA; - }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ - infiles->infileformat=ALT_SAMPLE_DATA; - }else{ - badparam=TRUE; - } - }else if(!strcmp(str1,"UNWRAPPEDINFILEFORMAT")){ - if(!strcmp(str2,"ALT_LINE_DATA")){ - infiles->unwrappedinfileformat=ALT_LINE_DATA; - }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ - infiles->unwrappedinfileformat=ALT_SAMPLE_DATA; - }else if(!strcmp(str2,"FLOAT_DATA")){ - infiles->unwrappedinfileformat=FLOAT_DATA; - }else{ - badparam=TRUE; - } - }else if(!strcmp(str1,"MAGFILEFORMAT")){ - if(!strcmp(str2,"ALT_LINE_DATA")){ - infiles->magfileformat=ALT_LINE_DATA; - }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ - infiles->magfileformat=ALT_SAMPLE_DATA; - }else if(!strcmp(str2,"FLOAT_DATA")){ - infiles->magfileformat=FLOAT_DATA; - }else if(!strcmp(str2,"COMPLEX_DATA")){ - infiles->magfileformat=COMPLEX_DATA; - }else{ - badparam=TRUE; - } - }else if(!strcmp(str1,"OUTFILEFORMAT")){ - if(!strcmp(str2,"ALT_LINE_DATA")){ - outfiles->outfileformat=ALT_LINE_DATA; - }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ - outfiles->outfileformat=ALT_SAMPLE_DATA; - }else if(!strcmp(str2,"FLOAT_DATA")){ - outfiles->outfileformat=FLOAT_DATA; - }else{ - badparam=TRUE; - } - }else if(!strcmp(str1,"CORRFILEFORMAT")){ - if(!strcmp(str2,"ALT_LINE_DATA")){ - infiles->corrfileformat=ALT_LINE_DATA; - }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ - infiles->corrfileformat=ALT_SAMPLE_DATA; - }else if(!strcmp(str2,"FLOAT_DATA")){ - infiles->corrfileformat=FLOAT_DATA; - }else{ - badparam=TRUE; - } - }else if(!strcmp(str1,"AMPFILEFORMAT")){ - if(!strcmp(str2,"ALT_LINE_DATA")){ - infiles->ampfileformat=ALT_LINE_DATA; - }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ - infiles->ampfileformat=ALT_SAMPLE_DATA; - }else if(!strcmp(str2,"FLOAT_DATA")){ - infiles->ampfileformat=FLOAT_DATA; - }else{ - badparam=TRUE; - } - }else if(!strcmp(str1,"ESTFILEFORMAT")){ - if(!strcmp(str2,"ALT_LINE_DATA")){ - infiles->estfileformat=ALT_LINE_DATA; - }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ - infiles->estfileformat=ALT_SAMPLE_DATA; - }else if(!strcmp(str2,"FLOAT_DATA")){ - infiles->estfileformat=FLOAT_DATA; - }else{ - badparam=TRUE; - } - }else if(!strcmp(str1,"INITFILE")){ - StrNCopy(outfiles->initfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"FLOWFILE")){ - StrNCopy(outfiles->flowfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"EIFILE")){ - StrNCopy(outfiles->eifile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"ROWCOSTFILE")){ - StrNCopy(outfiles->rowcostfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"COLCOSTFILE")){ - StrNCopy(outfiles->colcostfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"MSTROWCOSTFILE")){ - StrNCopy(outfiles->mstrowcostfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"MSTCOLCOSTFILE")){ - StrNCopy(outfiles->mstcolcostfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"MSTCOSTSFILE")){ - StrNCopy(outfiles->mstcostsfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"CORRDUMPFILE")){ - StrNCopy(outfiles->corrdumpfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"RAWCORRDUMPFILE")){ - StrNCopy(outfiles->rawcorrdumpfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"CONNCOMPFILE")){ - StrNCopy(outfiles->conncompfile,str2,MAXSTRLEN); - }else if(!strcmp(str1,"REGROWCONNCOMPS")){ - badparam=SetBooleanSignedChar(&(params->regrowconncomps),str2); - }else{ - fprintf(sp0,"unrecognized configuration parameter '%s' (%s:%ld)\n", - str1,conffile,nlines); - exit(ABNORMAL_EXIT); - } - - /* give an error if we had trouble interpreting the line */ - if(badparam){ - fprintf(sp0,"illegal argument %s for parameter %s (%s:%ld)\n", - str2,str1,conffile,nlines); - exit(ABNORMAL_EXIT); - } - } + } /* finish up */ fclose(fp); if(nparams>1){ fprintf(sp1,"%ld parameters input from file %s (%ld lines total)\n", - nparams,conffile,nlines); + nparams,conffile,nlines); }else{ if(nlines>1){ fprintf(sp1,"%ld parameter input from file %s (%ld lines total)\n", - nparams,conffile,nlines); + nparams,conffile,nlines); }else{ fprintf(sp1,"%ld parameter input from file %s (%ld line total)\n", - nparams,conffile,nlines); + nparams,conffile,nlines); + } + } + + /* done */ + return(0); + +} + + +/* function: ParseConfigLine() + * --------------------------- + * Parse config line from passed buffer. + */ +static +int ParseConfigLine(char *buf, char *conffile, long nlines, + infileT *infiles, outfileT *outfiles, + long *linelenptr, paramT *params){ + + int nparams; + long nfields; + char str1[MAXLINELEN], str2[MAXLINELEN]; + signed char badparam; + + + /* set up */ + nparams=0; + badparam=FALSE; + + /* read the first two fields */ + /* (str1, str2 same size as buf, so can't overflow them */ + nfields=sscanf(buf,"%s %s",str1,str2); + + /* if only one field is read, and it is not a comment, we have an error */ + if(nfields==1 && isalnum(str1[0])){ + fflush(NULL); + fprintf(sp0,"unrecognized configuration parameter '%s' (%s:%ld)\n", + str1,conffile,nlines); + exit(ABNORMAL_EXIT); + } + + /* if we have (at least) two non-comment fields */ + if(nfields==2 && isalnum(str1[0])){ + + /* do the conversions */ + nparams++; + if(!strcmp(str1,"INFILE")){ + StrNCopy(infiles->infile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"OUTFILE")){ + StrNCopy(outfiles->outfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"WEIGHTFILE")){ + StrNCopy(infiles->weightfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"AMPFILE") || !strcmp(str1,"AMPFILE1")){ + if(strlen(infiles->ampfile2) && !params->amplitude){ + fflush(NULL); + fprintf(sp0,"cannot specify both amplitude and power\n"); + exit(ABNORMAL_EXIT); + } + StrNCopy(infiles->ampfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"AMPFILE2")){ + if(strlen(infiles->ampfile) && !params->amplitude){ + fflush(NULL); + fprintf(sp0,"cannot specify both amplitude and power\n"); + exit(ABNORMAL_EXIT); + } + StrNCopy(infiles->ampfile2,str2,MAXSTRLEN); + infiles->ampfileformat=FLOAT_DATA; + }else if(!strcmp(str1,"PWRFILE") || !strcmp(str1,"PWRFILE1")){ + if(strlen(infiles->ampfile2) && params->amplitude){ + fflush(NULL); + fprintf(sp0,"cannot specify both amplitude and power\n"); + exit(ABNORMAL_EXIT); + } + StrNCopy(infiles->ampfile,str2,MAXSTRLEN); + params->amplitude=FALSE; + }else if(!strcmp(str1,"PWRFILE2")){ + if(strlen(infiles->ampfile) && params->amplitude){ + fflush(NULL); + fprintf(sp0,"cannot specify both amplitude and power\n"); + exit(ABNORMAL_EXIT); + } + StrNCopy(infiles->ampfile2,str2,MAXSTRLEN); + params->amplitude=FALSE; + infiles->ampfileformat=FLOAT_DATA; + }else if(!strcmp(str1,"MAGFILE")){ + StrNCopy(infiles->magfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"CORRFILE")){ + StrNCopy(infiles->corrfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"ESTIMATEFILE")){ + StrNCopy(infiles->estfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"LINELENGTH") || !strcmp(str1,"LINELEN")){ + badparam=StringToLong(str2,linelenptr); + }else if(!strcmp(str1,"STATCOSTMODE")){ + if(!strcmp(str2,"TOPO")){ + params->costmode=TOPO; + }else if(!strcmp(str2,"DEFO")){ + params->costmode=DEFO; + }else if(!strcmp(str2,"SMOOTH")){ + params->costmode=SMOOTH; + }else if(!strcmp(str2,"NOSTATCOSTS")){ + params->costmode=NOSTATCOSTS; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"INITONLY")){ + badparam=SetBooleanSignedChar(&(params->initonly),str2); + }else if(!strcmp(str1,"UNWRAPPED_IN")){ + badparam=SetBooleanSignedChar(&(params->unwrapped),str2); + }else if(!strcmp(str1,"DEBUG") || !strcmp(str1,"DUMPALL")){ + badparam=SetBooleanSignedChar(&(params->dumpall),str2); + }else if(!strcmp(str1,"VERBOSE")){ + badparam=SetBooleanSignedChar(&(params->verbose),str2); + }else if(!strcmp(str1,"INITMETHOD")){ + if(!strcmp(str2,"MST") || !strcmp(str2,"mst")){ + params->initmethod=MSTINIT; + }else if(!strcmp(str2,"MCF") || !strcmp(str2,"mcf") + || !strcmp(str2,"CS2") || !strcmp(str2,"cs2")){ + params->initmethod=MCFINIT; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"ORBITRADIUS")){ + if(!(badparam=StringToDouble(str2,&(params->orbitradius)))){ + params->altitude=0; + } + }else if(!strcmp(str1,"ALTITUDE")){ + if(!(badparam=StringToDouble(str2,&(params->altitude)))){ + params->orbitradius=0; + } + }else if(!strcmp(str1,"EARTHRADIUS")){ + badparam=StringToDouble(str2,&(params->earthradius)); + }else if(!strcmp(str1,"BPERP")){ + badparam=StringToDouble(str2,&(params->bperp)); + }else if(!strcmp(str1,"TRANSMITMODE")){ + if(!strcmp(str2,"PINGPONG") || !strcmp(str2,"REPEATPASS")){ + params->transmitmode=PINGPONG; + }else if(!strcmp(str2,"SINGLEANTENNATRANSMIT") || !strcmp(str2,"SAT") + || !strcmp(str2,"SINGLEANTTRANSMIT")){ + params->transmitmode=SINGLEANTTRANSMIT; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"BASELINE")){ + if(!(badparam=StringToDouble(str2,&(params->baseline)))){ + params->bperp=0; + } + }else if(!strcmp(str1,"BASELINEANGLE_RAD")){ + if(!(badparam=StringToDouble(str2,&(params->baselineangle)))){ + params->bperp=0; + } + }else if(!strcmp(str1,"BASELINEANGLE_DEG")){ + if(!(badparam=StringToDouble(str2,&(params->baselineangle)))){ + (params->baselineangle)*=(PI/180.0); + params->bperp=0; + } + }else if(!strcmp(str1,"NLOOKSRANGE")){ + badparam=StringToLong(str2,&(params->nlooksrange)); + }else if(!strcmp(str1,"NLOOKSAZ")){ + badparam=StringToLong(str2,&(params->nlooksaz)); + }else if(!strcmp(str1,"NLOOKSOTHER")){ + badparam=StringToLong(str2,&(params->nlooksother)); + }else if(!strcmp(str1,"NCORRLOOKS")){ + badparam=StringToDouble(str2,&(params->ncorrlooks)); + }else if(!strcmp(str1,"NCORRLOOKSRANGE")){ + badparam=StringToLong(str2,&(params->ncorrlooksrange)); + }else if(!strcmp(str1,"NCORRLOOKSAZ")){ + badparam=StringToLong(str2,&(params->ncorrlooksaz)); + }else if(!strcmp(str1,"NEARRANGE") || !strcmp(str1,"NOMRANGE")){ + badparam=StringToDouble(str2,&(params->nearrange)); + }else if(!strcmp(str1,"DR")){ + badparam=StringToDouble(str2,&(params->dr)); + }else if(!strcmp(str1,"DA")){ + badparam=StringToDouble(str2,&(params->da)); + }else if(!strcmp(str1,"RANGERES")){ + badparam=StringToDouble(str2,&(params->rangeres)); + }else if(!strcmp(str1,"AZRES")){ + badparam=StringToDouble(str2,&(params->azres)); + }else if(!strcmp(str1,"LAMBDA")){ + badparam=StringToDouble(str2,&(params->lambda)); + }else if(!strcmp(str1,"KDS") || !strcmp(str1,"KSD")){ + if(!strcmp(str1,"KSD")){ + fflush(NULL); + fprintf(sp0,"WARNING: parameter KSD interpreted as KDS (%s:%ld)\n", + conffile,nlines); + } + badparam=StringToDouble(str2,&(params->kds)); + }else if(!strcmp(str1,"SPECULAREXP") || !strcmp(str1,"N")){ + badparam=StringToDouble(str2,&(params->specularexp)); + }else if(!strcmp(str1,"DZRCRITFACTOR")){ + badparam=StringToDouble(str2,&(params->dzrcritfactor)); + }else if(!strcmp(str1,"SHADOW")){ + badparam=SetBooleanSignedChar(&(params->shadow),str2); + }else if(!strcmp(str1,"DZEIMIN")){ + badparam=StringToDouble(str2,&(params->dzeimin)); + }else if(!strcmp(str1,"LAYWIDTH")){ + badparam=StringToLong(str2,&(params->laywidth)); + }else if(!strcmp(str1,"LAYMINEI")){ + badparam=StringToDouble(str2,&(params->layminei)); + }else if(!strcmp(str1,"SLOPERATIOFACTOR")){ + badparam=StringToDouble(str2,&(params->sloperatiofactor)); + }else if(!strcmp(str1,"SIGSQEI")){ + badparam=StringToDouble(str2,&(params->sigsqei)); + }else if(!strcmp(str1,"DRHO")){ + badparam=StringToDouble(str2,&(params->drho)); + }else if(!strcmp(str1,"RHOSCONST1")){ + badparam=StringToDouble(str2,&(params->rhosconst1)); + }else if(!strcmp(str1,"RHOSCONST2")){ + badparam=StringToDouble(str2,&(params->rhosconst2)); + }else if(!strcmp(str1,"CSTD1")){ + badparam=StringToDouble(str2,&(params->cstd1)); + }else if(!strcmp(str1,"CSTD2")){ + badparam=StringToDouble(str2,&(params->cstd2)); + }else if(!strcmp(str1,"CSTD3")){ + badparam=StringToDouble(str2,&(params->cstd3)); + }else if(!strcmp(str1,"DEFAULTCORR")){ + badparam=StringToDouble(str2,&(params->defaultcorr)); + }else if(!strcmp(str1,"RHOMINFACTOR")){ + badparam=StringToDouble(str2,&(params->rhominfactor)); + }else if(!strcmp(str1,"DZLAYPEAK")){ + badparam=StringToDouble(str2,&(params->dzlaypeak)); + }else if(!strcmp(str1,"AZDZFACTOR")){ + badparam=StringToDouble(str2,&(params->azdzfactor)); + }else if(!strcmp(str1,"DZEIFACTOR")){ + badparam=StringToDouble(str2,&(params->dzeifactor)); + }else if(!strcmp(str1,"DZEIWEIGHT")){ + badparam=StringToDouble(str2,&(params->dzeiweight)); + }else if(!strcmp(str1,"DZLAYFACTOR")){ + badparam=StringToDouble(str2,&(params->dzlayfactor)); + }else if(!strcmp(str1,"LAYCONST")){ + badparam=StringToDouble(str2,&(params->layconst)); + }else if(!strcmp(str1,"LAYFALLOFFCONST")){ + badparam=StringToDouble(str2,&(params->layfalloffconst)); + }else if(!strcmp(str1,"SIGSQSHORTMIN")){ + badparam=StringToLong(str2,&(params->sigsqshortmin)); + }else if(!strcmp(str1,"SIGSQLAYFACTOR")){ + badparam=StringToDouble(str2,&(params->sigsqlayfactor)); + }else if(!strcmp(str1,"DEFOAZDZFACTOR")){ + badparam=StringToDouble(str2,&(params->defoazdzfactor)); + }else if(!strcmp(str1,"DEFOTHRESHFACTOR")){ + badparam=StringToDouble(str2,&(params->defothreshfactor)); + }else if(!strcmp(str1,"DEFOMAX_CYCLE")){ + badparam=StringToDouble(str2,&(params->defomax)); + }else if(!strcmp(str1,"DEFOMAX_RAD")){ + if(!(badparam=StringToDouble(str2,&(params->defomax)))){ + params->defomax/=TWOPI; + } + }else if(!strcmp(str1,"SIGSQCORR")){ + badparam=StringToDouble(str2,&(params->sigsqcorr)); + }else if(!strcmp(str1,"DEFOLAYCONST") || !strcmp(str1,"DEFOCONST")){ + badparam=StringToDouble(str2,&(params->defolayconst)); + }else if(!strcmp(str1,"INITMAXFLOW")){ + badparam=StringToLong(str2,&(params->initmaxflow)); + }else if(!strcmp(str1,"ARCMAXFLOWCONST")){ + badparam=StringToLong(str2,&(params->arcmaxflowconst)); + }else if(!strcmp(str1,"MAXFLOW")){ + badparam=StringToLong(str2,&(params->maxflow)); + }else if(!strcmp(str1,"KROWEI") || !strcmp(str1,"KROW")){ + badparam=StringToLong(str2,&(params->krowei)); + }else if(!strcmp(str1,"KCOLEI") || !strcmp(str1,"KCOL")){ + badparam=StringToLong(str2,&(params->kcolei)); + }else if(!strcmp(str1,"KPERPDPSI")){ + badparam=StringToLong(str2,&(params->kperpdpsi)); + }else if(!strcmp(str1,"KPARDPSI")){ + badparam=StringToLong(str2,&(params->kpardpsi)); + }else if(!strcmp(str1,"THRESHOLD")){ + badparam=StringToDouble(str2,&(params->threshold)); + }else if(!strcmp(str1,"INITDZR")){ + badparam=StringToDouble(str2,&(params->initdzr)); + }else if(!strcmp(str1,"INITDZSTEP")){ + badparam=StringToDouble(str2,&(params->initdzstep)); + }else if(!strcmp(str1,"MAXCOST")){ + badparam=StringToDouble(str2,&(params->maxcost)); + }else if(!strcmp(str1,"COSTSCALE")){ + badparam=StringToDouble(str2,&(params->costscale)); + }else if(!strcmp(str1,"COSTSCALEAMBIGHT")){ + badparam=StringToDouble(str2,&(params->costscaleambight)); + }else if(!strcmp(str1,"DNOMINCANGLE")){ + badparam=StringToDouble(str2,&(params->dnomincangle)); + }else if(!strcmp(str1,"CS2SCALEFACTOR")){ + badparam=StringToLong(str2,&(params->cs2scalefactor)); + }else if(!strcmp(str1,"NMAJORPRUNE")){ + badparam=StringToLong(str2,&(params->nmajorprune)); + }else if(!strcmp(str1,"PRUNECOSTTHRESH")){ + badparam=StringToLong(str2,&(params->prunecostthresh)); + }else if(!strcmp(str1,"PLPN")){ + badparam=StringToDouble(str2,&(params->p)); + }else if(!strcmp(str1,"BIDIRLPN")){ + badparam=SetBooleanSignedChar(&(params->bidirlpn),str2); + }else if(!strcmp(str1,"EDGEMASKTOP")){ + badparam=StringToLong(str2,&(params->edgemasktop)); + }else if(!strcmp(str1,"EDGEMASKBOT")){ + badparam=StringToLong(str2,&(params->edgemaskbot)); + }else if(!strcmp(str1,"EDGEMASKLEFT")){ + badparam=StringToLong(str2,&(params->edgemaskleft)); + }else if(!strcmp(str1,"EDGEMASKRIGHT")){ + badparam=StringToLong(str2,&(params->edgemaskright)); + }else if(!strcmp(str1,"PIECEFIRSTROW")){ + badparam=StringToLong(str2,&(params->piecefirstrow)); + }else if(!strcmp(str1,"PIECEFIRSTCOL")){ + badparam=StringToLong(str2,&(params->piecefirstcol)); + }else if(!strcmp(str1,"PIECENROW")){ + badparam=StringToLong(str2,&(params->piecenrow)); + }else if(!strcmp(str1,"PIECENCOL")){ + badparam=StringToLong(str2,&(params->piecencol)); + }else if(!strcmp(str1,"NTILEROW")){ + badparam=StringToLong(str2,&(params->ntilerow)); + }else if(!strcmp(str1,"NTILECOL")){ + badparam=StringToLong(str2,&(params->ntilecol)); + }else if(!strcmp(str1,"ROWOVRLP")){ + badparam=StringToLong(str2,&(params->rowovrlp)); + }else if(!strcmp(str1,"COLOVRLP")){ + badparam=StringToLong(str2,&(params->colovrlp)); + }else if(!strcmp(str1,"TILECOSTTHRESH")){ + badparam=StringToLong(str2,&(params->tilecostthresh)); + }else if(!strcmp(str1,"MINREGIONSIZE")){ + badparam=StringToLong(str2,&(params->minregionsize)); + }else if(!strcmp(str1,"TILEEDGEWEIGHT")){ + badparam=StringToDouble(str2,&(params->tileedgeweight)); + }else if(!strcmp(str1,"SCNDRYARCFLOWMAX")){ + badparam=StringToLong(str2,&(params->scndryarcflowmax)); + }else if(!strcmp(str1,"TILEDIR")){ + StrNCopy(params->tiledir,str2,MAXSTRLEN); + }else if(!strcmp(str1,"ASSEMBLEONLY")){ + badparam=SetBooleanSignedChar(&(params->assembleonly),str2); + }else if(!strcmp(str1,"SINGLETILEREOPTIMIZE")){ + badparam=SetBooleanSignedChar(&(params->onetilereopt),str2); + }else if(!strcmp(str1,"RMTMPTILE")){ + badparam=SetBooleanSignedChar(&(params->rmtmptile),str2); + params->rmtileinit=params->rmtmptile; + }else if(!strcmp(str1,"MINCONNCOMPFRAC")){ + badparam=StringToDouble(str2,&(params->minconncompfrac)); + }else if(!strcmp(str1,"CONNCOMPTHRESH")){ + badparam=StringToLong(str2,&(params->conncompthresh)); + }else if(!strcmp(str1,"MAXNCOMPS")){ + badparam=StringToLong(str2,&(params->maxncomps)); + }else if(!strcmp(str1,"CONNCOMPOUTTYPE")){ + if(!strcmp(str2,"UCHAR")){ + params->conncompouttype=CONNCOMPOUTTYPEUCHAR; + }else if(!strcmp(str2,"UINT")){ + params->conncompouttype=CONNCOMPOUTTYPEUINT; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"NSHORTCYCLE")){ + badparam=StringToLong(str2,&(params->nshortcycle)); + }else if(!strcmp(str1,"MAXNEWNODECONST")){ + badparam=StringToDouble(str2,&(params->maxnewnodeconst)); + }else if(!strcmp(str1,"MAXNFLOWCYCLES")){ + badparam=StringToLong(str2,&(params->maxnflowcycles)); + }else if(!strcmp(str1,"MAXCYCLEFRACTION")){ + badparam=StringToDouble(str2,&(params->maxcyclefraction)); + params->maxnflowcycles=USEMAXCYCLEFRACTION; + }else if(!strcmp(str1,"SOURCEMODE")){ + fflush(NULL); + fprintf(sp0, + "WARNING: SOURCEMODE keyword no longer supported--ignoring\n"); + }else if(!strcmp(str1,"NCONNNODEMIN")){ + badparam=StringToLong(str2,&(params->nconnnodemin)); + }else if(!strcmp(str1,"NPROC") || !strcmp(str1,"NTHREADS")){ + badparam=StringToLong(str2,&(params->nthreads)); + }else if(!strcmp(str1,"COSTINFILE")){ + StrNCopy(infiles->costinfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"BYTEMASKFILE")){ + StrNCopy(infiles->bytemaskfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"DOTILEMASKFILE")){ + StrNCopy(infiles->dotilemaskfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"COSTOUTFILE")){ + StrNCopy(outfiles->costoutfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"LOGFILE")){ + StrNCopy(outfiles->logfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"INFILEFORMAT")){ + if(!strcmp(str2,"COMPLEX_DATA")){ + infiles->infileformat=COMPLEX_DATA; + }else if(!strcmp(str2,"FLOAT_DATA")){ + infiles->infileformat=FLOAT_DATA; + }else if(!strcmp(str2,"ALT_LINE_DATA")){ + infiles->infileformat=ALT_LINE_DATA; + }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ + infiles->infileformat=ALT_SAMPLE_DATA; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"UNWRAPPEDINFILEFORMAT")){ + if(!strcmp(str2,"ALT_LINE_DATA")){ + infiles->unwrappedinfileformat=ALT_LINE_DATA; + }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ + infiles->unwrappedinfileformat=ALT_SAMPLE_DATA; + }else if(!strcmp(str2,"FLOAT_DATA")){ + infiles->unwrappedinfileformat=FLOAT_DATA; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"MAGFILEFORMAT")){ + if(!strcmp(str2,"ALT_LINE_DATA")){ + infiles->magfileformat=ALT_LINE_DATA; + }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ + infiles->magfileformat=ALT_SAMPLE_DATA; + }else if(!strcmp(str2,"FLOAT_DATA")){ + infiles->magfileformat=FLOAT_DATA; + }else if(!strcmp(str2,"COMPLEX_DATA")){ + infiles->magfileformat=COMPLEX_DATA; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"OUTFILEFORMAT")){ + if(!strcmp(str2,"ALT_LINE_DATA")){ + outfiles->outfileformat=ALT_LINE_DATA; + }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ + outfiles->outfileformat=ALT_SAMPLE_DATA; + }else if(!strcmp(str2,"FLOAT_DATA")){ + outfiles->outfileformat=FLOAT_DATA; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"CORRFILEFORMAT")){ + if(!strcmp(str2,"ALT_LINE_DATA")){ + infiles->corrfileformat=ALT_LINE_DATA; + }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ + infiles->corrfileformat=ALT_SAMPLE_DATA; + }else if(!strcmp(str2,"FLOAT_DATA")){ + infiles->corrfileformat=FLOAT_DATA; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"AMPFILEFORMAT")){ + if(!strcmp(str2,"ALT_LINE_DATA")){ + infiles->ampfileformat=ALT_LINE_DATA; + }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ + infiles->ampfileformat=ALT_SAMPLE_DATA; + }else if(!strcmp(str2,"FLOAT_DATA")){ + infiles->ampfileformat=FLOAT_DATA; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"ESTFILEFORMAT")){ + if(!strcmp(str2,"ALT_LINE_DATA")){ + infiles->estfileformat=ALT_LINE_DATA; + }else if(!strcmp(str2,"ALT_SAMPLE_DATA")){ + infiles->estfileformat=ALT_SAMPLE_DATA; + }else if(!strcmp(str2,"FLOAT_DATA")){ + infiles->estfileformat=FLOAT_DATA; + }else{ + badparam=TRUE; + } + }else if(!strcmp(str1,"INITFILE")){ + StrNCopy(outfiles->initfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"FLOWFILE")){ + StrNCopy(outfiles->flowfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"EIFILE")){ + StrNCopy(outfiles->eifile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"ROWCOSTFILE")){ + StrNCopy(outfiles->rowcostfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"COLCOSTFILE")){ + StrNCopy(outfiles->colcostfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"MSTROWCOSTFILE")){ + StrNCopy(outfiles->mstrowcostfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"MSTCOLCOSTFILE")){ + StrNCopy(outfiles->mstcolcostfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"MSTCOSTSFILE")){ + StrNCopy(outfiles->mstcostsfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"CORRDUMPFILE")){ + StrNCopy(outfiles->corrdumpfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"RAWCORRDUMPFILE")){ + StrNCopy(outfiles->rawcorrdumpfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"CONNCOMPFILE")){ + StrNCopy(outfiles->conncompfile,str2,MAXSTRLEN); + }else if(!strcmp(str1,"REGROWCONNCOMPS")){ + badparam=SetBooleanSignedChar(&(params->regrowconncomps),str2); + }else{ + fflush(NULL); + fprintf(sp0,"unrecognized configuration parameter '%s' (%s:%ld)\n", + str1,conffile,nlines); + exit(ABNORMAL_EXIT); + } + + /* give an error if we had trouble interpreting the line */ + if(badparam){ + fflush(NULL); + fprintf(sp0,"illegal argument %s for parameter %s (%s:%ld)\n", + str2,str1,conffile,nlines); + exit(ABNORMAL_EXIT); } + } + /* return number of parameters successfully parsed */ + return(nparams); + } @@ -1451,19 +1717,21 @@ void ReadConfigFile(char *conffile, infileT *infiles, outfileT *outfiles, * information. The log file is in a format compatible to be used as * a configuration file. */ -void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, - outfileT *outfiles, long linelen, paramT *params){ +int WriteConfigLogFile(int argc, char *argv[], infileT *infiles, + outfileT *outfiles, long linelen, paramT *params){ FILE *fp; time_t t[1]; long k; char buf[MAXSTRLEN], *ptr; + char hostnamestr[MAXSTRLEN]; /* see if we need to write a log file */ if(strlen(outfiles->logfile)){ /* open the log file */ if((fp=fopen(outfiles->logfile,"w"))==NULL){ + fflush(NULL); fprintf(sp0,"unable to write to log file %s\n",outfiles->logfile); exit(ABNORMAL_EXIT); } @@ -1473,6 +1741,12 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, fprintf(fp,"# %s v%s\n",PROGRAMNAME,VERSION); time(t); fprintf(fp,"# Log file generated %s",ctime(t)); + if(gethostname(hostnamestr,MAXSTRLEN)){ + fprintf(fp,"# Could not determine host name\n"); + }else{ + fprintf(fp,"# Host name: %s\n",hostnamestr); + } + fprintf(fp,"# PID %ld\n",params->parentpid); ptr=getcwd(buf,MAXSTRLEN); if(ptr!=NULL){ fprintf(fp,"# Current working directory: %s\n",buf); @@ -1485,6 +1759,17 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, } fprintf(fp,"\n\n"); + /* print some information about data type sizes */ + fprintf(fp,"# Data type size information for executable as compiled\n"); + fprintf(fp,"# sizeof(short): %ld\n",sizeof(short)); + fprintf(fp,"# sizeof(int): %ld\n",sizeof(int)); + fprintf(fp,"# sizeof(long): %ld\n",sizeof(long)); + fprintf(fp,"# sizeof(float): %ld\n",sizeof(float)); + fprintf(fp,"# sizeof(double): %ld\n",sizeof(double)); + fprintf(fp,"# sizeof(void *): %ld\n",sizeof(void *)); + fprintf(fp,"# sizeof(size_t): %ld\n",sizeof(size_t)); + fprintf(fp,"\n"); + /* print an entry for each run-time parameter */ /* input and output files and main runtime options */ fprintf(fp,"# File input and output and runtime options\n"); @@ -1494,17 +1779,17 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, LogStringParam(fp,"WEIGHTFILE",infiles->weightfile); if(params->amplitude){ if(strlen(infiles->ampfile2)){ - LogStringParam(fp,"AMPFILE1",infiles->ampfile); - LogStringParam(fp,"AMPFILE2",infiles->ampfile2); + LogStringParam(fp,"AMPFILE1",infiles->ampfile); + LogStringParam(fp,"AMPFILE2",infiles->ampfile2); }else{ - LogStringParam(fp,"AMPFILE",infiles->ampfile); + LogStringParam(fp,"AMPFILE",infiles->ampfile); } }else{ if(strlen(infiles->ampfile2)){ - LogStringParam(fp,"PWRFILE1",infiles->ampfile); - LogStringParam(fp,"PWRFILE2",infiles->ampfile2); + LogStringParam(fp,"PWRFILE1",infiles->ampfile); + LogStringParam(fp,"PWRFILE2",infiles->ampfile2); }else{ - LogStringParam(fp,"PWRFILE",infiles->ampfile); + LogStringParam(fp,"PWRFILE",infiles->ampfile); } } LogStringParam(fp,"MAGFILE",infiles->magfile); @@ -1512,6 +1797,7 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, LogStringParam(fp,"ESTIMATEFILE",infiles->estfile); LogStringParam(fp,"COSTINFILE",infiles->costinfile); LogStringParam(fp,"COSTOUTFILE",outfiles->costoutfile); + LogStringParam(fp,"BYTEMASKFILE",infiles->bytemaskfile); LogStringParam(fp,"LOGFILE",outfiles->logfile); if(params->costmode==TOPO){ fprintf(fp,"STATCOSTMODE TOPO\n"); @@ -1545,7 +1831,7 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, /* SAR and geometry parameters */ fprintf(fp,"\n# SAR and Geometry Parameters\n"); fprintf(fp,"ALTITUDE %.8f\n", - params->orbitradius-params->earthradius); + params->orbitradius-params->earthradius); fprintf(fp,"# ORBITRADIUS %.8f\n",params->orbitradius); fprintf(fp,"EARTHRADIUS %.8f\n",params->earthradius); if(params->bperp){ @@ -1553,7 +1839,7 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, }else{ fprintf(fp,"BASELINE %.8f\n",params->baseline); fprintf(fp,"BASELINEANGLE_DEG %.8f\n", - params->baselineangle*(180.0/PI)); + params->baselineangle*(180.0/PI)); } if(params->transmitmode==PINGPONG){ fprintf(fp,"TRANSMITMODE REPEATPASS\n"); @@ -1639,8 +1925,17 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, }else{ fprintf(fp,"MAXNFLOWCYCLES %ld\n",params->maxnflowcycles); } - fprintf(fp,"SOURCEMODE %ld\n",params->sourcemode); + fprintf(fp,"NCONNNODEMIN %ld\n",params->nconnnodemin); fprintf(fp,"CS2SCALEFACTOR %ld\n",params->cs2scalefactor); + fprintf(fp,"NMAJORPRUNE %ld\n",params->nmajorprune); + fprintf(fp,"PRUNECOSTTHRESH %ld\n",params->prunecostthresh); + if(params->p!=PROBCOSTP){ + fprintf(fp,"PLPN %.8g\n",params->p); + LogBoolParam(fp,"BIDIRLPN",params->bidirlpn); + }else{ + fprintf(fp,"# PLPN %.8g (not set)\n",params->p); + LogBoolParam(fp,"# BIDIRLPN",params->bidirlpn); + } /* file names for dumping intermediate arrays */ fprintf(fp,"\n# File names for dumping intermediate arrays\n"); @@ -1655,6 +1950,13 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, LogStringParam(fp,"RAWCORRDUMPFILE",outfiles->rawcorrdumpfile); LogStringParam(fp,"CORRDUMPFILE",outfiles->corrdumpfile); + /* edge masking parameters */ + fprintf(fp,"\n# Edge masking parameters\n"); + fprintf(fp,"EDGEMASKTOP %ld\n",params->edgemasktop); + fprintf(fp,"EDGEMASKBOT %ld\n",params->edgemaskbot); + fprintf(fp,"EDGEMASKLEFT %ld\n",params->edgemaskleft); + fprintf(fp,"EDGEMASKRIGHT %ld\n",params->edgemaskright); + /* piece extraction parameters */ if(params->ntilerow==1 && params->ntilecol==1){ fprintf(fp,"\n# Piece extraction parameters\n"); @@ -1671,7 +1973,6 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, fprintf(fp,"# PIECENCOL %ld\n",params->piecencol); } - /* tile control */ fprintf(fp,"\n# Tile control\n"); fprintf(fp,"NTILEROW %ld\n",params->ntilerow); @@ -1684,11 +1985,10 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, fprintf(fp,"TILEEDGEWEIGHT %.8f\n",params->tileedgeweight); fprintf(fp,"SCNDRYARCFLOWMAX %ld\n",params->scndryarcflowmax); LogBoolParam(fp,"RMTMPTILE",params->rmtmptile); - if(params->assembleonly){ - LogStringParam(fp,"ASSEMBLEONLY",params->tiledir); - }else{ - fprintf(fp,"ASSEMBLEONLY FALSE\n"); - } + LogStringParam(fp,"DOTILEMASKFILE",infiles->dotilemaskfile); + LogStringParam(fp,"TILEDIR",params->tiledir); + LogBoolParam(fp,"ASSEMBLEONLY",params->assembleonly); + LogBoolParam(fp,"SINGLETILEREOPTIMIZE",params->onetilereopt); /* connected component control */ fprintf(fp,"\n# Connected component control\n"); @@ -1697,10 +1997,28 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, fprintf(fp,"MINCONNCOMPFRAC %.8f\n",params->minconncompfrac); fprintf(fp,"CONNCOMPTHRESH %ld\n",params->conncompthresh); fprintf(fp,"MAXNCOMPS %ld\n",params->maxncomps); + if(params->conncompouttype==CONNCOMPOUTTYPEUCHAR){ + fprintf(fp,"CONNCOMPOUTTYPE UCHAR\n"); + }else if(params->conncompouttype==CONNCOMPOUTTYPEUINT){ + fprintf(fp,"CONNCOMPOUTTYPE UINT\n"); + }else{ + fflush(NULL); + fprintf(sp0,"ERROR: bad value of params->conncompouttype\n"); + exit(ABNORMAL_EXIT); + } /* close the log file */ - fclose(fp); + if(fclose(fp)){ + fflush(NULL); + fprintf(sp0,"ERROR in closing log file %s (disk full?)\nAbort\n", + outfiles->logfile); + exit(ABNORMAL_EXIT); + } } + + /* done */ + return(0); + } @@ -1709,7 +2027,8 @@ void WriteConfigLogFile(int argc, char *argv[], infileT *infiles, * Writes a line to the log file stream for the given keyword/value * pair. */ -void LogStringParam(FILE *fp, char *key, char *value){ +static +int LogStringParam(FILE *fp, char *key, char *value){ /* see if we were passed a zero length value string */ if(strlen(value)){ @@ -1718,6 +2037,7 @@ void LogStringParam(FILE *fp, char *key, char *value){ }else{ fprintf(fp,"# Empty value for parameter %s\n",key); } + return(0); } @@ -1726,13 +2046,15 @@ void LogStringParam(FILE *fp, char *key, char *value){ * Writes a line to the log file stream for the given keyword/bool * pair. */ -void LogBoolParam(FILE *fp, char *key, signed char boolvalue){ +static +int LogBoolParam(FILE *fp, char *key, signed char boolvalue){ if(boolvalue){ fprintf(fp,"%s TRUE\n",key); }else{ fprintf(fp,"%s FALSE\n",key); } + return(0); } /* LogFileFormat() @@ -1740,7 +2062,8 @@ void LogBoolParam(FILE *fp, char *key, signed char boolvalue){ * Writes a line to the log file stream for the given keyword/ * file format pair. */ -void LogFileFormat(FILE *fp, char *key, signed char fileformat){ +static +int LogFileFormat(FILE *fp, char *key, signed char fileformat){ if(fileformat==COMPLEX_DATA){ fprintf(fp,"%s COMPLEX_DATA\n",key); @@ -1751,6 +2074,7 @@ void LogFileFormat(FILE *fp, char *key, signed char fileformat){ }else if(fileformat==ALT_SAMPLE_DATA){ fprintf(fp,"%s ALT_SAMPLE_DATA\n",key); } + return(0); } @@ -1759,27 +2083,30 @@ void LogFileFormat(FILE *fp, char *key, signed char fileformat){ * Gets the number of lines of data in the input file based on the file * size. */ -long GetNLines(infileT *infiles, long linelen){ +long GetNLines(infileT *infiles, long linelen, paramT *params){ FILE *fp; long filesize, datasize; /* get size of input file in rows and columns */ if((fp=fopen(infiles->infile,"r"))==NULL){ + fflush(NULL); fprintf(sp0,"can't open file %s\n",infiles->infile); exit(ABNORMAL_EXIT); } fseek(fp,0,SEEK_END); filesize=ftell(fp); fclose(fp); - if(infiles->infileformat==FLOAT_DATA){ + if((!params->unwrapped && infiles->infileformat==FLOAT_DATA) + || (params->unwrapped && infiles->unwrappedinfileformat==FLOAT_DATA)){ datasize=sizeof(float); }else{ datasize=2*sizeof(float); } if(filesize % (datasize*linelen)){ + fflush(NULL); fprintf(sp0,"extra data in file %s (bad linelength?)\n", - infiles->infile); + infiles->infile); exit(ABNORMAL_EXIT); } return(filesize/(datasize*linelen)); /* implicit floor */ @@ -1792,8 +2119,8 @@ long GetNLines(infileT *infiles, long linelen){ * Writes the unwrapped phase to the output file specified, in the * format given in the parameter structure. */ -void WriteOutputFile(float **mag, float **unwrappedphase, char *outfile, - outfileT *outfiles, long nrow, long ncol){ +int WriteOutputFile(float **mag, float **unwrappedphase, char *outfile, + outfileT *outfiles, long nrow, long ncol){ if(outfiles->outfileformat==ALT_LINE_DATA){ WriteAltLineFile(mag,unwrappedphase,outfile,nrow,ncol); @@ -1801,13 +2128,15 @@ void WriteOutputFile(float **mag, float **unwrappedphase, char *outfile, WriteAltSampFile(mag,unwrappedphase,outfile,nrow,ncol); }else if(outfiles->outfileformat==FLOAT_DATA){ Write2DArray((void **)unwrappedphase,outfile, - nrow,ncol,sizeof(float)); + nrow,ncol,sizeof(float)); }else{ + fflush(NULL); fprintf(sp0,"WARNING: Illegal format specified for output file\n"); fprintf(sp0," using default floating-point format\n"); Write2DArray((void **)unwrappedphase,outfile, - nrow,ncol,sizeof(float)); + nrow,ncol,sizeof(float)); } + return(0); } @@ -1831,12 +2160,14 @@ FILE *OpenOutputFile(char *outfile, char *realoutfile){ StrNCopy(dumpfile,DUMP_PATH,MAXSTRLEN); strcat(dumpfile,basename); if((fp=fopen(dumpfile,"w"))!=NULL){ + fflush(NULL); fprintf(sp0,"WARNING: Can't write to file %s. Dumping to file %s\n", - outfile,dumpfile); + outfile,dumpfile); StrNCopy(realoutfile,dumpfile,MAXSTRLEN); }else{ + fflush(NULL); fprintf(sp0,"Unable to write to file %s or dump to file %s\nAbort\n", - outfile,dumpfile); + outfile,dumpfile); exit(ABNORMAL_EXIT); } }else{ @@ -1854,8 +2185,9 @@ FILE *OpenOutputFile(char *outfile, char *realoutfile){ * is written, then a full line of phase data. Dumps the file to a * default directory if the file name/path passed in cannot be used. */ -void WriteAltLineFile(float **mag, float **phase, char *outfile, - long nrow, long ncol){ +static +int WriteAltLineFile(float **mag, float **phase, char *outfile, + long nrow, long ncol){ int row; FILE *fp; @@ -1865,12 +2197,16 @@ void WriteAltLineFile(float **mag, float **phase, char *outfile, for(row=0; rowncol>LARGESHORT || tileparams->nrow>LARGESHORT){ + fflush(NULL); fprintf(sp0,"one or more interferogram dimensions too large\n"); exit(ABNORMAL_EXIT); } if(tileparams->ncol<2 || tileparams->nrow<2){ + fflush(NULL); fprintf(sp0,"input interferogram must be at least 2x2\n"); exit(ABNORMAL_EXIT); } @@ -2001,17 +2356,18 @@ void ReadInputFile(infileT *infiles, float ***magptr, float ***wrappedphaseptr, fprintf(sp1,"Reading wrapped phase from file %s\n",infiles->infile); if(infiles->infileformat==COMPLEX_DATA){ ReadComplexFile(&mag,&wrappedphase,infiles->infile, - linelen,nlines,tileparams); + linelen,nlines,tileparams); }else if(infiles->infileformat==ALT_LINE_DATA){ ReadAltLineFile(&mag,&wrappedphase,infiles->infile, - linelen,nlines,tileparams); + linelen,nlines,tileparams); }else if(infiles->infileformat==ALT_SAMPLE_DATA){ ReadAltSampFile(&mag,&wrappedphase,infiles->infile, - linelen,nlines,tileparams); + linelen,nlines,tileparams); }else if(infiles->infileformat==FLOAT_DATA){ Read2DArray((void ***)&wrappedphase,infiles->infile,linelen,nlines, - tileparams,sizeof(float *),sizeof(float)); + tileparams,sizeof(float *),sizeof(float)); }else{ + fflush(NULL); fprintf(sp0,"illegal input file format specification\n"); exit(ABNORMAL_EXIT); } @@ -2019,9 +2375,15 @@ void ReadInputFile(infileT *infiles, float ***magptr, float ***wrappedphaseptr, /* check to make sure the input data doesn't contain NaNs or infs */ if(!ValidDataArray(wrappedphase,nrow,ncol) || (mag!=NULL && !ValidDataArray(mag,nrow,ncol))){ + fflush(NULL); fprintf(sp0,"NaN or infinity found in input float data\nAbort\n"); exit(ABNORMAL_EXIT); } + if(mag!=NULL && !NonNegDataArray(mag,nrow,ncol)){ + fflush(NULL); + fprintf(sp0,"Negative magnitude found in input magnitude data\nAbort\n"); + exit(ABNORMAL_EXIT); + } /* flip the sign of the wrapped phase if flip flag is set */ FlipPhaseArraySign(wrappedphase,params,nrow,ncol); @@ -2035,14 +2397,15 @@ void ReadInputFile(infileT *infiles, float ***magptr, float ***wrappedphaseptr, fprintf(sp1,"Reading unwrapped phase from file %s\n",infiles->infile); if(infiles->unwrappedinfileformat==ALT_LINE_DATA){ ReadAltLineFile(&mag,&unwrappedphase,infiles->infile, - linelen,nlines,tileparams); + linelen,nlines,tileparams); }else if(infiles->unwrappedinfileformat==ALT_SAMPLE_DATA){ ReadAltSampFile(&mag,&unwrappedphase,infiles->infile, - linelen,nlines,tileparams); + linelen,nlines,tileparams); }else if(infiles->unwrappedinfileformat==FLOAT_DATA){ Read2DArray((void ***)&unwrappedphase,infiles->infile,linelen,nlines, - tileparams,sizeof(float *),sizeof(float)); + tileparams,sizeof(float *),sizeof(float)); }else{ + fflush(NULL); fprintf(sp0,"Illegal input file format specification\nAbort\n"); exit(ABNORMAL_EXIT); } @@ -2050,9 +2413,16 @@ void ReadInputFile(infileT *infiles, float ***magptr, float ***wrappedphaseptr, /* check to make sure the input data doesn't contain NaNs or infs */ if(!ValidDataArray(unwrappedphase,nrow,ncol) || (mag!=NULL && !ValidDataArray(mag,nrow,ncol))){ + fflush(NULL); fprintf(sp0,"NaN or infinity found in input float data\nAbort\n"); exit(ABNORMAL_EXIT); } + if(mag!=NULL && !NonNegDataArray(mag,nrow,ncol)){ + fflush(NULL); + fprintf(sp0,"Negative magnitude found in input magnitude data\nAbort\n"); + exit(ABNORMAL_EXIT); + } + /* flip the sign of the input unwrapped phase if flip flag is set */ FlipPhaseArraySign(unwrappedphase,params,nrow,ncol); @@ -2065,12 +2435,20 @@ void ReadInputFile(infileT *infiles, float ***magptr, float ***wrappedphaseptr, } + /* show which pixels read if tiling */ + if(tileparams->nrow!=nlines || tileparams->ncol!=linelen){ + fprintf(sp2, + "Read %ldx%ld array of pixels starting at row,col %ld,%ld\n", + tileparams->nrow,tileparams->ncol, + tileparams->firstrow,tileparams->firstcol); + } + /* get memory for mag (power) image and set to unity if not passed */ if(mag==NULL){ mag=(float **)Get2DMem(nrow,ncol,sizeof(float *),sizeof(float)); for(row=0;rowmagfile)){ fprintf(sp1,"Reading interferogram magnitude from file %s\n", - infiles->magfile); + infiles->magfile); if(infiles->magfileformat==FLOAT_DATA){ Read2DArray((void ***)&mag,infiles->magfile,linelen,nlines,tileparams, - sizeof(float *),sizeof(float)); + sizeof(float *),sizeof(float)); }else if(infiles->magfileformat==COMPLEX_DATA){ ReadComplexFile(&mag,&dummy,infiles->magfile,linelen,nlines, - tileparams); + tileparams); }else if(infiles->magfileformat==ALT_LINE_DATA){ ReadAltLineFile(&mag,&dummy,infiles->magfile,linelen,nlines, - tileparams); + tileparams); }else if(infiles->magfileformat==ALT_SAMPLE_DATA){ ReadAltSampFile(&mag,&dummy,infiles->magfile,linelen,nlines, - tileparams); + tileparams); } } if(dummy!=NULL){ Free2DArray((void **)dummy,tileparams->nrow); } + return(0); +} + +/* function: ReadByteMask() + * ------------------------ + * Read signed byte mask value; set magnitude to zero where byte mask + * is zero or where pixel is close enough to edge as defined by + * edgemask parameters; leave magnitude unchanged otherwise. + */ +int ReadByteMask(float **mag, infileT *infiles, long linelen, long nlines, + tileparamT *tileparams, paramT *params){ + + long row, col, nrow, ncol, fullrow, fullcol; + signed char **bytemask; + + /* set up */ + nrow=tileparams->nrow; + ncol=tileparams->ncol; + + /* read byte mask (memory allocated by read function) */ + bytemask=NULL; + if(strlen(infiles->bytemaskfile)){ + fprintf(sp1,"Reading byte mask from file %s\n",infiles->bytemaskfile); + Read2DArray((void ***)&bytemask,infiles->bytemaskfile,linelen,nlines, + tileparams,sizeof(signed char *),sizeof(signed char)); + } + + /* loop over rows and columns and zero out magnitude where mask is zero */ + /* also mask edges according to edgemask parameters */ + for(row=0;rowfirstrow+row; + fullcol=tileparams->firstcol+col; + if((bytemask!=NULL && bytemask[row][col]==0) + || fullrowedgemasktop + || fullcoledgemaskleft + || fullrow>=nlines-params->edgemaskbot + || fullcol>=linelen-params->edgemaskright){ + mag[row][col]=0; + } + } + } + + /* free bytemask memory */ + if(bytemask!=NULL){ + Free2DArray((void **)bytemask,nrow); + } + + /* done */ + return(0); + } @@ -2122,9 +2554,9 @@ void ReadMagnitude(float **mag, infileT *infiles, long linelen, long nlines, * ------------------------------------- * Reads the unwrapped-phase estimate from a file (assumes file name exists). */ -void ReadUnwrappedEstimateFile(float ***unwrappedestptr, infileT *infiles, - long linelen, long nlines, - paramT *params, tileparamT *tileparams){ +int ReadUnwrappedEstimateFile(float ***unwrappedestptr, infileT *infiles, + long linelen, long nlines, + paramT *params, tileparamT *tileparams){ float **dummy; long nrow, ncol; @@ -2137,19 +2569,20 @@ void ReadUnwrappedEstimateFile(float ***unwrappedestptr, infileT *infiles, /* read data */ fprintf(sp1,"Reading coarse unwrapped estimate from file %s\n", - infiles->estfile); + infiles->estfile); if(infiles->estfileformat==ALT_LINE_DATA){ ReadAltLineFilePhase(unwrappedestptr,infiles->estfile, - linelen,nlines,tileparams); + linelen,nlines,tileparams); }else if(infiles->estfileformat==FLOAT_DATA){ Read2DArray((void ***)unwrappedestptr,infiles->estfile,linelen,nlines, - tileparams,sizeof(float *),sizeof(float)); + tileparams,sizeof(float *),sizeof(float)); }else if(infiles->estfileformat==ALT_SAMPLE_DATA){ ReadAltSampFile(&dummy,unwrappedestptr,infiles->estfile, - linelen,nlines,tileparams); + linelen,nlines,tileparams); }else{ + fflush(NULL); fprintf(sp0,"Illegal file format specification for file %s\nAbort\n", - infiles->estfile); + infiles->estfile); } if(dummy!=NULL){ Free2DArray((void **)dummy,nrow); @@ -2157,6 +2590,7 @@ void ReadUnwrappedEstimateFile(float ***unwrappedestptr, infileT *infiles, /* make sure data is valid */ if(!ValidDataArray(*unwrappedestptr,nrow,ncol)){ + fflush(NULL); fprintf(sp0,"Infinity or NaN found in file %s\nAbort\n",infiles->estfile); exit(ABNORMAL_EXIT); } @@ -2164,6 +2598,9 @@ void ReadUnwrappedEstimateFile(float ***unwrappedestptr, infileT *infiles, /* flip the sign of the unwrapped estimate if the flip flag is set */ FlipPhaseArraySign(*unwrappedestptr,params,nrow,ncol); + /* done */ + return(0); + } @@ -2171,8 +2608,8 @@ void ReadUnwrappedEstimateFile(float ***unwrappedestptr, infileT *infiles, * --------------------------- * Read in weights form rowcol format file of short ints. */ -void ReadWeightsFile(short ***weightsptr,char *weightfile, - long linelen, long nlines, tileparamT *tileparams){ +int ReadWeightsFile(short ***weightsptr,char *weightfile, + long linelen, long nlines, tileparamT *tileparams){ long row, col, nrow, ncol; short **rowweight, **colweight; @@ -2185,38 +2622,43 @@ void ReadWeightsFile(short ***weightsptr,char *weightfile, if(strlen(weightfile)){ fprintf(sp1,"Reading weights from file %s\n",weightfile); Read2DRowColFile((void ***)weightsptr,weightfile,linelen,nlines, - tileparams,sizeof(short)); + tileparams,sizeof(short)); rowweight=*weightsptr; colweight=&(*weightsptr)[nrow-1]; printwarning=FALSE; for(row=0;rowampfile,infiles->ampfile2); + infiles->ampfile,infiles->ampfile2); if(infiles->ampfileformat==FLOAT_DATA){ Read2DArray((void ***)&pwr1,infiles->ampfile,linelen,nlines,tileparams, - sizeof(float *),sizeof(float)); + sizeof(float *),sizeof(float)); Read2DArray((void ***)&pwr2,infiles->ampfile2,linelen,nlines,tileparams, - sizeof(float *),sizeof(float)); + sizeof(float *),sizeof(float)); }else{ + fflush(NULL); fprintf(sp0,"Illegal file formats specified for files %s, %s\nAbort\n", - infiles->ampfile,infiles->ampfile2); + infiles->ampfile,infiles->ampfile2); exit(ABNORMAL_EXIT); } @@ -2264,18 +2707,19 @@ void ReadIntensity(float ***pwrptr, float ***pwr1ptr, float ***pwr2ptr, fprintf(sp1,"Reading brightness data from file %s\n",infiles->ampfile); if(infiles->ampfileformat==ALT_SAMPLE_DATA){ ReadAltSampFile(&pwr1,&pwr2,infiles->ampfile,linelen,nlines, - tileparams); + tileparams); }else if(infiles->ampfileformat==ALT_LINE_DATA){ ReadAltLineFile(&pwr1,&pwr2,infiles->ampfile,linelen,nlines, - tileparams); + tileparams); }else if(infiles->ampfileformat==FLOAT_DATA){ Read2DArray((void ***)&pwr,infiles->ampfile,linelen,nlines,tileparams, - sizeof(float *),sizeof(float)); + sizeof(float *),sizeof(float)); pwr1=NULL; pwr2=NULL; }else{ + fflush(NULL); fprintf(sp0,"Illegal file format specified for file %s\nAbort\n", - infiles->ampfile); + infiles->ampfile); exit(ABNORMAL_EXIT); } } @@ -2284,20 +2728,28 @@ void ReadIntensity(float ***pwrptr, float ***pwr1ptr, float ***pwr2ptr, if((pwr1!=NULL && !ValidDataArray(pwr1,nrow,ncol)) || (pwr2!=NULL && !ValidDataArray(pwr2,nrow,ncol)) || (pwr!=NULL && !ValidDataArray(pwr,nrow,ncol))){ + fflush(NULL); fprintf(sp0,"Infinity or NaN found in amplitude or power data\nAbort\n"); exit(ABNORMAL_EXIT); } + if((pwr1!=NULL && !NonNegDataArray(pwr1,nrow,ncol)) + || (pwr2!=NULL && !NonNegDataArray(pwr2,nrow,ncol)) + || (pwr!=NULL && !NonNegDataArray(pwr,nrow,ncol))){ + fflush(NULL); + fprintf(sp0,"Negative value found in amplitude or power data\nAbort\n"); + exit(ABNORMAL_EXIT); + } /* if data is amplitude, square to get power */ if(params->amplitude){ for(row=0;rowcorrfile,linelen,nlines,tileparams); }else if(infiles->corrfileformat==FLOAT_DATA){ Read2DArray((void ***)&corr,infiles->corrfile,linelen,nlines,tileparams, - sizeof(float *),sizeof(float)); + sizeof(float *),sizeof(float)); }else{ + fflush(NULL); fprintf(sp0,"Illegal file format specified for file %s\nAbort\n", - infiles->corrfile); + infiles->corrfile); exit(ABNORMAL_EXIT); } @@ -2359,6 +2815,9 @@ void ReadCorrelation(float ***corrptr, infileT *infiles, } *corrptr=corr; + /* done */ + return(0); + } @@ -2370,14 +2829,15 @@ void ReadCorrelation(float ***corrptr, infileT *infiles, * ncol refers to the number of complex elements in one line of * data. */ -void ReadAltLineFile(float ***mag, float ***phase, char *alfile, - long linelen, long nlines, tileparamT *tileparams){ +int ReadAltLineFile(float ***mag, float ***phase, char *alfile, + long linelen, long nlines, tileparamT *tileparams){ FILE *fp; long filesize,row,nrow,ncol,padlen; /* open the file */ if((fp=fopen(alfile,"r"))==NULL){ + fflush(NULL); fprintf(sp0,"Can't open file %s\nAbort\n",alfile); exit(ABNORMAL_EXIT); } @@ -2386,8 +2846,9 @@ void ReadAltLineFile(float ***mag, float ***phase, char *alfile, fseek(fp,0,SEEK_END); filesize=ftell(fp); if(filesize!=(2*nlines*linelen*sizeof(float))){ + fflush(NULL); fprintf(sp0,"File %s wrong size (%ldx%ld array expected)\nAbort\n", - alfile,nlines,linelen); + alfile,nlines,linelen); exit(ABNORMAL_EXIT); } fseek(fp,0,SEEK_SET); @@ -2404,15 +2865,17 @@ void ReadAltLineFile(float ***mag, float ***phase, char *alfile, /* read the data */ fseek(fp,(tileparams->firstrow*2*linelen+tileparams->firstcol) - *sizeof(float),SEEK_CUR); + *sizeof(float),SEEK_CUR); padlen=(linelen-ncol)*sizeof(float); for(row=0; rowfirstrow*2*linelen+linelen - +tileparams->firstcol)*sizeof(float),SEEK_CUR); + +tileparams->firstcol)*sizeof(float),SEEK_CUR); padlen=(2*linelen-ncol)*sizeof(float); for(row=0; rowfirstrow*linelen+tileparams->firstcol) - *2*sizeof(float),SEEK_CUR); + *2*sizeof(float),SEEK_CUR); padlen=(linelen-ncol)*2*sizeof(float); for(row=0; row=TWOPI){ @@ -2542,6 +3020,9 @@ void ReadComplexFile(float ***mag, float ***phase, char *rifile, free(inpline); fclose(fp); + /* done */ + return(0); + } @@ -2550,14 +3031,15 @@ void ReadComplexFile(float ***mag, float ***phase, char *rifile, * Reads file of real data of size elsize. Assumes the native byte order * of the platform. */ -void Read2DArray(void ***arr, char *infile, long linelen, long nlines, - tileparamT *tileparams, size_t elptrsize, size_t elsize){ +int Read2DArray(void ***arr, char *infile, long linelen, long nlines, + tileparamT *tileparams, size_t elptrsize, size_t elsize){ FILE *fp; long filesize,row,nrow,ncol,padlen; /* open the file */ if((fp=fopen(infile,"r"))==NULL){ + fflush(NULL); fprintf(sp0,"Can't open file %s\nAbort\n",infile); exit(ABNORMAL_EXIT); } @@ -2566,8 +3048,9 @@ void Read2DArray(void ***arr, char *infile, long linelen, long nlines, fseek(fp,0,SEEK_END); filesize=ftell(fp); if(filesize!=(nlines*linelen*elsize)){ + fflush(NULL); fprintf(sp0,"File %s wrong size (%ldx%ld array expected)\nAbort\n", - infile,nlines,linelen); + infile,nlines,linelen); exit(ABNORMAL_EXIT); } fseek(fp,0,SEEK_SET); @@ -2581,10 +3064,11 @@ void Read2DArray(void ***arr, char *infile, long linelen, long nlines, /* read the data */ fseek(fp,(linelen*tileparams->firstrow+tileparams->firstcol) - *elsize,SEEK_CUR); + *elsize,SEEK_CUR); padlen=(linelen-ncol)*elsize; for(row=0; rowfirstrow*linelen+tileparams->firstcol) - *2*sizeof(float),SEEK_CUR); + *2*sizeof(float),SEEK_CUR); padlen=(linelen-ncol)*2*sizeof(float); for(row=0; rowfirstrow+tileparams->firstcol) - *size,SEEK_SET); + *size,SEEK_SET); padlen=(linelen-ncol)*size; for(row=0; rowfirstrow - +tileparams->firstcol)*size,SEEK_SET); + +tileparams->firstcol)*size,SEEK_SET); for(row=nrow-1; row<2*nrow-1; row++){ if(fread((*arr)[row],size,ncol-1,fp)!=ncol-1){ + fflush(NULL); fprintf(sp0,"Error while reading from file %s\nAbort\n",filename); exit(ABNORMAL_EXIT); } fseek(fp,padlen,SEEK_CUR); } fclose(fp); + + /* done */ + return(0); + } @@ -2728,14 +3229,15 @@ void Read2DRowColFile(void ***arr, char *filename, long linelen, long nlines, * equivalent rows in the orginal pixel file (whose arcs are represented * in the RowCol file). */ -void Read2DRowColFileRows(void ***arr, char *filename, long linelen, - long nlines, tileparamT *tileparams, size_t size){ +int Read2DRowColFileRows(void ***arr, char *filename, long linelen, + long nlines, tileparamT *tileparams, size_t size){ FILE *fp; long row, nel, nrow, ncol, padlen, filelen; /* open the file */ if((fp=fopen(filename,"r"))==NULL){ + fflush(NULL); fprintf(sp0,"Can't open file %s\nAbort\n",filename); exit(ABNORMAL_EXIT); } @@ -2748,8 +3250,9 @@ void Read2DRowColFileRows(void ***arr, char *filename, long linelen, /* check file size */ if(2*linelen*nlines-nlines-linelen != nel || (filelen % size)){ + fflush(NULL); fprintf(sp0,"File %s wrong size (%ld elements expected)\nAbort\n", - filename,2*linelen*nlines-nlines-linelen); + filename,2*linelen*nlines-nlines-linelen); exit(ABNORMAL_EXIT); } @@ -2762,16 +3265,21 @@ void Read2DRowColFileRows(void ***arr, char *filename, long linelen, /* read arrays */ fseek(fp,(linelen*tileparams->firstrow+tileparams->firstcol) - *size,SEEK_SET); + *size,SEEK_SET); padlen=(linelen-ncol)*size; for(row=0; rowdumpall){ if(!strlen(outfiles->initfile)){ @@ -2814,6 +3322,7 @@ void SetDumpAll(outfileT *outfiles, paramT *params){ StrNCopy(outfiles->rawcorrdumpfile,DUMP_RAWCORRDUMPFILE,MAXSTRLEN); } } + return(0); } @@ -2821,33 +3330,38 @@ void SetDumpAll(outfileT *outfiles, paramT *params){ * ----------------------------- * Sets the default stream pointers (global variables). */ -void SetStreamPointers(void){ +int SetStreamPointers(void){ fflush(NULL); if((sp0=DEF_ERRORSTREAM)==NULL){ if((sp0=fopen(NULLFILE,"w"))==NULL){ + fflush(NULL); fprintf(sp0,"unable to open null file %s\n",NULLFILE); exit(ABNORMAL_EXIT); } } if((sp1=DEF_OUTPUTSTREAM)==NULL){ if((sp1=fopen(NULLFILE,"w"))==NULL){ + fflush(NULL); fprintf(sp0,"unable to open null file %s\n",NULLFILE); exit(ABNORMAL_EXIT); } } if((sp2=DEF_VERBOSESTREAM)==NULL){ if((sp2=fopen(NULLFILE,"w"))==NULL){ + fflush(NULL); fprintf(sp0,"unable to open null file %s\n",NULLFILE); exit(ABNORMAL_EXIT); } } if((sp3=DEF_COUNTERSTREAM)==NULL){ if((sp3=fopen(NULLFILE,"w"))==NULL){ + fflush(NULL); fprintf(sp0,"unable to open null file %s\n",NULLFILE); exit(ABNORMAL_EXIT); } } + return(0); } @@ -2856,7 +3370,7 @@ void SetStreamPointers(void){ * Set the global stream pointer sp2 to be stdout if the verbose flag * is set in the parameter data type. */ -void SetVerboseOut(paramT *params){ +int SetVerboseOut(paramT *params){ fflush(NULL); if(params->verbose){ @@ -2869,6 +3383,7 @@ void SetVerboseOut(paramT *params){ } sp3=stdout; } + return(0); } @@ -2877,8 +3392,8 @@ void SetVerboseOut(paramT *params){ * Reset the global stream pointers for a child. Streams equal to stdout * are directed to a log file, and errors are written to the screen. */ -void ChildResetStreamPointers(pid_t pid, long tilerow, long tilecol, - paramT *params){ +int ChildResetStreamPointers(pid_t pid, long tilerow, long tilecol, + paramT *params){ FILE *logfp; char logfile[MAXSTRLEN], cwd[MAXSTRLEN]; @@ -2886,11 +3401,12 @@ void ChildResetStreamPointers(pid_t pid, long tilerow, long tilecol, fflush(NULL); sprintf(logfile,"%s/%s%ld_%ld",params->tiledir,LOGFILEROOT,tilerow,tilecol); if((logfp=fopen(logfile,"w"))==NULL){ + fflush(NULL); fprintf(sp0,"Unable to open log file %s\nAbort\n",logfile); exit(ABNORMAL_EXIT); } fprintf(logfp,"%s (pid %ld): unwrapping tile at row %ld, column %ld\n\n", - PROGRAMNAME,(long )pid,tilerow,tilecol); + PROGRAMNAME,(long )pid,tilerow,tilecol); if(getcwd(cwd,MAXSTRLEN)!=NULL){ fprintf(logfp,"Current working directory is %s\n",cwd); } @@ -2907,9 +3423,11 @@ void ChildResetStreamPointers(pid_t pid, long tilerow, long tilecol, fclose(sp3); } if((sp3=fopen(NULLFILE,"w"))==NULL){ + fflush(NULL); fprintf(sp0,"Unable to open null file %s\n",NULLFILE); exit(ABNORMAL_EXIT); } + return(0); } @@ -2917,8 +3435,8 @@ void ChildResetStreamPointers(pid_t pid, long tilerow, long tilecol, * ----------------------------- * Dumps incremental cost arrays, creating file names for them. */ -void DumpIncrCostFiles(incrcostT **incrcosts, long iincrcostfile, - long nflow, long nrow, long ncol){ +int DumpIncrCostFiles(incrcostT **incrcosts, long iincrcostfile, + long nflow, long nrow, long ncol){ long row, col, maxcol; char incrcostfile[MAXSTRLEN]; @@ -2944,7 +3462,7 @@ void DumpIncrCostFiles(incrcostT **incrcosts, long iincrcostfile, sprintf(tempstr,".%ld_%ld",iincrcostfile,nflow); strncat(incrcostfile,tempstr,MAXSTRLEN-strlen(incrcostfile)-1); Write2DRowColArray((void **)tempcosts,incrcostfile, - nrow,ncol,sizeof(short)); + nrow,ncol,sizeof(short)); for(row=0;row<2*nrow-1;row++){ if(rowtiledir)){ + ParseFilename(outfiles->outfile,path,basename); + sprintf(params->tiledir,"%s%s%ld",path,TMPTILEDIRROOT,params->parentpid); + } - /* create name for tile directory (use pid to make unique) */ - ParseFilename(outfiles->outfile,path,basename); - sprintf(params->tiledir,"%s%s%ld",path,TMPTILEDIRROOT,(long )getpid()); + /* return if directory exists */ + /* this is a hack; tiledir could be file or could give other stat() error */ + /* but if there is a problem, the error will be caught later */ + if(!stat(params->tiledir,statbuf)){ + return(0); + } /* create tile directory */ fprintf(sp1,"Creating temporary directory %s\n",params->tiledir); if(mkdir(params->tiledir,TILEDIRMODE)){ + fflush(NULL); fprintf(sp0,"Error creating directory %s\nAbort\n",params->tiledir); exit(ABNORMAL_EXIT); } + /* done */ + return(0); + +} + + +/* function: SetTileInitOutfile() + * ------------------------------ + * Set name of temporary tile-mode output assuming nominal output file + * name is in string passed. Write new name in string memory pointed + * to by input. + */ +int SetTileInitOutfile(char *outfile, long pid){ + + char path[MAXSTRLEN], basename[MAXSTRLEN]; + struct stat statbuf[1]; + + + /* initialize, including statubf for good measure even though not used */ + memset(path,0,MAXSTRLEN); + memset(basename,0,MAXSTRLEN); + memset(statbuf,0,sizeof(struct stat)); + + /* create name for output file (use pid to make unique) */ + ParseFilename(outfile,path,basename); + sprintf(outfile,"%s%s%ld_%s",path,TILEINITFILEROOT,pid,basename); + + /* see if file already exists and exit if so */ + if(!stat(outfile,statbuf)){ + fprintf(sp0, + "ERROR: refusing to write tile init to existing file %s\n",outfile); + exit(ABNORMAL_EXIT); + } + + /* done */ + return(0); + } @@ -2997,13 +3572,14 @@ void MakeTileDir(paramT *params, outfileT *outfiles){ * should be no more than MAXSTRLEN characters. The output path * has a trailing "/" character. */ -void ParseFilename(char *filename, char *path, char *basename){ +int ParseFilename(char *filename, char *path, char *basename){ char tempstring[MAXSTRLEN]; char *tempouttok; /* make sure we have a nonzero filename */ if(!strlen(filename)){ + fflush(NULL); fprintf(sp0,"Zero-length filename passed to ParseFilename()\nAbort\n"); exit(ABNORMAL_EXIT); } @@ -3029,8 +3605,12 @@ void ParseFilename(char *filename, char *path, char *basename){ /* make sure we have a nonzero base filename */ if(!strlen(basename)){ + fflush(NULL); fprintf(sp0,"Zero-length base filename found in ParseFilename()\nAbort\n"); exit(ABNORMAL_EXIT); } + /* done */ + return(0); + } diff --git a/contrib/Snaphu/src/snaphu_solver.c b/contrib/Snaphu/src/snaphu_solver.c index 09e284ce..5060f01a 100644 --- a/contrib/Snaphu/src/snaphu_solver.c +++ b/contrib/Snaphu/src/snaphu_solver.c @@ -21,26 +21,189 @@ #include #include #include +#include #include #include #include "snaphu.h" +/* static variables local this file */ + +/* pointers to functions for tailoring network solver to specific topologies */ +static nodeT *(*NeighborNode)(nodeT *, long, long *, nodeT **, nodeT *, long *, + long *, long *, long, long, boundaryT *, + nodesuppT **); +static void (*GetArc)(nodeT *, nodeT *, long *, long *, long *, long, long, + nodeT **, nodesuppT **); + +/* static (local) function prototypes */ +static +void AddNewNode(nodeT *from, nodeT *to, long arcdir, bucketT *bkts, + long nflow, incrcostT **incrcosts, long arcrow, long arccol, + paramT *params); +static +void CheckArcReducedCost(nodeT *from, nodeT *to, nodeT *apex, + long arcrow, long arccol, long arcdir, + candidateT **candidatebagptr, + long *candidatebagnextptr, + long *candidatebagsizeptr, incrcostT **incrcosts, + signed char **iscandidate, paramT *params); +static +nodeT *InitBoundary(nodeT *source, nodeT **nodes, + boundaryT *boundary, nodesuppT **nodesupp, float **mag, + nodeT *ground, long ngroundarcs, long nrow, long ncol, + paramT *params, long *nconnectedptr); +static +long CheckBoundary(nodeT **nodes, float **mag, nodeT *ground, long ngroundarcs, + boundaryT *boundary, long nrow, long ncol, + paramT *params, nodeT *start); +static +int IsRegionEdgeArc(float **mag, long arcrow, long arccol, + long nrow, long ncol); +static +int IsRegionInteriorArc(float **mag, long arcrow, long arccol, + long nrow, long ncol); +static +int IsRegionArc(float **mag, long arcrow, long arccol, + long nrow, long ncol); +static +int IsRegionEdgeNode(float **mag, long row, long col, long nrow, long ncol); +static +int CleanUpBoundaryNodes(nodeT *source, boundaryT *boundary, float **mag, + nodeT **nodes, nodeT *ground, + long nrow, long ncol, long ngroundarcs, + nodesuppT **nodesupp); +static +int DischargeBoundary(nodeT **nodes, nodeT *ground, + boundaryT *boundary, nodesuppT **nodesupp, short **flows, + signed char **iscandidate, float **mag, + float **wrappedphase, long ngroundarcs, + long nrow, long ncol); +static +int InitTree(nodeT *source, nodeT **nodes, + boundaryT *boundary, nodesuppT **nodesupp, + nodeT *ground, long ngroundarcs, bucketT *bkts, long nflow, + incrcostT **incrcosts, long nrow, long ncol, paramT *params); +static +nodeT *FindApex(nodeT *from, nodeT *to); +static +int CandidateCompare(const void *c1, const void *c2); +static +nodeT *NeighborNodeGrid(nodeT *node1, long arcnum, long *upperarcnumptr, + nodeT **nodes, nodeT *ground, long *arcrowptr, + long *arccolptr, long *arcdirptr, long nrow, + long ncol, boundaryT *boundary, nodesuppT **nodesupp); +static inline +long GetArcNumLims(long fromrow, long *upperarcnumptr, + long ngroundarcs, boundaryT *boundary); +static +nodeT *NeighborNodeNonGrid(nodeT *node1, long arcnum, long *upperarcnumptr, + nodeT **nodes, nodeT *ground, long *arcrowptr, + long *arccolptr, long *arcdirptr, long nrow, + long ncol, boundaryT *boundary, + nodesuppT **nodesupp); +static +void GetArcGrid(nodeT *from, nodeT *to, long *arcrow, long *arccol, + long *arcdir, long nrow, long ncol, + nodeT **nodes, nodesuppT **nodesupp); +static +void GetArcNonGrid(nodeT *from, nodeT *to, long *arcrow, long *arccol, + long *arcdir, long nrow, long ncol, + nodeT **nodes, nodesuppT **nodesupp); +static +void NonDegenUpdateChildren(nodeT *startnode, nodeT *lastnode, + nodeT *nextonpath, long dgroup, + long ngroundarcs, long nflow, nodeT **nodes, + nodesuppT **nodesupp, nodeT *ground, + boundaryT *boundary, + nodeT ***apexes, incrcostT **incrcosts, + long nrow, long ncol, paramT *params); +static +long PruneTree(nodeT *source, nodeT **nodes, nodeT *ground, boundaryT *boundary, + nodesuppT **nodesupp, incrcostT **incrcosts, + short **flows, long ngroundarcs, long prunecostthresh, + long nrow, long ncol); +static +int CheckLeaf(nodeT *node1, nodeT **nodes, nodeT *ground, boundaryT *boundary, + nodesuppT **nodesupp, incrcostT **incrcosts, + short **flows, long ngroundarcs, long nrow, long ncol, + long prunecostthresh); +static +int GridNodeMaskStatus(long row, long col, float **mag); +static +int GroundMaskStatus(long nrow, long ncol, float **mag); +static +int InitBuckets(bucketT *bkts, nodeT *source, long nbuckets); +static +nodeT *MinOutCostNode(bucketT *bkts); +static +nodeT *SelectConnNodeSource(nodeT **nodes, float **mag, + nodeT *ground, long ngroundarcs, + long nrow, long ncol, + paramT *params, nodeT *start, long *nconnectedptr); +static +long ScanRegion(nodeT *start, nodeT **nodes, float **mag, + nodeT *ground, long ngroundarcs, + long nrow, long ncol, int groupsetting); +static +short GetCost(incrcostT **incrcosts, long arcrow, long arccol, + long arcdir); +static +void SolveMST(nodeT **nodes, nodeT *source, nodeT *ground, + bucketT *bkts, short **mstcosts, signed char **residue, + signed char **arcstatus, long nrow, long ncol); +static +long DischargeTree(nodeT *source, short **mstcosts, short **flows, + signed char **residue, signed char **arcstatus, + nodeT **nodes, nodeT *ground, long nrow, long ncol); +static +signed char ClipFlow(signed char **residue, short **flows, + short **mstcosts, long nrow, long ncol, + long maxflow); + + + +/* function: SetGridNetworkFunctionPointers() + * ------------------------------------------ + */ +int SetGridNetworkFunctionPointers(void){ + + /* set static pointers to functions */ + NeighborNode=NeighborNodeGrid; + GetArc=GetArcGrid; + return(0); + +} + + +/* function: SetNonGridNetworkFunctionPointers() + * --------------------------------------------- + */ +int SetNonGridNetworkFunctionPointers(void){ + + /* set static pointers to functions */ + NeighborNode=NeighborNodeNonGrid; + GetArc=GetArcNonGrid; + return(0); + +} + + /* function: TreeSolve() * --------------------- * Solves the nonlinear network optimization problem. */ -long TreeSolve(nodeT **nodes, nodesuppT **nodesupp, nodeT *ground, - nodeT *source, candidateT **candidatelistptr, - candidateT **candidatebagptr, long *candidatelistsizeptr, - long *candidatebagsizeptr, bucketT *bkts, short **flows, - void **costs, incrcostT **incrcosts, nodeT ***apexes, - signed char **iscandidate, long ngroundarcs, long nflow, - float **mag, float **wrappedphase, char *outfile, - long nnoderow, short *nnodesperrow, long narcrow, - short *narcsperrow, long nrow, long ncol, - outfileT *outfiles, paramT *params){ +long TreeSolve(nodeT **nodes, nodesuppT **nodesupp, nodeT *ground, + nodeT *source, candidateT **candidatelistptr, + candidateT **candidatebagptr, long *candidatelistsizeptr, + long *candidatebagsizeptr, bucketT *bkts, short **flows, + void **costs, incrcostT **incrcosts, nodeT ***apexes, + signed char **iscandidate, long ngroundarcs, long nflow, + float **mag, float **wrappedphase, char *outfile, + long nnoderow, int *nnodesperrow, long narcrow, + int *narcsperrow, long nrow, long ncol, + outfileT *outfiles, long nconnected, paramT *params){ long i, row, col, arcrow, arccol, arcdir, arcnum, upperarcnum; long arcrow1, arccol1, arcdir1, arcrow2, arccol2, arcdir2; @@ -48,16 +211,38 @@ long TreeSolve(nodeT **nodes, nodesuppT **nodesupp, nodeT *ground, long violation, groupcounter, fromgroup, group1, apexlistbase, apexlistlen; long cyclecost, outcostto, startlevel, dlevel, doutcost, dincost; long candidatelistlen, candidatebagnext; - long inondegen, ipivots, nnodes, nnewnodes, maxnewnodes, templong; + long inondegen, ipivots, nnewnodes, maxnewnodes, templong; + long nmajor, nmajorprune, npruned, prunecostthresh; signed char fromside; candidateT *candidatelist, *candidatebag, *tempcandidateptr; nodeT *from, *to, *cycleapex, *node1, *node2, *leavingparent, *leavingchild; nodeT *root, *mntpt, *oldmntpt, *skipthread, *tempnode1, *tempnode2; nodeT *firstfromnode, *firsttonode; nodeT **apexlist; + boundaryT boundary[1]; float **unwrappedphase; + - + /* initilize structures on stack to zero for good measure */ + memset(boundary,0,sizeof(boundaryT)); + + /* initialize some variables to zero to stop compiler warnings */ + from=NULL; + to=NULL; + cycleapex=NULL; + node1=NULL; + node2=NULL; + leavingparent=NULL; + leavingchild=NULL; + root=NULL; + mntpt=NULL; + oldmntpt=NULL; + skipthread=NULL; + tempnode1=NULL; + tempnode2=NULL; + firstfromnode=NULL; + firsttonode=NULL; + /* dereference some pointers and store as local variables */ candidatelist=(*candidatelistptr); candidatebag=(*candidatebagptr); @@ -66,34 +251,43 @@ long TreeSolve(nodeT **nodes, nodesuppT **nodesupp, nodeT *ground, candidatelistlen=0; candidatebagnext=0; + /* initialize boundary, which affects network structure */ + /* recompute number of connected nodes since setting boundary may make */ + /* some nodes inaccessible */ + source=InitBoundary(source,nodes,boundary,nodesupp,mag, + ground,ngroundarcs,nrow,ncol,params,&nconnected); + /* set up */ bkts->curr=bkts->maxind; - nnodes=InitTree(source,nodes,nodesupp,ground,ngroundarcs,bkts,nflow, - incrcosts,apexes,iscandidate,nnoderow,nnodesperrow, - narcrow,narcsperrow,nrow,ncol,params); + InitTree(source,nodes,boundary,nodesupp,ground,ngroundarcs,bkts,nflow, + incrcosts,nrow,ncol,params); apexlistlen=INITARRSIZE; apexlist=MAlloc(apexlistlen*sizeof(nodeT *)); groupcounter=2; ipivots=0; inondegen=0; - maxnewnodes=ceil(nnodes*params->maxnewnodeconst); + maxnewnodes=ceil(nconnected*params->maxnewnodeconst); nnewnodes=0; treesize=1; + npruned=0; + nmajor=0; + nmajorprune=params->nmajorprune; + prunecostthresh=params->prunecostthresh;; fprintf(sp3,"Treesize: %-10ld Pivots: %-11ld Improvements: %-11ld", - treesize,ipivots,inondegen); + treesize,ipivots,inondegen); /* loop over each entering node (note, source already on tree) */ - while(treesizepred; /* add new node to the tree */ - GetArc(from,to,&arcrow,&arccol,&arcdir,nrow,ncol,nodesupp); + GetArc(from,to,&arcrow,&arccol,&arcdir,nrow,ncol,nodes,nodesupp); to->group=1; to->level=from->level+1; to->incost=from->incost+GetCost(incrcosts,arcrow,arccol,-arcdir); @@ -104,38 +298,32 @@ long TreeSolve(nodeT **nodes, nodesuppT **nodesupp, nodeT *ground, /* scan new node's neighbors */ from=to; - if(from->row!=GROUNDROW){ - arcnum=-5; - upperarcnum=-1; - }else{ - arcnum=-1; - upperarcnum=ngroundarcs-1; - } + arcnum=GetArcNumLims(from->row,&upperarcnum,ngroundarcs,boundary); while(arcnumgroup>0){ - if(to!=from->pred){ - cycleapex=FindApex(from,to); - apexes[arcrow][arccol]=cycleapex; - CheckArcReducedCost(from,to,cycleapex,arcrow,arccol,arcdir,nflow, - nodes,ground,&candidatebag,&candidatebagnext, - &candidatebagsize,incrcosts,iscandidate, - params); - }else{ - apexes[arcrow][arccol]=NULL; - } - - }else{ - - /* if to is not on tree, update outcost and add to bucket */ - AddNewNode(from,to,arcdir,bkts,nflow,incrcosts,arcrow,arccol,params); - - } + + /* get row, col indices and distance of next node */ + to=NeighborNode(from,++arcnum,&upperarcnum,nodes,ground, + &arcrow,&arccol,&arcdir,nrow,ncol,boundary,nodesupp); + + /* if to node is on tree */ + if(to->group>0){ + if(to!=from->pred){ + cycleapex=FindApex(from,to); + apexes[arcrow][arccol]=cycleapex; + CheckArcReducedCost(from,to,cycleapex,arcrow,arccol,arcdir, + &candidatebag,&candidatebagnext, + &candidatebagsize,incrcosts,iscandidate, + params); + }else{ + apexes[arcrow][arccol]=NULL; + } + + }else if(to->group!=PRUNED && to->group!=MASKED){ + + /* if to is not on tree, update outcost and add to bucket */ + AddNewNode(from,to,arcdir,bkts,nflow,incrcosts,arcrow,arccol,params); + + } } nnewnodes++; treesize++; @@ -149,24 +337,27 @@ long TreeSolve(nodeT **nodes, nodesuppT **nodesupp, nodeT *ground, /* writing a non-feasible solution (ie, if signal during augment) */ /* signal handler disabled for all but primary (grid) networks */ if(dumpresults_global){ - fprintf(sp0,"\n\nDumping current solution to file %s\n", - outfile); - if(requestedstop_global){ - Free2DArray((void **)costs,2*nrow-1); - } - unwrappedphase=(float **)Get2DMem(nrow,ncol,sizeof(float *), - sizeof(float)); - IntegratePhase(wrappedphase,unwrappedphase,flows,nrow,ncol); - FlipPhaseArraySign(unwrappedphase,params,nrow,ncol); - WriteOutputFile(mag,unwrappedphase,outfiles->outfile,outfiles, - nrow,ncol); - if(requestedstop_global){ - fprintf(sp0,"Program exiting\n"); - exit(ABNORMAL_EXIT); - } - Free2DArray((void **)unwrappedphase,nrow); - dumpresults_global=FALSE; - fprintf(sp0,"\n\nProgram continuing\n"); + fflush(NULL); + fprintf(sp0,"\n\nDumping current solution to file %s\n", + outfile); + if(requestedstop_global){ + Free2DArray((void **)costs,2*nrow-1); + } + unwrappedphase=(float **)Get2DMem(nrow,ncol,sizeof(float *), + sizeof(float)); + IntegratePhase(wrappedphase,unwrappedphase,flows,nrow,ncol); + FlipPhaseArraySign(unwrappedphase,params,nrow,ncol); + WriteOutputFile(mag,unwrappedphase,outfiles->outfile,outfiles, + nrow,ncol); + if(requestedstop_global){ + fflush(NULL); + fprintf(sp0,"Program exiting\n"); + exit(ABNORMAL_EXIT); + } + Free2DArray((void **)unwrappedphase,nrow); + dumpresults_global=FALSE; + fflush(NULL); + fprintf(sp0,"\n\nProgram continuing\n"); } /* swap candidate bag and candidate list pointers and sizes */ @@ -181,15 +372,15 @@ long TreeSolve(nodeT **nodes, nodesuppT **nodesupp, nodeT *ground, /* sort candidate list by violation, with augmenting arcs always first */ qsort((void *)candidatelist,candidatelistlen,sizeof(candidateT), - CandidateCompare); + CandidateCompare); /* set all arc directions to be plus/minus 1 */ for(i=0;i1){ - candidatelist[i].arcdir=1; - }else if(candidatelist[i].arcdir<-1){ - candidatelist[i].arcdir=-1; - } + if(candidatelist[i].arcdir>1){ + candidatelist[i].arcdir=1; + }else if(candidatelist[i].arcdir<-1){ + candidatelist[i].arcdir=-1; + } } /* this doesn't seem to make it any faster, so just do all of them */ @@ -198,546 +389,588 @@ long TreeSolve(nodeT **nodes, nodesuppT **nodesupp, nodeT *ground, /* maxcandidates=MAXCANDIDATES; if(maxcandidates>candidatelistlen){ - ncandidates=candidatelistlen; + ncandidates=candidatelistlen; }else{ - ncandidates=maxcandidates; + ncandidates=maxcandidates; } */ /* now pivot for each arc in the candidate list */ for(i=0;ioutcost+ - GetCost(incrcosts,arcrow,arccol,arcdir); - cyclecost=outcostto + to->incost - -apexes[arcrow][arccol]->outcost - -apexes[arcrow][arccol]->incost; - - /* if violation no longer negative, check reverse arc */ - if(!((outcostto < to->outcost) || (cyclecost < 0))){ - from=to; - to=candidatelist[i].from; - arcdir=-arcdir; - outcostto=from->outcost+ - GetCost(incrcosts,arcrow,arccol,arcdir); - cyclecost=outcostto + to->incost - -apexes[arcrow][arccol]->outcost - -apexes[arcrow][arccol]->incost; - } - - /* see if the cycle is negative (see if there is a violation) */ - if((outcostto < to->outcost) || (cyclecost < 0)){ - - /* make sure the group counter hasn't gotten too big */ - if(++groupcounter>MAXGROUPBASE){ - for(row=0;row0){ - nodes[row][col].group=1; - } - } - } - if(ground!=NULL && ground->group>0){ - ground->group=1; - } - groupcounter=2; - } - - /* if augmenting cycle (nondegenerate pivot) */ - if(cyclecost<0){ - - /* augment flow along cycle and select leaving arc */ - /* if we are augmenting non-zero flow, any arc with zero flow */ - /* after the augmentation is a blocking arc */ - while(TRUE){ - fromside=TRUE; - node1=from; - node2=to; - leavingchild=NULL; - flows[arcrow][arccol]+=arcdir*nflow; - ReCalcCost(costs,incrcosts,flows[arcrow][arccol],arcrow,arccol, - nflow,nrow,params); - violation=GetCost(incrcosts,arcrow,arccol,arcdir); - if(node1->level > node2->level){ - while(node1->level != node2->level){ - GetArc(node1->pred,node1,&arcrow1,&arccol1,&arcdir1, - nrow,ncol,nodesupp); - flows[arcrow1][arccol1]+=(arcdir1*nflow); - ReCalcCost(costs,incrcosts,flows[arcrow1][arccol1], - arcrow1,arccol1,nflow,nrow,params); - if(leavingchild==NULL - && !flows[arcrow1][arccol1]){ - leavingchild=node1; - } - violation+=GetCost(incrcosts,arcrow1,arccol1,arcdir1); - node1->group=groupcounter+1; - node1=node1->pred; - } - }else{ - while(node1->level != node2->level){ - GetArc(node2->pred,node2,&arcrow2,&arccol2,&arcdir2, - nrow,ncol,nodesupp); - flows[arcrow2][arccol2]-=(arcdir2*nflow); - ReCalcCost(costs,incrcosts,flows[arcrow2][arccol2], - arcrow2,arccol2,nflow,nrow,params); - if(!flows[arcrow2][arccol2]){ - leavingchild=node2; - fromside=FALSE; - } - violation+=GetCost(incrcosts,arcrow2,arccol2,-arcdir2); - node2->group=groupcounter; - node2=node2->pred; - } - } - while(node1!=node2){ - GetArc(node1->pred,node1,&arcrow1,&arccol1,&arcdir1,nrow,ncol, - nodesupp); - GetArc(node2->pred,node2,&arcrow2,&arccol2,&arcdir2,nrow,ncol, - nodesupp); - flows[arcrow1][arccol1]+=(arcdir1*nflow); - flows[arcrow2][arccol2]-=(arcdir2*nflow); - ReCalcCost(costs,incrcosts,flows[arcrow1][arccol1], - arcrow1,arccol1,nflow,nrow,params); - ReCalcCost(costs,incrcosts,flows[arcrow2][arccol2], - arcrow2,arccol2,nflow,nrow,params); - violation+=(GetCost(incrcosts,arcrow1,arccol1,arcdir1) - +GetCost(incrcosts,arcrow2,arccol2,-arcdir2)); - if(!flows[arcrow2][arccol2]){ - leavingchild=node2; - fromside=FALSE; - }else if(leavingchild==NULL - && !flows[arcrow1][arccol1]){ - leavingchild=node1; - } - node1->group=groupcounter+1; - node2->group=groupcounter; - node1=node1->pred; - node2=node2->pred; - } - if(violation>=0){ - break; - } - } - inondegen++; - - }else{ - - /* We are not augmenting flow, but just updating potentials. */ - /* Arcs with zero flow are implicitly directed upwards to */ - /* maintain a strongly feasible spanning tree, so arcs with zero */ - /* flow on the path between to node and apex are blocking arcs. */ - /* Leaving arc is last one whose child's new outcost is less */ - /* than its old outcost. Such an arc must exist, or else */ - /* we'd be augmenting flow on a negative cycle. */ - - /* trace the cycle and select leaving arc */ - fromside=FALSE; - node1=from; - node2=to; - leavingchild=NULL; - if(node1->level > node2->level){ - while(node1->level != node2->level){ - node1->group=groupcounter+1; - node1=node1->pred; - } - }else{ - while(node1->level != node2->level){ - if(outcostto < node2->outcost){ - leavingchild=node2; - GetArc(node2->pred,node2,&arcrow2,&arccol2,&arcdir2, - nrow,ncol,nodesupp); - outcostto+=GetCost(incrcosts,arcrow2,arccol2,-arcdir2); - }else{ - outcostto=VERYFAR; - } - node2->group=groupcounter; - node2=node2->pred; - } - } - while(node1!=node2){ - if(outcostto < node2->outcost){ - leavingchild=node2; - GetArc(node2->pred,node2,&arcrow2,&arccol2,&arcdir2,nrow,ncol, - nodesupp); - outcostto+=GetCost(incrcosts,arcrow2,arccol2,-arcdir2); - }else{ - outcostto=VERYFAR; - } - node1->group=groupcounter+1; - node2->group=groupcounter; - node1=node1->pred; - node2=node2->pred; - } - } - cycleapex=node1; + /* get arc info */ + from=candidatelist[i].from; + to=candidatelist[i].to; + arcdir=candidatelist[i].arcdir; + arcrow=candidatelist[i].arcrow; + arccol=candidatelist[i].arccol; + + /* unset iscandidate */ + iscandidate[arcrow][arccol]=FALSE; + + /* make sure the next arc still has a negative violation */ + outcostto=from->outcost+ + GetCost(incrcosts,arcrow,arccol,arcdir); + cyclecost=outcostto + to->incost + -apexes[arcrow][arccol]->outcost + -apexes[arcrow][arccol]->incost; + + /* if violation no longer negative, check reverse arc */ + if(!((outcostto < to->outcost) || (cyclecost < 0))){ + from=to; + to=candidatelist[i].from; + arcdir=-arcdir; + outcostto=from->outcost+ + GetCost(incrcosts,arcrow,arccol,arcdir); + cyclecost=outcostto + to->incost + -apexes[arcrow][arccol]->outcost + -apexes[arcrow][arccol]->incost; + } + + /* see if the cycle is negative (see if there is a violation) */ + if((outcostto < to->outcost) || (cyclecost < 0)){ + + /* make sure the group counter hasn't gotten too big */ + if(++groupcounter>MAXGROUPBASE){ + for(row=0;row0){ + nodes[row][col].group=1; + } + } + } + if(ground!=NULL && ground->group>0){ + ground->group=1; + } + if(boundary->node->group>0){ + boundary->node->group=1; + } + groupcounter=2; + } + + /* if augmenting cycle (nondegenerate pivot) */ + if(cyclecost<0){ + + /* augment flow along cycle and select leaving arc */ + /* if we are augmenting non-zero flow, any arc with zero flow */ + /* after the augmentation is a blocking arc */ + while(TRUE){ + fromside=TRUE; + node1=from; + node2=to; + leavingchild=NULL; + flows[arcrow][arccol]+=arcdir*nflow; + ReCalcCost(costs,incrcosts,flows[arcrow][arccol],arcrow,arccol, + nflow,nrow,params); + violation=GetCost(incrcosts,arcrow,arccol,arcdir); + if(node1->level > node2->level){ + while(node1->level != node2->level){ + GetArc(node1->pred,node1,&arcrow1,&arccol1,&arcdir1, + nrow,ncol,nodes,nodesupp); + flows[arcrow1][arccol1]+=(arcdir1*nflow); + ReCalcCost(costs,incrcosts,flows[arcrow1][arccol1], + arcrow1,arccol1,nflow,nrow,params); + if(leavingchild==NULL + && !flows[arcrow1][arccol1]){ + leavingchild=node1; + } + violation+=GetCost(incrcosts,arcrow1,arccol1,arcdir1); + node1->group=groupcounter+1; + node1=node1->pred; + } + }else{ + while(node1->level != node2->level){ + GetArc(node2->pred,node2,&arcrow2,&arccol2,&arcdir2, + nrow,ncol,nodes,nodesupp); + flows[arcrow2][arccol2]-=(arcdir2*nflow); + ReCalcCost(costs,incrcosts,flows[arcrow2][arccol2], + arcrow2,arccol2,nflow,nrow,params); + if(!flows[arcrow2][arccol2]){ + leavingchild=node2; + fromside=FALSE; + } + violation+=GetCost(incrcosts,arcrow2,arccol2,-arcdir2); + node2->group=groupcounter; + node2=node2->pred; + } + } + while(node1!=node2){ + GetArc(node1->pred,node1,&arcrow1,&arccol1,&arcdir1,nrow,ncol, + nodes,nodesupp); + GetArc(node2->pred,node2,&arcrow2,&arccol2,&arcdir2,nrow,ncol, + nodes,nodesupp); + flows[arcrow1][arccol1]+=(arcdir1*nflow); + flows[arcrow2][arccol2]-=(arcdir2*nflow); + ReCalcCost(costs,incrcosts,flows[arcrow1][arccol1], + arcrow1,arccol1,nflow,nrow,params); + ReCalcCost(costs,incrcosts,flows[arcrow2][arccol2], + arcrow2,arccol2,nflow,nrow,params); + violation+=(GetCost(incrcosts,arcrow1,arccol1,arcdir1) + +GetCost(incrcosts,arcrow2,arccol2,-arcdir2)); + if(!flows[arcrow2][arccol2]){ + leavingchild=node2; + fromside=FALSE; + }else if(leavingchild==NULL + && !flows[arcrow1][arccol1]){ + leavingchild=node1; + } + node1->group=groupcounter+1; + node2->group=groupcounter; + node1=node1->pred; + node2=node2->pred; + } + if(violation>=0){ + break; + } + } + inondegen++; + + }else{ + + /* We are not augmenting flow, but just updating potentials. */ + /* Arcs with zero flow are implicitly directed upwards to */ + /* maintain a strongly feasible spanning tree, so arcs with zero */ + /* flow on the path between to node and apex are blocking arcs. */ + /* Leaving arc is last one whose child's new outcost is less */ + /* than its old outcost. Such an arc must exist, or else */ + /* we'd be augmenting flow on a negative cycle. */ + + /* trace the cycle and select leaving arc */ + fromside=FALSE; + node1=from; + node2=to; + leavingchild=NULL; + if(node1->level > node2->level){ + while(node1->level != node2->level){ + node1->group=groupcounter+1; + node1=node1->pred; + } + }else{ + while(node1->level != node2->level){ + if(outcostto < node2->outcost){ + leavingchild=node2; + GetArc(node2->pred,node2,&arcrow2,&arccol2,&arcdir2, + nrow,ncol,nodes,nodesupp); + outcostto+=GetCost(incrcosts,arcrow2,arccol2,-arcdir2); + }else{ + outcostto=VERYFAR; + } + node2->group=groupcounter; + node2=node2->pred; + } + } + while(node1!=node2){ + if(outcostto < node2->outcost){ + leavingchild=node2; + GetArc(node2->pred,node2,&arcrow2,&arccol2,&arcdir2,nrow,ncol, + nodes,nodesupp); + outcostto+=GetCost(incrcosts,arcrow2,arccol2,-arcdir2); + }else{ + outcostto=VERYFAR; + } + node1->group=groupcounter+1; + node2->group=groupcounter; + node1=node1->pred; + node2=node2->pred; + } + } + cycleapex=node1; /* set leaving parent */ if(leavingchild==NULL){ - fromside=TRUE; - leavingparent=from; - }else{ - leavingparent=leavingchild->pred; - } + fromside=TRUE; + leavingparent=from; + }else{ + leavingparent=leavingchild->pred; + } /* swap from and to if leaving arc is on the from side */ - if(fromside){ - groupcounter++; - fromgroup=groupcounter-1; - tempnode1=from; - from=to; - to=tempnode1; - }else{ - fromgroup=groupcounter+1; - } - - /* if augmenting pivot */ - if(cyclecost<0){ - - /* find first child of apex on either cycle path */ - firstfromnode=NULL; - firsttonode=NULL; - if(cycleapex->row!=GROUNDROW){ - arcnum=-5; - upperarcnum=-1; - }else{ - arcnum=-1; - upperarcnum=ngroundarcs-1; - } - while(arcnumgroup==groupcounter - && apexes[arcrow][arccol]==NULL){ - firsttonode=tempnode1; - if(firstfromnode!=NULL){ - break; - } - }else if(tempnode1->group==fromgroup - && apexes[arcrow][arccol]==NULL){ - firstfromnode=tempnode1; - if(firsttonode!=NULL){ - break; - } - } - } - - /* update potentials, mark stationary parts of tree */ - cycleapex->group=groupcounter+2; - if(firsttonode!=NULL){ - NonDegenUpdateChildren(cycleapex,leavingparent,firsttonode,0, - ngroundarcs,nflow,nodes,nodesupp,ground, - apexes,incrcosts,nrow,ncol,params); - } - if(firstfromnode!=NULL){ - NonDegenUpdateChildren(cycleapex,from,firstfromnode,1, - ngroundarcs,nflow,nodes,nodesupp,ground, - apexes,incrcosts,nrow,ncol,params); - } - groupcounter=from->group; - apexlistbase=cycleapex->group; - - /* children of cycleapex are not marked, so we set fromgroup */ - /* equal to cycleapex group for use with apex updates below */ - /* all other children of cycle will be in apexlist if we had an */ - /* augmenting pivot, so fromgroup only important for cycleapex */ - fromgroup=cycleapex->group; - - }else{ - - /* set this stuff for use with apex updates below */ - cycleapex->group=fromgroup; - groupcounter+=2; - apexlistbase=groupcounter+1; - } - - /* remount subtree at new mount point */ - if(leavingchild==NULL){ - - skipthread=to; - - }else{ - - root=from; - oldmntpt=to; - - /* for each node on the path from to node to leaving child */ - while(oldmntpt!=leavingparent){ - - /* remount the subtree at the new mount point */ - mntpt=root; - root=oldmntpt; - oldmntpt=root->pred; - root->pred=mntpt; - GetArc(mntpt,root,&arcrow,&arccol,&arcdir,nrow,ncol,nodesupp); - - /* calculate differences for updating potentials and levels */ - dlevel=mntpt->level-root->level+1; - doutcost=mntpt->outcost - root->outcost - + GetCost(incrcosts,arcrow,arccol,arcdir); - dincost=mntpt->incost - root->incost - + GetCost(incrcosts,arcrow,arccol,-arcdir); - - /* update all children */ - /* group of each remounted tree used to reset apexes below */ - node1=root; - startlevel=root->level; - groupcounter++; - while(TRUE){ - - /* update the level, potentials, and group of the node */ - node1->level+=dlevel; - node1->outcost+=doutcost; - node1->incost+=dincost; - node1->group=groupcounter; - - /* break when node1 is no longer descendent of the root */ - if(node1->next->level <= startlevel){ - break; - } - node1=node1->next; - } - - /* update threads */ - root->prev->next=node1->next; - node1->next->prev=root->prev; - node1->next=mntpt->next; - mntpt->next->prev=node1; - mntpt->next=root; - root->prev=mntpt; - - } - skipthread=node1->next; - - /* reset apex pointers for entering and leaving arcs */ - GetArc(from,to,&arcrow,&arccol,&arcdir,nrow,ncol,nodesupp); - apexes[arcrow][arccol]=NULL; - GetArc(leavingparent,leavingchild,&arcrow,&arccol, - &arcdir,nrow,ncol,nodesupp); - apexes[arcrow][arccol]=cycleapex; - - /* make sure we have enough memory for the apex list */ - if(groupcounter-apexlistbase+1>apexlistlen){ - apexlistlen=1.5*(groupcounter-apexlistbase+1); - apexlist=ReAlloc(apexlist,apexlistlen*sizeof(nodeT *)); - } + if(fromside){ + groupcounter++; + fromgroup=groupcounter-1; + tempnode1=from; + from=to; + to=tempnode1; + }else{ + fromgroup=groupcounter+1; + } + + /* if augmenting pivot */ + if(cyclecost<0){ + + /* find first child of apex on either cycle path */ + firstfromnode=NULL; + firsttonode=NULL; + arcnum=GetArcNumLims(cycleapex->row,&upperarcnum, + ngroundarcs,boundary); + while(arcnumgroup==groupcounter + && apexes[arcrow][arccol]==NULL){ + firsttonode=tempnode1; + if(firstfromnode!=NULL){ + break; + } + }else if(tempnode1->group==fromgroup + && apexes[arcrow][arccol]==NULL){ + firstfromnode=tempnode1; + if(firsttonode!=NULL){ + break; + } + } + } + + /* update potentials, mark stationary parts of tree */ + cycleapex->group=groupcounter+2; + if(firsttonode!=NULL){ + NonDegenUpdateChildren(cycleapex,leavingparent,firsttonode,0, + ngroundarcs,nflow,nodes,nodesupp,ground, + boundary,apexes,incrcosts,nrow,ncol, + params); + } + if(firstfromnode!=NULL){ + NonDegenUpdateChildren(cycleapex,from,firstfromnode,1, + ngroundarcs,nflow,nodes,nodesupp,ground, + boundary,apexes,incrcosts,nrow,ncol, + params); + } + groupcounter=from->group; + apexlistbase=cycleapex->group; + + /* children of cycleapex are not marked, so we set fromgroup */ + /* equal to cycleapex group for use with apex updates below */ + /* all other children of cycle will be in apexlist if we had an */ + /* augmenting pivot, so fromgroup only important for cycleapex */ + fromgroup=cycleapex->group; + + }else{ + + /* set this stuff for use with apex updates below */ + cycleapex->group=fromgroup; + groupcounter+=2; + apexlistbase=groupcounter+1; + } + + /* remount subtree at new mount point */ + if(leavingchild==NULL){ + + skipthread=to; + + }else{ + + root=from; + oldmntpt=to; + + /* for each node on the path from to node to leaving child */ + while(oldmntpt!=leavingparent){ + + /* remount the subtree at the new mount point */ + mntpt=root; + root=oldmntpt; + oldmntpt=root->pred; + root->pred=mntpt; + GetArc(mntpt,root,&arcrow,&arccol,&arcdir,nrow,ncol, + nodes,nodesupp); + + /* calculate differences for updating potentials and levels */ + dlevel=mntpt->level-root->level+1; + doutcost=mntpt->outcost - root->outcost + + GetCost(incrcosts,arcrow,arccol,arcdir); + dincost=mntpt->incost - root->incost + + GetCost(incrcosts,arcrow,arccol,-arcdir); + + /* update all children */ + /* group of each remounted tree used to reset apexes below */ + node1=root; + startlevel=root->level; + groupcounter++; + while(TRUE){ + + /* update the level, potentials, and group of the node */ + node1->level+=dlevel; + node1->outcost+=doutcost; + node1->incost+=dincost; + node1->group=groupcounter; + + /* break when node1 is no longer descendent of the root */ + if(node1->next->level <= startlevel){ + break; + } + node1=node1->next; + } + + /* update threads */ + root->prev->next=node1->next; + node1->next->prev=root->prev; + node1->next=mntpt->next; + mntpt->next->prev=node1; + mntpt->next=root; + root->prev=mntpt; + + } + skipthread=node1->next; + + /* reset apex pointers for entering and leaving arcs */ + GetArc(from,to,&arcrow,&arccol,&arcdir,nrow,ncol,nodes,nodesupp); + apexes[arcrow][arccol]=NULL; + GetArc(leavingparent,leavingchild,&arcrow,&arccol, + &arcdir,nrow,ncol,nodes,nodesupp); + apexes[arcrow][arccol]=cycleapex; + + /* make sure we have enough memory for the apex list */ + if(groupcounter-apexlistbase+1>apexlistlen){ + apexlistlen=1.5*(groupcounter-apexlistbase+1); + apexlist=ReAlloc(apexlist,apexlistlen*sizeof(nodeT *)); + } - /* set the apex list */ - node2=leavingchild; - for(group1=groupcounter;group1>=apexlistbase;group1--){ - apexlist[group1-apexlistbase]=node2; - node2=node2->pred; - } + /* set the apex list */ + /* the apex list is a look up table of apex node pointers indexed */ + /* by the group number relative to a base group value */ + node2=leavingchild; + for(group1=groupcounter;group1>=apexlistbase;group1--){ + apexlist[group1-apexlistbase]=node2; + node2=node2->pred; + } - /* reset apex pointers on remounted tree */ - /* only nodes which are in different groups need new apexes */ - node1=to; - startlevel=to->level; - while(TRUE){ - - /* loop over outgoing arcs */ - if(node1->row!=GROUNDROW){ - arcnum=-5; - upperarcnum=-1; - }else{ - arcnum=-1; - upperarcnum=ngroundarcs-1; - } - while(arcnumgroup>0){ - - - /* if node2 is either not part of remounted tree or */ - /* it is higher on remounted tree than node1, */ - /* and arc isn't already on tree */ - if(node2->group < node1->group - && apexes[arcrow][arccol]!=NULL){ - - /* if new apex in apexlist */ - /* node2 on remounted tree, if nonaugmenting pivot */ - if(node2->group >= apexlistbase){ - - apexes[arcrow][arccol]=apexlist[node2->group - -apexlistbase]; - - }else{ - - /* if old apex below level of cycleapex, */ - /* node2 is on "to" node's side of tree */ - /* implicitly, if old apex above cycleapex, */ - /* we do nothing since apex won't change */ - if(apexes[arcrow][arccol]->level > cycleapex->level){ - - /* since new apex not in apexlist (tested above), */ - /* node2 above leaving arc so new apex is cycleapex */ - apexes[arcrow][arccol]=cycleapex; - - }else{ - - /* node2 not on "to" side of tree */ - /* if old apex is cycleapex, node2 is on "from" side */ - if(apexes[arcrow][arccol]==cycleapex){ - - /* new apex will be on cycle, so trace node2->pred */ - /* until we hit a node with group==fromgroup */ - tempnode2=node2; - while(tempnode2->group != fromgroup){ - tempnode2=tempnode2->pred; - } + /* reset apex pointers on remounted tree */ + /* only nodes which are in different groups need new apexes */ + node1=to; + startlevel=to->level; + while(TRUE){ + + /* loop over outgoing arcs */ + arcnum=GetArcNumLims(node1->row,&upperarcnum, + ngroundarcs,boundary); + while(arcnumgroup>0){ + + + /* if node2 is either not part of remounted tree or */ + /* it is higher on remounted tree than node1, */ + /* and arc isn't already on tree */ + if(node2->group < node1->group + && apexes[arcrow][arccol]!=NULL){ + + /* if new apex in apexlist */ + /* node2 on remounted tree, if nonaugmenting pivot */ + if(node2->group >= apexlistbase){ + + apexes[arcrow][arccol]=apexlist[node2->group + -apexlistbase]; + + }else{ + + /* if old apex below level of cycleapex, */ + /* node2 is on "to" node's side of tree */ + /* implicitly, if old apex above cycleapex, */ + /* we do nothing since apex won't change */ + if(apexes[arcrow][arccol]->level > cycleapex->level){ + + /* since new apex not in apexlist (tested above), */ + /* node2 above leaving arc so new apex is cycleapex */ + apexes[arcrow][arccol]=cycleapex; + + }else{ + + /* node2 not on "to" side of tree */ + /* if old apex is cycleapex, node2 is on "from" side */ + if(apexes[arcrow][arccol]==cycleapex){ + + /* new apex will be on cycle, so trace node2->pred */ + /* until we hit a node with group==fromgroup */ + tempnode2=node2; + while(tempnode2->group != fromgroup){ + tempnode2=tempnode2->pred; + } apexes[arcrow][arccol]=tempnode2; - } - } - } + } + } + } - /* check outgoing arcs for negative reduced costs */ + /* check outgoing arcs for negative reduced costs */ CheckArcReducedCost(node1,node2,apexes[arcrow][arccol], - arcrow,arccol,arcdir,nflow,nodes, - ground,&candidatebag, - &candidatebagnext,&candidatebagsize, - incrcosts,iscandidate,params); - - } /* end if node2 below node1 and arc not on tree */ - - }else{ - - /* node2 is not on tree, so put it in correct bucket */ - AddNewNode(node1,node2,arcdir,bkts,nflow,incrcosts, - arcrow,arccol,params); - - } /* end if node2 on tree */ - } /* end loop over node1 outgoing arcs */ - - - /* move to next node in thread, break if we left the subtree */ - node1=node1->next; - if(node1->level <= startlevel){ - break; - } - } - } /* end if leavingchild!=NULL */ - - /* if we had an augmenting cycle */ - /* we need to check outarcs from descendents of any cycle node */ - /* (except apex, since apex potentials don't change) */ - if(cyclecost<0){ - - /* check descendents of cycle children of apex */ - while(TRUE){ - - /* firstfromnode, firsttonode may have changed */ - if(firstfromnode!=NULL && firstfromnode->pred==cycleapex){ - node1=firstfromnode; - firstfromnode=NULL; - }else if(firsttonode!=NULL && firsttonode->pred==cycleapex){ - node1=firsttonode; - firsttonode=NULL; - }else{ - break; - } - startlevel=node1->level; - - /* loop over all descendents */ - while(TRUE){ - - /* loop over outgoing arcs */ - if(node1->row!=GROUNDROW){ - arcnum=-5; - upperarcnum=-1; - }else{ - arcnum=-1; - upperarcnum=ngroundarcs-1; - } - while(arcnumgroup>0){ - if(apexes[arcrow][arccol]!=NULL - && (node2->group!=node1->group - || node1->group==apexlistbase)){ - CheckArcReducedCost(node1,node2,apexes[arcrow][arccol], - arcrow,arccol,arcdir,nflow,nodes, - ground,&candidatebag, - &candidatebagnext,&candidatebagsize, - incrcosts,iscandidate,params); - } - }else{ - AddNewNode(node1,node2,arcdir,bkts,nflow,incrcosts, - arcrow,arccol,params); - } - } - - /* move to next node in thread, break if left the subtree */ - /* but skip the remounted tree, since we checked it above */ - node1=node1->next; - if(node1==to){ - node1=skipthread; - } - if(node1->level <= startlevel){ - break; - } - } - } - } - ipivots++; - } /* end if cyclecost<0 || outcosttooutcost */ + arcrow,arccol,arcdir,&candidatebag, + &candidatebagnext,&candidatebagsize, + incrcosts,iscandidate,params); + + } /* end if node2 below node1 and arc not on tree */ + + }else if(node2->group!=PRUNED && node2->group!=MASKED){ + + /* node2 is not on tree, so put it in correct bucket */ + AddNewNode(node1,node2,arcdir,bkts,nflow,incrcosts, + arcrow,arccol,params); + + } /* end if node2 on tree */ + } /* end loop over node1 outgoing arcs */ + + + /* move to next node in thread, break if we left the subtree */ + node1=node1->next; + if(node1->level <= startlevel){ + break; + } + } + } /* end if leavingchild!=NULL */ + + /* if we had an augmenting cycle */ + /* we need to check outarcs from descendents of any cycle node */ + /* (except apex, since apex potentials don't change) */ + if(cyclecost<0){ + + /* check descendents of cycle children of apex */ + while(TRUE){ + + /* firstfromnode, firsttonode may have changed */ + if(firstfromnode!=NULL && firstfromnode->pred==cycleapex){ + node1=firstfromnode; + firstfromnode=NULL; + }else if(firsttonode!=NULL && firsttonode->pred==cycleapex){ + node1=firsttonode; + firsttonode=NULL; + }else{ + break; + } + startlevel=node1->level; + + /* loop over all descendents */ + while(TRUE){ + + /* loop over outgoing arcs */ + arcnum=GetArcNumLims(node1->row,&upperarcnum, + ngroundarcs,boundary); + while(arcnumgroup>0){ + if(apexes[arcrow][arccol]!=NULL + && (node2->group!=node1->group + || node1->group==apexlistbase)){ + CheckArcReducedCost(node1,node2,apexes[arcrow][arccol], + arcrow,arccol,arcdir,&candidatebag, + &candidatebagnext,&candidatebagsize, + incrcosts,iscandidate,params); + } + }else if(node2->group!=PRUNED && node2->group!=MASKED){ + AddNewNode(node1,node2,arcdir,bkts,nflow,incrcosts, + arcrow,arccol,params); + } + } + + /* move to next node in thread, break if left the subtree */ + /* but skip the remounted tree, since we checked it above */ + node1=node1->next; + if(node1==to){ + node1=skipthread; + } + if(node1->level <= startlevel){ + break; + } + } + } + } + ipivots++; + } /* end if cyclecost<0 || outcosttooutcost */ } /* end of for loop over candidates in list */ /* this is needed only if we don't process all candidates above */ /* copy remaining candidates into candidatebag */ /* while(candidatebagnext+(candidatelistlen-ncandidates)>candidatebagsize){ - candidatebagsize+=CANDIDATEBAGSTEP; - candidatebag=ReAlloc(candidatebag,candidatebagsize*sizeof(candidateT)); + candidatebagsize+=CANDIDATEBAGSTEP; + candidatebag=ReAlloc(candidatebag,candidatebagsize*sizeof(candidateT)); } for(i=ncandidates;inext; + while(node1!=source){ + if(node1->pred->level!=node1->level-1){ + printf("Error detected: row %d, col%d, level %d " + "has pred row %d, col%d, level %d\n", + node1->row,node1->col,node1->level,node1->pred->row,node1->pred->col, + node1->pred->level); + } + node1=node1->next; + } + + /* discharge boundary */ + /* flow to edge of region goes along normal grid arcs, but flow along edge */ + /* of region that should go along zero-cost arcs along edge is not */ + /* captured in solver code above since nodes of edge are collapsed into */ + /* single boundary node. This accumulates surplus/demand at edge nodes. */ + /* Here, find surplus/demand by balancing flow in/out of edge nodes and */ + /* discharge sending flow along zero-cost edge arcs */ + DischargeBoundary(nodes,ground,boundary,nodesupp,flows,iscandidate, + mag,wrappedphase,ngroundarcs,nrow,ncol); + + /* sanity check that buckets are actually all empty after optimizer is done */ + for(i=0;isize;i++){ + if(bkts->bucketbase[i]!=NULL){ + printf("ERROR: bucket %ld not empty after TreeSolve (row=%d, col=%d)\n", + i,bkts->bucketbase[i]->row,bkts->bucketbase[i]->col); + break; + } + } + + /* reset group numbers of nodes along boundary */ + /* nodes in neighboring regions may have been set to be MASKED in */ + /* in InitBoundary() to avoid reaching them across single line of */ + /* masked pixels, so return mask status of nodes along boundary to normal */ + CleanUpBoundaryNodes(source,boundary,mag,nodes,ground,nrow,ncol,ngroundarcs, + nodesupp); + if(boundary->neighborlist!=NULL){ + free(boundary->neighborlist); + } + if(boundary->boundarylist!=NULL){ + free(boundary->boundarylist); + } /* clean up: set pointers for outputs */ fprintf(sp3,"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" - "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" - "\b\b\b\b\b\b" - "Treesize: %-10ld Pivots: %-11ld Improvements: %-11ld\n", - treesize,ipivots,inondegen); + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" + "\b\b\b\b\b\b" + "Treesize: %-10ld Pivots: %-11ld Improvements: %-11ld\n", + treesize,ipivots,inondegen); fflush(sp3); *candidatelistptr=candidatelist; *candidatebagptr=candidatebag; *candidatelistsizeptr=candidatelistsize; *candidatebagsizeptr=candidatebagsize; free(apexlist); - + /* return the number of nondegenerate pivots (number of improvements) */ return(inondegen); @@ -750,43 +983,46 @@ long TreeSolve(nodeT **nodes, nodesuppT **nodesupp, nodeT *ground, * outcosts of to node if the new distance is less or if to's pred is * from (then we have to do the update). */ +static void AddNewNode(nodeT *from, nodeT *to, long arcdir, bucketT *bkts, - long nflow, incrcostT **incrcosts, long arcrow, long arccol, - paramT *params){ + long nflow, incrcostT **incrcosts, long arcrow, long arccol, + paramT *params){ long newoutcost; + newoutcost=from->outcost +GetCost(incrcosts,arcrow,arccol,arcdir); if(newoutcostoutcost || to->pred==from){ - if(to->group==-1){ /* if to is already in a bucket */ + if(to->group==INBUCKET){ /* if to is already in a bucket */ if(to->outcostmaxind){ - if(to->outcost>bkts->minind){ - BucketRemove(to,to->outcost,bkts); - }else{ - BucketRemove(to,bkts->minind,bkts); - } + if(to->outcost>bkts->minind){ + BucketRemove(to,to->outcost,bkts); + }else{ + BucketRemove(to,bkts->minind,bkts); + } }else{ - BucketRemove(to,bkts->maxind,bkts); + BucketRemove(to,bkts->maxind,bkts); } } to->outcost=newoutcost; to->pred=from; if(newoutcostmaxind){ if(newoutcost>bkts->minind){ - BucketInsert(to,newoutcost,bkts); - if(newoutcostcurr){ - bkts->curr=newoutcost; - } + BucketInsert(to,newoutcost,bkts); + if(newoutcostcurr){ + bkts->curr=newoutcost; + } }else{ - BucketInsert(to,bkts->minind,bkts); - bkts->curr=bkts->minind; + BucketInsert(to,bkts->minind,bkts); + bkts->curr=bkts->minind; } }else{ BucketInsert(to,bkts->maxind,bkts); } - to->group=-1; - } + to->group=INBUCKET; + } + return; } @@ -795,17 +1031,18 @@ void AddNewNode(nodeT *from, nodeT *to, long arcdir, bucketT *bkts, * Given a from and to node, checks for negative reduced cost, and adds * the arc to the entering arc candidate bag if one is found. */ +static void CheckArcReducedCost(nodeT *from, nodeT *to, nodeT *apex, - long arcrow, long arccol, long arcdir, - long nflow, nodeT **nodes, nodeT *ground, - candidateT **candidatebagptr, - long *candidatebagnextptr, - long *candidatebagsizeptr, incrcostT **incrcosts, - signed char **iscandidate, paramT *params){ + long arcrow, long arccol, long arcdir, + candidateT **candidatebagptr, + long *candidatebagnextptr, + long *candidatebagsizeptr, incrcostT **incrcosts, + signed char **iscandidate, paramT *params){ long apexcost, fwdarcdist, revarcdist, violation; nodeT *temp; - + + /* do nothing if already candidate */ /* illegal corner arcs have iscandidate=TRUE set ahead of time */ if(iscandidate[arcrow][arccol]){ @@ -831,13 +1068,13 @@ void CheckArcReducedCost(nodeT *from, nodeT *to, nodeT *apex, }else{ violation=fwdarcdist+from->outcost-to->outcost; if(violation>=0){ - violation=revarcdist+to->outcost-from->outcost; - if(violation<0){ - arcdir=-arcdir; - temp=from; - from=to; - to=temp; - } + violation=revarcdist+to->outcost-from->outcost; + if(violation<0){ + arcdir=-arcdir; + temp=from; + from=to; + to=temp; + } } } } @@ -847,7 +1084,7 @@ void CheckArcReducedCost(nodeT *from, nodeT *to, nodeT *apex, if((*candidatebagnextptr)>=(*candidatebagsizeptr)){ (*candidatebagsizeptr)+=CANDIDATEBAGSTEP; (*candidatebagptr)=ReAlloc(*candidatebagptr, - (*candidatebagsizeptr)*sizeof(candidateT)); + (*candidatebagsizeptr)*sizeof(candidateT)); } (*candidatebagptr)[*candidatebagnextptr].violation=violation; (*candidatebagptr)[*candidatebagnextptr].from=from; @@ -859,233 +1096,1101 @@ void CheckArcReducedCost(nodeT *from, nodeT *to, nodeT *apex, iscandidate[arcrow][arccol]=TRUE; } + /* done */ + return; } -/* function: InitTree() - * -------------------- +/* function: InitBoundary() + * ------------------------ + * Initialize boundary structure for region to be unwrapped assuming + * source is on boundary. + * + * This function makes several passes over the boundary nodes. The + * first pass finds nodes linked by zero-weight arcs that are candidates + * for being on the boundary. The second pass decides which of the + * candidate nodes should actually point to the boundary node while + * ensuring that no node has multiple valid arcs to the boundary node. + * The third pass builds the neighbor list given the boundary pointer + * nodes from the previous pass. The fourth pass sets the group + * members of boundary pointer nodes, which cannot be done earlier + * since it would mess up how NeighborNodeGrid() works. + * + * Return pointer to source since source may become pointer to boundary. */ -long InitTree(nodeT *source, nodeT **nodes, nodesuppT **nodesupp, - nodeT *ground, long ngroundarcs, bucketT *bkts, long nflow, - incrcostT **incrcosts, nodeT ***apexes, - signed char **iscandidate, long nnoderow, short *nnodesperrow, - long narcrow, short *narcsperrow, long nrow, long ncol, - paramT *params){ - - long row, col, arcnum, upperarcnum, arcrow, arccol, arcdir, nnodes; - nodeT *to; - +static +nodeT *InitBoundary(nodeT *source, nodeT **nodes, + boundaryT *boundary, nodesuppT **nodesupp, float **mag, + nodeT *ground, long ngroundarcs, long nrow, long ncol, + paramT *params, long *nconnectedptr){ + + int iseligible, isinteriornode; + long k, nlist, ninteriorneighbor; + long nlistmem, nboundarymem, nneighbormem; + long arcnum, upperarcnum; + long neighborarcnum, neighborupperarcnum; + long arcrow, arccol, arcdir; + long nconnected; + nodeT **nodelist, **boundarylist, *from, *to, *end; + neighborT *neighborlist; - /* loop over each node and initialize values */ - nnodes=0; - for(row=0;rownode->row=BOUNDARYROW; + boundary->node->col=BOUNDARYCOL; + boundary->node->next=NULL; + boundary->node->prev=NULL; + boundary->node->pred=NULL; + boundary->node->level=0; + boundary->node->group=0; + boundary->node->incost=VERYFAR; + boundary->node->outcost=VERYFAR; + boundary->neighborlist=NULL; + boundary->boundarylist=NULL; + boundary->nneighbor=0; + boundary->nboundary=0; + + /* if this is non-grid network, do nothing */ + if(nodesupp!=NULL){ + return(source); } - - /* initialize the ground node */ - if(ground!=NULL){ - ground->group=0; - ground->outcost=VERYFAR; - ground->pred=NULL; - nnodes++; + + /* make sure magnitude exists */ + if(mag==NULL){ + return(source); + } + + /* scan region and mask any nodes that are not already masked but are not */ + /* reachable through non-region arcs */ + /* such nodes can exist if there is single line of masked pixels separating */ + /* regions */ + /* boundary is not yet set up, so scanning will search node neighbors as */ + /* normal grid neighbors */ + nconnected=ScanRegion(source,nodes,mag,ground,ngroundarcs,nrow,ncol,MASKED); + + /* if source is ground, do nothing, since do not want boundary with ground */ + if(source==ground){ + return(source); } - /* initialize arcs */ - for(row=0;rowrow,source->col,nrow,ncol)){ + fprintf(sp0,"WARNING: Non edge node as source in InitBoundary()\n"); } + + /* get memory for node list */ + nlistmem=NLISTMEMINCR; + nodelist=(nodeT **)MAlloc(nlistmem*sizeof(nodeT *)); + nodelist[0]=source; + nlist=1; + + /* first pass: build list of nodes on boundary */ + /* this should handle double-corner cases where all four arcs out of grid */ + /* node will be region edge arcs (eg, mag[i][j] and mag[i+1][j+1] are */ + /* both zero and mag[i+1][j] and mag[i][j+1] are both nonzero */ + source->next=NULL; + source->group=BOUNDARYCANDIDATE; + from=source; + end=source; + while(TRUE){ - /* if in grid mode, ground will exist */ - if(ground!=NULL){ - - /* set iscandidate=TRUE for illegal corner arcs so they're never used */ - iscandidate[nrow-1][0]=TRUE; - iscandidate[2*nrow-2][0]=TRUE; - iscandidate[nrow-1][ncol-2]=TRUE; - iscandidate[2*nrow-2][ncol-2]=TRUE; + /* see if neighbors can be reached through region-edge arcs */ + arcnum=GetArcNumLims(from->row,&upperarcnum,ngroundarcs,NULL); + while(arcnumgroup=1; - source->outcost=0; - source->incost=0; - source->pred=NULL; - source->prev=source; - source->next=source; - source->level=0; + /* see if node is reached through edge arc and node is not yet in list */ + if(IsRegionEdgeArc(mag,arcrow,arccol,nrow,ncol) + && to->group!=BOUNDARYCANDIDATE){ - /* loop over outgoing arcs and add to buckets */ - if(source->row!=GROUNDROW){ - arcnum=-5; - upperarcnum=-1; - }else{ - arcnum=-1; - upperarcnum=ngroundarcs-1; - } - while(arcnumgroup=BOUNDARYCANDIDATE; - /* add to node to bucket */ - AddNewNode(source,to,arcdir,bkts,nflow,incrcosts,arcrow,arccol,params); + /* add node to list of nodes to be searched */ + end->next=to; + to->next=NULL; + end=to; + + } + } + + /* move to next node to search */ + if(from->next==NULL){ + break; + } + from=from->next; } - /* return the number of nodes in the network */ - return(nnodes); - -} + /* get memory for boundary list */ + nboundarymem=NLISTMEMINCR; + boundarylist=(nodeT **)MAlloc(nboundarymem*sizeof(nodeT *)); + /* second pass to avoid multiple arcs to same node */ + /* go through nodes in list and check criteria for including on boundary */ + for(k=0;krow!=GROUNDROW){ + + /* loop over neighbors */ + iseligible=TRUE; + ninteriorneighbor=0; + arcnum=GetArcNumLims(nodelist[k]->row,&upperarcnum,ngroundarcs,NULL); + while(arcnumlevel > to->level){ - while(from->level != to->level){ - from=from->pred; - } - }else{ - while(from->level != to->level){ - to=to->pred; + /* get neighbor */ + from=NeighborNode(nodelist[k],++arcnum,&upperarcnum,nodes,ground, + &arcrow,&arccol,&arcdir,nrow,ncol,NULL,nodesupp); + + /* see if node can be reached through interior arc */ + /* and node is not masked or on boundary */ + /* node may be on edge of island of masked pixels, so it does not */ + /* need to be interior node in sense of not touching masked pixels */ + isinteriornode=(IsRegionInteriorArc(mag,arcrow,arccol,nrow,ncol) + && from->group!=MASKED + && from->level!=BOUNDARYLEVEL); + if(isinteriornode){ + ninteriorneighbor++; + } + + /* scan neighbor's neighbors if neighbor is interior node */ + /* or if it is edge node that is not yet on boundary */ + /* edge node may have been reached through a non-region arc, but */ + /* that is okay since that non-region arc will have zero cost */ + /* given that non-region nodes will be masked; need to let this */ + /* happen because solver will use such an arc too */ + if(isinteriornode || (from->group==BOUNDARYCANDIDATE + && from->level!=BOUNDARYLEVEL)){ + + /* loop over neighbors of neighbor */ + neighborarcnum=GetArcNumLims(from->row,&neighborupperarcnum, + ngroundarcs,NULL); + while(neighborarcnumlevel==BOUNDARYLEVEL){ + iseligible=FALSE; + break; + } + } + } + + /* break if already ineligible */ + if(!iseligible){ + break; + } + } + + /* see if we should include this node in boundary */ + if(iseligible && ninteriorneighbor>0){ + nodelist[k]->level=BOUNDARYLEVEL; + if(++boundary->nboundary > nboundarymem){ + nboundarymem+=NLISTMEMINCR; + boundarylist=(nodeT **)ReAlloc(boundarylist, + nboundarymem*sizeof(nodeT *)); + } + boundarylist[boundary->nboundary-1]=nodelist[k]; + } } } - while(from != to){ - from=from->pred; - to=to->pred; + + /* set groups of all edge nodes back to zero */ + for(k=0;kgroup=0; + nodelist[k]->next=NULL; + } + free(nodelist); + + /* punt if there were too few boundary nodes */ + /* region should be unwrapped with nodes behaving like normal grid nodes */ + /* but with neighbors that are not part of region masked */ + if(boundary->nboundarynboundary;k++){ + boundarylist[k]->level=0; + boundarylist[k]->group=0; + } + free(boundarylist); + boundary->node->row=BOUNDARYROW; + boundary->node->col=BOUNDARYCOL; + boundary->node->next=NULL; + boundary->node->prev=NULL; + boundary->node->pred=NULL; + boundary->node->level=0; + boundary->node->group=0; + boundary->node->incost=VERYFAR; + boundary->node->outcost=VERYFAR; + boundary->neighborlist=NULL; + boundary->boundarylist=NULL; + boundary->nneighbor=0; + boundary->nboundary=0; + return(source); } - return(from); -} + /* third pass */ + /* set up for creating neighbor list */ + nneighbormem=NLISTMEMINCR; + neighborlist=(neighborT *)MAlloc(nneighbormem*sizeof(neighborT)); -/* function: CandidateCompare() - * ---------------------------- - * Compares the violations of candidate arcs for sorting. First checks - * if either candidate has an arcdir magnitude greater than 1, denoting - * an augmenting cycle. Augmenting candidates are always placed before - * non-augmenting candidates. Otherwise, returns positive if the first - * candidate has a greater (less negative) violation than the second, 0 - * if they are the same, and negative otherwise. - */ -int CandidateCompare(const void *c1, const void *c2){ + /* now go through boundary pointer nodes and build neighbor list */ + for(k=0;knboundary;k++){ + + /* loop over neighbors to keep in neighbor list */ + /* checks above should ensure that unmasked neighbors of this boundary */ + /* pointer node are not reachable by any other boundary pointer node */ + arcnum=GetArcNumLims(boundarylist[k]->row,&upperarcnum,ngroundarcs,NULL); + while(arcnumgroup!=MASKED && to->level!=BOUNDARYLEVEL){ + + /* add neighbor as neighbor of boundary */ + boundary->nneighbor++; + if(boundary->nneighbor>nneighbormem){ + nneighbormem+=NLISTMEMINCR; + neighborlist=(neighborT *)ReAlloc(neighborlist, + nneighbormem*sizeof(neighborT)); + } + neighborlist[boundary->nneighbor-1].neighbor=to; + neighborlist[boundary->nneighbor-1].arcrow=arcrow; + neighborlist[boundary->nneighbor-1].arccol=arccol; + neighborlist[boundary->nneighbor-1].arcdir=arcdir; + + } - if(labs(((candidateT *)c1)->arcdir) > 1){ - if(labs(((candidateT *)c2)->arcdir) < 2){ - return(-1); } - }else if(labs(((candidateT *)c2)->arcdir) > 1){ - return(1); } - return(((candidateT *)c1)->violation - ((candidateT *)c2)->violation); + /* fourth pass */ + /* now that boundary is properly set up, make one last pass to set groups */ + for(k=0;knboundary;k++){ + boundarylist[k]->group=BOUNDARYPTR; + boundarylist[k]->level=0; + } - /* - if(((candidateT *)c1)->violation > ((candidateT *)c2)->violation){ - return(1); - }else if(((candidateT *)c1)->violation < ((candidateT *)c2)->violation){ - return(-1); - }else{ - return(0); + /* keep only needed memory and store pointers in boundary structure */ + boundary->neighborlist=(neighborT *)ReAlloc(neighborlist, + (boundary->nneighbor + *sizeof(neighborT))); + boundary->boundarylist=(nodeT **)ReAlloc(boundarylist,(boundary->nboundary + *sizeof(nodeT *))); + + /* check boundary for consistency */ + /* count number of connected nodes, which should have changed by number */ + /* outer edge nodes that got collapsed into single boundary node (minus 1) */ + nconnected=CheckBoundary(nodes,mag,ground,ngroundarcs,boundary,nrow,ncol, + params,boundary->node); + if(nconnectedptr!=NULL){ + if(nconnected+boundary->nboundary-1!=(*nconnectedptr)){ + fprintf(sp1, + "WARNING: Changed number of connected nodes in InitBoundary()\n"); + } + (*nconnectedptr)=nconnected; } - */ + + /* done */ + return(boundary->node); + } -/* function: NeighborNodeGrid() +/* function: CheckBoundary() + * ------------------------- + * Similar to SelectConnNodeSource, but reset group to zero and check boundary. + */ +static +long CheckBoundary(nodeT **nodes, float **mag, nodeT *ground, long ngroundarcs, + boundaryT *boundary, long nrow, long ncol, + paramT *params, nodeT *start){ + + long arcrow, arccol, arcdir, arcnum, upperarcnum; + long nontree, nboundaryarc, nboundarynode, nconnected; + nodeT *node1, *node2, *end; + nodesuppT **nodesupp; + + + /* if start node is not eligible, give error */ + if(start->group==MASKED){ + fflush(NULL); + fprintf(sp0,"ERROR: ineligible starting node in CheckBoundary()\n"); + exit(ABNORMAL_EXIT); + } + + /* initialize local variables */ + nconnected=0; + end=start; + nodesupp=NULL; + node1=start; + node1->group=INBUCKET; + + /* loop to search for connected, unmasked nodes */ + while(node1!=NULL){ + + /* loop over neighbors of current node */ + arcnum=GetArcNumLims(node1->row,&upperarcnum,ngroundarcs,boundary); + while(arcnumgroup!=MASKED && node2->group!=ONTREE + && node2->group!=INBUCKET){ + + node2->group=INBUCKET; + end->next=node2; + node2->next=NULL; + end=node2; + } + } + + /* mark this node visited */ + node1->group=ONTREE; + nconnected++; + + /* move to next node in list */ + node1=node1->next; + + } + + /* loop over connected nodes to check connectivity and reset group numbers */ + node1=start; + nontree=0; + nboundaryarc=0; + nboundarynode=0; + while(node1!=NULL){ + + /* loop over neighbors of current node */ + arcnum=GetArcNumLims(node1->row,&upperarcnum,ngroundarcs,boundary); + while(arcnumrow==BOUNDARYROW){ + nboundaryarc++; + } + } + + /* check number of boundary nodes */ + if(node1->row==BOUNDARYROW){ + nboundarynode++; + } + + /* count total number of nodes */ + nontree++; + + /* reset group number */ + if(node1->group==ONTREE){ + node1->group=0; + } + + /* move to next node in list */ + node1=node1->next; + + } + + /* check for consistency */ + if(nontree!=nconnected){ + fflush(NULL); + fprintf(sp0, + "ERROR: inconsistent num connected nodes in CheckBoundary()\n"); + exit(ABNORMAL_EXIT); + } + if(nboundaryarc!=boundary->nneighbor){ + fflush(NULL); + fprintf(sp0, + "ERROR: inconsistent num neighbor nodes in CheckBoundary()\n"); + exit(ABNORMAL_EXIT); + } + if(nboundarynode!=1){ + fflush(NULL); + fprintf(sp0, + "ERROR: number of boundary nodes is not 1 in CheckBoundary()\n"); + exit(ABNORMAL_EXIT); + } + + /* return number of connected nodes */ + return(nconnected); + +} + + +/* function: IsRegionEdgeArc() + * --------------------------- + * Return TRUE if arc is on edge of region, FALSE otherwise. + */ +static +int IsRegionEdgeArc(float **mag, long arcrow, long arccol, + long nrow, long ncol){ + + long row1, col1, row2, col2, nzeromag; + + /* if no magnitude, then everything is in single region */ + if(mag==NULL){ + return(FALSE); + } + + /* determine indices of pixels on either side of this arc */ + if(arcrow0 && mag[row2][col2]>0){ + return(TRUE); + } + return(FALSE); + +} + + +/* function: IsRegionArc() + * ----------------------- + * Return TRUE if arc goes between two nodes in same region such that + * at least one pixel magnitude on either side of arc is nonzero. + */ +static +int IsRegionArc(float **mag, long arcrow, long arccol, + long nrow, long ncol){ + + long row1, col1, row2, col2; + + + /* if no magnitude, everything is in single region */ + if(mag==NULL){ + return(TRUE); + } + + /* determine indices of pixels on either side of this arc */ + if(arcrow0 || mag[row2][col2]>0){ + return(TRUE); + } + return(FALSE); + +} + + +/* function: IsInteriorNode() + * -------------------------- + * Return TRUE if node does not touch any zero magnitude pixels, FALSE + * otherwise. + */ +/* + * This function is no longer used + */ +#if 0 +static +int IsInteriorNode(float **mag, long row, long col, long nrow, long ncol); +static +int IsInteriorNode(float **mag, long row, long col, long nrow, long ncol){ + + /* if there is no magnitude info, then all nodes are interior nodes */ + if(mag==NULL){ + return(TRUE); + } + + /* check for ground */ + if(row==GROUNDROW){ + return(FALSE); + } + + /* check mag */ + if(mag[row][col]==0 || mag[row+1][col]==0 + || mag[row][col+1]==0 || mag[row+1][col+1]==0){ + return(FALSE); + } + return(TRUE); + +} +#endif + + +/* function: IsRegionEdgeNode() + * ---------------------------- + * Return TRUE if node touches at least one zero magnitude pixel and + * at least one non-zero magnitude pixel, FALSE otherwise. + */ +static +int IsRegionEdgeNode(float **mag, long row, long col, long nrow, long ncol){ + + int onezeromag, onenonzeromag; + + + /* if there is no magnitude info, then no nodes are on edge */ + if(mag==NULL){ + return(FALSE); + } + + /* check for ground */ + if(row==GROUNDROW){ + return(FALSE); + } + + /* check mag for one zero mag and one nonzero mag pixel around node */ + onezeromag=FALSE; + onenonzeromag=FALSE; + if(mag[row][col]==0 || mag[row+1][col]==0 + || mag[row][col+1]==0 || mag[row+1][col+1]==0){ + onezeromag=TRUE; + } + if(mag[row][col]!=0 || mag[row+1][col]!=0 + || mag[row][col+1]!=0 || mag[row+1][col+1]!=0){ + onenonzeromag=TRUE; + } + if(onezeromag && onenonzeromag){ + return(TRUE); + } + return(FALSE); + +} + + +/* function: CleanUpBoundaryNodes() + * -------------------------------- + * Unset group values indicating boundary nodes on network. This is + * necessary because InitBoundary() temporarily sets node groups to + * MASKED if the node is in a different region than the current but + * can be reached from the current region. This can occur if two + * regions are separated by a single row or column of masked pixels. + */ +static +int CleanUpBoundaryNodes(nodeT *source, boundaryT *boundary, float **mag, + nodeT **nodes, nodeT *ground, + long nrow, long ncol, long ngroundarcs, + nodesuppT **nodesupp){ + + long nconnected; + nodeT *start; + + + /* do nothing if this is not a grid network */ + if(nodesupp!=NULL){ + return(0); + } + + /* starting node should not be boundary */ + if(source->row==BOUNDARYROW){ + start=boundary->neighborlist[0].neighbor; + }else{ + start=source; + } + + /* scan region and unmask any nodes that touch good pixels since they */ + /* may have been masked by the ScanRegion() call in InitBoundaries() */ + nconnected=ScanRegion(start,nodes,mag,ground,ngroundarcs,nrow,ncol,0); + + /* done */ + return(nconnected); + +} + + +/* function: DischargeBoundary() + * ----------------------------- + * Find nodes and arcs along edge of region (defined by zero magnitude) and + * compute surplus/demand by balancing flow in/out of nodes. Then discharge + * surplus/demand by sending flow along zero-cost arcs along region edge. + */ +static +int DischargeBoundary(nodeT **nodes, nodeT *ground, + boundaryT *boundary, nodesuppT **nodesupp, short **flows, + signed char **iscandidate, float **mag, + float **wrappedphase, long ngroundarcs, + long nrow, long ncol){ + + long nedgenode; + long row, col, fromrow, fromcol, todir; + long arcnum, upperarcnum, arcrow, arccol, arcdir, narccol; + long surplus, residue, excess; + nodeT *from, *to, *nextnode; + + + /* do nothing if we have no boundary */ + if(nodesupp!=NULL || boundary==NULL + || boundary->nboundary==0 || boundary->nneighbor==0){ + return(0); + } + + /* find initial region edge node */ + nextnode=boundary->boundarylist[0]; + row=nextnode->row; + col=nextnode->col; + if(!IsRegionEdgeNode(mag,row,col,nrow,ncol)){ + fprintf(sp0,"ERROR: DischargeBoundary() start node %ld, %ld not on edge\n", + row,col); + exit(ABNORMAL_EXIT); + } + + /* silence compiler warnings */ + row=0; + col=0; + todir=0; + + /* make sure iscandidate is zero */ + /* temporarily set illegal corner arcs to 0 to simplify logic (reset later) */ + for(row=0;row<2*nrow-1;row++){ + if(rowoutcost=-1; + nextnode=NULL; + + /* loop over outgoing arcs */ + /* pass NULL to NeighborNode() for boundary so as not to follow */ + /* node pointers to boundary node */ + arcnum=GetArcNumLims(from->row,&upperarcnum,ngroundarcs,NULL); + while(arcnumoutcost!=-1))){ + + /* save arc */ + nextnode=to; + row=arcrow; + col=arccol; + todir=arcdir; + + /* stop and follow arc if arc not yet followed */ + if(!iscandidate[arcrow][arccol]){ + break; + } + + } + } + + /* break if no unfollowed arcs (ie, we are done examining tree) */ + if(nextnode==NULL){ + break; + } + + /* if we found leaf and we're moving back up the tree, do a push */ + /* otherwise, just mark the path by decrementing iscandidate */ + if((--iscandidate[row][col])==-2){ + + /* integrate flow into current node */ + fromrow=from->row; + fromcol=from->col; + surplus=(flows[fromrow][fromcol] + -flows[fromrow][fromcol+1] + +flows[fromrow+nrow-1][fromcol] + -flows[fromrow+1+nrow-1][fromcol]); + + /* compute residue from wrapped phase */ + residue=NodeResidue(wrappedphase,fromrow,fromcol); + + /* compute excess as surplus plus residue */ + excess=surplus+residue; + + /* augment flow */ + flows[row][col]+=todir*excess; + + /* increment counter of edge nodes */ + nedgenode++; + + } + + } + + /* reset all iscandidate and outcost values */ + /* set illegal corner arc iscandidate values back to TRUE */ + /* outcost of region edge nodes should be zero if source was on edge */ + /* and arc costs along boundary are all zero */ + for(row=0;row0){ + nodes[row][col-1].outcost=0; + } + if(col0){ + nodes[row-1][col].outcost=0; + } + if(rowgroup=1; + source->outcost=0; + source->incost=0; + source->pred=NULL; + source->prev=source; + source->next=source; + source->level=0; + + /* loop over outgoing arcs and add to buckets */ + arcnum=GetArcNumLims(source->row,&upperarcnum,ngroundarcs,boundary); + while(arcnumgroup!=PRUNED && to->group!=MASKED){ + AddNewNode(source,to,arcdir,bkts,nflow,incrcosts,arcrow,arccol,params); + } + + } + + /* done */ + return(0); + +} + + +/* function: FindApex() + * -------------------- + * Given pointers to two nodes on a spanning tree, the function finds + * and returns a pointer to their deepest common ancestor, the apex of + * a cycle formed by joining the two nodes with an arc. + */ +static +nodeT *FindApex(nodeT *from, nodeT *to){ + + if(from->level > to->level){ + while(from->level != to->level){ + from=from->pred; + } + }else{ + while(from->level != to->level){ + to=to->pred; + } + } + while(from != to){ + from=from->pred; + to=to->pred; + } + return(from); +} + + +/* function: CandidateCompare() + * ---------------------------- + * Compares the violations of candidate arcs for sorting. First checks + * if either candidate has an arcdir magnitude greater than 1, denoting + * an augmenting cycle. Augmenting candidates are always placed before + * non-augmenting candidates. Otherwise, returns positive if the first + * candidate has a greater (less negative) violation than the second, 0 + * if they are the same, and negative otherwise. + */ +static +int CandidateCompare(const void *c1, const void *c2){ + + if(labs(((candidateT *)c1)->arcdir) > 1){ + if(labs(((candidateT *)c2)->arcdir) < 2){ + return(-1); + } + }else if(labs(((candidateT *)c2)->arcdir) > 1){ + return(1); + } + + return(((candidateT *)c1)->violation - ((candidateT *)c2)->violation); + + /* + if(((candidateT *)c1)->violation > ((candidateT *)c2)->violation){ + return(1); + }else if(((candidateT *)c1)->violation < ((candidateT *)c2)->violation){ + return(-1); + }else{ + return(0); + } + */ +} + + +/* function: GetArcNumLims() + * ------------------------- + * Get the initial and ending values for arcnum to find neighbors of + * the passed node. + */ +static inline +long GetArcNumLims(long fromrow, long *upperarcnumptr, + long ngroundarcs, boundaryT *boundary){ + + long arcnum; + + /* set arcnum limits based on node type */ + if(fromrow<0){ + arcnum=-1; + if(fromrow==GROUNDROW){ + *upperarcnumptr=ngroundarcs-1; + }else{ + *upperarcnumptr=boundary->nneighbor-1; + } + }else{ + arcnum=-5; + *upperarcnumptr=-1; + } + return(arcnum); + +} + + +/* function: NeighborNodeGrid() * ---------------------------- * Return the neighboring node of the given node corresponding to the * given arc number for a grid network with a ground node. */ +static nodeT *NeighborNodeGrid(nodeT *node1, long arcnum, long *upperarcnumptr, - nodeT **nodes, nodeT *ground, long *arcrowptr, - long *arccolptr, long *arcdirptr, long nrow, - long ncol, nodesuppT **nodesupp){ + nodeT **nodes, nodeT *ground, long *arcrowptr, + long *arccolptr, long *arcdirptr, long nrow, + long ncol, boundaryT *boundary, nodesuppT **nodesupp){ long row, col; + nodeT *neighbor; + /* get starting node row and col for convenience */ row=node1->row; col=node1->col; - switch(arcnum){ - case -4: - *arcrowptr=row; - *arccolptr=col+1; - *arcdirptr=1; - if(col==ncol-2){ - return(ground); - }else{ - return(&nodes[row][col+1]); - } - break; - case -3: - *arcrowptr=nrow+row; - *arccolptr=col; - *arcdirptr=1; - if(row==nrow-2){ - return(ground); - }else{ - return(&nodes[row+1][col]); - } - break; - case -2: - *arcrowptr=row; - *arccolptr=col; - *arcdirptr=-1; - if(col==0){ - return(ground); - }else{ - return(&nodes[row][col-1]); - } - break; - case -1: - *arcrowptr=nrow-1+row; - *arccolptr=col; - *arcdirptr=-1; - if(row==0){ - return(ground); - }else{ - return(&nodes[row-1][col]); - } - break; - default: - if(arcnumneighborlist[arcnum].neighbor; + *arcrowptr=boundary->neighborlist[arcnum].arcrow; + *arccolptr=boundary->neighborlist[arcnum].arccol; + *arcdirptr=boundary->neighborlist[arcnum].arcdir; + + }else{ + + /* starting node is normal node */ + switch(arcnum){ + case -4: + *arcrowptr=row; + *arccolptr=col+1; *arcdirptr=1; - return(&nodes[*arcrowptr][0]); - }else if(arcnum<2*(nrow-1)){ - *arcrowptr=arcnum-(nrow-1); - *arccolptr=ncol-1; - *arcdirptr=-1; - return(&nodes[*arcrowptr][ncol-2]); - }else if(arcnum<2*(nrow-1)+ncol-3){ - *arcrowptr=nrow-1; - *arccolptr=arcnum-2*(nrow-1)+1; + if(col==ncol-2){ + neighbor=ground; + }else{ + neighbor=&nodes[row][col+1]; + } + break; + case -3: + *arcrowptr=nrow+row; + *arccolptr=col; *arcdirptr=1; - return(&nodes[0][*arccolptr]); - }else{ - *arcrowptr=2*nrow-2; - *arccolptr=arcnum-(2*(nrow-1)+ncol-3)+1; + if(row==nrow-2){ + neighbor=ground; + }else{ + neighbor=&nodes[row+1][col]; + } + break; + case -2: + *arcrowptr=row; + *arccolptr=col; *arcdirptr=-1; - return(&nodes[nrow-2][*arccolptr]); + if(col==0){ + neighbor=ground; + }else{ + neighbor=&nodes[row][col-1]; + } + break; + + case -1: + *arcrowptr=nrow-1+row; + *arccolptr=col; + *arcdirptr=-1; + if(row==0){ + neighbor=ground; + }else{ + neighbor=&nodes[row-1][col]; + } + break; + default: + if(arcnumgroup==BOUNDARYPTR && boundary!=NULL){ + neighbor=boundary->node; } - break; + } + /* return neighbor */ + return(neighbor); + } @@ -1094,10 +2199,12 @@ nodeT *NeighborNodeGrid(nodeT *node1, long arcnum, long *upperarcnumptr, * Return the neighboring node of the given node corresponding to the * given arc number for a nongrid network (ie, arbitrary topology). */ +static nodeT *NeighborNodeNonGrid(nodeT *node1, long arcnum, long *upperarcnumptr, - nodeT **nodes, nodeT *ground, long *arcrowptr, - long *arccolptr, long *arcdirptr, long nrow, - long ncol, nodesuppT **nodesupp){ + nodeT **nodes, nodeT *ground, long *arcrowptr, + long *arccolptr, long *arcdirptr, long nrow, + long ncol, boundaryT *boundary, + nodesuppT **nodesupp){ long tilenum, nodenum; scndryarcT *outarc; @@ -1128,11 +2235,14 @@ nodeT *NeighborNodeNonGrid(nodeT *node1, long arcnum, long *upperarcnumptr, * Given a from node and a to node, sets pointers for indices into * arc arrays, assuming primary (grid) network. */ +static void GetArcGrid(nodeT *from, nodeT *to, long *arcrow, long *arccol, - long *arcdir, long nrow, long ncol, nodesuppT **nodesupp){ + long *arcdir, long nrow, long ncol, + nodeT **nodes, nodesuppT **nodesupp){ long fromrow, fromcol, torow, tocol; + fromrow=from->row; fromcol=from->col; torow=to->row; @@ -1154,6 +2264,42 @@ void GetArcGrid(nodeT *from, nodeT *to, long *arcrow, long *arccol, *arcrow=fromrow+nrow-1; *arccol=fromcol; *arcdir=-1; + }else if(fromrow==BOUNDARYROW){ /* arc from boundary pointer */ + if(tocol0 && nodes[torow][tocol-1].group==BOUNDARYPTR){ + *arcrow=torow; + *arccol=tocol; + *arcdir=1; + }else if(torow0 && nodes[fromrow][fromcol-1].group==BOUNDARYPTR){ + *arcrow=fromrow; + *arccol=fromcol; + *arcdir=-1; + }else if(fromrowpred,node2,&arcrow,&arccol,&arcdir,nrow,ncol,nodesupp); + GetArc(node2->pred,node2,&arcrow,&arccol,&arcdir,nrow,ncol, + nodes,nodesupp); doutcost=node1->outcost - node2->outcost + GetCost(incrcosts,arcrow,arccol,arcdir); node2->outcost+=doutcost; @@ -1259,16 +2411,10 @@ void NonDegenUpdateChildren(nodeT *startnode, nodeT *lastnode, /* update potentials of children of this node in the flow path */ node1=node2; - if(node1->row!=GROUNDROW){ - arcnum=-5; - upperarcnum=-1; - }else{ - arcnum=-1; - upperarcnum=ngroundarcs-1; - } + arcnum=GetArcNumLims(node1->row,&upperarcnum,ngroundarcs,boundary); while(arcnumpred==node1 && node2->group>0){ if(node2->group==pathgroup){ nextonpath=node2; @@ -1288,126 +2434,421 @@ void NonDegenUpdateChildren(nodeT *startnode, nodeT *lastnode, } } } + return; +} + + +/* function: PruneTree() + * --------------------- + * Descends the tree from the source and finds leaves that can be + * removed. + */ +static +long PruneTree(nodeT *source, nodeT **nodes, nodeT *ground, boundaryT *boundary, + nodesuppT **nodesupp, incrcostT **incrcosts, + short **flows, long ngroundarcs, long prunecostthresh, + long nrow, long ncol){ + + long npruned; + nodeT *node1; + + /* set up */ + npruned=0; + + /* descend tree and look for leaves to prune */ + node1=source->next; + while(node1!=source){ + + /* see if current node is a leaf that should be pruned */ + if(CheckLeaf(node1,nodes,ground,boundary,nodesupp,incrcosts,flows, + ngroundarcs,nrow,ncol,prunecostthresh)){ + + /* remove the current node from the tree */ + node1->prev->next=node1->next; + node1->next->prev=node1->prev; + node1->group=PRUNED; + npruned++; + + /* see if last node checked was current node's parent */ + /* if so, it may need pruning since its child has been pruned */ + if(node1->prev->level < node1->level){ + node1=node1->prev; + }else{ + node1=node1->next; + } + + }else{ + + /* move on to next node */ + node1=node1->next; + + } + } + + /* show status */ + fprintf(sp3,"\n Pruned %ld nodes\n",npruned); + + /* return number of pruned nodes */ + return(npruned); + +} + + +/* function: CheckLeaf() + * --------------------- + * Checks to see if the passed node should be pruned from the tree. + * The node should be pruned if it is a leaf and if all of its outgoing + * arcs have very high costs and only lead to other nodes that are already + * on the tree or are already pruned. + */ +static +int CheckLeaf(nodeT *node1, nodeT **nodes, nodeT *ground, boundaryT *boundary, + nodesuppT **nodesupp, incrcostT **incrcosts, + short **flows, long ngroundarcs, long nrow, long ncol, + long prunecostthresh){ + + long arcnum, upperarcnum, arcrow, arccol, arcdir; + nodeT *node2; + + + /* first, check to see if node1 is a leaf */ + if(node1->next->level > node1->level){ + return(FALSE); + } + + /* loop over outgoing arcs */ + arcnum=GetArcNumLims(node1->row,&upperarcnum,ngroundarcs,boundary); + while(arcnumgroup==0 || node2->group==INBUCKET + || incrcosts[arcrow][arccol].poscostnshortcycle>LARGESHORT){ + fprintf(sp1,"Maximum flow on network: %ld\n",*mostflowptr); + fflush(NULL); + fprintf(sp0,"((Maximum flow) * NSHORTCYCLE) too large\nAbort\n"); + exit(ABNORMAL_EXIT); + } + if(ncol>2){ + *ngroundarcsptr=2*(nrow+ncol-2)-4; /* don't include corner column arcs */ + }else{ + *ngroundarcsptr=2*(nrow+ncol-2)-2; + } + *iscandidateptr=(signed char **)Get2DRowColMem(nrow,ncol, + sizeof(signed char *), + sizeof(signed char)); + *apexesptr=(nodeT ***)Get2DRowColMem(nrow,ncol,sizeof(nodeT **), + sizeof(nodeT *)); + } + + /* set up buckets for TreeSolve (MSTInitFlows() has local set of buckets) */ + *bktsptr=MAlloc(sizeof(bucketT)); + if(ground!=NULL){ + (*bktsptr)->minind=-LRound((params->maxcost+1)*(nrow+ncol) + *NEGBUCKETFRACTION); + (*bktsptr)->maxind=LRound((params->maxcost+1)*(nrow+ncol) + *POSBUCKETFRACTION); + }else{ + (*bktsptr)->minind=-LRound((params->maxcost+1)*(nrow) + *NEGBUCKETFRACTION); + (*bktsptr)->maxind=LRound((params->maxcost+1)*(nrow) + *POSBUCKETFRACTION); + } + (*bktsptr)->size=(*bktsptr)->maxind-(*bktsptr)->minind+1; + (*bktsptr)->bucketbase=(nodeT **)MAlloc((*bktsptr)->size*sizeof(nodeT *)); + (*bktsptr)->bucket=&((*bktsptr)->bucketbase[-(*bktsptr)->minind]); + for(i=0;i<(*bktsptr)->size;i++){ + (*bktsptr)->bucketbase[i]=NULL; + } + + /* get memory for incremental cost arrays */ + *iincrcostfileptr=0; + if(ground!=NULL){ + (*incrcostsptr)=(incrcostT **)Get2DRowColMem(nrow,ncol,sizeof(incrcostT *), + sizeof(incrcostT)); + } + + /* set number of nodes and arcs per row */ + if(ground!=NULL){ + (*nnoderowptr)=nrow-1; + (*nnodesperrowptr)=(int *)MAlloc((nrow-1)*sizeof(int)); + for(i=0;igroup!=MASKED){ + ground->group=0; + nnodes++; + } + ground->incost=VERYFAR; + ground->outcost=VERYFAR; + ground->pred=NULL; + } + + /* initialize arcs */ + for(row=0;row0){ + return(0); + } + } + } + return(1); + +} + + +/* function: MaskNodes() + * --------------------- + * Set group numbers of nodes to MASKED if they are surrounded by + * zero-magnitude pixels, 0 otherwise. + */ +int MaskNodes(long nrow, long ncol, nodeT **nodes, nodeT *ground, + float **mag){ + + long row, col; + + /* loop over grid nodes and see if masking is necessary */ + for(row=0;rowgroup=GroundMaskStatus(nrow,ncol,mag); + + /* done */ + return(0); + } -/* function: InitNetowrk() - * ----------------------- +/* function: GridNodeMaskStatus() + * --------------------------------- + * Given row and column of grid node, return MASKED if all pixels around node + * have zero magnitude, and 0 otherwise. */ -void InitNetwork(short **flows, long *ngroundarcsptr, long *ncycleptr, - long *nflowdoneptr, long *mostflowptr, long *nflowptr, - long *candidatebagsizeptr, candidateT **candidatebagptr, - long *candidatelistsizeptr, candidateT **candidatelistptr, - signed char ***iscandidateptr, nodeT ****apexesptr, - bucketT **bktsptr, long *iincrcostfileptr, - incrcostT ***incrcostsptr, nodeT ***nodesptr, nodeT *ground, - long *nnoderowptr, short **nnodesperrowptr, long *narcrowptr, - short **narcsperrowptr, long nrow, long ncol, - signed char *notfirstloopptr, totalcostT *totalcostptr, - paramT *params){ +static +int GridNodeMaskStatus(long row, long col, float **mag){ - long i; + /* return 0 if any pixel is not masked */ + if(mag[row][col] || mag[row][col+1] + || mag[row+1][col] || mag[row+1][col+1]){ + return(0); + } + return(MASKED); + +} - /* get and initialize memory for nodes */ - if(ground!=NULL && *nodesptr==NULL){ - *nodesptr=(nodeT **)Get2DMem(nrow-1,ncol-1,sizeof(nodeT *),sizeof(nodeT)); - InitNodeNums(nrow-1,ncol-1,*nodesptr,ground); - } +/* function: GroundMaskStatus() + * ---------------------------- + * Return MASKED if all pixels around grid edge have zero magnitude, 0 + * otherwise. + */ +static +int GroundMaskStatus(long nrow, long ncol, float **mag){ - /* take care of ambiguous flows to ground at corners */ - if(ground!=NULL){ - flows[0][0]+=flows[nrow-1][0]; - flows[nrow-1][0]=0; - flows[0][ncol-1]-=flows[nrow-1][ncol-2]; - flows[nrow-1][ncol-2]=0; - flows[nrow-2][0]-=flows[2*nrow-2][0]; - flows[2*nrow-2][0]=0; - flows[nrow-2][ncol-1]+=flows[2*nrow-2][ncol-2]; - flows[2*nrow-2][ncol-2]=0; - } + long row, col; + - /* initialize network solver variables */ - *ncycleptr=0; - *nflowptr=1; - *candidatebagsizeptr=INITARRSIZE; - *candidatebagptr=MAlloc(*candidatebagsizeptr*sizeof(candidateT)); - *candidatelistsizeptr=INITARRSIZE; - *candidatelistptr=MAlloc(*candidatelistsizeptr*sizeof(candidateT)); - if(ground!=NULL){ - *nflowdoneptr=0; - *mostflowptr=Short2DRowColAbsMax(flows,nrow,ncol); - if(*mostflowptr*params->nshortcycle>LARGESHORT){ - fprintf(sp1,"Maximum flow on network: %ld\n",*mostflowptr); - fprintf(sp0,"((Maximum flow) * NSHORTCYCLE) too large\nAbort\n"); - exit(ABNORMAL_EXIT); + /* check all pixels along edge */ + for(row=0;row2){ - *ngroundarcsptr=2*(nrow+ncol-2)-4; /* don't include corner column arcs */ - }else{ - *ngroundarcsptr=2*(nrow+ncol-2)-2; + } + for(col=0;colminind=-LRound((params->maxcost+1)*(nrow+ncol) - *NEGBUCKETFRACTION); - (*bktsptr)->maxind=LRound((params->maxcost+1)*(nrow+ncol) - *POSBUCKETFRACTION); - }else{ - (*bktsptr)->minind=-LRound((params->maxcost+1)*(nrow) - *NEGBUCKETFRACTION); - (*bktsptr)->maxind=LRound((params->maxcost+1)*(nrow) - *POSBUCKETFRACTION); - } - (*bktsptr)->size=(*bktsptr)->maxind-(*bktsptr)->minind+1; - (*bktsptr)->bucketbase=(nodeT **)MAlloc((*bktsptr)->size*sizeof(nodeT *)); - (*bktsptr)->bucket=&((*bktsptr)->bucketbase[-(*bktsptr)->minind]); - for(i=0;i<(*bktsptr)->size;i++){ - (*bktsptr)->bucketbase[i]=NULL; - } - /* get memory for incremental cost arrays */ - *iincrcostfileptr=0; - if(ground!=NULL){ - (*incrcostsptr)=(incrcostT **)Get2DRowColMem(nrow,ncol,sizeof(incrcostT *), - sizeof(incrcostT)); - } +/* function: MaxNonMaskFlowMag() + * ----------------------------- + * Return maximum flow magnitude that does not traverse an arc adjacent + * to a masked interferogram pixel. + */ +long MaxNonMaskFlow(short **flows, float **mag, long nrow, long ncol){ - /* set number of nodes and arcs per row */ - if(ground!=NULL){ - (*nnoderowptr)=nrow-1; - (*nnodesperrowptr)=(short *)MAlloc((nrow-1)*sizeof(short)); - for(i=0;imostflow && mag[row][col]>0 && mag[row+1][col]>0){ + mostflow=flowvalue; + } } - for(i=nrow-1;i<2*nrow-1;i++){ - (*narcsperrowptr)[i]=ncol-1; + } + for(row=nrow-1;row<2*nrow-1;row++){ + for(col=0;colmostflow + && mag[row-nrow+1][col]>0 && mag[row-nrow+1][col+1]>0){ + mostflow=flowvalue; + } } } - - /* initialize variables for main optimizer loop */ - (*notfirstloopptr)=FALSE; - (*totalcostptr)=INITTOTALCOST; + return(mostflow); } /* function: InitNodeNums() * ------------------------ */ -void InitNodeNums(long nrow, long ncol, nodeT **nodes, nodeT *ground){ +int InitNodeNums(long nrow, long ncol, nodeT **nodes, nodeT *ground){ long row, col; @@ -1424,13 +2865,18 @@ void InitNodeNums(long nrow, long ncol, nodeT **nodes, nodeT *ground){ ground->row=GROUNDROW; ground->col=GROUNDCOL; } + + /* done */ + return(0); + } /* function: InitBuckets() * ----------------------- */ -void InitBuckets(bucketT *bkts, nodeT *source, long nbuckets){ +static +int InitBuckets(bucketT *bkts, nodeT *source, long nbuckets){ long i; @@ -1449,6 +2895,9 @@ void InitBuckets(bucketT *bkts, nodeT *source, long nbuckets){ source->prev=NULL; source->group=INBUCKET; source->outcost=0; + + /* done */ + return(0); } @@ -1456,7 +2905,7 @@ void InitBuckets(bucketT *bkts, nodeT *source, long nbuckets){ /* function: InitNodes() * --------------------- */ -void InitNodes(long nnrow, long nncol, nodeT **nodes, nodeT *ground){ +int InitNodes(long nnrow, long nncol, nodeT **nodes, nodeT *ground){ long row, col; @@ -1464,6 +2913,7 @@ void InitNodes(long nnrow, long nncol, nodeT **nodes, nodeT *ground){ for(row=0;rowgroup=NOTINBUCKET; + ground->incost=VERYFAR; ground->outcost=VERYFAR; ground->pred=NULL; } + + /* done */ + return(0); } @@ -1495,6 +2949,9 @@ void BucketInsert(nodeT *node, long ind, bucketT *bkts){ /* mark node in bucket array */ node->group=INBUCKET; + /* done */ + return; + } @@ -1515,6 +2972,9 @@ void BucketRemove(nodeT *node, long ind, bucketT *bkts){ bkts->bucket[ind]=node->next; } + /* done */ + return; + } @@ -1530,7 +2990,7 @@ nodeT *ClosestNode(bucketT *bkts){ /* see if we got to the last bucket */ if((bkts->curr)>(bkts->maxind)){ - return(NULL); + return(NULL); } /* see if we found a nonempty bucket; if so, return it */ @@ -1539,7 +2999,7 @@ nodeT *ClosestNode(bucketT *bkts){ node->group=ONTREE; bkts->bucket[bkts->curr]=node->next; if((node->next)!=NULL){ - node->next->prev=NULL; + node->next->prev=NULL; } return(node); } @@ -1557,6 +3017,13 @@ nodeT *ClosestNode(bucketT *bkts){ * function should NOT be used if negative arc weights exist on the * network; initial value of bkts->minind should always be zero. */ +/* + * This function is no longer used + */ +#if 0 +static +nodeT *ClosestNodeCircular(bucketT *bkts); +static nodeT *ClosestNodeCircular(bucketT *bkts){ nodeT *node; @@ -1567,12 +3034,12 @@ nodeT *ClosestNodeCircular(bucketT *bkts){ /* see if we got to the last bucket */ if((bkts->curr+bkts->minind)>(bkts->maxind)){ if(bkts->wrapped){ - bkts->wrapped=FALSE; - bkts->curr=0; - bkts->minind+=bkts->size; - bkts->maxind+=bkts->size; + bkts->wrapped=FALSE; + bkts->curr=0; + bkts->minind+=bkts->size; + bkts->maxind+=bkts->size; }else{ - return(NULL); + return(NULL); } } @@ -1582,7 +3049,7 @@ nodeT *ClosestNodeCircular(bucketT *bkts){ node->group=ONTREE; bkts->bucket[bkts->curr]=node->next; if((node->next)!=NULL){ - node->next->prev=NULL; + node->next->prev=NULL; } return(node); } @@ -1592,6 +3059,7 @@ nodeT *ClosestNodeCircular(bucketT *bkts){ } } +#endif /* function: MinOutCostNode() @@ -1601,6 +3069,7 @@ nodeT *ClosestNodeCircular(bucketT *bkts){ * buckets. Does not handle no nodes left condition (this should be handled * by calling function). */ +static nodeT *MinOutCostNode(bucketT *bkts){ long minoutcost; @@ -1619,8 +3088,8 @@ nodeT *MinOutCostNode(bucketT *bkts){ minoutcost=node1->outcost; while(node2!=NULL){ if(node2->outcostoutcost; - node1=node2; + minoutcost=node2->outcost; + node1=node2; } node2=node2->next; } @@ -1641,168 +3110,310 @@ nodeT *MinOutCostNode(bucketT *bkts){ } -/* function: SelectSource() - * ------------------------ - * If params->sourcemode is zero, the ground is returned as the source. - * Otherwise, the returned source is the endpoint of the longest chain of - * arcs carrying at least nflow units of flow. This function does - * check for the case where two arcs both carry nflow into or out of a node, - * but if there are flow cycles (not unexpected for nonlinear costs), the - * longest chain is not guaranteed. Which end of the longest chain is - * determined by the sign of params->sourcemode (should be 1 or -1 if not 0). +/* function: SelectSources() + * ------------------------- + * Create a list of node pointers to be sources for each set of + * connected pixels (not disconnected by masking). Return the number + * of sources (ie, the number of connected sets of pixels). */ -nodeT *SelectSource(nodeT **nodes, nodeT *ground, long nflow, - short **flows, long ngroundarcs, - long nrow, long ncol, paramT *params){ - - long row, col, maxflowlength, arcnum, upperarcnum; - long arcrow, arccol, arcdir, endptsign; - signed char checknode; - nodeT *source, *node1, *node2, *nextnode; - nodesuppT **nodesupp; +long SelectSources(nodeT **nodes, float **mag, nodeT *ground, long nflow, + short **flows, long ngroundarcs, + long nrow, long ncol, paramT *params, + nodeT ***sourcelistptr, long **nconnectedarrptr){ + + long row, col, nsource, nsourcelistmem, nconnected; + long *nconnectedarr; + nodeT *source; + nodeT **sourcelist; - /* if sourcemode==0, return ground node; otherwise, it should be 1 or -1 */ - if(!params->sourcemode){ - return(ground); - }else{ - endptsign=params->sourcemode; - } - /* initialize variables */ - /* group: 0=unvisited, 1=descended, 2=done */ - /* outcost: longest distance to a chain end */ - /* pred: parent node */ - nodesupp=NULL; - source=ground; - maxflowlength=0; - ground->group=0; - ground->outcost=0; - ground->pred=NULL; + /* initialize local variables */ + nsource=0; + nsourcelistmem=0; + sourcelist=NULL; + nconnectedarr=NULL; + + /* loop over nodes to initialize */ + if(ground->group!=MASKED && ground->group!=BOUNDARYPTR){ + ground->group=0; + } + ground->next=NULL; for(row=0;rownsourcelistmem){ + nsourcelistmem+=NSOURCELISTMEMINCR; + sourcelist=ReAlloc(sourcelist,nsourcelistmem*sizeof(nodeT *)); + nconnectedarr=ReAlloc(nconnectedarr,nsourcelistmem*sizeof(long)); + } + + /* store source in list */ + sourcelist[nsource-1]=source; + nconnectedarr[nsource-1]=nconnected; + + } + + /* loop over nodes to find next set of connected nodes */ + for(row=0;rownsourcelistmem){ + nsourcelistmem+=NSOURCELISTMEMINCR; + sourcelist=ReAlloc(sourcelist,nsourcelistmem*sizeof(nodeT *)); + nconnectedarr=ReAlloc(nconnectedarr,nsourcelistmem*sizeof(long)); + } + + /* store source in list */ + sourcelist[nsource-1]=source; + nconnectedarr[nsource-1]=nconnected; + } + } + } - /* see if this node is an endpoint */ - checknode=FALSE; - if(!node1->group){ - if(node1!=ground){ - arcnum=-5; - upperarcnum=-1; - }else{ - arcnum=-1; - upperarcnum=ngroundarcs-1; - } - while(arcnum= nflow){ - checknode=FALSE; - break; - } - - /* node may be beginning of a chain */ - if(endptsign*arcdir*flows[arcrow][arccol] >= nflow){ - checknode=TRUE; - } - } + /* show message about number of connected regions */ + fprintf(sp1,"Found %ld valid set(s) of connected nodes\n",nsource); + + /* reset group values for all nodes */ + if(ground->group!=MASKED && ground->group!=BOUNDARYPTR){ + ground->group=0; + } + ground->next=NULL; + for(row=0;row= nflow){ - if(node2->group==2){ - if(node2->outcost+1 > node1->outcost){ - node1->outcost=node2->outcost+1; - } - }else if(node2->group==0){ - nextnode=node2; - break; - } - }else if(node2==node1->pred){ - nextnode=node2; - } - } - - /* we are back to the root if we didn't find any eligible nodes */ - if(nextnode==NULL){ - - /* see if the tree root should be the new source */ - if(node1->outcost > maxflowlength){ - source=node1; - maxflowlength=node1->outcost; - } - node1->group=2; - break; - } - - /* if nextnode is pred, mark current node and go back up the tree */ - if(nextnode->group==1){ - node1->group=2; - }else{ - node1->group=1; - nextnode->pred=node1; - } - } + if(nodes[row][col].group!=MASKED && nodes[row][col].group!=BOUNDARYPTR){ + nodes[row][col].group=0; } + nodes[row][col].next=NULL; } } + + + /* done */ + if(sourcelistptr!=NULL){ + (*sourcelistptr)=sourcelist; + }else{ + fflush(NULL); + fprintf(sp0,"ERROR: NULL sourcelistptr in SelectSources()\nAbort\n"); + exit(ABNORMAL_EXIT); + } + if(nconnectedarrptr!=NULL){ + (*nconnectedarrptr)=nconnectedarr; + }else{ + fflush(NULL); + fprintf(sp0,"ERROR: NULL nconnectedarrptr SelectSources()\nAbort\n"); + exit(ABNORMAL_EXIT); + } + return(nsource); + +} + + +/* function: SelectConnNodeSource() + * -------------------------------- + * Select source from among set of connected nodes specified by + * starting node. Return NULL if the start node is masked or already + * part of another connected set, or if the connected set is too + * small. + */ +static +nodeT *SelectConnNodeSource(nodeT **nodes, float **mag, + nodeT *ground, long ngroundarcs, + long nrow, long ncol, + paramT *params, nodeT *start, long *nconnectedptr){ + + long nconnected; + nodeT *source; + + + /* if start node is not eligible, just return NULL */ + if(start->group==MASKED || start->group==ONTREE){ + return(NULL); + } + + /* find all nodes for this set of connected pixels and mark them on tree */ + nconnected=ScanRegion(start,nodes,mag,ground,ngroundarcs,nrow,ncol,ONTREE); - /* return source */ + /* see if number of nodes in this connected set is big enough */ + if(nconnected>params->nconnnodemin){ + + /* set source to first node in chain */ + /* this ensures that the soruce is the ground node or on the edge */ + /* of the connected region, which tends to be faster */ + source = start; + + }else{ + source=NULL; + } + + /* set number of connected nodes and return source */ + if(nconnectedptr!=NULL){ + (*nconnectedptr)=nconnected; + } return(source); } +/* function: ScanRegion() + * ---------------------- + * Find all connected grid nodes of region, defined by reachability without + * crossing non-region arcs, and set group according to desired + * behavior defined by groupsetting, which should be either ONTREE for + * call from SelectConnNodeSourcre(), MASKED for a call from + * InitBoundary(), or 0 for a call from CleanUpBoundaryNodes(). Return + * number of connected nodes. + */ +static +long ScanRegion(nodeT *start, nodeT **nodes, float **mag, + nodeT *ground, long ngroundarcs, + long nrow, long ncol, int groupsetting){ + + nodeT *node1, *node2, *end; + long arcrow, arccol, arcdir, arcnum, upperarcnum, nconnected; + nodesuppT **nodesupp; + boundaryT *boundary; + + + /* set up */ + nconnected=0; + end=start; + nodesupp=NULL; + boundary=NULL; + node1=start; + node1->group=INBUCKET; + + /* loop to search for connected nodes */ + while(node1!=NULL){ + + /* loop over neighbors of current node */ + arcnum=GetArcNumLims(node1->row,&upperarcnum,ngroundarcs,boundary); + while(arcnumgroup==BOUNDARYPTR){ + node2->group=0; + } + + /* see if neighbor is in region */ + if(IsRegionArc(mag,arcrow,arccol,nrow,ncol)){ + + /* if neighbor is in region and not yet in list to be scanned, add it */ + if(node2->group!=ONTREE && node2->group!=INBUCKET){ + node2->group=INBUCKET; + end->next=node2; + node2->next=NULL; + end=node2; + } + } + } + + /* mark this node visited */ + node1->group=ONTREE; + + /* make sure level is initialized */ + if(groupsetting==ONTREE){ + node1->level=0; + } + + /* count this node */ + nconnected++; + + /* move to next node in list */ + node1=node1->next; + + } + + /* for each node in region, scan neighbors to mask or unmask unreachable */ + /* nodes that may be in other regions and therefore not yet masked */ + if(groupsetting!=ONTREE){ + + /* loop over nodes in region */ + node1=start; + while(node1!=NULL){ + + /* loop over neighbors of current node */ + arcnum=GetArcNumLims(node1->row,&upperarcnum,ngroundarcs,boundary); + while(arcnumgroup!=ONTREE){ + + /* set mask status according to desired behavior */ + if(groupsetting==MASKED){ + node2->group=MASKED; + }else if(groupsetting==0){ + if(node2->row==GROUNDROW){ + node2->group=GroundMaskStatus(nrow,ncol,mag); + }else{ + node2->group=GridNodeMaskStatus(node2->row,node2->col,mag); + } + } + } + } + + /* move to next node */ + node1=node1->next; + + } + + /* reset groups of all nodes within region */ + node1=start; + while(node1!=NULL){ + node1->group=0; + node1=node1->next; + } + } + + /* return number of connected nodes */ + return(nconnected); + +} + + /* function: GetCost() * ------------------- * Returns incremental flow cost for current flow increment dflow from * lookup array. */ +static short GetCost(incrcostT **incrcosts, long arcrow, long arccol, - long arcdir){ + long arcdir){ /* look up cost and return it for the appropriate arc direction */ /* we may want add a check here for clipped incremental costs */ @@ -1819,14 +3430,14 @@ short GetCost(incrcostT **incrcosts, long arcrow, long arccol, * Updates the incremental cost for an arc. */ long ReCalcCost(void **costs, incrcostT **incrcosts, long flow, - long arcrow, long arccol, long nflow, long nrow, - paramT *params){ + long arcrow, long arccol, long nflow, long nrow, + paramT *params){ long poscost, negcost, iclipped; /* calculate new positive and negative nflow costs, as long ints */ CalcCost(costs,flow,arcrow,arccol,nflow,nrow,params, - &poscost,&negcost); + &poscost,&negcost); /* clip costs to short int */ iclipped=0; @@ -1863,9 +3474,9 @@ long ReCalcCost(void **costs, incrcostT **incrcosts, long flow, * Calculates the costs for positive and negative dflow flow increment * if there is zero flow on the arc. */ -void SetupIncrFlowCosts(void **costs, incrcostT **incrcosts, short **flows, - long nflow, long nrow, long narcrow, - short *narcsperrow, paramT *params){ +int SetupIncrFlowCosts(void **costs, incrcostT **incrcosts, short **flows, + long nflow, long nrow, long narcrow, + int *narcsperrow, paramT *params){ long arcrow, arccol, iclipped, narcs; char pl[2]; @@ -1880,7 +3491,7 @@ void SetupIncrFlowCosts(void **costs, incrcostT **incrcosts, short **flows, /* calculate new positive and negative nflow costs, as long ints */ iclipped+=ReCalcCost(costs,incrcosts,flows[arcrow][arccol], - arcrow,arccol,nflow,nrow,params); + arcrow,arccol,nflow,nrow,params); } } @@ -1891,9 +3502,14 @@ void SetupIncrFlowCosts(void **costs, incrcostT **incrcosts, short **flows, }else{ strcpy(pl,""); } + fflush(NULL); fprintf(sp0,"%ld incremental cost%s clipped to avoid overflow (%.3f%%)\n", - iclipped,pl,((double )iclipped)/(2*narcs)); + iclipped,pl,((double )iclipped)/(2*narcs)); } + + /* done */ + return(0); + } @@ -1904,7 +3520,7 @@ void SetupIncrFlowCosts(void **costs, incrcostT **incrcosts, short **flows, * ncol=0 for nongrid mode (secondary network). */ totalcostT EvaluateTotalCost(void **costs, short **flows, long nrow, long ncol, - short *narcsperrow,paramT *params){ + int *narcsperrow,paramT *params){ totalcostT rowcost, totalcost; long row, col, maxrow, maxcol; @@ -1920,9 +3536,9 @@ totalcostT EvaluateTotalCost(void **costs, short **flows, long nrow, long ncol, rowcost=0; if(ncol){ if(rowmaxcost - && !((row==nrow-1 || 2*nrow-2) && (col==0 || col==ncol-2))){ - maxcost=mstcosts[row][col]; + && !((row==nrow-1 || 2*nrow-2) && (col==0 || col==ncol-2))){ + maxcost=mstcosts[row][col]; } } } @@ -1979,17 +3599,17 @@ void MSTInitFlows(float **wrappedphase, short ***flowsptr, bkts->maxind=bkts->size-1; bkts->bucket=bkts->bucketbase; arcstatus=(signed char **)Get2DRowColMem(nrow,ncol,sizeof(signed char *), - sizeof(signed char)); + sizeof(signed char)); /* calculate phase residues (integer numbers of cycles) */ fprintf(sp1,"Initializing flows with MST algorithm\n"); residue=(signed char **)Get2DMem(nrow-1,ncol-1,sizeof(signed char *), - sizeof(signed char)); + sizeof(signed char)); CycleResidue(wrappedphase,residue,nrow,ncol); /* get memory for flow arrays */ (*flowsptr)=(short **)Get2DRowColZeroMem(nrow,ncol, - sizeof(short *),sizeof(short)); + sizeof(short *),sizeof(short)); flows=*flowsptr; /* loop until no flows exceed the maximum flow */ @@ -2000,9 +3620,9 @@ void MSTInitFlows(float **wrappedphase, short ***flowsptr, source=NULL; for(row=0;rowbucketbase); - return; + return(0); } @@ -2051,9 +3671,10 @@ void MSTInitFlows(float **wrappedphase, short ***flowsptr, * Dijkstra implementation and some associated functions adapted from SPLIB * shortest path codes written by Cherkassky, Goldberg, and Radzik. */ +static void SolveMST(nodeT **nodes, nodeT *source, nodeT *ground, - bucketT *bkts, short **mstcosts, signed char **residue, - signed char **arcstatus, long nrow, long ncol){ + bucketT *bkts, short **mstcosts, signed char **residue, + signed char **arcstatus, long nrow, long ncol){ nodeT *from, *to, *pathfrom, *pathto; nodesuppT **nodesupp; @@ -2106,26 +3727,27 @@ void SolveMST(nodeT **nodes, nodeT *source, nodeT *ground, /* go back and make arcstatus -1 along path */ while(TRUE){ - /* give to node zero distance label */ - pathto->outcost=0; - - /* get arc indices for arc between pathfrom and pathto */ - GetArc(pathfrom,pathto,&arcrow,&arccol,&arcdir,nrow,ncol,nodesupp); - - /* set arc status to -1 to mark arc on tree */ - arcstatus[arcrow][arccol]=-1; - - /* stop when we get to a residue */ - pathfromrow=pathfrom->row; - pathfromcol=pathfrom->col; - if((pathfromrow!=GROUNDROW && residue[pathfromrow][pathfromcol]) - || (pathfromrow==GROUNDROW && groundcharge)){ - break; - } - - /* move up to previous node pair in path */ - pathto=pathfrom; - pathfrom=pathfrom->pred; + /* give to node zero distance label */ + pathto->outcost=0; + + /* get arc indices for arc between pathfrom and pathto */ + GetArc(pathfrom,pathto,&arcrow,&arccol,&arcdir,nrow,ncol, + nodes,nodesupp); + + /* set arc status to -1 to mark arc on tree */ + arcstatus[arcrow][arccol]=-1; + + /* stop when we get to a residue */ + pathfromrow=pathfrom->row; + pathfromcol=pathfrom->col; + if((pathfromrow!=GROUNDROW && residue[pathfromrow][pathfromcol]) + || (pathfromrow==GROUNDROW && groundcharge)){ + break; + } + + /* move up to previous node pair in path */ + pathto=pathfrom; + pathfrom=pathfrom->pred; } /* end while loop marking costs on path */ @@ -2135,54 +3757,48 @@ void SolveMST(nodeT **nodes, nodeT *source, nodeT *ground, fromdist=from->outcost; /* scan from's neighbors */ - if(fromrow!=GROUNDROW){ - arcnum=-5; - upperarcnum=-1; - }else{ - arcnum=-1; - upperarcnum=ngroundarcs-1; - } + arcnum=GetArcNumLims(fromrow,&upperarcnum,ngroundarcs,NULL); while(arcnumrow; col=to->col; /* get cost of arc to new node (if arc on tree, cost is 0) */ if(arcstatus[arcrow][arccol]<0){ - arcdist=0; + arcdist=0; }else if((arcdist=mstcosts[arcrow][arccol])==LARGESHORT){ - arcdist=VERYFAR; + arcdist=VERYFAR; } /* compare distance of new nodes to temp labels */ if((newdist=fromdist+arcdist)<(to->outcost)){ - /* if to node is already in a bucket, remove it */ - if(to->group==INBUCKET){ - if(to->outcostmaxind){ - BucketRemove(to,to->outcost,bkts); - }else{ - BucketRemove(to,bkts->maxind,bkts); - } - } - - /* update to node */ - to->outcost=newdist; - to->pred=from; - - /* insert to node into appropriate bucket */ - if(newdistmaxind){ - BucketInsert(to,newdist,bkts); - if(newdistcurr){ - bkts->curr=newdist; - } - }else{ - BucketInsert(to,bkts->maxind,bkts); - } - + /* if to node is already in a bucket, remove it */ + if(to->group==INBUCKET){ + if(to->outcostmaxind){ + BucketRemove(to,to->outcost,bkts); + }else{ + BucketRemove(to,bkts->maxind,bkts); + } + } + + /* update to node */ + to->outcost=newdist; + to->pred=from; + + /* insert to node into appropriate bucket */ + if(newdistmaxind){ + BucketInsert(to,newdist,bkts); + if(newdistcurr){ + bkts->curr=newdist; + } + }else{ + BucketInsert(to,bkts->maxind,bkts); + } + } /* end if newdist < old dist */ } /* end loop over outgoing arcs */ @@ -2199,9 +3815,10 @@ void SolveMST(nodeT **nodes, nodeT *source, nodeT *ground, * would also use much more stack memory. This method is equivalent to * walking the tree, so it should be nore more than a factor of 2 slower. */ +static long DischargeTree(nodeT *source, short **mstcosts, short **flows, - signed char **residue, signed char **arcstatus, - nodeT **nodes, nodeT *ground, long nrow, long ncol){ + signed char **residue, signed char **arcstatus, + nodeT **nodes, nodeT *ground, long nrow, long ncol){ long row, col, todir, arcrow, arccol, arcdir; long arcnum, upperarcnum, ngroundarcs; @@ -2210,17 +3827,18 @@ long DischargeTree(nodeT *source, short **mstcosts, short **flows, /* set up */ - /* use group member of node structure to temporarily store charge */ + /* use outcost member of node structure to temporarily store charge */ nextnode=source; - ground->group=0; + ground->outcost=0; for(row=0;rowgroup-=residue[row][col]; + nodes[row][col].outcost=residue[row][col]; + ground->outcost-=residue[row][col]; } } ngroundarcs=2*(nrow+ncol-2)-4; nodesupp=NULL; + todir=0; /* keep looping unitl we've walked the entire tree */ while(TRUE){ @@ -2229,36 +3847,30 @@ long DischargeTree(nodeT *source, short **mstcosts, short **flows, nextnode=NULL; /* loop over outgoing arcs from this node */ - if(from->row!=GROUNDROW){ - arcnum=-5; - upperarcnum=-1; - }else{ - arcnum=-1; - upperarcnum=ngroundarcs-1; - } + arcnum=GetArcNumLims(from->row,&upperarcnum,ngroundarcs,NULL); while(arcnumgroup; - nextnode->group+=from->group; - from->group=0; + flows[row][col]+=todir*from->outcost; + nextnode->outcost+=from->outcost; + from->outcost=0; } } /* finish up */ - return(from->group); + return(from->outcost); } /* end of DischargeTree() */ @@ -2292,9 +3904,10 @@ long DischargeTree(nodeT *source, short **mstcosts, short **flows, * whichever is greater. Clipped flow arcs get costs of passed variable * maxcost. Residues should have been set to zero by DischargeTree(). */ +static signed char ClipFlow(signed char **residue, short **flows, - short **mstcosts, long nrow, long ncol, - long maxflow){ + short **mstcosts, long nrow, long ncol, + long maxflow){ long row, col, cliplimit, maxcol, excess, tempcharge, sign; long mostflow, maxcost; @@ -2325,7 +3938,7 @@ signed char ClipFlow(signed char **residue, short **flows, } for(col=0;colmaxcost && mstcosts[row][col]=LARGESHORT){ + fflush(NULL); fprintf(sp0,"WARNING: escaping ClipFlow loop to prevent cost overflow\n"); return(TRUE); } @@ -2346,50 +3960,54 @@ signed char ClipFlow(signed char **residue, short **flows, } for(col=0;colcliplimit){ - if(flows[row][col]>0){ - sign=1; - excess=flows[row][col]-cliplimit; - }else{ - sign=-1; - excess=flows[row][col]+cliplimit; - } - if(rowMAXRES || tempchargeMAXRES){ - fprintf(sp0,"Overflow of residue data type\nAbort\n"); - exit(ABNORMAL_EXIT); - } - residue[row][col]=tempcharge; - } - }else{ - if(row!=nrow-1){ - tempcharge=residue[row-nrow][col]+excess; - if(tempcharge>MAXRES || tempchargeMAXRES){ - fprintf(sp0,"Overflow of residue data type\nAbort\n"); - exit(ABNORMAL_EXIT); - } - residue[row-nrow+1][col]=tempcharge; - } - } - flows[row][col]=sign*cliplimit; - mstcosts[row][col]=maxcost; + if(flows[row][col]>0){ + sign=1; + excess=flows[row][col]-cliplimit; + }else{ + sign=-1; + excess=flows[row][col]+cliplimit; + } + if(rowMAXRES || tempchargeMAXRES){ + fflush(NULL); + fprintf(sp0,"Overflow of residue data type\nAbort\n"); + exit(ABNORMAL_EXIT); + } + residue[row][col]=tempcharge; + } + }else{ + if(row!=nrow-1){ + tempcharge=residue[row-nrow][col]+excess; + if(tempcharge>MAXRES || tempchargeMAXRES){ + fflush(NULL); + fprintf(sp0,"Overflow of residue data type\nAbort\n"); + exit(ABNORMAL_EXIT); + } + residue[row-nrow+1][col]=tempcharge; + } + } + flows[row][col]=sign*cliplimit; + mstcosts[row][col]=maxcost; } } } @@ -2406,21 +4024,25 @@ signed char ClipFlow(signed char **residue, short **flows, * Initializes the flow on a the network using minimum cost flow * algorithm. */ -void MCFInitFlows(float **wrappedphase, short ***flowsptr, short **mstcosts, - long nrow, long ncol, long cs2scalefactor){ +int MCFInitFlows(float **wrappedphase, short ***flowsptr, short **mstcosts, + long nrow, long ncol, long cs2scalefactor){ + +#ifndef NO_CS2 signed char **residue; -#ifndef NO_CS2 /* calculate phase residues (integer numbers of cycles) */ fprintf(sp1,"Initializing flows with MCF algorithm\n"); residue=(signed char **)Get2DMem(nrow-1,ncol-1,sizeof(signed char *), - sizeof(signed char)); + sizeof(signed char)); CycleResidue(wrappedphase,residue,nrow,ncol); /* run the solver (memory freed within solver) */ SolveCS2(residue,mstcosts,nrow,ncol,cs2scalefactor,flowsptr); #endif + + /* done */ + return(0); } diff --git a/contrib/Snaphu/src/snaphu_tile.c b/contrib/Snaphu/src/snaphu_tile.c index 096040f9..a88fa7fa 100644 --- a/contrib/Snaphu/src/snaphu_tile.c +++ b/contrib/Snaphu/src/snaphu_tile.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -28,13 +29,146 @@ +/* static (local) function prototypes */ +static +long ThickenCosts(incrcostT **incrcosts, long nrow, long ncol); +static +nodeT *RegionsNeighborNode(nodeT *node1, long *arcnumptr, nodeT **nodes, + long *arcrowptr, long *arccolptr, + long nrow, long ncol); +static +int ClearBuckets(bucketT *bkts); +static +int MergeRegions(nodeT **nodes, nodeT *source, long *regionsizes, + long closestregion, long nrow, long ncol); +static +int RenumberRegion(nodeT **nodes, nodeT *source, long newnum, + long nrow, long ncol); +static +int ReadNextRegion(long tilerow, long tilecol, long nlines, long linelen, + outfileT *outfiles, paramT *params, + short ***nextregionsptr, float ***nextunwphaseptr, + void ***nextcostsptr, + long *nextnrowptr, long *nextncolptr); +static +int SetTileReadParams(tileparamT *tileparams, long nexttilenlines, + long nexttilelinelen, long tilerow, long tilecol, + long nlines, long linelen, paramT *params); +static +int ReadEdgesAboveAndBelow(long tilerow, long tilecol, long nlines, + long linelen, paramT *params, outfileT *outfiles, + short *regionsabove, short *regionsbelow, + float *unwphaseabove, float *unwphasebelow, + void *costsabove, void *costsbelow); +static +int TraceRegions(short **regions, short **nextregions, short **lastregions, + short *regionsabove, short *regionsbelow, float **unwphase, + float **nextunwphase, float **lastunwphase, + float *unwphaseabove, float *unwphasebelow, void **costs, + void **nextcosts, void **lastcosts, void *costsabove, + void *costsbelow, long prevnrow, long prevncol, long tilerow, + long tilecol, long nrow, long ncol, nodeT **scndrynodes, + nodesuppT **nodesupp, scndryarcT **scndryarcs, + long ***scndrycosts, int *nscndrynodes, + int *nscndryarcs, long *totarclens, short **bulkoffsets, + paramT *params); +static +long FindNumPathsOut(nodeT *from, paramT *params, long tilerow, long tilecol, + long nnrow, long nncol, short **regions, + short **nextregions, short **lastregions, + short *regionsabove, short *regionsbelow, long prevncol); +static +int RegionTraceCheckNeighbors(nodeT *from, nodeT **nextnodeptr, + nodeT **primarynodes, short **regions, + short **nextregions, short **lastregions, + short *regionsabove, short *regionsbelow, + long tilerow, long tilecol, long nnrow, + long nncol, nodeT **scndrynodes, + nodesuppT **nodesupp, scndryarcT **scndryarcs, + long *nnewnodesptr, long *nnewarcsptr, + long flowmax, long nrow, long ncol, + long prevnrow, long prevncol, paramT *params, + void **costs, void **rightedgecosts, + void **loweredgecosts, void **leftedgecosts, + void **upperedgecosts, short **flows, + short **rightedgeflows, short **loweredgeflows, + short **leftedgeflows, short **upperedgeflows, + long ***scndrycosts, + nodeT ***updatednontilenodesptr, + long *nupdatednontilenodesptr, + long *updatednontilenodesizeptr, + short **inontilenodeoutarcptr, + long *totarclenptr); +static +int SetUpperEdge(long ncol, long tilerow, long tilecol, void **voidcosts, + void *voidcostsabove, float **unwphase, + float *unwphaseabove, void **voidupperedgecosts, + short **upperedgeflows, paramT *params, short **bulkoffsets); +static +int SetLowerEdge(long nrow, long ncol, long tilerow, long tilecol, + void **voidcosts, void *voidcostsbelow, + float **unwphase, float *unwphasebelow, + void **voidloweredgecosts, short **loweredgeflows, + paramT *params, short **bulkoffsets); +static +int SetLeftEdge(long nrow, long prevncol, long tilerow, long tilecol, + void **voidcosts, void **voidlastcosts, float **unwphase, + float **lastunwphase, void **voidleftedgecosts, + short **leftedgeflows, paramT *params, short **bulkoffsets); +static +int SetRightEdge(long nrow, long ncol, long tilerow, long tilecol, + void **voidcosts, void **voidnextcosts, + float **unwphase, float **nextunwphase, + void **voidrightedgecosts, short **rightedgeflows, + paramT *params, short **bulkoffsets); +static +short AvgSigSq(short sigsq1, short sigsq2); +static +int TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, + nodesuppT **nodesupp, scndryarcT **scndryarcs, + long ***scndrycosts, long *nnewnodesptr, + long *nnewarcsptr, long tilerow, long tilecol, + long flowmax, long nrow, long ncol, + long prevnrow, long prevncol, paramT *params, + void **tilecosts, void **rightedgecosts, + void **loweredgecosts, void **leftedgecosts, + void **upperedgecosts, short **tileflows, + short **rightedgeflows, short **loweredgeflows, + short **leftedgeflows, short **upperedgeflows, + nodeT ***updatednontilenodesptr, + long *nupdatednontilenodesptr, + long *updatednontilenodesizeptr, + short **inontilenodeoutarcptr, long *totarclenptr); +static +nodeT *FindScndryNode(nodeT **scndrynodes, nodesuppT **nodesupp, + long tilenum, long primaryrow, long primarycol); +static +int IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes, + nodesuppT **nodesupp, scndryarcT **scndryarcs, + int *nscndryarcs, short **scndryflows, + short **bulkoffsets, outfileT *outfiles, + paramT *params); +static +int ParseSecondaryFlows(long tilenum, int *nscndryarcs, short **tileflows, + short **regions, short **scndryflows, + nodesuppT **nodesupp, scndryarcT **scndryarcs, + long nrow, long ncol, long ntilerow, long ntilecol, + paramT *params); +static +int AssembleTileConnComps(long linelen, long nlines, + outfileT *outfiles, paramT *params); +static +int ConnCompSizeNPixCompare(const void *ptr1, const void *ptr2); + + + /* function: SetupTile() * --------------------- * Sets up tile parameters and output file names for the current tile. */ -void SetupTile(long nlines, long linelen, paramT *params, - tileparamT *tileparams, outfileT *outfiles, - outfileT *tileoutfiles, long tilerow, long tilecol){ +int SetupTile(long nlines, long linelen, paramT *params, + tileparamT *tileparams, outfileT *outfiles, + outfileT *tileoutfiles, long tilerow, long tilecol){ long ni, nj; char tempstring[MAXTMPSTRLEN], path[MAXSTRLEN], basename[MAXSTRLEN]; @@ -43,9 +177,9 @@ void SetupTile(long nlines, long linelen, paramT *params, /* set parameters for current tile */ ni=ceil((nlines+(params->ntilerow-1)*params->rowovrlp) - /(double )params->ntilerow); + /(double )params->ntilerow); nj=ceil((linelen+(params->ntilecol-1)*params->colovrlp) - /(double )params->ntilecol); + /(double )params->ntilecol); tileparams->firstrow=tilerow*(ni-params->rowovrlp); tileparams->firstcol=tilecol*(nj-params->colovrlp); if(tilerow==params->ntilerow-1){ @@ -59,16 +193,23 @@ void SetupTile(long nlines, long linelen, paramT *params, tileparams->ncol=nj; } + /* error checking on tile size */ + if(params->minregionsize > (tileparams->nrow)*(tileparams->ncol)){ + fflush(NULL); + fprintf(sp0,"Minimum region size cannot exceed tile size\nAbort\n"); + exit(ABNORMAL_EXIT); + } + /* set output files */ tiledir=params->tiledir; ParseFilename(outfiles->outfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->outfile,tempstring,MAXSTRLEN); if(strlen(outfiles->initfile)){ ParseFilename(outfiles->initfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->initfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->initfile,"",MAXSTRLEN); @@ -76,7 +217,7 @@ void SetupTile(long nlines, long linelen, paramT *params, if(strlen(outfiles->flowfile)){ ParseFilename(outfiles->flowfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->flowfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->flowfile,"",MAXSTRLEN); @@ -84,7 +225,7 @@ void SetupTile(long nlines, long linelen, paramT *params, if(strlen(outfiles->eifile)){ ParseFilename(outfiles->eifile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->eifile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->eifile,"",MAXSTRLEN); @@ -92,7 +233,7 @@ void SetupTile(long nlines, long linelen, paramT *params, if(strlen(outfiles->rowcostfile)){ ParseFilename(outfiles->rowcostfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->rowcostfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->rowcostfile,"",MAXSTRLEN); @@ -100,7 +241,7 @@ void SetupTile(long nlines, long linelen, paramT *params, if(strlen(outfiles->colcostfile)){ ParseFilename(outfiles->colcostfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->colcostfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->colcostfile,"",MAXSTRLEN); @@ -108,7 +249,7 @@ void SetupTile(long nlines, long linelen, paramT *params, if(strlen(outfiles->mstrowcostfile)){ ParseFilename(outfiles->mstrowcostfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->mstrowcostfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->mstrowcostfile,"",MAXSTRLEN); @@ -116,7 +257,7 @@ void SetupTile(long nlines, long linelen, paramT *params, if(strlen(outfiles->mstcolcostfile)){ ParseFilename(outfiles->mstcolcostfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->mstcolcostfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->mstcolcostfile,"",MAXSTRLEN); @@ -124,7 +265,7 @@ void SetupTile(long nlines, long linelen, paramT *params, if(strlen(outfiles->mstcostsfile)){ ParseFilename(outfiles->mstcostsfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->mstcostsfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->mstcostsfile,"",MAXSTRLEN); @@ -132,7 +273,7 @@ void SetupTile(long nlines, long linelen, paramT *params, if(strlen(outfiles->corrdumpfile)){ ParseFilename(outfiles->corrdumpfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->corrdumpfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->corrdumpfile,"",MAXSTRLEN); @@ -140,24 +281,89 @@ void SetupTile(long nlines, long linelen, paramT *params, if(strlen(outfiles->rawcorrdumpfile)){ ParseFilename(outfiles->rawcorrdumpfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->rawcorrdumpfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->rawcorrdumpfile,"",MAXSTRLEN); } + if(strlen(outfiles->conncompfile)){ + ParseFilename(outfiles->conncompfile,path,basename); + sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + StrNCopy(tileoutfiles->conncompfile,tempstring,MAXSTRLEN); + }else{ + StrNCopy(tileoutfiles->conncompfile,"",MAXSTRLEN); + } if(strlen(outfiles->costoutfile)){ ParseFilename(outfiles->costoutfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", - tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->costoutfile,tempstring,MAXSTRLEN); }else{ sprintf(tempstring,"%s/%s%s%ld_%ld.%ld", - tiledir,TMPTILEROOT,TMPTILECOSTSUFFIX,tilerow,tilecol, - tileparams->ncol); + tiledir,TMPTILEROOT,TMPTILECOSTSUFFIX,tilerow,tilecol, + tileparams->ncol); StrNCopy(tileoutfiles->costoutfile,tempstring,MAXSTRLEN); } + if(strlen(outfiles->logfile)){ + ParseFilename(outfiles->logfile,path,basename); + sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", + tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); + StrNCopy(tileoutfiles->logfile,tempstring,MAXSTRLEN); + }else{ + StrNCopy(tileoutfiles->logfile,"",MAXSTRLEN); + } tileoutfiles->outfileformat=TMPTILEOUTFORMAT; + /* done */ + return(0); + +} + + +/* function: SetUpDoTileMask() + * --------------------------- + * Read the tile mask if a file name is specified in the infiles structure, + * otherwise return an array of all ones. + */ +signed char **SetUpDoTileMask(infileT *infiles, long ntilerow, long ntilecol){ + + long row, col; + signed char **dotilemask; + tileparamT readparams[1]; + + + /* initialize stack structures to zero for good measure */ + memset(readparams,0,sizeof(tileparamT)); + + /* get memory */ + dotilemask=(signed char **)Get2DMem(ntilerow,ntilecol,sizeof(signed char *), + sizeof(signed char)); + + /* see if a file name was passed */ + if(strlen(infiles->dotilemaskfile)){ + + /* read the input file */ + readparams->nrow=ntilerow; + readparams->ncol=ntilecol; + readparams->firstrow=0; + readparams->firstcol=0; + Read2DArray((void ***)&dotilemask,infiles->dotilemaskfile,ntilecol, + ntilerow,readparams,sizeof(signed char *),sizeof(signed char)); + + }else{ + + /* set array to be all ones */ + for(row=0;rowminregionsize; costthresh=params->tilecostthresh; - if(minsize>nrow*ncol){ - fprintf(sp0,"Minimum region size cannot exceed tile size\nAbort\n"); - exit(ABNORMAL_EXIT); + closestregion=0; + + /* store current values of CalcCost and EvalCost function pointers */ + tempcalccostfnptr=CalcCost; + tempevalcostfnptr=EvalCost; + + /* reread statistical costs from stored file if costs array is for Lp mode */ + if(params->p >= 0){ + if(params->costmode==TOPO){ + costtypesize=sizeof(costT); + CalcCost=CalcCostTopo; + EvalCost=EvalCostTopo; + }else if(params->costmode==DEFO){ + costtypesize=sizeof(costT); + CalcCost=CalcCostDefo; + EvalCost=EvalCostDefo; + }else if(params->costmode==SMOOTH){ + costtypesize=sizeof(smoothcostT); + CalcCost=CalcCostSmooth; + EvalCost=EvalCostSmooth; + }else{ + fflush(NULL); + fprintf(sp0,"Illegal cost mode in GrowRegions(). This is a bug.\n"); + exit(ABNORMAL_EXIT); + } + temptileparams->firstrow=0; + temptileparams->firstcol=0; + temptileparams->nrow=nrow; + temptileparams->ncol=ncol; + growregionscosts=NULL; + Read2DRowColFile((void ***)&growregionscosts,outfiles->costoutfile, + ncol,nrow,temptileparams,costtypesize); + }else{ + growregionscosts=costs; } /* loop over all arcs */ @@ -200,20 +448,20 @@ void GrowRegions(void **costs, short **flows, long nrow, long ncol, for(arccol=0;arccolnext=NULL; - source->prev=NULL; - source->group=INBUCKET; - source->outcost=0; - bkts->bucket[0]=source; - bkts->curr=0; - lastfromdist=0; - - /* increment the region counter */ - if(++regioncounter>=regionsizeslen){ - regionsizeslen+=INITARRSIZE; - regionsizes=(long *)ReAlloc(regionsizes, - regionsizeslen*sizeof(long)); - } - thisregionsize=®ionsizes[regioncounter]; - - /* set up */ - (*thisregionsize)=0; - closestregiondist=VERYFAR; - - /* loop to grow region */ - while(TRUE){ - - /* set from node to closest node in circular bucket structure */ - from=ClosestNode(bkts); - - /* break if we can't grow any more and the region is big enough */ - if(from==NULL){ - if(*thisregionsize>=minsize){ - - /* no more nonregion nodes, and current region is big enough */ - break; - - }else{ - - /* no more nonregion nodes, but current region still too small */ - /* merge with another region */ - MergeRegions(nodes,source,regionsizes,closestregion,nrow,ncol); - regioncounter--; - break; - - } - }else{ - fromdist=from->outcost; - if(fromdist>lastfromdist){ - if(regionsizes[regioncounter]>=minsize){ - - /* region grown to all nodes within mincost, is big enough */ - break; - - } - if(fromdist>closestregiondist){ - - /* another region closer than new node, so merge regions */ - MergeRegions(nodes,source,regionsizes,closestregion,nrow,ncol); - regioncounter--; - break; - } - } - } - - /* make from node a part of the current region */ - from->incost=regioncounter; - (*thisregionsize)++; - lastfromdist=fromdist; - - /* scan from's neighbors */ - arcnum=0; - while((to=RegionsNeighborNode(from,&arcnum,nodes, - &arcrow,&arccol,nrow,ncol))!=NULL){ - - /* get cost of arc to the to node */ - arcdist=incrcosts[arcrow][arccol].negcost; - - /* see if to node is already in another region */ - if(to->incost>=0){ - - /* keep track of which neighboring region is closest */ - if(to->incost!=regioncounter && arcdistincost; - } - - }else{ - - /* to node is not in another region */ - /* compare distance of new nodes to temp labels */ - if(arcdist<(to->outcost)){ - - /* if to node is already in a (circular) bucket, remove it */ - if(to->group==INBUCKET){ - BucketRemove(to,to->outcost,bkts); - } + /* clear the buckets */ + ClearBuckets(bkts); + + /* make node source and put it in the first bucket */ + source=&nodes[row][col]; + source->next=NULL; + source->prev=NULL; + source->group=INBUCKET; + source->outcost=0; + bkts->bucket[0]=source; + bkts->curr=0; + lastfromdist=0; + + /* increment the region counter */ + if(++regioncounter>=regionsizeslen){ + regionsizeslen+=INITARRSIZE; + regionsizes=(long *)ReAlloc(regionsizes, + regionsizeslen*sizeof(long)); + } + thisregionsize=®ionsizes[regioncounter]; + + /* set up */ + (*thisregionsize)=0; + closestregiondist=VERYFAR; + + /* loop to grow region */ + while(TRUE){ + + /* set from node to closest node in circular bucket structure */ + from=ClosestNode(bkts); + + /* break if we can't grow any more and the region is big enough */ + if(from==NULL){ + if(*thisregionsize>=minsize){ + + /* no more nonregion nodes, and current region is big enough */ + break; + + }else{ + + /* no more nonregion nodes, but current region still too small */ + /* merge with another region */ + MergeRegions(nodes,source,regionsizes,closestregion,nrow,ncol); + regioncounter--; + break; + + } + }else{ + fromdist=from->outcost; + if(fromdist>lastfromdist){ + if(regionsizes[regioncounter]>=minsize){ + + /* region grown to all nodes within mincost, is big enough */ + break; + + } + if(fromdist>closestregiondist){ + + /* another region closer than new node, so merge regions */ + MergeRegions(nodes,source,regionsizes,closestregion,nrow,ncol); + regioncounter--; + break; + } + } + } + + /* make from node a part of the current region */ + from->incost=regioncounter; + (*thisregionsize)++; + lastfromdist=fromdist; + + /* scan from's neighbors */ + arcnum=0; + while((to=RegionsNeighborNode(from,&arcnum,nodes, + &arcrow,&arccol,nrow,ncol))!=NULL){ + + /* get cost of arc to the to node */ + arcdist=incrcosts[arcrow][arccol].negcost; + + /* see if to node is already in another region */ + if(to->incost>=0){ + + /* keep track of which neighboring region is closest */ + if(to->incost!=regioncounter && arcdistincost; + } + + }else{ + + /* to node is not in another region */ + /* compare distance of new nodes to temp labels */ + if(arcdist<(to->outcost)){ + + /* if to node is already in a (circular) bucket, remove it */ + if(to->group==INBUCKET){ + BucketRemove(to,to->outcost,bkts); + } - /* update to node */ - to->outcost=arcdist; - to->pred=from; - - /* insert to node into appropriate (circular) bucket */ - BucketInsert(to,arcdist,bkts); - if(arcdistcurr){ - bkts->curr=arcdist; - } - } - } - } - } + /* update to node */ + to->outcost=arcdist; + to->pred=from; + + /* insert to node into appropriate (circular) bucket */ + BucketInsert(to,arcdist,bkts); + if(arcdistcurr){ + bkts->curr=arcdist; + } + } + } + } + } } } } @@ -376,55 +624,79 @@ void GrowRegions(void **costs, short **flows, long nrow, long ncol, regions=(short **)Get2DMem(nrow,ncol,sizeof(short *),sizeof(short)); for(row=0;rowLARGESHORT){ - fprintf(sp0, - "Number of regions in tile exceeds max allowed\nAbort\n"); - exit(ABNORMAL_EXIT); - } - regions[row][col]=nodes[row][col].incost; + if(nodes[row][col].incost>LARGESHORT){ + fflush(NULL); + fprintf(sp0, + "Number of regions in tile exceeds max allowed\nAbort\n"); + exit(ABNORMAL_EXIT); + } + regions[row][col]=nodes[row][col].incost; } } sprintf(regionfile,"%s%s",outfiles->outfile,REGIONSUFFIX); fprintf(sp2,"Writing region data to file %s\n",regionfile); Write2DArray((void **)regions,regionfile,nrow,ncol,sizeof(short)); + }else{ + regions=NULL; } + /* return CalcCost and EvalCost function pointers to initial values */ + CalcCost=tempcalccostfnptr; + EvalCost=tempevalcostfnptr; + /* free memory */ + if(params->p >= 0){ + Free2DArray((void **)growregionscosts,2*nrow-1); + } Free2DArray((void **)nodes,nrow); - Free2DArray((void **)regions,nrow); + if(regions!=NULL){ + Free2DArray((void **)regions,nrow); + } free(bkts->bucketbase); + /* done */ + return(0); + } -/* function: GrowConnCompMask() - * ---------------------------- +/* function: GrowConnCompsMask() + * ----------------------------- * Grows contiguous regions demarcated by arcs whose residual costs are * less than some threshold. Numbers the regions sequentially from 1. * Writes out byte file of connected component mask, with 0 for any pixels * not assigned to a component. */ -void GrowConnCompsMask(void **costs, short **flows, long nrow, long ncol, - incrcostT **incrcosts, outfileT *outfiles, - paramT *params){ +int GrowConnCompsMask(void **costs, short **flows, long nrow, long ncol, + incrcostT **incrcosts, outfileT *outfiles, + paramT *params){ long i, row, col, maxcol; long arcrow, arccol, arcnum; long regioncounter, *regionsizes, regionsizeslen, *thisregionsize; long *sortedregionsizes; long costthresh, minsize, maxncomps, ntied, newnum; + unsigned long outtypemax, outtypesize; nodeT **nodes; nodeT *source, *from, *to, *ground; - unsigned char **components; + unsigned char *ucharbuf; + unsigned int *uintbuf; + void *outbufptr; bucketT bkts[1]; + char realoutfile[MAXSTRLEN]; + FILE *conncompfp; + /* initialize stack structures to zero for good measure */ + memset(bkts,0,sizeof(bucketT)); + /* error checking */ fprintf(sp1,"Growing connected component mask\n"); minsize=params->minconncompfrac*nrow*ncol; maxncomps=params->maxncomps; costthresh=params->conncompthresh; if(minsize>nrow*ncol){ + fflush(NULL); fprintf(sp0,"Minimum region size cannot exceed tile size\nAbort\n"); exit(ABNORMAL_EXIT); } @@ -440,19 +712,19 @@ void GrowConnCompsMask(void **costs, short **flows, long nrow, long ncol, /* compute incremental costs of unit flows in either direction */ ReCalcCost(costs,incrcosts,flows[arcrow][arccol], - arcrow,arccol,1,nrow,params); + arcrow,arccol,1,nrow,params); /* store lesser of incremental costs in first field */ if(incrcosts[arcrow][arccol].negcostnext=NULL; - source->prev=NULL; - source->group=INBUCKET; - source->outcost=0; - bkts->bucket[0]=source; - bkts->curr=0; - - /* increment the region counter */ - if(++regioncounter>=regionsizeslen){ - regionsizeslen+=INITARRSIZE; - regionsizes=(long *)ReAlloc(regionsizes, - regionsizeslen*sizeof(long)); - } - thisregionsize=®ionsizes[regioncounter]; - - /* set up */ - (*thisregionsize)=0; - - /* loop to grow region */ - while(TRUE){ - - /* set from node to closest node in circular bucket structure */ - from=ClosestNode(bkts); - - /* break if we can't grow any more and the region is big enough */ - if(from==NULL){ - if(regionsizes[regioncounter]>=minsize){ - - /* no more nonregion nodes, and current region is big enough */ - break; - - }else{ - - /* no more nonregion nodes, but current region still too small */ - /* zero out the region */ - RenumberRegion(nodes,source,0,nrow,ncol); - regioncounter--; - break; - - } - } - - /* make from node a part of the current region */ - from->incost=regioncounter; - (*thisregionsize)++; - - /* scan from's neighbors */ - arcnum=0; - while((to=RegionsNeighborNode(from,&arcnum,nodes, - &arcrow,&arccol,nrow,ncol))!=NULL){ - - /* see if to can be reached */ - if(to->incost<0 && incrcosts[arcrow][arccol].negcost==0 - && to->group!=INBUCKET){ - - /* update to node */ - to->pred=from; - BucketInsert(to,0,bkts); - - } - } - } + /* clear the buckets */ + ClearBuckets(bkts); + + /* make node source and put it in the first bucket */ + source=&nodes[row][col]; + source->next=NULL; + source->prev=NULL; + source->group=INBUCKET; + source->outcost=0; + bkts->bucket[0]=source; + bkts->curr=0; + + /* increment the region counter */ + if(++regioncounter>=regionsizeslen){ + regionsizeslen+=INITARRSIZE; + regionsizes=(long *)ReAlloc(regionsizes, + regionsizeslen*sizeof(long)); + } + thisregionsize=®ionsizes[regioncounter]; + + /* set up */ + (*thisregionsize)=0; + + /* loop to grow region */ + while(TRUE){ + + /* set from node to closest node in circular bucket structure */ + from=ClosestNode(bkts); + + /* break if we can't grow any more and the region is big enough */ + if(from==NULL){ + if(regionsizes[regioncounter]>=minsize){ + + /* no more nonregion nodes, and current region is big enough */ + break; + + }else{ + + /* no more nonregion nodes, but current region still too small */ + /* zero out the region */ + RenumberRegion(nodes,source,0,nrow,ncol); + regioncounter--; + break; + + } + } + + /* make from node a part of the current region */ + from->incost=regioncounter; + (*thisregionsize)++; + + /* scan from's neighbors */ + arcnum=0; + while((to=RegionsNeighborNode(from,&arcnum,nodes, + &arcrow,&arccol,nrow,ncol))!=NULL){ + + /* see if to can be reached */ + if(to->incost<0 && incrcosts[arcrow][arccol].negcost==0 + && to->group!=INBUCKET){ + + /* update to node */ + to->pred=from; + BucketInsert(to,0,bkts); + + } + } + } } } } @@ -585,62 +857,95 @@ void GrowConnCompsMask(void **costs, short **flows, long nrow, long ncol, newnum=-1; for(row=0;row0){ - if(regionsizes[i]0)){ + i=nodes[row][col].incost; + if(i>0){ + if(regionsizes[i]0)){ - /* region too small, so zero it out */ - RenumberRegion(nodes,&(nodes[row][col]),0,nrow,ncol); + /* region too small, so zero it out */ + RenumberRegion(nodes,&(nodes[row][col]),0,nrow,ncol); - }else{ + }else{ - /* keep region, assign it new region number */ - /* temporarily assign negative of new number to avoid collisions */ - RenumberRegion(nodes,&(nodes[row][col]),newnum--,nrow,ncol); + /* keep region, assign it new region number */ + /* temporarily assign negative of new number to avoid collisions */ + RenumberRegion(nodes,&(nodes[row][col]),newnum--,nrow,ncol); - } - } + } + } } } /* flip temporary negative region numbers so they are positive */ for(row=0;rowconncompouttype==CONNCOMPOUTTYPEUCHAR){ + outtypemax=UCHAR_MAX; + outtypesize=(int )sizeof(unsigned char); + outbufptr=(void *)ucharbuf; + }else if(params->conncompouttype==CONNCOMPOUTTYPEUINT){ + outtypemax=UINT_MAX; + outtypesize=(int )sizeof(unsigned int); + outbufptr=(void *)uintbuf; + }else{ + fflush(NULL); + fprintf(sp0,"Bad conncompouttype in GrowConnCompMask()\n"); + exit(ABNORMAL_EXIT); + } + fprintf(sp1,"Writing connected components to file %s" + " as %d-byte unsigned ints\n", + outfiles->conncompfile,((int )outtypesize)); + conncompfp=OpenOutputFile(outfiles->conncompfile,realoutfile); for(row=0;row255){ - fprintf(sp0,"Number of connected components too large for byte data\n" - "Abort\n"); - exit(ABNORMAL_EXIT); + if(nodes[row][col].incost>outtypemax){ + fflush(NULL); + fprintf(sp0,"Number of connected components too large for output type\n" + "Abort\n"); + exit(ABNORMAL_EXIT); + } + uintbuf[col]=(unsigned int)(nodes[row][col].incost); + } + if(params->conncompouttype==CONNCOMPOUTTYPEUCHAR){ + for(col=0;colconncompfile); - Write2DArray((void **)components,outfiles->conncompfile,nrow,ncol, - sizeof(unsigned char)); + if(fclose(conncompfp)){ + fflush(NULL); + fprintf(sp0,"WARNING: problem closing file %s (disk full?)\n", + outfiles->conncompfile); + } /* free memory */ Free2DArray((void **)nodes,nrow); - Free2DArray((void **)components,nrow); free(bkts->bucketbase); - + free(uintbuf); + free(ucharbuf); + return(0); + } /* function: ThickenCosts() * ------------------------ */ +static long ThickenCosts(incrcostT **incrcosts, long nrow, long ncol){ long row, col, templong, maxcost; @@ -648,7 +953,7 @@ long ThickenCosts(incrcostT **incrcosts, long nrow, long ncol){ /* initialize variable storing maximum cost */ - maxcost=-LARGELONG; + maxcost=-LARGEINT; /* loop over row arcs and convolve */ for(row=0;rowLARGESHORT){ + fflush(NULL); fprintf(sp0,"WARNING: COSTS CLIPPED IN ThickenCosts()\n"); - incrcosts[row][col].negcost=LARGESHORT; + incrcosts[row][col].negcost=LARGESHORT; }else{ - incrcosts[row][col].negcost=templong; + incrcosts[row][col].negcost=templong; } if(incrcosts[row][col].negcost>maxcost){ - maxcost=incrcosts[row][col].negcost; + maxcost=incrcosts[row][col].negcost; } } } @@ -682,22 +988,23 @@ long ThickenCosts(incrcostT **incrcosts, long nrow, long ncol){ templong=2*incrcosts[row][col].poscost; n=2.0; if(row!=nrow-1){ - templong+=incrcosts[row-1][col].poscost; - n+=1.0; + templong+=incrcosts[row-1][col].poscost; + n+=1.0; } if(row!=2*nrow-2){ - templong+=incrcosts[row+1][col].poscost; - n+=1.0; + templong+=incrcosts[row+1][col].poscost; + n+=1.0; } templong=LRound(templong/n); if(templong>LARGESHORT){ + fflush(NULL); fprintf(sp0,"WARNING: COSTS CLIPPED IN ThickenCosts()\n"); - incrcosts[row][col].negcost=LARGESHORT; + incrcosts[row][col].negcost=LARGESHORT; }else{ - incrcosts[row][col].negcost=templong; + incrcosts[row][col].negcost=templong; } if(incrcosts[row][col].negcost>maxcost){ - maxcost=incrcosts[row][col].negcost; + maxcost=incrcosts[row][col].negcost; } } } @@ -713,9 +1020,10 @@ long ThickenCosts(incrcostT **incrcosts, long nrow, long ncol){ * Return the neighboring node of the given node corresponding to the * given arc number. */ +static nodeT *RegionsNeighborNode(nodeT *node1, long *arcnumptr, nodeT **nodes, - long *arcrowptr, long *arccolptr, - long nrow, long ncol){ + long *arcrowptr, long *arccolptr, + long nrow, long ncol){ long row, col; @@ -726,30 +1034,30 @@ nodeT *RegionsNeighborNode(nodeT *node1, long *arcnumptr, nodeT **nodes, switch((*arcnumptr)++){ case 0: if(col!=ncol-1){ - *arcrowptr=nrow-1+row; - *arccolptr=col; - return(&nodes[row][col+1]); + *arcrowptr=nrow-1+row; + *arccolptr=col; + return(&nodes[row][col+1]); } break; case 1: if(row!=nrow-1){ *arcrowptr=row; *arccolptr=col; - return(&nodes[row+1][col]); + return(&nodes[row+1][col]); } break; case 2: if(col!=0){ - *arcrowptr=nrow-1+row; - *arccolptr=col-1; - return(&nodes[row][col-1]); + *arcrowptr=nrow-1+row; + *arccolptr=col-1; + return(&nodes[row][col-1]); } break; case 3: if(row!=0){ - *arcrowptr=row-1; - *arccolptr=col; - return(&nodes[row-1][col]); + *arcrowptr=row-1; + *arccolptr=col; + return(&nodes[row-1][col]); } break; default: @@ -764,7 +1072,8 @@ nodeT *RegionsNeighborNode(nodeT *node1, long *arcnumptr, nodeT **nodes, * Removes any nodes in the bucket data structure passed, and resets * their distances to VERYFAR. Assumes bukets indexed from 0. */ -void ClearBuckets(bucketT *bkts){ +static +int ClearBuckets(bucketT *bkts){ nodeT *currentnode, *nextnode; long i; @@ -788,6 +1097,9 @@ void ClearBuckets(bucketT *bkts){ bkts->minind=0; bkts->maxind=bkts->size-1; bkts->wrapped=FALSE; + + /* done */ + return(0); } @@ -795,8 +1107,9 @@ void ClearBuckets(bucketT *bkts){ * ------------------------ * */ -void MergeRegions(nodeT **nodes, nodeT *source, long *regionsizes, - long closestregion, long nrow, long ncol){ +static +int MergeRegions(nodeT **nodes, nodeT *source, long *regionsizes, + long closestregion, long nrow, long ncol){ long nextnodelistlen, nextnodelistnext, arcnum, arcrow, arccol, regionnum; nodeT *from, *to, **nextnodelist; @@ -816,14 +1129,14 @@ void MergeRegions(nodeT **nodes, nodeT *source, long *regionsizes, from->incost=closestregion; arcnum=0; while((to=RegionsNeighborNode(from,&arcnum,nodes, - &arcrow,&arccol,nrow,ncol))!=NULL){ + &arcrow,&arccol,nrow,ncol))!=NULL){ if(to->incost==regionnum){ - if(nextnodelistnext>=nextnodelistlen){ - nextnodelistlen+=INITARRSIZE; - nextnodelist=(nodeT **)ReAlloc(nextnodelist, - nextnodelistlen*sizeof(nodeT *)); - } - nextnodelist[nextnodelistnext++]=to; + if(nextnodelistnext>=nextnodelistlen){ + nextnodelistlen+=INITARRSIZE; + nextnodelist=(nodeT **)ReAlloc(nextnodelist, + nextnodelistlen*sizeof(nodeT *)); + } + nextnodelist[nextnodelistnext++]=to; } } } @@ -833,7 +1146,8 @@ void MergeRegions(nodeT **nodes, nodeT *source, long *regionsizes, /* free memory */ free(nextnodelist); - + return(0); + } @@ -841,8 +1155,9 @@ void MergeRegions(nodeT **nodes, nodeT *source, long *regionsizes, * -------------------------- * */ -void RenumberRegion(nodeT **nodes, nodeT *source, long newnum, - long nrow, long ncol){ +static +int RenumberRegion(nodeT **nodes, nodeT *source, long newnum, + long nrow, long ncol){ long nextnodelistlen, nextnodelistnext, arcnum, arcrow, arccol, regionnum; nodeT *from, *to, **nextnodelist; @@ -862,35 +1177,37 @@ void RenumberRegion(nodeT **nodes, nodeT *source, long newnum, from->incost=newnum; arcnum=0; while((to=RegionsNeighborNode(from,&arcnum,nodes, - &arcrow,&arccol,nrow,ncol))!=NULL){ + &arcrow,&arccol,nrow,ncol))!=NULL){ if(to->incost==regionnum){ - if(nextnodelistnext>=nextnodelistlen){ - nextnodelistlen+=INITARRSIZE; - nextnodelist=(nodeT **)ReAlloc(nextnodelist, - nextnodelistlen*sizeof(nodeT *)); - } - nextnodelist[nextnodelistnext++]=to; + if(nextnodelistnext>=nextnodelistlen){ + nextnodelistlen+=INITARRSIZE; + nextnodelist=(nodeT **)ReAlloc(nextnodelist, + nextnodelistlen*sizeof(nodeT *)); + } + nextnodelist[nextnodelistnext++]=to; } } } /* free memory */ free(nextnodelist); - + return(0); + } /* function: AssembleTiles() * ------------------------- */ -void AssembleTiles(outfileT *outfiles, paramT *params, - long nlines, long linelen){ +int AssembleTiles(outfileT *outfiles, paramT *params, + long nlines, long linelen){ long tilerow, tilecol, ntilerow, ntilecol, ntiles, rowovrlp, colovrlp; long i, j, k, ni, nj, dummylong, costtypesize; long nrow, ncol, prevnrow, prevncol, nextnrow, nextncol; long n, ncycle, nflowdone, nflow, candidatelistsize, candidatebagsize; long nnodes, maxnflowcycles, arclen, narcs, sourcetilenum, flowmax; + long nnondecreasedcostiter; long *totarclens; long ***scndrycosts; double avgarclen; @@ -900,9 +1217,9 @@ void AssembleTiles(outfileT *outfiles, paramT *params, void *costsabove, *costsbelow; short **scndryflows, **bulkoffsets, **regions, **nextregions, **lastregions; short **tempregions, *regionsbelow, *regionsabove; - short *nscndrynodes, *nscndryarcs; + int *nscndrynodes, *nscndryarcs; incrcostT **incrcosts; - totalcostT totalcost, oldtotalcost; + totalcostT totalcost, oldtotalcost, mintotalcost; nodeT *source; nodeT **scndrynodes, ***scndryapexes; signed char **iscandidate; @@ -913,7 +1230,7 @@ void AssembleTiles(outfileT *outfiles, paramT *params, bucketT *bkts; char filename[MAXSTRLEN]; - + /* set up */ fprintf(sp1,"Assembling tiles\n"); ntilerow=params->ntilerow; @@ -926,13 +1243,41 @@ void AssembleTiles(outfileT *outfiles, paramT *params, nrow=0; ncol=0; flowmax=params->scndryarcflowmax; + prevnrow=0; + + /* we are reading statistical costs from file even if (params->p >= 0) */ + /* need to set size of cost type and CalcCost function pointer to */ + /* be consistent with data stored in file written by BuildCostArrays() */ if(params->costmode==TOPO){ costtypesize=sizeof(costT); + CalcCost=CalcCostTopo; + EvalCost=EvalCostTopo; }else if(params->costmode==DEFO){ costtypesize=sizeof(costT); + CalcCost=CalcCostDefo; + EvalCost=EvalCostDefo; }else if(params->costmode==SMOOTH){ costtypesize=sizeof(smoothcostT); + CalcCost=CalcCostSmooth; + EvalCost=EvalCostSmooth; + }else{ + fflush(NULL); + fprintf(sp0,"Illegal cost mode in AssembleTiles(). Abort\n"); + exit(ABNORMAL_EXIT); } + /* + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ + costtypesize=sizeof(costT); + }else if(CalcCost==CalcCostSmooth){ + costtypesize=sizeof(smoothcostT); + }else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1 + || CalcCost==CalcCostL2 || CalcCost==CalcCostLP){ + costtypesize=sizeof(short); + }else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir + || CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){ + costtypesize=sizeof(bidircostT); + } + */ /* get memory */ regions=(short **)Get2DMem(ni,nj,sizeof(short *),sizeof(short)); @@ -949,11 +1294,11 @@ void AssembleTiles(outfileT *outfiles, paramT *params, nodesupp=(nodesuppT **)MAlloc(ntiles*sizeof(nodesuppT *)); scndryarcs=(scndryarcT **)MAlloc(ntiles*sizeof(scndryarcT *)); scndrycosts=(long ***)MAlloc(ntiles*sizeof(long **)); - nscndrynodes=(short *)MAlloc(ntiles*sizeof(short)); - nscndryarcs=(short *)MAlloc(ntiles*sizeof(short)); + nscndrynodes=(int *)MAlloc(ntiles*sizeof(int)); + nscndryarcs=(int *)MAlloc(ntiles*sizeof(int)); totarclens=(long *)MAlloc(ntiles*sizeof(long)); bulkoffsets=(short **)Get2DMem(ntilerow,ntilecol,sizeof(short *), - sizeof(short)); + sizeof(short)); costs=(void **)Get2DRowColMem(ni+2,nj+2,sizeof(void *),costtypesize); nextcosts=(void **)Get2DRowColMem(ni+2,nj+2,sizeof(void *),costtypesize); lastcosts=(void **)Get2DRowColMem(ni+2,nj+2,sizeof(void *),costtypesize); @@ -968,11 +1313,11 @@ void AssembleTiles(outfileT *outfiles, paramT *params, /* read region, unwrapped phase, and flow data */ if(tilecol==0){ - ReadNextRegion(tilerow,0,nlines,linelen,outfiles,params, - &nextregions,&nextunwphase,&nextcosts, - &nextnrow,&nextncol); - prevnrow=nrow; - nrow=nextnrow; + ReadNextRegion(tilerow,0,nlines,linelen,outfiles,params, + &nextregions,&nextunwphase,&nextcosts, + &nextnrow,&nextncol); + prevnrow=nrow; + nrow=nextnrow; } prevncol=ncol; ncol=nextncol; @@ -989,23 +1334,23 @@ void AssembleTiles(outfileT *outfiles, paramT *params, costs=nextcosts; nextcosts=tempcosts; if(tilecol!=ntilecol-1){ - ReadNextRegion(tilerow,tilecol+1,nlines,linelen,outfiles,params, - &nextregions,&nextunwphase,&nextcosts, - &nextnrow,&nextncol); + ReadNextRegion(tilerow,tilecol+1,nlines,linelen,outfiles,params, + &nextregions,&nextunwphase,&nextcosts, + &nextnrow,&nextncol); } ReadEdgesAboveAndBelow(tilerow,tilecol,nlines,linelen,params, - outfiles,regionsabove,regionsbelow, - unwphaseabove,unwphasebelow, - costsabove,costsbelow); + outfiles,regionsabove,regionsbelow, + unwphaseabove,unwphasebelow, + costsabove,costsbelow); /* trace region edges to form nodes and arcs */ TraceRegions(regions,nextregions,lastregions,regionsabove,regionsbelow, - unwphase,nextunwphase,lastunwphase,unwphaseabove, - unwphasebelow,costs,nextcosts,lastcosts,costsabove, - costsbelow,prevnrow,prevncol,tilerow,tilecol, - nrow,ncol,scndrynodes,nodesupp,scndryarcs, - scndrycosts,nscndrynodes,nscndryarcs,totarclens, - bulkoffsets,params); + unwphase,nextunwphase,lastunwphase,unwphaseabove, + unwphasebelow,costs,nextcosts,lastcosts,costsabove, + costsbelow,prevnrow,prevncol,tilerow,tilecol, + nrow,ncol,scndrynodes,nodesupp,scndryarcs, + scndrycosts,nscndrynodes,nscndryarcs,totarclens, + bulkoffsets,params); } } @@ -1023,14 +1368,14 @@ void AssembleTiles(outfileT *outfiles, paramT *params, for(i=0;imaxcyclefraction); while(TRUE){ @@ -1092,27 +1438,40 @@ void AssembleTiles(outfileT *outfiles, paramT *params, /* set up the incremental (residual) cost arrays */ SetupIncrFlowCosts((void **)scndrycosts,incrcosts,scndryflows,nflow,ntiles, - ntiles,nscndryarcs,params); + ntiles,nscndryarcs,params); /* set the tree root (equivalent to source of shortest path problem) */ sourcetilenum=(long )ntilecol*floor(ntilerow/2.0)+floor(ntilecol/2.0); source=&scndrynodes[sourcetilenum][0]; + /* set up network variables for tree solver */ + SetupTreeSolveNetwork(scndrynodes,NULL,scndryapexes,iscandidate, + ntiles,nscndrynodes,ntiles,nscndryarcs, + ntiles,0); + /* run the solver, and increment nflowdone if no cycles are found */ n=TreeSolve(scndrynodes,nodesupp,NULL,source,&candidatelist,&candidatebag, &candidatelistsize,&candidatebagsize,bkts,scndryflows, - (void **)scndrycosts,incrcosts,scndryapexes,iscandidate,0, - nflow,NULL,NULL,NULL,ntiles,nscndrynodes,ntiles,nscndryarcs, - ntiles,0,NULL,params); + (void **)scndrycosts,incrcosts,scndryapexes,iscandidate,0, + nflow,NULL,NULL,NULL,ntiles,nscndrynodes,ntiles,nscndryarcs, + ntiles,0,NULL,nnodes,params); /* evaluate and save the total cost (skip if first loop through nflow) */ if(notfirstloop){ oldtotalcost=totalcost; totalcost=EvaluateTotalCost((void **)scndrycosts,scndryflows,ntiles,0, - nscndryarcs,params); + nscndryarcs,params); + if(totalcostoldtotalcost || (n>0 && totalcost==oldtotalcost)){ - fprintf(sp0,"Unexpected increase in total cost. Breaking loop\n"); - break; + fflush(NULL); + fprintf(sp1,"Caution: Unexpected increase in total cost\n"); + } + if(totalcost>=mintotalcost){ + nnondecreasedcostiter++; + }else{ + nnondecreasedcostiter=0; } } @@ -1124,6 +1483,15 @@ void AssembleTiles(outfileT *outfiles, paramT *params, nflowdone=1; } + /* break if lack of total cost reduction is sustained */ + if(nnondecreasedcostiter>=2*params->maxflow){ + fflush(NULL); + fprintf(sp0,"WARNING: No overall cost reduction for too many iterations." + " Breaking loop\n"); + break; + } + + /* break if we're done with all flow increments or problem is convex */ if(nflowdone>=params->maxflow){ break; @@ -1152,9 +1520,14 @@ void AssembleTiles(outfileT *outfiles, paramT *params, free(candidatelist); free(bkts->bucketbase); + /* assemble connected component files if needed */ + if(strlen(outfiles->conncompfile)){ + AssembleTileConnComps(linelen,nlines,outfiles,params); + } + /* integrate phase from secondary network problem */ IntegrateSecondaryFlows(linelen,nlines,scndrynodes,nodesupp,scndryarcs, - nscndryarcs,scndryflows,bulkoffsets,outfiles,params); + nscndryarcs,scndryflows,bulkoffsets,outfiles,params); /* free remaining memory */ for(i=0;irmtmptile){ + fflush(NULL); + fprintf(sp1,"Removing temporary directory %s\n",params->tiledir); for(tilerow=0;tilerowtiledir,LOGFILEROOT,tilerow,tilecol); - unlink(filename); + sprintf(filename,"%s/%s%ld_%ld", + params->tiledir,LOGFILEROOT,tilerow,tilecol); + unlink(filename); } } rmdir(params->tiledir); } + /* Give notice about increasing overlap if there are edge artifacts */ + if(params->rowovrlpcolovrlpcostmode==TOPO){ + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ costtypesize=sizeof(costT); - }else if(params->costmode==DEFO){ - costtypesize=sizeof(costT); - }else if(params->costmode==SMOOTH){ + }else if(CalcCost==CalcCostSmooth){ costtypesize=sizeof(smoothcostT); + }else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1 + || CalcCost==CalcCostL2 || CalcCost==CalcCostLP){ + costtypesize=sizeof(short); + }else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir + || CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){ + costtypesize=sizeof(bidircostT); + }else{ + fflush(NULL); + fprintf(sp0,"ERROR: Bad CalcCost func ptr in ReadNextRegion()\n"); + exit(ABNORMAL_EXIT); } /* use SetupTile() to set filenames only; tile params overwritten below */ SetupTile(nlines,linelen,params,nexttileparams,outfiles,nexttileoutfiles, - tilerow,tilecol); + tilerow,tilecol); nexttilenlines=nexttileparams->nrow; nexttilelinelen=nexttileparams->ncol; /* set tile parameters, overwriting values set by SetupTile() above */ SetTileReadParams(nexttileparams,nexttilenlines,nexttilelinelen, - tilerow,tilecol,nlines,linelen,params); + tilerow,tilecol,nlines,linelen,params); /* read region data */ ParseFilename(outfiles->outfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld%s", - params->tiledir,TMPTILEROOT,basename,tilerow,tilecol, - nexttilelinelen,REGIONSUFFIX); + params->tiledir,TMPTILEROOT,basename,tilerow,tilecol, + nexttilelinelen,REGIONSUFFIX); StrNCopy(nextfile,tempstring,MAXSTRLEN); Read2DArray((void ***)nextregionsptr,nextfile, - nexttilelinelen,nexttilenlines, - nexttileparams,sizeof(short *),sizeof(short)); + nexttilelinelen,nexttilenlines, + nexttileparams,sizeof(short *),sizeof(short)); /* read unwrapped phase data */ if(TMPTILEOUTFORMAT==ALT_LINE_DATA){ ReadAltLineFilePhase(nextunwphaseptr,nexttileoutfiles->outfile, - nexttilelinelen,nexttilenlines,nexttileparams); + nexttilelinelen,nexttilenlines,nexttileparams); }else if(TMPTILEOUTFORMAT==FLOAT_DATA){ Read2DArray((void ***)nextunwphaseptr,nexttileoutfiles->outfile, - nexttilelinelen,nexttilenlines,nexttileparams, - sizeof(float *),sizeof(float)); + nexttilelinelen,nexttilenlines,nexttileparams, + sizeof(float *),sizeof(float)); }else{ + fflush(NULL); fprintf(sp0,"Cannot read format of unwrapped phase tile data\nAbort\n"); exit(ABNORMAL_EXIT); } /* read cost data */ - if(params->p<0){ - Read2DRowColFile((void ***)nextcostsptr,nexttileoutfiles->costoutfile, - nexttilelinelen,nexttilenlines,nexttileparams, - costtypesize); - }else{ - fprintf(sp0,"Tile reassembly not enabled in Lp mode\nAbort\n"); - exit(ABNORMAL_EXIT); - } + Read2DRowColFile((void ***)nextcostsptr,nexttileoutfiles->costoutfile, + nexttilelinelen,nexttilenlines,nexttileparams, + costtypesize); /* flip sign of wrapped phase if flip flag is set */ FlipPhaseArraySign(*nextunwphaseptr,params, - nexttileparams->nrow,nexttileparams->ncol); + nexttileparams->nrow,nexttileparams->ncol); /* set outputs */ (*nextnrowptr)=nexttileparams->nrow; (*nextncolptr)=nexttileparams->ncol; + return(0); } @@ -1270,9 +1670,10 @@ void ReadNextRegion(long tilerow, long tilecol, long nlines, long linelen, * The meanings of these variables are different for the last row * and column. */ -void SetTileReadParams(tileparamT *tileparams, long nexttilenlines, - long nexttilelinelen, long tilerow, long tilecol, - long nlines, long linelen, paramT *params){ +static +int SetTileReadParams(tileparamT *tileparams, long nexttilenlines, + long nexttilelinelen, long tilerow, long tilecol, + long nlines, long linelen, paramT *params){ long rowovrlp, colovrlp; @@ -1303,17 +1704,19 @@ void SetTileReadParams(tileparamT *tileparams, long nexttilenlines, }else{ tileparams->ncol=nexttilelinelen-tileparams->firstcol; } + return(0); } /* function: ReadEdgesAboveAndBelow() * ---------------------------------- */ -void ReadEdgesAboveAndBelow(long tilerow, long tilecol, long nlines, - long linelen, paramT *params, outfileT *outfiles, - short *regionsabove, short *regionsbelow, - float *unwphaseabove, float *unwphasebelow, - void *costsabove, void *costsbelow){ +static +int ReadEdgesAboveAndBelow(long tilerow, long tilecol, long nlines, + long linelen, paramT *params, outfileT *outfiles, + short *regionsabove, short *regionsbelow, + float *unwphaseabove, float *unwphasebelow, + void *costsabove, void *costsbelow){ long ni, nj, readtilelinelen, readtilenlines, costtypesize; long ntilerow, ntilecol, rowovrlp, colovrlp; @@ -1325,6 +1728,16 @@ void ReadEdgesAboveAndBelow(long tilerow, long tilecol, long nlines, char tempstring[MAXTMPSTRLEN], readregionfile[MAXSTRLEN]; char path[MAXSTRLEN], basename[MAXSTRLEN]; + + /* initialize stack structures to zero for good measure */ + memset(tileparams,0,sizeof(tileparamT)); + memset(outfilesabove,0,sizeof(outfileT)); + memset(outfilesbelow,0,sizeof(outfileT)); + memset(tempstring,0,MAXSTRLEN); + memset(readregionfile,0,MAXSTRLEN); + memset(path,0,MAXSTRLEN); + memset(basename,0,MAXSTRLEN); + /* set temporary variables */ ntilerow=params->ntilerow; ntilecol=params->ntilecol; @@ -1334,23 +1747,31 @@ void ReadEdgesAboveAndBelow(long tilerow, long tilecol, long nlines, nj=ceil((linelen+(ntilecol-1)*colovrlp)/(double )ntilecol); /* size of the data type for holding cost data depends on cost mode */ - if(params->costmode==TOPO){ - costtypesize=sizeof(costT); - }else if(params->costmode==DEFO){ + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ costtypesize=sizeof(costT); - }else if(params->costmode==SMOOTH){ + }else if(CalcCost==CalcCostSmooth){ costtypesize=sizeof(smoothcostT); + }else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1 + || CalcCost==CalcCostL2 || CalcCost==CalcCostLP){ + costtypesize=sizeof(short); + }else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir + || CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){ + costtypesize=sizeof(bidircostT); + }else{ + fflush(NULL); + fprintf(sp0,"ERROR: Bad CalcCost func ptr in ReadEdgesAboveAndBelow()\n"); + exit(ABNORMAL_EXIT); } /* set names of files with SetupTile() */ /* tile parameters set by SetupTile() will be overwritten below */ if(tilerow!=0){ SetupTile(nlines,linelen,params,tileparams,outfiles,outfilesabove, - tilerow-1,tilecol); + tilerow-1,tilecol); } if(tilerow!=ntilerow-1){ SetupTile(nlines,linelen,params,tileparams,outfiles,outfilesbelow, - tilerow+1,tilecol); + tilerow+1,tilecol); } /* temporary pointers, so we can use Read2DArray() with 1D output array */ @@ -1384,32 +1805,32 @@ void ReadEdgesAboveAndBelow(long tilerow, long tilecol, long nlines, /* read region data */ ParseFilename(outfiles->outfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld%s", - params->tiledir,TMPTILEROOT,basename,tilerow-1,tilecol, - readtilelinelen,REGIONSUFFIX); + params->tiledir,TMPTILEROOT,basename,tilerow-1,tilecol, + readtilelinelen,REGIONSUFFIX); StrNCopy(readregionfile,tempstring,MAXSTRLEN); Read2DArray((void ***)®ionsaboveptr,readregionfile, - readtilelinelen,readtilenlines, - tileparams,sizeof(short *),sizeof(short)); + readtilelinelen,readtilenlines, + tileparams,sizeof(short *),sizeof(short)); /* read unwrapped phase data */ if(TMPTILEOUTFORMAT==ALT_LINE_DATA){ ReadAltLineFilePhase(&unwphaseaboveptr,outfilesabove->outfile, - readtilelinelen,readtilenlines,tileparams); + readtilelinelen,readtilenlines,tileparams); }else if(TMPTILEOUTFORMAT==FLOAT_DATA){ Read2DArray((void ***)&unwphaseaboveptr,outfilesabove->outfile, - readtilelinelen,readtilenlines,tileparams, - sizeof(float *),sizeof(float)); + readtilelinelen,readtilenlines,tileparams, + sizeof(float *),sizeof(float)); } /* flip sign of wrapped phase if flip flag is set */ FlipPhaseArraySign(unwphaseaboveptr,params, - tileparams->nrow,tileparams->ncol); + tileparams->nrow,tileparams->ncol); /* read costs data */ tileparams->firstrow--; Read2DRowColFileRows((void ***)&costsaboveptr,outfilesabove->costoutfile, - readtilelinelen,readtilenlines,tileparams, - costtypesize); + readtilelinelen,readtilenlines,tileparams, + costtypesize); /* remove temporary tile cost file unless told to save it */ if(params->rmtmptile && !strlen(outfiles->costoutfile)){ @@ -1427,41 +1848,45 @@ void ReadEdgesAboveAndBelow(long tilerow, long tilecol, long nlines, /* read region data */ ParseFilename(outfiles->outfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld%s", - params->tiledir,TMPTILEROOT,basename,tilerow+1,tilecol, - readtilelinelen,REGIONSUFFIX); + params->tiledir,TMPTILEROOT,basename,tilerow+1,tilecol, + readtilelinelen,REGIONSUFFIX); StrNCopy(readregionfile,tempstring,MAXSTRLEN); Read2DArray((void ***)®ionsbelowptr,readregionfile, - readtilelinelen,readtilenlines, - tileparams,sizeof(short *),sizeof(short)); + readtilelinelen,readtilenlines, + tileparams,sizeof(short *),sizeof(short)); /* read unwrapped phase data */ if(TMPTILEOUTFORMAT==ALT_LINE_DATA){ ReadAltLineFilePhase(&unwphasebelowptr,outfilesbelow->outfile, - readtilelinelen,readtilenlines,tileparams); + readtilelinelen,readtilenlines,tileparams); }else if(TMPTILEOUTFORMAT==FLOAT_DATA){ Read2DArray((void ***)&unwphasebelowptr,outfilesbelow->outfile, - readtilelinelen,readtilenlines,tileparams, - sizeof(float *),sizeof(float)); + readtilelinelen,readtilenlines,tileparams, + sizeof(float *),sizeof(float)); } /* flip the sign of the wrapped phase if flip flag is set */ FlipPhaseArraySign(unwphasebelowptr,params, - tileparams->nrow,tileparams->ncol); + tileparams->nrow,tileparams->ncol); /* read costs data */ Read2DRowColFileRows((void ***)&costsbelowptr,outfilesbelow->costoutfile, - readtilelinelen,readtilenlines,tileparams, - costtypesize); + readtilelinelen,readtilenlines,tileparams, + costtypesize); }else{ /* remove temporoary tile cost file for last row unless told to save it */ if(params->rmtmptile && !strlen(outfiles->costoutfile)){ SetupTile(nlines,linelen,params,tileparams,outfiles,outfilesbelow, - tilerow,tilecol); + tilerow,tilecol); unlink(outfilesbelow->costoutfile); } } + + /* done */ + return(0); + } @@ -1475,17 +1900,18 @@ void ReadEdgesAboveAndBelow(long tilerow, long tilecol, long nlines, * are calculated from combining adjacent cost parameters, not from * using the exact method in BuildCostArrays(). */ -void TraceRegions(short **regions, short **nextregions, short **lastregions, - short *regionsabove, short *regionsbelow, float **unwphase, - float **nextunwphase, float **lastunwphase, - float *unwphaseabove, float *unwphasebelow, void **costs, - void **nextcosts, void **lastcosts, void *costsabove, - void *costsbelow, long prevnrow, long prevncol, long tilerow, - long tilecol, long nrow, long ncol, nodeT **scndrynodes, - nodesuppT **nodesupp, scndryarcT **scndryarcs, - long ***scndrycosts, short *nscndrynodes, - short *nscndryarcs, long *totarclens, short **bulkoffsets, - paramT *params){ +static +int TraceRegions(short **regions, short **nextregions, short **lastregions, + short *regionsabove, short *regionsbelow, float **unwphase, + float **nextunwphase, float **lastunwphase, + float *unwphaseabove, float *unwphasebelow, void **costs, + void **nextcosts, void **lastcosts, void *costsabove, + void *costsbelow, long prevnrow, long prevncol, long tilerow, + long tilecol, long nrow, long ncol, nodeT **scndrynodes, + nodesuppT **nodesupp, scndryarcT **scndryarcs, + long ***scndrycosts, int *nscndrynodes, + int *nscndryarcs, long *totarclens, short **bulkoffsets, + paramT *params){ long i, j, row, col, nnrow, nncol, tilenum, costtypesize; long nnewnodes, nnewarcs, npathsout, flowmax, totarclen; @@ -1527,12 +1953,20 @@ void TraceRegions(short **regions, short **nextregions, short **lastregions, nupdatednontilenodes=0; /* size of the data type for holding cost data depends on cost mode */ - if(params->costmode==TOPO){ + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ costtypesize=sizeof(costT); - }else if(params->costmode==DEFO){ - costtypesize=sizeof(costT); - }else if(params->costmode==SMOOTH){ + }else if(CalcCost==CalcCostSmooth){ costtypesize=sizeof(smoothcostT); + }else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1 + || CalcCost==CalcCostL2 || CalcCost==CalcCostLP){ + costtypesize=sizeof(short); + }else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir + || CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){ + costtypesize=sizeof(bidircostT); + }else{ + fflush(NULL); + fprintf(sp0,"ERROR: Bad CalcCost func ptr in TraceRegions()\n"); + exit(ABNORMAL_EXIT); } /* get memory */ @@ -1553,15 +1987,15 @@ void TraceRegions(short **regions, short **nextregions, short **lastregions, /* set up cost and flow arrays for boundaries */ SetUpperEdge(ncol,tilerow,tilecol,costs,costsabove,unwphase,unwphaseabove, - upperedgecosts,upperedgeflows,params, bulkoffsets); + upperedgecosts,upperedgeflows,params, bulkoffsets); SetLowerEdge(nrow,ncol,tilerow,tilecol,costs,costsbelow,unwphase, - unwphasebelow,loweredgecosts,loweredgeflows, - params,bulkoffsets); + unwphasebelow,loweredgecosts,loweredgeflows, + params,bulkoffsets); SetLeftEdge(nrow,prevncol,tilerow,tilecol,costs,lastcosts,unwphase, - lastunwphase,leftedgecosts,leftedgeflows,params, bulkoffsets); + lastunwphase,leftedgecosts,leftedgeflows,params, bulkoffsets); SetRightEdge(nrow,ncol,tilerow,tilecol,costs,nextcosts,unwphase, - nextunwphase,rightedgecosts,rightedgeflows, - params,bulkoffsets); + nextunwphase,rightedgecosts,rightedgeflows, + params,bulkoffsets); /* trace edges between regions */ while(nextnode!=NULL){ @@ -1573,8 +2007,8 @@ void TraceRegions(short **regions, short **nextregions, short **lastregions, /* find number of paths out of from node */ npathsout=FindNumPathsOut(from,params,tilerow,tilecol,nnrow,nncol,regions, - nextregions,lastregions,regionsabove, - regionsbelow,prevncol); + nextregions,lastregions,regionsabove, + regionsbelow,prevncol); /* secondary node exists if region edges fork */ if(npathsout>2){ @@ -1585,49 +2019,55 @@ void TraceRegions(short **regions, short **nextregions, short **lastregions, /* create secondary node if not already created in another tile */ if((from->row!=0 || tilerow==0) && (from->col!=0 || tilecol==0)){ - /* create the secondary node */ - nnewnodes++; - scndrynodes[tilenum]=(nodeT *)ReAlloc(scndrynodes[tilenum], - nnewnodes*sizeof(nodeT)); - nodesupp[tilenum]=(nodesuppT *)ReAlloc(nodesupp[tilenum], - nnewnodes*sizeof(nodesuppT)); - scndrynodes[tilenum][nnewnodes-1].row=tilenum; - scndrynodes[tilenum][nnewnodes-1].col=nnewnodes-1; - nodesupp[tilenum][nnewnodes-1].row=from->row; - nodesupp[tilenum][nnewnodes-1].col=from->col; - nodesupp[tilenum][nnewnodes-1].noutarcs=0; - nodesupp[tilenum][nnewnodes-1].neighbornodes=NULL; - nodesupp[tilenum][nnewnodes-1].outarcs=NULL; + /* create the secondary node */ + nnewnodes++; + if(nnewnodes > SHRT_MAX){ + fflush(NULL); + fprintf(sp0,"Exceeded maximum number of secondary nodes\n" + "Decrease TILECOSTTHRESH and/or increase MINREGIONSIZE\n"); + exit(ABNORMAL_EXIT); + } + scndrynodes[tilenum]=(nodeT *)ReAlloc(scndrynodes[tilenum], + nnewnodes*sizeof(nodeT)); + nodesupp[tilenum]=(nodesuppT *)ReAlloc(nodesupp[tilenum], + nnewnodes*sizeof(nodesuppT)); + scndrynodes[tilenum][nnewnodes-1].row=tilenum; + scndrynodes[tilenum][nnewnodes-1].col=nnewnodes-1; + nodesupp[tilenum][nnewnodes-1].row=from->row; + nodesupp[tilenum][nnewnodes-1].col=from->col; + nodesupp[tilenum][nnewnodes-1].noutarcs=0; + nodesupp[tilenum][nnewnodes-1].neighbornodes=NULL; + nodesupp[tilenum][nnewnodes-1].outarcs=NULL; } /* create the secondary arc to this node if it doesn't already exist */ if(from->pred!=NULL - && ((from->row==from->pred->row && (from->row!=0 || tilerow==0)) - || (from->col==from->pred->col && (from->col!=0 || tilecol==0)))){ - - TraceSecondaryArc(from,scndrynodes,nodesupp,scndryarcs,scndrycosts, - &nnewnodes,&nnewarcs,tilerow,tilecol,flowmax, - nrow,ncol,prevnrow,prevncol,params,costs, - rightedgecosts,loweredgecosts,leftedgecosts, - upperedgecosts,flows,rightedgeflows,loweredgeflows, - leftedgeflows,upperedgeflows,&updatednontilenodes, - &nupdatednontilenodes,&updatednontilenodesize, - &inontilenodeoutarc,&totarclen); + && ((from->row==from->pred->row && (from->row!=0 || tilerow==0)) + || (from->col==from->pred->col && (from->col!=0 || tilecol==0)))){ + + TraceSecondaryArc(from,scndrynodes,nodesupp,scndryarcs,scndrycosts, + &nnewnodes,&nnewarcs,tilerow,tilecol,flowmax, + nrow,ncol,prevnrow,prevncol,params,costs, + rightedgecosts,loweredgecosts,leftedgecosts, + upperedgecosts,flows,rightedgeflows,loweredgeflows, + leftedgeflows,upperedgeflows,&updatednontilenodes, + &nupdatednontilenodes,&updatednontilenodesize, + &inontilenodeoutarc,&totarclen); } } /* scan neighboring primary nodes and place path candidates into stack */ RegionTraceCheckNeighbors(from,&nextnode,primarynodes,regions, - nextregions,lastregions,regionsabove, - regionsbelow,tilerow,tilecol,nnrow,nncol, - scndrynodes,nodesupp,scndryarcs,&nnewnodes, - &nnewarcs,flowmax,nrow,ncol,prevnrow,prevncol, - params,costs,rightedgecosts,loweredgecosts, - leftedgecosts,upperedgecosts,flows, - rightedgeflows,loweredgeflows,leftedgeflows, - upperedgeflows,scndrycosts,&updatednontilenodes, - &nupdatednontilenodes,&updatednontilenodesize, - &inontilenodeoutarc,&totarclen); + nextregions,lastregions,regionsabove, + regionsbelow,tilerow,tilecol,nnrow,nncol, + scndrynodes,nodesupp,scndryarcs,&nnewnodes, + &nnewarcs,flowmax,nrow,ncol,prevnrow,prevncol, + params,costs,rightedgecosts,loweredgecosts, + leftedgecosts,upperedgecosts,flows, + rightedgeflows,loweredgeflows,leftedgeflows, + upperedgeflows,scndrycosts,&updatednontilenodes, + &nupdatednontilenodes,&updatednontilenodesize, + &inontilenodeoutarc,&totarclen); } @@ -1639,7 +2079,7 @@ void TraceRegions(short **regions, short **nextregions, short **lastregions, for(j=0;jlevel][tempnode->incost]; + =&scndrynodes[tempnode->level][tempnode->incost]; } } @@ -1697,6 +2137,7 @@ void TraceRegions(short **regions, short **nextregions, short **lastregions, Free2DArray((void **)leftedgecosts,nrow); Free2DArray((void **)upperedgecosts,1); Free2DArray((void **)loweredgecosts,1); + return(0); } @@ -1704,10 +2145,11 @@ void TraceRegions(short **regions, short **nextregions, short **lastregions, * --------------------------- * Check all outgoing arcs to see how many paths out there are. */ +static long FindNumPathsOut(nodeT *from, paramT *params, long tilerow, long tilecol, - long nnrow, long nncol, short **regions, - short **nextregions, short **lastregions, - short *regionsabove, short *regionsbelow, long prevncol){ + long nnrow, long nncol, short **regions, + short **nextregions, short **lastregions, + short *regionsabove, short *regionsbelow, long prevncol){ long npathsout, ntilerow, ntilecol, fromrow, fromcol; @@ -1784,27 +2226,28 @@ long FindNumPathsOut(nodeT *from, paramT *params, long tilerow, long tilecol, /* function: RegionTraceCheckNeighbors() * ------------------------------------- */ -void RegionTraceCheckNeighbors(nodeT *from, nodeT **nextnodeptr, - nodeT **primarynodes, short **regions, - short **nextregions, short **lastregions, - short *regionsabove, short *regionsbelow, - long tilerow, long tilecol, long nnrow, - long nncol, nodeT **scndrynodes, - nodesuppT **nodesupp, scndryarcT **scndryarcs, - long *nnewnodesptr, long *nnewarcsptr, - long flowmax, long nrow, long ncol, - long prevnrow, long prevncol, paramT *params, - void **costs, void **rightedgecosts, - void **loweredgecosts, void **leftedgecosts, - void **upperedgecosts, short **flows, - short **rightedgeflows, short **loweredgeflows, - short **leftedgeflows, short **upperedgeflows, - long ***scndrycosts, - nodeT ***updatednontilenodesptr, - long *nupdatednontilenodesptr, - long *updatednontilenodesizeptr, - short **inontilenodeoutarcptr, - long *totarclenptr){ +static +int RegionTraceCheckNeighbors(nodeT *from, nodeT **nextnodeptr, + nodeT **primarynodes, short **regions, + short **nextregions, short **lastregions, + short *regionsabove, short *regionsbelow, + long tilerow, long tilecol, long nnrow, + long nncol, nodeT **scndrynodes, + nodesuppT **nodesupp, scndryarcT **scndryarcs, + long *nnewnodesptr, long *nnewarcsptr, + long flowmax, long nrow, long ncol, + long prevnrow, long prevncol, paramT *params, + void **costs, void **rightedgecosts, + void **loweredgecosts, void **leftedgecosts, + void **upperedgecosts, short **flows, + short **rightedgeflows, short **loweredgeflows, + short **leftedgeflows, short **upperedgeflows, + long ***scndrycosts, + nodeT ***updatednontilenodesptr, + long *nupdatednontilenodesptr, + long *updatednontilenodesizeptr, + short **inontilenodeoutarcptr, + long *totarclenptr){ long fromrow, fromcol; nodeT *to, *nextnode; @@ -1822,22 +2265,22 @@ void RegionTraceCheckNeighbors(nodeT *from, nodeT **nextnodeptr, if(fromrow==0 || fromrow==nnrow-1 || regions[fromrow-1][fromcol]!=regions[fromrow][fromcol]){ if(to!=from->pred){ - to->pred=from; - if(to->group==NOTINBUCKET){ - to->group=INBUCKET; - to->next=nextnode; - nextnode=to; - }else if(to->group==ONTREE && (fromrow!=0 || tilerow==0)){ - TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, - nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, - nrow,ncol,prevnrow,prevncol,params,costs, - rightedgecosts,loweredgecosts,leftedgecosts, - upperedgecosts,flows,rightedgeflows, - loweredgeflows,leftedgeflows,upperedgeflows, - updatednontilenodesptr,nupdatednontilenodesptr, - updatednontilenodesizeptr,inontilenodeoutarcptr, - totarclenptr); - } + to->pred=from; + if(to->group==NOTINBUCKET){ + to->group=INBUCKET; + to->next=nextnode; + nextnode=to; + }else if(to->group==ONTREE && (fromrow!=0 || tilerow==0)){ + TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, + nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, + nrow,ncol,prevnrow,prevncol,params,costs, + rightedgecosts,loweredgecosts,leftedgecosts, + upperedgecosts,flows,rightedgeflows, + loweredgeflows,leftedgeflows,upperedgeflows, + updatednontilenodesptr,nupdatednontilenodesptr, + updatednontilenodesizeptr,inontilenodeoutarcptr, + totarclenptr); + } } } } @@ -1849,22 +2292,22 @@ void RegionTraceCheckNeighbors(nodeT *from, nodeT **nextnodeptr, if(fromcol==0 || fromcol==nncol-1 || regions[fromrow][fromcol]!=regions[fromrow][fromcol-1]){ if(to!=from->pred){ - to->pred=from; - if(to->group==NOTINBUCKET){ - to->group=INBUCKET; - to->next=nextnode; - nextnode=to; - }else if(to->group==ONTREE && (fromcol!=0 || tilecol==0)){ - TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, - nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, - nrow,ncol,prevnrow,prevncol,params,costs, - rightedgecosts,loweredgecosts,leftedgecosts, - upperedgecosts,flows,rightedgeflows, - loweredgeflows,leftedgeflows,upperedgeflows, - updatednontilenodesptr,nupdatednontilenodesptr, - updatednontilenodesizeptr,inontilenodeoutarcptr, - totarclenptr); - } + to->pred=from; + if(to->group==NOTINBUCKET){ + to->group=INBUCKET; + to->next=nextnode; + nextnode=to; + }else if(to->group==ONTREE && (fromcol!=0 || tilecol==0)){ + TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, + nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, + nrow,ncol,prevnrow,prevncol,params,costs, + rightedgecosts,loweredgecosts,leftedgecosts, + upperedgecosts,flows,rightedgeflows, + loweredgeflows,leftedgeflows,upperedgeflows, + updatednontilenodesptr,nupdatednontilenodesptr, + updatednontilenodesizeptr,inontilenodeoutarcptr, + totarclenptr); + } } } } @@ -1876,22 +2319,22 @@ void RegionTraceCheckNeighbors(nodeT *from, nodeT **nextnodeptr, if(fromrow==0 || fromrow==nnrow-1 || regions[fromrow][fromcol-1]!=regions[fromrow-1][fromcol-1]){ if(to!=from->pred){ - to->pred=from; - if(to->group==NOTINBUCKET){ - to->group=INBUCKET; - to->next=nextnode; - nextnode=to; - }else if(to->group==ONTREE && (fromrow!=0 || tilerow==0)){ - TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, - nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, - nrow,ncol,prevnrow,prevncol,params,costs, - rightedgecosts,loweredgecosts,leftedgecosts, - upperedgecosts,flows,rightedgeflows, - loweredgeflows,leftedgeflows,upperedgeflows, - updatednontilenodesptr,nupdatednontilenodesptr, - updatednontilenodesizeptr,inontilenodeoutarcptr, - totarclenptr); - } + to->pred=from; + if(to->group==NOTINBUCKET){ + to->group=INBUCKET; + to->next=nextnode; + nextnode=to; + }else if(to->group==ONTREE && (fromrow!=0 || tilerow==0)){ + TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, + nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, + nrow,ncol,prevnrow,prevncol,params,costs, + rightedgecosts,loweredgecosts,leftedgecosts, + upperedgecosts,flows,rightedgeflows, + loweredgeflows,leftedgeflows,upperedgeflows, + updatednontilenodesptr,nupdatednontilenodesptr, + updatednontilenodesizeptr,inontilenodeoutarcptr, + totarclenptr); + } } } } @@ -1903,22 +2346,22 @@ void RegionTraceCheckNeighbors(nodeT *from, nodeT **nextnodeptr, if(fromcol==0 || fromcol==nncol-1 || regions[fromrow-1][fromcol-1]!=regions[fromrow-1][fromcol]){ if(to!=from->pred){ - to->pred=from; - if(to->group==NOTINBUCKET){ - to->group=INBUCKET; - to->next=nextnode; - nextnode=to; - }else if(to->group==ONTREE && (fromcol!=0 || tilecol==0)){ - TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, - nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, - nrow,ncol,prevnrow,prevncol,params,costs, - rightedgecosts,loweredgecosts,leftedgecosts, - upperedgecosts,flows,rightedgeflows, - loweredgeflows,leftedgeflows,upperedgeflows, - updatednontilenodesptr,nupdatednontilenodesptr, - updatednontilenodesizeptr,inontilenodeoutarcptr, - totarclenptr); - } + to->pred=from; + if(to->group==NOTINBUCKET){ + to->group=INBUCKET; + to->next=nextnode; + nextnode=to; + }else if(to->group==ONTREE && (fromcol!=0 || tilecol==0)){ + TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, + nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, + nrow,ncol,prevnrow,prevncol,params,costs, + rightedgecosts,loweredgecosts,leftedgecosts, + upperedgecosts,flows,rightedgeflows, + loweredgeflows,leftedgeflows,upperedgeflows, + updatednontilenodesptr,nupdatednontilenodesptr, + updatednontilenodesizeptr,inontilenodeoutarcptr, + totarclenptr); + } } } } @@ -1926,17 +2369,18 @@ void RegionTraceCheckNeighbors(nodeT *from, nodeT **nextnodeptr, /* set return values */ *nextnodeptr=nextnode; - + return(0); } /* function: SetUpperEdge() * ------------------------ */ -void SetUpperEdge(long ncol, long tilerow, long tilecol, void **voidcosts, - void *voidcostsabove, float **unwphase, - float *unwphaseabove, void **voidupperedgecosts, - short **upperedgeflows, paramT *params, short **bulkoffsets){ +static +int SetUpperEdge(long ncol, long tilerow, long tilecol, void **voidcosts, + void *voidcostsabove, float **unwphase, + float *unwphaseabove, void **voidupperedgecosts, + short **upperedgeflows, paramT *params, short **bulkoffsets){ long col, reloffset; double dphi, dpsi; @@ -1952,7 +2396,7 @@ void SetUpperEdge(long ncol, long tilerow, long tilecol, void **voidcosts, upperedgesmoothcosts=(smoothcostT **)voidupperedgecosts; smoothcosts=(smoothcostT **)voidcosts; smoothcostsabove=(smoothcostT *)voidcostsabove; - + /* see if tile is in top row */ if(tilerow!=0){ @@ -1966,61 +2410,90 @@ void SetUpperEdge(long ncol, long tilerow, long tilecol, void **voidcosts, upperedgeflows[0][col]=(short )LRound(dphi)-reloffset; dpsi=dphi-floor(dphi); if(dpsi>0.5){ - dpsi-=1.0; - } - if(params->costmode==TOPO || params->costmode==DEFO){ - upperedgecosts[0][col].offset=nshortcycle*dpsi; - upperedgecosts[0][col].sigsq=ceil((costs[0][col].sigsq - +costsabove[col].sigsq)/2.0); - if(costs[0][col].dzmax>costsabove[col].dzmax){ - upperedgecosts[0][col].dzmax=costs[0][col].dzmax; - }else{ - upperedgecosts[0][col].dzmax=costsabove[col].dzmax; - } - if(costs[0][col].laycostcostmode==SMOOTH){ - upperedgesmoothcosts[0][col].offset=nshortcycle*dpsi; - upperedgesmoothcosts[0][col].sigsq= - ceil((smoothcosts[0][col].sigsq+smoothcostsabove[col].sigsq)/2.0); + dpsi-=1.0; + } + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ + upperedgecosts[0][col].offset=(short )LRound(nshortcycle*dpsi); + upperedgecosts[0][col].sigsq=AvgSigSq(costs[0][col].sigsq, + costsabove[col].sigsq); + if(costs[0][col].dzmax>costsabove[col].dzmax){ + upperedgecosts[0][col].dzmax=costs[0][col].dzmax; + }else{ + upperedgecosts[0][col].dzmax=costsabove[col].dzmax; + } + if(costs[0][col].laycostcostmode==TOPO || params->costmode==DEFO){ + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ for(col=0;colcostmode==SMOOTH){ + }else if(CalcCost==CalcCostSmooth){ + for(col=0;colmaxflow){ - if(tempflow>flowlimhi){ - fprintf(sp0,"Overflow in tile offset\nAbort\n"); - exit(ABNORMAL_EXIT); - } - maxflow=tempflow; + if(tempflow>flowlimhi){ + fflush(NULL); + fprintf(sp0,"Overflow in tile offset\nAbort\n"); + exit(ABNORMAL_EXIT); + } + maxflow=tempflow; } flowhistogram[tempflow-flowlimlo]++; dpsi=dphi-floor(dphi); if(dpsi>0.5){ - dpsi-=1.0; - } - if(params->costmode==TOPO || params->costmode==DEFO){ - loweredgecosts[0][col].offset=nshortcycle*dpsi; - loweredgecosts[0][col].sigsq=ceil((costs[nrow-2][col].sigsq - +costsbelow[col].sigsq)/2.0); - if(costs[nrow-2][col].dzmax>costsbelow[col].dzmax){ - loweredgecosts[0][col].dzmax=costs[nrow-2][col].dzmax; - }else{ - loweredgecosts[0][col].dzmax=costsbelow[col].dzmax; - } - if(costs[nrow-2][col].laycostcostmode==SMOOTH){ - loweredgesmoothcosts[0][col].offset=nshortcycle*dpsi; - loweredgesmoothcosts[0][col].sigsq= - ceil((smoothcosts[nrow-2][col].sigsq - +smoothcostsbelow[col].sigsq)/2.0); + dpsi-=1.0; + } + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ + loweredgecosts[0][col].offset=(short )LRound(nshortcycle*dpsi); + loweredgecosts[0][col].sigsq=AvgSigSq(costs[nrow-2][col].sigsq, + costsbelow[col].sigsq); + if(costs[nrow-2][col].dzmax>costsbelow[col].dzmax){ + loweredgecosts[0][col].dzmax=costs[nrow-2][col].dzmax; + }else{ + loweredgecosts[0][col].dzmax=costsbelow[col].dzmax; + } + if(costs[nrow-2][col].laycostnmax){ - nmax=flowhistogram[iflow-flowlimlo]; - reloffset=iflow; + nmax=flowhistogram[iflow-flowlimlo]; + reloffset=iflow; } } bulkoffsets[tilerow+1][tilecol]=bulkoffsets[tilerow][tilecol]-reloffset; @@ -2118,33 +2606,50 @@ void SetLowerEdge(long nrow, long ncol, long tilerow, long tilecol, free(flowhistogram); }else{ - if(params->costmode==TOPO || params->costmode==DEFO){ + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ for(col=0;colcostmode==SMOOTH){ + }else if(CalcCost==CalcCostSmooth){ for(col=0;col0.5){ - dpsi-=1.0; - } - if(params->costmode==TOPO || params->costmode==DEFO){ - leftedgecosts[row][0].offset=(TILEDPSICOLFACTOR*nshortcycle*dpsi); - leftedgecosts[row][0].sigsq= - ceil((costs[row+nrow-1][0].sigsq - +lastcosts[row+nrow-1][prevncol-2].sigsq)/2.0); - if(costs[row+nrow-1][0].dzmax>lastcosts[row+nrow-1][prevncol-2].dzmax){ - leftedgecosts[row][0].dzmax=costs[row+nrow-1][0].dzmax; - }else{ - leftedgecosts[row][0].dzmax=lastcosts[row+nrow-1][prevncol-2].dzmax; - } - if(costs[row+nrow-1][0].laycost - >lastcosts[row+nrow-1][prevncol-2].laycost){ - leftedgecosts[row][0].laycost=costs[row+nrow-1][0].laycost; - }else{ - leftedgecosts[row][0].laycost - =lastcosts[row+nrow-1][prevncol-2].laycost; - } - }else if(params->costmode==SMOOTH){ - leftedgesmoothcosts[row][0].offset - =(TILEDPSICOLFACTOR*nshortcycle*dpsi); - leftedgesmoothcosts[row][0].sigsq= - ceil((smoothcosts[row+nrow-1][0].sigsq - +lastsmoothcosts[row+nrow-1][prevncol-2].sigsq)/2.0); + dpsi-=1.0; + } + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ + leftedgecosts[row][0].offset=(short )LRound(TILEDPSICOLFACTOR + *nshortcycle*dpsi); + leftedgecosts[row][0].sigsq + =AvgSigSq(costs[row+nrow-1][0].sigsq, + lastcosts[row+nrow-1][prevncol-2].sigsq); + if(costs[row+nrow-1][0].dzmax>lastcosts[row+nrow-1][prevncol-2].dzmax){ + leftedgecosts[row][0].dzmax=costs[row+nrow-1][0].dzmax; + }else{ + leftedgecosts[row][0].dzmax=lastcosts[row+nrow-1][prevncol-2].dzmax; + } + if(costs[row+nrow-1][0].laycost + >lastcosts[row+nrow-1][prevncol-2].laycost){ + leftedgecosts[row][0].laycost=costs[row+nrow-1][0].laycost; + }else{ + leftedgecosts[row][0].laycost + =lastcosts[row+nrow-1][prevncol-2].laycost; + } + }else if(CalcCost==CalcCostSmooth){ + leftedgesmoothcosts[row][0].offset + =(short )LRound(TILEDPSICOLFACTOR*nshortcycle*dpsi); + leftedgesmoothcosts[row][0].sigsq + =AvgSigSq(smoothcosts[row+nrow-1][0].sigsq, + lastsmoothcosts[row+nrow-1][prevncol-2].sigsq); + }else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1 + || CalcCost==CalcCostL2 || CalcCost==CalcCostLP){ + ((short **)voidleftedgecosts)[row][0]= + (((short **)voidcosts)[row+nrow-1][0] + +((short **)voidlastcosts)[row+nrow-1][prevncol-2])/2; + }else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir + || CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){ + ((bidircostT **)voidleftedgecosts)[row][0].posweight= + (((bidircostT **)voidcosts)[row+nrow-1][0].posweight + +((bidircostT **)voidlastcosts)[row+nrow-1][prevncol-2].posweight) + /2; + ((bidircostT **)voidleftedgecosts)[row][0].negweight= + (((bidircostT **)voidcosts)[row+nrow-1][0].negweight + +((bidircostT **)voidlastcosts)[row+nrow-1][prevncol-2].negweight) + /2; }else{ - fprintf(sp0,"Illegal cost mode in SetLeftEdge(). This is a bug.\n"); - exit(ABNORMAL_EXIT); + fflush(NULL); + fprintf(sp0,"Illegal cost mode in SetLeftEdge(). This is a bug.\n"); + exit(ABNORMAL_EXIT); } } }else{ - if(params->costmode==TOPO || params->costmode==DEFO){ + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ for(row=0;rowcostmode==SMOOTH){ + }else if(CalcCost==CalcCostSmooth){ + for(row=0;rowmaxflow){ - if(tempflow>flowlimhi){ - fprintf(sp0,"Overflow in tile offset\nAbort\n"); - exit(ABNORMAL_EXIT); - } - maxflow=tempflow; + if(tempflow>flowlimhi){ + fflush(NULL); + fprintf(sp0,"Overflow in tile offset\nAbort\n"); + exit(ABNORMAL_EXIT); + } + maxflow=tempflow; } flowhistogram[tempflow-flowlimlo]++; dpsi=dphi-floor(dphi); if(dpsi>0.5){ - dpsi-=1.0; - } - if(params->costmode==TOPO || params->costmode==DEFO){ - rightedgecosts[row][0].offset=(TILEDPSICOLFACTOR*nshortcycle*dpsi); - rightedgecosts[row][0].sigsq - =ceil((costs[row+nrow-1][ncol-2].sigsq - +nextcosts[row+nrow-1][0].sigsq)/2.0); - if(costs[row+nrow-1][ncol-2].dzmax>nextcosts[row+nrow-1][0].dzmax){ - rightedgecosts[row][0].dzmax=costs[row+nrow-1][ncol-2].dzmax; - }else{ - rightedgecosts[row][0].dzmax=nextcosts[row+nrow-1][0].dzmax; - } - if(costs[row+nrow-1][ncol-2].laycost>nextcosts[row+nrow-1][0].laycost){ - rightedgecosts[row][0].laycost=costs[row+nrow-1][ncol-2].laycost; - }else{ - rightedgecosts[row][0].laycost=nextcosts[row+nrow-1][0].laycost; - } - }else if(params->costmode==SMOOTH){ - rightedgesmoothcosts[row][0].offset - =(TILEDPSICOLFACTOR*nshortcycle*dpsi); - rightedgesmoothcosts[row][0].sigsq - =ceil((smoothcosts[row+nrow-1][ncol-2].sigsq - +nextsmoothcosts[row+nrow-1][0].sigsq)/2.0); + dpsi-=1.0; + } + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ + rightedgecosts[row][0].offset=(short )LRound(TILEDPSICOLFACTOR + *nshortcycle*dpsi); + rightedgecosts[row][0].sigsq + =AvgSigSq(costs[row+nrow-1][ncol-2].sigsq, + nextcosts[row+nrow-1][0].sigsq); + if(costs[row+nrow-1][ncol-2].dzmax>nextcosts[row+nrow-1][0].dzmax){ + rightedgecosts[row][0].dzmax=costs[row+nrow-1][ncol-2].dzmax; + }else{ + rightedgecosts[row][0].dzmax=nextcosts[row+nrow-1][0].dzmax; + } + if(costs[row+nrow-1][ncol-2].laycost>nextcosts[row+nrow-1][0].laycost){ + rightedgecosts[row][0].laycost=costs[row+nrow-1][ncol-2].laycost; + }else{ + rightedgecosts[row][0].laycost=nextcosts[row+nrow-1][0].laycost; + } + }else if(CalcCost==CalcCostSmooth){ + rightedgesmoothcosts[row][0].offset + =(short )LRound(TILEDPSICOLFACTOR*nshortcycle*dpsi); + rightedgesmoothcosts[row][0].sigsq + =AvgSigSq(smoothcosts[row+nrow-1][ncol-2].sigsq, + nextsmoothcosts[row+nrow-1][0].sigsq); + }else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1 + || CalcCost==CalcCostL2 || CalcCost==CalcCostLP){ + ((short **)voidrightedgecosts)[row][0]= + (((short **)voidcosts)[row+nrow-1][ncol-2] + +((short **)voidnextcosts)[row+nrow-1][0])/2; + }else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir + || CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){ + ((bidircostT **)voidrightedgecosts)[row][0].posweight= + (((bidircostT **)voidcosts)[row+nrow-1][ncol-2].posweight + +((bidircostT **)voidnextcosts)[row+nrow-1][ncol-2].posweight)/2; + ((bidircostT **)voidrightedgecosts)[row][0].negweight= + (((bidircostT **)voidcosts)[row+nrow-1][ncol-2].negweight + +((bidircostT **)voidnextcosts)[row+nrow-1][ncol-2].negweight)/2; }else{ - fprintf(sp0,"Illegal cost mode in SetRightEdge(). This is a bug.\n"); - exit(ABNORMAL_EXIT); + fflush(NULL); + fprintf(sp0,"Illegal cost mode in SetRightEdge(). This is a bug.\n"); + exit(ABNORMAL_EXIT); } } @@ -2318,10 +2874,10 @@ void SetRightEdge(long nrow, long ncol, long tilerow, long tilecol, nmax=0; reloffset=0; for(iflow=minflow;iflow<=maxflow;iflow++){ - if(flowhistogram[iflow-flowlimlo]>nmax){ - nmax=flowhistogram[iflow-flowlimlo]; - reloffset=iflow; - } + if(flowhistogram[iflow-flowlimlo]>nmax){ + nmax=flowhistogram[iflow-flowlimlo]; + reloffset=iflow; + } } bulkoffsets[tilerow][tilecol+1]=bulkoffsets[tilerow][tilecol]+reloffset; }else{ @@ -2338,51 +2894,95 @@ void SetRightEdge(long nrow, long ncol, long tilerow, long tilecol, free(flowhistogram); }else{ - if(params->costmode==TOPO || params->costmode==DEFO){ + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ for(row=0;rowcostmode==SMOOTH){ + }else if(CalcCost==CalcCostSmooth){ + for(row=0;rowpred==NULL || (tilerow!=0 && primaryhead->row==0 && primaryhead->pred->row==0) || (tilecol!=0 && primaryhead->col==0 && primaryhead->pred->col==0)){ - return; + return(0); } /* set up */ @@ -2411,6 +3011,7 @@ void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, nshortcycle=params->nshortcycle; zerocost=FALSE; arroffset=0; + sigsq=0; /* loop to determine appropriate value for arroffset */ while(TRUE){ @@ -2430,161 +3031,187 @@ void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, /* get primary arc just traversed */ arclen++; if(tempnode->col==primarytail->col+1){ /* rightward arc */ - primaryarcdir=1; - primaryarccol=primarytail->col; - if(primarytail->row==0){ /* top edge */ - if(tilerow==0){ - zerocost=TRUE; - }else{ - primaryarcrow=0; - costs=upperedgecosts; - flows=upperedgeflows; - calccostnrow=2; - } - }else if(primarytail->row==nnrow-1){ /* bottom edge */ - if(tilerow==ntilerow-1){ - zerocost=TRUE; - }else{ - primaryarcrow=0; - costs=loweredgecosts; - flows=loweredgeflows; - calccostnrow=2; - } - }else{ /* normal arc */ - primaryarcrow=primarytail->row-1; - costs=tilecosts; - flows=tileflows; - calccostnrow=nrow; - } + primaryarcdir=1; + primaryarccol=primarytail->col; + if(primarytail->row==0){ /* top edge */ + if(tilerow==0){ + zerocost=TRUE; + }else{ + primaryarcrow=0; + costs=upperedgecosts; + flows=upperedgeflows; + calccostnrow=2; + } + }else if(primarytail->row==nnrow-1){ /* bottom edge */ + if(tilerow==ntilerow-1){ + zerocost=TRUE; + }else{ + primaryarcrow=0; + costs=loweredgecosts; + flows=loweredgeflows; + calccostnrow=2; + } + }else{ /* normal arc */ + primaryarcrow=primarytail->row-1; + costs=tilecosts; + flows=tileflows; + calccostnrow=nrow; + } }else if(tempnode->row==primarytail->row+1){ /* downward arc */ - primaryarcdir=1; - if(primarytail->col==0){ /* left edge */ - if(tilecol==0){ - zerocost=TRUE; - }else{ - primaryarcrow=primarytail->row; - primaryarccol=0; - costs=leftedgecosts; - flows=leftedgeflows; - calccostnrow=0; - } - }else if(primarytail->col==nncol-1){ /* right edge */ - if(tilecol==ntilecol-1){ - zerocost=TRUE; - }else{ - primaryarcrow=primarytail->row; - primaryarccol=0; - costs=rightedgecosts; - flows=rightedgeflows; - calccostnrow=0; - } - }else{ /* normal arc */ - primaryarcrow=primarytail->row+nrow-1; - primaryarccol=primarytail->col-1; - costs=tilecosts; - flows=tileflows; - calccostnrow=nrow; - } + primaryarcdir=1; + if(primarytail->col==0){ /* left edge */ + if(tilecol==0){ + zerocost=TRUE; + }else{ + primaryarcrow=primarytail->row; + primaryarccol=0; + costs=leftedgecosts; + flows=leftedgeflows; + calccostnrow=0; + } + }else if(primarytail->col==nncol-1){ /* right edge */ + if(tilecol==ntilecol-1){ + zerocost=TRUE; + }else{ + primaryarcrow=primarytail->row; + primaryarccol=0; + costs=rightedgecosts; + flows=rightedgeflows; + calccostnrow=0; + } + }else{ /* normal arc */ + primaryarcrow=primarytail->row+nrow-1; + primaryarccol=primarytail->col-1; + costs=tilecosts; + flows=tileflows; + calccostnrow=nrow; + } }else if(tempnode->col==primarytail->col-1){ /* leftward arc */ - primaryarcdir=-1; - primaryarccol=primarytail->col-1; - if(primarytail->row==0){ /* top edge */ - if(tilerow==0){ - zerocost=TRUE; - }else{ - primaryarcrow=0; - costs=upperedgecosts; - flows=upperedgeflows; - calccostnrow=2; - } - }else if(primarytail->row==nnrow-1){ /* bottom edge */ - if(tilerow==ntilerow-1){ - zerocost=TRUE; - }else{ - primaryarcrow=0; - costs=loweredgecosts; - flows=loweredgeflows; - calccostnrow=2; - } - }else{ /* normal arc */ - primaryarcrow=primarytail->row-1; - costs=tilecosts; - flows=tileflows; - calccostnrow=nrow; - } + primaryarcdir=-1; + primaryarccol=primarytail->col-1; + if(primarytail->row==0){ /* top edge */ + if(tilerow==0){ + zerocost=TRUE; + }else{ + primaryarcrow=0; + costs=upperedgecosts; + flows=upperedgeflows; + calccostnrow=2; + } + }else if(primarytail->row==nnrow-1){ /* bottom edge */ + if(tilerow==ntilerow-1){ + zerocost=TRUE; + }else{ + primaryarcrow=0; + costs=loweredgecosts; + flows=loweredgeflows; + calccostnrow=2; + } + }else{ /* normal arc */ + primaryarcrow=primarytail->row-1; + costs=tilecosts; + flows=tileflows; + calccostnrow=nrow; + } }else{ /* upward arc */ - primaryarcdir=-1; - if(primarytail->col==0){ /* left edge */ - if(tilecol==0){ - zerocost=TRUE; - }else{ - primaryarcrow=primarytail->row-1; - primaryarccol=0; - costs=leftedgecosts; - flows=leftedgeflows; - calccostnrow=0; - } - }else if(primarytail->col==nncol-1){ /* right edge */ - if(tilecol==ntilecol-1){ - zerocost=TRUE; - }else{ - primaryarcrow=primarytail->row-1; - primaryarccol=0; - costs=rightedgecosts; - flows=rightedgeflows; - calccostnrow=0; - } - }else{ /* normal arc */ - primaryarcrow=primarytail->row+nrow-2; - primaryarccol=primarytail->col-1; - costs=tilecosts; - flows=tileflows; - calccostnrow=nrow; - } + primaryarcdir=-1; + if(primarytail->col==0){ /* left edge */ + if(tilecol==0){ + zerocost=TRUE; + }else{ + primaryarcrow=primarytail->row-1; + primaryarccol=0; + costs=leftedgecosts; + flows=leftedgeflows; + calccostnrow=0; + } + }else if(primarytail->col==nncol-1){ /* right edge */ + if(tilecol==ntilecol-1){ + zerocost=TRUE; + }else{ + primaryarcrow=primarytail->row-1; + primaryarccol=0; + costs=rightedgecosts; + flows=rightedgeflows; + calccostnrow=0; + } + }else{ /* normal arc */ + primaryarcrow=primarytail->row+nrow-2; + primaryarccol=primarytail->col-1; + costs=tilecosts; + flows=tileflows; + calccostnrow=nrow; + } } /* keep absolute cost of arc to the previous node */ if(!zerocost){ - flows[primaryarcrow][primaryarccol]-=primaryarcdir*arroffset; - nomcost=EvalCost(costs,flows,primaryarcrow,primaryarccol,calccostnrow, - params); - for(nflow=1;nflow<=flowmax;nflow++){ - flows[primaryarcrow][primaryarccol]+=(primaryarcdir*nflow); - poscost=EvalCost(costs,flows,primaryarcrow,primaryarccol, - calccostnrow,params); - flows[primaryarcrow][primaryarccol]-=(2*primaryarcdir*nflow); - negcost=EvalCost(costs,flows,primaryarcrow,primaryarccol, - calccostnrow,params); - flows[primaryarcrow][primaryarccol]+=(primaryarcdir*nflow); - templongdouble=(scndrycostarr[nflow]+(poscost-nomcost)); - if(templongdouble>LARGELONG){ - scndrycostarr[nflow]=LARGELONG; - }else if(templongdouble<-LARGELONG){ - scndrycostarr[nflow]=-LARGELONG; - }else{ - scndrycostarr[nflow]+=(poscost-nomcost); - } - templongdouble=(scndrycostarr[nflow+flowmax]+(negcost-nomcost)); - if(templongdouble>LARGELONG){ - scndrycostarr[nflow+flowmax]=LARGELONG; - }else if(templongdouble<-LARGELONG){ - scndrycostarr[nflow+flowmax]=-LARGELONG; - }else{ - scndrycostarr[nflow+flowmax]+=(negcost-nomcost); - } - } - flows[primaryarcrow][primaryarccol]+=primaryarcdir*arroffset; - if(params->costmode==TOPO || params->costmode==DEFO){ - sigsq=((costT **)costs)[primaryarcrow][primaryarccol].sigsq; - }else if(params->costmode==SMOOTH){ - sigsq=((smoothcostT **)costs)[primaryarcrow][primaryarccol].sigsq; - } - sumsigsqinv+=(1.0/sigsq); + + /* accumulate incremental cost in table for each nflow increment */ + /* offset flow in flow array temporarily by arroffset then undo below */ + flows[primaryarcrow][primaryarccol]-=primaryarcdir*arroffset; + nomcost=EvalCost(costs,flows,primaryarcrow,primaryarccol,calccostnrow, + params); + for(nflow=1;nflow<=flowmax;nflow++){ + flows[primaryarcrow][primaryarccol]+=(primaryarcdir*nflow); + poscost=EvalCost(costs,flows,primaryarcrow,primaryarccol, + calccostnrow,params); + flows[primaryarcrow][primaryarccol]-=(2*primaryarcdir*nflow); + negcost=EvalCost(costs,flows,primaryarcrow,primaryarccol, + calccostnrow,params); + flows[primaryarcrow][primaryarccol]+=(primaryarcdir*nflow); + tempdouble=(scndrycostarr[nflow]+(poscost-nomcost)); + if(tempdouble>LARGEINT){ + scndrycostarr[nflow]=LARGEINT; + }else if(tempdouble<-LARGEINT){ + scndrycostarr[nflow]=-LARGEINT; + }else{ + scndrycostarr[nflow]+=(poscost-nomcost); + } + tempdouble=(scndrycostarr[nflow+flowmax]+(negcost-nomcost)); + if(tempdouble>LARGEINT){ + scndrycostarr[nflow+flowmax]=LARGEINT; + }else if(tempdouble<-LARGEINT){ + scndrycostarr[nflow+flowmax]=-LARGEINT; + }else{ + scndrycostarr[nflow+flowmax]+=(negcost-nomcost); + } + } + flows[primaryarcrow][primaryarccol]+=primaryarcdir*arroffset; + + /* accumulate term to be used for cost growth beyond table bounds */ + if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){ + sigsq=((costT **)costs)[primaryarcrow][primaryarccol].sigsq; + }else if(CalcCost==CalcCostSmooth){ + sigsq=((smoothcostT **)costs)[primaryarcrow][primaryarccol].sigsq; + }else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1 + || CalcCost==CalcCostL2 || CalcCost==CalcCostLP){ + minweight=((short **)costs)[primaryarcrow][primaryarccol]; + if(minweight<1){ + sigsq=LARGESHORT; + }else{ + sigsq=1.0/(double )minweight; + } + }else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir + || CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){ + minweight=LMin(((bidircostT **)costs)[primaryarcrow][primaryarccol] + .posweight, + ((bidircostT **)costs)[primaryarcrow][primaryarccol] + .negweight); + if(minweight<1){ + sigsq=LARGESHORT; + }else{ + sigsq=1.0/(double )minweight; + } + } + if(sigsqgroup==ONTREE){ - break; + break; } /* move up the tree */ @@ -2600,16 +3227,29 @@ void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, /* find flow index with minimum cost */ mincost=0; + maxcost=0; mincostflow=0; for(nflow=1;nflow<=flowmax;nflow++){ if(scndrycostarr[nflow]maxcost){ + maxcost=scndrycostarr[nflow]; + } + if(scndrycostarr[flowmax+nflow]>maxcost){ + maxcost=scndrycostarr[flowmax+nflow]; + } + } + + /* if cost was all zero, treat as zero cost arc */ + if(maxcost==mincost){ + zerocost=TRUE; + sumsigsqinv=0; } /* break if cost array adequately centered on minimum cost flow */ @@ -2634,33 +3274,37 @@ void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, /* so any possible improvements should have been made by primary solver */ if(primaryhead==primarytail){ free(scndrycostarr); - return; + return(0); } - /* see if we have a secondary arc on the edge of the full-sized array */ /* these arcs have zero cost since the edge is treated as a single node */ + /* secondary arcs whose primary arcs all have zero cost are also zeroed */ if(zerocost){ /* set sum of standard deviations to indicate zero-cost secondary arc */ + scndrycostarr[0]=0; + for(nflow=1;nflow<=2*flowmax;nflow++){ + scndrycostarr[nflow]=0; + } scndrycostarr[2*flowmax+1]=ZEROCOSTARC; }else{ /* give extra weight to arcs on tile edges */ if((primaryhead->row==primarytail->row - && (primaryhead->row==0 || primaryhead->row==nnrow-1)) + && (primaryhead->row==0 || primaryhead->row==nnrow-1)) || (primaryhead->col==primarytail->col - && (primaryhead->col==0 || primaryhead->col==nncol-1))){ + && (primaryhead->col==0 || primaryhead->col==nncol-1))){ for(nflow=1;nflow<=2*flowmax;nflow++){ - tempdouble=scndrycostarr[nflow]*tileedgearcweight; - if(tempdouble>LARGELONG){ - scndrycostarr[nflow]=LARGELONG; - }else if(tempdouble<-LARGELONG){ - scndrycostarr[nflow]=-LARGELONG; - }else{ - scndrycostarr[nflow]=LRound(tempdouble); - } + tempdouble=scndrycostarr[nflow]*tileedgearcweight; + if(tempdouble>LARGEINT){ + scndrycostarr[nflow]=LARGEINT; + }else if(tempdouble<-LARGEINT){ + scndrycostarr[nflow]=-LARGEINT; + }else{ + scndrycostarr[nflow]=LRound(tempdouble); + } } sumsigsqinv*=tileedgearcweight; @@ -2668,10 +3312,10 @@ void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, /* store sum of primary cost variances at end of secondary cost array */ tempdouble=sumsigsqinv*nshortcycle*nshortcycle; - if(tempdoublerow==0 && tilerow!=0){ scndrytail=FindScndryNode(scndrynodes,nodesupp, - (tilerow-1)*ntilecol+tilecol, - prevnrow,primarytail->col); + (tilerow-1)*ntilecol+tilecol, + prevnrow,primarytail->col); }else if(primarytail->col==0 && tilecol!=0){ scndrytail=FindScndryNode(scndrynodes,nodesupp, - tilerow*ntilecol+(tilecol-1), - primarytail->row,prevncol); + tilerow*ntilecol+(tilecol-1), + primarytail->row,prevncol); }else{ scndrytail=FindScndryNode(scndrynodes,nodesupp,tilenum, - primarytail->row,primarytail->col); + primarytail->row,primarytail->col); } if(primaryhead->row==0 && tilerow!=0){ scndryhead=FindScndryNode(scndrynodes,nodesupp, - (tilerow-1)*ntilecol+tilecol, - prevnrow,primaryhead->col); + (tilerow-1)*ntilecol+tilecol, + prevnrow,primaryhead->col); }else if(primaryhead->col==0 && tilecol!=0){ scndryhead=FindScndryNode(scndrynodes,nodesupp, - tilerow*ntilecol+(tilecol-1), - primaryhead->row,prevncol); + tilerow*ntilecol+(tilecol-1), + primaryhead->row,prevncol); }else{ scndryhead=FindScndryNode(scndrynodes,nodesupp,tilenum, - primaryhead->row,primaryhead->col); + primaryhead->row,primaryhead->col); } /* see if there is already arc between secondary head, tail */ @@ -2710,104 +3354,110 @@ void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, for(i=0;irow==primaryhead->row - && tempnode->col==primaryhead->col) + && tempnode->row==primaryhead->row + && tempnode->col==primaryhead->col) || (nodesupp[row][col].outarcs[i]!=NULL - && tempnode->row==scndryhead->row - && tempnode->col==scndryhead->col)){ + && tempnode->row==scndryhead->row + && tempnode->col==scndryhead->col)){ /* see if secondary arc traverses only one primary arc */ primarydummy=primaryhead->pred; if(primarydummy->group!=ONTREE){ - /* arc already exists, free memory for cost array (will trace again) */ - free(scndrycostarr); - - /* set up dummy node */ - primarydummy->group=ONTREE; - nnewnodes=++(*nnewnodesptr); - scndrynodes[tilenum]=(nodeT *)ReAlloc(scndrynodes[tilenum], - nnewnodes*sizeof(nodeT)); - scndrydummy=&scndrynodes[tilenum][nnewnodes-1]; - nodesupp[tilenum]=(nodesuppT *)ReAlloc(nodesupp[tilenum], - nnewnodes*sizeof(nodesuppT)); - suppdummy=&nodesupp[tilenum][nnewnodes-1]; - scndrydummy->row=tilenum; - scndrydummy->col=nnewnodes-1; - suppdummy->row=primarydummy->row; - suppdummy->col=primarydummy->col; - suppdummy->noutarcs=0; - suppdummy->neighbornodes=NULL; - suppdummy->outarcs=NULL; - - /* recursively call TraceSecondaryArc() to set up arcs */ - TraceSecondaryArc(primarydummy,scndrynodes,nodesupp,scndryarcs, - scndrycosts,nnewnodesptr,nnewarcsptr,tilerow,tilecol, - flowmax,nrow,ncol,prevnrow,prevncol,params,tilecosts, - rightedgecosts,loweredgecosts,leftedgecosts, - upperedgecosts,tileflows,rightedgeflows, - loweredgeflows,leftedgeflows,upperedgeflows, - updatednontilenodesptr,nupdatednontilenodesptr, - updatednontilenodesizeptr,inontilenodeoutarcptr, - totarclenptr); - TraceSecondaryArc(primaryhead,scndrynodes,nodesupp,scndryarcs, - scndrycosts,nnewnodesptr,nnewarcsptr,tilerow,tilecol, - flowmax,nrow,ncol,prevnrow,prevncol,params,tilecosts, - rightedgecosts,loweredgecosts,leftedgecosts, - upperedgecosts,tileflows,rightedgeflows, - loweredgeflows,leftedgeflows,upperedgeflows, - updatednontilenodesptr,nupdatednontilenodesptr, - updatednontilenodesizeptr,inontilenodeoutarcptr, - totarclenptr); + /* arc already exists, free memory for cost array (will trace again) */ + free(scndrycostarr); + + /* set up dummy node */ + primarydummy->group=ONTREE; + nnewnodes=++(*nnewnodesptr); + scndrynodes[tilenum]=(nodeT *)ReAlloc(scndrynodes[tilenum], + nnewnodes*sizeof(nodeT)); + scndrydummy=&scndrynodes[tilenum][nnewnodes-1]; + nodesupp[tilenum]=(nodesuppT *)ReAlloc(nodesupp[tilenum], + nnewnodes*sizeof(nodesuppT)); + suppdummy=&nodesupp[tilenum][nnewnodes-1]; + scndrydummy->row=tilenum; + scndrydummy->col=nnewnodes-1; + suppdummy->row=primarydummy->row; + suppdummy->col=primarydummy->col; + suppdummy->noutarcs=0; + suppdummy->neighbornodes=NULL; + suppdummy->outarcs=NULL; + + /* recursively call TraceSecondaryArc() to set up arcs */ + TraceSecondaryArc(primarydummy,scndrynodes,nodesupp,scndryarcs, + scndrycosts,nnewnodesptr,nnewarcsptr,tilerow,tilecol, + flowmax,nrow,ncol,prevnrow,prevncol,params,tilecosts, + rightedgecosts,loweredgecosts,leftedgecosts, + upperedgecosts,tileflows,rightedgeflows, + loweredgeflows,leftedgeflows,upperedgeflows, + updatednontilenodesptr,nupdatednontilenodesptr, + updatednontilenodesizeptr,inontilenodeoutarcptr, + totarclenptr); + TraceSecondaryArc(primaryhead,scndrynodes,nodesupp,scndryarcs, + scndrycosts,nnewnodesptr,nnewarcsptr,tilerow,tilecol, + flowmax,nrow,ncol,prevnrow,prevncol,params,tilecosts, + rightedgecosts,loweredgecosts,leftedgecosts, + upperedgecosts,tileflows,rightedgeflows, + loweredgeflows,leftedgeflows,upperedgeflows, + updatednontilenodesptr,nupdatednontilenodesptr, + updatednontilenodesizeptr,inontilenodeoutarcptr, + totarclenptr); }else{ - /* only one primary arc; just delete other secondary arc */ - /* find existing secondary arc (must be in this tile) */ - /* swap direction of existing secondary arc if necessary */ - arcnum=0; - while(TRUE){ - if(scndryarcs[tilenum][arcnum].from==primarytail - && scndryarcs[tilenum][arcnum].to==primaryhead){ - break; - }else if(scndryarcs[tilenum][arcnum].from==primaryhead - && scndryarcs[tilenum][arcnum].to==primarytail){ - scndryarcs[tilenum][arcnum].from=primarytail; - scndryarcs[tilenum][arcnum].to=primaryhead; - break; - } - arcnum++; - } - - /* assign cost of this secondary arc to existing secondary arc */ - free(scndrycosts[tilenum][arcnum]); - scndrycosts[tilenum][arcnum]=scndrycostarr; - - /* update direction data in secondary arc structure */ - if(primarytail->col==primaryhead->col+1){ - scndryarcs[tilenum][arcnum].fromdir=RIGHT; - }else if(primarytail->row==primaryhead->row+1){ - scndryarcs[tilenum][arcnum].fromdir=DOWN; - }else if(primarytail->col==primaryhead->col-1){ - scndryarcs[tilenum][arcnum].fromdir=LEFT; - }else{ - scndryarcs[tilenum][arcnum].fromdir=UP; - } + /* only one primary arc; just delete other secondary arc */ + /* find existing secondary arc (must be in this tile) */ + /* swap direction of existing secondary arc if necessary */ + arcnum=0; + while(TRUE){ + if(scndryarcs[tilenum][arcnum].from==primarytail + && scndryarcs[tilenum][arcnum].to==primaryhead){ + break; + }else if(scndryarcs[tilenum][arcnum].from==primaryhead + && scndryarcs[tilenum][arcnum].to==primarytail){ + scndryarcs[tilenum][arcnum].from=primarytail; + scndryarcs[tilenum][arcnum].to=primaryhead; + break; + } + arcnum++; + } + + /* assign cost of this secondary arc to existing secondary arc */ + free(scndrycosts[tilenum][arcnum]); + scndrycosts[tilenum][arcnum]=scndrycostarr; + + /* update direction data in secondary arc structure */ + if(primarytail->col==primaryhead->col+1){ + scndryarcs[tilenum][arcnum].fromdir=RIGHT; + }else if(primarytail->row==primaryhead->row+1){ + scndryarcs[tilenum][arcnum].fromdir=DOWN; + }else if(primarytail->col==primaryhead->col-1){ + scndryarcs[tilenum][arcnum].fromdir=LEFT; + }else{ + scndryarcs[tilenum][arcnum].fromdir=UP; + } } /* we're done */ - return; + return(0); } } /* set up secondary arc datastructures */ nnewarcs=++(*nnewarcsptr); + if(nnewarcs > SHRT_MAX){ + fflush(NULL); + fprintf(sp0,"Exceeded maximum number of secondary arcs\n" + "Decrease TILECOSTTHRESH and/or increase MINREGIONSIZE\n"); + exit(ABNORMAL_EXIT); + } scndryarcs[tilenum]=(scndryarcT *)ReAlloc(scndryarcs[tilenum], - nnewarcs*sizeof(scndryarcT)); + nnewarcs*sizeof(scndryarcT)); newarc=&scndryarcs[tilenum][nnewarcs-1]; newarc->arcrow=tilenum; newarc->arccol=nnewarcs-1; scndrycosts[tilenum]=(long **)ReAlloc(scndrycosts[tilenum], - nnewarcs*sizeof(long *)); + nnewarcs*sizeof(long *)); scndrycosts[tilenum][nnewarcs-1]=scndrycostarr; /* update secondary node data */ @@ -2817,25 +3467,25 @@ void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, supphead=&nodesupp[scndryhead->row][scndryhead->col]; supptail->noutarcs++; supptail->neighbornodes=(nodeT **)ReAlloc(supptail->neighbornodes, - supptail->noutarcs - *sizeof(nodeT *)); + supptail->noutarcs + *sizeof(nodeT *)); supptail->neighbornodes[supptail->noutarcs-1]=primaryhead; primarytail->level=scndrytail->row; primarytail->incost=scndrytail->col; supptail->outarcs=(scndryarcT **)ReAlloc(supptail->outarcs, - supptail->noutarcs - *sizeof(scndryarcT *)); + supptail->noutarcs + *sizeof(scndryarcT *)); supptail->outarcs[supptail->noutarcs-1]=NULL; supphead->noutarcs++; supphead->neighbornodes=(nodeT **)ReAlloc(supphead->neighbornodes, - supphead->noutarcs - *sizeof(nodeT *)); + supphead->noutarcs + *sizeof(nodeT *)); supphead->neighbornodes[supphead->noutarcs-1]=primarytail; primaryhead->level=scndryhead->row; primaryhead->incost=scndryhead->col; supphead->outarcs=(scndryarcT **)ReAlloc(supphead->outarcs, - supphead->noutarcs - *sizeof(scndryarcT *)); + supphead->noutarcs + *sizeof(scndryarcT *)); supphead->outarcs[supphead->noutarcs-1]=NULL; /* keep track of updated secondary nodes that were not in this tile */ @@ -2843,11 +3493,11 @@ void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, if(++(*nupdatednontilenodesptr)==(*updatednontilenodesizeptr)){ (*updatednontilenodesizeptr)+=INITARRSIZE; (*updatednontilenodesptr)=(nodeT **)ReAlloc((*updatednontilenodesptr), - (*updatednontilenodesizeptr) - *sizeof(nodeT *)); + (*updatednontilenodesizeptr) + *sizeof(nodeT *)); (*inontilenodeoutarcptr)=(short *)ReAlloc((*inontilenodeoutarcptr), - (*updatednontilenodesizeptr) - *sizeof(short)); + (*updatednontilenodesizeptr) + *sizeof(short)); } (*updatednontilenodesptr)[*nupdatednontilenodesptr-1]=scndrytail; (*inontilenodeoutarcptr)[*nupdatednontilenodesptr-1]=supptail->noutarcs-1; @@ -2856,11 +3506,11 @@ void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, if(++(*nupdatednontilenodesptr)==(*updatednontilenodesizeptr)){ (*updatednontilenodesizeptr)+=INITARRSIZE; (*updatednontilenodesptr)=(nodeT **)ReAlloc((*updatednontilenodesptr), - (*updatednontilenodesizeptr) - *sizeof(nodeT *)); + (*updatednontilenodesizeptr) + *sizeof(nodeT *)); (*inontilenodeoutarcptr)=(short *)ReAlloc((*inontilenodeoutarcptr), - (*updatednontilenodesizeptr) - *sizeof(short)); + (*updatednontilenodesizeptr) + *sizeof(short)); } (*updatednontilenodesptr)[*nupdatednontilenodesptr-1]=scndryhead; (*inontilenodeoutarcptr)[*nupdatednontilenodesptr-1]=supphead->noutarcs-1; @@ -2885,14 +3535,18 @@ void TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes, /* add number of primary arcs in secondary arc to counter */ (*totarclenptr)+=arclen; + /* done */ + return(0); + } /* function: FindScndryNode() * -------------------------- */ +static nodeT *FindScndryNode(nodeT **scndrynodes, nodesuppT **nodesupp, - long tilenum, long primaryrow, long primarycol){ + long tilenum, long primaryrow, long primarycol){ long nodenum; nodesuppT *nodesuppptr; @@ -2903,7 +3557,7 @@ nodeT *FindScndryNode(nodeT **scndrynodes, nodesuppT **nodesupp, /* loop over all nodes in the tile until we find a match */ nodenum=0; while(nodesuppptr[nodenum].row!=primaryrow - || nodesuppptr[nodenum].col!=primarycol){ + || nodesuppptr[nodenum].col!=primarycol){ nodenum++; } return(&scndrynodes[tilenum][nodenum]); @@ -2913,11 +3567,12 @@ nodeT *FindScndryNode(nodeT **scndrynodes, nodesuppT **nodesupp, /* function: IntegrateSecondaryFlows() * ----------------------------------- */ -void IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes, - nodesuppT **nodesupp, scndryarcT **scndryarcs, - short *nscndryarcs, short **scndryflows, - short **bulkoffsets, outfileT *outfiles, - paramT *params){ +static +int IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes, + nodesuppT **nodesupp, scndryarcT **scndryarcs, + int *nscndryarcs, short **scndryflows, + short **bulkoffsets, outfileT *outfiles, + paramT *params){ FILE *outfp; float **unwphase, **tileunwphase, **mag, **tilemag; @@ -2935,6 +3590,15 @@ void IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes, outfileT readtileoutfiles[1]; + /* initialize stack structures to zero for good measure */ + memset(readtileparams,0,sizeof(tileparamT)); + memset(readtileoutfiles,0,sizeof(outfileT)); + memset(realoutfile,0,MAXSTRLEN); + memset(readfile,0,MAXSTRLEN); + memset(tempstring,0,MAXSTRLEN); + memset(path,0,MAXSTRLEN); + memset(basename,0,MAXSTRLEN); + /* set up */ fprintf(sp1,"Integrating secondary flows\n"); ntilerow=params->ntilerow; @@ -2945,6 +3609,7 @@ void IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes, nj=ceil((linelen+(ntilecol-1)*colovrlp)/(double )ntilecol); nextcoloffset=0; writeerror=FALSE; + nrow=0; /* get memory */ regions=(short **)Get2DMem(ni,nj,sizeof(short *),sizeof(short)); @@ -2960,7 +3625,7 @@ void IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes, if(params->flipphasesign){ for(row=0;rowfirstcol; readtilenlines=readtileparams->nrow; readtilelinelen=readtileparams->ncol; /* set tile read parameters */ SetTileReadParams(readtileparams,readtilenlines,readtilelinelen, - tilerow,tilecol,nlines,linelen,params); + tilerow,tilecol,nlines,linelen,params); colstart+=readtileparams->firstcol; nrow=readtileparams->nrow; ncol=readtileparams->ncol; @@ -2995,39 +3660,39 @@ void IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes, /* phase sign not flipped for positive baseline */ /* since flow will be flipped if necessary */ if(TMPTILEOUTFORMAT==ALT_LINE_DATA){ - ReadAltLineFile(&tilemag,&tileunwphase,readtileoutfiles->outfile, - readtilelinelen,readtilenlines,readtileparams); + ReadAltLineFile(&tilemag,&tileunwphase,readtileoutfiles->outfile, + readtilelinelen,readtilenlines,readtileparams); }else if(TMPTILEOUTFORMAT==FLOAT_DATA){ - Read2DArray((void ***)&tileunwphase,readtileoutfiles->outfile, - readtilelinelen,readtilenlines,readtileparams, - sizeof(float *),sizeof(float)); + Read2DArray((void ***)&tileunwphase,readtileoutfiles->outfile, + readtilelinelen,readtilenlines,readtileparams, + sizeof(float *),sizeof(float)); } - + /* read regions */ ParseFilename(outfiles->outfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld%s", - params->tiledir,TMPTILEROOT,basename,tilerow,tilecol, - readtilelinelen,REGIONSUFFIX); + params->tiledir,TMPTILEROOT,basename,tilerow,tilecol, + readtilelinelen,REGIONSUFFIX); StrNCopy(readfile,tempstring,MAXSTRLEN); Read2DArray((void ***)®ions,readfile,readtilelinelen,readtilenlines, - readtileparams,sizeof(short *),sizeof(short)); + readtileparams,sizeof(short *),sizeof(short)); /* remove temporary files unless told so save them */ if(params->rmtmptile){ - unlink(readtileoutfiles->outfile); - unlink(readfile); + unlink(readtileoutfiles->outfile); + unlink(readfile); } /* zero out primary flow array */ for(row=0;row<2*nrow+1;row++){ - if(rowoutfileformat==ALT_LINE_DATA){ - if(fwrite(mag[row],sizeof(float),linelen,outfp)!=linelen - || fwrite(unwphase[row],sizeof(float),linelen,outfp)!=linelen){ - writeerror=TRUE; - break; - } + if(fwrite(mag[row],sizeof(float),linelen,outfp)!=linelen + || fwrite(unwphase[row],sizeof(float),linelen,outfp)!=linelen){ + writeerror=TRUE; + break; + } }else if(outfiles->outfileformat==ALT_SAMPLE_DATA){ - for(col=0;colrow==tilenum){ - primaryfromrow=nodesupp[scndryfrom->row][scndryfrom->col].row; - primaryfromcol=nodesupp[scndryfrom->row][scndryfrom->col].col; + primaryfromrow=nodesupp[scndryfrom->row][scndryfrom->col].row; + primaryfromcol=nodesupp[scndryfrom->row][scndryfrom->col].col; }else if(scndryfrom->row==tilenum-ntilecol){ - primaryfromrow=0; - primaryfromcol=nodesupp[scndryfrom->row][scndryfrom->col].col; + primaryfromrow=0; + primaryfromcol=nodesupp[scndryfrom->row][scndryfrom->col].col; }else if(scndryfrom->row==tilenum-1){ - primaryfromrow=nodesupp[scndryfrom->row][scndryfrom->col].row; - primaryfromcol=0; + primaryfromrow=nodesupp[scndryfrom->row][scndryfrom->col].row; + primaryfromcol=0; }else{ - primaryfromrow=0; - primaryfromcol=0; + primaryfromrow=0; + primaryfromcol=0; } if(scndryto->row==tilenum){ - thisrow=nodesupp[scndryto->row][scndryto->col].row; - thiscol=nodesupp[scndryto->row][scndryto->col].col; + thisrow=nodesupp[scndryto->row][scndryto->col].row; + thiscol=nodesupp[scndryto->row][scndryto->col].col; }else if(scndryto->row==tilenum-ntilecol){ - thisrow=0; - thiscol=nodesupp[scndryto->row][scndryto->col].col; + thisrow=0; + thiscol=nodesupp[scndryto->row][scndryto->col].col; }else if(scndryto->row==tilenum-1){ - thisrow=nodesupp[scndryto->row][scndryto->col].row; - thiscol=0; + thisrow=nodesupp[scndryto->row][scndryto->col].row; + thiscol=0; }else{ - thisrow=0; - thiscol=0; + thisrow=0; + thiscol=0; } /* set initial direction out of secondary arc head */ switch(scndryarcs[tilenum][arcnum].fromdir){ case RIGHT: - nextrow=thisrow; - nextcol=thiscol+1; - tileflows[thisrow][thiscol]-=nflow; - break; + nextrow=thisrow; + nextcol=thiscol+1; + tileflows[thisrow][thiscol]-=nflow; + break; case DOWN: - nextrow=thisrow+1; - nextcol=thiscol; - tileflows[nnrow+thisrow][thiscol]-=nflow; - break; + nextrow=thisrow+1; + nextcol=thiscol; + tileflows[nnrow+thisrow][thiscol]-=nflow; + break; case LEFT: - nextrow=thisrow; - nextcol=thiscol-1; - tileflows[thisrow][thiscol-1]+=nflow; - break; + nextrow=thisrow; + nextcol=thiscol-1; + tileflows[thisrow][thiscol-1]+=nflow; + break; default: - nextrow=thisrow-1; - nextcol=thiscol; - tileflows[nnrow+thisrow-1][thiscol]+=nflow; - break; + nextrow=thisrow-1; + nextcol=thiscol; + tileflows[nnrow+thisrow-1][thiscol]+=nflow; + break; } /* use region data to trace path between secondary from, to */ while(!(nextrow==primaryfromrow && nextcol==primaryfromcol)){ - /* move to next node */ - prevrow=thisrow; - prevcol=thiscol; - thisrow=nextrow; - thiscol=nextcol; + /* move to next node */ + prevrow=thisrow; + prevcol=thiscol; + thisrow=nextrow; + thiscol=nextcol; - /* check rightward arc */ - if(thiscol!=nncol-1){ - if(thisrow==0 || thisrow==nnrow-1 - || regions[thisrow-1][thiscol]!=regions[thisrow][thiscol]){ - if(!(thisrow==prevrow && thiscol+1==prevcol)){ - tileflows[thisrow][thiscol]-=nflow; - nextcol++; - } - } - } - - /* check downward arc */ - if(thisrow!=nnrow-1){ - if(thiscol==0 || thiscol==nncol-1 - || regions[thisrow][thiscol]!=regions[thisrow][thiscol-1]){ - if(!(thisrow+1==prevrow && thiscol==prevcol)){ - tileflows[nnrow+thisrow][thiscol]-=nflow; - nextrow++; - } - } - } + /* check rightward arc */ + if(thiscol!=nncol-1){ + if(thisrow==0 || thisrow==nnrow-1 + || regions[thisrow-1][thiscol]!=regions[thisrow][thiscol]){ + if(!(thisrow==prevrow && thiscol+1==prevcol)){ + tileflows[thisrow][thiscol]-=nflow; + nextcol++; + } + } + } + + /* check downward arc */ + if(thisrow!=nnrow-1){ + if(thiscol==0 || thiscol==nncol-1 + || regions[thisrow][thiscol]!=regions[thisrow][thiscol-1]){ + if(!(thisrow+1==prevrow && thiscol==prevcol)){ + tileflows[nnrow+thisrow][thiscol]-=nflow; + nextrow++; + } + } + } - /* check leftward arc */ - if(thiscol!=0){ - if(thisrow==0 || thisrow==nnrow-1 - || regions[thisrow][thiscol-1]!=regions[thisrow-1][thiscol-1]){ - if(!(thisrow==prevrow && thiscol-1==prevcol)){ - tileflows[thisrow][thiscol-1]+=nflow; - nextcol--; - } - } - } - - /* check upward arc */ - if(thisrow!=0){ - if(thiscol==0 || thiscol==nncol-1 - || regions[thisrow-1][thiscol-1]!=regions[thisrow-1][thiscol]){ - if(!(thisrow-1==prevrow && thiscol==prevcol)){ - tileflows[nnrow+thisrow-1][thiscol]+=nflow; - nextrow--; - } - } - } + /* check leftward arc */ + if(thiscol!=0){ + if(thisrow==0 || thisrow==nnrow-1 + || regions[thisrow][thiscol-1]!=regions[thisrow-1][thiscol-1]){ + if(!(thisrow==prevrow && thiscol-1==prevcol)){ + tileflows[thisrow][thiscol-1]+=nflow; + nextcol--; + } + } + } + + /* check upward arc */ + if(thisrow!=0){ + if(thiscol==0 || thiscol==nncol-1 + || regions[thisrow-1][thiscol-1]!=regions[thisrow-1][thiscol]){ + if(!(thisrow-1==prevrow && thiscol==prevcol)){ + tileflows[nnrow+thisrow-1][thiscol]+=nflow; + nextrow--; + } + } + } } } } + return(0); } + + +/* function: AssembleTileConnComps() + * --------------------------------- + * Assemble conntected components per tile. + */ +static +int AssembleTileConnComps(long linelen, long nlines, + outfileT *outfiles, paramT *params){ + + int ipass; + long k; + long row, col, colstart, nrow, ncol; + long readtilelinelen, readtilenlines; + long tilerow, tilecol, ntilerow, ntilecol, rowovrlp, colovrlp; + long ni, nj, tilenum; + unsigned int iconncomp, iconncompmax; + long ntileconncomp, nconncomp; + long ntileconncompmem, nconncompmem, nmemold; + char realoutfile[MAXSTRLEN], readfile[MAXSTRLEN], tempstring[MAXTMPSTRLEN]; + char path[MAXSTRLEN], basename[MAXSTRLEN]; + signed char writeerror; + tileparamT readtileparams[1]; + outfileT readtileoutfiles[1]; + unsigned int *tilemapping; + unsigned int **tileconncomps, **tilerowconncomps; + unsigned char **ucharbuf; + unsigned char *ucharoutbuf; + conncompsizeT *tileconncompsizes, *conncompsizes; + FILE *outfp; + + + /* initialize stack structures to zero for good measure */ + memset(readtileparams,0,sizeof(tileparamT)); + memset(readtileoutfiles,0,sizeof(outfileT)); + memset(realoutfile,0,MAXSTRLEN); + memset(readfile,0,MAXSTRLEN); + memset(tempstring,0,MAXSTRLEN); + memset(path,0,MAXSTRLEN); + memset(basename,0,MAXSTRLEN); + + /* set up */ + fprintf(sp1,"Assembling tile connected components\n"); + ntilerow=params->ntilerow; + ntilecol=params->ntilecol; + rowovrlp=params->rowovrlp; + colovrlp=params->colovrlp; + ni=ceil((nlines+(ntilerow-1)*rowovrlp)/(double )ntilerow); + nj=ceil((linelen+(ntilecol-1)*colovrlp)/(double )ntilecol); + writeerror=FALSE; + nrow=0; + conncompsizes=NULL; + nconncomp=0; + nconncompmem=0; + tileconncompsizes=NULL; + ntileconncompmem=0; + iconncompmax=0; + + /* get memory */ + tileconncomps=(unsigned int **)Get2DMem(ni,nj,sizeof(unsigned int *), + sizeof(unsigned int)); + tilerowconncomps=(unsigned int **)Get2DMem(ni,linelen,sizeof(unsigned int *), + sizeof(unsigned int)); + ucharbuf=(unsigned char **)Get2DMem(ni,nj,sizeof(unsigned char *), + sizeof(unsigned char)); + ucharoutbuf=(unsigned char *)MAlloc(linelen*sizeof(unsigned char)); + tilemapping=NULL; + + /* open output file */ + outfp=OpenOutputFile(outfiles->conncompfile,realoutfile); + + /* do two passes looping over all tiles */ + for(ipass=0;ipass<2;ipass++){ + + /* process each tile row */ + for(tilerow=0;tilerowfirstcol; + readtilenlines=readtileparams->nrow; + readtilelinelen=readtileparams->ncol; + + /* set tile read parameters */ + SetTileReadParams(readtileparams,readtilenlines,readtilelinelen, + tilerow,tilecol,nlines,linelen,params); + colstart+=readtileparams->firstcol; + nrow=readtileparams->nrow; + ncol=readtileparams->ncol; + + /* set tile number */ + tilenum=tilerow*ntilecol+tilecol; + + /* read connected components for tile */ + if(params->conncompouttype==CONNCOMPOUTTYPEUCHAR){ + Read2DArray((void ***)&ucharbuf,readtileoutfiles->conncompfile, + readtilelinelen,readtilenlines,readtileparams, + sizeof(unsigned char *),sizeof(unsigned char)); + for(row=0;rowconncompfile, + readtilelinelen,readtilenlines,readtileparams, + sizeof(unsigned int *),sizeof(unsigned int)); + } + + /* see which pass we are in */ + if(ipass==0){ + + /* first pass */ + + /* initialize tileconncomps array for this tile */ + ntileconncomp=0; + for(k=0;k0){ + + /* get more memory for tile conncompsizeT array if needed */ + while(iconncomp>ntileconncompmem){ + nmemold=ntileconncompmem; + ntileconncompmem+=CONNCOMPMEMINCR; + tileconncompsizes + =(conncompsizeT *)ReAlloc(tileconncompsizes, + (ntileconncompmem + *sizeof(conncompsizeT))); + for(k=nmemold;kiconncompmax){ + iconncompmax=iconncomp; + } + + } + } + } + + /* get more memory for full set of connected components sizes */ + nmemold=nconncompmem; + nconncompmem+=ntileconncomp; + conncompsizes=(conncompsizeT *)ReAlloc(conncompsizes, + (nconncompmem + *sizeof(conncompsizeT))); + + /* store conncomp sizes from tile in full list */ + for(k=0;k0){ + conncompsizes[nconncomp].tilenum=tileconncompsizes[k].tilenum; + conncompsizes[nconncomp].icomptile=tileconncompsizes[k].icomptile; + conncompsizes[nconncomp].icompfull=0; + conncompsizes[nconncomp].npix=tileconncompsizes[k].npix; + nconncomp++; + } + } + + }else{ + + /* second pass */ + + /* build lookup table for tile mapping for this tile */ + /* lookup table index is conncomp number minus one */ + for(k=0;k0){ + tilerowconncomps[row][colstart+col]=tilemapping[iconncomp-1]; + }else{ + tilerowconncomps[row][colstart+col]=0; + } + } + } + + /* remove temporary files unless told so save them */ + if(params->rmtmptile){ + unlink(readtileoutfiles->conncompfile); + } + + } + + } /* end loop over tile columns */ + + /* write out tile row at end of second pass */ + if(ipass>0){ + for(row=0;rowconncompouttype==CONNCOMPOUTTYPEUCHAR){ + for(k=0;kparams->maxncomps){ + nconncomp=params->maxncomps; + } + + /* assign tile mappings */ + for(k=0;k0){ + free(tileconncompsizes); + } + if(nconncompmem>0){ + free(conncompsizes); + } + free(tilemapping); + + /* done */ + return(0); + +} + + +/* function: ConnCompSizeNPixCompare() + * ----------------------------------- + * Compare npix member of conncompsizeT structures pointed to by + * inputs for use with qsort() into descending order. + */ +static +int ConnCompSizeNPixCompare(const void *ptr1, const void *ptr2){ + return(((conncompsizeT *)ptr2)->npix-((conncompsizeT *)ptr1)->npix); +} + + diff --git a/contrib/Snaphu/src/snaphu_util.c b/contrib/Snaphu/src/snaphu_util.c index bb1422d7..db2c7105 100644 --- a/contrib/Snaphu/src/snaphu_util.c +++ b/contrib/Snaphu/src/snaphu_util.c @@ -21,17 +21,30 @@ #include #include #include +#include #include #include #include "snaphu.h" + +/* static (local) function prototypes */ +static +int IsTrue(char *str); +static +int IsFalse(char *str); +static +double ModDiff(double f1, double f2); + + + /* function: IsTrue() * ------------------ * Returns TRUE if the string input is any of TRUE, True, true, 1, * y, Y, yes, YES */ +static int IsTrue(char *str){ if(!strcmp(str,"TRUE") || !strcmp(str,"true") || !strcmp(str,"True") @@ -49,6 +62,7 @@ int IsTrue(char *str){ * Returns FALSE if the string input is any of FALSE, False, false, * 0, n, N, no, NO */ +static int IsFalse(char *str){ if(!strcmp(str,"FALSE") || !strcmp(str,"false") || !strcmp(str,"False") @@ -86,6 +100,7 @@ signed char SetBooleanSignedChar(signed char *boolptr, char *str){ * modulo difference between (-pi,pi]. Assumes that * PI and TWOPI have been defined. */ +static double ModDiff(double f1, double f2){ double f3; @@ -105,7 +120,7 @@ double ModDiff(double f1, double f2){ * Makes sure the passed float array is properly wrapped into the [0,2pi) * interval. */ -void WrapPhase(float **wrappedphase, long nrow, long ncol){ +int WrapPhase(float **wrappedphase, long nrow, long ncol){ long row, col; @@ -114,6 +129,7 @@ void WrapPhase(float **wrappedphase, long nrow, long ncol){ wrappedphase[row][col]-=TWOPI*floor(wrappedphase[row][col]/TWOPI); } } + return(0); } @@ -122,9 +138,9 @@ void WrapPhase(float **wrappedphase, long nrow, long ncol){ * Computes an array of wrapped phase differences in range (across rows). * Input wrapped phase array should be in radians. Output is in cycles. */ -void CalcWrappedRangeDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, - long kperpdpsi, long kpardpsi, - long nrow, long ncol){ +int CalcWrappedRangeDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, + long kperpdpsi, long kpardpsi, + long nrow, long ncol){ long row, col; float **paddpsi; @@ -132,20 +148,22 @@ void CalcWrappedRangeDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, for(col=0;col=0.5){ - dpsi[row][col]-=1.0; + dpsi[row][col]-=1.0; }else if(dpsi[row][col]<-0.5){ - dpsi[row][col]+=1.0; + dpsi[row][col]+=1.0; } } } paddpsi=MirrorPad(dpsi,nrow,ncol-1,(kperpdpsi-1)/2,(kpardpsi-1)/2); if(paddpsi==dpsi){ + fflush(NULL); fprintf(sp0,"Wrapped-gradient averaging box too large " - "for input array size\nAbort\n"); + "for input array size\nAbort\n"); exit(ABNORMAL_EXIT); } BoxCarAvg(avgdpsi,paddpsi,nrow,ncol-1,kperpdpsi,kpardpsi); Free2DArray((void **)paddpsi,nrow+kperpdpsi-1); + return(0); } @@ -155,8 +173,8 @@ void CalcWrappedRangeDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, * Computes an array of wrapped phase differences in range (across rows). * Input wrapped phase array should be in radians. Output is in cycles. */ -void CalcWrappedAzDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, - long kperpdpsi, long kpardpsi, long nrow, long ncol){ +int CalcWrappedAzDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, + long kperpdpsi, long kpardpsi, long nrow, long ncol){ long row, col; float **paddpsi; @@ -164,20 +182,22 @@ void CalcWrappedAzDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, for(col=0;col=0.5){ - dpsi[row][col]-=1.0; + dpsi[row][col]-=1.0; }else if(dpsi[row][col]<-0.5){ - dpsi[row][col]+=1.0; + dpsi[row][col]+=1.0; } } } paddpsi=MirrorPad(dpsi,nrow-1,ncol,(kpardpsi-1)/2,(kperpdpsi-1)/2); if(paddpsi==dpsi){ + fflush(NULL); fprintf(sp0,"Wrapped-gradient averaging box too large " - "for input array size\nAbort\n"); + "for input array size\nAbort\n"); exit(ABNORMAL_EXIT); } BoxCarAvg(avgdpsi,paddpsi,nrow-1,ncol,kpardpsi,kperpdpsi); Free2DArray((void **)paddpsi,nrow-1+kpardpsi-1); + return(0); } @@ -190,8 +210,8 @@ void CalcWrappedAzDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, * Residue array will then have size nrow-1 x ncol-1. Residues will * always be -1, 0, or 1 if wrapped phase is passed in. */ -void CycleResidue(float **phase, signed char **residue, - int nrow, int ncol){ +int CycleResidue(float **phase, signed char **residue, + int nrow, int ncol){ int row, col; float **rowdiff, **coldiff; @@ -213,15 +233,39 @@ void CycleResidue(float **phase, signed char **residue, for(row=0;rowflipphasesign){ for(row=0;rowflipphasesign){ for(row=0;row<2*nrow-1;row++){ if(rowmaxval){ + return(maxval); + }else{ + return(a); + } +} + + /* function: Short2DRowColAbsMax() * ------------------------------- * Returns the maximum of the absolute values of element in a * two-dimensional short array. The number of rows and columns - * should be passed in. + * should be passed in. */ long Short2DRowColAbsMax(short **arr, long nrow, long ncol){ @@ -607,14 +719,14 @@ long Short2DRowColAbsMax(short **arr, long nrow, long ncol){ for(row=0;rowmaxval){ - maxval=labs(arr[row][col]); + maxval=labs(arr[row][col]); } } } for(row=nrow-1;row<2*nrow-1;row++){ for(col=0;colmaxval){ - maxval=labs(arr[row][col]); + maxval=labs(arr[row][col]); } } } @@ -673,7 +785,7 @@ float LinInterp2D(float **arr, double rowind, double colind , * Filters magnitude/power data with adaptive geometric filter to get rid of * speckle. Allocates 2D memory for ei. Does not square before averaging. */ -void Despeckle(float **mag, float ***ei, long nrow, long ncol){ +int Despeckle(float **mag, float ***ei, long nrow, long ncol){ float **intensity; double ratio, ratiomax, wfull, wstick, w[NARMS+1]; @@ -690,8 +802,9 @@ void Despeckle(float **mag, float ***ei, long nrow, long ncol){ /* pad magnitude and place into new array (don't touch original data) */ intensity=MirrorPad(mag,nrow,ncol,ARMLEN,ARMLEN); if(intensity==mag){ + fflush(NULL); fprintf(sp0,"Despeckling box size too large for input array size\n" - "Abort\n"); + "Abort\n"); exit(ABNORMAL_EXIT); } @@ -705,60 +818,62 @@ void Despeckle(float **mag, float ***ei, long nrow, long ncol){ /* filter only if input is nonzero so we preserve mask info in input */ if(intensity[Irow][Icol]==0){ - (*ei)[row][col]=0; + (*ei)[row][col]=0; }else{ - for(k=0;kratiomax){ - ratiomax=ratio; - (*ei)[row][col]=wstick; - } - } + for(k=0;kratiomax){ + ratiomax=ratio; + (*ei)[row][col]=wstick; + } + } } } } /* free memory */ Free2DArray((void **)intensity,nrow+2*ARMLEN); + return(0); + } @@ -777,7 +892,7 @@ float **MirrorPad(float **array1, long nrow, long ncol, long krow, long kcol){ /* get memory */ array2=(float **)Get2DMem(nrow+2*krow,ncol+2*kcol, - sizeof(float *),sizeof(float)); + sizeof(float *),sizeof(float)); /* center array1 in new array */ for(row=0;row0 && tstop>0){ walltime=tstop-tstart; @@ -1131,8 +1278,12 @@ void DisplayElapsedTime(time_t tstart, double cputimestart){ minutes=(long )floor((walltime-3600*hours)/60); seconds=walltime-3600*hours-60*minutes; fprintf(sp1,"Elapsed wall clock time: %ld:%02ld:%02ld\n", - hours,minutes,(long )seconds); + hours,minutes,(long )seconds); } + + /* done */ + return(0); + }