/*-------------------------------------------------------------------------
  void direct_transform(double c, int i1, int i2, int j1, int j2, double lon_p, double lat_p, int n,
		        double *lon, double *lat)

  This is a direct transformation of the standard (symmetrical) cubic grid
  to a locally enhanced high-res grid on the sphere; it is an application
  of the Schmidt transformation at the south pole followed by a
  pole_shift_to_target (rotation) operation

  arguments:
    c            : Stretching factor
    lon_p, lat_p : center location of the target face, radian
    n            : grid face number
    i1,i2,j1,j2  : starting and ending index in i- and j-direction
    lon          : longitude. 0 <= lon <= 2*pi
    lat          : latitude. -pi/2 <= lat <= pi/2
  ------------------------------------------------------------------------*/


/*-----------------------------------------------------
      void gnomonic_ed
  Equal distance along the 4 edges of the cubed sphere
  -----------------------------------------------------
  Properties:
  * defined by intersections of great circles
  * max(dx,dy; global) / min(dx,dy; global) = sqrt(2) = 1.4142
  * Max(aspect ratio) = 1.06089
  * the N-S coordinate curves are const longitude on the 4 faces with equator
  For C2000: (dx_min, dx_max) = (3.921, 5.545)    in km unit
  ! Ranges:
  ! lamda = [0.75*pi, 1.25*pi]
  ! theta = [-alpha, alpha]
  --------------------------------------------------------*/


/*----------------------------------------------------------
  void gnomonic_angl()
  This is the commonly known equi-angular grid
**************************************************************/


/*----------------------------------------------------------
  void gnomonic_dist()
  This is the commonly known equi-distance grid
**************************************************************/


/*------------------------------------------------------------------
        void mirror_latlon
   Given the "mirror" as defined by (lon1, lat1), (lon2, lat2), and center
   of the sphere, compute the mirror image of (lon0, lat0) as  (lon, lat)
   ---------------------------------------------------------------*/


/*-------------------------------------------------------------------------
  void symm_ed(int ni, double *lamda, double *theta)
  ! Make grid symmetrical to i=ni/2+1 and j=nj/2+1
  ------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  void mirror_grid( )
  Mirror Across the 0-longitude
  ----------------------------------------------------------------------------*/


/*-------------------------------------------------------------------------------
  void rot_3d()
  rotate points on a sphere in xyz coords (convert angle from
  degrees to radians if necessary)
  -----------------------------------------------------------------------------*/


/*-------------------------------------------------------------
  void cartesian_to_spherical(x, y, z, lon, lat, r)
  may merge with xyz2latlon in the future
  ------------------------------------------------------------*/


/*-------------------------------------------------------------------------------
  void spherical_to_cartesian
  convert from spheircal coordinates to xyz coords
  may merge with latlon2xyz in the future
  -----------------------------------------------------------------------------*/


/* This routine calculate center location based on the vertices location */


/* This routine calculate east location based on the vertices location */


/*-------------------------------------------------------------------------------------------
  void spherical_linear_interpolation
  This formula interpolates along the great circle connecting points p1 and p2.
  This formula is taken from http://en.wikipedia.org/wiki/Slerp and is
  attributed to Glenn Davis based on a concept by Ken Shoemake.
  -------------------------------------------------------------------------------------------*/


/* calculate a distance in 3-d between points on unit square */


/* find the nearest ocean point of a given land point. */


/* transfer the index from supergrid to model grid
       return 0 if istart = iend
       otherwise return 1.
    */


/******************************************************************************
  void read_mosaic_grid_data(const char *mosaic_file, const char *name, int nx, int ny,
                             double *data, int level, int ioff, int joff)
  read mosaic grid information onto model grid. We assume the refinement is 2 right now.
  We may remove this restriction in the future. nx and ny are model grid size. level
  is the tile number. ioff and joff to indicate grid location. ioff =0 and joff = 0
  for C-cell. ioff=0 and joff=1 for E-cell, ioff=1 and joff=0 for N-cell,
  ioff=1 and joff=1 for T-cell
    ******************************************************************************/


/*******************************************************************************
  void create_xgrid_1dx2d_order1
  This routine generate exchange grids between two grids for the first order
  conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
  and lon_in,lat_in are 1-D grid bounds, lon_out,lat_out are geographic grid location of grid cell bounds.
*******************************************************************************/


/*******************************************************************************
  void create_xgrid_1dx2d_order1_ug
  This routine generate exchange grids between two grids for the first order
  conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
  and lon_in,lat_in are 1-D grid bounds, lon_out,lat_out are geographic grid location of grid cell bounds.
*******************************************************************************/


/********************************************************************************
  void create_xgrid_1dx2d_order2
  This routine generate exchange grids between two grids for the second order
  conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
  and lon_in,lat_in are 1-D grid bounds, lon_out,lat_out are geographic grid location of grid cell bounds.
********************************************************************************/


/*******************************************************************************
  void create_xgrid_2dx1d_order1
  This routine generate exchange grids between two grids for the first order
  conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
  and lon_out,lat_out are 1-D grid bounds, lon_in,lat_in are geographic grid location of grid cell bounds.
  mask is on grid lon_in/lat_in.
*******************************************************************************/


/********************************************************************************
  void create_xgrid_2dx1d_order2
  This routine generate exchange grids between two grids for the second order
  conservative interpolation. nlon_in,nlat_in,nlon_out,nlat_out are the size of the grid cell
  and lon_out,lat_out are 1-D grid bounds, lon_in,lat_in are geographic grid location of grid cell bounds.
  mask is on grid lon_in/lat_in.
********************************************************************************/


/*******************************************************************************
   Sutherland-Hodgeman algorithm sequentially clips parts outside 4 boundaries
*******************************************************************************/


/*******************************************************************************
   Revise Sutherland-Hodgeman algorithm to find the vertices of the overlapping
   between any two grid boxes. It return the number of vertices for the exchange grid.
*******************************************************************************/


/*******************************************************************************
   Revise Sutherland-Hodgeman algorithm to find the vertices of the overlapping
   between any two grid boxes. It return the number of vertices for the exchange grid.
   Each edge of grid box is a part of great circle. All the points are cartesian
   coordinates. Here we are assuming each polygon is convex.
   RANGE_CHECK_CRITERIA is used to determine if the two grid boxes are possible to be
   overlap. The size should be between 0 and 0.5. The larger the range_check_criteria,
   the more expensive of the computatioin. When the value is close to 0,
   some small exchange grid might be lost. Suggest to use value 0.05 for C48.
*******************************************************************************/


/* Intersects between the line a and the seqment s
   where both line and segment are great circle lines on the sphere represented by
   3D cartesian points.
   [sin sout] are the ends of a line segment
   returns true if the lines could be intersected, false otherwise.
   inbound means the direction of (a1,a2) go inside or outside of (q1,q2,q3)
*/


/*------------------------------------------------------------------------------
  double poly_ctrlat(const double x[], const double y[], int n)
  This routine is used to calculate the latitude of the centroid
  ---------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  double poly_ctrlon(const double x[], const double y[], int n, double clon)
  This routine is used to calculate the lontitude of the centroid.
  ---------------------------------------------------------------------------*/


/*******************************************************************************
  double grid_box_radius(double *x, double *y, double *z, int n);
  Find the radius of the grid box, the radius is defined the
  maximum distance between any two vertices
*******************************************************************************/


/*******************************************************************************
  double dist_between_boxes(const double *x1, const double *y1, const double *z1, int n1,
                            const double *x2, const double *y2, const double *z2, int n2);
  Find the distance between any two grid boxes. The distance is defined by the maximum
  distance between any vertices of these two box
*******************************************************************************/


/*******************************************************************************
 int inside_edge(double x0, double y0, double x1, double y1, double x, double y)
 determine a point(x,y) is inside or outside a given edge with vertex,
 (x0,y0) and (x1,y1). return 1 if inside and 0 if outside. <y1-y0, -(x1-x0)> is
 the outward edge normal from vertex <x0,y0> to <x1,y1>. <x-x0,y-y0> is the vector
 from <x0,y0> to <x,y>.
 if Inner produce <x-x0,y-y0>*<y1-y0, -(x1-x0)> > 0, outside, otherwise inside.
 inner product value = 0 also treate as inside.
*******************************************************************************/


/*********************************************************************

   int nearest_index(double value, const double *array, int ia)

   return index of nearest data point within "array" corresponding to "value".
   if "value" is outside the domain of "array" then nearest_index = 0
   or = size(array)-1 depending on whether array(0) or array(ia-1) is
   closest to "value"

   Arguments:
     value:  arbitrary data...same units as elements in "array"
     array:  array of data points  (must be monotonically increasing)
     ia   :  size of array.

********************************************************************/


