nco/nco_mss_val.h File Reference

#include <stdio.h>
#include <string.h>
#include <netcdf.h>
#include "nco_netcdf.h"
#include "nco.h"
#include "nco_cnf_typ.h"
#include "nco_mmr.h"
#include "nco_prn.h"
#include "nco_sng_utl.h"

Include dependency graph for nco_mss_val.h:

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

Go to the source code of this file.

Functions

ptr_unn nco_mss_val_mk (const nc_type type)
bool nco_mss_val_cnf (var_sct *const var1, var_sct *const var2)
void nco_mss_val_cp (const var_sct *const var1, var_sct *const var2)
int nco_mss_val_get (const int nc_id, var_sct *const var)


Function Documentation

bool nco_mss_val_cnf var_sct *const   var1,
var_sct *const   var2
 

Definition at line 44 of file nco_mss_val.c.

References ptr_unn::bp, cast_nctype_void(), cast_void_nctype(), ptr_unn::cp, ptr_unn::dp, False, ptr_unn::fp, var_sct_tag::has_mss_val, long_CEWI, ptr_unn::lp, var_sct_tag::mss_val, NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_INT, NC_NAT, NC_SHORT, nco_dfl_case_nc_type_err(), NCO_MAX_LEN_FMT_SNG, nco_mss_val_cp(), nco_typ_fmt_sng(), nco_typ_sng(), var_sct_tag::nm, prg_nm_get(), ptr_unn::sp, and var_sct_tag::type.

Referenced by main(), and VarOp< T >::var_var_op().

