/*
 * PML.H - header support Portable Mathematics Library
 *
 * Source Version: 2.0
 * Software Release #92-0043
 *
 */

#include "cpyright.h"

#ifndef PCK_PML

#define PCK_PML

/* Think C compiler defines THINK_C; CodeWarrior defines __MWERKS__ */

#ifdef THINK_C
# include "score.h"
#else
# ifdef __MWERKS__
#  include "score.h"
# else
#  include <score.h>
# endif
#endif


/* C++ programs will have to explicitly include mlcplx.h if they
 * want a complex type and don't have it
 */

#ifndef __cplusplus
#include "mlcplx.h"
#endif

#undef PI
#define PI        3.1415926535897931

#define RAD_DEG  57.295779513082323
#define DEG_RAD   0.017453292519943295

#define Z_CENT     -1                                      /* zone centered */
#define N_CENT     -2                                      /* node centered */
#define F_CENT     -3                                      /* face centered */
#define E_CENT     -4                                      /* edge centered */
#define U_CENT     -5                                         /* uncentered */

#define TOLERANCE 1.0e-10

#ifndef HYPOT
#define HYPOT hypot
#endif

#ifndef PM_random
#define PM_random PM_random_48
#endif

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

/*                          PROCEDURAL MACROS                               */

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

/* PM_SAME - return TRUE if the points are too close */

#define PM_SAME(x1, y1, x2, y2)                                              \
    ((ABS(x1-x2) < TOLERANCE) && (ABS(y1-y2) < TOLERANCE))

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

/* PM_CLOSETO_ABS - return TRUE if the numbers are close enough */

#define PM_CLOSETO_ABS(x1, x2)                                               \
    ((ABS(x1-x2) < TOLERANCE))

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

/* PM_CLOSETO_REL - return TRUE if the numbers are close enough */

#define PM_CLOSETO_REL(x1, x2)                                               \
    ((2.0*ABS(x1-x2)/(ABS(x1)+ABS(x2)+SMALL) < TOLERANCE))

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

/* PM_LESS_LESS - return TRUE if |x| << |y| as defined by TOLERANCE
 *              - NOTE: this breaks down is |y| ~ SMALL
 */

#define PM_LESS_LESS(x, y) (ABS(x)/(ABS(y) + SMALL) < TOLERANCE)

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

/* PM_ELEMENT - access a matrix element */

#define PM_element(mp, r, c) (*((mp->array) + (r-1)*(mp->ncol) + c-1))

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

/* PM_LOGICAL_ZONE - define a template for logical rectangular meshes */

#define PM_LOGICAL_ZONE(b, b1, b2, b3, b4, kx)                               \
   {b1 = b + 1;                                                              \
    b2 = b1 + kx;                                                            \
    b3 = b2 - 1;                                                             \
    b4 = b;}

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

/* PM_INTERP - interpolate between a pair of points */

#define PM_interp(val, xp, x0, y0, x1, y1)                                   \
   xta = (x0);                                                               \
   xtb = (x1);                                                               \
   xtc = (xp);                                                               \
   yta = (y0);                                                               \
   ytb = (y1);                                                               \
   if (xta != xtb)                                                           \
      val = yta + (ytb - yta)*(xtc - xta)/(xtb - xta);                       \
   else                                                                      \
      val = 0.5*(yta + ytb)

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

#define PM_CHECK_EMAP(alist, n, eflag, emap)                                 \
   {pcons *info;                                                             \
    char  *cemap;                                                            \
    if (eflag == FALSE)                                                      \
       {info = SC_assoc_entry(alist, "EXISTENCE");                           \
        if (info != NULL)                                                    \
           {if (strcmp(info->cdr_type, SC_STRING_S) != 0)                    \
               {cemap = NULL;                                                \
                CONVERT(SC_CHAR_S, &cemap, info->cdr_type, emap, n, FALSE);  \
                eflag = TRUE;                                                \
                emap = cemap;};};};}

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

#define PM_DELTA_CROSS_2D(x1, y1, x2, y2, x3, y3)                            \
    (((x2)-(x1))*((y3)-(y1)) - ((x3)-(x1))*((y2)-(y1)))

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

/*                         STRUCT DEFINITIONS                               */

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

