//To compile WITH Borland C++ set BORLAND to 1 otherwise set BORLAND to 0
#define BORLAND 1
#define EXT ".txt"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <fstream>
#include <map>
#include <iostream.h>
#include <vector>
#include "cen1901.hpp"

#define EL 3000
#define FL 4000
#define BESOK 2000
#define SERV 6000

#include "coderel.hpp"

#if BORLAND

#include <dir.h>
#include "borland.h"
#else
#include <dirent.h>
#include "fnmatch.h"
#include "fnmatch.c"
#include "borland.h"
#endif
#include "precoden.h"
#pragma hdrstop
#if BORLAND
#include <condefs.h>
#endif



#pragma argsused

#define HP 0
#define SEX 1
#define BOSATT 2
#define MAR 4
#define FSTD 6

#define RHP 1
#define RSPOUSE 2
#define RCHLD 3
#define RREL 4
#define RSERV 5
#define RANDRE 6
#define RIND 7

#define OHEAD 1
#define OSEX 2
#define OBOSATT 3
#define OREL 4
#define OMAG 5
#define OAGE 6
#define OFSTD 7
#define OOCC 8

#define BEFB 1
#define BEFMT 2
#define BEFF 3
#define BEFRAR 9
#define MAXDIFF 30

#define MARRIED 2

#define UNMARR  1
#define SPOUSEAB 3
#define WIDOWED 4
#define MARUNKWN 9
#define FEMALE 2
#define MALE 1
#define RCPARENT 120
#define RCUNCLE 131
#define PMAX 100
#define RULMAX 200
#define PIDMAX 2
#define MAXAGE 121

#define AGEMARR 20
#define MAXCOL 30

#define OLDAGE 65

FILE *flog;

int nclose, nopen;

class cultbio {
   public:
    cultbio();
        int menarch, menop, female_marr, male_marr, age_gap,head_ship;
        int usesurname;
   private:
};

cultbio::cultbio() {
 menarch=17;
 menop=45;
 female_marr=19;
 male_marr=21;
 head_ship=21;
 age_gap=27;
// Check on surname 0=yes, 1=no;
 usesurname=1;
};



class c_person {
    public:
       void Add_Person(char *surname,
                   int _sex, int mar, int _age, int rel);
       int relcode, marcode, sexcode, age;
       char sname[81];
      int poploc, momloc, sploc;
    private:
       };

void c_person::Add_Person(char *surname,
                   int _sex, int mar, int _age, int rel)
{
  marcode=mar;
  age=_age;
  relcode=rel;
  sexcode=_sex;
  strcpy(sname,surname);
  if (marcode<1 || marcode>5)
//  if (marcode==9 && age < bio.female_marr) marcode=1;
     marcode=1;
  if (relcode<10 || relcode>9999)
     relcode=9999;
};




int nperson=-1;

typedef struct  {
        int    piece,foli,page;
        long   rfnseq,minseq,foliint,lineno,seqjump;
        float  folinum;
        double pid,hid;
        char   pidstr[20];
        } sid_t;

struct ego_t {
        int sex, rel, age, mar;
        char sname[80];
        };


class c_household  : public c_person   {
    public:
    c_household(int age0);
    ~c_household();
    vector<c_person>pperson;
    int codecfu();
    int Add_Person(char *surname,
                   int sex, int mar, int age, int rel);
    int personid;
    void inithousehold();
    void IPUMScode();
    int parentspresent(int mannkone);
    int getfarogmor();
    int wifepresent();
    int numch0_5();
    private:
       cultbio bio;
       int Corr_Person();
       int modrelcode(c_person *person);
    int cfu[PMAX], cfu_h[PMAX];
    int i , egoi, starti, j, nkin, n_cfus;
    struct ego_t ego;
    int nrelcode, cfunos, count,spouse, rela, rela1, mar, mar1, hhd;
    char sex,sex1;
    FILE *flog;

    int lat,up1,up2,down1,down2;
    int sib,cfusize;
    int lat_k,up1_k,up2_k,up3_k,down1_k,down2_k,down3_k;
    int nserv, nlodg, nother, nvisit;
    int tage, nper, faren, mor;

};

c_household::c_household(int age0) {
 inithousehold();
 flog=fopen("data/hhold.log","a");
 tage=age0;
}

c_household::~c_household() {
  codecfu();
  fclose(flog);
}

void c_household::inithousehold() {
      int i;
      cfunos=0;
      count=0;
      for (i=0;i<PMAX;i++) cfu[i]=0;
      for (i=0;i<PMAX;i++) cfu_h[i]=0;
      nkin=0;
      spouse=0;
      cfusize=0;
      personid=0;
      nserv=0;
      nlodg=0;
      nother=0;
      nvisit=0;
 lat=0,up1=0,up2=0,down1=0,down2=0;
 sib=0,cfusize=0;
 lat_k=0,up1_k=0,up2_k=0,up3_k=0,down1_k=0,down2_k=0,down3_k=0;
};

int c_household::Add_Person(char *surname,
                   int sex, int mar, int age, int rel)
{
   c_person *pers;

  pers = new (c_person);
  pers->Add_Person(surname,sex,mar,age,rel);
  if (Corr_Person()>0)
    fprintf(flog,"Relationships corrected \n");
  pperson.push_back(*pers);
  delete pers;
  return ++personid;
};


int eqdiv(int a, int b, int denom)
{
 div_t at, bt;

 at=div(a,denom);
 bt=div(b,denom);
 if (at.quot!=bt.quot) return 1;
 else return 0;
}

int  c_household::codecfu()
{

    cfu[0]=0;
    if (personid>PMAX) {
        hhd=600;
/*        printf("Mulig feil i hushaldsinndeling %d \n",nhhold);
*/
        fprintf(flog,"Mulig feil i hushaldsinndeling \n");
        return hhd;
  }
/* find the head
*/
     for (i=0;i<personid;i++) {
       if (pperson[i].relcode>=10 && pperson[i].relcode<=13) {
          egoi=i;
          ego.sex=pperson[i].sexcode;
          ego.age=pperson[i].age;
          ego.mar=pperson[i].marcode;

          ego.rel=pperson[i].relcode;
          strcpy(ego.sname,pperson[i].sname);
          cfu_h[i]=pperson[i].relcode;
          cfunos++;
          cfu[i]=cfunos;
          count++;
          break;
       }
     }
// spouse of head=ego
     for (i=egoi+1;i<personid;i++) {
       if (pperson[i].relcode>=20 && pperson[i].relcode<=29 &&
         pperson[i].marcode==MARRIED && cfu[i]==0) {
           if (pperson[i].sexcode==FEMALE)
             ego.age=pperson[i].age;
             spouse=1;
             cfu[i]=cfunos;
             count++;
             break;
           }
     }
// children of head=ego
     for (i=egoi+1;i<personid;i++) {
         if ((pperson[i].relcode / 10)==3
         && pperson[i].marcode==UNMARR && cfu[i]==0) {
           cfu[i]=cfunos;
           count++;
         }
     }
//  if no matching cfu members found re-set ego's cfu & cfunos;
     if (count==1) {
          cfu[egoi]=0;
          cfu_h[egoi]=0;
          cfunos--;
     }
     if (ego.mar==MARRIED && spouse==0) {
        ego.mar=SPOUSEAB;
        pperson[egoi].marcode=SPOUSEAB;
     }
     count=0;
     spouse=0;
// look for secondary cfu
     starti=egoi+1;
     for (i=starti;i<personid;i++) {
        if (pperson[i].marcode>=MARRIED
        && pperson[i].marcode<MARUNKWN
        && cfu[i]==0) {
           egoi=i;
           cfunos++;
           count++;
           cfu[i]=cfunos;
           ego.sex=pperson[i].sexcode;
           ego.age=pperson[i].age;
           ego.mar=pperson[i].marcode;
           ego.rel=pperson[i].relcode;
           strcpy(ego.sname,pperson[i].sname);
           cfu_h[i]=pperson[i].relcode;
           if (ego.mar==MARRIED) {
             for (j=i+1;j<personid;j++) {
               if  (pperson[j].marcode==MARRIED
               &&  pperson[j].sexcode != ego.sex
               && (strcasecmp(pperson[j].sname,ego.sname)==0 ||
                   bio.usesurname==1)
               &&  abs(ego.age-pperson[j].age)<bio.age_gap
               &&  eqdiv(pperson[j].relcode,ego.rel,10) == 0
               &&  cfu[j]==0) {
                 cfu[j]=cfunos;
                 count++;
                 spouse=1;
                 if (pperson[j].sexcode==FEMALE) ego.age=pperson[j].age;
                    break;
               }
             }
           }
           for (j=i+1;j<personid;j++) {
             if ((cfu[j]==0
             && pperson[j].marcode==UNMARR
             && (strcasecmp(pperson[j].sname,ego.sname)==0 || bio.usesurname==1)
             && (ego.age - pperson[j].age) >= bio.menarch
             && (ego.age - pperson[j].age) <= bio.menop)
             && ((ego.rel/10)==3 && (pperson[j].relcode/10)==6
              || (ego.rel/10)==15 && (pperson[j].relcode/10)==4
              || (ego.rel/10)==12 && (pperson[j].relcode/10)==3
              || (ego.rel/10)==4 && (pperson[j].relcode/10)==7
              || (ego.rel/10)==6 && (pperson[j].relcode/10)==8
              || (ego.rel/10)==11 && (pperson[j].relcode/10)==12
              || (ego.rel/10)==13 && (pperson[j].relcode/10)==16
              || (ego.rel/10)==14 && (pperson[j].relcode/10)==13
              || (ego.rel/10)==16 && (pperson[j].relcode/10)==5
              || (ego.rel/10)==2 &&  (pperson[j].relcode/10)==6)) {
                 cfu[j]=cfunos;
//     set cfu number;
                 count=count+1;
//     set count of possible cfu members;
             }
             else if (pperson[j].marcode>=2
               &&  (strcasecmp(pperson[j].sname,ego.sname)==0 || bio.usesurname==1)
               &&  pperson[j].relcode==ego.rel/10
               &&  cfu[j]==0)
                   break;
           }
           if (count==1) {
              cfu[egoi]=0;
              cfunos--;
              cfu_h[egoi]=0;
           }
           if (ego.mar==MARRIED && spouse==0) {
              ego.mar=SPOUSEAB;
              pperson[egoi].marcode=SPOUSEAB;
           }
           spouse=0;
           count=0;
        }
     }
     nkin=0;
     n_cfus=0;
     for (i=0;i<personid;i++) {
        if (pperson[i].relcode>=10 && pperson[i].relcode<200) {
          nkin++;
          if (cfu[i]>n_cfus)
             n_cfus=cfu[i];
        }
        else if (pperson[i].relcode>=2000 && pperson[i].relcode<3000)
            nvisit++;
        else if (pperson[i].relcode>=3000 && pperson[i].relcode<5000)
            nlodg++;
        else if (pperson[i].relcode>=5000 && pperson[i].relcode<6000)
            nother++;
        else if (pperson[i].relcode>=6000 && pperson[i].relcode<7000)
            nserv++;
        else if (pperson[i].relcode>=7000 && pperson[i].relcode<10000)
            nother++;
     }
     down1=0;lat=0;down2=0;up1=0;up2=0;

     for (i=0;i<personid;i++)
       if ((cfu_h[i]>=10 && cfu_h[i]<=29)
       ||  (cfu_h[i]>=150 && cfu_h[i]<=169)
       ||  (cfu_h[i]>=50 && cfu_h[i]<=59))
          lat++;
       else if ((cfu_h[i]>=30 && cfu_h[i]<=39)
       || (cfu_h[i]>=40 && cfu_h[i]<=49))
          down1++;
       else if ((cfu_h[i]>= 60 && cfu_h[i]<=69)
       || (cfu_h[i]>=70 && cfu_h[i]<=79))
          down2++;
       else if (cfu_h[i]>= 120 && cfu_h[i]<=139)
          up1++;
       else if ((cfu_h[i]>= 110 && cfu_h[i]<=119)
       || (cfu_h[i]>= 140 && cfu_h[i]<=149))
          up2++;

     lat_k=0;down1_k=0;down2_k=0;up1_k=0;up2_k=0;up3_k=0;down3_k=0;
     for (i=0;i<personid;i++)
        if (cfu[i]==0 || cfu[i]>=2) {
           rela=pperson[i].relcode;
           if ((rela >=10 && rela<=29) || (rela >=150 && rela<=159)
           || (rela >=50 && rela<=59))
                lat_k=lat_k+1;
           else if ((rela>=30 && rela<=39) || (rela>=40 && rela<=49))
                down1_k=down1_k+1;
           else if ((rela>=60 && rela<=69) || (rela>=70 && rela<=79))
                down2_k=down2_k+1;
           else if ((rela>=120 && rela<=129) || (rela>=130 && rela<=139))
                up1_k=up1_k+1;
           else if ((rela>=110 && rela<=119) || (rela>=140 && rela<=149))
                up2_k=up2_k+1;
        }
     if (n_cfus==0 && nkin>0) {
        if (nkin==1) {
          if (pperson[0].marcode>=3 && pperson[0].marcode<=8) hhd=110;
          else {
            if (nother>0)
               hhd=230;
            else
               hhd=120;
          }
        }
        else {
          sib=0;
          for (i=0;i<personid;i++) {
            rela=pperson[i].relcode;
            if ((rela >=10 && rela<=19) || (rela>=150 && rela<=159))
              sib=sib+1;
          }
          if (sib==nkin) hhd=210; else hhd=220;
        }
     }
     else if (n_cfus==1) {
        cfusize=0;
        for (i=0;i<personid;i++) {
          rela=pperson[i].relcode;
          if (rela >=10 && rela<=199 && cfu[i]>0) cfusize=cfusize+1;
        }
        rela1=pperson[0].relcode;
        mar1 =pperson[0].marcode;
        if (pperson[0].sexcode==MALE) sex1='M';
        else sex1='F';
        if (nkin==cfusize) {
           if ((rela1==11 || rela1==10 || rela1==12) && (mar1==2)) {
              if (nkin==2) hhd=310;
              else if (nkin>=3) hhd=320;
           }
           else if (rela1==11 || rela1==10 || rela1==12) {
             if (sex1=='M' && mar1>=3 && mar1<=9) hhd=330;
             else if (sex1=='F' && mar1>=3 && mar1<=9) hhd=340;
             else hhd=350;
           }
           for (i=0;i<personid;i++) {
             rela=pperson[i].relcode;
             if (rela >= 120 && rela<=129 && cfu[i]>0) {
               mar=pperson[i].marcode;
               if (pperson[i].sexcode==MALE) sex='M'; else sex='F';
               if (mar==MARRIED) hhd=320;
               else if (sex=='M' && mar>=3 && mar <=9) hhd=330;
               else if (sex=='F' && mar>=3 && mar <=9) hhd=340;
               else hhd=350;
             }
           }
        }
        else {
        if (lat==1) {
          if (up1_k+up2_k+up3_k>=1 && lat_k+down1_k+down2_k+down3_k==0) hhd=410;
          else if (up1_k+up2_k+up3_k>=0 && lat_k==0 && down1_k+down2_k+down3_k>=1)
            hhd=420;
          else if (up1_k+up2_k+up3_k>=0 && lat_k>=1 && down1_k+down2_k+down3_k==0)
            hhd=430;
          else hhd=440;
        }
        else if (up1==1) {
          if (up2_k+up3_k>=1 && up1_k+lat_k+down1_k+down2_k+down3_k==0)
            hhd=410;
          else if (up1_k+up2_k+up3_k==0 && lat_k+down1_k+down2_k+down3_k>=1)
            hhd=420;
          else if (up1_k>=1 && up2_k+up3_k+lat_k+down1_k+down2_k+down3_k==0)
            hhd=430;
          else hhd=440;
        }
        else if (up2==1) {
          if (up3_k>=1 && up1_k+up2_k+lat_k+down1_k+down2_k+down3_k==0)
            hhd=410;
          else if (up2_k+up3_k==0 && up1_k+lat_k+down1_k+down2_k+down3_k>=1)
            hhd=420;
          else if (up2_k>=1 && up1_k+up3_k+lat_k+down1_k+down2_k+down3_k==0)
            hhd=430;
          else hhd=440;
        }
        else if (down1==1) {
          if (up1_k+up2_k+up3_k+lat_k>=1 && down1_k+down2_k+down3_k==0) hhd=410;
          else if (up1_k+up2_k+up3_k+lat_k+down1_k==0 && down2_k+down3_k>=1)
            hhd=420;
          else if (up1_k+up2_k+up3_k+lat_k==0 && down1_k>=1 && down2_k+down3_k==0)
            hhd=430;
          else hhd=440;
        }
        else if (down2==1) {
          if (up1_k+up2_k+up3_k+lat_k+down1_k>=1 && down2_k+down3_k==0)
            hhd=410;
          else if (up1_k+up2_k+up3_k+lat_k+down1_k+down2_k==0 && down3_k>=1)
            hhd=420;
          else if (up1_k+up2_k+up3_k+lat_k+down1_k+down3_k==0 && down2_k>=1)
            hhd=430;
          else hhd=440;
        }
        }
     }
     else {
       if (lat==1 && down1==0 && down2==0 && up1+up2>=1) hhd=510;
       else if (lat==1 && up1+up2==0 && down1+down2>=1) hhd=520;
       else if (lat>=2 && up1_k==0 && up1+up2+down1+down2==0) hhd=540;
       else if (lat>=2 && up1+up2+down1+down2==0) hhd=530;
       else hhd=550;
     }
     for (i=0;i<personid;i++) {
          cfu[i]=0;
          cfu_h[i]=0;
     }
     nper=personid;
     personid=0;
     return hhd;
}

