/*header file for loopbrk.c and unknown.c*/

#include<stdio.h>


/* Shriram: begin */
#include <errno.h>
#include <math.h>

/* VMS: MAY NEED TO CHANGE --
   possibly remove "sys/" from the next 3 lines */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
/* Shriram: end */

#include <string.h>

/* cgh */
#if !defined(vms)
#include <malloc.h>
#endif

/* VMS: MAY NEED TO CHANGE --
   comment out any of the next 3 lines for files your system can't find */
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
/* end cgh */

#if defined(vms)
#define unlink delete
#endif

/*
   If LOOPSPEED is defined, the file whose name is defined in the
   macro LOOPFILE_NAME is created.

   If defined here, define in commondefs.h as well.
*/
#if !defined(LOOPSPEED)
#define LOOPSPEED 1
#endif
#if LOOPSPEED
#endif /*LOOPSPEED */



#define aVersion         "5.20"   /*PRESENT VERSION OF LINKAGE*/
#define fVersion         "4.1P"   /*PRESENT VERSION OF FASTLINK*/

#if LOOPSPEED
/*
   max number of loop vectors that we will consider at any locus
   this is used to bound the number of loops we consider in unknown_poss

   we will always consider at least one loop if there are any
*/
#define max_vectors_considered 10000

int fewer_vects_size;  /* used for diagnostics when above macro is too big */
#endif

/*ALLELE_SPEED is used to set up renumbering of alleles when not all
  alleles are present in a pedigree*/
#if !defined(ALLELE_SPEED)
#define ALLELE_SPEED 1
#endif
#define ALLELE_SPEED_CONSTANT 61192012


#if LOOPSPEED
#if !defined(LOOP_BREAKERS)
#define LOOP_BREAKERS 1
#endif /*LOOP_BREAKERS*/
#else
#if !defined(LOOP_BREAKERS)
#define LOOP_BREAKERS 0
#endif /*LOOP_BREAKERS*/
#endif /*LOOPSPEED */

#ifndef EXIT_FAILURE
#ifdef vms
#define EXIT_FAILURE (02000000000L)
#else
#ifndef SOLARIS
#define EXIT_FAILURE (-1)
#endif   /* SOLARIS */
#endif
/*from p2c.h*/
#endif

#ifndef EXIT_SUCCESS
#ifdef vms
#define EXIT_SUCCESS 1
#else
#define EXIT_SUCCESS 0
#endif
/*from p2c.h*/
#endif

#define WHITE_SPACE " \n\r\t\v"

#define maxlocus        30   /*MAXIMUM NUMBER OF LOCI*/
#define maxall          25   /*MAX NUMBER OF ALLELES AT A SINGLE LOCUS*/

#define maxgeno         (maxall * (maxall + 1) / 2)
    /*MAX NUMBER OF SINGLE LOCUS GENOTYPES*/
/*Different definition than in analysis programs!*/

#define maxind         2000   /*MAXIMUM NUMBER OF INDIVIDUALS IN A PEDIGREE*/
#define maxmarriage     8   /*MAXIMUM NUMBER OF MARRIAGES FOR ONE MALE*/

#define maxloop         8

#define maxfact         maxall
    /*MAXIMUM NUMBER OF BINARY CODES AT A SINGLE LOCUS*/

#define maxtrait        3
    /*MAXIMUM NUMBER OF QUANTITATIVE FACTORS AT A SINGLE LOCUS*/

#define missval         0.0   /*MISSING VALUES FOR QUANTITATIVE TRAITS*/

#define affall          2
    /*DISEASE ALLELE FOR QUANT. TRAITS OR AFFECTION STATUS*/
#define missaff         0   /*MISSING VALUE FOR AFFECTION STATUS*/
#define affval          2   /*CODE FOR AFFECTED INDIVIDUAL*/
#define maxliab       120   /*MAXIMUM NUMBER OF LIABILITY CLASSES*/
#define binformat       2
#define allformat       3