00046 {
00047   /* Purpose: 
00048      1. Change missing_value of var2 to missing_value of var1 when both exist 
00049      2. Change missing_value of var1 to missing_value of var2 when only var2 has a missing_value
00050      3. Change missing_value of var2 to missing_value of var1 when only var1 has a missing_value
00051      4. Return false when neither operand has missing value */
00052   int has_mss_val=False; /* [flg] One or both operands have missing value */
00053   bool MSS_VAL_EQL=False; /* [flg] Missing values of input operands are identical */
00054   long idx;
00055   long var_sz=long_CEWI;
00056   nc_type var_typ=NC_NAT; /* CEWI [enm] Type of input values */
00057   ptr_unn var_val;
00058 
00059   has_mss_val=var1->has_mss_val || var2->has_mss_val; 
00060 
00061   /* No missing values */
00062   if(!var1->has_mss_val && !var2->has_mss_val) return has_mss_val;
00063 
00064   if(var1->has_mss_val && var2->has_mss_val){
00065     var_typ=var1->type;
00066     (void)cast_void_nctype(var_typ,&var1->mss_val);
00067     (void)cast_void_nctype(var_typ,&var2->mss_val);
00068     switch(var_typ){
00069     case NC_FLOAT: MSS_VAL_EQL=(*var1->mss_val.fp == *var2->mss_val.fp); break;
00070     case NC_DOUBLE: MSS_VAL_EQL=(*var1->mss_val.dp == *var2->mss_val.dp); break;
00071     case NC_INT: MSS_VAL_EQL=(*var1->mss_val.lp == *var2->mss_val.lp); break;
00072     case NC_SHORT: MSS_VAL_EQL=(*var1->mss_val.sp == *var2->mss_val.sp); break;
00073     case NC_CHAR: MSS_VAL_EQL=(*var1->mss_val.cp == *var2->mss_val.cp); break;
00074     case NC_BYTE: MSS_VAL_EQL=(*var1->mss_val.bp == *var2->mss_val.bp); break;
00075     default: nco_dfl_case_nc_type_err(); break;
00076     } /* end switch */
00077     if(!MSS_VAL_EQL){
00078       /* World's most anally formatted warning message... */
00079       char mss_val_1_sng[NCO_MAX_LEN_FMT_SNG];
00080       char mss_val_2_sng[NCO_MAX_LEN_FMT_SNG];
00081       char *fmt_sng;
00082       fmt_sng=nco_typ_fmt_sng(var1->type);
00083       switch(var1->type){
00084       case NC_FLOAT: (void)sprintf(mss_val_1_sng,fmt_sng,var1->mss_val.fp[0]); break;
00085       case NC_DOUBLE: (void)sprintf(mss_val_1_sng,fmt_sng,var1->mss_val.dp[0]); break;
00086       case NC_SHORT: (void)sprintf(mss_val_1_sng,fmt_sng,var1->mss_val.sp[0]); break;
00087       case NC_INT: (void)sprintf(mss_val_1_sng,fmt_sng,var1->mss_val.lp[0]); break;
00088       case NC_CHAR: (void)sprintf(mss_val_1_sng,fmt_sng,var1->mss_val.cp[0]); break;
00089       case NC_BYTE: (void)sprintf(mss_val_1_sng,fmt_sng,var1->mss_val.bp[0]); break;
00090       default: nco_dfl_case_nc_type_err(); break;
00091       } /* end switch */
00092       fmt_sng=nco_typ_fmt_sng(var2->type);
00093       switch(var2->type){
00094       case NC_FLOAT: (void)sprintf(mss_val_2_sng,fmt_sng,var2->mss_val.fp[0]); break;
00095       case NC_DOUBLE: (void)sprintf(mss_val_2_sng,fmt_sng,var2->mss_val.dp[0]); break;
00096       case NC_SHORT: (void)sprintf(mss_val_2_sng,fmt_sng,var2->mss_val.sp[0]); break;
00097       case NC_INT: (void)sprintf(mss_val_2_sng,fmt_sng,var2->mss_val.lp[0]); break;
00098       case NC_CHAR: (void)sprintf(mss_val_2_sng,fmt_sng,var2->mss_val.cp[0]); break;
00099       case NC_BYTE: (void)sprintf(mss_val_2_sng,fmt_sng,var2->mss_val.bp[0]); break;
00100       default: nco_dfl_case_nc_type_err(); break;
00101       } /* end switch */
00102       (void)fprintf(stderr,"%s: WARNING Input variables have different missing_value's:\nFile 1 variable %s has missing_value type = %s, value = %s\nFile 2 variable %s has missing_value type = %s, value = %s\nFile 3 variable %s will have missing_value type = %s, value = %s\nWill translate values of var2 equaling mss_val2 to mss_val1 before arithmetic operation\n",prg_nm_get(),var1->nm,nco_typ_sng(var1->type),mss_val_1_sng,var2->nm,nco_typ_sng(var2->type),mss_val_2_sng,var1->nm,nco_typ_sng(var1->type),mss_val_1_sng);
00103     } /* MSS_VAL_EQL */
00104     (void)cast_nctype_void(var_typ,&var1->mss_val);
00105     (void)cast_nctype_void(var_typ,&var2->mss_val);
00106     
00107     /* Missing values are already equal */
00108     if(MSS_VAL_EQL) return has_mss_val;
00109     
00110     /* If both files have missing_value's and they differ,
00111        must translate mss_val_2 in var2 to mss_val_1 before binary operation.
00112        Otherwise mss_val_2 would be treated as regular value in var_2
00113        Unfixable bug is when var1 has mss_val1 and var2 does not have a missing_value
00114        Then var2 values that happen to equal mss_val1 are treated as missing_values
00115        A generic, satisfactory solution to this problem does not exist 
00116        Picking missing_values that are nearly out-of-range is best workaround
00117        The user must be smart enough to do this, NCO cannot help */
00118     
00119     /* Typecast pointer to values before access */
00120     (void)cast_void_nctype(var_typ,&var1->mss_val);
00121     (void)cast_void_nctype(var_typ,&var2->mss_val);
00122     (void)cast_void_nctype(var_typ,&var2->val);
00123     
00124     /* Shortcuts to avoid indirection */
00125     var_val=var2->val;
00126     var_sz=var2->sz;
00127     switch(var_typ){
00128     case NC_FLOAT: {
00129       const float mss_val_1_flt=*var1->mss_val.fp;
00130       const float mss_val_2_flt=*var2->mss_val.fp; 
00131       for(idx=0L;idx<var_sz;idx++) if(var_val.fp[idx] == mss_val_2_flt) var_val.fp[idx]=mss_val_1_flt;
00132     } break;
00133     case NC_DOUBLE: {
00134       const double mss_val_1_dbl=*var1->mss_val.dp;
00135       const double mss_val_2_dbl=*var2->mss_val.dp; 
00136       for(idx=0L;idx<var_sz;idx++) if(var_val.dp[idx] == mss_val_2_dbl) var_val.dp[idx]=mss_val_1_dbl;
00137     } break;
00138     case NC_INT: {
00139       const nco_int mss_val_1_lng=*var1->mss_val.lp;
00140       const nco_int mss_val_2_lng=*var2->mss_val.lp; 
00141       for(idx=0L;idx<var_sz;idx++) if(var_val.lp[idx] == mss_val_2_lng) var_val.lp[idx]=mss_val_1_lng;
00142     } break;
00143     case NC_SHORT: {
00144       const short mss_val_1_sht=*var1->mss_val.sp;
00145       const short mss_val_2_sht=*var2->mss_val.sp; 
00146       for(idx=0L;idx<var_sz;idx++) if(var_val.sp[idx] == mss_val_2_sht) var_val.sp[idx]=mss_val_1_sht; 
00147     } break;
00148     case NC_CHAR: {
00149       const nco_char mss_val_1_chr=*var1->mss_val.cp;
00150       const nco_char mss_val_2_chr=*var2->mss_val.cp; 
00151       for(idx=0L;idx<var_sz;idx++) if(var_val.cp[idx] == mss_val_2_chr) var_val.cp[idx]=mss_val_1_chr; 
00152     } break;
00153     case NC_BYTE: {
00154       const nco_byte mss_val_1_byt=*var1->mss_val.bp;
00155       const nco_byte mss_val_2_byt=*var2->mss_val.bp; 
00156       for(idx=0L;idx<var_sz;idx++) if(var_val.bp[idx] == mss_val_2_byt) var_val.bp[idx]=mss_val_1_byt; 
00157     } break;
00158     default: nco_dfl_case_nc_type_err(); break;
00159     } /* end switch */
00160 
00161     /* Un-typecast the pointer to values after access */
00162     (void)cast_nctype_void(var_typ,&var2->val);
00163     (void)cast_nctype_void(var_typ,&var1->mss_val);
00164     (void)cast_nctype_void(var_typ,&var2->mss_val);
00165   
00166   } /* end if both variables have missing values */
00167   
00168   /* Handle cases where only one variable has missing value.
00169      First, if var2 has missing_value and var1 does not,
00170      then copy missing_value from var2 to var1 to ensure binary arithmetic 
00171      (which uses var1's missing_value) handles missing_value's correctly
00172      Assume var1 and var2 already have same type */
00173   if(!var1->has_mss_val && var2->has_mss_val) (void)nco_mss_val_cp(var2,var1);
00174   if(var1->has_mss_val && !var2->has_mss_val) (void)nco_mss_val_cp(var1,var2);
00175   
00176   return has_mss_val;
00177 } /* end nco_mss_val_cnf() */

