/*======================================================*/
/*  LIRL Laue Integrated Reflection List routines       */
/*======================================================*/

/*-Title: LAUE INTEGRATED REFLECTION LISTS (LIRL)
-end*/

/*-Intro:
This file contains a series of routines concerned with the allocation
and management of memory for lists of Laue reflection records containing
integrated reflection data. These are used to collate data from integrations
of single plates (using LDM based routines) and/or to collate integrated
intensity data for scaling & normalisation. 
-end*/

/*Routines:
The following routines are available:

     lirl_init        Allocate and initialise a reflections list
     lirl_addref      Add a reflection to a reflections list
     lirl_putref      Update reflection details for a reflection
     lirl_set_ovpix   Set number of overload pixels for a reflection
     lirl_set_outlier Set reflection 'outlier' flag
     lirl_set_refint  Set reflection reference intensity and sigma
     lirl_putksym     Update 'ksym' for a reflection
     lirl_setsym      Pass symmetry matrices to LIRL routines
     lirl_numrefs     Get number of reflections in a list
     lirl_sortord     Get sort order
     lirl_gethkl      Get reflection indices  for a reflection
     lirl_hklunq      Get unique reflection indices  for a reflection
     lirl_nodunq      Get unique nodal indice, lambda  for a reflection
     lirl_getref      Get reflection details for a reflection
     lirl_get_ovpix   Get number of overload pixels for a reflection
     lirl_get_outlier Get reflection 'outlier' flag value
     lirl_get_refint  Get reflection reference intensity and sigma
     lirl_sort        Sort reflection list (various options)
     lirl_delete      Delete reflections for pack(s) or plate(s)
     lirl_clear       Clear a reflections list
     lirl_free        Clear and free a reflections list

     The equivalent Fortran interface routines are named lirlf...

Additional routines for the Laue Scaling Module

     lirl_lsm_start       Prepare to read reflection sets 
     lirl_lsm_next        Read next reflection set
     lirl_lsm_settemp     Set temporary pre-calculated items for scaling
     lirl_lsm_setuse      Set temporary 'use_reflection' flag for scaling
     lirl_lsm_scalobs     Get items needed for calculating scaling factor
     lirl_lsm_getranges   Get stored norm/plate_scale ranges
*/

#include <stdlib.h>
#include <stdio.h>

#include "dml.h"

#include "lirl_systyp.h"
#include "lirl.h"

/* Define Fortran binding names */

#if    LINKTYP == 1

#define lirlf_init lirlf_init_
#define lirlf_addref lirlf_addref_ 
#define lirlf_putref lirlf_putref_
#define lirlf_set_ovpix lirlf_set_ovpix_
#define lirlf_set_outlier lirlf_set_outlier_
#define lirlf_set_refint lirlf_set_refint_
#define lirlf_putksym lirlf_putksym_
#define lirlf_setsym lirlf_setsym_
#define lirlf_numrefs lirlf_numrefs_
#define lirlf_sortord lirlf_sortord_
#define lirlf_gethkl lirlf_gethkl_
#define lirlf_hklunq lirlf_hklunq_
#define lirlf_nodunq lirlf_nodunq_
#define lirlf_getref lirlf_getref_
#define lirlf_get_ovpix lirlf_get_ovpix_
#define lirlf_get_outlier lirlf_get_outlier_
#define lirlf_get_refint lirlf_get_refint_
#define lirlf_sort lirlf_sort_
#define lirlf_delete lirlf_delete_
#define lirlf_clear lirlf_clear_
#define lirlf_free lirlf_free_
#define lirlf_lsm_start lirlf_lsm_start_
#define lirlf_lsm_next lirlf_lsm_next_
#define lirlf_lsm_settemp lirlf_lsm_settemp_
#define lirlf_lsm_setuse lirlf_lsm_setuse_
#define lirlf_lsm_scalobs lirlf_lsm_scalobs_
#define lirlf_lsm_getranges lirlf_lsm_getranges_

#endif

#if  LINKTYP == 2

#define lirlf_init LIRLF_INIT
#define lirlf_addref LIRLF_ADDREF 
#define lirlf_putref LIRLF_PUTREF
#define lirlf_set_ovpix LIRLF_SET_OVPIX
#define lirlf_set_outlier LIRLF_SET_OUTLIER
#define lirlf_set_refint LIRLF_SET_REFINT
#define lirlf_putksym LIRLF_PUTKSYM
#define lirlf_setsym LIRLF_SETSYM
#define lirlf_numrefs LIRLF_NUMREFS
#define lirlf_sortord LIRLF_SORTORD
#define lirlf_gethkl LIRLF_GETHKL
#define lirlf_hklunq LIRLF_HKLUNQ
#define lirlf_nodunq LIRLF_NODUNQ
#define lirlf_getref LIRLF_GETREF
#define lirlf_get_ovpix LIRLF_GET_OVPIX
#define lirlf_get_outlier LIRLF_GET_OUTLIER
#define lirlf_get_refint LIRLF_GET_REFINT
#define lirlf_sort LIRLF_SORT
#define lirlf_delete LIRLF_DELETE
#define lirlf_clear LIRLF_CLEAR
#define lirlf_free LIRLF_FREE
#define lirlf_lsm_start LIRLF_LSM_START
#define lirlf_lsm_next LIRLF_LSM_NEXT
#define lirlf_lsm_settemp LIRLF_LSM_SETTEMP
#define lirlf_lsm_setuse LIRLF_LSM_SETUSE
#define lirlf_lsm_scalobs LIRLF_LSM_SCALOBS
#define lirlf_lsm_getranges LIRLF_LSM_GETRANGES

#endif

void lirlf_init();
void lirlf_addref();
void lirlf_putref();
void lirlf_set_ovpix();
void lirlf_set_outlier();
void lirlf_set_refint();
void lirlf_putksym();
void lirlf_setsym();
void lirlf_numrefs();
void lirlf_sortord();
void lirlf_gethkl();
void lirlf_hklunq();
void lirlf_nodunq();
void lirlf_getref();
void lirlf_get_ovpix();
void lirlf_get_outlier();
void lirlf_get_refint();
void lirlf_sort();
void lirlf_delete();
void lirlf_clear();
void lirlf_free();
void lirlf_lsm_start();
void lirlf_lsm_next();
void lirlf_lsm_settemp();
void lirlf_lsm_setuse();
void lirlf_lsm_scalobs();
void lirlf_lsm_getranges();

typedef struct _LIRLpkpl
{
  int pack;
  int plate;
}LIRLpkpl;

#define MAXLISTS 10
#define two20 1048576
#define two12 4096
#define two10 1024


typedef struct _LIRLhead
{
   int in_use;          /* List in use flag =1 yes, =0 no */
   int dml_indx;        /* 'dml' memory list index; -1 for not set */
   int list_type;       /* = 0 Integrated spots list 
                           (for future expansion) */
   int coord_type;      /* Coordinate type = 0 in mm from pattern centre 
                                               (ideal)
                                           = 1 in mm from pattern centre 
                                               (distortion corrected) 
                                           = 2 in detector raster units */
   int sort_order;      /* Sort order =0 not sorted or unknown
                                      >0 sort code 'ityp' as used in
                                         latest successful lirl_sort call */
   float *rsym;         /* Pointer to symmetry matrices (stored as
                           in CCP4 & LDM symmetry routines). 0 if not set */
   float *rsymiv;       /* Pointer to inverted symmetry matrices (stored as
                           in CCP4 & LDM symmetry routines). 0 if not set */
}LIRLhead;

static LIRLhead lirl_head[MAXLISTS];

static int lirl_initialised=0;

typedef struct _LIRLreflection
{
   int hkl;                 /* Packed reflection indices as measured
                               2**20(h+512)+2**10(k+512)+l+512 
                               (of lowest harmonic present for a multiple) */
   float xfd;               /* xfd detector coordinate as defined by
                               coordinate type flag in header */
   float yfd;               /* yfd detector coordinate as defined by
                               coordinate type flag in header */
   float lambda;            /* Wavelength (of lowest harmonic present for 
                               a multiple) */
   float intensity;         /* Integrated intensity I */
   float sigint;            /* sig(I) */
   unsigned short pack;     /* Pack no. or index (>0) */
   unsigned char plate;     /* Plate no. */
   unsigned char ksym;      /* Symmetry no. 0=not defined (usually 0 if
                               measured/predicted indices stored or set
                               to symmetry no. if indices have been
                               converted to unique set */
   int mult_flags;          /* multiplicity flag   
                                 = 1 single
                                 > 1 2**20*mult + 2**12*min-hrm 
                                     + 2**4*max-hrm + harm_inc 
                                 = 0 deconvoluted multiple */
   unsigned char icode;     /* Integration routine specific flag 0-255 */
   unsigned spov : 1;       /* Spatially overlapped flag =1 yes, =0 no */
   unsigned clos : 1;       /* Too close for spatial deconvolution 
                               flag =1 yes, =0 no */
   unsigned measured : 1;   /* Spot has been integrated flag =1 yes, =0 no */
   unsigned bad  : 1;       /* Bad intensity (other than overload) flag
                               =1 yes, =0 no */
   unsigned ovld : 1;       /* Overload flag =1 yes, =0 no */
   unsigned novpix : 1;     /* No. of overloaded pixels stored flag
                               =1 yes, =0 no (if yes value is stored 
                               in num_ovpix */

                            /* Optional additional items */

   float ref_int;           /* Reference e.g. monochromatic intensity
                               (may be sign separated as values can be
                               stored for each individual reflection)  */
   float ref_sigint;        /* sigma(reference_intensity) 0.0 (the
                               default) if reference a intensity value 
                               is not present or available. */
   unsigned char num_ovpix; /* This may be used to store the number of
                               pixels in the spot above the overload
                               threshold (0-255). A value of 255 
                               indicates 255 or more overloaded pixels. */
   unsigned char outlier;   /* A reflection may be marked as an outlier
                               for use within a program. The use of this
                               flag will be program specific. The flag
                               must be in the range 0-255; 0 (the
                               default) indicates that the reflection 
                               has not been flagged as an outlier and any 
                               value > 0 indicates an outlier. */

                            /* Additional items for internal use by the
                               Laue Scaling Module (LSM) routines */

  int hkl_unq;              /* Packed unique reflection indices
                               2**20(h+512)+2**10(k+512)+l+512 
                               (of lowest harmonic present for a multiple) */
  float abscor_nu;          /* 'nu' coordinate for absorption correction 
                               surface in degrees */
  float abscor_psi_local;   /* 'psi' coordinate for absorption correction 
                               surface, local to pack (in degrees) */
  float abscor_psi_global;  /* 'psi' coordinate for absorption correction 
                               surface, global (wrt 1'st pack) (in degrees) */
  float stol2;              /* sin(theta)**2/lambda**2 */
  float al3c2t;             /* lambda**3/(cos(2*theta)) */
  float abscor_lamfn;       /* Lambda based function as used in absorption
                               correction mu(lam)/mu(lam_ref) or mu(lam) */
  float ob_lpfac;           /* Combined obliquity factor, Lorentz and
                               Polarisation factor */
  unsigned char norm_range; /* Range no. of normalisation curve to use */   
  unsigned char filmsc_range;  
                            /* Range to use for 'plate to plate' scaling */
  unsigned char  use_reflection;
                            /* A flag set by LSM_TOP_LIRL indicating, for
                               each reflection, whether or not it is to
                               be returned by routines such as LSM_NEXT_REFLN
                               and LSM_NEXT_SCALOBS as determined by the
                               current reflection selection criteria. */   
}LIRLreflection;

/* NOTE: For a deconvoluted multiple, only the following items will
         be used: hkl, intensity, siging, ksym, mult_flags=0,
         measured=1 and optionally, ref_int, ref_sigint. */

/* Global data items for LSM routines */

                      /* Items set by lirl_lsm_start to be used by 
                         lirl_lsm_next */
int list_indx;        /* Index for dml records */
int num_refs;         /* No. of reflection records */
int eof;              /* End of file reached flag */
int first;            /* First refflection set flag */
int last_hkl;         /* Last used hkl found */
int last_sign;        /* Last used reflection sign found */
int sign_sep;         /* Treat as sign separated data */
int iref_cur;         /* Current reflection list index (from 1 up) */

/*-Section: Creating and Writing 'LIRL' lists
Routines are available to create new LIRL reflection lists, to add records
to such lists and to modify data in such lists.
-end*/

/*-Routine: Allocate and initialise a reflections list  - lirl_init
The routine lirl_init (lirlf_init) checks to see if a spare slot is available
and, if so, allocates the memory for a new Laue integrated reflections list 
(LIPL) with an initial allocation of records. The routine returns an index 
(handle) to be used in all other routines for accessing that list.
-end*/

/*                                            
***********************
**    lirl_init      **
***********************

Purpose: Allocate and initialise a Laue Integrated Reflections List

Author:  John W. Campbell, October 1995

CD-Fortran:
         CALL LIRLF_INIT  (INIT_ALLOC, INT_ALLOC, LIST_TYPE, 
        +                  ICOORD_TYPE, MINDX)
CD-end
*/
/*-Parameters:
INIT_ALLOC   i  (R)  Initial allocation required (no. of reflection
                     records).
INC_ALLOC    i  (R)  No. of records by which to extend the 
                     reflections list each time an extension is 
                     required.
LIST_TYPE    i  (R)  = 0 Integrated spots list 
                     (others reserved for future expansion)
ICOORD_TYPE  i  (R)  Coordinate type flag 
                       =0 in mm from pattern centre (ideal)
                       =1 in mm from pattern centre (distortion 
                          corrected)
                       =2 in detector raster units
MINDX        i  (W)  Index for the allocated reflection list (>=0)
                     A negative return value indicates an error and
                     the value is the return code from the routine
                     lirl_init.
-end*/