/*******************************************************************************
  double maxval_double(int size, double *data)
  get the maximum value of double array
*******************************************************************************/


/*******************************************************************************
  double minval_double(int size, double *data)
  get the minimum value of double array
*******************************************************************************/


/*******************************************************************************
  double avgval_double(int size, double *data)
  get the average value of double array
*******************************************************************************/


/*******************************************************************************
  void latlon2xyz
  Routine to map (lon, lat) to (x,y,z)
******************************************************************************/


/*------------------------------------------------------------
  void xyz2laton(np, p, xs, ys)
  Transfer cartesian coordinates to spherical coordinates
  ----------------------------------------------------------*/


/*------------------------------------------------------------------------------
  double poly_area(const x[], const y[], int n)
  obtains area of input polygon by line integrating -sin(lat)d(lon)
  Vertex coordinates must be in degrees.
  Vertices must be listed counter-clockwise around polygon.
  grid is in radians.
  ----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  double great_circle_distance()
  computes distance between two points along a great circle
  (the shortest distance between 2 points on a sphere)
  returned in units of meter
  ----------------------------------------------------------------------------*/


/* Compute the great circle area of a polygon on a sphere */


/*------------------------------------------------------------------------------
  double spherical_excess_area(p_lL, p_uL, p_lR, p_uR)
  get the surface area of a cell defined as a quadrilateral
  on the sphere. Area is computed as the spherical excess
  [area units are m^2]
  ----------------------------------------------------------------------------*/


/*----------------------------------------------------------------------
  void vect_cross(e, p1, p2)
  Perform cross products of 3D vectors: e = P1 X P2
  -------------------------------------------------------------------*/


/*----------------------------------------------------------------------
  double* vect_cross(p1, p2)
  return cross products of 3D vectors: = P1 X P2
  -------------------------------------------------------------------*/


/* ----------------------------------------------------------------
   make a unit vector
   --------------------------------------------------------------*/


/*------------------------------------------------------------------
  void unit_vect_latlon(int size, lon, lat, vlon, vlat)

  calculate unit vector for latlon in cartesian coordinates

  ---------------------------------------------------------------------*/


/* Intersect a line and a plane
   Intersects between the plane ( three points ) (entries in counterclockwise order)
   and the line determined by the endpoints l1 and l2 (t=0.0 at l1 and t=1.0 at l2)
   returns true if the two intersect and the output variables are valid
   outputs p containing the coordinates in the tri and t the coordinate in the line
   of the intersection.
   NOTE: the intersection doesn't have to be inside the tri or line for this to return true
*/


/* returns 1 if matrix is inverted, 0 otherwise */


/* return 1 if the point (x,y,z) is added in the list, return 0 if it is already in the list */


/* two points are the same if there are close enough */


/* The following insert a intersection after non-intersect point (x2,y2,z2), if the point
   after (x2,y2,z2) is an intersection, if u is greater than the u value of the intersection,
   insert after, otherwise insert before
*/


/* check if node is inside polygon list or not */


/*********************************************************************
   void cublic_spline_sp(size1, size2, grid1, grid2, data1, data2)

   Calculate a shape preserving cubic spline. Monotonicity is ensured over each subinterval
   unlike classic cubic spline interpolation.
   It will be used to interpolation data in 1-D space.

   INPUT Arguments:
    grid1:    grid for input data grid.
    grid2:    grid for output data grid.
    size1:    size of input grid.
    size2:    size of output grid.
    data1:    input data associated with grid1.

   OUTPUT ARGUMENTS:
    data2:    output data associated with grid2. (OUTPUT)

*********************************************************************/


/*********************************************************************
   void cublic_spline(size1, size2, grid1, grid2, data1, data2, yp1, ypn  )

   This alborithm is to get an interpolation formula that is smooth in the first
   derivative, and continuous in the second derivative, both within an interval
   and its boundaries. It will be used to interpolation data in 1-D space.

   INPUT Arguments:
    grid1:    grid for input data grid.
    grid2:    grid for output data grid.
    size1:    size of input grid.
    size2:    size of output grid.
    data1:    input data associated with grid1.
    yp1:      first derivative of starting point.
              Set to 0 to be "natural"           (INPUT)
    ypn:      first derivative of ending point.
              Set to 0 to be "natural"           (INPUT)

   OUTPUT ARGUMENTS:
    data2:    output data associated with grid2. (OUTPUT)

*********************************************************************/


/*------------------------------------------------------------------------------
  void conserve_interp()
  conservative interpolation through exchange grid.
  Currently only first order interpolation are implemented here.
  ----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  void conserve_interp_great_circle()
  conservative interpolation through exchange grid.
  Currently only first order interpolation are implemented here.
  great_circle algorithm is used for clipping and interpolation.
  ----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  Routine to compute gradient terms for SCRIP:
  SJL: Oct 5, 2007
  NOTe: pin has halo size = 1.
  the size of pin    will be (nx+2,ny+2), T-cell center, with halo = 1
  the size of dx     will be (nx, ny+1),  N-cell center
  the size of dy     will be (nx+1, ny),  E-cell center
  the size of area   will be (nx, ny),    T-cell center.
  The size of edge_w will be (ny+1),      C-cell center
  The size of edge_e will be (ny+1),      C-cell center
  The size of edge_s will be (nx+1),      C-cell center
  The size of edge_n will be (nx+1),      C-cell center
  The size of en_n   will be (nx, ny+1,3),N-cell center
  The size of en_e   will be (nx+1,ny,3), E-cell center
  The size of vlon   will be (nx, ny, 3)  T-cell center
  The size of vlat   will be (nx, ny, 3), T-cell center
  ----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  qin:  A-grid field, size (nx+2, ny+2)
  qout: B-grid field, size (nx+1, ny+1)
  ----------------------------------------------------------------------------*/


/**********************************************************************************************
  This routine is used to calculate grid information for second order conservative interpolation
  from cubic grid to other grid
  the size of xt     will be (nx+2,ny+2), T-cell center, with halo = 1
  the size of yt     will be (nx+2,ny+2), T-cell center, with halo = 1
  the size of xc     will be (nx+1,ny+1), C-cell center
  the size of yc     will be (nx+1,ny+1), C-cell center
  the size of dx     will be (nx, ny+1),  N-cell center
  the size of dy     will be (nx+1, ny),  E-cell center
  the size of area   will be (nx, ny),    T-cell center.
  The size of edge_w will be (ny-1),      C-cell center, without two end point
  The size of edge_e will be (ny-1),      C-cell center, without two end point
  The size of edge_s will be (nx-1),      C-cell center, without two end point
  The size of edge_n will be (nx-1),      C-cell center, without two end point
  The size of en_n   will be (nx, ny+1,3),N-cell center
  The size of en_e   will be (nx+1,ny,3), E-cell center
  The size of vlon   will be (nx, ny)     T-cell center
  The size of vlat   will be (nx, ny),    T-cell center
**********************************************************************************************/


// clock resolution in nanoseconds


/// Write out the current block and start a new one


/// Force write of the file header, if not already written


/// Force load the comments at the end of a streaming
/// file if we don't already have them


// Check if backing fieldData object exists.  If not, throw an exception.
// This branch is not a performance penalty, as the CPU should predict
// this one correctly ~100% of the time.


// Less efficient endian-independent bit-packing routine


// Less efficient endian-independent bit-unpacking routine


/* This function returns the documentation string to be assigned to
   __doc__.
*/


/* calling sequence for binevents:

   binevents(x, y, array, x_offset, dq, sdqflags, epsilon)

    x, y       i: arrays of pixel coordinates of the events
                  (int16, or default is float32)
    array     io: the output 2-D array (float32)
    x_offset   i: the offset (it's zero or positive) to add to
                  the x pixel coordinate to get image pixel (int)

   optional arguments:
    dq         i: array of data quality flags (int16; 0 is good)
    sdqflags   i: bit mask for the "serious" dq flags (short)
    epsilon    i: array of weights for the events (float32)

   ccos_binevents calls binEventsToImage, which converts arrays of pixel
   coordinates to an image array.  The 2-D array ('array') will first be
   initialized to zero.  For each pair of elements (x[i],y[i]), the value
   in the nearest pixel to (x[i]+x_offset,y[i]) of array will be incremented.
   If epsilon is not null, the increment will be epsilon[i]; otherwise, the
   increment will be one.  If dq is not null, the pixel will be incremented
   only if dq[i] does not include a "serious" flag value (e.g. pulse height
   out of range or within a bad time interval).
*/