#ifndef NULL
#define NULL             0
#endif
#define FileNotFound   10
#ifndef TRUE
#define TRUE            1
#endif
#ifndef FALSE
#define FALSE           0
#endif
#ifndef EXIT_FAILURE
#ifdef vms
#define EXIT_SUCCESS    1
#define EXIT_FAILURE    (02000000000L)
#else
#define EXIT_SUCCESS    0
#define EXIT_FAILURE    (-1)
#endif
#endif
#define Malloc          malloc
#define Free            free

#if LOOPSPEED
#define LOOPFILE_NAME "loopfile.dat"
#if LOOP_BREAKERS
#define COUNTFILE_NAME "countfile.dat"
#define TPEDFILE_NAME  "tpedfile.dat"
#define LPEDFILE_NAME  "lpedfile.dat"
#endif /*LOOP_BREAKERS*/
#endif /*LOOPSPEED*/

#if !defined(ONE_ERROR_ONLY)
#define ONE_ERROR_ONLY   0   /*print one sure error, or all possible errors*/
#endif

#if !defined(DEPTH_MULTIPLE)
#define DEPTH_MULTIPLE   3
#endif

#if !defined(DOWN_CHECK)
#define DOWN_CHECK TRUE
#endif

#define OLD      1  /*compatible with original unknown.c*/
#define NEW      2
#define NEWFIRST 3
#define NEWSECOND 4
#define OLD2     5
#define FIRST    1
#define SECOND   2

/*Possible status for inidividual number i while reading pedfile.dat*/
#define NOT_FOUND 0
#define FOUND_AS_SELF 1
#define FOUND_AS_PARENT 2
#define DUPLICATED 3
#define FILE_NAME_LENGTH 30

/*from p2c*/

typedef char boolean;

typedef boolean genotype[maxgeno];
typedef enum {
  peelup, peeldown
} direction;
typedef long binset;

typedef binset phenarray[maxall];
typedef boolean possvect[maxall][maxall];
typedef possvect possarray[maxlocus];
typedef enum {
  affection, quantitative, binary_
} locustype;

typedef struct locusvalues {
  long nallele;
  long maxallele;
  locustype which;
  double onefreq;
#if LOOPSPEED
  long fgeno; /* number of genotypes at this locus */
  long mgeno;
#endif
  union {
    long ntrait;
    struct {
      double pen[maxall + 1][maxall][3][maxliab];
      long nclass;
    } U0;
    struct {
      phenarray allele;
      long nfactor, format;
    } U2;
  } UU;
} locusvalues;

typedef struct phenotype {
  locustype which;
  double x[maxtrait];
  boolean missing;
  long aff;
  long  liability;
  binset phenf; /*encodes phenotype/genotype in pedin.dat as a
                    bit vector */
  int allele1;
  int allele2;
} phenotype;

typedef phenotype *indphen[maxlocus];

typedef struct thisarray {
  genotype genarray;
} thisarray;

typedef struct information {
  possarray possible;
} information;

typedef struct thisperson {
  long id, paid, maid, offid, npaid, nmaid, sex, profield, oldped, nseq;
  struct thisperson *pa, *ma, *foff, *nextpa, *nextma;
  thisarray *gen;
  indphen phen;
#if !LOOPSPEED
  information *store;
#endif
  boolean thisunknown[maxlocus];
  boolean unknown, multi, done, up, male;
  boolean downvisit;  /*added by A. A. Schaffer for diagnostic*/
} thisperson;

#if LOOPSPEED
/*
   These typedefs define the table to hold the valid loopbreaker vectors
   for each locus.
*/
typedef int *vector_for_loop;
typedef vector_for_loop *vector_for_locus;
typedef vector_for_locus *loop_vector_array;
#endif

#if LOOPSPEED
/*
   These typedefs define the table to hold the possible genotypes
   for each unknown person at each locus for each valid loopbreaker
   vector.
*/
typedef boolean *geno_for_loop_vector;
typedef geno_for_loop_vector *geno_for_locus;
typedef geno_for_locus *geno_for_unknown;
#endif