/*-C:*/
int lirl_init (int init_alloc, int inc_alloc, int list_type, int coord_type)
/*end*/

/*-Parameters:
int init_alloc;      No. of records to be allocated initially (R)
int inc_alloc;       No. of records to be added each time an extension
                     to the list is required (R)
int list_type;       = 0 Integrated spots list (others reserved for future 
                     expansion) (R)
int coord_type       Coordinate type flag 
                     =0 in mm from pattern centre (ideal)
                     =1 in mm from pattern centre (distortion corrected)
                     =2 in detector raster units (R)

Return:  >=0, the index of the allocated list
          -1, no spare reflection lists available
          -2, no spare 'dml' memory lists available
          -3, cannot allocate initial memory
          -4, init_alloc<1 or inc_alloc<1
          -5, invalid list type 
          -6, invalid coordinate type 
-end*/
{
   int indx;
   int iret;
   int i;

   if (!lirl_initialised)
   { 
      for (i=0;i<MAXLISTS;++i)
      {
         lirl_head[i].in_use = 0;
         lirl_head[i].dml_indx = -1;
         lirl_head[i].list_type = -1;
         lirl_head[i].coord_type = 0;
         lirl_head[i].rsym = 0;
         lirl_head[i].rsymiv = 0;
      }
      lirl_initialised = 1;
   }
   if (init_alloc<1||inc_alloc<1) return -4;
   if (list_type!=0) return -5;
   if (coord_type<0||coord_type>2) return -6;
   iret = -1;
   for (i=0;i<MAXLISTS;++i)
   {
      if (lirl_head[i].in_use==0)
      {
         indx = dml_init (init_alloc, inc_alloc, sizeof(LIRLreflection));
         if (indx>=0)
	 {
            lirl_head[i].in_use = 1;
            lirl_head[i].dml_indx = indx;
            lirl_head[i].list_type = list_type;
            lirl_head[i].coord_type = coord_type;
            lirl_head[i].rsym = 0;
            lirl_head[i].rsymiv = 0;
            iret = i;
	 }
         else
	 {
            iret = indx - 1;
	 }
         break;
      }
   }
   return iret;
}

/* Fortran binding: lirlf_init */

void lirlf_init (int * init_alloc, int * inc_alloc, int *list_type, 
                 int *icoord_type, int *mindx)
{
   *mindx = lirl_init (*init_alloc, *inc_alloc, *list_type, *icoord_type);
   return;
}

/*-Routine: Add a reflection to a reflections list  - lirl_addref
The routine lirl_addref (lirlf_addref) adds a new reflection to 
the end of the requested Laue integrated reflections list providing 
that the list has been initialised and that sufficient memory is available 
or can be allocated for it. The routine sets values for the main items
and default values for the optional additional items.
-end*/

/*                                            
************************
**    lirl_addref     **
************************

Purpose: Add a reflection record to a Laue integrated reflections list

Author:  John W. Campbell, October 1995


CD-Fortran:
         CALL LIRLF_ADDREF  (MINDX, IH, IK, IL, IPACK, IPLATE, KSYM, 
        +                    XFD, YFD, ALAM,
        +                    MULT, MINHARM, MAXHARM, INCHARM, AI, SIGI,
        +                    ISPAT, ICLOS, IMEAS, IBAD, IOVLD, 
        +                    ICODE, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IH           i  (R)  Reflection 'h' index (as measured) (lowest harmonic 
IK           i  (R)  Reflection 'k' index (as measured)  present for a
IL           i  (R)  Reflection 'l' index (as measured)  multiple)
IPACK        i  (R)  Pack no. or index (1-65535)
IPLATE       i  (R)  Plate number within pack
KSYM         i  (R)  Symmetry no. (0 if not yet determined)
XFD          r  (R)  'xfd' coordinate of spot (units as defined by
                     ICOORD_TYPE in LIRLF_INIT call)
YFD          r  (R)  'yfd' coordinate of spot (units as defined by
                     ICOORD_TYPE in LIRLF_INIT call)
ALAM         r  (R)  Wavelength (for lowest harmonic present for a
                     multiple)
MULT         i  (R)  Multiplicity (1=single) (0=deconvoluted multiple)
MINHARM      i  (R)  Minimum harmonic (if MULT > 1)
MAXHARM      i  (R)  Maximum harmonic (if MULT > 1)
INCHARM      i  (R)  Harmonics increment (if MULT > 1)
AI           r  (R)  Integrated intensity
SIGI         r  (R)  Standard deviation of integrated intensity
ISPAT        i  (R)  Spatially overlapped flag =1 yes, =0 no
ICLOS        i  (R)  Spot too close to deconvolute flag =1 yes, =0 no
IMEAS        i  (R)  Integration done flag =1 yes, =0 no
IBAD         i  (R)  Bad spot other than overload flag =1 yes, =0 no
IOVLD        i  (R)  Intensity overload flag =1 yes, =0 no
ICODE        i  (R)  Code specific to integration routine (0-255)
IERR         i  (W)  Error return code from lirl_addref

   Indices are for lowest harmonic present for a multiple

   For a deconvoluted multiple, the following items are ignored:
   IPACK, IPLATE, XFD, YFD, ALAM, MINHARM, MAXHARM, INCHARM. ISPAT, ICLOS,
   IMEAS (treated as 1), IBAD, IOVLD, ICODE. Normally the indices will 
   be the unique ones and KSYM will be 1. Note also that the intensity
   and sigma(intensity) values are already normalised and scaled.
-end*/

/*-C:*/
int lirl_addref (int mindx, int h, int k, int l, int ipack, int iplate,
                 int ksym, float xfd, float yfd, float alam, int mult,
                 int minharm, int maxharm, int incharm, float ai, float sigi,
                 int ispat, int iclos, int imeas,
                 int ibad, int iovld, int icode)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int h;           Reflection 'h' index (as measured) (R) (lowest harmonic
int k;           Reflection 'k' index (as measured) (R)  presennt for a
int l;           Reflection 'l' index (as measured) (R)  multiple)
int ipack;       Pack no. or index (1-65535) (R)
int iplate;      Plate number within pack (R)
int ksym;        Symmetry no. (0 if not yet determined) (R)
float xfd;       'xfd' coordinate of spot (units as defined by 
                 coord_type in lirl_init call) (R)
float yfd;       'yfd' coordinate of spot  (units as defined by 
                 coord_type in lirl_init call (R)
float alam;      Wavelength (for lowest harmonic present for a
                 multiple) (R)
int mult;        Multiplicity (1=single) (R)
int minharm;     Minimum harmonic (if mult!=1) (R)
int maxharm;     Maximum harmonic (if mult!=1) (R)
int incharm;     Harmonics increment (if mult!=1) (R)
float ai;        Integrated intensity (R)
float sigi;      Standard deviation of integrated intensity (R)
int ispat;       Spatially overlapped flag =1 yes, =0 no (R)
int iclos;       Spot too close to deconvolute flag =1 yes, =0 no (R)
int imeas;       Integration done flag =1 yes, =0 no (R)
int ibad;        Bad spot other than overload flag =1 yes, =0 no (R)
int iovld;       Intensity overload flag =1 yes, =0 no (R)
int icode;       Code specific to integration routine (0-255) (R) 

    Indices are for lowest harmonic present for a multiple 

    For a deconvoluted multiple, the following items are ignored:
    ipack, iplate, xfd, yfd, alam, minharm, maxharm, incharm. ispat, iclos,
    imeas (treated as 1), ibad, iovld, icode. Normally the indices will 
    be the unique ones and KSYM will be 1. Note also that the intensity
    and sigma(intensity) values are already normalised and scaled.


Return:  =  0, OK
         = -1, Invalid index given or list not initialised
         = -2, Cannot allocate required memory 
-end*/
{
   LIRLreflection refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;

   refl.hkl = two20*(h+512)+two10*(k+512)+l+512;
   refl.xfd = xfd;
   refl.yfd = yfd;
   refl.lambda = alam;
   refl.intensity = ai;
   refl.sigint = sigi;
   refl.pack = ipack;
   refl.plate = iplate;
   refl.ksym = ksym;
   refl.mult_flags = 1;
   if (mult>1) refl.mult_flags = two20*mult + two12*minharm 
                                  + 16*maxharm + incharm; 
   if (mult<0) mult = 0;
   refl.icode = icode;
   refl.spov = 0; if (ispat!=0) refl.spov = 1;
   refl.clos = 0; if (iclos!=0) refl.clos = 1;
   refl.measured = 0; if (imeas!=0) refl.measured = 1;
   refl.bad = 0; if (ibad!=0) refl.bad = 1;
   refl.ovld = 0; if (iovld!=0) refl.ovld = 1;

   if (mult==0)
   {
      refl.mult_flags = 0;
      refl.xfd = 0.0;
      refl.yfd = 0.0;
      refl.lambda = 0.0;
      refl.pack = 0;
      refl.plate = 0;
      refl.icode = icode;
      refl.spov = 0;
      refl.clos = 0;
      refl.measured = 1;
      refl.bad = 0;
      refl.ovld = 0;
   }

   refl.ref_int = 0.0;
   refl.ref_sigint = 0.0;
   refl.novpix = 0;
   refl.num_ovpix = 0;
   refl.outlier = 0;

   refl.abscor_nu = 0.0;
   refl.abscor_psi_local = 0.0;
   refl.abscor_psi_global = 0.0;
   refl.stol2 = 0.0;
   refl.al3c2t = 0.0;
   refl.abscor_lamfn = 0.0;
   refl.ob_lpfac = 0.0;
   refl.norm_range = 0;
   refl.filmsc_range = 0;
   refl.use_reflection = 0;

   return dml_addrec (dml_indx, (void *) &refl);
}

/* Fortran binding: lirlf_addref */

void lirlf_addref (int *mindx, int *h, int *k, int *l, 
                   int *ipack, int *iplate, int *ksym,
                   float *xfd, float *yfd, float *alam,
                   int *mult, int *minharm, int *maxharm, int *incharm,
                   float *ai, float *sigi, 
                   int *ispat, int *iclos, int *imeas, int *ibad, int *iovld,
                   int *icode, int *ierr)
{
   *ierr = lirl_addref (*mindx, *h, *k, *l, *ipack, *iplate, *ksym,
                        *xfd, *yfd, *alam, *mult, *minharm, *maxharm, *incharm,
                        *ai, *sigi, *ispat, *iclos, *imeas,
                        *ibad, *iovld, *icode);
   return;
}

/*-Routine: Update a reflection in a reflections list  - lirl_putref
The routine lirl_putref (lirlf_putref) updates a reflection in
a Laue integrated reflections list. The routine sets values for the main 
items and leaves unchanged any values currently stored for the optional 
additional items.
-end*/

/*                                            
************************
**    lirl_putref     **
************************

Purpose: Update a reflection record in a Laue integrated reflections list

Author:  John W. Campbell, October 1995


CD-Fortran:
         CALL LIRLF_PUTREF  (MINDX, IREF, IH, IK, IL, IPACK, IPLATE, KSYM, 
        +                    XFD, YFD, ALAM,
        +                    MULT, MINHARM, MAXHARM, INCHARM, AI, SIGI,
        +                    ISPAT, ICLOS, IMEAS, IBAD, IOVLD, 
        +                    ICODE, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards)  
IH           i  (R)  Reflection 'h' index (as measured) (lowest harmonic 
IK           i  (R)  Reflection 'k' index (as measured)  present for a 
IL           i  (R)  Reflection 'l' index (as measured)  multiple)
IPACK        i  (R)  Pack no. or index (1-65535)
IPLATE       i  (R)  Plate number within pack
KSYM         i  (R)  Symmetry no. (0 if not yet determined)
XFD          r  (R)  'xfd' coordinate of spot (units as defined by
                     ICOORD_TYPE in LIRLF_INIT call)
YFD          r  (R)  'yfd' coordinate of spot (units as defined by
                     ICOORD_TYPE in LIRLF_INIT call)
ALAM         r  (R)  Wavelength (for lowest harmonic present for a
                     multiple)
MULT         i  (R)  Multiplicity (1=single) (0=deconvoluted multiple)
MINHARM      i  (R)  Minimum harmonic (if MULT > 1)
MAXHARM      i  (R)  Maximum harmonic (if MULT > 1)
INCHARM      i  (R)  Harmonics increment (if MULT > 1)
AI           r  (R)  Integrated intensity
SIGI         r  (R)  Standard deviation of integrated intensity
ISPAT        i  (R)  Spatially overlapped flag =1 yes, =0 no
ICLOS        i  (R)  Spot too close to deconvolute flag =1 yes, =0 no
IMEAS        i  (R)  Integration done flag =1 yes, =0 no
IBAD         i  (R)  Bad spot other than overload flag =1 yes, =0 no
IOVLD        i  (R)  Intensity overload flag =1 yes, =0 no
ICODE        i  (R)  Code specific to integration routine (0-255)
IERR         i  (W)  Error return code from lirl_putref

   For a deconvoluted multiple, the following items are ignored:
   IPACK, IPLATE, XFD, YFD, ALAM, MINHARM, MAXHARM, INCHARM. ISPAT, ICLOS,
   IMEAS (treated as 1), IBAD, IOVLD, ICODE. Normally the indices will 
   be the unique ones and KSYM will be 1. Note also that the intensity
   and sigma(intensity) values are already normalised and scaled.
-end*/

/*-C:*/
int lirl_putref (int mindx, int iref, int h, int k, int l, 
                 int ipack, int iplate,
                 int ksym, float xfd, float yfd, float alam, int mult,
                 int minharm, int maxharm, int incharm, float ai, float sigi,
                 int ispat, int iclos, int imeas,
                 int ibad, int iovld, int icode)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int iref;        Reflection number (from 1 upwards) (R)
int h;           Reflection 'h' index (as measured) (R) (lowest harmonic
int k;           Reflection 'k' index (as measured) (R)  present for a
int l;           Reflection 'l' index (as measured) (R)  multiple)
int ipack;       Pack no. or index (1-65535) (R)
int iplate;      Plate number within pack (R)
int ksym;        Symmetry no. (0 if indices are as measured) (R)
float xfd;       'xfd' coordinate of spot (units as defined by 
                  coord_type in lirl_init call) (R)
float yfd;       'yfd' coordinate of spot (units as defined by 
                  coord_type in lirl_init call) (R)
float alam;      Wavelength (for lowest harmonic present for a
                 multiple) (R)
int mult;        Multiplicity (1=single) (R)
int minharm;     Minimum harmonic (if mult!=1) (R)
int maxharm;     Maximum harmonic (if mult!=1) (R)
int incharm;     Harmonics increment (if mult!=1) (R)
float ai;        Integrated intensity (R)
float sigi;      Standard deviation of integrated intensity (R)
int ispat;       Spatially overlapped flag =1 yes, =0 no (R)
int iclos;       Spot too close to deconvolute flag =1 yes, =0 no (R)
int imeas;       Integration done flag =1 yes, =0 no (R)
int ibad;        Bad spot other than overload flag =1 yes, =0 no (R)
int iovld;       Intensity overload flag =1 yes, =0 no (R)
int icode;       Code specific to integration routine (0-255) (R)

   For a deconvoluted multiple, the following items are ignored:
   ipack, iplate, xfd, yfd, alam, minharm, maxharm, incharm. ispat, iclos,
   imeas (treated as 1), ibad, iovld, icode. Normally the indices will 
   be the unique ones and KSYM will be 1. Note also that the intensity
   and sigma(intensity) values are already normalised and scaled.

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   refl->hkl = two20*(h+512)+two10*(k+512)+l+512;
   refl->xfd = xfd;
   refl->yfd = yfd;
   refl->lambda = alam;
   refl->intensity = ai;
   refl->sigint = sigi;
   refl->pack = ipack;
   refl->plate = iplate;
   refl->ksym = ksym;
   refl->mult_flags = 1;
   if (mult>1) refl->mult_flags = two20*mult + two12*minharm 
                                  + 16*maxharm + incharm; 
   if (mult<0) mult = 0;
   refl->icode = icode;
   refl->spov = 0; if (ispat!=0) refl->spov = 1;
   refl->clos = 0; if (iclos!=0) refl->clos = 1;
   refl->measured = 0; if (imeas!=0) refl->measured = 1;
   refl->bad = 0; if (ibad!=0) refl->bad = 1;
   refl->ovld = 0; if (iovld!=0) refl->ovld = 1;

   if (mult==0)
   {
      refl->xfd = 0.0;
      refl->yfd = 0.0;
      refl->lambda = 0.0;
      refl->pack = 0;
      refl->plate = 0;
      refl->icode = icode;
      refl->spov = 0;
      refl->clos = 0;
      refl->measured = 1;
      refl->bad = 0;
      refl->ovld = 0;
   }
   return 0;
}