/* This is called by ccos_binevents. */


/* calling sequence for bindq:

   bindq(lx, ly, ux, uy, flag, dq_array, x_offset)

    lx, ly     i: arrays of lower left corners of regions (int32)
    ux, uy     i: arrays of upper right corners of regions (int32)
    flag       i: array of data quality flags (int32)
    dq_array  io: 2-D array (int16); dq_array must have already been
                  initialized before calling bindq
    x_offset   i: the offset (it's zero or positive) to add to
                  x pixel coordinate to get the pixel in dq_array (int)

   The arrays lx, ly, ux, uy and flag are all of the same length.  These
   were taken from the data quality initialization table, but they may
   have been modified by adding wavecal offsets and Doppler shifts.
   Note that x_offset is added by this function.

   ccos_bindq calls binDQToImage, which updates in-place a 2-D DQ image
   array, flagging regions according to the regions specified in a data
   quality initialization table.  The input arrays are the lower left
   corner of a region, width of the region, and flag value.

   axis is the dispersion direction, which is relevant when extending the
   flagged region due to the Doppler shift during the exposure (specified
   by mindopp and maxdopp); if the value of axis is neither 0 nor 1, no
   Doppler smearing will be included.  mindopp and maxdopp are pixel offsets
   to be applied in the dispersion direction to each region to be flagged.

   dq_array will not be initialized by this function; values on input are
   assumed to be valid.
*/


/* This is called by ccos_bindq. */


/* calling sequence for applydq:

   applydq(lx, ly, dx, dy, flag, x, y, dq)

    lx, ly     i: arrays of lower left corners of regions (int32)
    dx, dy     i: arrays of region widths (int32)
    flag       i: array of data quality flags (int32)
    x, y       i: arrays of pixel coordinates of the events, not Doppler
                  corrected (either int16 or float32)
    dq        io: array of data quality flags (int16)

   ccos_applydq calls applyDQToEvents, which updates in-place a 1-D dq
   array (column) for an events list, flagging regions according to the
   regions specified in a data quality initialization table (bpixtab).
   The input arrays from the reference table give the lower left corner
   of each region, width of the region, and flag value.  The x and y
   arrays are the rawx and rawy columns from an events table.  The dq
   array is the data quality column from that events table; this is
   the array that will be updated in-place.  Values of dq on input are
   assumed to be valid (i.e. this function will not initialize dq).
*/


/* This is called by ccos_applydq. */


/* calling sequence for dq_or:

   dq_or(dq_2d, dq_1d)

    dq_2d      i: 2-D data quality array (int16)
    dq_1d     io: 1-D data quality array (int16)

   If the shape of dq_2d is (ny, nx), the shape of dq_1d should be (nx,).

   ccos_dq_or calls bitwiseOrDQ, which updates dq_1d in-place.  For each
   element i, dq_1d[i] will be the bitwise OR of dq_2d[:,i].
*/


/* This is called by ccos_dq_or. */


/* calling sequence for applyflat:

   applyflat(x, y, epsilon, flat, origin_x, origin_y)

    x, y       i: arrays of pixel coordinates of the events
                  (either float32 or int16)
    epsilon   io: an array of efficiencies for the events (float32)
    flat       i: the 2-D flat field image array (float32)

   optional arguments:
    origin_x   i: offset in the more rapidly varying axis (int)
    origin_y   i: offset in the less rapidly varying axis (int)
            origin_x and origin_y are the offsets of the flat field array
            from the beginning of the detector, to allow the flat to be
	    a subarray.  origin_x & origin_y are the values of the keywords
	    ORIGIN_X and ORIGIN_Y respectively.  These are in units of
            pixels, and they are zero-indexed.  These are the negative of
            the IRAF keywords LTV1 & LTV2 respectively.

   ccos_applyflat calls applyFlatField, which applies a flat field image to
   the epsilon (weight) array.  It is assumed that epsilon has previously
   been initialized to one, although it may subsequently have been modified,
   e.g. by applying a deadtime correction.
*/


/* This is called by ccos_applyflat. */


/* calling sequence for range:

   indices = range(time, t0, t1)

    time       i: array of times of the events (read as float64)
    t0, t1     i: the times for which the indices are needed (double)

    indices    o: a two-element tuple of the indices in the time array
                  that bracket t0 and t1, to be used in the sense:
                      for i in range (indices[0], indices[1]):

   ccos_range calls timeRange, which returns (i0, i1) such that all values
   in time[i0:i1] are within the range from t0 to t1, and that would not
   be true for a smaller i0 or a larger i1.  time is assumed to be
   monotonically nondecreasing.
*/


/* This is called by ccos_range. */


/* This is a binary search function for t in time, but the routine isn't
   looking for an exact match.  We're searching for an index that can be
   used as the lower or upper index of a slice.

   If t falls between time[k] and time[k+1], then k+1 will be returned.
   If t exactly matches all time[k] values for k in the range k0 to k1
   inclusive, then k0 will be returned.
   if t is less than or equal to time[0], 0 will be returned.
   If t is greater than or equal to time[len(time)-1], len(time) will be
   returned (where len(time) is the length of the time array).  Note that
   the equality condition is inconsistent with the normal case where t is
   somewhere in the middle of the time array, but it makes the useage more
   intuitive.
*/


/* This is a double precision version of search. */


/* calling sequence for unbinaccum:

   unbinaccum(image, x, y, x_offset)

    image      i: a 2-D array (int16, or default is float32)
    x, y      io: the arrays of pixel coordinates (float32)

   optional argument:
    x_offset   i: the offset (it's zero or positive) to subtract from the
                  image x pixel number to get the value to assign to x (int)

   ccos_unbinaccum calls unbinImage, which converts an image array ('image')
   to a pseudo time-tag list.  No time array will be created, just x and y
   pixel coordinates.  image is expected to contain integer values.  For
   each pixel of image that contains a positive value, that number of
   elements will be assigned in the x and y arrays, with their values
   being all the same, the coordinates of the current pixel in image.
*/


/* This is called by ccos_unbinaccum. */


/* calling sequence for addrandom:

   newseed = addrandom(x, seed, use_clock)

    x         io: an array of pixel coordinates, either X or Y axis (float32)
    seed       i: a 32-bit integer for the pseudo-random number generator
    use_clock  i: true means use system clock to generate the seed (int)

    newseed    o: a 32-bit integer that could be used as the seed for
                  another call to addrandom

   ccos_addrandom calls addRn, which adds a pseudo-random number between
   -0.5 and +0.5 to each element of x.  If use_clock is true, the system
   clock will be used to create a seed for the generator (and the seed
   argument will be ignored); otherwise, seed will be used to start the
   generator.  The final value of the seed will be converted to a Python
   integer and returned as the function value.

   The actual endpoint of the range of the pseudo-random numbers may be
   equal to -0.5 or +0.5, depending on roundoff.
*/


/* This is called by ccos_addrandom. */


/* calling sequence for convolve1d:

   convolve1d(flat, dopp, axis)

    flat      io: 2-D flat field image array (float32)
    dopp       i: 1-D array with which flat will be convolved (float32)
    axis       i: the axis (0 or 1) along which flat will be convolved (int);
                  axis 1 is the more rapidly varying axis

   The middle element of dopp corresponds to no shift.  For example,
   the following dopp would result in no change to flat:
        dopp = array ((0, 0, 0, 1, 0, 0, 0), dtype=float32)

   ccos_convolve1d calls convolveWithDopp, which convolves a flat field
   in-place with dopp.  The dopp array is 1-D, while the flat field is 2-D.
   The convolution will be done along just one axis, specified by axis.
*/


/* This is called by ccos_convolve1d. */