int c_household::getfarogmor()
{
        return faren+mor;
}
int c_household::numch0_5()
{
  int barn;
  int mina, maxa;

  faren=0;mor=0;barn=0;
  for (i=0;i<nper;i++)
    if (pperson[i].relcode>=10 && pperson[i].relcode<20) faren=1;
  mina=tage+19;
  maxa=tage+50;
  for (i=0;i<nper;i++)
    if (pperson[i].relcode>=20 && pperson[i].relcode<30
     && pperson[i].age>mina && pperson[i].age<maxa)
        mor=1;
  mina=tage;
  maxa=tage+5;
  if (faren==mor==1)
  for (i=1;i<nper;i++)
    if (pperson[i].relcode>30 && pperson[i].relcode<33
     && pperson[i].age>=mina && pperson[i].age<maxa) barn++;
  return barn;
};


int c_household::parentspresent(int mannkone)
{
 int i;

 if (mannkone>9 && mannkone<15) {
     for (i=1;i<personid;i++) {
//         test=     pperson[i].relcode;
         if (pperson[i].relcode>120 && pperson[i].relcode<125)
            return pperson[0].age;
     }
 }
 else if (mannkone>19 && mannkone<23) {
     for (i=1;i<personid;i++)   {
         if (pperson[i].relcode>124 && pperson[i].relcode<129)
            return pperson[0].age;
     }
 }
 return 0;
}

int c_household::wifepresent()
{
 int wifepre=0;

 if (personid>2 && pperson[1].relcode%10==2)
    wifepre=pperson[1].age;
 return wifepre;
};



int c_household::modrelcode(c_person *person)
{
 int modcode, mod10;

 modcode=person->relcode;
 mod10=person->relcode % 10;

 if (person->relcode>9 && person->relcode<20) {
    if (mod10==0  && (person->sexcode == 1 || person->sexcode==2))
         modcode=person->relcode + person->sexcode;
    else if (mod10>2)
         modcode=person->relcode - 2;
 }
 else if ((person->relcode >=150 && person->relcode <160)
      ||  (person->relcode >=30 && person->relcode <100)) {
          if (mod10>2 && (person->relcode % 5) > 1)
             modcode=person->relcode-2;
          else if (mod10==0 && person->sexcode<3)
             modcode=person->relcode+person->sexcode;
          if (mod10<5 && (person->marcode <2 || person->marcode>4))
              modcode = person->relcode - mod10;
 }
 else if (person->relcode > RCPARENT &&  person->relcode < RCUNCLE-1) {
       if (mod10>2  && (person->relcode % 5) > 1)
           modcode=person->relcode-2;
       else if (mod10==0 && person->sexcode<3)
           modcode=person->relcode+person->sexcode;
//        else  modcode=person->relcode
       }
 else if (person->relcode > 100 && person->relcode <1000)
      modcode = person->relcode - mod10;
  return modcode;
}

int c_household::Corr_Person()
{
 int corrections=0;
 int i,newfirst;
 div_t divide;


 if (personid>1) {
   if (pperson[0].sexcode==FEMALE
   && pperson[1].sexcode==FEMALE
   && (pperson[1].relcode==20 || pperson[1].relcode==22)) {
      fprintf(flog,"Corrected sex from %d to ",pperson[0].sexcode);
      pperson[0].sexcode=MALE;
      fprintf(flog," %d\n",pperson[0].sexcode);
      corrections++;
   }
   if (pperson[0].marcode!=MARRIED
   &&  pperson[1].marcode==MARRIED
   && (pperson[1].relcode==20 || pperson[1].relcode==22)) {
      fprintf(flog,"Corrected marital status from %d to ",pperson[0].marcode);
      pperson[0].marcode=MARRIED;
      fprintf(flog," %d\n",pperson[0].marcode);
      corrections++;
   }
   newfirst=0;
   for (i=1;i<personid;i++) {
      divide=div(pperson[i-1].relcode,1000);
      if (divide.quot>1 && divide.quot!=5 && divide.rem>=10 && divide.rem <70
      && pperson[i].relcode>=20 && pperson[i].relcode<70) {
         if (newfirst==0) newfirst=i-1;
         if (newfirst>0) {
           if ((pperson[newfirst].marcode==MARRIED
             && pperson[i].marcode==MARRIED
             && pperson[i].relcode>=20 && pperson[i].relcode<23)
           ||  (pperson[newfirst].marcode!=UNMARR
             && pperson[i].relcode>=30)) {
                fprintf(flog,"Corrected relcode from %d to ",pperson[i].relcode);
                pperson[i].relcode=pperson[i].relcode+(divide.quot*1000);
                fprintf(flog," %d\n",pperson[i].relcode);
                corrections++;
           }
         }
       }
   }
 }
 return corrections;
}