/* Fortran binding: lirlf_putref */

void lirlf_putref (int *mindx, int *iref, int *h, int *k, int *l, 
                   int *ipack, int *iplate, int *ksym,
                   float *xfd, float *yfd, float *alam,
                   int *mult, int *minharm, int *maxharm, int *incharm,
                   float *ai, float *sigi,
                   int *ispat, int *iclos, int *imeas, int *ibad, int *iovld,
                   int *icode, int *ierr)
{
   *ierr = lirl_putref (*mindx, *iref, *h, *k, *l, *ipack, *iplate, *ksym,
                        *xfd, *yfd, *alam, *mult, *minharm, *maxharm, *incharm,
                        *ai, *sigi, *ispat, *iclos, *imeas,
                        *ibad, *iovld, *icode);
   return;
}
/*-Routine: Set number of overload pixels  - lirl_set_ovpix
The routine lirl_set_ovpix (lirlf_set_ovpix) sets the value for the
number of overload pixels found for a reflection.
-end*/

/*                                            
**************************
**    lirl_set_ovpix    **
**************************

Purpose: Update a reflection record in a Laue integrated reflections list
         with the number of overload pixels item

Author:  John W. Campbell, May 1997


CD-Fortran:
         CALL LIRLF_SET_OVPIX  (MINDX, IREF, NUM_OVPIX, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards) 
NUM_OVPIX    i  (R)  The number of overload pixels (-1 = not known)
                     (Values > 255 stored as 255)
IERR         i  (W)  Error return code from lirl_set_ovpix 
-end*/

/*-C:*/
int lirl_set_ovpix (int mindx, int iref, int num_ovpix)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int iref;        Reflection number (from 1 upwards) (R)
int num_ovpix;   The number of overload pixels (-1 = not known)
                 (Values > 255 stored as 255) (R)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   if (num_ovpix<0)
   { 
      refl->novpix = 0;
      refl->num_ovpix = 0;
   }
   else
   {
      if (num_ovpix>255) num_ovpix = 255;
      refl->novpix = 1;
      refl->num_ovpix = num_ovpix;
   }
   return 0;
}

/* Fortran binding: lirlf_set_ovpix */

void lirlf_set_ovpix (int *mindx, int *iref, int *num_ovpix, int *ierr) 
{
   *ierr = lirl_set_ovpix (*mindx, *iref, *num_ovpix);
   return;
}

/*-Routine: Set reflection 'outlier' flag  - lirl_set_outlier
The routine lirl_set_outlier (lirlf_set_outlier) sets the value for the
for a reflection 'outlier' flag. 
-end*/

/*                                            
**************************
**    lirl_set_outlier  **
**************************

Purpose: Update a reflection record in a Laue integrated reflections list
         with the 'outlier' flag

Author:  John W. Campbell, May 1997


CD-Fortran:
         CALL LIRLF_SET_OUTLIER  (MINDX, IREF, ICODE, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards) 
ICODE        i  (R)  Program dependent flag 0-255; 0 indicates
                     that the reflection is OK (i.e. not an
                     outlier) and any value >0 indicates an
                     outlier.
IERR         i  (W)  Error return code from lirl_set_outlier 
-end*/

/*-C:*/
int lirl_set_outlier (int mindx, int iref, int icode)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int iref;        Reflection number (from 1 upwards) (R)
int icode;       Program dependent flag 0-255; 0 indicates
                 that the reflection is OK (i.e. not an outlier) 
                 and any value >0 indicates an outlier. (R)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   if (icode<0) icode = 0;
   if (icode>255) icode = 255;
   refl->outlier = icode;
   return 0;
}

/* Fortran binding: lirlf_set_outlier */

void lirlf_set_outlier (int *mindx, int *iref, int *icode, int *ierr) 
{
   *ierr = lirl_set_outlier (*mindx, *iref, *icode);
   return;
}

/*-Routine: Set reference intensity and sigma  - lirl_set_refint
The routine lirl_set_refint (lirlf_set_refint) sets the values
for a reflection reference intensity and its sigma value. 
-end*/

/*                                            
**************************
**    lirl_set_refint   **
**************************

Purpose: Update a reflection record in a Laue integrated reflections list
         with the reference intensity and its sigma

Author:  John W. Campbell, May 1997


CD-Fortran:
         CALL LIRLF_SET_REFINT  (MINDX, IREF, REFINT, SIGREF, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards) 
REFINT       r  (R)  The reference intensity.
SIGREF       r  (R)  sigma(reference intensity). A value of 0.0
                     indicates that the intensity is not present.
IERR         i  (W)  Error return code from lirl_set_refint 
-end*/

/*-C:*/
int lirl_set_refint (int mindx, int iref, float refint, float sigref)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int iref;        Reflection number (from 1 upwards) (R)
float refint;    The reference intensity. (R)
float sigref;    sigma(reference intensity). A value of 0.0
                 indicates that the intensity is not present. (R)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   if (sigref<=0.0)
   {
      sigref = 0.0;
      refint = 0.0;
   }
   refl->ref_int = refint;
   refl->ref_sigint = sigref;
   return 0;
}

/* Fortran binding: lirlf_set_refint */

void lirlf_set_refint (int *mindx, int *iref, float *refint, float *sigref,
                        int *ierr) 
{
   *ierr = lirl_set_refint (*mindx, *iref, *refint, *sigref);
   return;
}

/*-Routine: Update 'ksym' for a reflection - lirl_putksym
The routine lirl_putksym (lirlf_putksym) updates a reflection 'ksym' value in
a Laue integrated reflections list.
-end*/

/*                                            
************************
**    lirl_putksym    **
************************

Purpose: Update a reflection record in a Laue integrated reflections list
         with a new 'ksym' value

Author:  John W. Campbell, October 1995


CD-Fortran:
         CALL LIRLF_PUTKSYM  (MINDX, IREF, KSYM, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards)  
KSYM         i  (R)  Symmetry no. (0 if not yet determined)
IERR         i  (W)  Error return code from lirl_putksym
-end*/

/*-C:*/
int lirl_putksym (int mindx, int iref, int ksym)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int iref;        Reflection number (from 1 upwards) (R)
int ksym;        Symmetry no. (0 if indices are as measured) (R)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;

   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;
   refl->ksym = ksym;
   return 0;
}

/* Fortran binding: lirlf_putksym */

void lirlf_putksym (int *mindx, int *iref, int *ksym, int *ierr)
{
   *ierr = lirl_putksym (*mindx, *iref, *ksym);
   return;
}

/*-Routine: Pass symmetry matrices to LIRL routines - lirl_setsym
The routine lirl_setsym (lirlf_setsym) passes the symmetry matrices
(as defined in the CCP4 and LDM routines) to the LIRL routines for
internal use when indices need to be converted to various forms.
Note that the symmetry matrices must remain in place as copies are
not made.
-end*/

/*                                            
*************************
**    lirl_setsym      **
*************************

Purpose: Pass symmetry matrices to LIRL routines

Author:  John W. Campbell, October 1995

CD-Fortran:
         CALL LIRLF_SETSYM  (MINDX, RSYM, RSYMIV, IERR)
CD-end
*/
/*-Parameters:
MINDX          i  (R)  Index as returned by LIRLF_INIT
RSYM(4,4,96)   r  (R)  Symmetry matrices (as CCP4 & LDM)
RSYMIV(4,4,96) r  (R)  Inverse symmetry matrices (as CCP4 & LDM)
IERR           i  (W)  Error return code from lirl_setsym
-end*/

/*-C:*/
int lirl_setsym (int mindx, float *rsym, float *rsymiv)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
float * rsym;    Symmetry matrices (as CCP4 & LDM) - see Fortran 
                 call (R)
float * rsymiv;  Inverse symmetry matrices (as CCP4 & LDM) - see Fortran
                 call (R)

Return:  >= 0, The number of reflections
         = -1, Invalid index given or list not initialised
-end*/
{
   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   lirl_head[mindx].rsym = rsym;
   lirl_head[mindx].rsymiv = rsymiv;
   return 0;
}

/* Fortran binding: lirlf_setsym */

void lirlf_setsym (int *mindx, float *rsym, float *rsymiv, int *ierr)
{
   *ierr = lirl_setsym (*mindx, rsym, rsymiv);
   return;
}

/*-Section: Get Data from 'LIRL' Lists
Routines are available to get the number of reflection records and details
of the individual reflections from a Laue integrated reflections list.
-end*/

/*-Routine: Get number of reflections in a list  - lirl_numrefs
The routine lirl_numrefs (lirlf_numrefs) returns the number of 
reflections currently stored in a Laue integrated reflections list.
-end*/

/*                                            
*************************
**    lirl_numrefs     **
*************************

Purpose: Get no. of reflections in a Laue integrated reflections list

Author:  John W. Campbell, October 1995

CD-Fortran:
         CALL LIRLF_NUMREFS  (MINDX, NUMREFS)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
NUMREFS      i  (W)  No. of reflections in the reflections list. If
                     there is an error a value of -1 will be returned
                     from the lirl_numrefs call
-end*/

/*-C:*/
int lirl_numrefs (int mindx)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)

Return:  >= 0, The number of reflections
         = -1, Invalid index given or list not initialised
-end*/
{
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   return dml_numrecs (dml_indx);
}

/* Fortran binding: lirlf_numrefs */

void lirlf_numrefs (int *mindx, int*numrefs)
{
   *numrefs = lirl_numrefs (*mindx);
   return;
}
/*-Routine: Get sort order  - lirl_sortord
The routine lirl_sortord (lirlf_sortord) returns the current sort
order ('ityp' code as used in call to lirl_sort (lirlf_sort) call).
-end*/

/*                                            
*************************
**    lirl_sortord     **
*************************

Purpose: Get sort order

Author:  John W. Campbell, October 1995

CD-Fortran:
         CALL LIRLF_SORTORD  (MINDX, ISORT)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
ISORT        i  (W)  The sort order code (>0), 0=unknown. The code
                     is that was used as the 'ITYP' parameter in the
                     latest LIRLF_SORT call. If there is an error  
                     in the call, a value of -1 will be returned.
-end*/