/* calling sequence for extractband:

   extractband(indata, axis, slope, intercept, x_offset, outdata)

    indata     i: 2-D image array, from which a band will be extracted
                  (either float32 or int16)
    axis       i: the axis (0 or 1) along which the band will be extracted (int)
                  axis 1 is the more rapidly varying axis
    slope      i: the slope of the band (pixels per pixel, double)
    intercept  i: the center line of the band should cross this location
                  in the cross dispersion direction at pixel 'x_offset'
                  in the dispersion direction (pixel number, double)
    x_offset   i: x_offset is zero or positive; this is the offset of the
                  detector in the dispersion direction within indata (int)
    outdata   io: a 2-D array, into which the extracted data will be put
                  (either float32 or int16)

   While indata and outdata may be either float32 or int16, they both
   must be the same type.

   slope is the slope of the band with respect to the axis along which
   it will be extracted.  If axis=1 and slope=+0.1, for example, then
   the band is about six degrees counterclockwise from the horizontal
   axis.  If axis=0 and slope=+0.1, the band is about six degrees
   clockwise from the vertical axis.

   ccos_extractband calls extract2DBand, which copies out a 2-D array
   ('outdata') from a larger 2-D array ('indata').  outdata is an
   extracted spectrum or a background region.  The spectrum in indata
   may be oriented horizontally or vertically (specified by axis = 1 or 0
   respectively), but the data will be copied to outdata so that the
   dispersion direction in outdata will be oriented horizontally
   (the more rapidly varying axis).

   The location of the region in indata to be extracted is specified by
   slope and intercept (and axis).  The slope is in pixels per pixel.  The
   intercept is zero indexed, at the bottom (if axis=0) or left (if axis=1)
   edge; this is the location where the center line of the region to be
   extracted meets the edge.  No interpolation is done.  For each pixel in
   the dispersion direction, a short strip of pixels will be copied to
   outdata.  The location of that strip in the cross dispersion direction
   will be rounded to an integer, and pixel values will be copied directly
   to outdata.
*/


/* This is called by ccos_extractband. */


/* calling sequence for smoothbkg:

   smoothbkg(data, width, flags)

    data      io: a 1-D array to be smoothed in-place (float32)
    width      i: the width (pixels) of the boxcar smoothing function (int)

   optional argument:
    flags      i: a 1-D array of flags, 0 is good, 1 is bad (int16)

   ccos_smoothbkg calls smoothBackground, which boxcar smoothes the
   1-D array 'data' in-place, with a width of 'width' pixels.
*/


/* This is called by ccos_smoothbkg. */


/* calling sequence for addlines:

   addlines(intensity, wavelength, reswidth, x1d_wl, template)

    intensity   i: array of amplitudes of lines (float32)
    wavelength  i: array of wavelengths of lines (float64)
    reswidth    i: FWHM of Gaussian line shape (double)
    x1d_wl      i: wavelength array for template spectrum (read as float64)
    template   io: 1-D template spectrum (float32)

   ccos_addlines calls addEmissionLines, which constructs a spectrum of
   emission lines.  The wavelengths and intensities of the lines are
   given by the arrays intensity and wavelength; there is one element in
   each of those arrays for each emission line to be used in creating
   the spectrum.  The output spectrum (written to in-place) is
   template, and the wavelength at each pixel of template is
   given by x1d_wl.  The line shape is a Gaussian, boxcar smoothed
   by three pixels (to simulate a slit width of three pixels),
   and the full-width-half-maximum of the Gaussian is reswidth.
*/


/* This is called by ccos_addlines. */


/* This function does a binary search and returns the index i such that
   wl is between array[i] and array[i+1].  Normally, i is restricted to
   the range from 0 to n-1 inclusive.

   Out of range conditions:

   i = -1 means that wl is smaller than array[0] (or larger, if array is
   decreasing); i = nelem means that wl is greater than array[nelem-1]
   (or smaller, if array is decreasing).  Note that the function value i
   will never be equal to nelem-1.
*/


/* This function adds an emission line with amplitude ampl, centered at
   pixel number x, to template.  The line shape is a Gaussian, boxcar
   smoothed by three pixels; the FWHM is reswidth, and the line is
   truncated after about 2.5 * reswidth.
*/


/* calling sequence for geocorrection:

   geocorrection(x, y, x_image, y_image, interp_flag, \
		origin_x, origin_y, xbin, ybin)

    x, y       io: arrays of pixel coordinates of the events (float32)
    x_image     i: the 2-D image array of dx values (float32)
    y_image     i: the 2-D image array of dy values (float32)
    interp_flag i: indicates the type of interpolation (int):
                   0 --> use nearest neighbor, 1 --> use bilinear interpolation

   optional arguments:
    origin_x    i: offset in the more rapidly varying axis (int)
    origin_y    i: offset in the less rapidly varying axis (int)
    xbin        i: bin factor in the more rapidly varying axis (int)
    ybin        i: bin factor in the less rapidly varying axis (int)
            origin_x and origin_y are the offsets of x_image and y_image
            from the beginning of the detector, to allow them to be
            subarrays.  origin_x & origin_y are the values of the keywords
            ORIGIN_X and ORIGIN_Y respectively.  These are in units of
            unbinned pixels, and they are zero-indexed.
            xbin and ybin are the bin factors of x_image and y_image
            in the X and Y axes respectively, with default values of 1.
            These are the values of the keywords XBIN and YBIN.

   ccos_geocorrection calls geoInterp2D, which applies the geometric (INL)
   correction to the x and y arrays (in-place).  The corrections to x and y
   are given by the values in x_image and y_image respectively, which have
   offsets of origin_x and origin_y from the origin (so the images do not
   have to be full size).  If interp_flag is true, bilinear interpolation
   within x_image and y_image will be used to get the corrections to x and
   y; otherwise, the nearest pixel in x_image and y_image will be used.
*/


/* This is called by ccos_geocorrection. */


/* calling sequence for walkcorrection:

   walkcorrection(x, y, image, delta)

    x, y       i: arrays of pixel coordinates of the events (float32)
    image       i: the 2-D image array of delta values (float32)
    delta:     io: array of lookups in the image at the x, y coordinates
   ccos_walkcorrection calls bilinearinterpolation, which calculates the
   walk correction.
*/


/* This is called by ccos_walkcorrection. */


/* calling sequence for pha_check:

   counters = pha_check(x, y, pha, dq, im_low, im_high, pha_flag)

    x, y        i: arrays of pixel coordinates of the events (float32)
    pha         i: array of pulse heights (int16)
    dq         io: array of data quality flags (int16)
    im_low      i: the 2-D image array of lower limits for pulse height (int16)
    im_high     i: the 2-D image array of upper limits for pulse height (int16)
    pha_flag    i: the flag value that indicates that the pulse height is
                   out of bounds (int)

    (nlow, nhigh) o: a two-element tuple giving the number of events that
                     were flagged as out of range on the low side or on
                     the high side respectively

   ccos_pha_check calls phaCheck, which compares the value of each value
   in the pha column with the lower and upper limits of the acceptable
   range for pulse height at the corresponding location on the detector.
   Values that are out of range will be flagged in the dq array.
*/


/* This is called by ccos_pha_check. */


/* This routine does bilinear interpolation at x,y within the x and y
   image arrays.  The interpolated values are returned as dx and dy.
   x is the more rapidly varying axis.  nx and ny give the size of the
   image arrays.
*/


/* calling sequence for clear_rows:

   clear_rows(dq, y_lower, y_upper, x_left, x_right)

    dq             io: array of data quality flags (int16)
    y_lower         i: array of Y coordinates at lower edge (float32)
    y_upper         i: array of Y coordinates at upper edge (float32)
    x_left          i: array of X coordinates at left edge (float32)
    x_right         i: array of X coordinates at right edge (float32)

   ccos_clear_rows calls clearRows, which assigns zero to the region within
   the specified (curved) borders.
*/


/* This is called by ccos_clear_rows. */


/* calling sequence for interp1d:

   interp1d(x_a, y_a, x_b, y_b)

    x_a, y_a   i: input independent and dependent variable arrays
    x_b        i: independent variable array
    y_b       io: interpolated data at each element of x_b (modified in-place)

   ccos_interp1d calls interp1d to interpolate within y_a for each element
   of x_b.  All arrays must be 1-D.  x_a and y_a must be the same length,
   and x_b and y_b must be the same length (possibly different from the
   length of x_a).  The arrays will be converted internally to double
   if they aren't already.
*/


/* This function compares the shapes of the arrays.  x_a and y_a must be
   the same length, and x_b and y_b must be the same length (which need not
   be the same as the length of x_a).  All arrays must be 1-D.
*/


/* This function does linear interpolation to assign values to y_b.
   For values of x_a that are outside the range of x_b, the first
   or last value of y_a will be assigned to y_b.
*/


/* calling sequence for getstartstop:

   getstartstop(time, istart, istop, delta_t)

    time          i: array of times (seconds) of the events (float32)
    istart        o: array of indices in events list of the start of
                     time intervals (int32)
    istop         o: array of indices of the end of time intervals (int32)
    delta_t       i: length (seconds) of each time interval (double)

   ccos_getstartstop gets the indices in the events list of the start and
   stop times of the time intervals.  istart[i] and istop[i] are intended
   to be used as the limits of a Python slice for time interval i.
*/