typedef struct s_PM_lagrangian_mesh PM_lagrangian_mesh;
typedef struct s_coefficient coefficient;
typedef struct s_C_array C_array;
typedef struct s_PM_matrix PM_matrix;
typedef struct s_PM_field PM_field;
typedef struct s_PM_conic_curve PM_conic_curve;
typedef struct s_PM_end_point PM_end_point;
typedef struct s_PM_side PM_side;
typedef struct s_PM_part PM_part;
typedef struct s_PM_mesh PM_mesh;
typedef struct s_PM_mesh_topology PM_mesh_topology;
typedef struct s_PM_set PM_set;
FUNCTION_POINTER(PM_set, *(*PFPPM_set));
typedef struct s_PM_map_info PM_map_info;
typedef struct s_PM_mapping PM_mapping;
FUNCTION_POINTER(PM_mapping, *(*PFPPM_mapping));
typedef struct s_sort_link sort_link;

struct s_PM_lagrangian_mesh
   {REAL *x;
    REAL *y;
    int kmax;
    int lmax;};

struct s_coefficient
   {int n_points;
    int *indexes;
    REAL *weights;};


/* C_ARRAY - define an encapulated vector/array type
 *         - this is PD_defstr'd in PANACE.C changes must be reflected there!!!
 */

struct s_C_array
   {char *type;                                                /* data type */
    long length;                                      /* number of elements */
    byte *data;};                                    /* pointer to the data */


/* PM_MATRIX - specify a 2d rank matrix */

struct s_PM_matrix
   {int nrow;
    int ncol;
    REAL *array;};


/* FIELD - specify the operations which define the field for a set
 *       - depending on which members are NULL one is left with an
 *       - algebra, a ring, a group, etc
 */

struct s_PM_field
   {PFByte add;
    PFByte sub;
    PFByte scalar_mult;
    PFByte mult;
    PFByte div;};

/* PM_CONIC_CURVE - quadratic line descriptor
 *                - this is PD_defstr'd in PDBX.C
 */

struct s_PM_conic_curve
   {char *type;
    REAL xx;
    REAL xy;
    REAL yy;
    REAL x;
    REAL y;
    REAL c;};


/* PM_END_POINT - line segment end point for mesh generation
 *              - this is PD_defstr'd in PDBX.C
 */

struct s_PM_end_point
   {REAL rn;
    REAL rx;
    int k;
    int dk;
    REAL rat;
    REAL drn;
    REAL drx;
    PM_end_point *next;};


/* PM_SIDE - mesh patch edge descriptor
 *         - this is PD_defstr'd in PDBX.C
 */

struct s_PM_side
   {REAL x;
    REAL y;
    REAL ratio;
    int dk;
    int dl;
    int k;
    int l;
    REAL side_rat;
    REAL min_dr_f;
    REAL max_dr_f;
    REAL mag_start;
    REAL exp_start;
    REAL mag_end;
    REAL exp_end;
    int fill;
    REAL scale;
    REAL cosine;
    REAL sine;
    REAL c0;
    REAL c1;
    REAL c2;
    REAL c3;
    int dir;
    PM_conic_curve *crve;
    PM_side *match;
    PM_side *next;};


/* PM_PART - mesh patch part descriptor
 *         - this is PD_defstr'd in PDBX.C
 */

struct s_PM_part
   {int n_sides;
    PM_side *leg;
    PM_end_point *ends;
    byte *comp;
    char *name;
    int reg;
    REAL k_ratio;
    REAL k_mag_start;
    REAL k_exp_start;
    REAL k_mag_end;
    REAL k_exp_end;
    REAL l_ratio;
    REAL l_mag_start;
    REAL l_exp_start;
    REAL l_mag_end;
    REAL l_exp_end;
    PM_part *next;};


/* PM_MESH - mesh patch descriptor */

struct s_PM_mesh
   {int kmin;
    int kmax;
    int lmin;
    int lmax;
    int n_zones;
    int n_nodes;
    int frn;
    int lrn;
    int frz;
    int lrz;
    int *reg_map;
    REAL *zone;
    REAL *nodet;
    REAL *rx;
    REAL *ry;
    REAL *kra;
    REAL *lra;
    REAL *apk;
    REAL *apl;};