/*-C:*/
int lirl_sortord (int mindx)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)

Return:  = 0, Sort order unknown
         > 0, The code is that was used as the 'ityp' parameter in 
              the latest 'lirl_sort' call.
         =-1, Invalid index given or list not initialised
-end*/
{
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   return lirl_head[mindx].sort_order;
}

/* Fortran binding: lirlf_sortord */

void lirlf_sortord (int *mindx, int *isort)
{
   *isort = lirl_sortord (*mindx);
   return;
}
/*-Routine: Get reflection indices for a reflection  - lirl_gethkl
The routine lirl_gethkl (lirlf_gethkl) gets the reflection indices and 
symmetry no. (if set) for a given reflection in a Laue integrated
reflection list.
-end*/

/*                                            
*************************
**    lirl_gethkl      **
*************************

Purpose: Get reflection indices from a Laue integrated reflections list

Author:  John W. Campbell, October 1995


CD-Fortran:
         CALL LIRLF_GETHKL  (MINDX, IREF, IH, IK, IL, KSYM, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards)
IH           i  (W)  Reflection 'h' index (as measured)
IK           i  (W)  Reflection 'k' index (as measured)
IL           i  (W)  Reflection 'l' index (as measured)
KSYM         i  (W)  Symmetry no. (0 if not yet set)
IERR         i  (W)  Error return code from lirl_gethkl
-end*/

/*-C:*/
int lirl_gethkl (int mindx, int iref, int *h, int *k, int *l, int *ksym)
/*end*/

/*-Parameters:
int mindx;        Index as returned by lirl_init (R)
int iref;         Reflection number (from 1 upwards) (R)
int *h;           Reflection 'h' index  (as measured) (W)
int *k;           Reflection 'k' index (as measured) (W)
int *l;           Reflection 'l' index (as measured) (W)
int ksym;         Symmetry no. (0 if not set) (W)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or reflection
               record not present.
-end*/
{
   LIRLreflection *refl;
   int jj;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;

   dml_indx = lirl_head[mindx].dml_indx;

   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;
   jj = refl->hkl; 
   *h = jj/two20;
   jj -= two20*(*h);
   *h -= 512;
   *k = jj/two10;
   *l = jj - two10*(*k) - 512;
   *k -= 512;
   *ksym = refl->ksym;
   return 0;
}
/* Fortran binding: lirlf_gethkl */

void lirlf_gethkl (int *mindx, int * iref, int *h, int *k, int *l, int *ksym, 
                   int *ierr)
{
   *ierr = lirl_gethkl (*mindx, *iref, h, k, l, ksym);
   return;
}
/*-Routine: Get unique reflection indices for a reflection  - lirl_hklunq
The routine lirl_hklunq (lirlf_hklunq) gets the unique reflection indices and 
for a given reflection in a Laue integrated reflection list. The symmetry
number must have been set (e.g using lirl_addref, lirl_putref or lirl_putksym
(lirlf_addref, lirlf_putref or lirlf_putksym) and the symmetry matrices must 
have been passed to the LIRL routines using the lirl_setsym (lirlf_setsym) 
routine.
-end*/

/*                                            
*************************
**    lirl_hklunq      **
*************************

Purpose: Get unique reflection indices from a Laue integrated reflections list

Author:  John W. Campbell, October 1995


CD-Fortran:
         CALL LIRLF_HKLUNQ  (MINDX, IREF, IH, IK, IL, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards)
IH           i  (W)  Reflection 'h' index (unique) (0 if error)
IK           i  (W)  Reflection 'k' index (unique) (0 if error)
IL           i  (W)  Reflection 'l' index (unique) (0 if error)
IERR         i  (W)  Error return code from lirl_hklunq
-end*/

/*-C:*/
int lirl_hklunq (int mindx, int iref, int *h, int *k, int *l)
/*end*/

/*-Parameters:
int mindx;        Index as returned by lirl_init (R)
int iref;         Reflection number (from 1 upwards) (R)
int *h;           Reflection 'h' index  (unique) (0 if error)(W)
int *k;           Reflection 'k' index (unique) (0 if error)(W)
int *l;           Reflection 'l' index (unique) (0 if error)(W)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or reflection
               record not present.
         = -2, symmetry no. not set
         = -3, symmetry matrices not defined
-end*/
{
   LIRLreflection *refl;
   int ih, ik, il;
   int jj;
   int is;
   int dml_indx;
   float *rs;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   if (lirl_head[mindx].rsym==0) return -3;

   dml_indx = lirl_head[mindx].dml_indx;

   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;
   if (refl->ksym==0) return -2;
   jj = refl->hkl; 
   ih = jj/two20;
   jj -= two20*ih;
   ih -= 512;
   ik = jj/two10;
   il = jj - two10*ik - 512;
   ik -= 512;
   if (refl->ksym==1)
   {
      *h = ih;
      *k = ik;
      *l = il;
      return 0;
   }
   is = (refl->ksym-1)/2;
   rs = &lirl_head[mindx].rsym[16*is];
   *h = ih*rs[0] + ik*rs[1] + il*rs[2];
   *k = ih*rs[4] + ik*rs[5] + il*rs[6];
   *l = ih*rs[8] + ik*rs[9] + il*rs[10];
   if (refl->ksym%2==0)
   {
     *h = -(*h);
     *k = -(*k);
     *l = -(*l);
   }
   return 0;
}
/* Fortran binding: lirlf_hklunq */

void lirlf_hklunq (int *mindx, int * iref, int *h, int *k, int *l, int *ierr)
{
   *ierr = lirl_hklunq (*mindx, *iref, h, k, l);
   return;
}

/*-Routine: Get unique nodal indices for a reflection  - lirl_nodunq
The routine lirl_nodunq (lirlf_nodunq) gets the unique nodal reflection 
indices and nodal lambda value for a given reflection in a Laue integrated 
reflection list. The symmetry number must have been set (e.g using 
lirl_addref, lirl_putref or lirl_putksym (lirlf_addref, lirlf_putref or 
lirlf_putksym) and the symmetry matrices must have been passed to the 
LIRL routines using the lirl_setsym (lirlf_setsym) routine.
-end*/

/*                                            
*************************
**    lirl_nodunq      **
*************************

Purpose: Get unique nodal reflection indices and nodal lambda value from 
         a Laue integrated reflections list reflection

Author:  John W. Campbell, October 1995


CD-Fortran:
         CALL LIRLF_NODUNQ  (MINDX, IREF, NH, NK, NL, ALNOD, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards)
NH           i  (W)  Reflection 'h' nodal index (unique) (0 if error)
NK           i  (W)  Reflection 'k' nodal index (unique) (0 if error)
NL           i  (W)  Reflection 'l' nodal index (unique) (0 if error)
ALNOD        r  (W)  Nodal lambda value
IERR         i  (W)  Error return code from lirl_hklunq
-end*/

/*-C:*/
int lirl_nodunq (int mindx, int iref, int *nh, int *nk, int *nl, float *alnod)
/*end*/

/*-Parameters:
int mindx;         Index as returned by lirl_init (R)
int iref;          Reflection number (from 1 upwards) (R)
int *nh;           Reflection 'h' nodal index (unique) (0 if error)(W)
int *nk;           Reflection 'k' nodal index (unique) (0 if error)(W)
int *nl;           Reflection 'l' nodal index (unique) (0 if error)(W)
float *alnod;      Nodal lambda value (W)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or reflection
               record not present.
         = -2, symmetry no. not set
         = -3, symmetry matrices not defined
-end*/
{
   LIRLreflection *refl;
   int h, k, l;
   int ih, ik, il;
   int jh1, jk1, jl1;
   int jj;
   int is;
   int hcf1, hcf2;
   int minharm;
   int dml_indx;
   float *rs;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   if (lirl_head[mindx].rsym==0) return -3;

   dml_indx = lirl_head[mindx].dml_indx;

   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;
   if (refl->ksym==0) return -2;
   jj = refl->hkl; 
   ih = jj/two20;
   jj -= two20*ih;
   ih -= 512;
   ik = jj/two10;
   il = jj - two10*ik - 512;
   ik -= 512;
   if (refl->ksym==1)
   {
      h = ih;
      k = ik;
      l = il;
   }
   else
   {
      is = (refl->ksym-1)/2;
      rs = &lirl_head[mindx].rsym[16*is];
      h = ih*rs[0] + ik*rs[1] + il*rs[2];
      k = ih*rs[4] + ik*rs[5] + il*rs[6];
      l = ih*rs[8] + ik*rs[9] + il*rs[10];
      if (refl->ksym%2==0)
      {
        h = -h;
        k = -k;
        l = -l;
      }
   }
   jh1 = h;
   jk1 = k;
   jl1 = l;
   hcf1 = lirl_hcf(jh1, jk1);
   hcf2 = lirl_hcf(hcf1, jl1);
   *nh = lirl_sign(jh1/hcf2, jh1);
   *nk = lirl_sign(jk1/hcf2, jk1);
   *nl = lirl_sign(jl1/hcf2, jl1);
   minharm = 0;
   if (*nh!=0)
   {
      minharm = h/(*nh);
   }
   else if (*nk!=0)
   {
      minharm = k/(*nk);
   }
   else if (*nl!=0)
   {
       minharm = l/(*nl);
   }
   *alnod = refl->lambda*minharm;   
   return 0;
}
/* Fortran binding: lirlf_nodunq */

void lirlf_nodunq (int *mindx, int * iref, int *h, int *k, int *l, 
                   float *alnod, int *ierr)
{
   *ierr = lirl_nodunq (*mindx, *iref, h, k, l, alnod);
   return;
}

/*-Routine: Get reflection details for a reflection  - lirl_getref
The routine lirl_getref (lirlf_getref) gets the reflection details
for the main items for a given reflection in a Laue integrated reflection 
list. The values for the optional additional items are retrieved via
other routines if required.
-end*/

/*                                            
*************************
**    lirl_getref      **
*************************

Purpose: Get reflection details from a Laue integrated reflections list

Author:  John W. Campbell, October 1995


CD-Fortran:
         CALL LIRLF_GETREF  (MINDX, IREF, IH, IK, IL, IPACK, IPLATE, 
        +                    KSYM, XFD, YFD, ALAM,
        +                    MULT, MINHARM, MAXHARM, INCHARM, AI, SIGI,
        +                    ISPAT, ICLOS, IMEAS, IBAD, IOVLD, 
        +                    ICODE, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards)
IH           i  (W)  Reflection 'h' index (as measured)
IK           i  (W)  Reflection 'k' index (as measured)
IL           i  (W)  Reflection 'l' index (as measured)
IL           i  (R)  Reflection 'l' index
IPACK        i  (W)  Pack no. or index (1-65535)
IPLATE       i  (W)  Plate number within pack
KSYM         i  (W)  Symmetry no. (0 if not yet determined)
XFD          r  (W)  'xfd' coordinate of spot  (units as defined by 
                     ICOORD_TYPE in LIRLF_INIT call)
YFD          r  (W)  'yfd' coordinate of spot (units as defined by 
                     ICOORD_TYPE in LIRLF_INIT call)
ALAM         r  (W)  Wavelength (for lowest harmonic present for a
                     multiple)
MULT         i  (W)  Multiplicity (1=single)
MINHARM      i  (W)  Minimum harmonic (set if MULT not 1, otherwise 0)
MAXHARM      i  (W)  Maximum harmonic (set if MULT not 1, otherwise 0)
INCHARM      i  (W)  Harmonics increment (set if MULT not 1, otherwise 0)
AI           r  (W)  Integrated intensity
SIGI         r  (W)  Standard deviation of integrated intensity
ISPAT        i  (W)  Spatially overlapped flag =1 yes, =0 no
ICLOS        i  (W)  Spot too close to deconvolute flag =1 yes, =0 no
IMEAS        i  (W)  Integration done flag =1 yes, =0 no
IBAD         i  (W)  Bad spot other than overload flag =1 yes, =0 no
IOVLD        i  (W)  Intensity overload flag =1 yes, =0 no
ICODE        i  (W)  Code specific to integration routine (0-255)
IERR         i  (W)  Error return code from lirl_getref

   For a deconvoluted multiple, the following items are returned as zero:
   IPACK, IPLATE, XFD, YFD, ALAM, MINHARM, MAXHARM, INCHARM. ISPAT, ICLOS,
   IBAD, IOVLD, ICODE. IMEAS will be returned as 1. Note also that the 
   intensity and sigma(intensity) values are already normalised and scaled.
-end*/

/*-C:*/
int lirl_getref (int mindx, int iref, int *h, int *k, int *l, int *ipack, 
                 int *iplate, int *ksym, 
                 float *xfd, float *yfd, float *alam, 
                 int *mult, int *minharm, int *maxharm, int *incharm, 
                 float *ai, float *sigi,
                 int *ispat, int *iclos, int *imeas, int *ibad, int *iovld, 
                 int *icode)
/*end*/

