#include <stdio.h>#include <netcdf.h>#include "nco_netcdf.h"#include "nco.h"#include "nco_cnf_typ.h"#include "nco_mmr.h"#include "nco_rth_utl.h"#include "nco_var_rth.h"#include "nco_var_utl.h"Include dependency graph for nco_var_avg.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
Functions | |
| var_sct * | nco_var_avg (var_sct *var, dmn_sct *const *const dim, const int nbr_dim, const int nco_op_typ) |
| void | nco_var_avg_reduce_ttl (const nc_type type, const long sz_op1, const long sz_op2, const int has_mss_val, ptr_unn mss_val, long *const tally, ptr_unn op1, ptr_unn op2) |
| void | nco_var_avg_reduce_min (const nc_type type, const long sz_op1, const long sz_op2, const int has_mss_val, ptr_unn mss_val, ptr_unn op1, ptr_unn op2) |
| void | nco_var_avg_reduce_max (const nc_type type, const long sz_op1, const long sz_op2, const int has_mss_val, ptr_unn mss_val, ptr_unn op1, ptr_unn op2) |
|
||||||||||||||||||||
|
Definition at line 13 of file nco_var_avg.c. References var_sct_tag::cnt, dmn_sct_tag::cnt, dbg_lvl_get(), var_sct_tag::dim, var_sct_tag::dmn_id, var_sct_tag::end, False, var_sct_tag::has_mss_val, dmn_sct_tag::id, dmn_sct_tag::is_crd_dmn, var_sct_tag::is_crd_var, dmn_sct_tag::is_rec_dmn, var_sct_tag::is_rec_var, var_sct_tag::mss_val, var_sct_tag::nbr_dim, NC_MAX_DIMS, nco_free(), nco_malloc(), nco_op_avg, nco_op_avgsqr, nco_op_max, nco_op_min, nco_op_rms, nco_op_rmssdn, nco_op_sqravg, nco_op_ttl, nco_realloc(), nco_typ_lng(), nco_var_avg_reduce_max(), nco_var_avg_reduce_min(), nco_var_avg_reduce_ttl(), nco_var_dpl(), nco_var_free(), nco_var_zero(), nco_zero_long(), var_sct_tag::nm, prg_nm_get(), var_sct_tag::srt, var_sct_tag::sz, var_sct_tag::sz_rec, var_sct_tag::tally, True, var_sct_tag::type, var_sct_tag::val, and ptr_unn::vp. Referenced by main(). 00017 { 00018 /* Threads: Routine is thread safe and calls no unsafe routines */ 00019 /* Purpose: Reduce given variable over specified dimensions 00020 "Reduce" means to rank-reduce variable by performing arithmetic operation 00021 Output variable is duplicate of input variable, except for averaging dimensions 00022 Default operation is averaging, but nco_op_typ can also be min, max, etc. 00023 nco_var_avg() overwrites contents, if any, of tally array with number of valid input elements contributing to each valid output element 00024 00025 Input variable structure is destroyed and routine returns resized, partially reduced variable 00026 For some operations, such as min, max, ttl, variable returned by nco_var_avg() is complete and need not be further processed 00027 For averaging operation, output variable must be normalized by its tally array 00028 In other words, nco_var_nrm() should be called subsequently if normalization is desired 00029 Normalization is not done internally to nco_var_avg() to allow user more flexibility */ 00030 00031 /* Routine keeps track of three variables whose abbreviations are: 00032 var: Input variable (already hyperslabbed) 00033 avg: An array of averaging blocks, each a contiguous arrangement of all 00034 elements of var which contribute to a single element of fix. 00035 fix: Output (averaged) variable */ 00036 00037 dmn_sct **dmn_avg; 00038 dmn_sct **dmn_fix; 00039 00040 int idx_avg_var[NC_MAX_DIMS]; 00041 /* int idx_var_avg[NC_MAX_DIMS];*/ /* Variable is unused but instructive anyway */ 00042 int idx_fix_var[NC_MAX_DIMS]; 00043 /* int idx_var_fix[NC_MAX_DIMS];*/ /* Variable is unused but instructive anyway */ 00044 int idx; 00045 int idx_dmn; 00046 int dmn_avg_nbr; 00047 int nbr_dmn_fix; 00048 int nbr_dmn_var; 00049 00050 long avg_sz; 00051 long fix_sz; 00052 long var_sz; 00053 00054 var_sct *fix; 00055 00056 /* Copy basic attributes of input variable into output (averaged) variable */ 00057 fix=nco_var_dpl(var); 00058 00059 /* Create lists of averaging and fixed dimensions (in order of their appearance 00060 in the variable). We do not know a priori how many dimensions remain in the 00061 output (averaged) variable, but nbr_dmn_var is an upper bound. Similarly, we do 00062 not know a priori how many of the dimensions in the input list of averaging 00063 dimensions (dim) actually occur in the current variable, so we do not know 00064 dmn_avg_nbr, but nbr_dim is an upper bound on it. */ 00065 nbr_dmn_var=var->nbr_dim; 00066 nbr_dmn_fix=0; 00067 dmn_avg_nbr=0; 00068 dmn_avg=(dmn_sct **)nco_malloc(nbr_dim*sizeof(dmn_sct *)); 00069 dmn_fix=(dmn_sct **)nco_malloc(nbr_dmn_var*sizeof(dmn_sct *)); 00070 for(idx=0;idx<nbr_dmn_var;idx++){ 00071 for(idx_dmn=0;idx_dmn<nbr_dim;idx_dmn++){ 00072 /* Comparing dimension IDs is faster than comparing dimension names 00073 but requires assumption that all dimensions are from same file */ 00074 if(var->dmn_id[idx] == dim[idx_dmn]->id){ 00075 /* Although structures in dim are never altered, linking them into 00076 dmn_avg list makes them vulnerable to manipulation and forces 00077 dim to lose const protection in prototype */ 00078 dmn_avg[dmn_avg_nbr]=dim[idx_dmn]; 00079 /* idx_avg_var[i]=j means that the ith averaging dimension is the jth dimension of var */ 00080 idx_avg_var[dmn_avg_nbr]=idx; 00081 /* idx_var_avg[j]=i means that the jth dimension of var is the ith averaging dimension */ 00082 /* idx_var_avg[idx]=dmn_avg_nbr;*/ /* Variable is unused but instructive anyway */ 00083 dmn_avg_nbr++; 00084 break; 00085 } /* end if */ 00086 } /* end loop over idx_dmn */ 00087 if(idx_dmn == nbr_dim){ 00088 dmn_fix[nbr_dmn_fix]=var->dim[idx]; 00089 /* idx_fix_var[i]=j means that the ith fixed dimension is the jth dimension of var */ 00090 idx_fix_var[nbr_dmn_fix]=idx; 00091 /* idx_var_fix[j]=i means that the jth dimension of var is the ith fixed dimension */ 00092 /* idx_var_fix[idx]=nbr_dmn_fix;*/ /* Variable is unused but instructive anyway */ 00093 nbr_dmn_fix++; 00094 } /* end if */ 00095 } /* end loop over idx */ 00096 00097 if(dmn_avg_nbr == 0){ 00098 /* 20050517: ncwa only calls nco_var_avg() with variables containing averaging dimensions 00099 Variables without averaging dimensions are in the var_fix list 00100 We preserve nco_var_avg() capability to work on var_fix variables for future flexibility */ 00101 (void)fprintf(stderr,"%s: WARNING %s does not contain any averaging dimensions\n",prg_nm_get(),fix->nm); 00102 /* Variable does not contain any averaging dimensions so we are done 00103 For consistency, return copy of variable held in fix and free() original 00104 Hence, nco_var_avg() always destroys original input and returns valid output */ 00105 goto cln_and_xit; 00106 } /* end if */ 00107 00108 /* Free extra list space */ 00109 dmn_fix=(dmn_sct **)nco_realloc(dmn_fix,nbr_dmn_fix*sizeof(dmn_sct *)); 00110 dmn_avg=(dmn_sct **)nco_realloc(dmn_avg,dmn_avg_nbr*sizeof(dmn_sct *)); 00111 00112 /* Get rid of averaged dimensions */ 00113 fix->nbr_dim=nbr_dmn_fix; 00114 00115 avg_sz=1L; 00116 for(idx=0;idx<dmn_avg_nbr;idx++){ 00117 avg_sz*=dmn_avg[idx]->cnt; 00118 fix->sz/=dmn_avg[idx]->cnt; 00119 if(!dmn_avg[idx]->is_rec_dmn) fix->sz_rec/=dmn_avg[idx]->cnt; 00120 } /* end loop over idx */ 00121 /* Convenience variable to avoid repetitive indirect addressing */ 00122 fix_sz=fix->sz; 00123 00124 fix->is_rec_var=False; 00125 for(idx=0;idx<nbr_dmn_fix;idx++){ 00126 if(dmn_fix[idx]->is_rec_dmn) fix->is_rec_var=True; 00127 fix->dim[idx]=dmn_fix[idx]; 00128 fix->dmn_id[idx]=dmn_fix[idx]->id; 00129 fix->srt[idx]=var->srt[idx_fix_var[idx]]; 00130 fix->cnt[idx]=var->cnt[idx_fix_var[idx]]; 00131 fix->end[idx]=var->end[idx_fix_var[idx]]; 00132 } /* end loop over idx */ 00133 00134 fix->is_crd_var=False; 00135 if(nbr_dmn_fix == 1) 00136 if(dmn_fix[0]->is_crd_dmn) 00137 fix->is_crd_var=True; 00138 00139 /* Trim dimension arrays to their new sizes */ 00140 fix->dim=(dmn_sct **)nco_realloc(fix->dim,nbr_dmn_fix*sizeof(dmn_sct *)); 00141 fix->dmn_id=(int *)nco_realloc(fix->dmn_id,nbr_dmn_fix*sizeof(int)); 00142 fix->srt=(long *)nco_realloc(fix->srt,nbr_dmn_fix*sizeof(long)); 00143 fix->cnt=(long *)nco_realloc(fix->cnt,nbr_dmn_fix*sizeof(long)); 00144 fix->end=(long *)nco_realloc(fix->end,nbr_dmn_fix*sizeof(long)); 00145 00146 if(avg_sz == 1L){ 00147 /* If averaging block size is 1, input and output value arrays are identical 00148 var->val was copied to fix->val by nco_var_dpl() at beginning of routine 00149 Only one task remains: to set fix->tally appropriately */ 00150 long *fix_tally; 00151 00152 fix_tally=fix->tally; 00153 00154 /* First set tally field to 1 */ 00155 for(idx=0;idx<fix_sz;idx++) fix_tally[idx]=1L; 00156 /* Next overwrite any missing value locations with zero */ 00157 if(fix->has_mss_val){ 00158 int val_sz_byte; 00159 00160 char *val; 00161 char *mss_val; 00162 00163 /* NB: Use char * rather than void * because some compilers (acc) will not do pointer 00164 arithmetic on void * */ 00165 mss_val=(char *)fix->mss_val.vp; 00166 val_sz_byte=nco_typ_lng(fix->type); 00167 val=(char *)fix->val.vp; 00168 for(idx=0;idx<fix_sz;idx++,val+=val_sz_byte) 00169 if(!memcmp(val,mss_val,(size_t)val_sz_byte)) fix_tally[idx]=0L; 00170 } /* fix->has_mss_val */ 00171 } /* end if avg_sz == 1L */ 00172 00173 /* Distribute all elements of input hyperslab into averaging block in avg_val 00174 Each block contains avg_sz elements in contiguous buffer 00175 Reduction step then "reduces" each block into single output element */ 00176 if(avg_sz != 1L){ 00177 bool AVG_DMN_ARE_MRV=False; /* [flg] Avergaging dimensions are MRV dimensions */ 00178 ptr_unn avg_val; 00179 00180 /* Initialize data needed by reduction step independent of collection algorithm */ 00181 var_sz=var->sz; 00182 00183 /* Value buffer of size var_sz is currently duplicate of input values 00184 MRV algorithm uses these values without re-arranging 00185 General collection algorithm overwrites avg_val with averaging blocks */ 00186 avg_val=fix->val; 00187 /* Create new value buffer for output (averaged) size */ 00188 fix->val.vp=(void *)nco_malloc(fix_sz*nco_typ_lng(fix->type)); 00189 /* Resize (or just plain allocate) tally array */ 00190 fix->tally=(long *)nco_realloc(fix->tally,fix_sz*sizeof(long)); 00191 00192 /* Initialize value and tally arrays */ 00193 (void)nco_zero_long(fix_sz,fix->tally); 00194 (void)nco_var_zero(fix->type,fix_sz,fix->val); 00195 00196 /* Complex expensive collection step for creating averaging blocks works 00197 in all cases though is unnecessary in one important case. 00198 If averaging dimensions are most rapidly varying (MRV) dimensions, then no 00199 re-arrangement is necessary because original variable is stored in averaging 00200 block order. 00201 Averaging dimensions are MRV dimensions iff nbr_dmn_fix fixed dimensions are 00202 one-to-one with first nbr_dmn_fix input dimensions. 00203 Alternatively, could compare dmn_avg_nbr averaging dimensions to last 00204 dmn_avg_nbr dimensions of input variable. 00205 However, averaging dimensions may appear in any order so it is more 00206 straightforward to compare fixed dimensions to LRV input dimensions. */ 00207 for(idx=0;idx<nbr_dmn_fix;idx++) 00208 if(idx_fix_var[idx] != idx) break; 00209 if(idx == nbr_dmn_fix){ 00210 if(dbg_lvl_get() > 0) (void)fprintf(stderr,"%s: INFO Reduction dimensions are %d most-rapidly-varying (MRV) dimensions of %s. Will skip collection step and proceed straight to reduction step.\n",prg_nm_get(),dmn_avg_nbr,fix->nm); 00211 AVG_DMN_ARE_MRV=True; /* [flg] Avergaging dimensions are MRV dimensions */ 00212 } /* idx != nbr_dmn_fix */ 00213 00214 /* MRV algorithm simply skips this collection step */ 00215 if(!AVG_DMN_ARE_MRV){ 00216 /* Dreaded, expensive collection algorithm sorts input into averaging blocks */ 00217 char *avg_cp; 00218 char *var_cp; 00219 00220 int typ_sz; 00221 int nbr_dmn_var_m1; 00222 00223 long *var_cnt; 00224 long avg_lmn; 00225 long fix_lmn; 00226 long var_lmn; 00227 long dmn_ss[NC_MAX_DIMS]; 00228 long dmn_var_map[NC_MAX_DIMS]; 00229 long dmn_avg_map[NC_MAX_DIMS]; 00230 long dmn_fix_map[NC_MAX_DIMS]; 00231 00232 nbr_dmn_var_m1=nbr_dmn_var-1; 00233 typ_sz=nco_typ_lng(fix->type); 00234 var_cnt=var->cnt; 00235 var_cp=(char *)var->val.vp; 00236 avg_cp=(char *)avg_val.vp; 00237 00238 /* Compute map for each dimension of input variable */ 00239 for(idx=0;idx<nbr_dmn_var;idx++) dmn_var_map[idx]=1L; 00240 for(idx=0;idx<nbr_dmn_var-1;idx++) 00241 for(idx_dmn=idx+1;idx_dmn<nbr_dmn_var;idx_dmn++) 00242 dmn_var_map[idx]*=var->cnt[idx_dmn]; 00243 00244 /* Compute map for each dimension of output variable */ 00245 for(idx=0;idx<nbr_dmn_fix;idx++) dmn_fix_map[idx]=1L; 00246 for(idx=0;idx<nbr_dmn_fix-1;idx++) 00247 for(idx_dmn=idx+1;idx_dmn<nbr_dmn_fix;idx_dmn++) 00248 dmn_fix_map[idx]*=fix->cnt[idx_dmn]; 00249 00250 /* Compute map for each dimension of averaging buffer */ 00251 for(idx=0;idx<dmn_avg_nbr;idx++) dmn_avg_map[idx]=1L; 00252 for(idx=0;idx<dmn_avg_nbr-1;idx++) 00253 for(idx_dmn=idx+1;idx_dmn<dmn_avg_nbr;idx_dmn++) 00254 dmn_avg_map[idx]*=dmn_avg[idx_dmn]->cnt; 00255 00256 /* var_lmn is offset into 1-D array */ 00257 for(var_lmn=0;var_lmn<var_sz;var_lmn++){ 00258 /* dmn_ss are corresponding indices (subscripts) into N-D array */ 00259 /* Operations: 1 modulo, 1 pointer offset, 1 user memory fetch 00260 Repetitions: \lmnnbr 00261 Total Counts: \rthnbr=2\lmnnbr, \mmrusrnbr=\lmnnbr 00262 NB: LHS assumed compact and cached, counted RHS offsets and fetches only */ 00263 dmn_ss[nbr_dmn_var_m1]=var_lmn%var_cnt[nbr_dmn_var_m1]; 00264 for(idx=0;idx<nbr_dmn_var_m1;idx++){ 00265 /* Operations: 1 divide, 1 modulo, 2 pointer offset, 2 user memory fetch 00266 Repetitions: \lmnnbr(\dmnnbr-1) 00267 Counts: \rthnbr=4\lmnnbr(\dmnnbr-1), \mmrusrnbr=2\lmnnbr(\dmnnbr-1) 00268 NB: LHS assumed compact and cached, counted RHS offsets and fetches only 00269 NB: Neglected loop arithmetic/compare */ 00270 dmn_ss[idx]=(long)(var_lmn/dmn_var_map[idx]); 00271 dmn_ss[idx]%=var_cnt[idx]; 00272 } /* end loop over dimensions */ 00273 00274 /* Map variable's N-D array indices into a 1-D index into averaged data */ 00275 fix_lmn=0L; 00276 /* Operations: 1 add, 1 multiply, 3 pointer offset, 3 user memory fetch 00277 Repetitions: \lmnnbr(\dmnnbr-\avgnbr) 00278 Counts: \rthnbr=5\lmnnbr(\dmnnbr-\avgnbr), \mmrusrnbr=3\lmnnbr(\dmnnbr-\avgnbr) */ 00279 for(idx=0;idx<nbr_dmn_fix;idx++) fix_lmn+=dmn_ss[idx_fix_var[idx]]*dmn_fix_map[idx]; 00280 00281 /* Map N-D array indices into 1-D offset from group offset */ 00282 avg_lmn=0L; 00283 /* Operations: 1 add, 1 multiply, 3 pointer offset, 3 user memory fetch 00284 Repetitions: \lmnnbr\avgnbr 00285 Counts: \rthnbr=5\lmnnbr\avgnbr, \mmrusrnbr=3\lmnnbr\avgnbr */ 00286 for(idx=0;idx<dmn_avg_nbr;idx++) avg_lmn+=dmn_ss[idx_avg_var[idx]]*dmn_avg_map[idx]; 00287 00288 /* Copy current element in input array into its slot in sorted avg_val */ 00289 /* Operations: 3 add, 3 multiply, 0 pointer offset, 1 system memory copy 00290 Repetitions: \lmnnbr 00291 Counts: \rthnbr=6\lmnnbr, \mmrusrnbr=0, \mmrsysnbr=1 */ 00292 (void)memcpy(avg_cp+(fix_lmn*avg_sz+avg_lmn)*typ_sz,var_cp+var_lmn*typ_sz,(size_t)typ_sz); 00293 } /* end loop over var_lmn */ 00294 } /* AVG_DMN_ARE_MRV */ 00295 00296 /* Input data are now sorted and stored (in avg_val) in blocks (of length avg_sz) 00297 in same order as blocks' average values will appear in output buffer. 00298 Averaging routines can take advantage of this by casting avg_val to 00299 two dimensional variable and averaging over inner dimension. 00300 nco_var_avg_reduce_*() sets tally array */ 00301 switch(nco_op_typ){ 00302 case nco_op_max: 00303 (void)nco_var_avg_reduce_max(fix->type,var_sz,fix_sz,fix->has_mss_val,fix->mss_val,avg_val,fix->val); 00304 break; 00305 case nco_op_min: 00306 (void)nco_var_avg_reduce_min(fix->type,var_sz,fix_sz,fix->has_mss_val,fix->mss_val,avg_val,fix->val); 00307 break; 00308 case nco_op_avg: /* Operations: Previous=none, Current=sum, Next=normalize and root */ 00309 case nco_op_sqravg: /* Operations: Previous=none, Current=sum, Next=normalize and square */ 00310 case nco_op_avgsqr: /* Operations: Previous=square, Current=sum, Next=normalize */ 00311 case nco_op_rms: /* Operations: Previous=square, Current=sum, Next=normalize and root */ 00312 case nco_op_rmssdn: /* Operations: Previous=square, Current=sum, Next=normalize and root */ 00313 case nco_op_ttl: /* Operations: Previous=none, Current=sum, Next=none */ 00314 default: 00315 (void)nco_var_avg_reduce_ttl(fix->type,var_sz,fix_sz,fix->has_mss_val,fix->mss_val,fix->tally,avg_val,fix->val); 00316 break; 00317 } /* end case */ 00318 00319 /* Free dynamic memory that held rearranged input variable values */ 00320 avg_val.vp=nco_free(avg_val.vp); 00321 } /* end if avg_sz != 1 */ 00322 00323 /* Jump here when variable is not to be reduced. This occurs when 00324 1. Variable contains no averaging dimensions 00325 2. Averaging block size is 1 */ 00326 cln_and_xit: 00327 00328 /* Free input variable */ 00329 var=nco_var_free(var); 00330 dmn_avg=(dmn_sct **)nco_free(dmn_avg); 00331 dmn_fix=(dmn_sct **)nco_free(dmn_fix); 00332 00333 /* Return averaged variable */ 00334 return fix; 00335 } /* end nco_var_avg() */
|
|
||||||||||||||||||||||||||||||||
|
Definition at line 907 of file nco_var_avg.c. References cast_void_nctype(), double_CEWI, False, float_CEWI, NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT, nco_dfl_case_nc_type_err(), nco_int_CEWI, nco_typ_lng(), short_CEWI, True, and type. Referenced by nco_var_avg(), and nco_var_pck(). 00914 { 00915 /* Purpose: Find maximum value of each contiguous block of first operand and place 00916 result in corresponding element in second operand. Operands are assumed to have 00917 conforming types, but not dimensions or sizes. */ 00918 00919 /* nco_var_avg_reduce_min() is derived from nco_var_avg_reduce_ttl() 00920 Routines are very similar but tallies are not incremented 00921 See nco_var_avg_reduce_ttl() for more algorithmic documentation 00922 nco_var_avg_reduce_max() is derived from nco_var_avg_reduce_min() */ 00923 00924 #define FXM_NCO315 1 00925 #ifdef FXM_NCO315 00926 long idx_op1; 00927 #endif /* __GNUC__ */ 00928 const long sz_blk=sz_op1/sz_op2; 00929 long idx_op2; 00930 long idx_blk; 00931 00932 double mss_val_dbl=double_CEWI; 00933 float mss_val_flt=float_CEWI; 00934 nco_int mss_val_lng=nco_int_CEWI; 00935 short mss_val_sht=short_CEWI; 00936 nco_char mss_val_chr; 00937 nco_byte mss_val_byt; 00938 00939 bool flg_mss=False; 00940 00941 /* Typecast pointer to values before access */ 00942 (void)cast_void_nctype(type,&op1); 00943 (void)cast_void_nctype(type,&op2); 00944 if(has_mss_val) (void)cast_void_nctype(type,&mss_val); 00945 00946 if(has_mss_val){ 00947 switch(type){ 00948 case NC_FLOAT: mss_val_flt=*mss_val.fp; break; 00949 case NC_DOUBLE: mss_val_dbl=*mss_val.dp; break; 00950 case NC_SHORT: mss_val_sht=*mss_val.sp; break; 00951 case NC_INT: mss_val_lng=*mss_val.lp; break; 00952 case NC_BYTE: mss_val_byt=*mss_val.bp; break; 00953 case NC_CHAR: mss_val_chr=*mss_val.cp; break; 00954 default: nco_dfl_case_nc_type_err(); break; 00955 } /* end switch */ 00956 } /* endif */ 00957 00958 switch(type){ 00959 case NC_FLOAT: 00960 00961 #define FXM_NCO315 1 00962 #ifdef FXM_NCO315 00963 /* ANSI-compliant branch */ 00964 if(!has_mss_val){ 00965 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00966 const long blk_off=idx_op2*sz_blk; 00967 op2.fp[idx_op2]=op1.fp[blk_off]; 00968 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 00969 if(op2.fp[idx_op2] < op1.fp[blk_off+idx_blk]) op2.fp[idx_op2]=op1.fp[blk_off+idx_blk]; 00970 } /* end loop over idx_op2 */ 00971 }else{ 00972 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00973 const long blk_off=idx_op2*sz_blk; 00974 flg_mss=False; 00975 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00976 idx_op1=blk_off+idx_blk; 00977 if(op1.fp[idx_op1] != mss_val_flt) { 00978 if(!flg_mss || op2.fp[idx_op2] < op1.fp[idx_op1]) op2.fp[idx_op2]=op1.fp[idx_op1]; 00979 flg_mss=True; 00980 } /* end if */ 00981 } /* end loop over idx_blk */ 00982 if(!flg_mss) op2.fp[idx_op2]=mss_val_flt; 00983 } /* end loop over idx_op2 */ 00984 } /* end else */ 00985 #else /* __GNUC__ */ 00986 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 00987 if(True){ 00988 float op1_2D[sz_op2][sz_blk]; 00989 00990 (void)memcpy((void *)op1_2D,(void *)(op1.fp),sz_op1*nco_typ_lng(type)); 00991 00992 if(!has_mss_val){ 00993 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00994 op2.fp[idx_op2]=op1_2D[idx_op2][0]; 00995 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 00996 if(op2.fp[idx_op2] < op1_2D[idx_op2][idx_blk]) op2.fp[idx_op2]=op1_2D[idx_op2][idx_blk]; 00997 } /* end loop over idx_op2 */ 00998 }else{ 00999 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01000 flg_mss=False; 01001 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 01002 if(op1_2D[idx_op2][idx_blk] != mss_val_flt) { 01003 if(!flg_mss || op2.fp[idx_op2] < op1_2D[idx_op2][idx_blk]) op2.fp[idx_op2]=op1_2D[idx_op2][idx_blk]; 01004 flg_mss=True; 01005 } /* end if */ 01006 } /* end loop over idx_blk */ 01007 if(!flg_mss) op2.fp[idx_op2]=mss_val_flt; 01008 } /* end loop over idx_op2 */ 01009 } /* end else */ 01010 } /* end if */ 01011 #endif /* __GNUC__ */ 01012 01013 break; 01014 case NC_DOUBLE: 01015 01016 #define FXM_NCO315 1 01017 #ifdef FXM_NCO315 01018 /* ANSI-compliant branch */ 01019 if(!has_mss_val){ 01020 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01021 const long blk_off=idx_op2*sz_blk; 01022 op2.dp[idx_op2]=op1.dp[blk_off]; 01023 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 01024 if(op2.dp[idx_op2] < op1.dp[blk_off+idx_blk]) op2.dp[idx_op2]=op1.dp[blk_off+idx_blk]; 01025 } /* end loop over idx_op2 */ 01026 }else{ 01027 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01028 const long blk_off=idx_op2*sz_blk; 01029 flg_mss=False; 01030 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 01031 idx_op1=blk_off+idx_blk; 01032 if(op1.dp[idx_op1] != mss_val_dbl) { 01033 if(!flg_mss || (op2.dp[idx_op2] < op1.dp[idx_op1])) op2.dp[idx_op2]=op1.dp[idx_op1]; 01034 flg_mss=True; 01035 } /* end if */ 01036 } /* end loop over idx_blk */ 01037 if(!flg_mss) op2.dp[idx_op2]=mss_val_dbl; 01038 } /* end loop over idx_op2 */ 01039 } /* end else */ 01040 #else /* __GNUC__ */ 01041 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 01042 if(True){ 01043 double op1_2D[sz_op2][sz_blk]; 01044 01045 (void)memcpy((void *)op1_2D,(void *)(op1.dp),sz_op1*nco_typ_lng(type)); 01046 01047 if(!has_mss_val){ 01048 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01049 op2.dp[idx_op2]=op1_2D[idx_op2][0]; 01050 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 01051 if(op2.dp[idx_op2] < op1_2D[idx_op2][idx_blk]) op2.dp[idx_op2]=op1_2D[idx_op2][idx_blk] ; 01052 } /* end loop over idx_op2 */ 01053 }else{ 01054 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01055 flg_mss=False; 01056 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 01057 if(op1_2D[idx_op2][idx_blk] != mss_val_dbl){ 01058 if(!flg_mss || (op2.dp[idx_op2] < op1_2D[idx_op2][idx_blk])) op2.dp[idx_op2]=op1_2D[idx_op2][idx_blk]; 01059 flg_mss=True; 01060 } /* end if */ 01061 } /* end loop over idx_blk */ 01062 if(!flg_mss) op2.dp[idx_op2]=mss_val_dbl; 01063 } /* end loop over idx_op2 */ 01064 } /* end else */ 01065 } /* end if */ 01066 #endif /* __GNUC__ */ 01067 break; 01068 case NC_INT: 01069 #define FXM_NCO315 1 01070 #ifdef FXM_NCO315 01071 /* ANSI-compliant branch */ 01072 if(!has_mss_val){ 01073 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01074 const long blk_off=idx_op2*sz_blk; 01075 op2.lp[idx_op2]=op1.lp[blk_off]; 01076 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 01077 if(op2.lp[idx_op2] < op1.lp[blk_off+idx_blk]) op2.lp[idx_op2]=op1.lp[blk_off+idx_blk]; 01078 } /* end loop over idx_op2 */ 01079 }else{ 01080 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01081 const long blk_off=idx_op2*sz_blk; 01082 flg_mss=False; 01083 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 01084 idx_op1=blk_off+idx_blk; 01085 if(op1.lp[idx_op1] != mss_val_lng){ 01086 if(!flg_mss || op2.lp[idx_op2] < op1.lp[idx_op1]) op2.lp[idx_op2]=op1.lp[idx_op1]; 01087 flg_mss= True; 01088 } /* end if */ 01089 } /* end loop over idx_blk */ 01090 if(!flg_mss) op2.lp[idx_op2]=mss_val_lng; 01091 } /* end loop over idx_op2 */ 01092 } /* end else */ 01093 #else /* __GNUC__ */ 01094 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 01095 if(True){ 01096 long op1_2D[sz_op2][sz_blk]; 01097 01098 (void)memcpy((void *)op1_2D,(void *)(op1.lp),sz_op1*nco_typ_lng(type)); 01099 01100 if(!has_mss_val){ 01101 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01102 op2.lp[idx_op2]=op1_2D[idx_op2][0]; 01103 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 01104 if(op2.lp[idx_op2] < op1_2D[idx_op2][idx_blk]) op2.lp[idx_op2]=op1_2D[idx_op2][idx_blk]; 01105 } /* end loop over idx_op2 */ 01106 }else{ 01107 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01108 flg_mss=False; 01109 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 01110 if(op1_2D[idx_op2][idx_blk] != mss_val_lng){ 01111 if(!flg_mss || op2.lp[idx_op2] < op1_2D[idx_op2][idx_blk]) op2.lp[idx_op2]=op1_2D[idx_op2][idx_blk]; 01112 flg_mss=True; 01113 } /* end if */ 01114 } /* end loop over idx_blk */ 01115 if(!flg_mss) op2.lp[idx_op2]=mss_val_lng; 01116 } /* end loop over idx_op2 */ 01117 } /* end else */ 01118 } /* end if */ 01119 #endif /* __GNUC__ */ 01120 break; 01121 case NC_SHORT: 01122 #define FXM_NCO315 1 01123 #ifdef FXM_NCO315 01124 /* ANSI-compliant branch */ 01125 if(!has_mss_val){ 01126 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01127 const long blk_off=idx_op2*sz_blk; 01128 op2.sp[idx_op2]=op1.sp[blk_off]; 01129 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 01130 if(op2.sp[idx_op2] < op1.sp[blk_off+idx_blk]) op2.sp[idx_op2]=op1.sp[blk_off+idx_blk]; 01131 } /* end loop over idx_op2 */ 01132 }else{ 01133 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01134 const long blk_off=idx_op2*sz_blk; 01135 flg_mss=False; 01136 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 01137 idx_op1=blk_off+idx_blk; 01138 if(op1.sp[idx_op1] != mss_val_sht){ 01139 if(!flg_mss || op2.sp[idx_op2] < op1.sp[idx_op1]) op2.sp[idx_op2]=op1.sp[idx_op1]; 01140 flg_mss=True; 01141 } /* end if */ 01142 } /* end loop over idx_blk */ 01143 if(!flg_mss) op2.sp[idx_op2]=mss_val_sht; 01144 } /* end loop over idx_op2 */ 01145 } /* end else */ 01146 #else /* __GNUC__ */ 01147 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 01148 if(True){ 01149 short op1_2D[sz_op2][sz_blk]; 01150 01151 (void)memcpy((void *)op1_2D,(void *)(op1.sp),sz_op1*nco_typ_lng(type)); 01152 01153 if(!has_mss_val){ 01154 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01155 op2.sp[idx_op2]=op1_2D[idx_op2][0]; 01156 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 01157 if(op2.sp[idx_op2] < op1_2D[idx_op2][idx_blk]) op2.sp[idx_op2]=op1_2D[idx_op2][idx_blk]; 01158 } /* end loop over idx_op2 */ 01159 }else{ 01160 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 01161 flg_mss=False; 01162 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 01163 if(op1_2D[idx_op2][idx_blk] != mss_val_sht){ 01164 if(!flg_mss || op2.sp[idx_op2] < op1_2D[idx_op2][idx_blk]) op2.sp[idx_op2]=op1_2D[idx_op2][idx_blk]; 01165 flg_mss=True; 01166 } /* end if */ 01167 } /* end loop over idx_blk */ 01168 if(!flg_mss) op2.sp[idx_op2]=mss_val_sht; 01169 } /* end loop over idx_op2 */ 01170 } /* end else */ 01171 } /* end if */ 01172 #endif /* __GNUC__ */ 01173 break; 01174 case NC_CHAR: 01175 /* Do nothing except avoid compiler warnings */ 01176 mss_val_chr=mss_val_chr; 01177 break; 01178 case NC_BYTE: 01179 /* Do nothing except avoid compiler warnings */ 01180 mss_val_byt=mss_val_byt; 01181 break; 01182 default: nco_dfl_case_nc_type_err(); break; 01183 } /* end switch */ 01184 01185 /* NB: it is not neccessary to un-typecast pointers to values after access 01186 because we have only operated on local copies of them. */ 01187 01188 } /* end nco_var_avg_reduce_max() */
|
|
||||||||||||||||||||||||||||||||
|
Definition at line 622 of file nco_var_avg.c. References cast_void_nctype(), double_CEWI, False, float_CEWI, NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT, nco_dfl_case_nc_type_err(), nco_int_CEWI, nco_typ_lng(), short_CEWI, True, and type. Referenced by nco_var_avg(), and nco_var_pck(). 00629 { 00630 /* Purpose: Find minimum value of each contiguous block of first operand and place 00631 result in corresponding element in second operand. Operands are assumed to have 00632 conforming types, but not dimensions or sizes. */ 00633 00634 /* nco_var_avg_reduce_min() is derived from nco_var_avg_reduce_ttl() 00635 Routines are very similar but tallies are not incremented 00636 See nco_var_avg_reduce_ttl() for more algorithmic documentation 00637 nco_var_avg_reduce_max() is derived from nco_var_avg_reduce_min() */ 00638 00639 #define FXM_NCO315 1 00640 #ifdef FXM_NCO315 00641 long idx_op1; 00642 #endif /* __GNUC__ */ 00643 const long sz_blk=sz_op1/sz_op2; 00644 long idx_op2; 00645 long idx_blk; 00646 00647 double mss_val_dbl=double_CEWI; 00648 float mss_val_flt=float_CEWI; 00649 nco_int mss_val_lng=nco_int_CEWI; 00650 short mss_val_sht=short_CEWI; 00651 nco_char mss_val_chr; 00652 nco_byte mss_val_byt; 00653 00654 bool flg_mss=False; /* [flg] Block has valid (non-missing) values */ 00655 00656 /* Typecast pointer to values before access */ 00657 (void)cast_void_nctype(type,&op1); 00658 (void)cast_void_nctype(type,&op2); 00659 if(has_mss_val) (void)cast_void_nctype(type,&mss_val); 00660 00661 if(has_mss_val){ 00662 switch(type){ 00663 case NC_FLOAT: mss_val_flt=*mss_val.fp; break; 00664 case NC_DOUBLE: mss_val_dbl=*mss_val.dp; break; 00665 case NC_SHORT: mss_val_sht=*mss_val.sp; break; 00666 case NC_INT: mss_val_lng=*mss_val.lp; break; 00667 case NC_BYTE: mss_val_byt=*mss_val.bp; break; 00668 case NC_CHAR: mss_val_chr=*mss_val.cp; break; 00669 default: nco_dfl_case_nc_type_err(); break; 00670 } /* end switch */ 00671 } /* endif */ 00672 00673 switch(type){ 00674 case NC_FLOAT: 00675 00676 #define FXM_NCO315 1 00677 #ifdef FXM_NCO315 00678 /* ANSI-compliant branch */ 00679 if(!has_mss_val){ 00680 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00681 const long blk_off=idx_op2*sz_blk; 00682 op2.fp[idx_op2]=op1.fp[blk_off]; 00683 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 00684 if(op2.fp[idx_op2] > op1.fp[blk_off+idx_blk]) op2.fp[idx_op2]=op1.fp[blk_off+idx_blk]; 00685 } /* end loop over idx_op2 */ 00686 }else{ 00687 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00688 const long blk_off=idx_op2*sz_blk; 00689 flg_mss=False; 00690 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00691 idx_op1=blk_off+idx_blk; 00692 if(op1.fp[idx_op1] != mss_val_flt) { 00693 if(!flg_mss || op2.fp[idx_op2] > op1.fp[idx_op1]) op2.fp[idx_op2]=op1.fp[idx_op1]; 00694 flg_mss=True; 00695 } /* end if */ 00696 } /* end loop over idx_blk */ 00697 if(!flg_mss) op2.fp[idx_op2]=mss_val_flt; 00698 } /* end loop over idx_op2 */ 00699 } /* end else */ 00700 #else /* __GNUC__ */ 00701 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 00702 if(True){ 00703 float op1_2D[sz_op2][sz_blk]; 00704 00705 (void)memcpy((void *)op1_2D,(void *)(op1.fp),sz_op1*nco_typ_lng(type)); 00706 00707 if(!has_mss_val){ 00708 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00709 op2.fp[idx_op2]=op1_2D[idx_op2][0]; 00710 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 00711 if(op2.fp[idx_op2] > op1_2D[idx_op2][idx_blk]) op2.fp[idx_op2]=op1_2D[idx_op2][idx_blk]; 00712 } /* end loop over idx_op2 */ 00713 }else{ 00714 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00715 flg_mss=False; 00716 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00717 if(op1_2D[idx_op2][idx_blk] != mss_val_flt) { 00718 if(!flg_mss || op2.fp[idx_op2] > op1_2D[idx_op2][idx_blk]) op2.fp[idx_op2]=op1_2D[idx_op2][idx_blk]; 00719 flg_mss=True; 00720 } /* end if */ 00721 } /* end loop over idx_blk */ 00722 if(!flg_mss) op2.fp[idx_op2]=mss_val_flt; 00723 } /* end loop over idx_op2 */ 00724 } /* end else */ 00725 } /* end if */ 00726 #endif /* __GNUC__ */ 00727 00728 break; 00729 case NC_DOUBLE: 00730 00731 #define FXM_NCO315 1 00732 #ifdef FXM_NCO315 00733 /* ANSI-compliant branch */ 00734 if(!has_mss_val){ 00735 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00736 const long blk_off=idx_op2*sz_blk; 00737 op2.dp[idx_op2]=op1.dp[blk_off]; 00738 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 00739 if(op2.dp[idx_op2] > op1.dp[blk_off+idx_blk]) op2.dp[idx_op2]=op1.dp[blk_off+idx_blk]; 00740 } /* end loop over idx_op2 */ 00741 }else{ 00742 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00743 const long blk_off=idx_op2*sz_blk; 00744 flg_mss=False; 00745 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00746 idx_op1=blk_off+idx_blk; 00747 if(op1.dp[idx_op1] != mss_val_dbl) { 00748 if(!flg_mss || (op2.dp[idx_op2] > op1.dp[idx_op1])) op2.dp[idx_op2]=op1.dp[idx_op1]; 00749 flg_mss=True; 00750 } /* end if */ 00751 } /* end loop over idx_blk */ 00752 if(!flg_mss) op2.dp[idx_op2]=mss_val_dbl; 00753 } /* end loop over idx_op2 */ 00754 } /* end else */ 00755 #else /* __GNUC__ */ 00756 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 00757 if(True){ 00758 double op1_2D[sz_op2][sz_blk]; 00759 00760 (void)memcpy((void *)op1_2D,(void *)(op1.dp),sz_op1*nco_typ_lng(type)); 00761 00762 if(!has_mss_val){ 00763 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00764 op2.dp[idx_op2]=op1_2D[idx_op2][0]; 00765 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 00766 if(op2.dp[idx_op2] > op1_2D[idx_op2][idx_blk]) op2.dp[idx_op2]=op1_2D[idx_op2][idx_blk] ; 00767 } /* end loop over idx_op2 */ 00768 }else{ 00769 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00770 flg_mss=False; 00771 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00772 if(op1_2D[idx_op2][idx_blk] != mss_val_dbl){ 00773 if(!flg_mss || (op2.dp[idx_op2] > op1_2D[idx_op2][idx_blk])) op2.dp[idx_op2]=op1_2D[idx_op2][idx_blk]; 00774 flg_mss=True; 00775 } /* end if */ 00776 } /* end loop over idx_blk */ 00777 if(!flg_mss) op2.dp[idx_op2]=mss_val_dbl; 00778 } /* end loop over idx_op2 */ 00779 } /* end else */ 00780 } /* end if */ 00781 #endif /* __GNUC__ */ 00782 break; 00783 case NC_INT: 00784 #define FXM_NCO315 1 00785 #ifdef FXM_NCO315 00786 /* ANSI-compliant branch */ 00787 if(!has_mss_val){ 00788 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00789 const long blk_off=idx_op2*sz_blk; 00790 op2.lp[idx_op2]=op1.lp[blk_off]; 00791 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 00792 if(op2.lp[idx_op2] > op1.lp[blk_off+idx_blk]) op2.lp[idx_op2]=op1.lp[blk_off+idx_blk]; 00793 } /* end loop over idx_op2 */ 00794 }else{ 00795 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00796 const long blk_off=idx_op2*sz_blk; 00797 flg_mss=False; 00798 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00799 idx_op1=blk_off+idx_blk; 00800 if(op1.lp[idx_op1] != mss_val_lng){ 00801 if(!flg_mss || op2.lp[idx_op2] > op1.lp[idx_op1]) op2.lp[idx_op2]=op1.lp[idx_op1]; 00802 flg_mss= True; 00803 } /* end if */ 00804 } /* end loop over idx_blk */ 00805 if(!flg_mss) op2.lp[idx_op2]=mss_val_lng; 00806 } /* end loop over idx_op2 */ 00807 } /* end else */ 00808 #else /* __GNUC__ */ 00809 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 00810 if(True){ 00811 long op1_2D[sz_op2][sz_blk]; 00812 00813 (void)memcpy((void *)op1_2D,(void *)(op1.lp),sz_op1*nco_typ_lng(type)); 00814 00815 if(!has_mss_val){ 00816 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00817 op2.lp[idx_op2]=op1_2D[idx_op2][0]; 00818 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 00819 if(op2.lp[idx_op2] > op1_2D[idx_op2][idx_blk]) op2.lp[idx_op2]=op1_2D[idx_op2][idx_blk]; 00820 } /* end loop over idx_op2 */ 00821 }else{ 00822 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00823 flg_mss=False; 00824 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00825 if(op1_2D[idx_op2][idx_blk] != mss_val_lng){ 00826 if(!flg_mss || op2.lp[idx_op2] > op1_2D[idx_op2][idx_blk]) op2.lp[idx_op2]=op1_2D[idx_op2][idx_blk]; 00827 flg_mss=True; 00828 } /* end if */ 00829 } /* end loop over idx_blk */ 00830 if(!flg_mss) op2.lp[idx_op2]=mss_val_lng; 00831 } /* end loop over idx_op2 */ 00832 } /* end else */ 00833 } /* end if */ 00834 #endif /* __GNUC__ */ 00835 break; 00836 case NC_SHORT: 00837 #define FXM_NCO315 1 00838 #ifdef FXM_NCO315 00839 /* ANSI-compliant branch */ 00840 if(!has_mss_val){ 00841 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00842 const long blk_off=idx_op2*sz_blk; 00843 op2.sp[idx_op2]=op1.sp[blk_off]; 00844 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 00845 if(op2.sp[idx_op2] > op1.sp[blk_off+idx_blk]) op2.sp[idx_op2]=op1.sp[blk_off+idx_blk]; 00846 } /* end loop over idx_op2 */ 00847 }else{ 00848 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00849 const long blk_off=idx_op2*sz_blk; 00850 flg_mss=False; 00851 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00852 idx_op1=blk_off+idx_blk; 00853 if(op1.sp[idx_op1] != mss_val_sht){ 00854 if(!flg_mss || op2.sp[idx_op2] > op1.sp[idx_op1]) op2.sp[idx_op2]=op1.sp[idx_op1]; 00855 flg_mss=True; 00856 } /* end if */ 00857 } /* end loop over idx_blk */ 00858 if(!flg_mss) op2.sp[idx_op2]=mss_val_sht; 00859 } /* end loop over idx_op2 */ 00860 } /* end else */ 00861 #else /* __GNUC__ */ 00862 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 00863 if(True){ 00864 short op1_2D[sz_op2][sz_blk]; 00865 00866 (void)memcpy((void *)op1_2D,(void *)(op1.sp),sz_op1*nco_typ_lng(type)); 00867 00868 if(!has_mss_val){ 00869 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00870 op2.sp[idx_op2]=op1_2D[idx_op2][0]; 00871 for(idx_blk=1;idx_blk<sz_blk;idx_blk++) 00872 if(op2.sp[idx_op2] > op1_2D[idx_op2][idx_blk]) op2.sp[idx_op2]=op1_2D[idx_op2][idx_blk]; 00873 } /* end loop over idx_op2 */ 00874 }else{ 00875 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00876 flg_mss=False; 00877 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00878 if(op1_2D[idx_op2][idx_blk] != mss_val_sht){ 00879 if(!flg_mss || op2.sp[idx_op2] > op1_2D[idx_op2][idx_blk]) op2.sp[idx_op2]=op1_2D[idx_op2][idx_blk]; 00880 flg_mss=True; 00881 } /* end if */ 00882 } /* end loop over idx_blk */ 00883 if(!flg_mss) op2.sp[idx_op2]=mss_val_sht; 00884 } /* end loop over idx_op2 */ 00885 } /* end else */ 00886 } /* end if */ 00887 #endif /* __GNUC__ */ 00888 break; 00889 case NC_CHAR: 00890 /* Do nothing except avoid compiler warnings */ 00891 mss_val_chr=mss_val_chr; 00892 break; 00893 case NC_BYTE: 00894 /* Do nothing except avoid compiler warnings */ 00895 mss_val_byt=mss_val_byt; 00896 break; 00897 default: nco_dfl_case_nc_type_err(); break; 00898 } /* end switch */ 00899 00900 /* NB: it is not neccessary to un-typecast pointers to values after access 00901 because we have only operated on local copies of them. */ 00902 00903 } /* end nco_var_avg_reduce_min() */
|
|
||||||||||||||||||||||||||||||||||||
|
Definition at line 339 of file nco_var_avg.c. References cast_void_nctype(), double_CEWI, float_CEWI, NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT, nco_dfl_case_nc_type_err(), nco_int_CEWI, nco_typ_lng(), short_CEWI, True, and type. Referenced by nco_var_avg(). 00347 { 00348 /* Threads: Routine is thread safe and calls no unsafe routines */ 00349 /* Purpose: Sum values in each contiguous block of first operand and place 00350 result in corresponding element in second operand. 00351 Currently arithmetic operation performed is summation of elements in op1 00352 Input operands are assumed to have conforming types, but not dimensions or sizes 00353 nco_var_avg_reduce() knows nothing about dimensions 00354 Routine is one dimensional array operator acting serially on each element of input buffer op1 00355 Calling rouine knows exactly how rank of output, op2, is reduced from rank of input 00356 Routine only does summation rather than averaging in order to remain flexible 00357 Operations which require normalization, e.g., averaging, must call nco_var_nrm() 00358 or nco_var_dvd() to divide sum set in this routine by tally set in this routine. */ 00359 00360 /* Each operation has GNUC and non-GNUC blocks: 00361 GNUC: Utilize (non-ANSI-compliant) compiler support for local automatic arrays 00362 This results in more elegent loop structure and, theoretically, in faster performance 00363 20040225: In reality, the GNUC non-ANSI blocks fail on some large files 00364 This may be because they allocate significant local storage on the stack 00365 00366 non-GNUC: Fully ANSI-compliant structure 00367 Fortran: Support deprecated */ 00368 00369 #define FXM_NCO315 1 00370 #ifdef FXM_NCO315 00371 long idx_op1; 00372 #endif /* __GNUC__ */ 00373 const long sz_blk=sz_op1/sz_op2; 00374 long idx_op2; 00375 long idx_blk; 00376 double mss_val_dbl=double_CEWI; 00377 float mss_val_flt=float_CEWI; 00378 nco_char mss_val_chr; 00379 nco_byte mss_val_byt; 00380 nco_int mss_val_lng=nco_int_CEWI; 00381 short mss_val_sht=short_CEWI; 00382 00383 /* Typecast pointer to values before access */ 00384 (void)cast_void_nctype(type,&op1); 00385 (void)cast_void_nctype(type,&op2); 00386 if(has_mss_val) (void)cast_void_nctype(type,&mss_val); 00387 00388 if(has_mss_val){ 00389 switch(type){ 00390 case NC_FLOAT: mss_val_flt=*mss_val.fp; break; 00391 case NC_DOUBLE: mss_val_dbl=*mss_val.dp; break; 00392 case NC_SHORT: mss_val_sht=*mss_val.sp; break; 00393 case NC_INT: mss_val_lng=*mss_val.lp; break; 00394 case NC_BYTE: mss_val_byt=*mss_val.bp; break; 00395 case NC_CHAR: mss_val_chr=*mss_val.cp; break; 00396 default: nco_dfl_case_nc_type_err(); break; 00397 } /* end switch */ 00398 } /* endif */ 00399 00400 switch(type){ 00401 case NC_FLOAT: 00402 #define FXM_NCO315 1 00403 #ifdef FXM_NCO315 00404 /* ANSI-compliant branch */ 00405 if(!has_mss_val){ 00406 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00407 /* Operations: 1 multiply 00408 Repetitions: \dmnszavg^(\dmnnbr-\avgnbr) 00409 Total Counts: \rthnbr=\dmnszavg^(\dmnnbr-\avgnbr) */ 00410 const long blk_off=idx_op2*sz_blk; 00411 /* Operations: 1 fp add, 3 pointer offsets, 3 user memory fetch 00412 Repetitions: \lmnnbr 00413 Total Counts: \flpnbr=\lmnnbr, \rthnbr=3\lmnnbr, \mmrusrnbr=3\lmnnbr, 00414 NB: Counted LHS+RHS+tally offsets and fetches */ 00415 for(idx_blk=0;idx_blk<sz_blk;idx_blk++) op2.fp[idx_op2]+=op1.fp[blk_off+idx_blk]; 00416 tally[idx_op2]=sz_blk; 00417 } /* end loop over idx_op2 */ 00418 }else{ 00419 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00420 const long blk_off=idx_op2*sz_blk; 00421 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00422 idx_op1=blk_off+idx_blk; 00423 if(op1.fp[idx_op1] != mss_val_flt){ 00424 op2.fp[idx_op2]+=op1.fp[idx_op1]; 00425 tally[idx_op2]++; 00426 } /* end if */ 00427 } /* end loop over idx_blk */ 00428 if(tally[idx_op2] == 0L) op2.fp[idx_op2]=mss_val_flt; 00429 } /* end loop over idx_op2 */ 00430 } /* end else */ 00431 #else /* __GNUC__ */ 00432 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 00433 if(True){ 00434 float op1_2D[sz_op2][sz_blk]; 00435 00436 (void)memcpy((void *)op1_2D,(void *)(op1.fp),sz_op1*nco_typ_lng(type)); 00437 00438 if(!has_mss_val){ 00439 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00440 for(idx_blk=0;idx_blk<sz_blk;idx_blk++) op2.fp[idx_op2]+=op1_2D[idx_op2][idx_blk]; 00441 tally[idx_op2]=sz_blk; 00442 } /* end loop over idx_op2 */ 00443 }else{ 00444 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00445 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00446 if(op1_2D[idx_op2][idx_blk] != mss_val_flt){ 00447 op2.fp[idx_op2]+=op1_2D[idx_op2][idx_blk]; 00448 tally[idx_op2]++; 00449 } /* end if */ 00450 } /* end loop over idx_blk */ 00451 if(tally[idx_op2] == 0L) op2.fp[idx_op2]=mss_val_flt; 00452 } /* end loop over idx_op2 */ 00453 } /* end else */ 00454 } /* end if */ 00455 #endif /* __GNUC__ */ 00456 break; 00457 case NC_DOUBLE: 00458 #define FXM_NCO315 1 00459 #ifdef FXM_NCO315 00460 /* ANSI-compliant branch */ 00461 if(!has_mss_val){ 00462 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00463 const long blk_off=idx_op2*sz_blk; 00464 for(idx_blk=0;idx_blk<sz_blk;idx_blk++) op2.dp[idx_op2]+=op1.dp[blk_off+idx_blk]; 00465 tally[idx_op2]=sz_blk; 00466 } /* end loop over idx_op2 */ 00467 }else{ 00468 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00469 const long blk_off=idx_op2*sz_blk; 00470 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00471 idx_op1=blk_off+idx_blk; 00472 if(op1.dp[idx_op1] != mss_val_dbl){ 00473 op2.dp[idx_op2]+=op1.dp[idx_op1]; 00474 tally[idx_op2]++; 00475 } /* end if */ 00476 } /* end loop over idx_blk */ 00477 if(tally[idx_op2] == 0L) op2.dp[idx_op2]=mss_val_dbl; 00478 } /* end loop over idx_op2 */ 00479 } /* end else */ 00480 #else /* __GNUC__ */ 00481 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 00482 if(True){ 00483 double op1_2D[sz_op2][sz_blk]; 00484 00485 (void)memcpy((void *)op1_2D,(void *)(op1.dp),sz_op1*nco_typ_lng(type)); 00486 00487 if(!has_mss_val){ 00488 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00489 for(idx_blk=0;idx_blk<sz_blk;idx_blk++) op2.dp[idx_op2]+=op1_2D[idx_op2][idx_blk]; 00490 tally[idx_op2]=sz_blk; 00491 } /* end loop over idx_op2 */ 00492 }else{ 00493 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00494 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00495 if(op1_2D[idx_op2][idx_blk] != mss_val_dbl){ 00496 op2.dp[idx_op2]+=op1_2D[idx_op2][idx_blk]; 00497 tally[idx_op2]++; 00498 } /* end if */ 00499 } /* end loop over idx_blk */ 00500 if(tally[idx_op2] == 0L) op2.dp[idx_op2]=mss_val_dbl; 00501 } /* end loop over idx_op2 */ 00502 } /* end else */ 00503 } /* end if */ 00504 #endif /* __GNUC__ */ 00505 break; 00506 case NC_INT: 00507 #define FXM_NCO315 1 00508 #ifdef FXM_NCO315 00509 /* ANSI-compliant branch */ 00510 if(!has_mss_val){ 00511 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00512 const long blk_off=idx_op2*sz_blk; 00513 for(idx_blk=0;idx_blk<sz_blk;idx_blk++) op2.lp[idx_op2]+=op1.lp[blk_off+idx_blk]; 00514 tally[idx_op2]=sz_blk; 00515 } /* end loop over idx_op2 */ 00516 }else{ 00517 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00518 const long blk_off=idx_op2*sz_blk; 00519 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00520 idx_op1=blk_off+idx_blk; 00521 if(op1.lp[idx_op1] != mss_val_lng){ 00522 op2.lp[idx_op2]+=op1.lp[idx_op1]; 00523 tally[idx_op2]++; 00524 } /* end if */ 00525 } /* end loop over idx_blk */ 00526 if(tally[idx_op2] == 0L) op2.lp[idx_op2]=mss_val_lng; 00527 } /* end loop over idx_op2 */ 00528 } /* end else */ 00529 #else /* __GNUC__ */ 00530 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 00531 if(True){ 00532 long op1_2D[sz_op2][sz_blk]; 00533 00534 (void)memcpy((void *)op1_2D,(void *)(op1.lp),sz_op1*nco_typ_lng(type)); 00535 00536 if(!has_mss_val){ 00537 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00538 for(idx_blk=0;idx_blk<sz_blk;idx_blk++) op2.lp[idx_op2]+=op1_2D[idx_op2][idx_blk]; 00539 tally[idx_op2]=sz_blk; 00540 } /* end loop over idx_op2 */ 00541 }else{ 00542 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00543 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00544 if(op1_2D[idx_op2][idx_blk] != mss_val_lng){ 00545 op2.lp[idx_op2]+=op1_2D[idx_op2][idx_blk]; 00546 tally[idx_op2]++; 00547 } /* end if */ 00548 } /* end loop over idx_blk */ 00549 if(tally[idx_op2] == 0L) op2.lp[idx_op2]=mss_val_lng; 00550 } /* end loop over idx_op2 */ 00551 } /* end else */ 00552 } /* end if */ 00553 #endif /* __GNUC__ */ 00554 break; 00555 case NC_SHORT: 00556 #define FXM_NCO315 1 00557 #ifdef FXM_NCO315 00558 /* ANSI-compliant branch */ 00559 if(!has_mss_val){ 00560 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00561 const long blk_off=idx_op2*sz_blk; 00562 for(idx_blk=0;idx_blk<sz_blk;idx_blk++) op2.sp[idx_op2]+=op1.sp[blk_off+idx_blk]; 00563 tally[idx_op2]=sz_blk; 00564 } /* end loop over idx_op2 */ 00565 }else{ 00566 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00567 const long blk_off=idx_op2*sz_blk; 00568 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00569 idx_op1=blk_off+idx_blk; 00570 if(op1.sp[idx_op1] != mss_val_sht){ 00571 op2.sp[idx_op2]+=op1.sp[idx_op1]; 00572 tally[idx_op2]++; 00573 } /* end if */ 00574 } /* end loop over idx_blk */ 00575 if(tally[idx_op2] == 0L) op2.sp[idx_op2]=mss_val_sht; 00576 } /* end loop over idx_op2 */ 00577 } /* end else */ 00578 #else /* __GNUC__ */ 00579 /* Compiler supports local automatic arrays. Not ANSI-compliant, but more elegant. */ 00580 if(True){ 00581 short op1_2D[sz_op2][sz_blk]; 00582 00583 (void)memcpy((void *)op1_2D,(void *)(op1.sp),sz_op1*nco_typ_lng(type)); 00584 00585 if(!has_mss_val){ 00586 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00587 for(idx_blk=0;idx_blk<sz_blk;idx_blk++) op2.sp[idx_op2]+=op1_2D[idx_op2][idx_blk]; 00588 tally[idx_op2]=sz_blk; 00589 } /* end loop over idx_op2 */ 00590 }else{ 00591 for(idx_op2=0;idx_op2<sz_op2;idx_op2++){ 00592 for(idx_blk=0;idx_blk<sz_blk;idx_blk++){ 00593 if(op1_2D[idx_op2][idx_blk] != mss_val_sht){ 00594 op2.sp[idx_op2]+=op1_2D[idx_op2][idx_blk]; 00595 tally[idx_op2]++; 00596 } /* end if */ 00597 } /* end loop over idx_blk */ 00598 if(tally[idx_op2] == 0L) op2.sp[idx_op2]=mss_val_sht; 00599 } /* end loop over idx_op2 */ 00600 } /* end else */ 00601 } /* end if */ 00602 #endif /* __GNUC__ */ 00603 break; 00604 case NC_CHAR: 00605 /* Do nothing except avoid compiler warnings */ 00606 mss_val_chr=mss_val_chr; 00607 break; 00608 case NC_BYTE: 00609 /* Do nothing except avoid compiler warnings */ 00610 mss_val_byt=mss_val_byt; 00611 break; 00612 default: nco_dfl_case_nc_type_err(); break; 00613 } /* end switch */ 00614 00615 /* NB: it is not neccessary to un-typecast pointers to values after access 00616 because we have only operated on local copies of them. */ 00617 00618 } /* end nco_var_avg_reduce_ttl() */
|
1.4.4