nco/nco_cnf_typ.h File Reference

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

Include dependency graph for nco_cnf_typ.h:

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

Go to the source code of this file.

Functions

void cast_void_nctype (const nc_type type, ptr_unn *const ptr)
void cast_nctype_void (const nc_type type, ptr_unn *const ptr)
var_sctnco_typ_cnv_rth (var_sct *var, const int nco_op_typ)
var_sctnco_cnv_var_typ_dsk (var_sct *var)
var_sctnco_var_cnf_typ (const nc_type var_out_typ, var_sct *const var_in)
var_sctnco_cnv_mss_val_typ (var_sct *var, const nc_type mss_val_out_typ)
void nco_val_cnf_typ (const nc_type typ_in, ptr_unn val_in, const nc_type typ_out, ptr_unn val_out)
int nco_scv_cnf_typ (const nc_type typ_new, scv_sct *const scv_old)
nc_type ncap_var_retype (var_sct *var_1, var_sct *var_2)
nc_type ncap_scv_scv_cnf_typ_hgh_prc (scv_sct *const scv_1, scv_sct *const scv_2)
nc_type ncap_var_scv_cnf_typ_hgh_prc (var_sct **const var, scv_sct *const scv)


Function Documentation

void cast_nctype_void const nc_type  type,
ptr_unn *const   ptr
 

Definition at line 42 of file nco_cnf_typ.c.

References NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT, nco_dfl_case_nc_type_err(), and type.

Referenced by ncap_scv_2_ptr_unn(), ncap_var_fnc(), ncap_var_lgcl(), nco_aed_prc(), nco_lmt_evl(), nco_mss_val_cnf(), nco_mss_val_get(), nco_mss_val_mk(), nco_prs_aed_lst(), nco_var_cnf_typ(), and scl_mk_var().

00044 {
00045   /* Cast generic pointer in ptr_unn structure from type type to type void */
00046   switch(type){
00047   case NC_FLOAT:
00048     ptr->vp=(void *)ptr->fp;
00049     break;
00050   case NC_DOUBLE:
00051     ptr->vp=(void *)ptr->dp;
00052     break;
00053   case NC_INT:
00054     ptr->vp=(void *)ptr->lp;
00055     break;
00056   case NC_SHORT:
00057     ptr->vp=(void *)ptr->sp;
00058     break;
00059   case NC_CHAR:
00060     ptr->vp=(void *)ptr->cp;
00061     break;
00062   case NC_BYTE:
00063     ptr->vp=(void *)ptr->bp;
00064     break;
00065   default: nco_dfl_case_nc_type_err(); break;
00066   } /* end switch */
00067 } /* end cast_nctype_void() */

void cast_void_nctype const nc_type  type,
ptr_unn *const   ptr
 

Definition at line 13 of file nco_cnf_typ.c.

References NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT, nco_dfl_case_nc_type_err(), and type.

Referenced by ncap_scv_2_ptr_unn(), ncap_var_fnc(), ncap_var_lgcl(), nco_aed_prc(), nco_lmt_evl(), nco_msa_prn_var_val(), nco_mss_val_cnf(), nco_mss_val_mk(), nco_prn_att(), nco_prn_var_val_lmt(), nco_val_cnf_typ(), nco_var_abs(), nco_var_add(), nco_var_add_tll_ncflint(), nco_var_add_tll_ncra(), nco_var_avg_reduce_max(), nco_var_avg_reduce_min(), nco_var_avg_reduce_ttl(), nco_var_cnf_typ(), nco_var_dvd(), nco_var_max_bnr(), nco_var_min_bnr(), nco_var_mlt(), nco_var_mod(), nco_var_msk(), nco_var_nrm(), nco_var_nrm_sdn(), nco_var_pwr(), nco_var_sbt(), nco_var_sqrt(), nco_var_zero(), ptr_unn_2_scv(), scv_var_dvd(), scv_var_mod(), scv_var_pwr(), var_scv_add(), var_scv_dvd(), var_scv_mlt(), var_scv_mod(), var_scv_pwr(), var_scv_sub(), and vec_set().

00015 {
00016   /* Purpose: Cast generic pointer in ptr_unn structure from type void to output netCDF type */
00017   switch(type){
00018   case NC_FLOAT:
00019     ptr->fp=(float *)ptr->vp;
00020     break;
00021   case NC_DOUBLE:
00022     ptr->dp=(double *)ptr->vp;
00023     break;
00024   case NC_INT:
00025     ptr->lp=(nco_int *)ptr->vp;
00026     break;
00027   case NC_SHORT:
00028     ptr->sp=(short *)ptr->vp;
00029     break;
00030   case NC_CHAR:
00031     ptr->cp=(nco_char *)ptr->vp;
00032     break;
00033   case NC_BYTE:
00034     ptr->bp=(nco_byte *)ptr->vp;
00035     break;
00036   default: nco_dfl_case_nc_type_err(); break;
00037   } /* end switch */
00038 } /* end cast_void_nctype() */