/*-Parameters:
int mindx;        Index as returned by lirl_init (R)
int iref;         Reflection number (from 1 upwards) (R)
int *h;           Reflection 'h' index  (as measured) (W)
int *k;           Reflection 'k' index (as measured) (W)
int *l;           Reflection 'l' index (as measured) (W)
int *ipack;       Pack no. or index (1-65535) (W)
int *iplate;      Plate number within pack (W)
int *ksym;        Symmetry no. (0 if indices are as measured) (W)
float *xfd;       'xfd' coordinate of spot (units as defined by 
                  coord_type in lirl_init call) (W)
float *yfd;       'yfd' coordinate of spot (units as defined by 
                  coord_type in lirl_init call) (W)
float *alam;      Wavelength (for lowest harmonic present for a
                  multiple) (W)
int *mult;        Multiplicity (1=single) (W)
int *minharm;     Minimum harmonic (if mult!=1, else 0) (W)
int *maxharm;     Maximum harmonic (if mult!=1, else 0) (W)
int *incharm;     Harmonics increment (if mult!=1, else 0) (W)
float *ai;        Integrated intensity (W)
float *sigi;      Standard deviation of integrated intensity (W)
int *ispat;       Spatially overlapped flag =1 yes, =0 no (W)
int *iclos;       Spot too close to deconvolute flag =1 yes, =0 no (W)
int *imeas;       Integration done flag =1 yes, =0 no (W)
int *ibad;        Bad spot other than overload flag =1 yes, =0 no (W)
int *iovld;       Intensity overload flag =1 yes, =0 no (W)
int *icode;       Code specific to integration routine (0-255) (W)

   For a deconvoluted multiple, the following items are returned as zero:
   ipack, iplate, xfd, yfd, alam, minharm, maxharm, incharm. ispat, iclos,
   ibad, iovld, icode. imeas will be returned as 1. Note also that the 
   intensity and sigma(intensity) values are already normalised and scaled.

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or reflection
               record not present.
-end*/
{
   LIRLreflection *refl;
   int ii;
   int jj;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;

   dml_indx = lirl_head[mindx].dml_indx;

   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;
   jj = refl->hkl; 
   *h = jj/two20;
   jj -= two20*(*h);
   *h -= 512;
   *k = jj/two10;
   *l = jj - two10*(*k) - 512;
   *k -= 512;
   *ipack = refl->pack;
   *iplate = refl->plate;
   *ksym = refl->ksym;
   *xfd = refl->xfd;
   *yfd = refl->yfd;
   *alam = refl->lambda;
   if (refl->mult_flags==1)
   {
      *mult = 1;
      *minharm = 0;
      *maxharm = 0;
      *incharm = 0;
   }
   else
   {
      ii = refl->mult_flags;
      *mult = ii/two20;
      ii -= two20*(*mult);
      *minharm = ii/two12;
      ii -= two12*(*minharm);
      *maxharm = ii/16;
      *incharm = ii - 16*(*maxharm);
   }
   *ai = refl->intensity;
   *sigi = refl->sigint;
   *ispat = refl->spov;
   *iclos = refl->clos;
   *imeas = refl->measured;
   *ibad = refl->bad;
   *iovld = refl->ovld;
   *icode = refl->icode;
   return 0;
}
/* Fortran binding: lirlf_getref */

void lirlf_getref (int *mindx, int *iref, int *h, int *k, int *l, 
                   int *ipack, int *iplate, int *ksym,
                   float *xfd, float *yfd, float *alam,
                   int *mult, int *minharm, int *maxharm, int *incharm,
                   float *ai, float *sigi,
                   int *ispat, int *iclos, int *imeas, int *ibad, int *iovld,
                   int *icode, int *ierr)
{
   *ierr = lirl_getref (*mindx, *iref, h, k, l, ipack, iplate, ksym,
                        xfd, yfd, alam, mult, minharm, maxharm, incharm,
                        ai, sigi, ispat, iclos, imeas,
                        ibad, iovld, icode);
   return;
}

/*-Routine: Get number of overload pixels  - lirl_get_ovpix
The routine lirl_get_ovpix (lirlf_get_ovpix) returns the value for the
number of overload pixels found set for a reflection.
-end*/

/*                                            
**************************
**    lirl_get_ovpix    **
**************************

Purpose: Get the no. of overload pixels for a reflection.

Author:  John W. Campbell, May 1997


CD-Fortran:
         CALL LIRLF_GET_OVPIX  (MINDX, IREF, NUM_OVPIX, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards) 
NUM_OVPIX    i  (W)  Returns the number of overload pixels 0-255,
                     (-1 = not known)
IERR         i  (W)  Error return code from lirl_get_ovpix 
-end*/

/*-C:*/
int lirl_get_ovpix (int mindx, int iref, int *num_ovpix)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int iref;        Reflection number (from 1 upwards) (R)
int *num_ovpix;  Returns the number of overload pixels  0-255,
                 (-1 = not known) (W)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   if (refl->novpix==0)
   {
      *num_ovpix = -1;
   }
   else
   {
      *num_ovpix = refl->num_ovpix;
   }
   return 0;
}

/* Fortran binding: lirlf_get_ovpix */

void lirlf_get_ovpix (int *mindx, int *iref, int *num_ovpix, int *ierr) 
{
   *ierr = lirl_get_ovpix (*mindx, *iref, num_ovpix);
   return;
}

/*-Routine: Get reflection 'outlier' flag  - lirl_get_outlier
The routine lirl_get_outlier (lirlf_get_outlier) gets the value for the
for a reflection 'outlier' flag. 
-end*/

/*                                            
**************************
**    lirl_get_outlier  **
**************************

Purpose: Get a reflection 'outlier' flag value

Author:  John W. Campbell, May 1997


CD-Fortran:
         CALL LIRLF_GET_OUTLIER  (MINDX, IREF, ICODE, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards) 
ICODE        i  (W)  Returns the program dependent flag 0-255; 
                     0 indicates that the reflection is OK (i.e. 
                     not an outlier) and any value >0 indicates an
                     outlier.
IERR         i  (W)  Error return code from lirl_get_outlier 
-end*/

/*-C:*/
int lirl_get_outlier (int mindx, int iref, int *icode)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int iref;        Reflection number (from 1 upwards) (R)
int *icode;      Returns the program dependent flag 0-255; 
                 0 indicates that the reflection is OK (i.e. 
                 not an outlier) and any value >0 indicates an
                 outlier. (W)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   *icode = refl->outlier;
   return 0;
}

/* Fortran binding: lirlf_get_outlier */

void lirlf_get_outlier (int *mindx, int *iref, int *icode, int *ierr) 
{
   *ierr = lirl_get_outlier (*mindx, *iref, icode);
   return;
}

/*-Routine: Get reference intensity and sigma  - lirl_get_refint
The routine lirl_get_refint (lirlf_get_refint) gets the values 
for a reflection reference intensity and its sigma value. 
-end*/

/*                                            
**************************
**    lirl_get_refint   **
**************************

Purpose: Get reference intensity and sigma

Author:  John W. Campbell, May 1997


CD-Fortran:
         CALL LIRLF_GET_REFINT  (MINDX, IREF, REFINT, SIGREF, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards) 
REFINT       r  (W)  Returns the reference intensity.
SIGREF       r  (W)  Returns sigma(reference intensity). A value of 0.0
                     indicates that the intensity is not present.
IERR         i  (W)  Error return code from lirl_get_refint 
-end*/

/*-C:*/
int lirl_get_refint (int mindx, int iref, float *refint, float *sigref)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int iref;        Reflection number (from 1 upwards) (R)
float *refint;   Returns the reference intensity. (W)
float *sigref;   Returns sigma(reference intensity). A value of 0.0
                 indicates that the intensity is not present. (W)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   *refint = refl->ref_int;
   *sigref = refl->ref_sigint;
   return 0;
}

/* Fortran binding: lirlf_get_refint */

void lirlf_get_refint (int *mindx, int *iref, float *refint, float *sigref,
                        int *ierr) 
{
   *ierr = lirl_get_refint (*mindx, *iref, refint, sigref);
   return;
}

/*-Section: Sort 'LIRL' Lists
A routine enables Laue integrated reflection lists to be sorted on a number
of the stored parameters.
-end*/

/*-Routine: Sort LIRL reflection lists - lirl_sort
The routine lirl_sort (lirlf_sort) is used to sort the reflection
list by reflection indices of various forms or on various other
parameters. For options involving sorts on unique indices, the symmetry 
number must have been set for all the reflections (e.g using lirl_addref, 
lirl_putref or lirl_putksym (lirlf_addref, lirlf_putref or lirlf_putksym) 
and the symmetry matrices must have been passed to the LIRL routines using 
the lirl_setsym (lirlf_setsym) routine. The sorting process preserves
the data order of items which have the same value of the sort key (this
requires allocation of additional memory and hence the error return
of the sort routine should alwasy be checked)
-end*/

/*                                            
**********************
**    lirl_sort     **
**********************

Purpose: Sort reflection list on various parameters

Author:  John W. Campbell, October 1995

CD-Fortran:
         CALL LIRLF_SORT  (MINDX, ITYP, IERR)
CD-end
*/
/*-Parameters:
MINDX          i  (R)  Index as returned by LIRLF_INIT
ITYP           i  (R)  = 1 sort on measured hkl
                       = 2 sort on unique hkl
                       = 3 sort on pack no./index
                       = 4 sort on plate no.
                       = 5 sort on lambda
                       = 6 sort on xfd
                       = 7 sort on yfd
                       = 8 sort on intensity
                       = 9 sort on multiplicity
                       = 10 sort on unique hkl and sign
                       = 11 sort on unique nodal indices
IERR           i  (W)  Error return code from lirl_sort
-end*/

/*-C:*/
int lirl_sort (int mindx, int ityp)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int ityp;        = 1 sort on measured indices
                 = 2 sort on unique indices
                 = 3 sort on pack no./index
                 = 4 sort on plate no.
                 = 5 sort on lambda
                 = 6 sort on xfd
                 = 7 sort on yfd
                 = 8 sort on intensity
                 = 9 sort on multiplicity
                 = 10 sort on unique hkl and sign
                 = 11 sort on unique nodal indices
                 (R)

Return:  >= 0, The number of reflections
         = -1, Invalid index given or list not initialised or invalid 
               index type requested
         = -2, Not all 'ksym' values set
         = -3, Symmetry matrices not defined (if required) 
         = -4, Cannot allocate temporary memory
-end*/
{
   int dml_indx;
   int ier;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   if (ityp<1||ityp>11) return -1;
   dml_indx = lirl_head[mindx].dml_indx;

   lirl_head[mindx].sort_order = 0;

   switch (ityp)
   {
      case 1: /* Sort on measured indices */
      ier = dml_sort (dml_indx, lirl_xxx_sorhkl);
      if (ier==-2) return -4;
      break;

      case 2: /* Sort on unique indices */
      ier = lirl_xxx_tounq (mindx);
      if (ier<0) return -1;
      if (ier==1)
      {
         lirl_xxx_fromunq (mindx);
         return -2;
      }
      ier = dml_sort (dml_indx, lirl_xxx_sorhkl);         
      lirl_xxx_fromunq (mindx);
      if (ier==-2) return -4;      
      break;

      case 3: /* Sort on pack no./index */
      ier = dml_sort (dml_indx, lirl_xxx_sorpk);
      if (ier==-2) return -4;
      break;

      case 4: /* Sort on plate no. */
      ier = dml_sort (dml_indx, lirl_xxx_sorpl);
      if (ier==-2) return -4;
      break;

      case 5: /* Sort on lambda. */
      ier = dml_sort (dml_indx, lirl_xxx_sorlam);
      if (ier==-2) return -4;
      break;

      case 6: /* Sort on xfd */
      ier = dml_sort (dml_indx, lirl_xxx_sorxfd);
      if (ier==-2) return -4;
      break;

      case 7: /* Sort on yfd */
      ier = dml_sort (dml_indx, lirl_xxx_soryfd);
      if (ier==-2) return -4;
      break;

      case 8: /* Sort on intensity */
      ier = dml_sort (dml_indx, lirl_xxx_sorint);
      if (ier==-2) return -4;
      break;

      case 9: /* Sort on multiplicity */
      ier = dml_sort (dml_indx, lirl_xxx_sormul);
      if (ier==-2) return -4;
      break;

      case 10: /* Sort on unique indices and sign */
      ier = lirl_xxx_tounq (mindx);
      if (ier<0) return -1;
      if (ier==1)
      {
         lirl_xxx_fromunq (mindx);
         return -2;
      }
      ier = dml_sort (dml_indx, lirl_xxx_sorhklsgn);         
      lirl_xxx_fromunq (mindx);
      if (ier==-2) return -4;      
      break;

      case 11: /* Sort on unique nodal indices */
      ier = lirl_xxx_tounqnod (mindx);
      if (ier<0) return -1;
      if (ier==1)
      {
         lirl_xxx_fromunqnod (mindx);
         return -2;
      }
      ier = dml_sort (dml_indx, lirl_xxx_sorhkl);         
      lirl_xxx_fromunqnod (mindx);
      if (ier==-2) return -4;      
      break;
   }
   lirl_head[mindx].sort_order = ityp;
   return 0;
}

/* Fortran binding: lirlf_sort */

void lirlf_sort (int *mindx, int *ityp, int *ierr)
{
   *ierr = lirl_sort (*mindx, *ityp);
   return;
}
/*-Section: Delete and Clear 'LIRL' Data
Routines enable the data stored in a Laue integrated reflection list to be
deleted for a given pack or plate and also for complete lists to be cleared
or removed.
-end*/

/*-Routine: Delete reflections for given pack(s)/plate(s) - lirl_delete
The routine lirl_delete (lirlf_delete) deletes the reflections
for a requested pack (or all packs) and for a requested plate (or
all plates). Unused space at the end of the list will be automatically freed.
-end*/