void c_household::IPUMScode() {
  int i, momloc, poploc;
  if (personid>1) {
     if ((pperson[0].relcode>=10 && pperson[0].relcode<14)
     && (pperson[1].relcode>=20 && pperson[1].relcode<23)) {
        pperson[0].sploc=2;
        pperson[1].sploc=1;
        momloc=2;
        poploc=1;
     }  else {
        pperson[0].sploc=0;
        pperson[1].sploc=0;
        momloc=0;poploc=0;
     }
     if (personid>2) {
        for (i=2;i<personid;i++)
        if (pperson[i].relcode>30 && pperson[i].relcode<33) {
           pperson[i].momloc=momloc;
           pperson[i].poploc=poploc;
        }
        else {
           pperson[i].momloc=0;
           pperson[i].poploc=0;
        }

     }
  }
  else {
     pperson[0].momloc=0;pperson[0].poploc=0;pperson[0].sploc=0;
  }
};

   using namespace std;



   class Person
   {
   public:
      int head,sex,mar,rel,age,bosatt,fstd,occupation;
      short relgrp;
   private:
   };



   class cmat {
      public:
      cmat(int startage);
      void AddMar(int age, int marcode);
      void AddHead(int age, int famcode);
      void AddLeavingHome(int age, int relcode);
      void AddParentsHome(int age);
      void AddHouseholdSize(int size);
      float ComputeEMHS(int maxsize);
      void Prevalence(int agef, int aget);
      void Prevalence2(int agef, int aget);
      float getage(int quartile, int maxv);
      float getage2(int quartile, int maxv);
      float Median(int quartile, int maxv, int agef, int aget);
      float ComputeQ(int harkol, int sumkol, int quartile);
      float PolynomFit(int quartile, int minv, int maxv, int agef, int aget);
      float indirect();
      float prevl, prevl2;
         int mat[3][MAXAGE];
      private:
         float percent[MAXAGE];
         float movavg[MAXAGE];
         int age0;
/*         CPolyFit<double> PolyFitObj;
         double correlation_coefficiant;
         vector<double> X;
         vector<double> Y;
         vector<double> A;*/
      };


   cmat::cmat(int startage)
   {
    for (int i=0;i<MAXAGE;i++) {
        mat[0][i]=0;
        mat[1][i]=0;
        mat[2][i]=0;
        percent[i]=(float) 0.0;
        movavg[i]=(float) 0.0;
    }
//  age0 må vere 1 dersom ft1865 og ft1801, age0=0 dersom ft1900

    age0=startage;
   }

   void cmat::AddMar(int age, int  marcode)
   {
      if (age>0)
         age=age-age0;
      else
         age=0;
      if (age>=0 && age<MAXAGE)
        if (marcode>=2 && marcode<=4)
            mat[0][age]++;
         else
            mat[1][age]++;
   };

   void cmat::AddHead(int age, int  famcode)
   {
      if (age>0)
         age=age-age0;
      else
         age=0;
      if (age>=0 && age<MAXAGE)
        if (famcode==1)
            mat[0][age]++;
         else
            mat[1][age]++;
   };

   void cmat::AddParentsHome(int age)
   {
      if (age>0)
         age=age-age0;
      else
         age=0;
      if (age>=0 && age<MAXAGE) {
         mat[1][age]++;
         mat[0][age]--;
      }
   }


   void cmat::AddLeavingHome(int age, int relcode)
   {
      if (age>0)
         age=age-age0;
      else
         age=0;
      if (age>=0 && age<MAXAGE)
        if (relcode>30 && relcode<35)
            mat[1][age]++;
         else
            mat[0][age]++;
   };


   void cmat::AddHouseholdSize(int size)
   {
    if (size>0 && size<MAXAGE)
       mat[0][size]++;
   }

   float cmat::ComputeEMHS(int maxsize)
   {
     int i;
     mat[0][0]=0;
     mat[1][0]=0;
     mat[2][0]=0;
     percent[0]= 0.0;
     percent[1]= 0.0;
     for (i=1;i<MAXAGE && i<maxsize;i++) {

       mat[1][i]=mat[0][i]*i;
       mat[2][i]=mat[1][i]*i;
       mat[0][0]+=mat[0][i];
       mat[1][0]+=mat[1][i];
       mat[2][0]+=mat[2][i];
     }
     if (mat[0][0]>0) percent[0]=(float) mat[1][0]/mat[0][0];
     if (mat[1][0]>0) percent[1]=(float) mat[2][0]/mat[1][0];
     return percent[1];
   }


   void cmat::Prevalence(int agef, int aget)
   {
        int har, ikkjehar;
        har=0;ikkjehar=0;
        for (int i=agef;i<aget;i++) {
            har+=mat[0][i];
            ikkjehar+=mat[1][i];
        }
        if (har>0)
           prevl=(float) har / (float)(har+ikkjehar);
        else
           prevl=(float) 1.0;
   };

   void cmat::Prevalence2(int agef, int aget)
   {
        int har, ikkjehar;
        float maxhar, testhar;
        har=0;ikkjehar=0;
        maxhar=(float) 0.0;
        for (int i=agef;i<aget;i++) {
            har+=mat[0][i];
            ikkjehar+=mat[1][i];
            if (i>agef && i%5==0) {
               if ((ikkjehar+har)>0) {
                 testhar=(float) har/(float) (ikkjehar+har);
                 if (testhar>maxhar) maxhar=testhar;
               }
               har=0;ikkjehar=0;
            }
        }
        if (maxhar>0)
           prevl2=maxhar;
        else
           prevl2=(float) 1.0;
   };


   float cmat::indirect()
   {
    int i, t2,t1;
    float sum, average, alder;

//  0=gifte+enkjer , 1 = ugifte

    for (i=15;i<55;i+=5) {
        mat[2][i]=mat[0][i]+mat[1][i]
                 +mat[0][i+1]+mat[1][i+1]
                 +mat[0][i+2]+mat[1][i+2]
                 +mat[0][i+3]+mat[1][i+3]
                 +mat[0][i+4]+mat[1][i+4];
        if (mat[2][i]>0) percent[i]=(float)
          (mat[1][i]+ mat[1][i+1]+ mat[1][i+2] + mat[1][i+3]+ mat[1][i+4])
        / (float) mat[2][i];
        else percent[i]=(float) 0.0;
    };
    sum=0;
    for (i=15;i<50;i+=5)
        sum+=(percent[i]*5);
    sum=sum+(float) 15.0;
    t1=0;t2=0;
    for (i=45;i<55;i++) {
        t1+=mat[1][i];
        t2+=mat[2][i];
    }
    average =  (float) t1/ (float) t2;
    sum=sum-(average* 50.0);
    alder = sum / (1.0 - average);
    return alder;
   }


   float cmat::getage(int quartile, int maxv)
   {
         float terskel, derivert, diff1, verdi;
         int i;

         Prevalence(45,54);
         for (i=0;i<15;i++) {
            movavg[i]=(float) 0.0;
            percent[i]=(float) 0.0;
         }
         for (i=15;i<MAXAGE;i++) {
           mat[2][i]=mat[0][i]+mat[1][i];
           if (mat[2][i]>0) percent[i]=(float) mat[0][i] / (float) mat[2][i];
           else percent[i]=(float) 0.0;
         };
         for (i=15;i<MAXAGE;i++)
           movavg[i]=(percent[i-1] + percent[i] + percent[i+1])/3;
         terskel=prevl / 4 * quartile;
         for (i=0;i<MAXAGE;i++)
           if (movavg[i]>terskel) break;
         derivert = (movavg[i] - movavg[i-1]);
         if (derivert==0)
             return (float) 99.0;
         diff1=(terskel-movavg[i-1])/derivert;
         verdi = (float) (i) - 0.5 + diff1;
         if (verdi>maxv)
            return (float) 99.0;
         else
            return verdi;
   }

  float cmat::ComputeQ(int harkol, int sumkol, int quartile)
   {
   float diff1, derivert, prevl,terskel;
   int i;

   for (i=0;i<99;i++)
      mat[sumkol][i]=mat[0][i]+mat[1][i];
      if (mat[sumkol][i]>0)
      percent[i]=(float) mat[harkol][i]/(float) mat[sumkol][i];
      else percent[i]=0.0;
   prevl=0.0;
   for (i=45;i<55;i++)
      prevl=prevl+percent[i];
   prevl=prevl/10.0;
   terskel=prevl / 4 * quartile;
   for (i=5;i<45;i++)
       movavg[i]=(percent[i-1]+percent[i]+percent[i+1])/3;
   for (i=0;i<45;i++)
      if (movavg[i]>terskel) break;
   derivert = (movavg[i] - movavg[i-1]);
   diff1=(terskel-movavg[i-1])/derivert;
// endra frå i - 1 til i - 0.5, 27.09.2002
   return (float) (i - 0.5) + diff1;
   }

   float cmat::Median(int quartile, int maxv, int agef, int aget)
   {

        float har, pop, prev, terskel;
        float verdi, derivert, diff;
        int i;

        har=0.0;pop=0.0;
        for (i=agef;i<aget;i++) {
           har=har+mat[0][i];
           mat[2][i]=mat[1][i]+mat[0][i];
           pop=pop+mat[2][i];
        }
        prev=har/pop;
        terskel=(prev/4)*quartile;
        for (i=0;i<99;i++) {
           if (mat[2][i]>0) percent[i]=(float) mat[0][i]/(float) mat[2][i];
           else percent[i]=0.0;
        }
        for (i=5;i<maxv;i++)
           movavg[i]=(percent[i-1]+percent[i]+percent[i+1])/3;
        for (i=6;i<agef;i++)
           if (movavg[i]>terskel) break;
        verdi = (float) i;
        derivert = movavg[i]-movavg[i-1];
        diff=(terskel-movavg[i-1])/derivert;
        verdi=verdi - 0.5 + diff;
        return verdi;
   }

   float cmat::PolynomFit(int quartile, int minv, int maxv, int agef, int aget)
   {
/*
        float har, pop, prev, terskel;
        float verdi, derivert, diff;
        int i,j;

        har=0.0;pop=0.0;
        for (i=agef;i<aget;i++) {
           har=har+mat[0][i];
           mat[2][i]=mat[1][i]+mat[0][i];
           pop=pop+mat[2][i];
        }
        prev=har/pop;
        terskel=(prev/4)*quartile;
        for (i=0;i<99;i++) {
           if (mat[2][i]>0) percent[i]=(float) mat[0][i]/(float) mat[2][i];
           else percent[i]=0.0;
        }
        for (i=minv,j=0;i<maxv;i++,j++) {
           Y.push_back(percent[i]);
           X.push_back(float(i));
        };
        PolyFitObj.PolyFit(X, Y, A);

        for (i=6;i<agef;i++)
           if (movavg[i]>terskel) break;
        verdi = (float) i;
        derivert = movavg[i]-movavg[i-1];
        diff=(terskel-movavg[i-1])/derivert;
        verdi=verdi - 0.5 + diff;
        return verdi;            */
   }


   float cmat::getage2(int quartile, int maxv)
   {
         float terskel, derivert, diff1, verdi;
         int i;

         Prevalence2(0,55);
         for (i=0;i<MAXAGE;i++) {
           mat[2][i]=mat[0][i]+mat[1][i];
           if (mat[2][i]>0) percent[i]=(float) mat[0][i] / (float) mat[2][i];
           else percent[i]=(float) 0.0;
         }
         movavg[0]=(percent[0]+ percent[1])/2;
         for (i=1;i<MAXAGE-1;i++)
           movavg[i]=(percent[i-1] + percent[i] + percent[i+1])/3;
         terskel=prevl2 / 4 * quartile;
         for (i=1;i<MAXAGE-1;i++)
           if (movavg[i]>terskel) break;
         derivert = (movavg[i] - movavg[i-1]);
         verdi=float (i);
         if (i>4 && derivert>0) {
            diff1=(terskel-movavg[i-1])/derivert;
            verdi = verdi - 0.5 + diff1;
         }
         else
            verdi = (float) 99.0;
         if (verdi>maxv) return (float) 99.0;
         else return verdi;
   }

   class StatObject
   {
    public:
        int matrise[100][MAXCOL];
        float males[12], females[12];
    StatObject();
    void PrintMatrise();
    void Skriv(ofstream *LOGFILE);
    void AddPerson(class Person *pers);
    void AddExtraChild (int perage, int persex);
    void AddMat(StatObject *FromMat);
    void CopyMat(StatObject *FromMat);
    void AddAlder(int hpalder, int makealder);
    float ComputeQ( int harkol, int sumkol, int quartile);
    float ComputeQ2( int harkol, int sumkol, int quartile);
    void Transitions(int _startage);
    void LoadFromFile(char *fn);
    void AkkMat(cmat Mat, int start);
    void SaveToFile(char *fn);
    private:
         tTable Table1;
         float percent[100];
         int startage;
         ofstream einlog;
   };

   void StatObject::AkkMat(cmat Mat, int start)
   {
    int i,j;
    for (i=0;i<MAXAGE;i++)
      for (j=start;j<start+3;j++)
         matrise[i+1][j]+=Mat.mat[j-start][i];
   }

   void StatObject::PrintMatrise()
   {
    int i,j;
    einlog.open("data/pm.txt",ios::app);

    for (i=0;i<100;i++) {
      for (j=0;j<MAXCOL;j++)
        einlog << matrise[i][j] << ";";
      einlog << endl;
    }
    einlog.close();
   };

   StatObject::StatObject()
   {
    int i,j;
    for (i=0;i<100;i++)
      for (j=0;j<MAXCOL;j++)
        matrise[i][j]=0;
   };

   void StatObject::SaveToFile(char *fn)
   {
    int i,j;
    ofstream fout;

    fout.open(fn);
    fout << "Alder\tAntmenn\tAnthp\tAntmake\tAntBarn\tAntslekt\tAnttenste\tAntAndre\tAntInd\tAntUgift\tAntgift";
    fout <<      "\tAntkvinner\tAnthp\tAntmake\tAntBarn\tAntslekt\tAnttenste\tAntAndre\tAntInd\tAntUgift\tAntgift";
    fout << "\tLedig\t31g\t32j\t33g\t34j\tAntPHpALD\t\t\t\t\n";
    for (i=0;i<100;i++) {
      fout << i << "\t";
      for (j=0;j<MAXCOL;j++)
        fout << matrise[i][j] << "\t";
      fout << endl;
    }
    fout.close();
   };

   void StatObject::LoadFromFile(char *fn)
   {
    int i,j;

    if (Table1.Open(fn)==0) {
       while (Table1.Read()==0) {
         if (Table1.fields[0][0]<';') {
           i=atoi(Table1.fields[0]);
           for (j=1;j<Table1.count;j++)
             if (j<=MAXCOL && i<100)
               matrise[i][j-1]+=atoi(Table1.fields[j]);
         }
       }
    }
   };

// Adderer FromMat til matrise
   void StatObject::AddMat(StatObject *FromMat)
   {
    int i,j;
    for (i=0;i<100;i++)
      for (j=0;j<MAXCOL;j++)
          matrise[i][j]+=FromMat->matrise[i][j];
   };

