mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-12-27 08:49:16 +08:00
163 lines
4.1 KiB
C
163 lines
4.1 KiB
C
/*********************************************************************
|
|
* Copyright 2018, UCAR/Unidata
|
|
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
|
*********************************************************************/
|
|
/* $Id: odom.c,v 1.5 2010/05/27 21:34:18 dmh Exp $ */
|
|
/* $Header: /upc/share/CVS/netcdf-3/ncgen/odom.c,v 1.5 2010/05/27 21:34:18 dmh Exp $ */
|
|
|
|
#include "includes.h"
|
|
#include "odom.h"
|
|
|
|
/**************************************************/
|
|
/* Define methods for a dimension odometer*/
|
|
|
|
Odometer*
|
|
newodometer(Dimset* dimset, size_t* startp, size_t* countp)
|
|
{
|
|
int i;
|
|
Odometer* odom;
|
|
ASSERT(dimset != NULL);
|
|
ASSERT(dimset->ndims > 0);
|
|
odom = (Odometer*)ecalloc(sizeof(Odometer));
|
|
if(odom == NULL) return NULL;
|
|
odom->origin = odom;
|
|
odom->offset = 0;
|
|
odom->rank = dimset->ndims;
|
|
ASSERT(odom->rank <= NC_MAX_VAR_DIMS);
|
|
for(i=0;i<odom->rank;i++) {
|
|
odom->declsize[i] = dimset->dimsyms[i]->dim.declsize;
|
|
odom->start[i] = (startp == NULL ? 0
|
|
: startp[i]);
|
|
odom->count[i] = (countp == NULL ? odom->declsize[i]
|
|
: countp[i]);
|
|
odom->index[i] = odom->start[i];
|
|
/* verify */
|
|
ASSERT(odom->start[i] + odom->count[i] <= odom->declsize[i]);
|
|
}
|
|
return odom;
|
|
}
|
|
|
|
Odometer*
|
|
newsubodometer(Odometer* origin, Dimset* dimset, int start, int stop)
|
|
{
|
|
Odometer* odom;
|
|
ASSERT(dimset != NULL);
|
|
ASSERT(dimset->ndims > 0 && dimset->ndims >= stop);
|
|
ASSERT(stop > start);
|
|
odom = (Odometer*)ecalloc(sizeof(Odometer));
|
|
if(odom == NULL) return NULL;
|
|
odom->origin = origin;
|
|
odom->offset = start;
|
|
odom->rank = (stop - start);
|
|
ASSERT(odom->rank <= NC_MAX_VAR_DIMS);
|
|
return odom;
|
|
}
|
|
|
|
void
|
|
odometerfree(Odometer* odom)
|
|
{
|
|
if(odom) efree(odom);
|
|
}
|
|
|
|
char*
|
|
odometerprint(Odometer* odom)
|
|
{
|
|
int i;
|
|
static char line[1024];
|
|
char tmp[64];
|
|
line[0] = '\0';
|
|
if(odom->origin->rank == 0) {
|
|
strcat(line,"[]");
|
|
} else for(i=0;i<odom->rank;i++) {
|
|
int ioffset = i + odom->offset;
|
|
sprintf(tmp,"[%lu/%lu..%lu:%lu]",
|
|
(unsigned long)odom->origin->index[ioffset],
|
|
(unsigned long)odom->origin->start[ioffset],
|
|
(unsigned long)odom->origin->declsize[ioffset],
|
|
(unsigned long)odom->origin->count[ioffset]
|
|
);
|
|
strcat(line,tmp);
|
|
}
|
|
return line;
|
|
}
|
|
|
|
int
|
|
odometermore(Odometer* odom)
|
|
{
|
|
size_t index,start,count;
|
|
int offset = odom->offset;
|
|
ASSERT(odom->rank > 0);
|
|
index = odom->origin->index[offset];
|
|
start = odom->origin->start[offset];
|
|
count = odom->origin->count[offset];
|
|
if(index < start + count) return 1;
|
|
/* reset the zero'th wheel before returning */
|
|
odom->origin->index[offset] = odom->origin->start[offset];
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
odometerincr(Odometer* odom)
|
|
{
|
|
int i;
|
|
int last = odom->rank-1;
|
|
ASSERT(odom->rank > 0);
|
|
for(i=last;i>=0;i--) {
|
|
int ioffset = i+odom->offset;
|
|
odom->origin->index[ioffset]++;
|
|
if(odom->origin->index[ioffset]
|
|
< (odom->origin->start[ioffset]
|
|
+odom->origin->count[ioffset]))
|
|
break;
|
|
if(i==0) break; /* leave 0'th for next more() check */
|
|
odom->origin->index[ioffset] = odom->origin->start[ioffset];
|
|
}
|
|
return i; /* return rightmost incremented */
|
|
}
|
|
|
|
|
|
/*
|
|
Suppose we have the declaration int F[2][5][3];
|
|
There are obviously a total of 2 X 5 X 3 = 30 integers in F.
|
|
Thus, these three dimensions will be reduced to a single
|
|
dimension of size 30 (0..29).
|
|
A particular point in the three dimensions, say [x][y][z], is reduced to
|
|
a number in the range 0..29 by computing ((x*5)+y)*3+z
|
|
So, given an odometer in some state, it computes the offset
|
|
for that odometer's state.
|
|
*/
|
|
|
|
size_t
|
|
odometeroffset(Odometer* odom)
|
|
{
|
|
int i;
|
|
size_t count = 0;
|
|
for(i=0;i<odom->rank;i++) {
|
|
int ioffset = i+odom->offset;
|
|
if(i > 0) count *= odom->origin->declsize[ioffset];
|
|
count += odom->origin->index[ioffset];
|
|
}
|
|
return count;
|
|
}
|
|
|
|
/*
|
|
Get the start vector
|
|
from the odometer
|
|
*/
|
|
size_t*
|
|
odometerstartvector(Odometer* odom)
|
|
{
|
|
return odom->start;
|
|
}
|
|
|
|
/*
|
|
Get the count vector
|
|
from the odometer
|
|
*/
|
|
size_t*
|
|
odometercountvector(Odometer* odom)
|
|
{
|
|
return odom->count;
|
|
}
|
|
|