/*                                            
***********************
**    lirl_delete    **
***********************

Purpose: Delete the reflections for given pack(s)/plate(s) from a Laue
         integrated reflections list

Author:  John W. Campbell, October 1995

CD-Fortran:
         CALL LIRLF_DELETE  (MINDX, IPACK, IPLATE, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IPACK        i  (R)  No. (or index) of pack for which reflections 
                     are to be deleted; 0 = all packs
IPLATE       i  (R)  Plate no. for requested pack(s) of reflections
                     to be deleted; 0 = all plates
IERR         i  (W)  Error return code from lirl_delete
-end*/

/*-C:*/
int lirl_delete (int mindx, int ipack, int plate)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int ipack;       No. or index of pack to be deleted; 0 = all packs (R)
int plate;       Plate no. to be deleted; 0 = all plates (R)

Return:  =  0, OK
         = -1, Invalid index given or list not initialised
-end*/
{
   LIRLpkpl client_data;
   int i;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;

   client_data.pack = ipack;
   client_data.plate = plate;
   i = dml_delrecs (dml_indx, lirl_xxx_del, (void *) &client_data);
   if (i<0) return i;
   dml_freespace (dml_indx);
   return 0;
}

/* Fortran binding: lirlf_delete */

void lirlf_delete (int *mindx, int *ipack, int *iplate, int *ierr)
{
   *ierr = lirl_delete (*mindx, *ipack, *iplate);
   return;
}

/*-Routine: Clear a reflections list - lirl_clear
The routine lirl_clear (lirlf_clear) clears a reflections list.
The memory is not released and the index returned from the lirl_init
(lirlf_init) call can still be used and new reflections may be added 
etc. as required. 
-end*/

/*                                            
***********************
**    lirl_clear     **
***********************

Purpose: Clear a reflections list (keep memory and list parameters)

Author:  John W. Campbell, October 1995

CD-Fortran:
         CALL LIRLF_CLEAR  (MINDX, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IERR         i  (W)  Error return code from lirl_clear
-end*/

/*-C:*/
int lirl_clear (int mindx)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)

Return:  =  0, OK
         = -1, Invalid index given or list not initialised
-end*/
{
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;

   return dml_clear (dml_indx);
}

/* Fortran binding: lirlf_clear */

void lirlf_clear (int *mindx, int *ierr)
{
   *ierr = lirl_clear (*mindx);
   return;
}

/*-Routine: Clear and free a reflections list - lirl_free
The routine lirl_free (lirlf_free) clears a reflections list
and makes it available for re-use via another initialisation call. 
All the memory that was allocated for the list is freed.
-end*/

/*                                            
***********************
**    lirl_free      **
***********************

Purpose: Clear a reflections list and free it for re-use

Author:  John W. Campbell, October 1995

CD-Fortran:
         CALL LIRLF_FREE  (MINDX, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IERR         i  (W)  Error return code from lirl_free
-end*/

/*-C:*/
int lirl_free (int mindx)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)

Return:  =  0, OK
         = -1, Invalid index given or list not initialised
-end*/
{
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;

   dml_free (dml_indx);

   lirl_head[mindx].in_use = 0;
   lirl_head[mindx].dml_indx = -1;
   lirl_head[mindx].list_type = -1;

   return 0;
}

/* Fortran binding: lirlf_free */

void lirlf_free (int *mindx, int *ierr)
{
   *ierr = lirl_free (*mindx);
   return;
}

/*-Section: Routines for the Laue Scaling Module
These are a series of routines written specifically for use with
the Laue Scaling Module (LSM).
-end*/

/*-Routine: Start to read reflections - lirl_lsm_start
The routine lirl_lsm_start (lirlf_lsm_start) is called to set some
initialisation flags before sets of reflections are read using
the routine lirl_lsl_next (lirlf_lsm_next). Note that the 'use_reflection'
flag must be set for each reflection before reading reflection sets
from a list. Note also that only one reflection list may be accessed
at a time using the lirl_lsm_start/lirl_lsm_next routines and that
the reflections must be sorted on unique hkl (or unique_hkl and sign
if sign separated data are being used).
-end*/

/*                                            
**************************
**    lirl_lsm_start    **
**************************

Purpose: Prepare for reading relection sets for LSM use

Author:  John W. Campbell, May 1997

CD-Fortran:
         CALL LIRLF_LSM_START  (MINDX, ISIGN, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
ISIGN        i  (R)  Flag =1 prepare to return sign separated reflection sets
                          =0 ingore reflection I+/I- sign
IERR         i  (W)  Error return code from lirl_lsm_start
-end*/

/*-C:*/
int lirl_lsm_start (int mindx, int isign)
/*end*/

/*-Parameters:
int mindx;       Index as returned by lirl_init (R)
int isign;       Flag =1 prepare to return sign separated reflection sets
                      =0 ingore reflection I+/I- sign (R)

Return:  =  0, OK
         = -1, Invalid index given or list not initialised
-end*/
{
   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   list_indx = lirl_head[mindx].dml_indx;
   num_refs = dml_numrecs (list_indx);
   eof = 0;
   first = 1;
   last_hkl = 0;
   last_sign = 0;
   sign_sep = isign;
   iref_cur = 0;

   return 0;
}
/* Fortran binding: lirlf_lsm_start */

void lirlf_lsm_start (int *mindx, int *isign, int *ierr)
{
   *ierr = lirl_lsm_start (*mindx, *isign);
   return;
}

/*-Routine: Read next reflection set - lirl_lsm_next
The routine lirl_lsm_next (lirlf_lsm_next) is called to return the
next reflection set from the reflection list. Note that the routine
lirl_lsm_start (lirlf_lsm_start) must be called before attempting
to read the first reflection set and the 'use_reflection' flag must be 
set for each reflection (except for deconvoluted multiples
where used) before reading the reflection sets.
Note that the list index is set via lirl_lsm_start and is stored
internally; only one list may be accessed at a time using lirl_lsm_start
and lirl_lsm_next.
-end*/

/*                                            
**************************
**    lirl_lsm_next     **
**************************

Purpose: Read next reflection set for LSM use

Author:  John W. Campbell, May 1997

CD-Fortran:
         CALL LIRLF_LSM_NEXT  (IDX_ARR, MAX_ARR, NREFS, MULT_INC, IFLAG)
CD-end
*/
/*-Parameters:
IDX_ARR      i  (W)  Array of reflection indices (from 1 upwards) for
                     the reflections in the set (dimensioned to at least
                     MAX_ARR).
MAX_ARR      i  (R)  The maximum no. of reflections which may be returned
                     in the set.
NREFS        i  (W)  The number of reflections in the returned set.
MULT_INC     i  (R)  Include deconvoluted multiples flag
                      =1 yes, (deconvoluted multiples included 
                               unconditionally)
                      =0 no, deconvoluted multiples excluded

IFLAG        i  (W)  Return flag from lirl_lsm_next 
                     =0    OK
                     =-1   End of list reached
                     >0    List truncated; IFLAG shows the actual
                           no. of reflections present in the set.
-end*/

/*-C:*/
int lirl_lsm_next (int idx_arr[], int max_arr, int *nrefs, int mult_inc)
/*end*/

/*-Parameters:
int idx_arr[];   Array of reflection indices (from 1 upwards) for
                 the reflections in the set. (dimensioned to at least
                 max_arr). (W)
int max_arr;     The maximum no. of reflections which may be returned
                 in the set. (R)
int *nrefs;      The no. of reflections in the set. (W)
int mult_inc;    Include deconvoluted multiples flag
                 =1 yes, (deconvoluted multiples included unconditionally)
                 =0 no, deconvoluted multiples excluded

Return:  =  0,   OK
         = -1,   End of list reached
         > 0,    List truncated; IFLAG shows the actual
                 no. of reflections present in the set. 
-end*/
{
   LIRLreflection *refl;
   int nc;
   int ihkl;
   int isign;

   if (eof) {*nrefs = 0; return -1;}

   if (first)
   {
      nc = 0;
      *nrefs = 0;
   }
   else
   {
      nc = 1;
      *nrefs = 1;
      idx_arr[0] = iref_cur;
   }

   nxt:
   iref_cur++;
   if (iref_cur>num_refs)
   {
      eof = 1;
      if (first) return -1;
      if (nc>*nrefs) return nc;
      return 0;
   }
   refl = (LIRLreflection *) dml_recpointer (list_indx, iref_cur);
   if (mult_inc)
   {
      if (refl->mult_flags!=0&&!refl->use_reflection) goto nxt;
   }
   else
   {
      if (!refl->use_reflection) goto nxt;
   }
   ihkl = refl->hkl_unq;
   isign = 0;
   if (sign_sep) isign = refl->ksym%2;
   if (first)
   {
      last_hkl = ihkl;
      last_sign = isign;
      *nrefs = 1;
      nc = 1;
      idx_arr[0] = iref_cur;
      first = 0;
      goto nxt;
   }
   else if (ihkl!=last_hkl||isign!=last_sign)
   {
      last_hkl = ihkl;
      last_sign = isign;
      if (nc>*nrefs) return nc;
      return 0;
   }
   nc++;
   if (nc<=max_arr)
   {
      idx_arr[*nrefs] = iref_cur;
      *nrefs += 1;
   }
   goto nxt;
}

/* Fortran binding: lirlf_lsm_next */

void lirlf_lsm_next (int *idx_arr, int *max_arr, int *nrefs, int *mult_inc, 
                     int *iflag)
{
   *iflag = lirl_lsm_next (idx_arr, *max_arr, nrefs, *mult_inc);
   return;
}

/*-Routine: Set LSM temporary scaling items - lirl_lsm_settemp
The routine lirl_lsm_settemp (lirlf_lsm_settemp) is used to set the
temporary pre-calculated values which will enable efficient scaling
to be carried out within the Laue Scaling Module (LSM) routines.
(The unique indices will also be calculated and stored)
-end*/

/*                                            
*****************************
**    lirl_lsm_settemp     **
*****************************

Purpose: Set LSM temporary pre-calculated scaling items

Author:  John W. Campbell, May 1997

CD-Fortran:
         CALL LIRLF_LSM_SETTEMP  (MINDX, IREF, ABSCOR_NU, PSI_LOCAL,
        +                         PSI_GLOBAL, STOL2, AL3C2T, ABSCOR_LAMFN, 
        +                         OB_LPFAC, KNORM, KPLSC, IUSE, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards) 
ABSCOR_NU    r  (R)  'nu' angle for absorption correction 
PSI_LOCAL    r  (R)  'psi' angle for absorption correction (local)
PSI_GLOBAL   r  (R)  'psi' angle for absorption correction (global)
STOL2        r  (R)  sin**theta/lambda**2
AL3C2T       r  (R)  lambda**3/(cos(2*theta))
ABSCOR_LAMFN r  (R)  lambda dependent function for absorption correction
OB_LPFAC     r  (R)  Combined obliquity/Lorentz/polarisation factor
KNORM        i  (R)  Normalisation curve range no. flag
KPLSC        i  (R)  Plate to plate scaling range flag
IUSE         i  (R)  Use reflection flag =1 yes, =0 no
IERR         i  (W)  Error return code from lirl_lsm_settemp
-end*/

/*-C:*/
int lirl_lsm_settemp (int mindx, int iref, float abscor_nu, float psi_local,
                      float psi_global, float stol2, float al3c2t, 
                      float abscor_lamfn, float ob_lpfac, int knorm, 
                      int kplsc, int iuse)
/*end*/

/*-Parameters:
int mindx;          Index as returned by lirl_init (R)
int iref;           Reflection number (from 1 upwards) (R)
float abscor_nu;    'nu' angle for absorption correction (R)
float psi_local;    'psi' angle for absorption correction (local) (R)
float psi_global;   'psi' angle for absorption correction (global) (R)
float stol2;        sin**theta/lambda**2 (R)
float al3c2t;       lambda**3/(cos(2*theta)) (R)
float abscor_lamfn; lambda dependent function for absorption 
                    correction (R)
float ob_lpfac;     Combined obliquity/Lorentz/polarisation factor (R)
int knorm;          Normalisation curve range no. flag (R)
int kplsc;          Plate to plate scaling range flag (R)
int iuse;           Use reflection flag =1 yes, =0 no (R)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;
   int ih, ik, il;
   int jh, jk, jl;
   int jj;
   int is;
   int ir;
   float *rs;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   if (iuse!=0) iuse = 1;

   refl->abscor_nu = abscor_nu;
   refl->abscor_psi_local = psi_local;
   refl->abscor_psi_global = psi_global;
   refl->stol2 = stol2;
   refl->al3c2t = al3c2t;
   refl->abscor_lamfn = abscor_lamfn;
   refl->ob_lpfac = ob_lpfac;
   refl->norm_range = (unsigned char) knorm;
   refl->filmsc_range = (unsigned char) kplsc;
   refl->use_reflection = (unsigned char) iuse;

   jj = refl->hkl; 
   ih = jj/two20;
   jj -= two20*ih;
   ih -= 512;
   ik = jj/two10;
   il = jj - two10*ik - 512;
   ik -= 512;
   jh = ih;
   jk = ik;
   jl = il;
   if (refl->ksym!=1)
   {
      is = (refl->ksym-1)/2;
      rs = &lirl_head[mindx].rsym[16*is];
      jh = ih*rs[0] + ik*rs[1] + il*rs[2];
      jk = ih*rs[4] + ik*rs[5] + il*rs[6];
      jl = ih*rs[8] + ik*rs[9] + il*rs[10];
      if (refl->ksym%2==0)
      {
        jh = -jh;
        jk = -jk;
        jl = -jl;
      }
   }
   refl->hkl_unq = two20*(jh+512)+two10*(jk+512)+jl+512;

   return 0;
}

/* Fortran binding: lirlf_lsm_settemp */