// Kopierer FromMat til matrise
   void StatObject::CopyMat(StatObject *FromMat)
   {
    int i,j;
    for (i=0;i<100;i++)
      for (j=0;j<MAXCOL;j++)
          matrise[i][j]=FromMat->matrise[i][j];
   };

   void StatObject::AddExtraChild(int perage, int persex)
   {
    if (persex==1)
       matrise[perage][21]++;
    else
       matrise[perage][22]++;
   }


   void StatObject::AddPerson(Person *pers)
   {
      if (pers->sex==1) {
        matrise[pers->age][0]++;
        matrise[pers->age][pers->relgrp]++;
        if (pers->mar==1 || pers->mar==9)
           matrise[pers->age][8]++;
        else
           matrise[pers->age][9]++;
      }
      else if (pers->sex==2) {
        matrise[pers->age][10]++;
        matrise[pers->age][pers->relgrp+10]++;
        if (pers->mar==1 || pers->mar==9)
           matrise[pers->age][18]++;
        else
           matrise[pers->age][19]++;
      }
      if (pers->rel > 30 && pers->rel<35)
         if (pers->rel==31 || pers->rel==33)
            matrise[pers->age][21]++;
         else
            matrise[pers->age][22]++;
   }

   void StatObject::AddAlder(int hpalder, int makeald)
   {
         int i;
         if ((makeald>15) && (makeald<99) && (abs(hpalder-makeald)<25)) {
            if (hpalder>15 && hpalder<99)
              i=(makeald + hpalder)/2;
            else
              i=hpalder;
         }
         else i=hpalder;
         matrise[i][25]++;
   }

   float StatObject::ComputeQ2(int harkol, int sumkol, int quartile)
   {
   float diff1, derivert, prevl,terskel;
   int i;

   for (i=0;i<100;i++)
      if (matrise[i+startage][sumkol]>0)
      percent[i]= 1.0 -((float) matrise[i+startage][harkol]/(float) matrise[i+startage][sumkol]);
      else percent[i]=1.0;
   prevl=0.0;
   for (i=45;i<55;i++)
      prevl=prevl+percent[i];
   prevl=prevl/10.0;
   terskel=prevl / 4 * quartile;
   for (i=0;i<MAXAGE;i++)
      if (percent[i]>terskel) break;
   derivert = (percent[i] - percent[i-1]);
   diff1=(terskel-percent[i-1])/derivert;
   return (float) (i - 0.5) + diff1;
   }

  float StatObject::ComputeQ(int harkol, int sumkol, int quartile)
   {
   float diff1, derivert, prevl,terskel;
   int i;

   for (i=0;i<100;i++)
      if (matrise[i+startage][sumkol]>0)
      percent[i]=(float) matrise[i+startage][harkol]/(float) matrise[i+startage][sumkol];
      else percent[i]=0.0;
   prevl=0.0;
   for (i=45;i<55;i++)
      prevl=prevl+percent[i];
   prevl=prevl/10.0;
   terskel=prevl / 4 * quartile;
   for (i=0;i<MAXAGE;i++)
      if (percent[i]>terskel) break;
   derivert = (percent[i] - percent[i-1]);
   diff1=(terskel-percent[i-1])/derivert;
// endra fra i - 1 til i - 0.5, 27.09.2002
   return (float) (i - 0.5) + diff1;
   }


   void StatObject::Transitions(int _startage)
   {
//    PrintMatrise();
    startage=_startage;
    males[8]=ComputeQ(1,0,1);
    males[9]=ComputeQ(1,0,2);
    males[10]=ComputeQ(1,0,3);
//  First marriage
    males[4]=ComputeQ(9,0,1);
    males[5]=ComputeQ(9,0,2);
    males[6]=ComputeQ(9,0,3);
    males[7]=matrise[40][9];
    females[4]=ComputeQ(19,10,1);
    females[5]=ComputeQ(19,10,2);
    females[6]=ComputeQ(19,10,3);
    females[7]=matrise[40][19];
//   leaving home
    males[0]=ComputeQ2(21,0,1);
    males[1]=ComputeQ2(21,0,2);
    males[2]=ComputeQ2(21,0,3);
    females[0]=ComputeQ2(22,10,1);
    females[1]=ComputeQ2(22,10,2);
    females[2]=ComputeQ2(22,10,3);
   }
   void  StatObject::Skriv(ofstream *LOGFILE)
    {
        int i;
      *LOGFILE << "ALH\t AFM\t Headship" << endl;
       for (i=0;i<12;i++)
      *LOGFILE << "Age\t " << i << "\t" << males[i] << "\t" << females[i] << endl;
    }

   class FileObject
   {
   public:
   FileObject();
   void Skriv(ofstream *LOGFILE);
   long readtek(char *ifname,char *ofname, int cyear);
   float prevsum[5];
   int  prevcount;
   StatObject FAgg, BAgg, Agg;
   StatObject MatAkk;
   };

   FileObject::FileObject()
   {
    int i;
    for (i=0;i<5;i++)
      prevsum[i]=0.0;
    prevcount=0;
   };

   void FileObject::Skriv(ofstream *LOGFILE)
   {
    int i;
    string s;
    for (i=0;i<5;i++)
      if (prevcount>0) {
         if (i<1) s=" Age first marriage male ";
         else if (i<2) s=" Age first marriage female ";
         else if (i<3) s=" headship";
         else if (i<4) s=" ALH male ";
         else if (i<5) s=" ALH female ";
         *LOGFILE << "Prevalence\t " << i << s << "\t" << prevsum[i]/prevcount << endl;
      }
   };

   FileObject *tekfil;

   class cprmaal
   {
   public:
        cprmaal();
        void LoadFromFile(char *fn);
        struct tprmaal {float prmaal[8];};
        tprmaal  amtmaal[22];
    private:
    tTable Table1;
   };

   cprmaal::cprmaal()
   {
      int i;

      for (i=0;i<22;i++) {
         amtmaal[i].prmaal[0]=i;
         amtmaal[i].prmaal[1]=0.20;
         amtmaal[i].prmaal[2]=0.15;
         amtmaal[i].prmaal[3]=0.27;
         amtmaal[i].prmaal[4]=0.34;
         amtmaal[i].prmaal[5]=0.42;
         amtmaal[i].prmaal[6]=0.23;
         amtmaal[i].prmaal[7]=2.20;
      }
   }


   void cprmaal::LoadFromFile(char *fn)
   {
    int i,j;

    if (Table1.Open(fn)==0) {
       while (Table1.Read()==0) {
         if (Table1.fields[0][0]<';') {
           i=atoi(Table1.fields[0]);
           for (j=1;j<Table1.count;j++)
             if (j<8 && i<22)
               amtmaal[i].prmaal[j]=atof(Table1.fields[j]);
         }
       }
    }
   }


   class tjord

   {
   public:
        tjord();
        void init();
        void LoadFromFile(char *fn);
        void ku();
        void korn();
        float getmaal(int nbruk);
        void addfoll(int knr,float hvete,float rug,float byg,
                     float havre,float bland,float erter,float poteter);
        void setprmaal(int anr, cprmaal *amtprmaal);
        int hest,  kveg ,faar, geiter,svin, reinsdyr;
        float hvete, rug, bygg, blandkorn, havre, erter, poteter;
        int anthush;
        float kuverd, kornverd;
        float getprod(int knr);
        int husdyrhald, dyrkar;
   private:
        struct tfoll {float foll[8];};
        tfoll amtfoll[20];
        float prod[8];
        float maal[8];
        float prmaal[8];
        tTable Table1;
        int antamt;
   };



   tjord::tjord()
   {
      init();
      antamt=0;
   }

   void tjord::init()
   {
    int i;
    hest=0;kveg=0;faar=0;geiter=0;svin=0;reinsdyr=0;
    hvete=0.0;rug=0.0;bygg=0.0;blandkorn=0.0;havre=0.0;
    erter=0.0;poteter=0.0;
    kornverd=0.0;kuverd=0.0; husdyrhald=0;dyrkar=0;
    anthush=0;
    for (i=0;i<8;i++)
      maal[0]=0.0;
   }

   void tjord::setprmaal(int anr, cprmaal *amtprmaal)
   {
     int i;
     if (anr>20) anr=0;
     for (i=0;i<8;i++) {
        prmaal[i]=amtprmaal->amtmaal[anr].prmaal[i];
        if (prmaal[i]==0)
           prmaal[i]=amtprmaal->amtmaal[0].prmaal[i];
     }
   }

   void tjord::ku()
   {
       kuverd=float (faar+geiter)+(svin*3);
       kuverd=(kuverd+(float)((hest*12)+(kveg*6)))/6;
   }

   void tjord::korn()
   {
    kornverd=bygg+(blandkorn*2/3)+(havre/2)
            +((hvete+rug+erter)*4/3)+(poteter/3*162/139);
   }

   float tjord::getmaal(int nbruk)
   {
    int i;
    if (nbruk==0) return 0.0;
    maal[0]=hvete/prmaal[1];
    maal[1]=rug/prmaal[2];
    maal[2]=bygg/prmaal[3];
    maal[3]=havre/prmaal[5];
    maal[4]=blandkorn/prmaal[4];
    maal[5]=erter/prmaal[6];
    maal[6]=poteter/prmaal[7];
    maal[7]=0;
    for (i=0;i<7;i++)
      maal[7]=maal[7]+maal[i];
    return maal[7]/(float) nbruk;

   }

   void tjord::addfoll(int knr,float fhvete,float frug,float fbyg,
                     float fhavre,float fbland,float ferter,float fpoteter)
   {
        if (knr>=0 && knr<20) {
           amtfoll[knr].foll[0]=fhvete;
           amtfoll[knr].foll[1]=frug;
           amtfoll[knr].foll[2]=fbyg;
           amtfoll[knr].foll[3]=fhavre;
           amtfoll[knr].foll[4]=fbland;
           amtfoll[knr].foll[5]=ferter;
           amtfoll[knr].foll[6]=fpoteter;
           antamt++;
        }
   }

   float tjord::getprod(int knr)
   {
    int i;
    prod[0]=amtfoll[knr].foll[0]*hvete*1.39*4/3;
    prod[1]=amtfoll[knr].foll[1]*rug*1.39*4/3;
    prod[2]=amtfoll[knr].foll[2]*bygg*1.39;
    prod[3]=amtfoll[knr].foll[3]*havre*1.39/2;
    prod[4]=amtfoll[knr].foll[4]*blandkorn*1.39*2/3;
    prod[5]=amtfoll[knr].foll[5]*erter*1.39*4/3;
    prod[6]=amtfoll[knr].foll[6]*poteter*1.62/3;
    prod[7]=0;
    for (i=0;i<7;i++)
      prod[7]=prod[7]+prod[i];
    return prod[7];
   }

   int Csex(char *s)
   {
      if (s[0]=='m' || s[0]=='M')
         return 1;
      else  if (s[0]=='k' || s[0]=='K' || s[0]=='f' || s[0]=='F')
         return 2;
      arfn["S\t"+string(s)]++;
      return 9;
   }

   int Chead(char *s)
   {
      if ((s[0]=='1' || s[0]=='x' || s[0]=='X') ||
          (s[0]>'1' && s[0]<='9'))
         return 1;
      else  if (s[0]==' ' || s[0]=='\0')
         return 2;
      arfn["H\t"+string(s)]++;
      return 9;
   }

   int Cmt(char *s)
   {
      int kode;
      strupr(s);
      if (s[0]=='B' || s[0]=='\0')
         return BEFB;
      else  if (s[0]=='F')
//           3
         return BEFF;
      else  if ((s[0]=='M' && s[1]=='T') ||
                (s[0]=='M' && s[1]=='\0'))
//           2
         return BEFMT;
      else  if (s[0]=='M' && s[1]=='F')
         return BEFF;
      if ((strlen(s)>2) && (s[0]=='M'))
         if (s[2]=='F') return BEFF;
         else if (s[2]=='T') return BEFMT;
      if ((strlen(s)>2) && (s[0]=='(')) {
           kode=Cmt(&s[1]);
           if (kode<9) return kode;
         }
      arfn["B\t"+string(s)]++;
      return 9;
   }

   int Cage(char *s, int ftaar)
   {
      long age;
      int ypos;
      int validage=0;

      if (*s==NULL)
         return 99;
      age=atol(s);
      if (age>(ftaar-100) && age<=ftaar) {
// Fire siffer i alder dvs. årstal
         age=ftaar - (int) age;
         validage=1;
      }
      else if (age>1011800) {
// Dato på forma ddmmyyyy, minste gyldige er 01.01.1800
         ypos=strlen(s)-4;
         if (ypos>4)
           while (ypos>4 && (s[ypos+3]<'0' || s[ypos+3]>'9'))
             ypos--;
         age=atol(s+ypos);
         if (age>(ftaar-100) && age<=ftaar) {
            age=ftaar-(int) age;
            validage=1;
         }
      }
      else if (strlen(s)==6) {
// Dato på forma ddmmyy
         age=atol(s+4);
         if (ftaar==1900)
            if (age>0)
               age=100 - (int) age;
            else
               age=0;
         else
            age=66 - (int) age;
         validage=1;
      }
      else if (strlen(s)==5) {
// Dato på forma ddmmyy
         age=atol(s+3);
         if (ftaar==1900)
            if (age>0)
               age=100 - (int) age;
            else
               age=0;
         else
            age=66 - (int) age;
         validage=1;
      }

      else if (strlen(s)==10) {
// Dato på forma dd.mm.yyyy
         age=atol(s+6);
         if (age>(ftaar-100) && age<=ftaar) {
            age = ftaar-(int) age;
            validage=1;
         }
      }
      else if (age<0)
         age=99;
      else if (age>99)
         age=99;
      else if (ftaar==1900) {
// Fødselsår er lik to siffer, aktuelt FT1900 for Moss, Ålesund og ?
         age = 100 - (int) age;
         validage=1;
      }
      if ((age>0 && age<100)
      || (age==0 && validage!=0))
         return age;
      if (age==0 && strcmp(s,"0")==0)
// Alder er lik 0 år.
         return 0;
      arfn["A\t"+string(s)]++;
      return 99;
   }

   int Cmar(char *s)
   {
      switch (s[0]) {
         case 'u': case 'U':
            return 1;
         case 'g': case 'G':
            return MARRIED;
         case 'e': case 'E':
            return 4;
         case 's': case 'S':
            return 5;
         case 'f': case 'F':
            return 6;
         case 'b': case 'B':
            return 1;
         case '\0':
            return 9;
      }
      if ((strcmp(s,"Pige")==0)
      || (strcmp(s,"pige")==0)) return 1;

      arfn["M\t"+string(s)]++;
      return 9;
   }


   CodeObject *RelCode, *OccCode, *FstdCode, *hputval, *huskode;
   cprmaal *prmaal;



class Jord1900 {
    public:
        virtual void Add_Jordbruk1900(tTable *table);
    protected:
        int njord,nkornpotet, nkreatur;
        int tilstdv, hjemmeh;
};