void nco_mss_val_cp const var_sct *const   var1,
var_sct *const   var2
 

Definition at line 181 of file nco_mss_val.c.

References False, var_sct_tag::has_mss_val, var_sct_tag::mss_val, nco_realloc(), nco_typ_lng(), nco_val_cnf_typ(), True, and var_sct_tag::type.

Referenced by main(), and nco_mss_val_cnf().

00183 {
00184   /* Threads: Routine is thread safe and calls no unsafe routines */
00185   /* Purpose: Copy missing value from var1 to var2
00186      On exit, var2 contains has_mss_val, and mss_val identical to var1
00187      Type of mss_val in var2 will agree with type of var2
00188      This maintains assumed consistency between type of variable and type of mss_val in all var_sct's */
00189 
00190   if(!var1->has_mss_val){
00191     var2->has_mss_val=False;
00192     if(var2->mss_val.vp != NULL) free(var2->mss_val.vp);
00193   }else{ /* endif no mss_val in var1 */
00194     var2->mss_val.vp=(void *)nco_realloc(var2->mss_val.vp,nco_typ_lng(var2->type));
00195     (void)nco_val_cnf_typ(var1->type,var1->mss_val,var2->type,var2->mss_val);
00196     var2->has_mss_val=True;
00197   } /* endif var1 has mss_val */
00198 
00199 } /* end nco_mss_val_cp() */

int nco_mss_val_get const int  nc_id,
var_sct *const   var
 

Definition at line 203 of file nco_mss_val.c.

References cast_nctype_void(), ptr_unn::cp, False, NC_CHAR, NC_MAX_NAME, nco_free(), nco_get_att(), nco_inq_att(), nco_inq_attname(), nco_inq_varnatts(), nco_malloc(), nco_realloc(), nco_typ_lng(), nco_val_cnf_typ(), prg_nm_get(), True, and ptr_unn::vp.

Referenced by nco_aed_prc(), nco_var_fll(), and nco_var_mtd_refresh().