/* MESH_CELL - description of a cell in a mesh topology hierarchy
 *           - the cell information is kept as a contiguous block of
 *           - long integer values (n_bound_params) in an array
 *           - describing a list of n dimensional cells which are either
 *           - the highest dimensional units or boundary elements of (n+1)
 *           - dimensional cells.
 *           -
 *           - Different simulations want more or less information for
 *           - optimization purposes, but it is all integer and
 *           - accompanying the list of cells, is a number specifying
 *           - the number of values used to describe the cells. These
 *           - values are listed here in order of importance from
 *           - mandatory to least likely to be used:
 *           -    BND_CELL_MIN       beg block of bounding (N-1)-cells
 *           -    BND_CELL_MAX       end block of bounding (N-1)-cells
 *           -    OPPOSITE_CELL      N-cell which has opposite orientation
 *           -    PARENT_CELL        (N+1)-cell of whose bnd this is a part
 *           -    NGB_CELL           (N+1)-cell parent neighbor sharing this
 *           -    CENTER_CELL        0-cell which is center of this cell
 *           -    DEC_CELL_MIN       beg of block of decomposition N-cells
 *           -    DEC_CELL_MAX       end of block of decomposition N-cells
 *           - Acceptable values for number of values are: 
 *           -    BND_CELL_MAX, OPPOSITE_CELL, PARENT_CELL, NGB_CELL,
 *           -    CENTER_CELL, and DEC_CELL_MAX
 *           -
 *           - There is redundancy in this information. It is permitted
 *           - for computational efficiency, however. This is especially
 *           - useful since an application can use the minimal
 *           - representation and avoid the redundancy.
 *           -
 *           - for the bottom of the hierarchy the BND_CELL_MIN and
 *           - BND_CELL_MAX indices refer to node indices not a contiguous
 *           - block of MESH_CELL value indices in another level of the
 *           - heirarchy
 */

#define BND_CELL_MIN  0
#define BND_CELL_MAX  1
#define OPPOSITE_CELL 2
#define PARENT_CELL   3
#define NGB_CELL      4
#define CENTER_CELL   5
#define DEC_CELL_MIN  6
#define DEC_CELL_MAX  7

/* MESH_TOPOLOGY - attempt to describe in complete generality a
 *               - mesh of points and their neighbors as a heirarchy
 *               - in which the highest dimensional volumes sit at
 *               - the top and the line segment descriptions sit
 *               - at the bottom.
 *               - A place is kept for the nodes and is in fact used
 *               - to record the number of nodes in the mesh. This
 *               - is the level 0 of the heirarchy.
 *               - At each level in the heirarchy an n-dimensional
 *               - surface is described by a contiguous block of
 *               - (n-1)-dimensional boundary sections (next lower
 *               - down in the heirarchy.
 *               -
 *               - assuming the dimensionality to be n the heirarchy
 *               - goes like:
 *               - boundaries[n]   - the description for the n-dim surfaces
 *               - boundaries[n-1] - the description for the (n-1)-dim surfaces
 *               -            .
 *               -            .
 *               -            .
 *               -
 *               - boundaries[1]   - the description for the 1-dim surfaces
 *               -                 - i.e. line segments whose endpoints
 *               -                 - are the node indices
 *               - boundaries[0]   - a mimimal description for the nodes
 */

struct s_PM_mesh_topology
   {int n_dimensions;              /* number of dimensions */
    int *n_bound_params;           /* number of bound params at each level */
    int *n_cells;                  /* number of cells at each level */
    long **boundaries;};           /* boundary info array at each level */


/* SET - attempt to describe a usefully general mathematical set for
 *     - purposes of data I/O (PDBLib), graphics (PGS), data
 *     - analysis (ULTRA and SX)
 *     -
 *     -    name           - every set should have a unique identifier so
 *     -                   - that large identical sets don't happen
 *     -    element_type   - the type of elements in the set so that sets are
 *     -                   - self-describing
 *     -    dimension      - the dimensionality of the set
 *     -    max_index      - an array of the maximum index along each
 *     -                   - dimension such that the product of max_index
 *     -                   - should equal dimension
 *     -    dimension_elem - the dimensionality of an element
 *     -                   - this permits things such as 3 vectors on 2 spheres   
 *     -    n_elements     - the number of elements in the set
 *     -    elements       - a pointer to the actual elements of the set
 *     -    es_type        - the type of the extrema and the scales arrays
 *     -                   - typically, element_type is "double **" while
 *     -                   - es_type is "double *"
 *     -    extrema        - an array of minimum and maximum values,
 *     -                   - respectively, for each component
 *     -                   - extrema is 2*dimension_elem long
 *     -    scales         - an array of scales for each dimension
 *     -                   - which is used in some mathematical operations
 *     -                   - such as interpolation
 *     -                   - NOTE: it is unclear what this means if
 *     -                   -       dimension != dimension_elem
 *     -    opers          - specifies the field for the set
 *     -    metric         - a metric if the set has or needs one
 *     -    symmetry_type  - a string to identify the type of the symmetries
 *     -                   - member
 *     -    symmetry       - a pointer to some object (struct or function)
 *     -                   - describing the symmetries of the set
 *     -    topology_type  - a string to identify the type of the topology
 *     -                   - member
 *     -    topology       - a pointer to some object describing the topology
 *     -                   - of the set e.g. connectivity and ordering
 *     -    info_type      - a string to identify the type of the info
 *     -                   - member
 *     -    info           - a pointer to some object containing any other
 *     -                   - information about the set
 *     -
 *     - Assume that for anything after elements which is NULL that a set
 *     - is a part of flat, singly connected Euclidean N space over the
 *     - field of reals (REALs) and has a logical mesh structure 
 */