void Jord1900::Add_Jordbruk1900(tTable *table)
{
    njord++;
    if (table->count>2) {
      tilstdv=atoi(table->fields[1]);
      hjemmeh=atoi(table->fields[2]);
      if (table->fields[3][0]=='j' || table->fields[3][0]=='J')
         nkornpotet=1;
      else
         nkornpotet=0;
      if (table->fields[4][0]=='j' || table->fields[4][0]=='J')
         nkreatur=1;
      else
         nkreatur=0;
    } else {
      tilstdv=0;hjemmeh=0;nkornpotet=0;nkreatur=0;
    }
};


   class Hushald
   {
   public:
      Hushald(char *filename, char *_knr, int _ftaar, char _byland);
      ~Hushald();
      void Insert(Person *person);
      void InitHushald(bool _matr, char _mtrkl[100]);
      int AddJordbruk(tekTable *intab);
      int CountYoung(int ageb);
      void Skriv_Hushald();
      int Ant_Generasjonar();
      long pid;
      int  hushstrl, hammel_laslett;
      long phyid,preid;
      short sams[8],mnsams[8],kvsams[8];
      short mar[5];
      tjord jordbruk;
      int hsex,hpage,antbarn0_5,farogmor;
      int utvald, utvalsnr, divisor;
   private:
      vector<Person>group;
      vector<Person>::iterator p1;
      int spage,hocc,hfstd,hmar;
      FILE *fp;
      int knr, ftaar;
      int harjord;
      int smaafeverd;
      float kornverd;
      float snbruk;
      bool matr;
      char mtrkl[100];
      int aldre[100];
      int antgen;
      char byland;
   };


   class ctmat {
       public:
            ctmat(int alder0);
            void Add_Person(int mar, int age);
            void Add_Head(int head, int age);
            float SMAM();
       private:
         int mat[3][MAXAGE];
         int startage;
      };

   ctmat::ctmat(int alder0)
   {
    int i,j;

    for (i=0;i<3;i++)
      for (j=0;j<MAXAGE;j++)
        mat[i][j]=0;
    startage=alder0;
   };

   void ctmat::Add_Person(int mar, int age) {
      if (age>0) age = age - startage;
      else age=0;
      if (mar>=2 && mar<=4)
          mat[0][age]++;
      else
          mat[1][age]++;
   }

   void ctmat::Add_Head(int head, int age) {
      if (age>0) age = age - startage;
      else age=0;
      if (head==1)
          mat[0][age]++;
      else
          mat[1][age]++;
      }

   int Hushald::AddJordbruk(tekTable *intab)
   {
//     jordbruk = new tjord;

     if (intab->count > intab->FFEDRIFT) {
       jordbruk.anthush=1;
       jordbruk.hest=intab->AsInt(intab->FFEDRIFT);
       jordbruk.kveg=intab->AsInt(intab->FFEDRIFT+1);
       jordbruk.faar=intab->AsInt(intab->FFEDRIFT+2);
       jordbruk.geiter=intab->AsInt(intab->FFEDRIFT+3);
       jordbruk.svin=intab->AsInt(intab->FFEDRIFT+4);
       jordbruk.reinsdyr=intab->AsInt(intab->FFEDRIFT+5);
       jordbruk.ku();
       if (jordbruk.kuverd>0.15) jordbruk.husdyrhald=1; else jordbruk.husdyrhald=0;
       if (intab->count>intab->FLANDBRUK) {
         jordbruk.hvete=intab->AsFloat(intab->FLANDBRUK);
         jordbruk.rug=intab->AsFloat(intab->FLANDBRUK+1);
         jordbruk.bygg=intab->AsFloat(intab->FLANDBRUK+2);
         jordbruk.blandkorn=intab->AsFloat(intab->FLANDBRUK+3);
         jordbruk.havre=intab->AsFloat(intab->FLANDBRUK+4);
         jordbruk.erter=intab->AsFloat(intab->FLANDBRUK+5);
         jordbruk.poteter=intab->AsFloat(intab->FLANDBRUK+6);
         jordbruk.korn();
         if (jordbruk.kornverd>0.01) jordbruk.dyrkar=1; else jordbruk.dyrkar=0;
       }
       else {
         jordbruk.bygg=0;jordbruk.blandkorn=0;jordbruk.havre=0;
         jordbruk.poteter=0; jordbruk.dyrkar=0;
         jordbruk.kornverd=0.0; jordbruk.erter=0;
       }
       harjord=pid-1;
       return harjord;
     }
     else {
         jordbruk.init();
         jordbruk.anthush=0;
         return -1;
     }
   }

   Hushald::Hushald(char *filename,char *_knr, int _ftaar, char _byland)

   {
      short i;
      knr=atoi(_knr);
      for (i=0;i<=RIND;i++) {
         sams[i]=0;
         kvsams[i]=0;
         mnsams[i]=0;
         if (i<5) mar[i]=0;
      }
      hushstrl=0;
      fp=fopen(filename,"a");
      preid=1;
      harjord=-1;
      ftaar=_ftaar;
      jordbruk.addfoll(0,7.8,9.9,7.0,5.8,6.9,5.4,7.0);
      jordbruk.setprmaal(knr/100,prmaal);
      for (i=0;i<100;i++) aldre[i]=0;
      antbarn0_5=0;
      utvald=-1;
      byland=_byland;
      if (byland=='F') divisor=20; else divisor=10;
      utvalsnr=knr % divisor;
   }


   void Hushald::Skriv_Hushald()
   {
      short i;
      float prod;
      float kuv, kornv, nmaal;

      if (spage<15 || spage>98) spage=99;
      if (hpage<15 || hpage>98) hpage=99;
      fprintf(fp,"%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d",knr,knr/100,preid,hsex,hmar,hpage,spage,hocc,hfstd,hammel_laslett);
      preid=phyid;
      if (sams[RSPOUSE]>1) sams[RSPOUSE]=1;
      for (i=0;i<=RIND;i++)
         fprintf(fp,"\t%d",sams[i]);
      fprintf(fp,"\t%d\t%d",mnsams[5],kvsams[5]);
      for (i=0;i<5;i++)
         if (i!=3) fprintf(fp,"\t%d",mar[i]);
      fprintf(fp,"\t%d",antgen);
      fprintf(fp,"\t%d",antbarn0_5);
      fprintf(fp,"\t%d",farogmor);
      if (ftaar==1865) {
        if ((matr==false) || (*mtrkl=='\0')) strcpy(mtrkl,"9999");
        if (harjord>-1) {
           kuv=jordbruk.kuverd;
           kornv=jordbruk.kornverd;
           nmaal=jordbruk.getmaal(1);
           if (nmaal<0.01 || nmaal > 9998) nmaal=9999;
           prod=jordbruk.getprod(0);
           if (prod<=0 || prod>9998) prod=9999;
           if (kuv<=0.01 || kuv>998) kuv=999;
           if (kornv<=0.01 || kornv>998) kornv=999;
           fprintf(fp,"\t%d\t%d\t%d",jordbruk.hest,jordbruk.kveg,jordbruk.faar);
           fprintf(fp,"\t%d\t%d\t%d",jordbruk.geiter,jordbruk.svin,jordbruk.reinsdyr);
           fprintf(fp,"\t%4.2f",kuv);
           fprintf(fp,"\t%4.2f\t%4.2f\t%4.2f\t%4.2f",jordbruk.bygg,jordbruk.blandkorn,jordbruk.havre,jordbruk.poteter);
           fprintf(fp,"\t%4.2f",kornv);
           fprintf(fp,"\t%4.2f\t%4.2f\n",prod,nmaal);

//           fprintf(fp,"\t%s\n",mtrkl);
        }
        else {
           fprintf(fp,"\t999\t999\t999\t999\t999\t999\t999\t999\t999\t999\t999\t999\t9999\t9999\n");
//           fprintf(fp,"\t%s\n",mtrkl);
        }
        matr=false;
      }
      else fprintf(fp,"\n");
//      fprintf(fp," %d",(*p1).rel); }
      hushstrl=sams[0];
      jordbruk.init();
      strcpy(mtrkl,"       ");
      *mtrkl='\0';
      harjord=-1;
   }

   void Hushald::InitHushald(bool _matr, char _mtrkl[100])
   {
    matr=_matr;
    if (matr==true)
       strcpy(mtrkl,_mtrkl);
    else
       mtrkl[0]='\0';
    antbarn0_5=0;
    utvald=-1;
   }

   void Hushald::Insert(Person *pers)
   {
      int i;

      if (pers->head==1) {
         spage=99;
         hsex=pers->sex;
         hpage=pers->age;
         hocc=pers->occupation;
         hmar=pers->mar;
         if (pers->fstd<100) hfstd=knr;
         else hfstd=pers->fstd;

         for (i=0;i<=RIND;i++) {
            sams[i]=0;
            kvsams[i]=0;
            mnsams[i]=0;
            if (i<5) mar[i]=0;
         }
         pid=0;
         pers->relgrp=RHP;
         hushstrl=1;
         group.clear();
      }
      else {
         if (pers->rel<20) pers->relgrp=RANDRE;
         else if (pers->rel<30) pers->relgrp=RSPOUSE;
         else if (pers->rel<35) pers->relgrp=RCHLD;
         else if (pers->rel<37) pers->relgrp=RREL;
         else if (pers->rel<40) pers->relgrp=RANDRE;
         else if (pers->rel<200) pers->relgrp=RREL;
         else if (pers->rel<3000) pers->relgrp=RANDRE;
         else if (pers->rel<5000) pers->relgrp=RIND;
         else if (pers->rel<6000) pers->relgrp=RANDRE;
         else if (pers->rel<7000) pers->relgrp=RSERV;
         else pers->relgrp=RANDRE;
         if (pid==1 && pers->relgrp==RSPOUSE)
            spage=pers->age;
         if (pid==1 && group[0].sex != pers->sex &&
            pers->mar==MARRIED &&
            group[0].mar == pers->mar &&
            abs(group[0].age - pers->age) < MAXDIFF) {
// Person 2 blir sett til kone dersom alt dette stemmer
            spage=pers->age;
            pers->relgrp=RSPOUSE;
         }
         hushstrl++;
      }
      group.push_back(*pers);
      sams[0]++;
      sams[pers->relgrp]++;
      if (pers->sex==1)
         mnsams[pers->relgrp]++;
      else if  (pers->sex==2)
         kvsams[pers->relgrp]++;
      if (pers->age<15) pers->mar=1;
      if (pers->mar==1 || pers->mar==MARRIED || pers->mar==4)
         mar[pers->mar]++;
      else
         mar[0]++;
      pid++;
   }

   int Hushald::CountYoung(int ageboarder)
   {
       int pers,i;
       pers=0;
       for (i=0;i<pid;i++)
         if (group[i].age<ageboarder && group[i].bosatt!=BEFMT)
              pers++;
       return pers;
   };

   int Hushald::Ant_Generasjonar()
   {
       int i,j,diff;
       int gene[5];

       antgen=0;
       for (i=0;i<100;i++) aldre[i]=0;
       for (i=0;i<(pid-1);i++)
         for (j=i+1;j<pid;j++) {
           if (group[i].age<99 && group[j].age<99) {
             diff=group[i].age-group[j].age;
             diff=abs(diff);
             if (diff>99) diff=99;
             aldre[diff]++;
           }
         }
       for (i=0;i<5;i++) gene[i]=0;
       for (i=0;i<99;i++)
         if (aldre[i] > 0) {
            if (i<26) gene[1]=1;
            else if (i>=26 && i<52) gene[2]=1;
            else if (i>=52 && i<79) gene[3]=1;
            else if (i>=79) gene[4]=1;
          }
       for (i=1;i<5;i++)
          if (gene[i]==1) antgen++;
       return antgen;
   }




   Hushald::~Hushald()
   {
      group.clear();
      fclose(fp);
   }

   class Komm
   {
   public:
      Komm(char  *_knr);
      int knr;
   private:
   };

   Komm::Komm(char *_knr)
   {
      knr=atoi(_knr);
   }

   class Kommune : Komm, Jord1900
   {
   public:
      Kommune(char  *_knr, int censyear, char _byland);
      ~Kommune();
      void Add_Person(tekTable *ottab);
      void Skriv_Person(int persno);
      void Add_FamStill();
      int  Add_kommkat(char *s);
      void SisteHushald();
      void AddJordbruk(tekTable *intab);
      void AddJord1900(tekTable *intab);
      void Skriv(tTable *ottab);
      void SkrivNSD();
      void PstFleirGen();
      float MHS(int agefrom, int ageto);
      float finnkjprop();
      int mhsagemax;
      float kjhpprop(int kj);
      float heimfodingar();
      long hjemmeh, tilstedev;
      long nper,nhh, nhhel;
      long nfam2, nenpk, nenpm, nenph, nenpm20, nekstrah, neksm, neksk;
      string prestegjeld;
      long nhrecs, nprecs;
      StatObject KommAgg;
      char byland;
      float Y, O, HO, YHO, NO;
/*
    N = nper = number of persons in the popultation
    O = number of old persons in the population
    Y = number of non-old persons in the population
    H = nhh = numbers of households
    HO = numbers of households containing an older person
    YHO = number of younger persons in households containing an older person
    NO = number of persons in household containing an older person

    N = O + Y

    NO = YHO + O
    propold=
    propholdh=
    agglomerative=
    affilative=
    propindoldph=proportion of individuals in old person hhs
*/
      float propold, propoldh, agglomerative, affilative, propindoldph;
      float mhsageg;
      cmat *pch[5];
      bool headmt;
      int headborte;
      char matrikkel[100];
      bool matr;

   private:
      ctmat *smam[3];
      cmat *emhs;
      int  sams[8],mar[5],hhtypes[10],
           ksams[8], msams[8];
      int  kommtyp[10];
      Person pers;
      Hushald *H;
      c_household *HH;
      FILE *ohh, *kodefil;
      int hpage, ftaar;
      int hsz[MAXAGE][2];
      float Emhs,mhs, mhsage[MAXAGE], maxmhs, fammhs;
      long nmenn,nkvinner,heimfod;
      int hpkjprop[3];
      float msmam, ksmam, headmed;
      float heimfodprop, kjprop;

      float mhs30, mhs40,mhs60;
      float headage;
      float hpkvinner;
      char ofname[100];
      tjord jordb;
      int   oldpersoninhousehold;
      int age0;
      int   forste;
      float qmafm[4], qkafm[4], qhead[4], qmalh[4], qkalh[4];
      int hszs[20];
      int nkreat,nkornpt;
      int fleirgen[6];
      float pstfgen[5];
   };

   Kommune::Kommune(char *_knr, int censyear, char _byland):
   Komm(_knr), Jord1900()
   {
      char buffer[10];
      int i,j;
      mhs=-0.1;

      byland=_byland;
      fammhs=-0.1;
      mhsagemax=0;
      maxmhs=0.0;
      nmenn=0;nkvinner=0;
      heimfod=0;
      nper=0;
      nhh=0;
      nhhel=0;
      hjemmeh=0;
      tilstedev=0;
      nprecs=0;
      nhrecs=0;
      headborte=0;
      nfam2=0; nenpk=0; nenpm=0; nekstrah=0; neksm=0; neksk=0;
      nenph=0; nenpm20=0;
      O=0; Y=0; HO=0; YHO=0;
      NO=0;
      oldpersoninhousehold=0;
      forste=0;
      nkreat=0;
      nkornpt=0;
      matr=false;
      for (i=0;i<6;i++) fleirgen[i]=0;
      for (i=0;i<5;i++) pstfgen[i]=0;
      for (i=0;i<20;i++) hszs[i]=0;
      for (i=0;i<MAXAGE;i++) {
         for (j=0;j<2;j++)
            hsz[i][j]=0;
         mhsage[i]=0.0;
      }
      for (i=0;i<=RIND;i++) {
         sams[i]=0;
         ksams[i]=0;
         msams[i]=0;
         if (i<5) mar[i]=0;
      }
      for (i=0;i<3;i++)
         hpkjprop[i]=0;
      for (i=0;i<10;i++) kommtyp[i]=0;
      ftaar=censyear;
      itoa(ftaar,buffer,10);
      if (byland=='F')
         strcpy(ofname,"d:\\data\\kode\\F");
      else
         strcpy(ofname,"d:\\data\\kode\\B");
      strcat(ofname,buffer);
      strcat(ofname,_knr);
      strcat(ofname,".cod");
      kodefil=fopen(ofname,"w");
      strcpy(ofname,"data/hush");
      strcat(ofname,buffer);
      strcat(ofname,EXT);
      H=new Hushald(ofname,_knr,ftaar,byland);
      if (ftaar==1900)
         age0=0;
      else
         age0=1;
      HH=new c_household(age0);
      strcpy(ofname,"data/hh");
      strcat(ofname,buffer);
      strcat(ofname,EXT);
      pch[0] = new cmat(age0);
      pch[1] = new cmat(age0);
      pch[2] = new cmat(age0);
      pch[3] = new cmat(age0);
      pch[4] = new cmat(age0);
      emhs = new cmat(0);
      smam[0] = new ctmat(age0);
      smam[1] = new ctmat(age0);
      smam[2] = new ctmat(age0);
      jordb.addfoll(0,7.8,9.9,7.0,5.8,6.9,5.4,7.0);
      jordb.setprmaal(atoi(_knr)/100,prmaal);

   }

   void  Kommune::Add_FamStill()
   {
     if (pers.relgrp>0 && pers.relgrp <=RIND) {
         sams[pers.relgrp]++;
         sams[0]++;
         if (pers.sex==2) {
           ksams[0]++;
           ksams[pers.relgrp]++;
         }
         else {
           msams[pers.relgrp]++;
           msams[0]++;
         }
     };
     if (pers.mar==1 || pers.mar==MARRIED || pers.mar==4)
         mar[pers.mar]++;
     else
         mar[0]++;
   }


   int Kommune::Add_kommkat(char *s)
   {
    char *p;
    p=strupr(s);
    while (*s!=NULL) {
       if ((int) *s == -101) *s='O';
       s++;
    }
    if (strstr(p,"SKOG")) return 3;
    else if (strstr(p,"SAG")) return 3;
    else if (strstr(p,"FLOTER")) return 3;
    else if (strstr(p,"FISK")) return 6;
    else if (strstr(p,"MATR")) return 5;
    else if (strstr(p,"MMERH")) return 3;
    else if (strstr(p,"SKIB")) return 5;
    else if (strstr(p,"ARB")) return 4;
    else if (strstr(p,"SOMAND")) return 5;
    else if (strstr(p,"BSTOM")) return 5;
    else if (strstr(p,"MMERM")) return 3;
    else if (strstr(p,"AARD")) return 2;
    else if (strstr(p,"M J")) return 2;
    else {
       arfn["K\t"+string(p)]++;
       return 9;
    }
   }

   void Kommune::PstFleirGen()
   {
    int i;
    fleirgen[5]=fleirgen[0];
    for (i=1;i<5;i++)
       fleirgen[5]=fleirgen[5]+fleirgen[i];
    for (i=0;i<5;i++)
       pstfgen[i]=(float) fleirgen[i]/fleirgen[5]*100;
   }

   void   Kommune::Add_Person(tekTable *tab)
   {
      int prepersage;

      if (ftaar==1900) pers.bosatt=Cmt(tab->fields[OBOSATT]);
      else pers.bosatt=BEFB;

      nper++;
      if (pers.bosatt==BEFB || pers.bosatt==BEFRAR) {
         hjemmeh++;
         tilstedev++;
      }
      if (pers.bosatt==BEFF)
         hjemmeh++;

      pers.head=(int) tab->fields[OHEAD][0] - 48;
      pers.sex=Csex(tab->fields[OSEX]);
      pers.age=Cage(tab->fields[OAGE],ftaar);
      if (*tab->fields[OREL]!='\0') {
         pers.rel=RelCode->Crel(tab->fields[OREL]);
//         s= tab->fields[OREL];
      }
      else if (pers.head==2) {
         pers.rel=RelCode->Crel(tab->fields[OOCC]);
//         s= tab->fields[OOCC];
      }
      pers.mar=Cmar(tab->fields[OMAG]);
      pers.fstd=FstdCode->Cfstd(tab->fields[OFSTD]);
      if (pers.fstd==1) pers.fstd=knr;
      pers.occupation=OccCode->Cocc(tab->fields[OOCC], pers.head);
      if (pers.bosatt==BEFMT) {
         tilstedev++;
         Skriv_Person(0);
         if (pers.head==1)
            headmt=true;
         return;
      }

      if (pers.head==1) {
         kommtyp[Add_kommkat(tab->fields[OOCC])]++;
         kommtyp[0]++;
      };
      if (ftaar==1900 && pers.head!=1 && pers.rel==EL && pers.age>15 && pers.age<99) {
/*
         Enslig losjerande blir sett til hushaldsoverhovud
         if (pers.sex==2) pers.rel=12;
         else pers.rel=11;
         pers.head=1;   */
         nhhel++;
      }
      H->phyid=nprecs;
      if (pers.head==1) {
         if (nhh>0) {
           if (H->hushstrl>0) {
             prepersage=HH->parentspresent(11);
             if (prepersage>15)
               if (HH->pperson[0].sexcode==1) {
                 pch[3]->AddParentsHome(prepersage);
/*                 KommAgg.AddExtraChild(prepersage,1); */
               }
               else {
                 pch[4]->AddParentsHome(prepersage);
/*                KommAgg.AddExtraChild(prepersage,2); */
               }
             prepersage=HH->wifepresent();
             if (prepersage>15 && HH->parentspresent(22)>15) {
               pch[4]->AddParentsHome(prepersage);
/*              KommAgg.AddExtraChild(prepersage,2); */
             }
//         HH->correcthh();
//        HH->modrelcode();

             H->hammel_laslett=HH->codecfu();
             emhs->AddHouseholdSize(H->hushstrl);
             if (H->hushstrl==1) {
                nenph++;
                if (H->hsex=1) {
                   nenpm++;
                   if (H->hpage>=20 && H->hpage<30) nenpm20++;
                }
                else nenph++;
             }
             else if (H->hushstrl>1) nfam2++;
             if (H->hushstrl>12) hszs[13]++;
             else hszs[H->hushstrl]++;
             HH->IPUMScode();
             if (oldpersoninhousehold==1) {
                HO++;
                NO=NO+H->pid;
                YHO=YHO+H->CountYoung(OLDAGE+age0);
//             printf("\n%d %d %d %d\n",(int) O, (int) YHO, (int) NO, (int) (O+YHO));
             }
             fleirgen[H->Ant_Generasjonar()]++;
             H->antbarn0_5=HH->numch0_5();
             H->farogmor=HH->getfarogmor();
             if (H->utvald>-1) H->Skriv_Hushald();
             else H->preid=H->phyid;
           }
           else {
              headborte++;
           }
           HH->inithousehold();
           HH->pperson.clear();
           HH->personid=0;
           oldpersoninhousehold=0;
           H->InitHushald(matr,matrikkel);
         };
         nhh++;
         if (nhh % H->divisor == H->utvalsnr) {
           H->utvald=H->utvalsnr;
           pers.occupation=hputval->Cyrke(tab->fields[OOCC], pers.head);
         }
         else H->utvald=-1;
         hpage=pers.age;
         hsz[hpage][0]++;
         if (pers.sex==1 || pers.sex==2)  {
            hpkjprop[pers.sex]++;
            hpkjprop[0]++;
         }
         if (pers.sex==2) pers.rel=12;
         else pers.rel=11;

      };

      HH->Add_Person(tab->fields[9],
                     pers.sex,pers.mar,pers.age,pers.rel);
      hsz[hpage][1]++;
      if (pers.sex==1) {
         smam[0]->Add_Person(pers.mar,pers.age);
         smam[2]->Add_Head(pers.head,pers.age);
      }
      else
         smam[1]->Add_Person(pers.mar,pers.age);
      if (pers.sex==1) {
         pch[0]->AddMar(pers.age,pers.mar);
         nmenn++;
         pch[2]->AddHead(pers.age,pers.head);
         pch[3]->AddLeavingHome(pers.age,pers.rel);
      }
      else if (pers.sex==2) {
         pch[1]->AddMar(pers.age,pers.mar);
         nkvinner++;
         pch[4]->AddLeavingHome(pers.age,pers.rel);
      }
      if ((pers.bosatt==BEFB || pers.bosatt==BEFRAR)  && (pers.fstd==knr || pers.fstd==1))
         heimfod++;
      H->Insert(&pers);
      Add_FamStill();
      KommAgg.AddPerson(&pers);
      KommAgg.AddAlder(hpage,0);
      Skriv_Person(H->pid);
      if (pers.age>=(OLDAGE+age0)) {
         O++;
         oldpersoninhousehold=1;
      }
      else Y++;
   }

   void Kommune::Skriv_Person(int persno)
   {
        fprintf(kodefil,
        "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
         knr,nper,nhh,persno,pers.head,pers.sex,pers.mar,pers.age,
         pers.relgrp,pers.rel,pers.bosatt,pers.fstd,
         pers.occupation);
   };

   void Kommune::AddJordbruk(tekTable *intab)
   {
    if (H->AddJordbruk(intab)>-1) {
       jordb.hest+=H->jordbruk.hest;
       jordb.kveg+=H->jordbruk.kveg;
       jordb.reinsdyr+=H->jordbruk.reinsdyr;
       jordb.svin+=H->jordbruk.svin;
       jordb.faar+=H->jordbruk.faar;
       jordb.geiter+=H->jordbruk.geiter;
       jordb.hvete+=H->jordbruk.hvete;
       jordb.bygg+=H->jordbruk.bygg;
       jordb.blandkorn+=H->jordbruk.blandkorn;
       jordb.havre+=H->jordbruk.havre;
       jordb.erter+=H->jordbruk.erter;
       jordb.poteter+=H->jordbruk.poteter;
       jordb.kuverd+=H->jordbruk.kuverd;
       jordb.kornverd+=H->jordbruk.kornverd;
       jordb.husdyrhald+=H->jordbruk.husdyrhald;
       jordb.dyrkar+=H->jordbruk.dyrkar;
       jordb.anthush++;
     }
   }

   void Kommune::AddJord1900(tekTable *intab)
   {
    Add_Jordbruk1900(intab);
    nkreat+=Jord1900::nkreatur;
    nkornpt+=Jord1900::nkornpotet;
   }

   void Kommune::SisteHushald()
   {
      int i;
      float medmar, medhead;

      H->hammel_laslett=HH->codecfu();
      if (H->hushstrl==1) {
         nenph++;
         if (H->hsex=1) {
            nenpm++;
            if (H->hpage>=20 && H->hpage<30) nenpm20++;
         }
         else nenph++;
      }
      else if (H->hushstrl>1) nfam2++;
      if (H->hushstrl>12) hszs[13]++;
      else hszs[H->hushstrl]++;
      HH->IPUMScode();
      emhs->AddHouseholdSize(H->hushstrl);
      Emhs=emhs->ComputeEMHS(40);
      if (oldpersoninhousehold==1) {
          HO++;
          NO=NO+H->pid;
          YHO=YHO+H->CountYoung(OLDAGE+age0);
      }
      fleirgen[H->Ant_Generasjonar()]++;
      if (H->utvald>-1) H->Skriv_Hushald();
      for (i=0;i<13;i++)
        if (hszs[i]>hszs[14]) {
           hszs[14]=hszs[i];
           hszs[0]=i;
        }
      HH->~c_household();
      printf ("End read\t");
      msmam=smam[0]->SMAM();
      ksmam=smam[1]->SMAM();
       headage=smam[2]->SMAM();
      mhs=MHS(0,100);
      mhs30=MHS(28,33);
      mhs40=MHS(42,47);
      mhs60=MHS(58,63);
      if (nfam2>0) fammhs=(float) (nper-nenph)/nfam2;
      if (fammhs<2.0) fammhs=99;
      hpkvinner=kjhpprop(2);
//    age first marriage male
      qmafm[0]=pch[0]->indirect();
      qmafm[1]=pch[0]->getage(1,40);
      tekfil->prevsum[0]+=pch[0]->prevl;
      qmafm[2]=pch[0]->getage(2,45);
      qmafm[3]=pch[0]->getage(3,50);
//    age first marriage female
      qkafm[0]=pch[1]->indirect();
      qkafm[1]=pch[1]->getage(1,40);
      tekfil->prevsum[1]+=pch[1]->prevl;
      qkafm[2]=pch[1]->getage(2,45);
      qkafm[3]=pch[1]->getage(3,50);
//    headship
      qhead[0]=pch[2]->indirect();
      qhead[1]=pch[2]->getage(1,40);
      tekfil->prevsum[2]+=pch[2]->prevl;
      qhead[2]=pch[2]->getage(2,45);
      qhead[3]=pch[2]->getage(3,50);

      tekfil->prevcount++;
//    male leaving home
      qmalh[1]=pch[3]->getage2(1,40);
      tekfil->prevsum[3]+=pch[3]->prevl2;
      qmalh[2]=pch[3]->getage2(2,45);
      qmalh[3]=pch[3]->getage2(3,50);
//    female leaving home
      qkalh[1]=pch[4]->getage2(1,40);
      tekfil->prevsum[4]+=pch[4]->prevl2;
      qkalh[2]=pch[4]->getage2(2,45);
      qkalh[3]=pch[4]->getage2(3,50);
/*      medmar=pch[0]->Median(2,40,45,54);
      medhead=pch[2]->Median(2,40,45,54);

      printf("\nMed mar %4.1f qmafm[0] %4.1f qmafm[2] %4.1f\n",medmar,qmafm[0],qmafm[2]);
      printf("med head %4.1f qhead0 %4.1f Qhead2 %4.1f headage %4.1f\n",medhead,qhead[0],qhead[2],headage);
      printf ("SMAM %4.1f\t",msmam);
      medmar=pch[0]->ComputeQ(0,2,2);
      medhead=pch[2]->ComputeQ(0,2,2);
      printf("\nComputeQ mar %4.1f\n",medmar);
      printf("ComputeQ head %4.1f\n",medhead);

      printf ("End compute\t");
*/
   }

   void Kommune::Skriv(tTable *ottab)
   {
   int i;
   float f2, f3, f4;
   float N, prod, snmaal;
   float pstenph,pstenphm20, pstmannten;
   float pst_husdyr,pst_dyrkar;
   float snkornv, snkuv;
   int amt;

   char s[100];
      ohh=fopen(ofname,"a");

      amt = atoi(ottab->fields[0])/100;
      fprintf(ohh,"%s\t%d\t%d\t%4d\t%4d\t%4d\t%4d\t",ottab->fields[0],amt,(int) byland,nper,tilstedev,hjemmeh,nhh);
      fprintf(ohh,"%4d\t%4d\t%4d\t",nfam2,nenph,nhhel);
      fprintf(ohh,"%4d\t%4d\t%4d\t",nenpm,nenpk,nenpm20);
      pstenph=(float) nenph/ (float) nhh * 100.0;
      pstenphm20=(float) nenpm20/ (float) nenpm * 100.0;
      fprintf(ohh,"%4.2f\t%4.2f\t",pstenph,pstenphm20);
      fprintf(ohh,"%03.1f\t%03.1f\t%03.1f\t%d",ksmam,msmam,headage,mhsagemax);

      heimfodprop=heimfodingar();
      if (heimfodprop<20.0 || heimfodprop>100.0) heimfodprop=0.0;

      kjprop=finnkjprop();
      if (kjprop<50.0 || kjprop>200.0) kjprop=100.0;

      fprintf(ohh,"\t%03.2f\t%03.2f",heimfodprop,kjprop);

      if (mhs30<1.0 || mhs30>12.0)  mhs30=0.0;
      if (mhs60<1.0 || mhs60>12.0)  mhs60=0.0;
      if (mhs40<1.0 || mhs40>12.0)  mhs40=0.0;

      fprintf(ohh,"\t%4.2f\t%4.2f\t%4.2f\t%4.2f\t%4.2f\t%4.2f\t%5.2f",
                     mhs30,mhs40,mhs60,mhs,fammhs,Emhs,hpkvinner);
      fprintf(ohh,"\t%d",hszs[0]);
      for (i=0;i<=RIND;i++)
        fprintf(ohh,"\t%d",sams[i]);
      fprintf(ohh,"\t%d",ksams[0]);
      fprintf(ohh,"\t%d",msams[0]);
      fprintf(ohh,"\t%d",ksams[RSERV]);
      pstmannten=(float) msams[RSERV]/msams[0] * 100.0;
      fprintf(ohh,"\t%d\t%4.2f",msams[RSERV],pstmannten);
      fprintf(ohh,"\t%d",msams[RIND]);
      for (i=0;i<5;i++)
        if (i!=3) fprintf(ohh,"\t%d",mar[i]);
      for (i=0;i<4;i++)
          fprintf(ohh,"\t%4.1f",qmafm[i]);
      for (i=0;i<4;i++)
          fprintf(ohh,"\t%4.1f",qkafm[i]);
      for (i=0;i<4;i++)
          fprintf(ohh,"\t%4.1f",qhead[i]);
      N = (float) nmenn+nkvinner;
      propold=(float) O / (float) N;
      propoldh=(float) HO / (float) nhh;
      agglomerative= (float) O / (float) HO;
      affilative=  (float) YHO/ (float) HO;
      fprintf(ohh,"\t%5.3f\t%5.3f",propold,propoldh);
      f2 = propold * mhs * (1/agglomerative);
      fprintf(ohh,"\t%4.2f",agglomerative);
      propindoldph = (float) NO / N;
      f3 = propold * ((float)1+affilative/agglomerative);
      mhsageg=NO/HO;
      fprintf(ohh,"\t%5.3f",propindoldph);
      fprintf(ohh,"\t%4.2f",affilative);
      f4=(float)((float)HO/(float)nhh)*(((float)NO/(float)HO)/((N)/(float)nhh));
      fprintf(ohh,"\t%4.2f",mhsageg);
//      Age leaving home - m=menn, k=kvinner
     for (i=1;i<4;i++)
         fprintf(ohh,"\t%4.1f",qmalh[i]);
      for (i=1;i<4;i++)
         fprintf(ohh,"\t%4.1f",qkalh[i]);
      PstFleirGen();
      for (i=0;i<5;i++)
         fprintf(ohh,"\t%4.1f",pstfgen[i]);
      fprintf(ohh,"\t%d",jordb.anthush);
      if (ftaar==1865) {
         prod=jordb.getprod(0);
         snmaal=jordb.getmaal(jordb.dyrkar);
         pst_dyrkar=(float) jordb.dyrkar/nhh*100;
         pst_husdyr=(float) jordb.husdyrhald/nhh*100;
         if (jordb.husdyrhald>0)
            snkuv=(float)jordb.kuverd/jordb.husdyrhald;
         else
            snkuv=999;
         if (jordb.dyrkar>0)
            snkornv=(float)jordb.kornverd/jordb.dyrkar;
         else
            snkornv=999;
         if (snmaal<0.01 || snmaal>998) snmaal=999;
         fprintf(ohh,"\t%d\t%d\t%d",jordb.hest,jordb.kveg,jordb.faar);
         fprintf(ohh,"\t%d\t%d\t%d",jordb.geiter,jordb.svin,jordb.reinsdyr);
         fprintf(ohh,"\t%4.2f\t%d\t%4.2f",jordb.kuverd,jordb.husdyrhald,snkuv);
         fprintf(ohh,"\t%4.2f\t%4.2f\t%4.2f\t%4.2f",jordb.bygg,jordb.blandkorn,jordb.havre,jordb.poteter);
         fprintf(ohh,"\t%4.2f\t%d\t%4.2f",jordb.kornverd,jordb.dyrkar,snkornv);
         fprintf(ohh,"\t%4.2f\t%4.2f",prod,snmaal);
         fprintf(ohh,"\t%3.1f\t%3.1f",pst_husdyr,pst_dyrkar);
      } else {
         fprintf(ohh,"\t%d\t%d",nkreat,nkornpt);
         pst_husdyr=(float) nkreat/nhh*100;
         pst_dyrkar=(float) nkornpt/nhh*100;
         fprintf(ohh,"\t%3.1f\t%3.1f",pst_husdyr,pst_dyrkar);
      }
      fprintf(ohh,"\n");
      fclose(ohh);

      strcpy(s,ofname);
      strcat(s,".2");
      ohh=fopen(s,"a");
/*      if (forste==0) {
         fprintf(ohh,"knr\tbyland\tnhh");
         for (i=2;i<10;i++) fprintf(ohh,"\tKommtyp%d",i);
         fprintf(ohh,"\tKommtyp0\tpropold\tpropoldh\t");
         fprintf(ohh,"EQ2\tagglomerative\tNO/N\tEQ3\taffilative\tmhs\t");
         fprintf(ohh,"EQ4\tmhsageg\n");
         forste=1;
      }*/
      fprintf(ohh,"%s\t%d\t%d\t%4d",ottab->fields[0],amt,(int) byland,nhh);
      for (i=2;i<10;i++)
        fprintf(ohh,"\t%d",kommtyp[i]);
      fprintf(ohh,"\t%d",kommtyp[0]);
      fprintf(ohh,"\t%4.2f\t%4.2f",f2,agglomerative);
      fprintf(ohh,"\t%5.3f\t%5.3f",propindoldph,f3);
      fprintf(ohh,"\t%4.2f\t%4.2f",affilative,mhs);
      fprintf(ohh,"\t%4.2f\t%4.2f",f4,mhsageg);
      fprintf(ohh,"\t%4.3f\t%4.3f",Emhs,mhs);
      fprintf(ohh,"\n");
//      N = (float) nper;
      fclose(ohh);
   };