void lirlf_lsm_settemp (int *mindx, int *iref,  float *abscor_nu, 
                        float *psi_local, float * psi_global, float *stol2, 
                        float *al3c2t, float *abscor_lamfn, float *ob_lpfac, 
                        int *knorm, int *kplsc, int *iuse, int *ierr) 
{
   *ierr = lirl_lsm_settemp (*mindx, *iref, *abscor_nu, 
                             *psi_local, *psi_global, *stol2,
                             *al3c2t, *abscor_lamfn, *ob_lpfac, *knorm, *kplsc,
                             *iuse);
   return;
}

/*-Routine: Set 'use reflection' flag  - lirl_lsm_setuse
The routine lirl_lsm_setuse (lirlf_lsm_setuse) is used to set the
temporary 'use_reflection' flag for a reflection  within the 
Laue Scaling Module (LSM) routines.
-end*/

/*                                            
*****************************
**    lirl_lsm_setuse      **
*****************************

Purpose: Set LSM temporary 'use_reflection' flag

Author:  John W. Campbell, July 1997

CD-Fortran:
         CALL LIRLF_LSM_SETUSE  (MINDX, IREF, IUSE, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards) 
IUSE         i  (R)  Use reflection flag =1 yes, =0 no
IERR         i  (W)  Error return code from lirl_lsm_setuse
-end*/

/*-C:*/
int lirl_lsm_setuse (int mindx, int iref, int iuse)
/*end*/

/*-Parameters:
int mindx;          Index as returned by lirl_init (R)
int iref;           Reflection number (from 1 upwards) (R)
int iuse;           Use reflection flag =1 yes, =0 no (R)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   if (iuse!=0) iuse = 1;

   refl->use_reflection = (unsigned char) iuse;
   return 0;
}

/* Fortran binding: lirlf_lsm_setuse */

void lirlf_lsm_setuse (int *mindx, int *iref, int *iuse, int *ierr) 
{
   *ierr = lirl_lsm_setuse (*mindx, *iref, *iuse);
   return;
}

/*-Routine: Get LSM scaling items - lirl_lsm_scalobs
The routine lirl_lsm_scalobs (lirlf_lsm_scalobs) is used to get the
items required to calculate a scaled intensity and sigma(intensity)
value for use within the LSM refinement and scaling routines. Note
that values must have been set for all the required items - this routine
does not determine them.
-end*/

/*                                            
*****************************
**    lirl_lsm_scalobs     **
*****************************

Purpose: Get LSM scaling data

Author:  John W. Campbell, May 1997

CD-Fortran:
         CALL LIRLF_LSM_SCALOBS  (MINDX, IREF, IPACK, IPLATE,
        +                         AINT, SIGINT, ALAM, REFINT,
        +                         ABSCOR_NU, PSI_LOCAL, PSI_GLOBAL,
        +                         STOL2, AL3C2T, ABSCOR_LAMFN, OB_LPFAC,
        +                         KNORM, KPLSC, IUSE, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards)
IPACK        i  (W)  Returns the pack number 
IPLATE       i  (W)  Returns the plate number 
AINT         r  (W)  Returns the intensity value (unscaled)
SIGINT       r  (W)  Returns the sig(I) (unscaled)
ALAM         r  (W)  Returns the lambda value
REFINT       r  (W)  Returns the reference intensity
ABSCOR_NU    r  (W)  Returns 'nu' angle for absorption correction 
PSI_LOCAL    r  (W)  Returns 'psi' angle for absorption correction (local)
PSI_GLOBAL   r  (W)  Returns 'psi' angle for absorption correction (global)
STOL2        r  (W)  Returns sin**theta/lambda**2
AL3C2T       r  (W)  Returns lambda**3/(cos(2*theta))
ABSCOR_LAMFN r  (W)  Returns lambda dependent function for absorption 
                     correction
OB_LPFAC     r  (W)  Returns combined obliquity/Lorentz/polarisation 
                     factor
KNORM        i  (W)  Returns normalisation curve range no. flag
KPLSC        i  (W)  Returns plate to plate scaling range flag
IUSE         i  (W)  Returns use reflection flag =1 yes, =0 no
IERR         i  (W)  Error return code from lirl_lsm_scalobs
-end*/

/*-C:*/
int lirl_lsm_scalobs (int mindx, int iref, int *ipack, int *iplate,
                     float *aint, float *sigint, float *alam, 
                     float *refint, float *abscor_nu, 
                     float *psi_local, float *psi_global, float *stol2, 
                     float *al3c2t, float *abscor_lamfn, float *ob_lpfac, 
                     int *knorm, int *kplsc, int *iuse)
/*end*/

/*-Parameters:
int mindx;           Index as returned by lirl_init (R)
int iref;            Reflection number (from 1 upwards) (R)
int *ipack;          Returns the pack number (W)
int *iplate;         Returns the plate number (W)
float *aint;         Returns the intensity value (unscaled) (W)
float *sigint;       Returns the sig(I) (unscaled) (W)
float *alam;         Returns the lambda value (W)
float *refint;       Returns the reference intensity (W)
float *abscor_nu;    Returns 'nu' angle for absorption correction (W)
float *psi_local;    Returns 'psi' angle for absorption correction 
                     (local) (W)
float *psi_global;   Returns 'psi' angle for absorption correction 
                     (global) (W)
float *stol2;        Returns sin**theta/lambda**2 (W)
float *al3c2t;       Returns lambda**3/(cos(2*theta)) (W)
float *abscor_lamfn; Returns lambda dependent function for absorption 
                     correction (W)
float *ob_lpfac;     Returns combined obliquity/Lorentz/polarisation 
                     factor (W)
int *knorm;          Returns normalisation curve range no. flag (W)
int *kplsc;          Returns plate to plate scaling range flag (W)
int *iuse;           Returns use reflection flag =1 yes, =0 no (W)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   *ipack = refl->pack;
   *iplate = refl->plate;
   *aint = refl->intensity;
   *sigint = refl->sigint;
   *alam = refl->lambda;
   *refint = refl->ref_int;

   *abscor_nu = refl->abscor_nu;
   *psi_local = refl->abscor_psi_local;
   *psi_global = refl->abscor_psi_global;
   *stol2 = refl->stol2;
   *al3c2t = refl->al3c2t;
   *abscor_lamfn = refl->abscor_lamfn;
   *ob_lpfac = refl->ob_lpfac;
   *knorm = refl->norm_range;
   *kplsc = refl->filmsc_range;
   *iuse = refl->use_reflection;
   return 0;
}

/* Fortran binding: lirlf_lsm_scalobs */

void lirlf_lsm_scalobs (int *mindx, int *iref,  int*ipack, int*iplate,
                        float *aint, float *sigint, float *alam, 
                        float *refint, float *abscor_nu, 
                        float *psi_local, float *psi_global, float *stol2, 
                        float *al3c2t, float *abscor_lamfn, float *ob_lpfac, 
                        int *knorm, int *kplsc, int *iuse, int *ierr) 
{
   *ierr = lirl_lsm_scalobs (*mindx, *iref, ipack, iplate, aint, sigint, 
                             alam, refint,
                             abscor_nu, psi_local, psi_global, stol2, al3c2t,
                             abscor_lamfn, ob_lpfac, knorm, kplsc,
                             iuse);
   return;
}

/*-Routine: Get LSM range items - lirl_lsm_getranges
The routine lirl_lsm_getranges (lirlf_lsm_getranges) is used to get the
stored values for the normalisation curve wavelength range and plate scaling
wavelength range flags for use within the LSM refinement and scaling routines.
Note that values must have been set for the required items - this routine
does not determine them.
-end*/

/*                                            
*****************************
**    lirl_lsm_getranges   **
*****************************

Purpose: Get LSM scaling wavelength ranges

Author:  John W. Campbell, May 1997

CD-Fortran:
         CALL LIRLF_LSM_GETRANGES  (MINDX, IREF, KNORM, KPLSC, 
        +                           ABSCOR_NU, PSI_LOC, PSI_GLOB, IERR)
CD-end
*/
/*-Parameters:
MINDX        i  (R)  Index as returned by LIRLF_INIT
IREF         i  (R)  The reflection number (from 1 upwards)
KNORM        i  (W)  Returns normalisation curve range no. flag
KPLSC        i  (W)  Returns plate to plate scaling range flag
ABSCOR_NU    r  (W)  'nu' value
PSI_LOC      r  (W)  'psi' value (local)
PSI_GLOB     r  (W)  'psi' valus (global)
IERR         i  (W)  Error return code from lirl_lsm_getranges
-end*/

/*-C:*/
int lirl_lsm_getranges (int mindx, int iref,  int *knorm, int *kplsc,
                       float *abscor_nu, float *psi_loc, float *psi_glob)
/*end*/

/*-Parameters:
int mindx;           Index as returned by lirl_init (R)
int iref;            Reflection number (from 1 upwards) (R)
int *knorm;          Returns normalisation curve range no. flag (W)
int *kplsc;          Returns plate to plate scaling range flag (W)
float *abscor_nu;    Returns 'nu' value (W)
float *psi_loc;      Returns 'psi' value (local) (W)
float *psi_glob;     Returns 'psi' value (global) (W)

Return:  =  0, OK
         = -1, Invalid index given, list not initialised or record not present
-end*/
{
   LIRLreflection *refl;
   int dml_indx;

   if (!lirl_initialised) return -1;
   if (mindx<0||mindx>=MAXLISTS) return -1;
   if (lirl_head[mindx].in_use==0) return -1;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, iref);
   if (refl==0) return -1;

   *knorm = refl->norm_range;
   *kplsc = refl->filmsc_range;
   *abscor_nu = refl->abscor_nu;
   *psi_loc = refl->abscor_psi_local;
   *psi_glob = refl->abscor_psi_global;
   return 0;
}

/* Fortran binding: lirlf_lsm_getranges */

void lirlf_lsm_getranges (int *mindx, int *iref, int *knorm, int *kplsc, 
                          float *abscor_nu, float *psi_loc,
                          float *psi_glob, int *ierr) 
{
   *ierr = lirl_lsm_getranges (*mindx, *iref, knorm, kplsc, abscor_nu,
                               psi_loc, psi_glob);
   return;
}

/****************************************************************************/
/*               S E R V I C E       R O U T I N E S                        */
/****************************************************************************/


/*                                            
***************************
**    lirl_xxx_del       **
***************************

Purpose: 'User supplied'  delete function for given image packs/plates for 
         a Laue integrated reflections list

Return:  =  0, Do not delete reflection
         =  1, Delete reflection

Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_del (void * rec, void * client_data)
{
   LIRLreflection *refl;
   LIRLpkpl *pp;

   refl = (LIRLreflection *) rec;
   pp = (LIRLpkpl *) client_data;
   if (pp->pack==0&&pp->plate==0) return 1;
   if (pp->pack!=0)
   {
      if (refl->pack!=pp->pack) return 0;
   }
   if (pp->plate==0) return 1;
   if (refl->plate==pp->plate) return 1;
   return 0;
}

/*                                            
***************************
**    lirl_xxx_tounq     **
***************************

Purpose: Temp convert indices to unique ones in LIRL (for sorting)

Return:  =  0, OK all done
         =  1, One or more values of 'ksym' not set
         < -1, Invalid index given or list not initialised

Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_tounq (int mindx)
{
   LIRLreflection *refl;
   int numrefs;
   int err;
   int dml_indx;
   int ih, ik, il;
   int jh, jk, jl;
   int jj;
   int is;
   int ir;
   float *rs;

   err = 0;
   numrefs = lirl_numrefs (mindx);
   if (numrefs<0) return -1;
   if (numrefs==0) return 0;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, 1);

   for (ir=0;ir<numrefs;++ir)
   {
      if (refl[ir].ksym==0)
      {
         err = 1;
         continue;
      }
      jj = refl[ir].hkl; 
      ih = jj/two20;
      jj -= two20*ih;
      ih -= 512;
      ik = jj/two10;
      il = jj - two10*ik - 512;
      ik -= 512;
      if (refl[ir].ksym!=1)
      {
         is = (refl[ir].ksym-1)/2;
         rs = &lirl_head[mindx].rsym[16*is];
         jh = ih*rs[0] + ik*rs[1] + il*rs[2];
         jk = ih*rs[4] + ik*rs[5] + il*rs[6];
         jl = ih*rs[8] + ik*rs[9] + il*rs[10];
         if (refl[ir].ksym%2==0)
         {
           jh = -jh;
           jk = -jk;
           jl = -jl;
         }
         refl[ir].hkl = two20*(jh+512)+two10*(jk+512)+jl+512;
      }
   }
   return err;
}
/*                                            
*****************************
**    lirl_xxx_fromunq     **
*****************************

Purpose: Convert indices back from unique ones in LIRL to measured ones
         set via lirl_xxx_tounq (for sorting)

Return:  =  0, OK all done
         < -1, Invalid index given or list not initialised

Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_fromunq (int mindx)
{
   LIRLreflection *refl;
   int numrefs;
   int dml_indx;
   int ih, ik, il;
   int jh, jk, jl;
   int jj;
   int is;
   int ir;
   float *rs;

   numrefs = lirl_numrefs (mindx);
   if (numrefs<0) return -1;
   if (numrefs==0) return 0;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, 1);

   for (ir=0;ir<numrefs;++ir)
   {
      if (refl[ir].ksym==0) continue;
      jj = refl[ir].hkl; 
      ih = jj/two20;
      jj -= two20*ih;
      ih -= 512;
      ik = jj/two10;
      il = jj - two10*ik - 512;
      ik -= 512;
      if (refl[ir].ksym!=1)
      {
         is = (refl[ir].ksym-1)/2;
         rs = &lirl_head[mindx].rsymiv[16*is];
         jh = ih*rs[0] + ik*rs[1] + il*rs[2];
         jk = ih*rs[4] + ik*rs[5] + il*rs[6];
         jl = ih*rs[8] + ik*rs[9] + il*rs[10];
         if (refl[ir].ksym%2==0)
         {
           jh = -jh;
           jk = -jk;
           jl = -jl;
         }
         refl[ir].hkl = two20*(jh+512)+two10*(jk+512)+jl+512;
      }
   }
   return 0;
}
/*                                            
******************************
**    lirl_xxx_tounqnod     **
******************************

Purpose: Temp convert indices to unique nodal ones in LIRL (for sorting)

Return:  =  0, OK all done
         =  1, One or more values of 'ksym' not set
         < -1, Invalid index given or list not initialised

Author:  John W. Campbell, September 1997

**** SERVICE ROUTINE ONLY ****

NOTE: For singles, temporarily set multiplicity flag to - the harmonic
      no. for the single (or -10000 - the harmonic no. for a deconvoluted
      multiple)

*/