/* calling sequence for getbkgcounts:

   getbkgcounts(y, dq,
	istart, istop, bkg_counts, src_counts,
	bkg1_low, bkg1_high, bkg2_low, bkg2_high,
	src_low, src_high, bkgsf)

    y             i: array of Y pixel coordinates of the events
                     (either float32 or int16)
    dq            i: array of data quality flags for the events (int16)
    istart        i: array of indices in events list of the start of
                     time intervals (int32)
    istop         i: array of indices of the end of time intervals (int32)
    bkg_counts    o: array of background counts in each interval (int32)
    src_counts    o: array of source counts in each interval (int32)
    bkg1_low,     i: row numbers of lower background region (int)
      bkg1_high
    bkg2_low,     i: row numbers of upper background region (int)
      bkg2_high
    src_low,      i: row numbers of source region (int)
      src_high
    bkgsf         i: scale factor to estimate how many background counts
                     there are in the source extraction region (double)

   ccos_getbkgcounts gets the number of source and background counts within
   each interval [istart[i]:istop[i]].
*/


/* calling sequence for smallerbursts:

   smallerbursts(time, dq,
	istart, istop, bkg_counts, src_counts,
	smallest_burst, stdrej, source_frac,
	half_block, max_iter,
	large_burst, small_burst, dq_burst, verbose)

    time            i: array of times, used only if verbose (float32)
    dq             io: array of data quality flags for the events (int16)
    istart          i: array of indices in events list of the start of
                       time intervals (int32)
    istop           i: array of indices of the end of time intervals (int32)
    bkg_counts     io: array of background counts in each interval (int32)
    src_counts      i: array of source counts in each interval (int32)
    delta_t         i: length (seconds) of each time interval (double)
    smallest_burst  i: burst_min * delta_t (double)
    stdrej          i: criterion for N * sigma rejection (double)
    source_frac     i: minimum fraction of source counts (double)
    half_block      i: round (median_dt / delta_t) / 2 (int)
    max_iter        i: maximum number of iterations (int)
    large_burst     i: flag value for a "large" burst (int)
    small_burst     i: flag value for a "small" burst (int)
    dq_burst        i: data quality flag for a burst (int)
    verbose         i: if true, print info about bursts (int)

   ccos_smallerbursts screens for smaller bursts.  If any are found,
   they will be flagged by setting elements of the dq array to dq_burst,
   and the bkg_counts element for each burst will be set to small_burst
   (assumed to be negative).
*/


/* This function, called by ccos_smallerbursts, screens for "smaller"
   bursts.  This is done iteratively, up to max_iter times.  Within each
   iteration, bkg_counts is boxcar filtered (into a scratch array), but
   using median within the box.  The box size is 2 * half_block + 1, but
   it is truncated on one side as an endpoint is approached.  Negative
   values in bkg_counts are used to flag bursts, so when computing the
   median, values less than zero are ignored.

   The rejection criteria are based on the difference delta_counts between
   an element of bkg_counts and the filtered value.  For element i to be
   flagged as a burst, the following three criteria must all be met:

	delta_counts > smallest_burst
	delta_counts > stdrej * sqrt(bkg_counts[i])
	delta_counts > source_frac * src_counts[i]
*/


/* Boxcar smooth bkg_counts, with a box of width (2 * half_block + 1).
   Within the box, the smoothed value is the median of all non-negative
   values (previously detected bursts will have been flagged by replacing
   the value in bkg_counts with a negative number).  As an endpoint is
   approached, the box will be truncated on the side of the endpoint.

   The result is returned in the array m_filtered.
*/


/* calling sequence for getbadtime:

   badtime = getbadtime(time, dq)

    time       i: array of times of the events (float32)
    dq         i: array of data quality flags for the events (int16)

   The function value is the sum of the time intervals within which
   the data quality flag was non-zero for every event in the intervals.
*/


/* calling sequence for xy_extract:

   xy_extract(xi, eta, outdata, slope, intercept, x_offset,
               dq, sdqflags, epsilon)

    xi, eta     i: arrays of pixel coordinates of the events
                   (either float32 or int16); xi is in the dispersion
                   direction, eta is cross-dispersion
    outdata    io: a 2-D array, into which the extracted spectrum will be put
                   (float64)
    slope       i: the slope of the band (pixels per pixel, double)
    intercept   i: the zero point of the band (pixel number, double)
    x_offset    i: the offset (it's zero or positive) to add to the xi pixel
                   coordinate to get the pixel in the output array (int)

   optional arguments:
    dq          i: array of data quality flags (int16)
    sdqflags    i: bit mask for the "serious" dq flags (short)
    epsilon     i: array of weights for the events (float32)

   xi and eta may be either Float32 or Int16, and they do not need to be
   the same type.

   The x_offset argument is the offset to add to values from xi to get the
   index into the output spectrum.  This lets the output spectrum be longer
   than the detector width.

   slope is the slope of the band with respect to the axis along which
   it will be extracted.  If slope=+0.1, for example, then the band is
   about six degrees counterclockwise from the horizontal axis (or
   clockwise from the vertical axis for NUV).

   ccos_xy_extract calls extrFromEvents, which first initializes the output
   spectrum to zero and then increments elements of the spectrum, one for
   each event within the spectral extraction region.  The output array is
   2-D, as with ccos_extractband; sum along axis 0 to get a 1-D spectrum.

   The location of the region to be extracted is specified by slope and
   intercept.  The slope is in pixels per pixel.  The intercept is zero
   indexed, at the eta = 0 edge; this is the location where the center line
   of the region to be extracted meets the edge.  No interpolation is done.
*/


/* This is called by ccos_xy_extract. */


/* calling sequence for xy_collapse:

   xy_collapse(xi, eta, dq, slope, xdisp)

    xi, eta     i: arrays of pixel coordinates of the events
                   (either float32 or int16); xi is in the dispersion
                   direction, eta is cross-dispersion
    dq          i: array of data quality flags (int16)
    slope       i: the slope of the band (pixels per pixel, double)
    xdisp      io: a 1-D array, into which the collapsed data will be put;
                   the location of a feature in this array shows where the
                   spectrum crosses the left edge of the detector (float64)

   xi and eta may be either Float32 or Int16, and they do not need to be
   the same type.

   slope is the slope (in pixels per pixel) of the band with respect to
   the axis along which it will be extracted.  See the description for
   xy_extract.

   ccos_xy_collapse calls collapseFromEvents, which first initializes
   xdisp to zero, then collapses the data along the dispersion direction,
   incrementing xdisp for each event.  The length of xdisp should be
   the width of the detector in the cross-dispersion direction.  If the
   slope of the spectrum were zero, element i of xdisp would be incremented
   for each element of eta that is between i-0.5 and i+0.5.  For a non-zero
   slope, each eta position is first adjusted by subtracting (slope * xi),
   so the position is projected to the left edge.  Note that this is the same
   convention as for the intercept as given in the xtractab reference table.
*/


/* This is called by ccos_xy_collapse. */


/* calling sequence for csum_3d:

   csum_3d(array, x, y, epsilon, pha, binx, biny)

    array     io: the output 3-D array (float32)
    x, y       i: arrays of pixel coordinates of the events (float32)
    epsilon    i: array of weights for the events (float32)
    pha        i: array of pulse heights (int16)

   optional arguments:
    binx       i: binning factor in the more rapidly varying axis
    biny       i: binning factor in the less rapidly varying axis

   ccos_csum_3d calls bin3DtoCsum, which converts arrays of pixel
   coordinates to an image array.  The 3-D array ('array') is assumed
   to have already been initialized to zero.  For each event n, the
   array element at [pha[n],y[n],x[n]] will be incremented by epsilon[n].
*/


/* This is called by ccos_csum_3d. */


/* calling sequence for csum_2d:

   csum_2d(array, x, y, epsilon, binx, biny)

    array     io: the output 2-D array (float32)
    x, y       i: arrays of pixel coordinates of the events (float32)
    epsilon    i: array of weights for the events (float32)

   optional arguments:
    binx       i: binning factor in the more rapidly varying axis
    biny       i: binning factor in the less rapidly varying axis

   ccos_csum_2d calls bin2DtoCsum, which converts arrays of pixel
   coordinates to an image array.  The 2-D array ('array') is assumed
   to have already been initialized to zero.  For each event n, the
   array element at [y[n],x[n]] will be incremented by epsilon[n].
*/


/* This is called by ccos_csum_2d. */