Kommune::~Kommune()
{
  delete H;
  delete pch[0],pch[1],pch[2], pch[3], pch[4];
  delete emhs;
  fclose(kodefil);
}

class Leilighet  {
// 1900 by
public:
    int tilstdv,hjemmeh;
    virtual void Add_Leilighet(tTable *table);
};

void Leilighet::Add_Leilighet(tTable *table){
    if (table->count>13) {
         tilstdv=atoi(table->fields[13]);
         hjemmeh=atoi(table->fields[14]);
    }  else {
         tilstdv=0; hjemmeh=0;
    }

}


class Bosted {
// '2' 1865 by og land
// 2 1900 by og land
public:
   int hjemmeh,tilstdv;
   int beboddehus, husholdninger;
   int hustyper[10];
   int tbosted;
   virtual void Add_Bosted(tTable *table);
   virtual void Add_hus(tTable *table);
   void Settype(char byland, int knr);
   char byland;
private:
   int ix;
};

void Bosted::Settype(char _byland, int knr)
{
    byland=_byland;
    if (knr==1301 || knr==1107)
       ix=8;
    else
       ix=9;

};

void Bosted::Add_Bosted(tTable *table)
{
int i;
    for (i=0;i<10;i++) hustyper[i]=0;
    if (table->count>11) {
        if (*table->fields[10]!='\0') {
           i=huskode->KodeOrd(table->fields[10]);
           while (i>0) {
              if( i<10) hustyper[i]++;
              else
                 huskode->InsertUkoda(table->fields[10]);
              i=huskode->KodeOrd(table->fields[10]);
           }
        }
        tilstdv=atoi(table->fields[11]);
        if (table->count>12)
          hjemmeh=atoi(table->fields[12]);
        else
          hjemmeh=0;
    } else {
      tilstdv=0;
      hjemmeh=0;
    }
    tbosted=1;
};