struct s_PM_set
   {char *name;
    char *element_type;
    int dimension;
    int *max_index;
    int dimension_elem;
    long n_elements;
    byte *elements;
    char *es_type;
    byte *extrema;
    byte *scales;
    PM_field *opers;
    REAL *metric;
    char *symmetry_type;                         /* describe any symmetries */
    byte *symmetry;
    char *topology_type;              /* describe ordering and connectivity */
    byte *topology;
    char *info_type;                  /* provide any additional information */
    byte *info;
    struct s_PM_set *next;};


/* PM_MAP_INFO - should tell how two sets (domain and range) are to
 *             -  be combined for purposes of manipulation and graphics
 *             - this information should help to interpret the range as the
 *             - image of the domain and all such issues
 *             - as disparate sizes (injections, surjections, and 
 *             - bijections) should be dealt with.
 *             - at the moment the pressing example to be dealt with is that
 *             - of centering
 */

struct s_PM_map_info
   {char *name;
    int centering;};


struct s_PM_mapping
   {char *name;                                       /* the mapping's name */
    char *category;                /* the category to which mapping belongs */
    PM_set *domain;                                 /* the mapping's domain */
    PM_set *range;             /* a subset of the image of DOMAIN under MAP */
    char *map_type;             /* describe the data type pointed to by map */
    byte *map;         /* describe the mapping between the DOMAIN and RANGE */
    int file_type;                          /* file type ASCII, BINARY, PDB */
    byte *file_info;           /* file info - cast to some struct with info */
    char *file;                                    /* file name for mapping */
    struct s_PM_mapping *next;};


struct s_sort_link
   {int count;
    struct s_sort_link *next;};