/* calling sequence for bin2d:

   bin2d(array, binned_array)

    array        i: the input 2-D array (float32)
    binned_array o: the output 2-D array (float32)

   ccos_bin2d calls bin2DArray, which bins the input 'array' by integer
   factors in each axis and writes the results to the output 'binned_array'.
   The binning factor must be an integer in each axis; that is, the shape
   of 'binned_array' must divide the shape of 'array'.
*/


/* This is called by ccos_bin2d. */


/****************************************************************************/
/*! This function computes various information associated with a partition */
/****************************************************************************/


/*************************************************************************/
/*! This is the entry point of the command-line argument parser */
/*************************************************************************/


/*************************************************************************
* This is the entry point of the command-line argument parser
**************************************************************************/


/*************************************************************************/
/*! This function prints run parameters */
/*************************************************************************/


/*************************************************************************/
/*! This function does any post-partitioning reporting */
/*************************************************************************/


/*************************************************************************/
/*! This function does any post-metis reporting */
/*************************************************************************/


/*************************************************************************/
/*! This function does any post-ordering reporting */
/*************************************************************************/


/*************************************************************************/
/*! This function sets up data structures for fill-in computations */
/*************************************************************************/


/*************************************************************************/
/*! This function reads in a sparse graph */
/*************************************************************************/


/*************************************************************************/
/*! This function reads in a mesh */
/*************************************************************************/


/*************************************************************************/
/*! This function reads in a partition/ordering vector  */
/**************************************************************************/


/*************************************************************************/
/*! This function writes out the partition vector */
/*************************************************************************/


/*************************************************************************/
/*! This function writes out the partition vectors for a mesh */
/*************************************************************************/


/*************************************************************************/
/*! This function writes out the permutation vector */
/*************************************************************************/


/*************************************************************************/
/*! This function writes a graph into a file  */
/*************************************************************************/


/* initializes mt[NN] with a seed */


/* generates a random number on [0, 2^64-1]-interval */


/* generates a random number on [0, 2^32-1]-interval */


/* Inline functions for bitset operation.  */


/* Specify the precise syntax of regexps for compilation.  This provides
   for compatibility for various utilities which historically have
   different, incompatible syntaxes.

   The argument SYNTAX is a bit mask comprised of the various bits
   defined in regex.h.  We return the old syntax.  */


/* Entry point for POSIX code.  */
/* regcomp takes a regular expression as a string and compiles it.

   PREG is a regex_t *.  We do not expect any fields to be initialized,
   since POSIX says we shouldn't.  Thus, we set

     `buffer' to the compiled pattern;
     `used' to the length of the compiled pattern;
     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
       REG_EXTENDED bit in CFLAGS is set; otherwise, to
       RE_SYNTAX_POSIX_BASIC;
     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
     `fastmap' to an allocated space for the fastmap;
     `fastmap_accurate' to zero;
     `re_nsub' to the number of subexpressions in PATTERN.

   PATTERN is the address of the pattern string.

   CFLAGS is a series of bits which affect compilation.

     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
     use POSIX basic syntax.

     If REG_NEWLINE is set, then . and [^...] don't match newline.
     Also, regexec will try a match beginning after every newline.

     If REG_ICASE is set, then we considers upper- and lowercase
     versions of letters to be equivalent when matching.

     If REG_NOSUB is set, then when PREG is passed to regexec, that
     routine will report only success or failure, and nothing about the
     registers.

   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
   the return codes and their meanings.)  */


/* regerror ( int errcode, preg, errbuf, errbuf_size) */


/* Free dynamically allocated space used by PREG.  */


/* Internal entry point.
   Compile the regular expression PATTERN, whose length is LENGTH.
   SYNTAX indicate regular expression's syntax.  */


/* Initialize DFA.  We use the length of the regular expression PAT_LEN
   as the initial length of some arrays.  */


/* Free the work area which are only used while compiling.  */


/* Create initial states for all contexts.  */


/* If it is possible to do searching in single byte encoding instead of UTF-8
   to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
   DFA nodes where needed.  */


/* Analyze the structure tree, and calculate "first", "next", "edest",
   "eclosure", and "inveclosure".  */


/* Our parse trees are very unbalanced, so we cannot use a stack to
   implement parse tree visits.  Instead, we use parent pointers and
   some hairy code in these two functions.  */


/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell
   re_search_internal to map the inner one's opr.idx to this one's.  Adjust
   backreferences as well.  Requires a preorder visit.  */


/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation
   of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP.  */


/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton
   nodes.  Requires a postorder visit.  */


/* Pass 2: compute NEXT on the tree.  Preorder visit.  */


/* Pass 3: link all DFA nodes to their NEXT node (any order will do).  */


/* Search for a node which is duplicated from the node ORG_NODE, and
   satisfies the constraint CONSTRAINT.  */


/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
   Return the index of the new node, or -1 if insufficient storage is
   available.  */


/* Calculate "eclosure" for all the node in DFA.  */


/* Calculate epsilon closure of NODE.  */


/* Entry point of the parser.
   Parse the regular expression REGEXP and return the structure tree.
   If an error is occured, ERR is set by error code, and return NULL.
   This function build the following tree, from regular expression <reg_exp>:
	   CAT
	   / \
	  /   \
   <reg_exp>  EOR

   CAT means concatenation.
   EOR means end of regular expression.  */


/* This function build the following tree, from regular expression
   <branch1>|<branch2>:
	   ALT
	   / \
	  /   \
   <branch1> <branch2>

   ALT means alternative, which represents the operator `|'.  */


/* This function build the following tree, from regular expression
   <exp1><exp2>:
	CAT
	/ \
       /   \
   <exp1> <exp2>

   CAT means concatenation.  */


/* This function build the following tree, from regular expression a*:
	 *
	 |
	 a
*/


/* This function build the following tree, from regular expression
   (<reg_exp>):
	 SUBEXP
	    |
	<reg_exp>
*/


/* This function parse repetition operators like "*", "+", "{1,3}" etc.  */


/* Local function for parse_bracket_exp used in _LIBC environement.
     Seek the collating symbol entry correspondings to NAME.
     Return the index of the symbol in the SYMB_TABLE.  */


/* Local function for parse_bracket_exp used in _LIBC environement.
     Look up the collation sequence value of BR_ELEM.
     Return the value if succeeded, UINT_MAX otherwise.  */


/* Local function for parse_bracket_exp used in _LIBC environement.
     Build the range expression which starts from START_ELEM, and ends
     at END_ELEM.  The result are written to MBCSET and SBCSET.
     RANGE_ALLOC is the allocated size of mbcset->range_starts, and
     mbcset->range_ends, is a pointer argument sinse we may
     update it.  */


/* Local function for parse_bracket_exp used in _LIBC environement.
     Build the collating element which is represented by NAME.
     The result are written to MBCSET and SBCSET.
     COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
     pointer argument sinse we may update it.  */


/* Parse an element in the bracket expression.  */


/* Parse a bracket symbol in the bracket expression.  Bracket symbols are
   such as [:<character_class>:], [.<collating_element>.], and
   [=<equivalent_class>=].  */


/* This is intended for the expressions like "a{1,3}".
   Fetch a number from `input', and return the number.
   Return -1, if the number field is empty like "{,1}".
   Return -2, If an error is occured.  */


/* Create a tree node.  */


/* Mark the tree SRC as an optional subexpression.
   To be called from preorder or postorder.  */


/* Worker function for tree walking.  Free the allocated memory inside NODE
   and its children. */


/* Duplicate the node SRC, and return new node.  This is a preorder
   visit similar to the one implemented by the generic visitor, but
   we need more infrastructure to maintain two parallel trees --- so,
   it's easier to duplicate.  */


/* re_match, re_search, re_match_2, re_search_2

   The former two functions operate on STRING with length LENGTH,
   while the later two operate on concatenation of STRING1 and STRING2
   with lengths LENGTH1 and LENGTH2, respectively.

   re_match() matches the compiled pattern in BUFP against the string,
   starting at index START.

   re_search() first tries matching at index START, then it tries to match
   starting from index START + 1, and so on.  The last start position tried
   is START + RANGE.  (Thus RANGE = 0 forces re_search to operate the same
   way as re_match().)

   The parameter STOP of re_{match,search}_2 specifies that no match exceeding
   the first STOP characters of the concatenation of the strings should be
   concerned.

   If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
   and all groups is stroed in REGS.  (For the "_2" variants, the offsets are
   computed relative to the concatenation, not relative to the individual
   strings.)

   On success, re_match* functions return the length of the match, re_search*
   return the position of the start of the match.  Return value -1 means no
   match was found and -2 indicates an internal error.  */