void Bosted::Add_hus(tTable *table)
{
    if (table->count>ix) {
       beboddehus=atoi(table->fields[ix]);
       husholdninger=atoi(table->fields[ix+1]);
       if (table->count>17) {
          tilstdv=atoi(table->fields[17]);
          if (table->count>18)
            hjemmeh=atoi(table->fields[18]);
          else
            hjemmeh=0;
       }
       else
          tilstdv=0;

    } else {
         beboddehus=0;
         husholdninger=0;
    }
}

   class Kommgard : Komm , Bosted, Leilighet, Jord1900
   {
   public:
      Kommgard(char  *_knr, int ftaar, char byland);
      ~Kommgard();
      void Add_Leilighet(tTable *table);
      void Add_hus(tTable *table);
      void Add_Bosted(tTable *table);
      void Add_Jordbruk1900(tTable *table);
      void Skriv();
   private:
      FILE *fp;
      long hjemmeh2,tilstdv1,tilstdv2,hjemmeh1,tilstdv3,hjemmeh3, vaaningshus;
      int anthush, anthus, njordbr;
      int nkreat,nkornpt;
      int sidebygn[10];
   };

   Kommgard::Kommgard(char *_knr, int ftyear, char byland):
   Komm(_knr)
   {
      char s[20];
      int i;

      sprintf(s,"data/kg%d.txt",ftyear);
      fp=fopen(s,"a");
      tilstdv1=0;
      tilstdv2=0;
      tilstdv3=0;
      hjemmeh1=0; hjemmeh2=0; hjemmeh3=0;
      anthus=0;
      anthush=0;
      nkornpt=0;
      nkreat=0;
      vaaningshus=0;
      tbosted=0;
      for (i=0;i<10;i++) {
         hustyper[i]=0;
         sidebygn[i]=0;
      }
      Settype(byland, knr);
   }

   Kommgard::~Kommgard()
   {
      fclose(fp);
   }

   void Kommgard::Add_Leilighet(tTable *table)
   {
    Leilighet::Add_Leilighet(table);
    tilstdv2+=Leilighet::tilstdv;
    hjemmeh2+=Leilighet::hjemmeh;
   }

   void Kommgard::Add_Bosted(tTable *table)
   {
    int i;
    if (byland=='F') {
      Bosted::Add_Bosted(table);
      tilstdv1+=Bosted::tilstdv;
      hjemmeh1+=Bosted::hjemmeh;
      for (i=1;i<10;i++) sidebygn[i]+=Bosted::hustyper[i];
      vaaningshus+=Bosted::tbosted;
    }
   }

   void Kommgard::Add_hus(tTable *table)
   {
    Bosted::Add_hus(table);
    anthus+=Bosted::beboddehus;
    anthush+=Bosted::husholdninger;
    tilstdv1+=Bosted::tilstdv;
    hjemmeh1+=Bosted::hjemmeh;
   }

   void Kommgard::Add_Jordbruk1900(tTable *table)
   {
    Jord1900::Add_Jordbruk1900(table);
    nkornpt+=Jord1900::nkornpotet;
    nkreat+=Jord1900::nkreatur;
    njordbr+=Jord1900::njord;
    tilstdv3+=Jord1900::tilstdv;
    hjemmeh3+=Jord1900::hjemmeh;
   }

   void Kommgard::Skriv()
   {
      int i;
      float pstkaarh;
      fprintf(fp,"%04d\t%4d\t%4d\t%4d\t%4d\t%4d\t%4d\t%4d\t%4d",
      knr,tilstdv1,tilstdv2,tilstdv3,hjemmeh1,hjemmeh2,hjemmeh3,anthush,anthus);
      fprintf(fp,"\t%4d",vaaningshus);
      for (i=1;i<7;i++)
        fprintf(fp,"\t%4d",sidebygn[i]);
      if (vaaningshus>0) pstkaarh=(float) sidebygn[1]/(float) vaaningshus*100.0;
      else pstkaarh=0.0;
      fprintf(fp,"\t%3.2f\n",pstkaarh);
   };


   float Kommune::finnkjprop()
   {
      if (nmenn>0)
         return (float) nkvinner / (float) nmenn * 100.0;
      else
         return 0.0;
   }


   float Kommune::kjhpprop(int kj)

   {
      if (hpkjprop[0]>0 && (kj==1 || kj==2))
         return (float) hpkjprop[kj] / (float) hpkjprop[0] * 100.0;
      else
         return 0.0;
   }

   float Kommune::heimfodingar()
   {
      if ((nkvinner+nmenn)>0)
         return (float) heimfod
            /(float) (nkvinner+nmenn) * 100.0;
      else
         return 0.0;
   }

   float ctmat::SMAM()
   {
      float prop45,single45,single;
      int i, pop, ugifte;
      float MA;

      single45=0.0;
      prop45=0.0;
      single=0.0;
      for (i=45;i<50;i++) {
         single45=single45+mat[1][i];
         prop45=prop45+mat[0][i]+mat[1][i];
      }
      if (prop45!=0.0)
         single45=(float) single45 / (float) prop45;
      else
         single45=0.0;
      MA=0.0;
      single=0.0;
      pop=0;
      for (i=0;i<45;i+=5) {
         mat[2][i]=mat[1][i]+mat[0][i]
                  +mat[1][i+1]+mat[0][i+1]
                  +mat[1][i+2]+mat[0][i+2]
                  +mat[1][i+3]+mat[0][i+3]
                  +mat[1][i+4]+mat[0][i+4] ;
         ugifte = mat[1][i]+mat[1][i+1]+mat[1][i+2]+mat[1][i+3]+mat[1][i+4];
         if (i<15) single=1.0;
         else {
           pop+=mat[2][i];
           if (mat[2][i]==0) {
             if (i<20) single=1.0;
             else if(i<30) single=0.45;
             else single=0.1;
           }
           else single=(float) ugifte/ (float) mat[2][i];
         }
         if (single - single45 > 0) single=single-single45;
         else single=0.0;
         MA=MA+(single*5);
      }
      if (single45!=1.0)
         MA=MA/(1.0-single45);
      if (MA<20.0 || MA>40.0) MA=0.0;
      return MA;
   }

  void varpr(FILE *fp,char *s, char *s2, int i1, int i2, int i3, int i4,int yr)
  {
  fprintf(fp,"+\nK%s:%s (%d)\n%d\n%d\n%d\n%d #\n",s,s2,yr,i1,i2,i3,i4);
  }