#ifdef __cplusplus
extern "C" {
#endif

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

/*                          VARIABLE DECLARATIONS                           */

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

extern char
 *PM_AC_S,
 *PM_LR_S,
 *PM_MAP_INFO_S,
 *PM_MAPPING_S,
 *PM_SET_S,
 *PM_MAP_INFO_P_S,
 *PM_MAPPING_P_S,
 *PM_MESH_TOPOLOGY_S,
 *PM_MESH_TOPOLOGY_P_S,
 *PM_SET_P_S,
 PM_error[];

extern PM_field
 *PM_REAL_Opers,
 *PM_Int_Opers,
 *PM_Long_Opers;

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

/*                          FUNCTION DECLARATIONS                           */

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


/* MLICGS.C declarations */

extern REAL
 SC_DECLARE(_PM_iccg_s,
	    (int km, int lm, double eps, int maxit,
	     REAL *a0, REAL *a1, REAL *b0, REAL *b1, REAL *bm1,
	     REAL *x, REAL *y, int neq, int method));


/* MLICCG.C declarations */

extern REAL
 SC_DECLARE(PM_iccg,
	    (int km, int lm, double eps, int ks, int maxit,
	     REAL *a0, REAL *a1, REAL *b0, REAL *b1, REAL *bm1,
	     REAL *x, REAL *y)),
 SC_DECLARE(_PM_iccg_v,
	    (int km, int lm, double eps, int ks, int maxit,
	     REAL *a0, REAL *a1, REAL *b0, REAL *b1, REAL *bm1,
	     REAL *x, REAL *y)),
 SC_DECLARE(PM_dot, (REAL *x, REAL *y, int n));


/* MLINTP.C declarations */

extern byte
 *SC_DECLARE(PM_connectivity, (PM_mapping *f));

extern void
 SC_DECLARE(PM_zone_centered_mesh_2d,
	    (REAL **px, REAL **py, REAL *rx, REAL *ry,
	     int kmax, int lmax)),
 SC_DECLARE(_PM_spline,
	    (REAL *x, REAL *y, int n, double yp1, double ypn, REAL *d2y));

extern REAL
 *SC_DECLARE(PM_zone_node_lr_2d, (REAL *f, byte *cnnct, pcons *alist)),
 *SC_DECLARE(PM_node_zone_lr_2d, (REAL *f, byte *cnnct, pcons *alist)),
 *SC_DECLARE(PM_zone_node_ac_2d, (REAL *f, byte *cnnct, pcons *alist)),
 *SC_DECLARE(PM_node_zone_ac_2d, (REAL *f, byte *cnnct, pcons *alist)),
 **SC_DECLARE(PM_interpol,
	      (PM_lagrangian_mesh *grid, REAL **pts,
	       int n_pts, REAL **fncs, int n_fncs)),
 SC_DECLARE(PM_interpolate_value, (coefficient *vertices, REAL *f));

extern int
 SC_DECLARE(PM_inside, 
            (double x, double y, REAL *px, REAL *py, int *map, int n)),
 SC_DECLARE(PM_inside_fix, 
            (int x, int y, int *px, int *py, int n, int direct)),
 SC_DECLARE(PM_find_vertices,
	    (double x, double y,
	     PM_lagrangian_mesh *grid, coefficient *vertices)),
 SC_DECLARE(PM_find_coefficients,
	    (double x, double y,
	     PM_lagrangian_mesh *grid, coefficient *vertices)),
 SC_DECLARE(PM_cubic_spline_int,
	    (REAL *fx, REAL *fy, REAL *d2y, int n, double x, REAL *py));

extern coefficient
 *SC_DECLARE(PM_alloc_vertices, (PM_lagrangian_mesh *grid));


/* MLMATR.C declarations */

extern PM_matrix
 *SC_DECLARE(PM_create, (int nrow, int ncol)),
 *SC_DECLARE(PM_transpose, (PM_matrix *a)),
 *SC_DECLARE(PM_times, (PM_matrix *a, PM_matrix *b)),
 *SC_DECLARE(PM_plus, (PM_matrix *a, PM_matrix *b)),
 *SC_DECLARE(PM_minus, (PM_matrix *a, PM_matrix *b)),
 *SC_DECLARE(PM_zero, (PM_matrix *a)),
 *SC_DECLARE(PM_ident, (PM_matrix *a)),
 *SC_DECLARE(PM_copy, (PM_matrix *to, PM_matrix *from)),
 *SC_DECLARE(_PM_negative_times, (PM_matrix *m, PM_matrix *a, PM_matrix *b)),
 *SC_DECLARE(_PM_times, (PM_matrix *c, PM_matrix *a, PM_matrix *b)),
 *SC_DECLARE(_PM_plus, (PM_matrix *c, PM_matrix *a, PM_matrix *b)),
 *SC_DECLARE(_PM_minus, (PM_matrix *c, PM_matrix *a, PM_matrix *b)),
 *SC_DECLARE(_PM_transpose, (PM_matrix *m, PM_matrix *a)),
 *SC_DECLARE(PM_print, (PM_matrix *a));

extern int
 SC_DECLARE(PM_destroy, (PM_matrix *mp));


/* MLRAND.C declarations */

extern void
 SC_DECLARE(PM_srand_48, (double x));

extern double
 SC_DECLARE(PM_grand_48, (byte)),
 SC_DECLARE(PM_random_48, (double x)),
 SC_DECLARE(PM_random_s, (double x));


/* MLSOLV.C declarations */

extern int
 SC_DECLARE(PM_block_rsys_elim, (REAL *a, REAL *b, REAL *c, REAL *u,
				 int ns, int nb, int *elim_flag)),
 SC_DECLARE(PM_block_nf_backsub, (REAL *a, REAL *c, REAL *u,
				  int ns, int nb, int *lnbrs)),
 SC_DECLARE(PM_block_tridi_nf, (REAL *af, REAL *a, REAL *b, REAL *c, REAL *cl, REAL *u,
				int nf, int nb, int nl, int ns, int *lnbrs)),
 SC_DECLARE(PM_block_tridi, 
            (REAL *a, REAL *b, REAL *c, REAL *u, int ns, int nb)),
 SC_DECLARE(PM_tridi, 
            (REAL *a, REAL *b, REAL *c, REAL *r, REAL *u, int n));

extern REAL
 SC_DECLARE(PM_determinant, (PM_matrix *a));

extern PM_matrix
 *SC_DECLARE(PM_solve, (PM_matrix *a, PM_matrix *b)),
 *SC_DECLARE(PM_decomp, 
             (PM_matrix *a, int *ips, int flag, int *pnc)),
 *SC_DECLARE(PM_decompose, (PM_matrix *a, int *ips, int flag)),
 *SC_DECLARE(PM_sol, 
             (PM_matrix *ul, PM_matrix *b, int *ips, int flag)),
 *SC_DECLARE(PM_inverse, (PM_matrix *a)),
 *SC_DECLARE(PM_upper, (PM_matrix *a)),
 *SC_DECLARE(PM_lower, (PM_matrix *a)),
 *SC_DECLARE(PM_decb, 
             (int n, int ml, int mu, PM_matrix *b, int *ip)),
 *SC_DECLARE(PM_solb, 
             (int n, int ml, int mu, 
              PM_matrix *b, PM_matrix *y, int *ips));


/* MLFFT.C declarations */

extern int
 SC_DECLARE(PM_near_power, (int n, int a)),
 SC_DECLARE(PM_next_exp_two, (int n)),
 SC_DECLARE(PM_next_power_two, (int n)),
 SC_DECLARE(PM_convolve,
	    (REAL *gx, REAL *gy, int gn, REAL *hx, REAL *hy, int hn,
	     double dt, REAL **pxr, REAL **pyr, int *pnr)),
 SC_DECLARE(PM_convolve_logical,
	    (REAL *g, int n, REAL *h, int m, int isign, REAL *cnv)),
 SC_DECLARE(PM_fft_sc_real_simul,
	    (REAL *fx1, REAL *fx2, REAL *fw1, REAL *fw2, int n));


/* MLGEOM.C declarations */

extern int
 SC_DECLARE(PM_cross,
	    (double x1, double y1, double x2, double y2,
	     double x3, double y3, double x4, double y4,
	     double *px0, double *py0)),
 SC_DECLARE(PM_cross_seg,
	    (double x1, double y1, double x2, double y2,
	     double x3, double y3, double x4, double y4,
	     double *px0, double *py0)),
 SC_DECLARE(PM_cross_line_plane, (double x1, double y1, double z1,
				  double x2, double y2, double z2,
				  REAL *px, REAL *py, REAL *pz,
				  REAL *px0, REAL *py0, REAL *pz0,
				  int line)),
 SC_DECLARE(PM_colinear_2d, (REAL *px, REAL *py, int n)),
 SC_DECLARE(PM_colinear_3d, (REAL *px, REAL *py, REAL *pz, int n)),
 SC_DECLARE(PM_contains_2d, (double x, double y,
			     REAL *px, REAL *py, int n)),
 SC_DECLARE(PM_contains_3d, (double x, double y, double z,
			     REAL *px, REAL *py, REAL *pz, int bnd)),
 SC_DECLARE(PM_intersect_line_polygon,
	    (REAL *pxmn, REAL *pymn, REAL *pxmx, REAL *pymx,
	     REAL *ppx, REAL *ppy, int np, int *pic));

extern void
 SC_DECLARE(PM_convex_hull, (REAL *p1, REAL *p2, int nh,
			     REAL **ppx, REAL **ppy, int *pnp)),
 SC_DECLARE(PM_nearest_point, (REAL *px, REAL *py, int n,
			       double xs, double ys, REAL *pxt, REAL *pyt,
			       int *pi));


/* MLMATH.C declarations */

extern void
 SC_DECLARE(PM_derivative,
	    (int n, REAL *fncx, REAL *fncy,
	     REAL *derx, REAL *dery)),
 SC_DECLARE(PM_scale_array, (double *p, int n, double f)),
 SC_DECLARE(PM_shift_array, (double *p, int n, double f)),
 SC_DECLARE(PM_set_value, (REAL *p, int n, double f)),
 SC_DECLARE(PM_copy_array, (REAL *s, REAL *t, int n));

extern int
 SC_DECLARE(PM_set_opers, (PM_set *set)),
 SC_DECLARE(PM_thin_1d_der,
	    (int n, REAL *fncx, REAL *fncy, REAL *thnx, REAL *thny,
	     double toler)),
 SC_DECLARE(PM_thin_1d_int,
	    (int n, REAL *fncx, REAL *fncy, REAL *thnx, REAL *thny,
	     double toler)),
 SC_DECLARE(PM_filter_coeff, (REAL *y, int n, REAL *coef, int nc)),
 SC_DECLARE(PM_smooth_int_ave, (REAL *x, REAL *y, int n, int pts));

extern double
 SC_DECLARE(PM_romberg, 
            (PFDouble func, double x0, double x1, double tol)),
 SC_DECLARE(PM_integrate_tzr,
	    (double xmn, double xmx, int *pn,
	     REAL *fncx, REAL *fncy, REAL *intx, REAL *inty)),
 SC_DECLARE(PM_random, (double x)),
 SC_DECLARE(PM_sqr, (double x)),
 SC_DECLARE(PM_sqrt, (double x)),
 SC_DECLARE(PM_recip, (double x)),
 SC_DECLARE(PM_atan, (double x, double y)),
 SC_DECLARE(PM_ln, (double x)),
 SC_DECLARE(PM_log, (double x)),
 SC_DECLARE(PM_j0, (double x)),
 SC_DECLARE(PM_j1, (double x)),
 SC_DECLARE(PM_jn, (double x, double n)),
 SC_DECLARE(PM_y0, (double x)),
 SC_DECLARE(PM_y1, (double x)),
 SC_DECLARE(PM_yn, (double x, double n)),
 SC_DECLARE(PM_tchn, (double x, double n)),
 SC_DECLARE(PM_pow, (double x, double y)),
 SC_DECLARE(PM_power, (double x, int p)),
 SC_DECLARE(PM_sign, (double x)),
 SC_DECLARE(PM_round, (double x)),
 SC_DECLARE(PM_frac, (double x)),
 SC_DECLARE(PM_fix, (double value)),
 SC_DECLARE(PM_sgn, (double value, double sign)),
 SC_DECLARE(PM_hypot, (double x, double y)),
 SC_DECLARE(PM_curve_len_2d, (REAL *x, REAL *y, int n)),
 SC_DECLARE(PM_curve_len_3d, 
            (REAL *x, REAL *y, REAL *z, int n));


/* MLMM.C declarations */

extern PM_set
 *SC_DECLARE(PM_make_set_alt, (char *name, char *type, int cp, int nd,
			       int *diml, int nde, byte **elml)),
 *SC_DECLARE(PM_make_set, (char *name, char *type, int rl,
			   int nd, ...)),
 *SC_DECLARE(PM_make_ac_set, (char *name, char *type, int cp,
			      PM_mesh_topology *mt, int nde, ...)),
 *SC_DECLARE(_PM_make_set,
	     (char *name, char *type, int rl, long ne,
	      int nd, int nde,
	      int *maxes, byte *elem, PM_field *opers,
	      REAL *metric, char *symtype, byte *sym,
	      char *toptype, byte *top, char *inftype, byte *inf,
	      PM_set *next)),
 *SC_DECLARE(PM_make_lr_domain, (char *name, char *type,
				 int nd, int nde, int *maxes,
				 REAL *extrema)),
 *SC_DECLARE(PM_make_cp_domain, (char *name, char *type, int nd,
				 PM_set **sets));

extern PM_mesh_topology
 *SC_DECLARE(PM_make_topology, (int nd, int *bnp, int *bnc, long **bnd));

extern PM_mapping
 *SC_DECLARE(PM_make_mapping,
	     (char *name, char *cat, PM_set *domain, PM_set *range,
	      int centering, PM_mapping *next)),
 *SC_DECLARE(PM_build_grotrian,
	     (char *name, char *type, int cp,
	      byte *xv, byte *yv, char **labels, int n_s,
	      byte *tr, byte *up, byte *low, int n_tr));

extern PM_mesh_topology
 *SC_DECLARE(PM_lr_ac_mesh_2d,
	     (REAL **px, REAL **py, int kmax, int lmax,
	      int k1, int k2, int l1, int l2, int ord));

extern void
 SC_DECLARE(PM_promote_array, (C_array *a, char *ntyp, int flag)),
 SC_DECLARE(PM_promote_set, (PM_set *s, char *ntyp, int flag)),
 SC_DECLARE(PM_find_extrema, (PM_set *s)),
 SC_DECLARE(PM_rel_set, (PM_set *set, int mfl)),
 SC_DECLARE(PM_rel_topology, (PM_mesh_topology *mt)),
 SC_DECLARE(PM_rel_mapping, 
            (PM_mapping *f, int rld, int rlr)),
 SC_DECLARE(PM_set_limits, (PM_set *s, REAL *extr));

extern pcons
 *SC_DECLARE(PM_mapping_info, (PM_mapping *h, ...)),
 *SC_DECLARE(PM_map_info_alist, (PM_map_info *ti));

extern REAL
 *SC_DECLARE(PM_array_real, 
             (char *type, byte *p, int n, REAL *x)),
 *SC_DECLARE(PM_get_limits, (PM_set *set));


/* MLNLS.C declarations */

extern double
 SC_DECLARE(PM_newtondl,
	    (int neqns, REAL *y, REAL *x, REAL *tol, int maxiter,
	     double atol, double rtol, PFVoid linsolv, byte *arg)),
 SC_DECLARE(PM_newtonul,
	    (int neqns, REAL *y, REAL *x, REAL *tol, int maxiter,
	     double atol, double rtol, PFVoid linsolv, byte *arg));


/* MLFPE.C declarations */

extern void
 SC_DECLARE(PM_enable_fpe, 
            (int flg, PFSignal_handler hand));


/* MLMESH.C declarations */

extern PM_mesh
 *SC_DECLARE(PM_make_lr_mesh,
	     (PM_part *parts, HASHTAB *curves,
	      int method, int constr,
	      double dspat, double drat, double orient));

/* MLCMSH.C declarations */

extern PM_conic_curve
 *SC_DECLARE(PM_mk_cline,
	     (char *type, double axx, double ayy, double axy,
	      double ax, double ay, double ac));

extern PM_side
 *SC_DECLARE(PM_mk_side,
	     (PM_conic_curve *cur, int dir, double x, double y,
	      int dk, int dl, double krat, double lrat,
	      double srat, double drn, double drx,
	      double ms, double es, double me, double ee,
	      PM_side *match, PM_side *next));

extern PM_part
 *SC_DECLARE(PM_mk_part,
	     (char *name, int rg, int nsides,
	      PM_side *leg, PM_end_point *ends,
	      byte *comp, double kms, double kes,
	      double kme, double kee, double krat,
	      double lms, double les, double lme,
	      double lee, double lrat, PM_part *next));

extern PM_end_point
 *SC_DECLARE(PM_mk_endpt,
	     (double rn, double rx, int dk,
	      double rat, double drn, double drx,
	      PM_end_point *nxt));

extern int
 SC_DECLARE(PM_reg_base, (PM_part *parts, PM_side *base));

extern void
 SC_DECLARE(PM_mesh_part,
	    (REAL *rx, REAL *ry, REAL *nodet,
	     int *reg_map, int n, int k, int l,
	     int kmn, int kmx, int lmn, int lmx, 
	     int kmax, int lmax, int m,
	     double kr, double lr,
	     REAL *kra, REAL *lra, REAL *apk, REAL *apl,
	     double ask, double xsk, double aek, double xek,
	     double asl, double xsl, double ael, double xel,
	     int method, int constr,
	     double dspat, double drat, double orient));


/* MLOPER.C declarations */

extern int
 SC_DECLARE(PM_iplus, (int x, int y)),
 SC_DECLARE(PM_iminus, (int x, int y)),
 SC_DECLARE(PM_itimes, (int x, int y)),
 SC_DECLARE(PM_idivide, (int x, int y)),
 SC_DECLARE(PM_imodulo, (int x, int y));

extern long
 SC_DECLARE(PM_lplus, (long x, long y)),
 SC_DECLARE(PM_lminus, (long x, long y)),
 SC_DECLARE(PM_ltimes, (long x, long y)),
 SC_DECLARE(PM_ldivide, (long x, long y)),
 SC_DECLARE(PM_lmodulo, (long x, long y));

extern double
 SC_DECLARE(PM_fplus, (double x, double y)),
 SC_DECLARE(PM_fminus, (double x, double y)),
 SC_DECLARE(PM_ftimes, (double x, double y)),
 SC_DECLARE(PM_fdivide, (double x, double y)),
 SC_DECLARE(PM_fmin, (double x, double y)),
 SC_DECLARE(PM_fmax, (double x, double y));


/* MLSORT.C declarations */

extern int
 *SC_DECLARE(PM_t_sort, 
             (int *in, int n_dep, int n_pts, int *ord));

extern void
 SC_DECLARE(PM_q_sort, (REAL *z, int *ind, int n)),
 SC_DECLARE(PM_val_sort, (int n, REAL *xp, REAL *yp));


/* MLSRCH.C declarations */

extern void
 SC_DECLARE(PM_minmax, (byte *p, int n, byte *pn, byte *px,
			int *imin, int *imax)),
 SC_DECLARE(PM_maxmin, (REAL *xp, REAL *xmin, REAL *xmax, int n)),
 SC_DECLARE(PM_sub_array, (byte *in, byte *out, long *dims,
			   long *reg, long bpi)),
 SC_DECLARE(PM_search, 
            (int nx, REAL *x, int ny, REAL *y, int offs,
	     int *indx));

extern int
 SC_DECLARE(PM_find_index, (byte *p, double f, int n)),
 SC_DECLARE(PM_index_min, (double *p, int n));

extern double
 SC_DECLARE(PM_max_value, (double *p, int imin, int n));


#ifdef __cplusplus
}
#endif

#endif