nc_type ncap_scv_scv_cnf_typ_hgh_prc scv_sct *const   scv_1,
scv_sct *const   scv_2
 

Definition at line 507 of file nco_cnf_typ.c.

References nco_scv_cnf_typ(), and scv_sct::type.

00509 {
00510   /* fxm: TODO nco616: netCDF4 breaks assumption that range/precision increases with nc_type enum */
00511   /* Purpose: Promote scalar values to higher of two precisions, if necessary */
00512   if(scv_1->type == scv_2->type){
00513     return scv_1->type;
00514   }else if(scv_1->type > scv_2->type){
00515     (void)nco_scv_cnf_typ(scv_1->type,scv_2);
00516     return scv_1->type;
00517   }else{
00518     (void)nco_scv_cnf_typ(scv_2->type,scv_1);
00519     return scv_2->type;
00520   } /* endif */
00521 } /* end ncap_scv_scv_cnf_typ_hgh_prc */

nc_type ncap_var_retype var_sct var_1,
var_sct var_2
 

Definition at line 489 of file nco_cnf_typ.c.

References nco_var_cnf_typ(), and var_sct_tag::type.

Referenced by ncap_var_var_add(), ncap_var_var_dvd(), ncap_var_var_mlt(), ncap_var_var_mod(), ncap_var_var_op(), ncap_var_var_pwr(), and ncap_var_var_sub().

00491 {
00492   /* fxm: TODO nco616: netCDF4 breaks assumption that range/precision increases with nc_type enum */
00493   /* Purpose: Convert variable, if necessary, so variables are of same type */
00494   if(var_1->type == var_2->type) return var_1->type;
00495   /* fxm: Unsafe assumption that netCDF types are enumerated in increasing order of precision */
00496   if(var_1->type > var_2->type){
00497     var_2=nco_var_cnf_typ(var_1->type,var_2);
00498     return var_1->type;
00499   }else{
00500     var_1=nco_var_cnf_typ(var_2->type,var_1);
00501     return var_2->type;
00502   } /* endif */
00503 } /* end ncap_var_retype */

nc_type ncap_var_scv_cnf_typ_hgh_prc var_sct **const   var,
scv_sct *const   scv
 

Definition at line 525 of file nco_cnf_typ.c.

References nco_scv_cnf_typ(), and nco_var_cnf_typ().

Referenced by ncap_scv_var_dvd(), ncap_scv_var_mod(), ncap_var_scv_add(), ncap_var_scv_dvd(), ncap_var_scv_mlt(), ncap_var_scv_mod(), and ncap_var_scv_sub().

00527 {
00528   /* fxm: TODO nco616: netCDF4 breaks assumption that range/precision increases with nc_type enum */
00529   /* Purpose: If types of variable and scalar value differ, convert argument with 
00530      lower precision to type of argument with higher precision.
00531      Otherwise do nothing. 
00532      fxm: Assumes nc_type increases monotonically with precision */
00533 
00534   /* Do nothing if types match */
00535   if((*var)->type == scv->type){
00536     return (*var)->type;
00537   }else if((*var)->type > scv->type){
00538     (void)nco_scv_cnf_typ((*var)->type,scv); 
00539     return (*var)->type;
00540   }else{
00541     *var=nco_var_cnf_typ(scv->type,*var);
00542     return scv->type;
00543   } /* endif */
00544 
00545 } /* end ncap_var_scv_cnf_typ_hgh_prc() */

var_sct* nco_cnv_mss_val_typ var_sct var,
const nc_type  mss_val_out_typ
 

Definition at line 111 of file nco_cnf_typ.c.

References dbg_lvl_get(), var_sct_tag::has_mss_val, var_sct_tag::mss_val, nco_free(), nco_malloc(), nco_typ_lng(), nco_typ_sng(), nco_val_cnf_typ(), var_sct_tag::nm, prg_nm_get(), var_sct_tag::type, and ptr_unn::vp.

Referenced by main(), nco_var_get(), and nco_var_upk().