/* The parameters have the same meaning as those of re_search.
   Additional parameters:
   If RET_LEN is nonzero the length of the match is returned (re_match style);
   otherwise the position of the match is returned.  */


/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
   this memory for recording register information.  STARTS and ENDS
   must be allocated using the malloc library routine, and must each
   be at least NUM_REGS * sizeof (regoff_t) bytes long.

   If NUM_REGS == 0, then subsequent matches should allocate their own
   register data.

   Unless this function is called, the first search or match using
   PATTERN_BUFFER will allocate its own register data, without
   freeing the old data.  */


/* Return the next state to which the current state STATE will transit by
   accepting the current input byte.  */


/******************************************************************************/
/*! This function puts the 'topk' largest values in the beginning of the array */
/*******************************************************************************/


/******************************************************************************/
/*! This function puts the 'topk' smallest values in the beginning of the array */
/*******************************************************************************/


/*************************************************************************
* This function checks if a file exists
**************************************************************************/


/*************************************************************************
* This function checks if a directory exists
**************************************************************************/


/*************************************************************************
* This function takes in a potentially full path specification of a file
* and just returns a string containing just the basename of the file.
* The basename is derived from the actual filename by stripping the last
* .ext part.
**************************************************************************/


/*************************************************************************
* This function takes in a potentially full path specification of a file
* and just returns a string corresponding to its file extension. The
* extension of a file is considered to be the string right after the
* last '.' character.
**************************************************************************/


/*************************************************************************
* This function takes in a potentially full path specification of a file
* and just returns a string containing just the filename.
**************************************************************************/


/*************************************************************************
* This function creates a path
**************************************************************************/


/*************************************************************************
* This function deletes a directory tree and all of its contents
**************************************************************************/


/*************************************************************************
* This function returns the ID of a particular string based on the
* supplied StringMap array
**************************************************************************/


/*************************************************************************
* This file randomly permutes the contents of an array.
* flag == 0, don't initialize perm
* flag == 1, set p[i] = i
**************************************************************************/


/*************************************************************************
* This function returns the log2(x)
**************************************************************************/


/************************************************************************
* This function tokenizes a string based on the user-supplied delimiters
* list. The resulting tokens are returned into an array of strings.
*************************************************************************/


/*************************************************************************/
/*! The entry point of the frequent itemset discovery code */
/*************************************************************************/


/*************************************************************************/
/*! The recursive routine for DFS-based frequent pattern discovery */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of chars in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of chars in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of integers in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of integers in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of floats in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of floats in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of doubles in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of doubles in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_idx_t in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_idx_t in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_ckv_t in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_ckv_t in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_ikv_t in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_ikv_t in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_i32kv_t in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_i32kv_t in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_i64kv_t in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_i64kv_t in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_zkv_t in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_zkv_t in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_fkv_t in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_fkv_t in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_dkv_t in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_skv_t in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_skv_t in decreasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_idxkv_t in increasing order */
/*************************************************************************/


/*************************************************************************/
/*! Sorts an array of gk_idxkv_t in decreasing order */
/*************************************************************************/


/******************************************************************************
* Encode 3 '8-bit' binary bytes as 4 '6-bit' characters
*******************************************************************************/


/******************************************************************************
* Decode 4 '6-bit' characters into 3 '8-bit' binary bytes
*******************************************************************************/


/******************************************************************************
* This function encodes an input array of bytes into a base64 encoding. Memory
* for the output array is assumed to have been allocated by the calling program
* and be sufficiently large. The output string is NULL terminated.
*******************************************************************************/


/******************************************************************************
* This function decodes an input array of base64 characters into their actual
* 8-bit codes. Memory * for the output array is assumed to have been allocated
* by the calling program and be sufficiently large. The padding is discarded.
*******************************************************************************/


/*************************************************************************
* This function opens a file
**************************************************************************/


/******************************************************************************
* This function creates the hash-table
*******************************************************************************/


/******************************************************************************
* This function resets the data-structures associated with the hash-table
*******************************************************************************/


/******************************************************************************
* This function resizes the hash-table
*******************************************************************************/


/******************************************************************************
* This function inserts a key-value pair in the array
*******************************************************************************/


/******************************************************************************
* This function deletes key from the htable
*******************************************************************************/


/******************************************************************************
* This function returns the data associated with the key in the hastable
*******************************************************************************/


/******************************************************************************
* This function returns the next key/val
*******************************************************************************/


/**********************************************************************
 * This function computes the max accuracy score of a ranked list,
 * given +1/-1 class list
 **********************************************************************/


/*****************************************************************************
 * This function computes the ROC score of a ranked list, given a +1/-1 class
 * list.
 ******************************************************************************/


/*****************************************************************************
* This function computes the median rate of false positive for each positive
* instance.
******************************************************************************/


/*********************************************************
 * Compute the mean
 ********************************************************/


/********************************************************
 * Compute the standard deviation
 ********************************************************/


/***************************************************************************
* This function sets a number of signal handlers and sets the return point
* of a longjmp
****************************************************************************/


/***************************************************************************
* This function sets the handlers for the signals to their default handlers
****************************************************************************/


/*************************************************************************/
/*! \brief Thread-safe implementation of strerror() */
/**************************************************************************/


/*************************************************************************
* This function prints a backtrace of calling functions
**************************************************************************/


/*************************************************************************
* This function returns the CPU seconds
**************************************************************************/


/*************************************************************************
* This function is my wrapper around realloc
**************************************************************************/


/*************************************************************************
* This function is my wrapper around free, allows multiple pointers
**************************************************************************/


/*************************************************************************
* This function returns the current ammount of dynamically allocated
* memory that is used by the system
**************************************************************************/


/*************************************************************************
* This function returns the maximum ammount of dynamically allocated
* memory that was used by the system
**************************************************************************/


/*************************************************************************/
/*! This function prints final statistics */
/*************************************************************************/


/*************************************************************************/
/*! This function computes the compactness of the graph's adjacency list */
/*************************************************************************/


/*************************************************************************/
/*! This function uses a centroid-based approach to refine the ordering */
/*************************************************************************/


/*************************************************************************/
/*! This is the callback function for the itemset discovery routine */
/*************************************************************************/


/*************************************************************************/
/*! This function performs a multilevel bisection */
/*************************************************************************/


/*************************************************************************/
/*! This function splits a graph into two based on its bisection */
/*************************************************************************/


/*************************************************************************/
/*! This function performs a node-based FM refinement */
/**************************************************************************/


/*************************************************************************
* This function performs an edge-based FM refinement
**************************************************************************/


/*************************************************************************/
/*! This function performs a cut-focused FM refinement */
/*************************************************************************/


/*************************************************************************/
/*! This function performs a cut-focused multi-constraint FM refinement */
/*************************************************************************/


/*************************************************************************/
/*! Prints statistics about the refinement */
/*************************************************************************/


/*************************************************************************
*  genmmd  -- multiple minimum external degree
*  purpose -- this routine implements the minimum degree
*     algorithm. it makes use of the implicit representation
*     of elimination graphs by quotient graphs, and the notion
*     of indistinguishable nodes. It also implements the modifications
*     by multiple elimination and minimum external degree.
*     Caution -- the adjacency vector adjncy will be destroyed.
*  Input parameters --
*     neqns -- number of equations.
*     (xadj, adjncy) -- the adjacency structure.
*     delta  -- tolerance value for multiple elimination.
*     maxint -- maximum machine representable (short) integer
*               (any smaller estimate will do) for marking nodes.
*  Output parameters --
*     perm -- the minimum degree ordering.
*     invp -- the inverse of perm.
*     *ncsub -- an upper bound on the number of nonzero subscripts
*               for the compressed storage scheme.
*  Working parameters --
*     head -- vector for head of degree lists.
*     invp  -- used temporarily for degree forward link.
*     perm  -- used temporarily for degree backward link.
*     qsize -- vector for size of supernodes.
*     list -- vector for temporary linked lists.
*     marker -- a temporary marker vector.
*  Subroutines used -- mmdelm, mmdint, mmdnum, mmdupd.
**************************************************************************/


/***************************************************************************
*    mmdint ---- mult minimum degree initialization
*    purpose -- this routine performs initialization for the
*       multiple elimination version of the minimum degree algorithm.
*    input parameters --
*       neqns  -- number of equations.
*       (xadj, adjncy) -- adjacency structure.
*    output parameters --
*       (head, dfrow, backward) -- degree doubly linked structure.
*       qsize -- size of supernode ( initialized to one).
*       list -- linked list.
*       marker -- marker vector.
****************************************************************************/