00205 {
00206   /* Purpose: Update number of attributes and missing_value attribute of variable
00207      No matter what type missing_value is on disk, this routine ensures that 
00208      copy of mss_val in var_sct is stored as same type as host variable.
00209      Routine does not allow output missing_value to have more than one element */
00210 
00211   /* has_mss_val is typed as int not bool because it was sent to Fortran routines */
00212 
00213   char att_nm[NC_MAX_NAME];
00214   
00215   long att_sz;
00216   int idx;
00217   
00218   size_t att_lng;
00219 
00220   nc_type att_typ;
00221 
00222   ptr_unn mss_tmp;
00223   
00224   /* Refresh netCDF "mss_val" attribute for this variable */
00225   var->has_mss_val=False;
00226   var->mss_val.vp=nco_free(var->mss_val.vp);
00227 
00228   /* Refresh number of attributes for variable */
00229   (void)nco_inq_varnatts(nc_id,var->id,&var->nbr_att);
00230 
00231   for(idx=0;idx<var->nbr_att;idx++){
00232     (void)nco_inq_attname(nc_id,var->id,idx,att_nm);
00233     if((int)strcasecmp(att_nm,"missing_value") != 0) continue;
00234     (void)nco_inq_att(nc_id,var->id,att_nm,&att_typ,&att_sz);
00235     if(att_sz != 1L && att_typ != NC_CHAR){
00236       (void)fprintf(stderr,"%s: WARNING the \"%s\" attribute for %s has %li elements and so will not be used\n",prg_nm_get(),att_nm,var->nm,att_sz);
00237       continue;
00238     } /* end if */
00239     /* if(att_typ != var->type) (void)fprintf(stderr,"%s: WARNING the \"%s\" attribute for %s will be typecast from %s to %s for arithmetic purposes\n",prg_nm_get(),att_nm,var->nm,nco_typ_sng(att_typ),nco_typ_sng(var->type)); */
00240     /* If we got this far then try to retrieve attribute and make sure it conforms to variable's type */
00241     var->has_mss_val=True;
00242     /* Oddly, ARM uses NC_CHAR for type of missing_value, so make allowances for this */
00243     att_lng=att_sz*nco_typ_lng(att_typ);
00244     mss_tmp.vp=(void *)nco_malloc(att_lng);
00245     (void)nco_get_att(nc_id,var->id,att_nm,mss_tmp.vp,att_typ);
00246     if(att_typ == NC_CHAR){
00247       /* NUL-terminate missing value string */
00248       if(mss_tmp.cp[att_lng-1] != '\0'){
00249         att_lng++;
00250         mss_tmp.vp=(void *)nco_realloc(mss_tmp.vp,att_lng);
00251         mss_tmp.cp[att_lng-1]='\0';
00252         /* Un-typecast pointer to values after access */
00253         (void)cast_nctype_void(att_typ,&mss_tmp);
00254       } /* end if */
00255     } /* end if */
00256     
00257     /* Ensure mss_val in memory is stored as same type as variable */
00258     var->mss_val.vp=(void *)nco_malloc(nco_typ_lng(var->type));
00259     (void)nco_val_cnf_typ(att_typ,mss_tmp,var->type,var->mss_val);
00260 
00261     /* Release temporary memory */
00262     mss_tmp.vp=nco_free(mss_tmp.vp);
00263     break;
00264   } /* end loop over att */
00265 
00266   return var->has_mss_val;
00267 
00268 } /* end nco_mss_val_get() */

ptr_unn nco_mss_val_mk const nc_type  type  ) 
 

Definition at line 13 of file nco_mss_val.c.

References ptr_unn::bp, cast_nctype_void(), cast_void_nctype(), ptr_unn::cp, ptr_unn::dp, ptr_unn::fp, ptr_unn::lp, NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FILL_BYTE, NC_FILL_CHAR, NC_FILL_DOUBLE, NC_FILL_FLOAT, NC_FILL_INT, NC_FILL_SHORT, NC_FLOAT, NC_INT, NC_SHORT, nco_dfl_case_nc_type_err(), nco_malloc(), nco_typ_lng(), ptr_unn::sp, type, and ptr_unn::vp.

Referenced by main().

00014 {
00015   /* Threads: Routine is thread safe and makes no unsafe routines */
00016   /* Purpose: Return pointer union containing default missing value for type type */
00017 
00018   ptr_unn mss_val;
00019 
00020   mss_val.vp=(void *)nco_malloc(nco_typ_lng(type));
00021 
00022   /* Typecast pointer to values before access */
00023   (void)cast_void_nctype(type,&mss_val);
00024 
00025   switch(type){
00026   case NC_FLOAT: *mss_val.fp=NC_FILL_FLOAT; break; 
00027   case NC_DOUBLE: *mss_val.dp=NC_FILL_DOUBLE; break; 
00028   case NC_INT: *mss_val.lp=NC_FILL_INT; break;
00029   case NC_SHORT: *mss_val.sp=NC_FILL_SHORT; break;
00030   case NC_CHAR: *mss_val.cp=NC_FILL_CHAR; break;
00031   case NC_BYTE: *mss_val.bp=NC_FILL_BYTE; break;
00032   default: nco_dfl_case_nc_type_err(); break;
00033   } /* end switch */
00034 
00035   /* Un-typecast pointer to values after access */
00036   (void)cast_nctype_void(type,&mss_val);
00037   
00038   return mss_val;
00039 
00040 } /* end nco_mss_val_mk() */


Generated on Thu Mar 16 18:15:54 2006 for nco by  doxygen 1.4.4