void   Kommune::SkrivNSD()
{
  NSDvardok *NSD;

  NSD = new NSDvardok("hh",ftaar);

  NSD->AddVar("Kommnr","Kommunenr",100,9998,0);
  NSD->AddVar("Amt","Amtnr",0,30,0);
  NSD->AddKodaVar("Byland","By Land","\n66 By\n70 Land\n99 # Mangler data\n");
  NSD->AddVar("Npers","Person records",0,999998,0);
  NSD->AddVar("NTilstede","Tilstedeverende befolkning",0,999998,0);
  NSD->AddVar("Nhjemmeh","Hjemmehorende befolkning",0,999998,0);
  NSD->AddVar("NHushald","Tal hushald",0,99998,0);
  NSD->AddVar("NfamHush","Tal familiehushald",0,99998,0);
  NSD->AddVar("NenpHush","Tal enpersonsshushald",0,99998,0);
  NSD->AddVar("NELHush","Tal Enslig losjerande (ikkje HP)",0,99998,0);
  NSD->AddVar("NenpmHush","Tal enpersonshushald menn",0,99998,0);
  NSD->AddVar("NenpkHush","Tal enpersonshushald kvinner",0,99998,0);
  NSD->AddVar("Nenpm20Hush","Tal enpersonshushald menn 20-29",0,99998,0);
  NSD->AddVar("Pstenphush","Prosent enperson hushald av alle hushald",0,98,2);
  NSD->AddVar("Pstenpm20Hush","Prosent enpersonhushald menn 20-29 av alle menn enpersonshushald",0,98,2);
  NSD->AddVar("KvSMAM","SMAM kvinner 1",20,40,1);
  NSD->AddVar("MSMAM","SMAM menn 1",20,40,1);
  NSD->AddVar("HeadSMAM","Headship median (SMAM-metoden)",20,40,1);
  NSD->AddVar("HszAgeMx","Hsz age max",16,90,0);
  NSD->AddVar("Heimfod","Heimfoding %",0,100,2);
  NSD->AddVar("Kjprop","Kjonnsprop. %",0,200,2);
  NSD->AddVar("MHS30","MHS 28-32",0,12,2);
  NSD->AddVar("MHS45","MHS 42-46",0,15,2);
  NSD->AddVar("MHS60","MHS 58-62",0,12,2);
  NSD->AddVar("MHS","MHS",1,12,2);
  NSD->AddVar("FAMMHS","FAMMHS",1,15,2);
  NSD->AddVar("MEHS","Opplevd MHS",1,17,2);
  NSD->AddVar("HKjprop","HP kjonnsprop",0,100,2);
  NSD->AddVar("MedianHS","Median Hushaldsstorleik",1,14,0);
     NSD->AddVar("AntHPers","Antall Hushaldspersonar",0,99998,0);
     NSD->AddVar("HP","Hovudpersonar",0,99998,0);
     NSD->AddVar("Make","makar",0,99998,0);
     NSD->AddVar("Barn","Barn",0,99998,0);
     NSD->AddVar("Slekt","Slekt",0,99998,0);
     NSD->AddVar("Teneste","tenestefolk",0,99998,0);
     NSD->AddVar("Andre","Andre",0,99998,0);
     NSD->AddVar("Losj","Losjerande/innerstar",0,99998,0);
     NSD->AddVar("AntKPers","Antall kvinner Hushaldspersonar",0,99998,0);
     NSD->AddVar("AntMPers","Antall menn Hushaldspersonar",0,99998,0);
     NSD->AddVar("KTeneste","Tenestejenter",0,99998,0);
     NSD->AddVar("MTeneste","Tenestegutar",0,99998,0);
     NSD->AddVar("Mdeltenar","Prosent tenestegutar av alle menn",0,98,2);
     NSD->AddVar("MInderst","Losjerande/innerstar menn",0,99998,0);
     NSD->AddVar("Andre","Ukjent sivstatus",0,99998,0);
     NSD->AddVar("Ugift","Ugift",0,150000,0);
     NSD->AddVar("Gift","Gift",0,99998,0);
     NSD->AddVar("Enkje","Enkjemann/Enkje",0,99998,0);
  NSD->AddVar("MSMAM2","SMAM menn m2",20,40,1);
  NSD->AddVar("Mq1","Menn: Age first marriage q1",15,40,1);
  NSD->AddVar("Mq2","Menn: Age first marriage q2",20,45,1);
  NSD->AddVar("Mq3","Menn: Age first marriage q3",25,50,1);
  NSD->AddVar("KSMAM2","SMAM kvinner m2",20,40,1);
  NSD->AddVar("Kq1","Kvinner: Age first marriage q1",15,40,1);
  NSD->AddVar("Kq2","Kvinner: Age first marriage q2",20,45,1);
  NSD->AddVar("Kq3","Kvinner: Age first marriage q3",20,50,1);
  NSD->AddVar("HeadIndirect3","Headship (indirect) m3",20,40,1);
  NSD->AddVar("HMeadianq1","Headship q1",20,40,1);
  NSD->AddVar("HMeadianq2","Headship q2 (median)",20,45,1);
  NSD->AddVar("HMeadianq3","Headship q3",20,50,1);
  NSD->AddVar("Propold","Proportion of older",0,1,3);
  NSD->AddVar("Propoldh","Proportion of households with older",0,1,3);
  NSD->AddVar("agglomerative","Agglomerative tendency of old",0,8,2);
  NSD->AddVar("propinoldph","Proportion of individuals in old person hhs",0,8,3);
  NSD->AddVar("affilative","Affilative tendency of old",0,8,2);
  NSD->AddVar("mhsageg","Mhs of hhs containg an older person",1,8,2);
  NSD->AddVar("malh1","Menn: Age leaving home q1",1,40,1);
  NSD->AddVar("malh2","Menn: Age leaving home q2",5,45,1);
  NSD->AddVar("malh3","Menn: Age leaving home q3",5,50,1);
  NSD->AddVar("kalh1","Kvinner: Age leaving home q1",1,40,1);
  NSD->AddVar("kalh2","Kvinner: Age leaving home q2",5,45,1);
  NSD->AddVar("kalh3","Kvinner: Age leaving home q3",5,50,1);
  NSD->AddVar("Pst0gen","Prosent 0-generasjonshushald",0,100,1);
  NSD->AddVar("Pst1gen","Prosent 1-generasjonshushald",0,100,1);
  NSD->AddVar("Pst2gen","Prosent 2-generasjonshushald",0,100,1);
  NSD->AddVar("Pst3gen","Prosent 3-generasjonshushald",0,100,1);
  NSD->AddVar("Pst4gen","Prosent 4-generasjonshushald",0,100,1);
  NSD->AddVar("Njordbr","Antall hushald med jordbruksproduksjon",0,99998,0);
  if (ftaar==1865) {
    NSD->AddVar("Nhest","Tal hestar",0,99998,0);
    NSD->AddVar("Nkveg","Tal stort kveg",0,99998,0);
    NSD->AddVar("Nfaar","Tal faar",0,99998,0);
    NSD->AddVar("Ngeiter","Tal geiter",0,99998,0);
    NSD->AddVar("Nsvin","Tal svin",0,99998,0);
    NSD->AddVar("NRein","Tal reinsdyr",0,99998,0);
    NSD->AddVar("SumKuverdi","Sum Kuverdi",0,99998,2);
    NSD->AddVar("NHusdyrhald","Einingar med husdyrhald",0,99998,0);
    NSD->AddVar("SnHusdyr","Snitt husdyr pr. hushald",0,998,0);
    NSD->AddVar("Nbygg","Tal bygg",0,99998,2);
    NSD->AddVar("Nblandkorn","Tal blandkorn",0,99998,2);
    NSD->AddVar("Nhavre","Tal havre",0,99998,2);
    NSD->AddVar("Npoteter","Tal poteter",0,99998,2);
    NSD->AddVar("Byggverdi","Sum byggverdi",0,99998,2);
    NSD->AddVar("NDyrkar","Einingar som dyrkar",0,99998,0);
    NSD->AddVar("SnDyrkar","Snitt utsaad pr. hushald",0,998,0);
    NSD->AddVar("Sumkornprod","Sum kornproduksjon",0,99998,0);
    NSD->AddVar("SnMaal","Sn bruksstorleik i maal",0,998,0);
  }
  else {
    NSD->AddVar("Nkornpotet","Tal kornpotet hushald ",0,99998,0);
    NSD->AddVar("Nkreatur","Tal kreatur hushald",0,99998,0);
  }
  NSD->AddVar("Psthusdyr","Prosent hushald med husdyrhald",0,998,2);
  NSD->AddVar("Pstdyrkar","Prosent hushald som dyrkar jord",0,998,2);
  NSD->SkrivVar();
  NSD->SkrivDok();
  delete NSD;

  NSD = new NSDvardok("hush", ftaar);
  NSD->AddVar("Kommnr","Kommunenr ",100,9998,0);
  NSD->AddVar("Amt","Amtsnr",0,30,0);
  NSD->AddVar("persid","Personid",0,99998,0);
  NSD->AddKodaVar("HeadSex","Kjønn","1 Mann \n2 Kvinne\n9 # Manglar\n");
  NSD->AddKodaVar("HeadMar","Sivstat","1 Ugift\n2 Gift\n3 einsleg gift\n4 Enkjefolk\n5 Separert\n6 Fraskild\n9 # Manglar\n");
  NSD->AddVar("HeadAge","Alder hovudperson",15,98,0);
  NSD->AddVar("SpouseAge","Alder make",15,98,0);
  NSD->AddVar("Occupation","Yrkeskode",0,9998,0);
  NSD->AddVar("hfstd","Hovudpers fodested",100,9998,0);
  NSD->AddVar("hhtype","Hammel Laslett",0,998,0);
  NSD->AddVar("hsIZE","Hushaldsstorleik",0,98,0);
  NSD->AddVar("nhp","Antall hovudpersonar",0,1,0);;
  NSD->AddVar("nmakar","Antall makar",0,1,0);
  NSD->AddVar("nchld","Antall barn",0,19,0);
  NSD->AddVar("nrel","Antall slekt",0,19,0);
  NSD->AddVar("nserv","Antall tenestefolk",0,98,0);
  NSD->AddVar("nother","Antall Andre",0,98,0);
  NSD->AddVar("ninmate","Antall losjerande",0,98,0);
  NSD->AddVar("nMserv","Antall mannlege tenestefolk",0,98,0);
  NSD->AddVar("nKserv","Antall kvinnlege tenestefolk",0,98,0);
  NSD->AddVar("nandre","Antall sivilstatus anna/ukjent",0,98,0);
  NSD->AddVar("nugift","Antall ugifte",0,98,0);
  NSD->AddVar("ngift","Antall gifte",0,98,0);
  NSD->AddVar("nenkje","Antall enkjefolk",0,98,0);
  NSD->AddVar("ngenerasjonar","Antall generasjonar",0,4,0);
  NSD->AddVar("neignebarn0_5","Antall eigne barn 0-5",0,8,0);
  NSD->AddKodaVar("farogmor","Far og Mor tilstades","0 utan\n1 Berre far eller mor \n2 Begge\n9 # Manglar\n");
  if (ftaar==1865) {
    NSD->AddVar("nhest","Tal hest",0,998,0);
    NSD->AddVar("nkveg","Tal stort kveg",0,998,0);
    NSD->AddVar("nfaar","Tal faar",0,998,0);
    NSD->AddVar("ngeit","Tal geiter",0,998,0);
    NSD->AddVar("nsvin","Tal svin",0,998,0);
    NSD->AddVar("nRein","Tal reinsdyr",0,998,0);
    NSD->AddVar("nkuverd","Tal Kueiningar (sau+geit+gris+hest+kveg)",0,998,0);
    NSD->AddVar("nbygg","Tal bygg",0,998,2);
    NSD->AddVar("nbland","Tal blandkorn",0,998,2);
    NSD->AddVar("nhavre","Tal havre",0,998,2);
    NSD->AddVar("npoteter","Tal poteter",0,998,2);
    NSD->AddVar("nkornverd","Tal Byggeiningar",0,998,2);
    NSD->AddVar("kornprod","Kornproduksjon",0,9998,2);
    NSD->AddVar("SnMaal","Snitt bruksstorleik i maal ",0,9998,2);
  };
  NSD->SkrivVar();
  NSD->SkrivDok();
  delete NSD;

  NSD = new NSDvardok("kg", ftaar);
  NSD->AddVar("Kommnr","Kommunenr",100,9998,0);
  NSD->AddVar("NTilstede1","Tilstede1",0,999998,0);
  NSD->AddVar("NTilstede2","Tilstede2",0,999998,0);
  NSD->AddVar("NTilstede3","Tilstede2",0,999998,0);
  NSD->AddVar("Nhjemmeh1","Hjemmehorende befolkning 1",0,999998,0);
  NSD->AddVar("Nhjemmeh2","Hjemmehorende befolkning 2",0,999998,0);
  NSD->AddVar("Nhjemmeh3","Hjemmehorende befolkning 3",0,999998,0);
  NSD->AddVar("NHushald","Tal Hushald",0,99998,0);
  NSD->AddVar("NHus","Tal hus",0,99998,0);
  NSD->AddVar("NBosted","Tal bosteder",0,99998,0);
  NSD->AddVar("Nkaarhus","Kårhus (1900)",0,99998,0);
  NSD->AddVar("Ndrengestuer","Tjenerboliger, drengestuer (1900)",0,99998,0);
  NSD->AddVar("Nbryggerhuse","Bryggerhuse, strygestuer (1900)",0,99998,0);
  NSD->AddVar("Nfjos","Fjøse og stalde der nyttes til nattelogis (1900)",0,99998,0);
  NSD->AddVar("Nandre","Andre sidebygninger (1900)",0,99998,0);
  NSD->AddVar("Nuspes","Uspesifiserte sidebygninger (1900)",0,99998,0);
  NSD->AddVar("Npstkaar","Prosent kaarhus av vaaningshus",0,998,2);
  NSD->SkrivVar();
  NSD->SkrivDok();
  delete NSD;

  NSD = new NSDvardok("pers", ftaar);
  NSD->AddVar("Kommnr","Kommunenr",100,9998,0);
  NSD->AddVar("nper","Person ID",0,999998,0);
  NSD->AddVar("nhh","Hushald ID",0,999998,0);
  NSD->AddVar("persno","Personnr. i hushald",0,9998,0);
  NSD->AddKodaVar("HP","Hovudperson","1 Hovudperson \n2 Andre\n9 # Manglar\n");
  NSD->AddKodaVar("Kjonn","Kjønn","1 Mann \n2 Kvinne\n9 # Manglar\n");
  NSD->AddKodaVar("Sivstat","Sivilstatus","1 Ugift \n2 Gift\n3 Gift make manglar \n4 Enkje eller enkjemann \n5 Skild \n6 Separert \n9 # Manglar\n");
  NSD->AddVar("Alder","Alder",0,998,0);
  NSD->AddKodaVar("Relcode","Familiestilling koda","1 HP \n2 Make\n3 Barn \n4 Slekt \n5 Tenestefolk \n6 Andre \n7 Innerst/losjerande \n9 # Manglar\n");
  NSD->AddVar("Rel","Familiestilling Essex",0,9998,0);
  NSD->AddKodaVar("Bosatt","Bustad teljetidspunkt","1 Bosatt \n2 Midlertidig tilstede\n3 Fraverande \n9 # Manglar\n");
  NSD->AddVar("Fodestad","Fødestad kommunenr",100,9998,0);
  NSD->AddVar("Yrkeskode","Framtidig bruk HISCO",1,99998,0);
  NSD->SkrivVar();
  NSD->SkrivDok();
  delete NSD;

};


   float Kommune::MHS(int agefrom, int ageto)
   {
      int i;
      float antp, anth;
      if (mhs<0.0) {
         hsz[MAXAGE-1][1]=0;
         hsz[MAXAGE-1][0]=0;
         maxmhs=0.0;
         mhsagemax=0;
         for (i=16;i<100;i++) {
            if (hsz[i][0]>0) mhsage[i]=(float) hsz[i][1] / (float) hsz[i][0];
            else mhsage[i]=0.0;
            if (i>28 && i<61 && mhsage[i]>maxmhs) {
               mhsagemax=i;
               maxmhs=mhsage[i];
            }
            hsz[MAXAGE-1][1]=hsz[i][1]+hsz[MAXAGE-1][1];
            hsz[MAXAGE-1][0]=hsz[i][0]+hsz[MAXAGE-1][0];
         }
         if (hsz[MAXAGE-1][0]>0)
             mhs=(float) hsz[MAXAGE-1][1] / (float) hsz[MAXAGE-1][0];
         else mhs=0.0;
      }
      if (agefrom<15 && ageto>99)
         return mhs;
/*      nage=0;
      if (agefrom==28 && agefrom!= (int) (headmed)+1) {
         agefrom=(int) (headmed)+1;
         if (agefrom<26) agefrom=26;
         else if (agefrom>31) agefrom=31;
         ageto=agefrom+5;
      }*/
      anth=0;
      antp=0;
      for (i=agefrom;i<ageto;i++) {
        anth=anth+hsz[i][0];
        antp=antp+hsz[i][1];
      }
     if (anth>0)
        return (float) (antp/anth);
     else
        return 0.0;
   }




   long FileObject::readtek(char *ifname, char *knr, int cyear)
   {
      int   kommnrtest, rest;
      long  nrecs=0,nskip=0,
//            njrdbruk=0,
            nhus=0, nfields;
      long  head1manglar=0;

      bool nytthushald=true;

      tekTable intab,ottab;
      cForceEof FEof(knr);
//      FILE *ofp;
      FILE *RTLOG;
      Kommune *K;
      Kommgard *Kg;
      char filnamn[100];
      int  fieldlen;
      int  forceeof;

      char byland;
      char *p;

      sprintf(filnamn,"data/rtlog%d.txt",cyear);
      RTLOG=fopen(filnamn,"a");

      printf("Readtek: %s\t",ifname);
      fprintf(RTLOG,"Readtek: %s\t%s\t",ifname,knr);
      if (intab.Open(ifname)!=0) {
         fprintf(stderr,"Unable to open %s\n",ifname);
         exit(2);
      }
      nopen++;
      p=strrchr(ifname,'\\');
      if (p) {
         p++;
         byland=(char) toupper(*p);
      } else byland='F';
      ottab.OpenTmp(30);
      strcpy(ottab.fields[0],knr);
      ottab.fields[0][4]='\0';
      kommnrtest = atoi(knr);
      rest = kommnrtest % 100;
      if ((byland=='F') && (rest > 0) && (rest < 10))
         byland='B';
      printf("Start reading\t");
      K=new Kommune(knr,cyear,byland);
      Kg=new Kommgard(knr,cyear,byland);
      forceeof=1;
      if (intab.year==1865 && FEof.kfound==1 && FEof.skip==0) {
          while (nrecs<FEof.lesfra) {
             intab.Read();
             nrecs++;
          }
          printf("Force Skip at %d ",nrecs);
          fprintf(RTLOG," Force skip %d ",nrecs);
          nrecs=0;
      }
      while (((nfields=intab.Read())>0) && (forceeof!=0)) {
        nrecs++;
        switch (intab.fields[0][0]) {
            case 1: case '5': case '1':
              if (intab.year==1865 && intab.rhd==1 && intab.fields[0][0]=='1') {
                 K->prestegjeld=intab.fields[5];
                 if (FEof.kfound==0) {
                    if ((intab.AsInt(1)>FEof.skoletil)
                    || (intab.AsInt(2)>FEof.ltil)
                    || (nrecs>FEof.npostar)) {
                       forceeof=0;
                       printf("ForceEof1 at %d",K->nprecs);
                       fprintf(RTLOG,"ForceEof at %d",K->nprecs);
                    }
                 }
              }
              else {
               K->nprecs++;
               if ((Chead(intab.fields[intab.FHEAD])==1)
                  || (nytthushald==true)
                  || (K->headmt==true)) {
                  if (intab.fields[intab.FHEAD][