#if LOOPSPEED
/* basic linked list stuff */
typedef struct List_Elt {
  struct List_Elt *next;
  int value;
} list_elt;

typedef struct Simple_List {
  list_elt *head;
  list_elt *curr;
} simple_list;
#endif

/* Dylan
         -- changed haplotype from enumerated type of {a,b}
         -- done in mid 1994
*/
typedef unsigned char haplotype;

typedef long subhap[2];

typedef struct new_locus_info {
  int present;  /*is this allele present?*/
  int new_allele; /*what is this allele mapped to?*/
  int old_allele; /*inverse of mapping*/
} new_locus_info;

typedef int new_allele_count[maxlocus];

/*Adjusted allele counts for each pedigree and locus*/
new_allele_count *ped_new_allele_count;

/* Does this pedigree have different adjusted allele counts from
   the previous pedigree? */

boolean *ped_must_change_locations;

/* dwix: begin */

#define DEFAULT_STRING_LENGTH  500

/* type definitions for *allele_downcode_check* */
typedef new_locus_info  loc_all[maxlocus][maxall+1];
loc_all *ped_loc_all;
int currentped, currentlocus;
int *pedidx2num;
/* dwix: end */

#define maxmar		  5   /* max number of marriages --- should be defined in unknown.c */
#define maxindperpedigree  300 /* max number of individuals in one pedigree --- should be defined in unknown.c */ 
#define maxnode		  maxindperpedigree*2  /* max number of individuals and families */
#define MAXIN		  10000     /* max number */
#define MAXPED            500
#define epsilon		  0.0000001 /* small float to reduce dividing by zero */
#define LINEN		  9         /* number of relevant fields in each line */
#define COUNTFILE_WORD_LENGTH   50  /* max number of chracters in a string in countfile */
#define COUNTFILE_LINE_LENGTH	500 /* max number of characters in each line of countfile */    
#define UNVISITED  	  0   
#define VISITED     	  1
#define EXPANDED    	  2
#define MALE  		  1
#define FEMALE 		  2
/*Next 9 constants are for the first 9 columns of pedigree file*/
#define LINE_PEDIGREE     0
#define LINE_ID           1
#define LINE_PA           2
#define LINE_MA           3
#define LINE_FOFF         4
#define LINE_NEXTPA       5
#define LINE_NEXTMA       6
#define LINE_GENDER       7
#define LINE_PROFIELD     8

/* 
 *  Directed node structure
 */
typedef struct DNODE_ {
   int   fSelected;                 /* flag = true if node is selected */
   int   fFamilyNode;               /* flag = true if node represents a family 
                                       and false if node is an individual */ 
   int   indegree, outdegree;       /* number of parents, children */
   int   in[maxnode], out[maxnode]; /* array of possible parents, children, where in[x] is true
                                       iff x is a parent of this node */
} DNODE, *PDNODE;

/* 
 *  Undirected node structure
 */
typedef struct NODE_ {
   int  fSelected;                      /* flag = true if node selected */
   int  degree;                         /* number of neighbors */
   int  D[maxnode];                     /* array of neighbors, where D[i]=true
                                           iff i is a neighbor of this node */
   int  sel[maxnode];                   /* help array */
} NODE, *PNODE;

/* 
 *  persons structure
 */
typedef struct TMPERSON_ {
 /*fields for id, father's id, mother's id, id of first child, id
   of next child with same father, id of next child with same mother, gender,
   cycle indicator*/
  long   id, paid, maid, foff, nextpa, nextma, sex, cycle; 
  long   numMarriages;   /*number of marriages*/
  long   numCopies;     /*number of clones of this person*/
  long   marriages[maxmar];  /*array of spouse ids*/
 /*weight, number of homozygous and heterozygous single-locus genotypes possible
   at each locus*/
  long   weight, homoz[maxlocus], heteroz[maxlocus]; 
  double weight_log; /*logarithm of weight*/
} PERSON;


long nsystem; /*number of loci*/
locusvalues *thislocus[maxlocus]; /*description of each locus*/
char pedfilename[FILE_NAME_LENGTH];