00113 {
00114   /* Purpose: Convert variable missing_value field, if any, to mss_val_out_typ
00115      Routine is currently called only by ncra and by nco_var_get(), for following reason:
00116      Most applications should call nco_var_cnf_typ() without calling nco_cnv_mss_val_typ()
00117      since nco_var_cnf_typ() converts misssing_value type along with variable type.
00118      The important exception to this is ncra
00119      ncra refreshes variable metadata (including missing_value, if any) 
00120      once per file (naturally), but refreshes variable values once per record.
00121      Current type of missing_value is not stored separately in variable structure
00122      (maybe this is a mistake), so type of missing value may remain as promoted
00123      type for arithmetic.
00124      When next record is read and nco_typ_cnf_rth() promotion of new input 
00125      to arithmetic type (double, if necessary) will fail when it tries to
00126      convert the missing_value, if any, which _was already promoted_.
00127      Performing type conversion on memory already converted is a no-no!
00128      And it results in unpredictable and incorrect answers
00129      Thus it is very important to synchronize type of variable and missing_value 
00130      In the case described above, ncra simply calls this routine to convert 
00131      missing_value to typ_upk at the end of each record.
00132      Routine is dangerous because it _allows_ mss_val and variable to be different types
00133      Make sure you have a (very) good reason to do this!
00134      Better permanent solution is to add missing_value type to variable structure */
00135 
00136   nc_type var_in_typ; /* [enm] Type of variable and mss_val on input */
00137 
00138   ptr_unn mss_val_in;
00139   ptr_unn mss_val_out;
00140 
00141   var_in_typ=var->type; /* [enm] Type of variable and mss_val on input */
00142 
00143   /* Skip if no missing_value or if missing_value is already typ_upk */ 
00144   if(!var->has_mss_val || var_in_typ == mss_val_out_typ) return var; 
00145 
00146   /* Simple error-checking and diagnostics */
00147   if(dbg_lvl_get() > 2){
00148     (void)fprintf(stderr,"%s: DEBUG %s missing_value attribute of variable %s from type %s to type %s\n",prg_nm_get(),mss_val_out_typ > var_in_typ ? "Promoting" : "Demoting",var->nm,nco_typ_sng(var_in_typ),nco_typ_sng(mss_val_out_typ));
00149   } /* end if */
00150   
00151   /* Sequence of following commands is important (copy before overwriting!) */
00152   mss_val_in=var->mss_val;
00153   mss_val_out.vp=(void *)nco_malloc(nco_typ_lng(mss_val_out_typ));
00154   (void)nco_val_cnf_typ(var_in_typ,mss_val_in,mss_val_out_typ,mss_val_out);
00155   var->mss_val=mss_val_out;
00156   /* Free original 
00157      Of course this only changes var_in->mss_val
00158      Calling routine must update var_out->mss_val if var_out->val points to var_in->val
00159      This dangling pointer was a problem in ncpdq */
00160   mss_val_in.vp=nco_free(mss_val_in.vp);
00161   
00162   return var; /* O [sct] Variable with mss_val converted to typ_upk */
00163 } /* nco_cnv_mss_val_typ() */

var_sct* nco_cnv_var_typ_dsk var_sct var  ) 
 

Definition at line 100 of file nco_cnf_typ.c.

References nco_var_cnf_typ(), var_sct_tag::typ_dsk, and var_sct_tag::type.

00101 {
00102   /* Purpose: Revert variable to on-disk type */
00103   
00104   if(var->type != var->typ_dsk) var=nco_var_cnf_typ(var->typ_dsk,var);
00105   
00106   return var;
00107 } /* nco_cnv_var_typ_dsk() */

int nco_scv_cnf_typ const nc_type  typ_new,
scv_sct *const   scv_old
 

Definition at line 418 of file nco_cnf_typ.c.

References val_unn::b, val_unn::d, val_unn::f, val_unn::l, NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_INT, NC_NAT, NC_SHORT, nco_dfl_case_nc_type_err(), val_unn::s, scv_sct::type, and scv_sct::val.

Referenced by ncap_scv_scv_cnf_typ_hgh_prc(), ncap_scv_var_pwr(), ncap_var_scv_cnf_typ_hgh_prc(), ncap_var_scv_pwr(), and nco_var_pck().