int lirl_xxx_tounqnod (int mindx)
{
   LIRLreflection *refl;
   int numrefs;
   int err;
   int dml_indx;
   int ih, ik, il;
   int jh, jk, jl;
   int jh1, jk1, jl1;
   int nh, nk, nl;
   int hcf1, hcf2;
   int jj;
   int is;
   int ir;
   int harmpad;
   int minharm;
   float *rs;

   err = 0;
   numrefs = lirl_numrefs (mindx);
   if (numrefs<0) return -1;
   if (numrefs==0) return 0;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, 1);

   for (ir=0;ir<numrefs;++ir)
   {
      if (refl[ir].ksym==0)
      {
         err = 1;
         continue;
      }
      jj = refl[ir].hkl; 
      ih = jj/two20;
      jj -= two20*ih;
      ih -= 512;
      ik = jj/two10;
      il = jj - two10*ik - 512;
      ik -= 512;
      jh = ih;
      jk = ik;
      jl = il;
      if (refl[ir].ksym!=1)
      {
         is = (refl[ir].ksym-1)/2;
         rs = &lirl_head[mindx].rsym[16*is];
         jh = ih*rs[0] + ik*rs[1] + il*rs[2];
         jk = ih*rs[4] + ik*rs[5] + il*rs[6];
         jl = ih*rs[8] + ik*rs[9] + il*rs[10];
         if (refl[ir].ksym%2==0)
         {
           jh = -jh;
           jk = -jk;
           jl = -jl;
         }
      }
      jh1 = jh;
      jk1 = jk;
      jl1 = jl;
      hcf1 = lirl_hcf(jh1, jk1);
      hcf2 = lirl_hcf(hcf1, jl1);
      nh = lirl_sign(jh1/hcf2, jh1);
      nk = lirl_sign(jk1/hcf2, jk1);
      nl = lirl_sign(jl1/hcf2, jl1);
      refl[ir].hkl = two20*(nh+512)+two10*(nk+512)+nl+512;
      if (refl[ir].mult_flags==1||refl[ir].mult_flags==0)
      {
         harmpad = 0;
         if (refl[ir].mult_flags==0) harmpad = 10000;
         minharm = 0;
         if (nh!=0)
         {
            minharm = jh/nh;
         }
         else if (nk!=0)
	 {
            minharm = jk/nk;
         }
         else if (nl!=0)
	 {
            minharm = jl/nl;
         }
         refl[ir].mult_flags = - minharm - harmpad;
        
      }
   }
   return err;
}
/*                                            
********************************
**    lirl_xxx_fromunqnod     **
********************************

Purpose: Convert indices back from unique nodal ones in LIRL to measured ones
         set via lirl_xxx_tounqnod (for sorting)

Return:  =  0, OK all done
         < -1, Invalid index given or list not initialised

Author:  John W. Campbell, September 1997

**** SERVICE ROUTINE ONLY ****

NOTE: For singles, remember to  reset multiplicity flag to 1

*/

int lirl_xxx_fromunqnod (int mindx)
{
   LIRLreflection *refl;
   int numrefs;
   int dml_indx;
   int ih, ik, il;
   int jh, jk, jl;
   int jj;
   int is;
   int ir;
   int ii;
   int minharm;
   int mult;
   int deconv;
   float *rs;

   numrefs = lirl_numrefs (mindx);
   if (numrefs<0) return -1;
   if (numrefs==0) return 0;
   dml_indx = lirl_head[mindx].dml_indx;
   refl = (LIRLreflection *) dml_recpointer (dml_indx, 1);

   for (ir=0;ir<numrefs;++ir)
   {
      if (refl[ir].ksym==0) continue;
      jj = refl[ir].hkl; 
      ih = jj/two20;
      jj -= two20*ih;
      ih -= 512;
      ik = jj/two10;
      il = jj - two10*ik - 512;
      ik -= 512;
      if (refl[ir].mult_flags<0)
      {
         deconv = 0;
         minharm = -refl[ir].mult_flags;
         if (minharm>10000)
	 {
            deconv = 1;
            minharm = minharm - 10000;
	 }
         refl[ir].mult_flags = 1-deconv;
      }
      else
      {
         ii = refl[ir].mult_flags;
         mult = ii/two20;
         ii -= two20*mult;
         minharm = ii/two12;
      }
      ih = minharm*ih;
      ik = minharm*ik;
      il = minharm*il;
      jh = ih;
      jk = ik;
      jl = il;
      if (refl[ir].ksym!=1)
      {
         is = (refl[ir].ksym-1)/2;
         rs = &lirl_head[mindx].rsymiv[16*is];
         jh = ih*rs[0] + ik*rs[1] + il*rs[2];
         jk = ih*rs[4] + ik*rs[5] + il*rs[6];
         jl = ih*rs[8] + ik*rs[9] + il*rs[10];
         if (refl[ir].ksym%2==0)
         {
           jh = -jh;
           jk = -jk;
           jl = -jl;
         }
      }
      refl[ir].hkl = two20*(jh+512)+two10*(jk+512)+jl+512;
   }
   return 0;
}
/*                                            
******************************
**    lirl_xxx_sorhkl       **
******************************

Purpose: 'User supplied'  sort comparison function for 'hkl' based sort. 

Return:  (For as needed by dml_sort)
         
Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_sorhkl (void * rec1, void * rec2, int * i1, int * i2)
{
   LIRLreflection *refl1, *refl2;

   refl1 = (LIRLreflection *) rec1;
   refl2 = (LIRLreflection *) rec2;
   if (refl1->hkl>refl2->hkl) return 1;
   if (refl1->hkl<refl2->hkl) return -1;
   if (*i1>*i2) return 1;
   if (*i1<*i2) return -1;
   return 0;
}
/*                                            
******************************
**    lirl_xxx_sorpk        **
******************************

Purpose: 'User supplied'  sort comparison function for pack based sort. 

Return:  (For as needed by dml_sort)
         
Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_sorpk (void * rec1, void * rec2, int * i1, int * i2)
{
   LIRLreflection *refl1, *refl2;

   refl1 = (LIRLreflection *) rec1;
   refl2 = (LIRLreflection *) rec2;
   if (refl1->pack>refl2->pack) return 1;
   if (refl1->pack<refl2->pack) return -1;
   if (*i1>*i2) return 1;
   if (*i1<*i2) return -1;
   return 0;
}
/*                                            
******************************
**    lirl_xxx_sorpl        **
******************************

Purpose: 'User supplied'  sort comparison function for plate based sort. 

Return:  (For as needed by dml_sort)
         
Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_sorpl (void * rec1, void * rec2, int * i1, int * i2)
{
   LIRLreflection *refl1, *refl2;

   refl1 = (LIRLreflection *) rec1;
   refl2 = (LIRLreflection *) rec2;
   if (refl1->plate>refl2->plate) return 1;
   if (refl1->plate<refl2->plate) return -1;
   if (*i1>*i2) return 1;
   if (*i1<*i2) return -1;
   return 0;
}
/*                                            
******************************
**    lirl_xxx_sorlam       **
******************************

Purpose: 'User supplied'  sort comparison function for lambda based sort. 

Return:  (For as needed by dml_sort)
         
Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_sorlam (void * rec1, void * rec2, int * i1, int * i2)
{
   LIRLreflection *refl1, *refl2;

   refl1 = (LIRLreflection *) rec1;
   refl2 = (LIRLreflection *) rec2;
   if (refl1->lambda>refl2->lambda) return 1;
   if (refl1->lambda<refl2->lambda) return -1;
   if (*i1>*i2) return 1;
   if (*i1<*i2) return -1;
   return 0;
}
/*                                            
******************************
**    lirl_xxx_sorxfd       **
******************************

Purpose: 'User supplied'  sort comparison function for 'xfd' based sort. 

Return:  (For as needed by dml_sort)
         
Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_sorxfd (void * rec1, void * rec2, int * i1, int * i2)
{
   LIRLreflection *refl1, *refl2;

   refl1 = (LIRLreflection *) rec1;
   refl2 = (LIRLreflection *) rec2;
   if (refl1->xfd>refl2->xfd) return 1;
   if (refl1->xfd<refl2->xfd) return -1;
   if (*i1>*i2) return 1;
   if (*i1<*i2) return -1;
   return 0;
}
/*                                            
******************************
**    lirl_xxx_soryfd       **
******************************

Purpose: 'User supplied'  sort comparison function for 'yfd' based sort. 

Return:  (For as needed by dml_sort)
         
Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_soryfd (void * rec1, void * rec2, int * i1, int * i2)
{
   LIRLreflection *refl1, *refl2;

   refl1 = (LIRLreflection *) rec1;
   refl2 = (LIRLreflection *) rec2;
   if (refl1->yfd>refl2->yfd) return 1;
   if (refl1->yfd<refl2->yfd) return -1;
   if (*i1>*i2) return 1;
   if (*i1<*i2) return -1;
   return 0;
}
/*                                            
******************************
**    lirl_xxx_sorint       **
******************************

Purpose: 'User supplied'  sort comparison function for intensity based sort. 

Return:  (For as needed by dml_sort)
         
Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_sorint (void * rec1, void * rec2, int * i1, int * i2)
{
   LIRLreflection *refl1, *refl2;

   refl1 = (LIRLreflection *) rec1;
   refl2 = (LIRLreflection *) rec2;
   if (refl1->intensity>refl2->intensity) return 1;
   if (refl1->intensity<refl2->intensity) return -1;
   if (*i1>*i2) return 1;
   if (*i1<*i2) return -1;
   return 0;
}
/*                                            
*****************************
**    lirl_xxx_sormul      **
*****************************

Purpose: 'User supplied'  sort comparison function for multiplicity 
         based sort. 

Return:  (For as needed by dml_sort)
         
Author:  John W. Campbell, October 1995

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_sormul (void * rec1, void * rec2, int * i1, int * i2)
{
   LIRLreflection *refl1, *refl2;
   int mul1;
   int mul2;

   refl1 = (LIRLreflection *) rec1;
   refl2 = (LIRLreflection *) rec2;
   mul1 = refl1->mult_flags;
   if (mul1>1) mul1 = refl1->mult_flags/two20;
   mul2 = refl2->mult_flags;
   if (mul2>1) mul2 = refl2->mult_flags/two20;
   if (mul1>mul2) return 1;
   if (mul1<mul2) return -1;
   if (*i1>*i2) return 1;
   if (*i1<*i2) return -1;
   return 0;
}
/*                                            
******************************
**    lirl_xxx_sorhklsgn    **
******************************

Purpose: 'User supplied'  sort comparison function for sign
         separated 'hkl' based sort. 

Return:  (For as needed by dml_sort)
         
Author:  John W. Campbell, May 1997

**** SERVICE ROUTINE ONLY ****

*/

int lirl_xxx_sorhklsgn (void * rec1, void * rec2, int * i1, int * i2)
{
   LIRLreflection *refl1, *refl2;

   refl1 = (LIRLreflection *) rec1;
   refl2 = (LIRLreflection *) rec2;
   if (refl1->hkl>refl2->hkl) return 1;
   if (refl1->hkl<refl2->hkl) return -1;
   if (refl1->ksym%2>refl2->ksym%2) return 1;
   if (refl1->ksym%2<refl2->ksym%2) return -1;
   if (*i1>*i2) return 1;
   if (*i1<*i2) return -1;
   return 0;
}
/*                                            
********************
**    lirl_hcf    **
********************

Purpose: Get highest common factor of two integers

Return:  The highest common factor
         
Author:  John W. Campbell, September 1997

**** SERVICE ROUTINE ONLY ****

*/

int lirl_hcf (int ii, int jj)
{
   int i, j, k;
   int isav;

   i = ii;
   j = jj;
   if (i==j) return i;
   if (i<j) 
   {
      isav = i;
      i = j;
      j = isav;
   }
   if (j==0)return i;

   labl:
   k = i%j;
   if (k==0) return j;
   i = j;
   j = k;
   goto labl;
}
/*                                            
********************
**    lirl_sign   **
********************

Purpose: Copy sign of second integer to value of first integer

Return:  The signed value
         
Author:  John W. Campbell, September 1997

**** SERVICE ROUTINE ONLY ****

*/

int lirl_sign (int ii, int jj)
{
   if (jj>=0)
   {
      if (ii>=0) return ii;
      return -ii;
   }
   else
   {
      if (ii<0) return ii;
      return -ii;
   }
}




