/* internal ana subroutines and functions, this is file fun4.c  */
#include "ana_structures.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#define ABS(x) ((x)>=0?(x):-(x))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
 extern int scrat[NSCRAT];
 extern struct sym_desc sym[];
 extern struct sym_list         *subr_sym_list[];
 extern int     temp_base;
 extern int     ana_float();
 extern char *find_sym_name(int iq);
 extern int     ana_type_size[];
 extern int     vfix_top, num_ana_subr, next_user_subr_num;
 extern int     lastmin_sym, lastmax_sym;
 extern float   float_arg();
 extern double  double_arg();
 int    result_sym;
 /*------------------------------------------------------------------------- */
#define CKQ if (q < qbase || q > (qbase+n*m-1)) printf("q out of range %#x\n", q)
#define CKQA if (qabove < qbase || qabove > (qbase+n*m-1)) printf("qabove out of range %#x\n", qabove)
#define CKQB if (qbelow < qbase || qbelow > (qbase+n*m-1)) printf("qbelow out of range %#x\n", qbelow)
#define CKQR if (q < qbase || q > (qbase+n*m-1)) printf("q in run %#x\n", q)
#define CKQAR if (qabove < qbase || qabove > (qbase+n*m-1)) printf("qabove in run %#x\n", qabove)
#define CKQBR if (qbelow < qbase || qbelow > (qbase+n*m-1)) printf("qbelow in run %#x\n", qbelow)
 /*------------------------------------------------------------------------- */
int ana_erode(narg,ps)                         /* dilation function */
 /* the call is x = dilate(array)
    where array must be a 2-D array, returns the dilated bitmap */
 int    narg, ps[];
 {
 byte   *pbase, *qbase, *p, *q, *p_endline, *qabove, *qbelow;
 unsigned long  q_minus_p;

 int    iq, n, m, mq, type;
 int    dim[8];
 struct ahead   *h;
 iq = ps[0];
                                 /* first arg must be a 2-D integer array */
 if ( sym[iq].class != 4 ) return execute_error(66);
 type = sym[iq].type;
 if (type != 0) return execute_error(118);
 h = (struct ahead *) sym[iq].spec.array.ptr;
 if ( h->ndim != 2 ) return execute_error(101);
 n = h->dims[0];        m = h->dims[1];
 dim[0] = n;            dim[1] = m;
 if ( n < 3 || m < 3 ) {
        printf("ERODE: array too small, nx, ny = %d %d\n", n, m);
        return -1; }
 pbase = (byte *) ((char *)h + sizeof(struct ahead));
 result_sym = array_scratch(0, 2, dim);         /*for the result */
 h = (struct ahead *) sym[result_sym].spec.array.ptr;
 qbase = (byte *) ((char *)h + sizeof(struct ahead));

 bcopy(pbase, qbase, n*m);
 q_minus_p = qbase - pbase - 1;
 
 p = pbase;
 q = qbase;

 /* the edges and corners are done as special cases */
 /* first corner */
 if (*p == 0) {  /* zap the 3 neighbors */
 *q++;  *q = 0; q = qbase + n;  *q++ = 0; *q = 0;}
 /* starting row */
 p_endline = pbase + n - 2;
 p++;
 while (1) {
  if (*p == 0) {
  /* got a hit, this means we need to set 6 pixels in the output image */
  q = q_minus_p + p;   /* this is the q just before the corresponding p */
  qabove = q + n;
  *q++ = 0;             *q++;       *q++ = 0;
  *qabove++ = 0;        *qabove++ = 0;  *qabove++ = 0;
  if (p >= p_endline) break;
  p++;
  /* if we continue to get consecutive hits, just need to set next 2 */
  while (*p == 0) {
   if (p >= p_endline) break;
   *q++ = 0;    *qabove++ = 0;
   p++; }
  }
  if (p >= p_endline) break;
  p++;
  }
  p++;
  /* last point in starting row, set independent of previous so we may
  set some pixels twice */
  if (*p == 0) {  
  q = q_minus_p + p;   /* this is the q just before the corresponding p */
  qabove = q + n;
  *q = 0;
  *qabove++ = 0;        *qabove = 0;
  }
  p++;


 /* central area */ 
 /* now the interior rows */
 mq = m - 2;
 while (mq-- > 0) {
 /* start row, not top or bottom */
 /* left hand edge */
 if (*p == 0) {      /* set 6 points */
  q = q_minus_p + 1 + p;        /* q at p */
  qabove = q + n;       qbelow = q - n; 
  *q++;             *q = 0;
  *qabove++ = 0;        *qabove = 0;
  *qbelow++ = 0;        *qbelow = 0;
 }
 p_endline = p + n - 2;
 p++;

 /* done with left edge, now the middle */
 
 while (1) {
  if (*p == 0) {
  /* got a hit, this means we need to clear 8 pixels in the output image */
  q = q_minus_p + p;
  qabove = q + n;       qbelow = q - n; 
  *q++ = 0;             *q++;       *q++ = 0;
  *qabove++ = 0;        *qabove++ = 0;  *qabove++ = 0;
  *qbelow++ = 0;        *qbelow++ = 0;  *qbelow++ = 0;
  if (p >= p_endline) break;
  p++;
  /* if we continue to get consecutive hits, just need to clear next 3 */
  while (*p == 0) {
   if (p >= p_endline) break;
   *q++ = 0;    *qabove++ = 0;  *qbelow++ = 0;
   p++; }
  }
  if (p >= p_endline) break;
  p++;
  }
  p++;


 /* the last point in row */
  if (*p == 0) {  
  q = q_minus_p + p;   /* this is the q just before the corresponding p */
  qabove = q + n;       qbelow = q - n; 
  *q = 0;
  *qabove++ = 0;        *qabove++ = 0;
  *qbelow++ = 0;        *qbelow++ = 0;
  }
  p++;

 }

 /* at last, the last row */
 /* left hand edge */
 if (*p == 0) {      /* set 4 points */
  q = q_minus_p + 1 + p;        /* q at p */
  qbelow = q - n;       
  *q++;              *q = 0;
  *qbelow++ = 0;         *qbelow = 0;
 }
 p_endline = p + n - 2;
 p++;

 /* now the middle of the last row */
 
 while (1) {
  if (*p == 0) {
  /* got a hit, this means we need to set 9 pixels in the output image */
  q = q_minus_p + p;
  qbelow = q - n;       
  *q++ = 0;             *q++;       *q++ = 0;
  *qbelow++ = 0;        *qbelow++ = 0;  *qbelow++ = 0;
  if (p >= p_endline) break;
  p++;
  /* if we continue to get consecutive hits, just need to set next 3 */
  while (*p == 0) {
  if (p >= p_endline) break;
  *q++ = 0;     *qbelow++ = 0;  p++; }
  }
  if (p >= p_endline) break;
  p++;
  }
  p++;
  /* printf("pbase, p_endline, p = %#x, %#x, %#x\n", pbase, p_endline, p); */
 /* the last point in last row */
  /* printf("pbase, p = %#x, %#x\n", pbase, p); */
  if (*p == 0) {  
  q = q_minus_p + p;   /* this is the q just before the corresponding p */
  qbelow = q - n;       
  *q = 0;
  *qbelow++ = 0;        *qbelow = 0;
  }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