00420 {
00421   /* Purpose: Convert scalar attribute to typ_new using C implicit coercion */
00422   nc_type typ_old=scv_old->type;
00423   
00424   scv_sct scv_new;
00425 
00426   switch (typ_new){ 
00427   case NC_BYTE:
00428     switch(typ_old){
00429     case NC_FLOAT: scv_new.val.b=(nco_byte)(scv_old->val).f; break;
00430     case NC_DOUBLE: scv_new.val.b=(nco_byte)(scv_old->val).d; break;
00431     case NC_INT: scv_new.val.b=(scv_old->val).l; break;
00432     case NC_SHORT: scv_new.val.b=(scv_old->val).s; break;
00433     case NC_BYTE: scv_new.val.b=(scv_old->val).b; break;
00434     case NC_CHAR: break;
00435     case NC_NAT: break;
00436     } break;
00437   case NC_CHAR:
00438     /* Do nothing */
00439     break;
00440   case NC_SHORT:
00441     switch(typ_old){
00442     case NC_FLOAT: scv_new.val.s=(short)(scv_old->val).f; break; /* Coerce to avoid C++ compiler assignment warning */
00443     case NC_DOUBLE: scv_new.val.s=(short)(scv_old->val).d; break; /* Coerce to avoid C++ compiler assignment warning */
00444     case NC_INT: scv_new.val.s=(scv_old->val).l; break;
00445     case NC_SHORT: scv_new.val.s=(scv_old->val).s; break;
00446     case NC_BYTE: scv_new.val.s=(scv_old->val).b; break;
00447     case NC_CHAR: break;
00448     case NC_NAT: break;    
00449     } break;
00450   case NC_INT:
00451     switch(typ_old){
00452     case NC_FLOAT: scv_new.val.l=(nco_int)(scv_old->val).f; break; /* Coerce to avoid C++ compiler assignment warning */
00453     case NC_DOUBLE: scv_new.val.l=(nco_int)(scv_old->val).d; break; /* Coerce to avoid C++ compiler assignment warning */
00454     case NC_INT: scv_new.val.l =scv_old->val.l; break;
00455     case NC_SHORT: scv_new.val.l=(scv_old->val).s; break;
00456     case NC_BYTE: scv_new.val.l=(scv_old->val).b; break;
00457     case NC_CHAR: break;
00458     case NC_NAT: break;
00459     } break;
00460   case NC_FLOAT:
00461     switch(typ_old){
00462     case NC_FLOAT: scv_new.val.f=(scv_old->val).f; break; 
00463     case NC_DOUBLE: scv_new.val.f=(scv_old->val).d; break; 
00464     case NC_INT: scv_new.val.f=(scv_old->val).l; break;
00465     case NC_SHORT: scv_new.val.f=(scv_old->val).s; break;
00466     case NC_BYTE: scv_new.val.f=(scv_old->val).b; break;
00467     case NC_CHAR: break;
00468     case NC_NAT: break;    
00469     } break;
00470   case NC_DOUBLE:
00471     switch(typ_old){
00472     case NC_FLOAT: scv_new.val.d=(scv_old->val).f; break; 
00473     case NC_DOUBLE: scv_new.val.d =(scv_old->val).d; break; 
00474     case NC_INT: scv_new.val.d=(scv_old->val).l; break;
00475     case NC_SHORT: scv_new.val.d=(scv_old->val).s; break;
00476     case NC_BYTE: scv_new.val.d=(scv_old->val).b; break;
00477     case NC_CHAR: break;
00478     case NC_NAT: break;    
00479     } break;
00480   default: nco_dfl_case_nc_type_err(); break;
00481   } /* end switch */
00482   scv_new.type=typ_new;
00483   *scv_old=scv_new;
00484   return 1;      
00485 } /* end nco_scv_cnf_typ */

var_sct* nco_typ_cnv_rth var_sct var,
const int  nco_op_typ
 

Definition at line 71 of file nco_cnf_typ.c.

References NC_DOUBLE, NC_FLOAT, nco_op_max, nco_op_min, nco_var_cnf_typ(), var_sct_tag::typ_upk, and var_sct_tag::type.

Referenced by main().

00073 {
00074   /* Threads: Routine is thread safe and calls no unsafe routines */
00075   /* Purpose: Convert char, short, long, int types to doubles for arithmetic
00076      Conversions are performed unless arithmetic operation type is min or max
00077      Floats (and doubles, of course) are not converted for performance reasons
00078      Convert back after weighting and arithmetic are complete! */
00079 
00080   /* Variables which are unpacked into NC_FLOAT should remain NC_FLOAT here
00081      Unpacking happens 'transparently' when original data are read by nco_var_get() 
00082      Output structures (i.e., var_prc_out) often correspond to original input type
00083      Thus var may have typ_upk=NC_FLOAT and type=NC_SHORT
00084      In that case, promote based on typ_upk rather than on type
00085      Otherwise most var's that had been unpacked would be converted to NC_DOUBLE here
00086      That would put them in conflict with corresponding var_out, which is usually
00087      based on typ_upk
00088      Check this first, then proceed with normal non-float->double conversion */
00089   if(var->typ_upk == NC_FLOAT){
00090     var=nco_var_cnf_typ((nc_type)NC_FLOAT,var);
00091   }else{ /* Conversion only for appropriate operation types */ 
00092     if(var->type != NC_FLOAT && var->type != NC_DOUBLE && nco_op_typ != nco_op_min && nco_op_typ != nco_op_max) var=nco_var_cnf_typ((nc_type)NC_DOUBLE,var);
00093   } /* end if */
00094   
00095   return var;
00096 } /* nco_typ_cnv_rth() */

