/* initptr.c Copyright (c) Kapteyn Laboratorium Groningen 1990 All Rights Reserved. */ #include "stdio.h" /* */ #include "stdlib.h" /* */ #include "gipsyc.h" /* GIPSY symbols */ static fint *fp = NULL; static fint *b1p = NULL, *b2p = NULL; static fint *gip = NULL, *gop = NULL; static fint *gis = NULL, *gos = NULL; static fint *p1p = NULL, *p2p = NULL; static fint *mp = NULL; static fint inc; static fint dim; static fint nic, noc; static void reseti( void ) { fint n; nic = 0; for (n = 0; n < dim; n++) gip[n] = gis[n]; } static void reseto( void ) { fint n; noc = 0; for (n = 0; n < dim; n++) gop[n] = gos[n]; } static bool inside( fint g[] ) { bool ins = 1; fint n = dim - 1; do { ins = ((g[n] >= b1p[n]) && (g[n] <= b2p[n])); } while ((ins) && (n-- > 0)); return(ins); } static void next( fint g[] ) { fint n = 0; fint l; while (g[n] > fp[n]) { l = 0; while (g[n] > fp[n]) { g[n] -= fp[n]; l++; } if (++n == dim) break; g[n] += l; } } /* #> initptr.dc2 Subroutine: INITPTR Purpose: Pointer handling within parts of subset. File: initptr.c Author: K.G. Begeman Use: CALL INITPTR( RFLO, Input INTEGER ARRAY RFHI, Input INTEGER ARRAY SFLO, Input INTEGER ARRAY SFHI, Input INTEGER ARRAY NDIM, Input INTEGER NR, Input INTEGER NT ) In/Output INTEGER RFLO Array with the lower coordinates of readframe. RFHI Array with the upper coordinates of readframe. SFLO Array with the lower coordinates of subframe. SFHI Array with the upper coordinates of subframe. NDIM Dimension of subset (length of RFLO,RFHI, etc.). NR Number of data values currently in readbuffer. NT On input, number of points done sofar, on output number of points done. Initial value must be 0! Description: The subroutine INITPTR is used in combination with GDSI_READ. GDSI_READ returns the number of data values actually read, which is input to INITPTR in order to initialize the logical functions INSIDEPTR and OUTSIDEPTR. Further input to INITPTR are the dimension of the subset, the readframe (part of the subset which is to be read by GDSI_READ) and a subframe (which is contained in the readframe). After each call to GDSI_READ and INITPTR the functions INSIDEPTR and OUTSIDEPTR return pointers to datavalues (in the buffer filled by GDSI_READ) which are inside or outside the subframe. INSIDEPTR and OUTSIDEPTR return .FALSE. if all positions in the readbuffer have been scanned. These routines provide the applications programmer with a simple tool to handle data in subframes (i.e. frames returned from BOXINP) in a different way than the data outside the subframe. See the example below. Example: INTEGER SIZE PARAMETER (SIZE=4096) INTEGER MAXAX PARAMETER (MAXAX=5) CHARACTER*80 SET INTEGER C1,C2,F1(MAXAX),F2(MAXAX),B1(MAXAX),B2(MAXAX) INTEGER IP,NP,NR,NT,NW,IERR,IERW REAL RBUF(SIZE) LOGICAL INSIDEPTR, OUTSIDEPTR NT=0 REPEAT CALL GDSI_READ(SET,C1,C2,RBUF,SIZE,NR,IERR) CALL INITPTR(F1,F2,B1,B2,NDIM,NR,NT) WHILE (INSIDEPTR(IP,NP)) CALL SCALE1(RBUF(IP+1),NP,2.0,0.0) CWHILE WHILE (OUTSIDEPTR(IP,NP)) CALL SCALE1(RBUF(IP+1),NP,0.5,0.0) CWHILE CALL GDSI_WRITE(SET,C1,C2,RBUF,NR,NW,IERW) UNTIL (IERR .EQ. 0) COPY and SCALE are example programs which demonstrate the use of INITPTR. Related Docs: insideptr.dc2, outsideptr.dc2 Updates: Nov 15, 1988: KGB, Creation date. Jan 3, 1992: KGB, Bug removed. #< @ subroutine initptr( integer, integer, integer, integer, @ integer, integer, integer ) */ void initptr_c( fint *f1 , fint *f2 , fint *b1 , fint *b2 , fint *ndim , fint *nd , fint *ntot ) { fint i, j; fint ipos; if (*ntot == 0) { int s = sizeof(fint); int d = dim = *ndim; if (dim) { if (fp != NULL) { free(fp); free(b1p); free(b2p); free(gip); free(gop); free(gis); free(gos); free(p1p); free(p2p); free(mp); } fp = calloc(d,s); b1p = calloc(d,s); b2p = calloc(d,s); gip = calloc(d,s); gop = calloc(d,s); gis = calloc(d,s); gos = calloc(d,s); p1p = calloc(d,s); p2p = calloc(d,s); mp = calloc(d,s); for (j = 1, i = 0; i < dim; i++) { fp[i] = f2[i] - f1[i] + 1; b1p[i] = b1[i] - f1[i] + 1; b2p[i] = b2[i] - f1[i] + 1; p2p[i] = 1; mp[i] = j; j = j * fp[i]; } } } ipos = *ntot += inc = *nd; ipos++; for (i = dim; i-- > 0; ) { fint g = (ipos - 1)/ mp[i]; ipos -= g * mp[i]; gis[i] = gos[i] = gip[i] = gop[i] = p1p[i] = p2p[i]; p2p[i] = 1 + g; } nic = noc = 0; } /* #> insideptr.dc2 Function: INSIDEPTR Purpose: Indicates whether inside or outside subframe defined by INITPTR. File: initptr.c Author: K.G. Begeman Use: LOGICAL INSIDEPTR( IP, Output INTEGER NP ) Output INTEGER INSIDEPTR Returns .TRUE. when still some data inside subframe in readbuffer, else .FALSE. IP If INSIDEPTR .eq. .TRUE., offset pointer from start of readbuffer to where first data value insiderame can be found. NP If INSIDEPTR .eq. .TRUE., number of data values inside subframe in readbuffer starting at IP. Notes: When INSIDEPTR returns .FALSE. it reinitializes itself to the state just after the call to INITPTR. So it can be used again to do a different operation on data inside the sub frame. Related Docs: initptr.dc2, outsideptr.dc2 Updates: Nov 15, 1988: KGB, Creation date. Feb 27, 1990: KGB, Reinitialization implemented. #< @ logical function insideptr( integer, integer ) */ bool insideptr_c( fint *ip , fint *np ) { fint n; if (nic >= inc) { reseti(); /* reset to initial status after call to initptr */ return(FALSE); } if (!dim) { *ip = 0; *np = 1; nic += inc; return(TRUE); } *ip = nic; *np = 0; if (!dim) return(TRUE); while (!inside(gip)) { if (b1p[0] > gip[0]) { nic += n = b1p[0] - gip[0]; } else { nic += n = b1p[0] - gip[0] + fp[0]; } if (nic >= inc) { reseti(); /* reset to initial status after call to initptr */ return(FALSE); } gip[0] += n; *ip += n; next(gip); } while (inside(gip)) { nic += n = b2p[0] - gip[0] + 1; if (nic >= inc) { *np = inc - *ip; return(TRUE); } gip[0] += n; *np += n; next(gip); } return(TRUE); } /* #> outsideptr.dc2 Function: OUTSIDEPTR Purpose: Indicates whether inside or outside subframe defined by INITPTR. File: initptr.c Author: K.G. Begeman Use: LOGICAL OUTSIDEPTR( IP, Output INTEGER NP ) Output INTEGER OUTSIDEPTR Returns .TRUE. when still some data outside subframe in readbuffer, else .FALSE. IP If OUTSIDEPTR .eq. .TRUE., offset pointer from start of readbuffer to where first data value outside subframe can be found. NP If OUTSIDEPTR .eq. .TRUE., number of data values outside subframe in readbuffer starting at IP. Notes: When OUTSIDEPTR returns .FALSE. it reinitializes itself to the state just after the call to INITPTR. So it can be used again to do a different operation on data outside the sub frame. Related Docs: initptr.dc2, insideptr.dc2 Updates: Nov 15, 1988: KGB, Creation date. Feb 27, 1990: KGB, Reinitialization implemented. #< @ logical function outsideptr( integer, integer ) */ bool outsideptr_c( fint *ip, fint *np ) { fint n; if (noc >= inc) { reseto(); /* reset to initial status after call to initptr */ return(FALSE); } if (!dim) { noc += inc; return(FALSE); } *ip = noc; *np = 0; while (inside(gop)) { noc += n = b2p[0] - gop[0] + 1; if (noc >= inc) { reseto(); /* reset to initial status after call to initptr */ return(FALSE); } gop[0] += n; *ip += n; next(gop); } while (!inside(gop)) { if (b1p[0] > gop[0]) { noc += n = b1p[0] - gop[0]; } else { noc += n = b1p[0] - gop[0] + fp[0]; } if (noc >= inc) { *np = inc - *ip; return(TRUE); } gop[0] += n; *np += n; next(gop); } return(TRUE); } #if defined(TESTBED) main(argc,argv) int argc; char *argv[]; { bool bingo = 1; fint area[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; fint save[sizeof(area)/sizeof(fint*)]; fint frame2[] = { 10, 10 }; fint frame1[] = { 1, 1 }; fint boxlo[] = { 3, 3 }; fint boxhi[] = { 6, 7 }; fint d = 2; fint ntot = 0; fint nd = 2; fint ip, np; fint nt = 0; if (argc > 1) { sscanf(argv[1],"%ld",&nd); } else { nd = 2; } if (nd <= 0) nd = 7; printf("INITPTR, Step:%5ld\n",nd); printf("Initial:\n"); for (ip = 0; ip < 10; ip++) { for (np = 0; np < 10; np++) { save[ip*10+np] = area[ip*10+np]; printf("%5ld",area[ip*10+np]); } printf("\n"); } do { if ((ntot + nd) > 100) nd = 100 - ntot; initptr_c(frame1,frame2,boxlo,boxhi,&d,&nd,&ntot); while (tobool(insideptr_c(&ip,&np))) { fint i; for (i = 0; i < np; i++) area[nt+ip+i] += 2; } while (tobool(outsideptr_c(&ip,&np))) { fint i; for (i = 0; i < np; i++) area[nt+ip+i] += 4; } while (tobool(insideptr_c(&ip,&np))) { fint i; for (i = 0; i < np; i++) area[nt+ip+i] += 2; } while (tobool(outsideptr_c(&ip,&np))) { fint i; for (i = 0; i < np; i++) area[nt+ip+i] += 4; } nt = ntot; } while (ntot < 100); printf("Result:\n"); for (ip = 0; ip < 10; ip++) { for (np = 0; np < 10; np++) { printf("%5ld",area[ip*10+np]); if (area[ip*10+np] == 8 && save[ip*10+np] != 0) bingo = 0; if (area[ip*10+np] == 5 && save[ip*10+np] != 1) bingo = 0; } printf("\n"); } if (bingo) { printf( "bingo\n" ); } else { printf( "not bingo\n" ); } } #endif