/****************************************************************************
* mmdnum --- multi minimum degree numbering
* purpose -- this routine performs the final step in producing
*    the permutation and inverse permutation vectors in the
*    multiple elimination version of the minimum degree
*    ordering algorithm.
* input parameters --
*     neqns -- number of equations.
*     qsize -- size of supernodes at elimination.
* updated parameters --
*     invp -- inverse permutation vector. on input,
*             if qsize[node] = 0, then node has been merged
*             into the node -invp[node]; otherwise,
*            -invp[node] is its inverse labelling.
* output parameters --
*     perm -- the permutation vector.
****************************************************************************/


/****************************************************************************
* mmdupd ---- multiple minimum degree update
* purpose -- this routine updates the degrees of nodes after a
*            multiple elimination step.
* input parameters --
*    ehead -- the beginning of the list of eliminated nodes
*             (i.e., newly formed elements).
*    neqns -- number of equations.
*    (xadj, adjncy) -- adjacency structure.
*    delta -- tolerance value for multiple elimination.
*    maxint -- maximum machine representable (short) integer.
* updated parameters --
*    mdeg -- new minimum degree after degree update.
*    (head, forward, backward) -- degree doubly linked structure.
*    qsize -- size of supernode.
*    list -- marker vector for degree update.
*    *tag   -- tag value.
****************************************************************************/


/*************************************************************************/
/*! This function allocates memory for 2-way node-based refinement */
/**************************************************************************/


/*************************************************************************/
/*! This function computes the edegrees[] to the left & right sides */
/*************************************************************************/


/*************************************************************************/
/*! This function projects the node-based bisection */
/*************************************************************************/


/*************************************************************************/
/*! This function creates and sets the run parameters (ctrl_t) */
/*************************************************************************/


/*************************************************************************/
/*! Computes the per-partition/constraint balance multipliers */
/*************************************************************************/


/*************************************************************************/
/*! This function prints the various control fields */
/*************************************************************************/


/*************************************************************************/
/*! This function checks the validity of user-supplied parameters */
/*************************************************************************/


/*************************************************************************/
/*! This function frees the memory associated with a ctrl_t */
/*************************************************************************/


/*****************************************************************************/
/*! This function creates the dual of a finite element mesh */
/*****************************************************************************/


/*****************************************************************************/
/*! This function creates the (almost) nodal of a finite element mesh */
/*****************************************************************************/


/*************************************************************************/
/*! This function creates and initializes a mesh_t structure */
/*************************************************************************/


/*************************************************************************/
/*! This function deallocates any memory stored in a mesh */
/*************************************************************************/


/*************************************************************************/
/*! This function is the entry point of refinement */
/*************************************************************************/


/*************************************************************************/
/*! This function allocates memory for 2-way edge refinement */
/*************************************************************************/


/*************************************************************************/
/*! This function computes the initial id/ed */
/*************************************************************************/


/*************************************************************************/
/*! Projects a partition and computes the refinement params. */
/*************************************************************************/


/*************************************************************************
* This function computes cuts and balance information
**************************************************************************/


/*************************************************************************
* This function computes the balance of the partitioning
**************************************************************************/


/*************************************************************************
* This function computes the balance of the element partitioning
**************************************************************************/


/*************************************************************************/
/*! This function is the entry point of cut-based refinement */
/*************************************************************************/


/*************************************************************************/
/*! This function allocates memory for the k-way cut-based refinement */
/*************************************************************************/


/*************************************************************************/
/*! This function computes the initial id/ed  for cut-based partitioning */
/**************************************************************************/


/*************************************************************************/
/*! This function computes the boundary definition for balancing. */
/*************************************************************************/


/*************************************************************************/
/*! This function computes the initial gains in the communication volume */
/*************************************************************************/


/*************************************************************************
* This function partitions a finite element mesh by partitioning its nodal
* graph using KMETIS and then assigning elements in a load balanced fashion.
**************************************************************************/


/*************************************************************************
* This function partitions a finite element mesh by partitioning its dual
* graph using KMETIS and then assigning nodes in a load balanced fashion.
**************************************************************************/


/*************************************************************************
* This function is the entry poidx_t of the bisection balancing algorithms.
**************************************************************************/


/*************************************************************************
* This function balances two partitions by moving boundary nodes
* from the domain that is overweight to the one that is underweight.
**************************************************************************/


/*************************************************************************
* This function balances two partitions by moving the highest gain
* (including negative gain) vertices to the other domain.
* It is used only when tha unbalance is due to non contigous
* subdomains. That is, the are no boundary vertices.
* It moves vertices from the domain that is overweight to the one that
* is underweight.
**************************************************************************/


/*************************************************************************/
/*! This function changes the numbering to start from 0 instead of 1 */
/*************************************************************************/


/*************************************************************************/
/*! This function changes the numbering to start from 1 instead of 0 */
/*************************************************************************/


/*************************************************************************/
/*! The top-level routine of the actual multilevel node bisection */
/*************************************************************************/


/*************************************************************************
* This function takes a bisection and constructs a minimum weight vertex
* separator out of it. It uses the node-based separator refinement for it.
**************************************************************************/


/*************************************************************************
* This function takes a bisection and constructs a minimum weight vertex
* separator out of it. It uses an unweighted minimum-cover algorithm
* followed by node-based separator refinement.
**************************************************************************/


/*************************************************************************/
/*! This function computes the initial bisection of the coarsest graph */
/*************************************************************************/


/*************************************************************************/
/*! This function computes the initial separator of the coarsest graph */
/*************************************************************************/


/*************************************************************************
* This function uses simple counting sort to return a permutation array
* corresponding to the sorted order. The keys are arsumed to start from
* 0 and they are positive.  This sorting is used during matching.
**************************************************************************/


/*************************************************************************/
/*! This function returns max_i(x[i]-y[i]) */
/**************************************************************************/


/*************************************************************************/
/*! This function returns true if \forall i, x[i] <= z[i]. */
/**************************************************************************/


/*************************************************************************/
/*! This function returns true if \forall i, x[i] >= z[i]. */
/**************************************************************************/


/*************************************************************************/
/*! This function returns true if \forall i, a*x[i]+y[i] <= z[i]. */
/**************************************************************************/


/*************************************************************************/
/*! This function returns true if \forall i, a*x[i]+y[i] >= z[i]. */
/**************************************************************************/


/*************************************************************************/
/*! Computes the load imbalance of each constraint across the partitions. */
/**************************************************************************/


/* Sorts based both on key and val */


/*************************************************************************/
/*! This function moves a collection of vertices and updates their rinfo */
/*************************************************************************/


/*************************************************************************
* This function clears the timers
**************************************************************************/


/*************************************************************************
* This function prints the various timers
**************************************************************************/


/*************************************************************************/
/*! This function allocates memory for the workspace */
/*************************************************************************/


/*************************************************************************/
/*! This function allocates refinement-specific memory for the workspace */
/*************************************************************************/


/*************************************************************************/
/*! This function frees the workspace */
/*************************************************************************/


/*************************************************************************/
/*! This function gets the next free index from cnbrpool */
/*************************************************************************/


/*************************************************************************/
/*! This function gets the next free index from vnbrpool */
/*************************************************************************/


/*************************************************************************
* This function returns the min-cover of a bipartite graph.
* The algorithm used is due to Hopcroft and Karp as modified by Duff etal
* adj: the adjacency list of the bipartite graph
*       asize: the number of vertices in the first part of the bipartite graph
* bsize-asize: the number of vertices in the second part
*        0..(asize-1) > A vertices
*        asize..bsize > B vertices
*
* Returns:
*  cover : the actual cover (array)
*  csize : the size of the cover
**************************************************************************/


/*************************************************************************
* This function perfoms a restricted DFS and augments matchings
**************************************************************************/


/*************************************************************************
* This function performs a coarse decomposition and determines the
* min-cover.
* REF: Pothen ACMTrans. on Amth Software
**************************************************************************/


/*************************************************************************
* This function perfoms a dfs starting from an unmatched col node
* forming alternate paths
**************************************************************************/


/*************************************************************************/
/*! This function is the entry point for MCKMETIS */
/*************************************************************************/


/*************************************************************************/
/*! This function performs a quick check of the weights of the graph */
/*************************************************************************/


/*************************************************************************/
/*! This function bisects a graph by computing a vertex separator */
/**************************************************************************/


/*************************************************************************/
/*! This function sets up the graph from the user input */
/*************************************************************************/


/*************************************************************************/
/*! Set's up the tvwgt/invtvwgt info */
/*************************************************************************/