void nco_val_cnf_typ const nc_type  typ_in,
ptr_unn  val_in,
const nc_type  typ_out,
ptr_unn  val_out
 

Definition at line 328 of file nco_cnf_typ.c.

References cast_void_nctype(), NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT, nco_dfl_case_nc_type_err(), and val_out().

Referenced by nco_aed_prc(), nco_att_cpy(), nco_cnv_mss_val_typ(), nco_mss_val_cp(), nco_mss_val_get(), nco_var_cnf_typ(), nco_var_pck(), and ptr_unn_2_scl_dbl().

00332 {
00333   /* Threads: Routine is thread safe and makes no unsafe routines */
00334   /* Purpose: Fill val_out with copy of val_in that has been typecast from typ_in to typ_out
00335      Last-referenced state of both value pointers is assumed to be .vp, and val_out union is returned in that state */
00336 
00337   /* val_in and val_out should not be same pointer union since
00338      val_out must hold enough space (one element of type typ_out) to hold output
00339      and output type may be larger than input type */
00340 
00341   /* Typecast pointer to values before access */
00342   (void)cast_void_nctype(typ_in,&val_in);
00343   (void)cast_void_nctype(typ_out,&val_out);
00344   
00345   /* Copy and typecast single value using implicit coercion rules of C */
00346   switch(typ_out){
00347   case NC_FLOAT:
00348     switch(typ_in){
00349     case NC_FLOAT: *val_out.fp=*val_in.fp; break; 
00350     case NC_DOUBLE: *val_out.fp=*val_in.dp; break; 
00351     case NC_INT: *val_out.fp=*val_in.lp; break;
00352     case NC_SHORT: *val_out.fp=*val_in.sp; break;
00353     case NC_CHAR: *val_out.fp=strtod((const char *)val_in.cp,(char **)NULL); break;
00354     case NC_BYTE: *val_out.fp=*val_in.bp; break;
00355     default: nco_dfl_case_nc_type_err(); break;
00356     } break;
00357   case NC_DOUBLE:
00358     switch(typ_in){
00359     case NC_FLOAT: *val_out.dp=*val_in.fp; break; 
00360     case NC_DOUBLE: *val_out.dp=*val_in.dp; break; 
00361     case NC_INT: *val_out.dp=*val_in.lp; break;
00362     case NC_SHORT: *val_out.dp=*val_in.sp; break;
00363     case NC_CHAR: *val_out.dp=strtod((const char *)val_in.cp,(char **)NULL); break;
00364     case NC_BYTE: *val_out.dp=*val_in.bp; break;
00365     default: nco_dfl_case_nc_type_err(); break;
00366     } break;
00367   case NC_INT:
00368     switch(typ_in){
00369     case NC_FLOAT: *val_out.lp=(nco_int)*val_in.fp; break; /* Coerce to avoid C++ compiler assignment warning */
00370     case NC_DOUBLE: *val_out.lp=(nco_int)*val_in.dp; break; /* Coerce to avoid C++ compiler assignment warning */
00371     case NC_INT: *val_out.lp=*val_in.lp; break;
00372     case NC_SHORT: *val_out.lp=*val_in.sp; break;
00373     case NC_CHAR: *val_out.lp=(nco_int)strtod((const char *)val_in.cp,(char **)NULL); break; /* Coerce to avoid C++ compiler assignment warning */
00374     case NC_BYTE: *val_out.lp=*val_in.bp; break;
00375     default: nco_dfl_case_nc_type_err(); break;
00376     } break;
00377   case NC_SHORT:
00378     switch(typ_in){
00379     case NC_FLOAT: *val_out.sp=(short)*val_in.fp; break; /* Coerce to avoid C++ compiler assignment warning */
00380     case NC_DOUBLE: *val_out.sp=(short)*val_in.dp; break; /* Coerce to avoid C++ compiler assignment warning */
00381     case NC_INT: *val_out.sp=*val_in.lp; break;
00382     case NC_SHORT: *val_out.sp=*val_in.sp; break;
00383     case NC_CHAR: *val_out.sp=(short)strtod((const char *)val_in.cp,(char **)NULL); break; /* Coerce to avoid C++ compiler assignment warning */
00384     case NC_BYTE: *val_out.sp=*val_in.bp; break;
00385     default: nco_dfl_case_nc_type_err(); break;
00386     } break;
00387   case NC_CHAR:
00388     switch(typ_in){
00389     case NC_FLOAT: *val_out.cp=(nco_char)*val_in.fp; break; /* Coerce to avoid C++ compiler assignment warning */
00390     case NC_DOUBLE: *val_out.cp=(nco_char)*val_in.dp; break; /* Coerce to avoid C++ compiler assignment warning */
00391     case NC_INT: *val_out.cp=*val_in.lp; break;
00392     case NC_SHORT: *val_out.cp=*val_in.sp; break;
00393     case NC_CHAR: *val_out.cp=*val_in.cp; break;
00394     case NC_BYTE: *val_out.cp=*val_in.bp; break;
00395     default: nco_dfl_case_nc_type_err(); break;
00396     } break;
00397   case NC_BYTE:
00398     switch(typ_in){
00399     case NC_FLOAT: *val_out.bp=(nco_byte)*val_in.fp; break; /* Coerce to avoid C++ compiler assignment warning */
00400     case NC_DOUBLE: *val_out.bp=(nco_byte)*val_in.dp; break; /* Coerce to avoid C++ compiler assignment warning */
00401     case NC_INT: *val_out.bp=*val_in.lp; break;
00402     case NC_SHORT: *val_out.bp=*val_in.sp; break;
00403     case NC_CHAR: *val_out.bp=*val_in.cp; break;
00404     case NC_BYTE: *val_out.bp=*val_in.bp; break;
00405     default: nco_dfl_case_nc_type_err(); break;
00406     } break;
00407   default: nco_dfl_case_nc_type_err(); break;
00408   } /* end switch */
00409   
00410   /* NB: There is no need to un-typecast input pointers because they were passed by
00411      value and are thus purely local to this routine. The only thing changed by this
00412      routine is the contents of the location pointed to by the pointer to the output value. */
00413   
00414 } /* end nco_val_cnf_typ */

var_sct* nco_var_cnf_typ const nc_type  var_out_typ,
var_sct *const   var_in
 

Definition at line 167 of file nco_cnf_typ.c.

References ptr_unn::bp, cast_nctype_void(), cast_void_nctype(), ptr_unn::cp, dbg_lvl_get(), ptr_unn::dp, 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_SHORT, nco_dfl_case_nc_type_err(), nco_free(), nco_malloc(), nco_typ_lng(), nco_typ_sng(), nco_val_cnf_typ(), prg_nm_get(), ptr_unn::sp, var_sct_tag::sz, var_sct_tag::type, var_sct_tag::val, val_out(), and ptr_unn::vp.

Referenced by main(), ncap_scv_var_pwr(), ncap_var_fnc(), ncap_var_lgcl(), ncap_var_retype(), ncap_var_scv_cnf_typ_hgh_prc(), ncap_var_scv_pwr(), ncap_var_var_op(), ncap_var_var_pwr(), nco_cnv_var_typ_dsk(), nco_typ_cnv_rth(), nco_var_pck(), and nco_var_upk().

00169 {
00170   /* Threads: Routine is thread safe and makes no unsafe routines */
00171   /* Purpose: Return copy of input variable typecast to desired type
00172      Routine converts missing_value, if any, to output type
00173      Routine saves time by returning original variable structure
00174      with val and type members changed as necessary
00175      Routine assumes variable and missing_value, if any, are same type in memory
00176      This is currently always true except briefly in ncra (and possibly ncpdq)
00177      This condition is unsafe and is described more fully in nco_cnv_mss_val_typ() */
00178   long idx;
00179   long sz;
00180   long sz_msk=long_CEWI; /* Holds value when called with var_in->val.vp==NULL */
00181   
00182   nc_type var_in_typ;
00183   
00184   ptr_unn val_in;
00185   ptr_unn val_out;
00186 
00187   var_sct *var_out;
00188 
00189   /* Do types of variable AND its missing value already match?
00190      This routine assumes missing_value, if any, to be same type as variable */
00191   if(var_in->type == var_out_typ) return var_in;
00192 
00193   if(var_in->val.vp==NULL){
00194     /* Variable has no data when var_in.val.vp==NULL
00195        In this case function should only convert missing values 
00196        Accomplish this by temporarily masking off val_in by setting var_in->sz=0
00197        Restore correct size at function end
00198        fxm: 20050521 Which operators take advantage of this behavior? */
00199     sz_msk=var_in->sz;
00200     var_in->sz=0L;
00201   } /* endif NULL */
00202 
00203   /* Setting output pointer equal to input pointer is confusing
00204      Theoretical advantage is that it speeds up routine 
00205      Nevertheless, be careful... */
00206   var_out=var_in;
00207   
00208   var_in_typ=var_in->type;
00209   
00210   /* Simple error-checking and diagnostics */
00211   if(dbg_lvl_get() > 2){
00212     (void)fprintf(stderr,"%s: DEBUG %s variable %s from type %s to type %s\n",prg_nm_get(),var_out_typ > var_in_typ ? "Promoting" : "Demoting",var_in->nm,nco_typ_sng(var_in_typ),nco_typ_sng(var_out_typ));
00213   } /* end if */
00214   
00215   /* Move current variable values to swap location */
00216   val_in=var_in->val;
00217   
00218   /* Allocate space for type-conforming values */
00219   var_out->type=var_out_typ;
00220   var_out->val.vp=(void *)nco_malloc(var_out->sz*nco_typ_lng(var_out->type));
00221   
00222   /* Define convenience variables to avoid repetitive indirect addressing */
00223   sz=var_out->sz;
00224   val_out=var_out->val;
00225   
00226   /* Copy and typecast missing_value attribute, if any */
00227   /* Calling routine must avoid re-promoting missing values already promoted during arithmetic */
00228   if(var_out->has_mss_val){
00229     ptr_unn var_in_mss_val;
00230 
00231     /* Sequence of following commands is important (copy before overwriting!) */
00232     var_in_mss_val=var_out->mss_val;
00233     var_out->mss_val.vp=(void *)nco_malloc(nco_typ_lng(var_out->type));
00234     (void)nco_val_cnf_typ(var_in_typ,var_in_mss_val,var_out_typ,var_out->mss_val);
00235     /* Free original */
00236     var_in_mss_val.vp=nco_free(var_in_mss_val.vp);
00237   } /* end if */
00238 
00239   /* Typecast pointer to values before access 
00240      There is only one var structure so use shortcut, de-referenced types */
00241   (void)cast_void_nctype(var_in_typ,&val_in);
00242   (void)cast_void_nctype(var_out_typ,&val_out);
00243   
00244   /* Copy and typecast entire array of values, using C implicit coercion */
00245   switch(var_out_typ){
00246   case NC_FLOAT:
00247     switch(var_in_typ){
00248     case NC_FLOAT: for(idx=0L;idx<sz;idx++) {val_out.fp[idx]=val_in.fp[idx];} break; 
00249     case NC_DOUBLE: for(idx=0L;idx<sz;idx++) {val_out.fp[idx]=val_in.dp[idx];} break; 
00250     case NC_INT: for(idx=0L;idx<sz;idx++) {val_out.fp[idx]=val_in.lp[idx];} break;
00251     case NC_SHORT: for(idx=0L;idx<sz;idx++) {val_out.fp[idx]=val_in.sp[idx];} break;
00252     case NC_CHAR: for(idx=0L;idx<sz;idx++) {val_out.fp[idx]=val_in.cp[idx];} break;
00253     case NC_BYTE: for(idx=0L;idx<sz;idx++) {val_out.fp[idx]=val_in.bp[idx];} break;
00254     default: nco_dfl_case_nc_type_err(); break;
00255     } break;
00256   case NC_DOUBLE:
00257     switch(var_in_typ){
00258     case NC_FLOAT: for(idx=0L;idx<sz;idx++) {val_out.dp[idx]=val_in.fp[idx];} break; 
00259     case NC_DOUBLE: for(idx=0L;idx<sz;idx++) {val_out.dp[idx]=val_in.dp[idx];} break; 
00260     case NC_INT: for(idx=0L;idx<sz;idx++) {val_out.dp[idx]=val_in.lp[idx];} break;
00261     case NC_SHORT: for(idx=0L;idx<sz;idx++) {val_out.dp[idx]=val_in.sp[idx];} break;
00262       /* valgrind detects uninitialized write errors in following line with GCC 3.4 */
00263     case NC_CHAR: for(idx=0L;idx<sz;idx++) {val_out.dp[idx]=val_in.cp[idx];} break;
00264     case NC_BYTE: for(idx=0L;idx<sz;idx++) {val_out.dp[idx]=val_in.bp[idx];} break;
00265     default: nco_dfl_case_nc_type_err(); break;
00266     } break;
00267   case NC_INT:
00268     switch(var_in_typ){
00269     case NC_FLOAT: for(idx=0L;idx<sz;idx++) {val_out.lp[idx]=(nco_int)val_in.fp[idx];} break; /* Coerce to avoid C++ compiler assignment warning */
00270     case NC_DOUBLE: for(idx=0L;idx<sz;idx++) {val_out.lp[idx]=(nco_int)val_in.dp[idx];} break; /* Coerce to avoid C++ compiler assignment warning */
00271     case NC_INT: for(idx=0L;idx<sz;idx++) {val_out.lp[idx]=val_in.lp[idx];} break;
00272     case NC_SHORT: for(idx=0L;idx<sz;idx++) {val_out.lp[idx]=val_in.sp[idx];} break;
00273     case NC_CHAR: for(idx=0L;idx<sz;idx++) {val_out.lp[idx]=val_in.cp[idx];} break;
00274     case NC_BYTE: for(idx=0L;idx<sz;idx++) {val_out.lp[idx]=val_in.bp[idx];} break;
00275     default: nco_dfl_case_nc_type_err(); break;
00276     } break;
00277   case NC_SHORT:
00278     switch(var_in_typ){
00279     case NC_FLOAT: for(idx=0L;idx<sz;idx++) {val_out.sp[idx]=(short)val_in.fp[idx];} break; /* Coerce to avoid C++ compiler assignment warning */
00280     case NC_DOUBLE: for(idx=0L;idx<sz;idx++) {val_out.sp[idx]=(short)(val_in.dp[idx]);} break; /* Coerce to avoid C++ compiler assignment warning */
00281     case NC_INT: for(idx=0L;idx<sz;idx++) {val_out.sp[idx]=val_in.lp[idx];} break;
00282     case NC_SHORT: for(idx=0L;idx<sz;idx++) {val_out.sp[idx]=val_in.sp[idx];} break;
00283     case NC_CHAR: for(idx=0L;idx<sz;idx++) {val_out.sp[idx]=val_in.cp[idx];} break;
00284     case NC_BYTE: for(idx=0L;idx<sz;idx++) {val_out.sp[idx]=val_in.bp[idx];} break;
00285     default: nco_dfl_case_nc_type_err(); break;
00286     } break;
00287   case NC_CHAR:
00288     switch(var_in_typ){
00289     case NC_FLOAT: for(idx=0L;idx<sz;idx++) {val_out.cp[idx]=(nco_char)val_in.fp[idx];} break; /* Coerce to avoid C++ compiler assignment warning */
00290     case NC_DOUBLE: for(idx=0L;idx<sz;idx++) {val_out.cp[idx]=(nco_char)val_in.dp[idx];} break; /* Coerce to avoid C++ compiler assignment warning */
00291     case NC_INT: for(idx=0L;idx<sz;idx++) {val_out.cp[idx]=val_in.lp[idx];} break;
00292     case NC_SHORT: for(idx=0L;idx<sz;idx++) {val_out.cp[idx]=val_in.sp[idx];} break;
00293     case NC_CHAR: for(idx=0L;idx<sz;idx++) {val_out.cp[idx]=val_in.cp[idx];} break;
00294     case NC_BYTE: for(idx=0L;idx<sz;idx++) {val_out.cp[idx]=val_in.bp[idx];} break;
00295     default: nco_dfl_case_nc_type_err(); break;
00296     } break;
00297   case NC_BYTE:
00298     switch(var_in_typ){
00299     case NC_FLOAT: for(idx=0L;idx<sz;idx++) {val_out.bp[idx]=(nco_byte)val_in.fp[idx];} break; /* Coerce to avoid C++ compiler assignment warning */
00300     case NC_DOUBLE: for(idx=0L;idx<sz;idx++) {val_out.bp[idx]=(nco_byte)val_in.dp[idx];} break; /* Coerce to avoid C++ compiler assignment warning */
00301     case NC_INT: for(idx=0L;idx<sz;idx++) {val_out.bp[idx]=val_in.lp[idx];} break;
00302     case NC_SHORT: for(idx=0L;idx<sz;idx++) {val_out.bp[idx]=val_in.sp[idx];} break;
00303     case NC_CHAR: for(idx=0L;idx<sz;idx++) {val_out.bp[idx]=val_in.cp[idx];} break;
00304     case NC_BYTE: for(idx=0L;idx<sz;idx++) {val_out.bp[idx]=val_in.bp[idx];} break;
00305     default: nco_dfl_case_nc_type_err(); break;
00306     } break;
00307   default: nco_dfl_case_nc_type_err(); break;
00308   } /* end switch */
00309   
00310   /* NB: we operated on local copies of val_in and val_out
00311      It is only neccessary to un-typecast pointer to val_in because we access it one more time
00312      Un-typecast pointer to val_out for symmetry */
00313   (void)cast_nctype_void(var_in_typ,&val_in);
00314   (void)cast_nctype_void(var_out_typ,&val_out);
00315 
00316   /* If var_in.vp empty then unmask sz */
00317   if(val_in.vp==NULL) var_out->sz=sz_msk;
00318 
00319   /* Free input variable data */
00320   val_in.vp=nco_free(val_in.vp);
00321   
00322   return var_out;
00323   
00324 } /* end nco_var_cnf_typ() */


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