nco/nco_pck.h File Reference

#include <stdio.h>
#include <netcdf.h>
#include "nco_netcdf.h"
#include "nco.h"
#include "nco_cnf_typ.h"
#include "nco_ctl.h"
#include "nco_mmr.h"
#include "nco_scl_utl.h"
#include "nco_rth_utl.h"
#include "nco_var_avg.h"
#include "nco_var_rth.h"
#include "nco_var_scv.h"
#include "nco_var_utl.h"

Include dependency graph for nco_pck.h:

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

Go to the source code of this file.

Enumerations

enum  nco_pck_plc {
  nco_pck_plc_nil, nco_pck_plc_all_xst_att, nco_pck_plc_all_new_att, nco_pck_plc_xst_new_att,
  nco_pck_plc_upk
}
enum  nco_pck_map {
  nco_pck_map_nil, nco_pck_map_hgh_sht, nco_pck_map_hgh_chr, nco_pck_map_hgh_byt,
  nco_pck_map_nxt_lsr, nco_pck_map_flt_sht, nco_pck_map_flt_chr, nco_pck_map_flt_byt
}

Functions

void nco_dfl_case_pck_map_err (void)
void nco_dfl_case_pck_plc_err (void)
bool nco_is_packable (const nc_type nc_typ_in)
const char * nco_pck_map_sng_get (const int nco_pck_map)
const char * nco_pck_plc_sng_get (const int nco_pck_plc)
bool nco_pck_plc_typ_get (const int nco_pck_map, const nc_type nc_typ_in, nc_type *nc_typ_pck_out)
void nco_pck_mtd (const var_sct *const var_in, var_sct *const var_out, const int nco_pck_map, const int nco_pck_plc)
void nco_pck_val (var_sct *const var_in, var_sct *var_out, const int nco_pck_map, const int nco_pck_plc, aed_sct *const aed_lst_add_fst, aed_sct *const aed_lst_scl_fct)
int nco_pck_map_get (const char *nco_pck_map_sng)
int nco_pck_plc_get (const char *nco_pck_plc_sng)
bool nco_pck_dsk_inq (const int nc_id, var_sct *var)
var_sctnco_put_var_pck (const int out_id, var_sct *var, const int nco_pck_plc)
var_sctnco_var_pck (var_sct *var, const nc_type typ_pck, bool *PCK_VAR_WITH_NEW_PCK_ATT)
var_sctnco_var_upk (var_sct *const var)
void nco_var_upk_swp (var_sct *const var_in, var_sct *const var_out)


Enumeration Type Documentation

enum nco_pck_map
 

Enumerator:
nco_pck_map_nil 
nco_pck_map_hgh_sht 
nco_pck_map_hgh_chr 
nco_pck_map_hgh_byt 
nco_pck_map_nxt_lsr 
nco_pck_map_flt_sht 
nco_pck_map_flt_chr 
nco_pck_map_flt_byt 

Definition at line 45 of file nco_pck.h.

00045                 { /* [enm] Packing conversion map */
00046   /* NB: Packing to NC_CHAR is implemented but not advertised or supported because 
00047      (char)0 == NUL, a special value with difficult implicit conversion rules.
00048      We recommend always packing to type NC_BYTE rather than NC_CHAR */
00049   nco_pck_map_nil, /* 0 [enm] Do not convert anything, i.e., all types remain unchanged */
00050   nco_pck_map_hgh_sht, /* 1 [enm] Pack higher precision types to NC_SHORT, pack nothing else
00051                           [NC_DOUBLE,NC_FLOAT,NC_INT]->NC_SHORT, [NC_SHORT,NC_CHAR,NC_BYTE]->unaltered */
00052   nco_pck_map_hgh_chr, /* 2 [enm] Pack higher precision types to NC_CHAR, pack nothing else
00053                           [NC_DOUBLE,NC_FLOAT,NC_INT,NC_SHORT]->NC_CHAR, [NC_CHAR,NC_BYTE]->unaltered */
00054   nco_pck_map_hgh_byt, /* 3 [enm] Pack higher precision types to NC_BYTE, pack nothing else
00055                           [NC_DOUBLE,NC_FLOAT,NC_INT,NC_SHORT]->NC_BYTE, [NC_CHAR,NC_BYTE]->unaltered */
00056   nco_pck_map_nxt_lsr, /* 4 [enm] Convert each type of each size to type of next size down
00057                           NC_DOUBLE->NC_INT, [NC_FLOAT,NC_INT]->NC_SHORT, NC_SHORT->NC_BYTE, [NC_CHAR,NC_BYTE]->unaltered */
00058   nco_pck_map_flt_sht, /* 5 [enm] Pack floating precision types to NC_SHORT, pack nothing else
00059                           [NC_DOUBLE,NC_FLOAT]->NC_SHORT, [NC_INT,NC_SHORT,NC_CHAR,NC_BYTE]->unaltered */
00060   nco_pck_map_flt_chr, /* 6 [enm] Pack floating precision types to NC_CHAR, pack nothing else
00061                           [NC_DOUBLE,NC_FLOAT]->NC_CHAR, [NC_INT,NC_SHORT,NC_CHAR,NC_BYTE]->unaltered */
00062   nco_pck_map_flt_byt /* 7 [enm] Pack floating precision types to NC_BYTE, pack nothing else
00063                           [NC_DOUBLE,NC_FLOAT]->NC_BYTE, [NC_INT,NC_SHORT,NC_CHAR,NC_BYTE]->unaltered */
00064 }; /* end nco_pck_map enum */

enum nco_pck_plc
 

Enumerator:
nco_pck_plc_nil 
nco_pck_plc_all_xst_att 
nco_pck_plc_all_new_att 
nco_pck_plc_xst_new_att 
nco_pck_plc_upk 

Definition at line 36 of file nco_pck.h.

00036                 { /* [enm] Packing policy */
00037   nco_pck_plc_nil, /* 0 [enm] Do not think about packing */
00038   nco_pck_plc_all_xst_att, /* 1 [enm] Pack all variables, keep existing packing attributes if any */
00039   nco_pck_plc_all_new_att, /* 2 [enm] Pack all variables, always generate new packing attributes */
00040   nco_pck_plc_xst_new_att, /* 3 [enm] Pack existing packed variables, always generate new packing attributes */
00041   nco_pck_plc_upk /* 4 [enm] Unpack all packed variables */
00042 }; /* end nco_pck_plc enum */


Function Documentation

void nco_dfl_case_pck_map_err void   ) 
 

Definition at line 74 of file nco_pck.c.

References nco_err_exit().

Referenced by nco_pck_map_sng_get().

00075 {
00076   /* Purpose: Convenience routine for printing error and exiting when
00077      switch(pck_map) statement receives an illegal default case
00078 
00079      Placing this in its own routine also has the virtue of saving many lines 
00080      of code since this function is used in many many switch() statements. */
00081   const char fnc_nm[]="nco_dfl_case_pck_map_err()";
00082   (void)fprintf(stdout,"%s: ERROR switch(pck_map) statement fell through to default case, which is unsafe. This catch-all error handler ensures all switch(pck_map) statements are fully enumerated. Exiting...\n",fnc_nm);
00083   nco_err_exit(0,fnc_nm);
00084 } /* end nco_dfl_case_pck_map_err() */

void nco_dfl_case_pck_plc_err void   ) 
 

Definition at line 87 of file nco_pck.c.

References nco_err_exit().

Referenced by nco_pck_mtd(), nco_pck_plc_sng_get(), nco_pck_val(), and nco_put_var_pck().

00088 {
00089   /* Purpose: Convenience routine for printing error and exiting when
00090      switch(pck_plc) statement receives an illegal default case
00091 
00092      Placing this in its own routine also has the virtue of saving many lines 
00093      of code since this function is used in many many switch() statements. */
00094   const char fnc_nm[]="nco_dfl_case_pck_plc_err()";
00095   (void)fprintf(stdout,"%s: ERROR switch(pck_plc) statement fell through to default case, which is unsafe. This catch-all error handler ensures all switch(pck_plc) statements are fully enumerated. Exiting...\n",fnc_nm);
00096   nco_err_exit(0,fnc_nm);
00097 } /* end nco_dfl_case_pck_plc_err() */

bool nco_is_packable const nc_type  nc_typ_in  ) 
 

Definition at line 101 of file nco_pck.c.

References EXIT_FAILURE, False, NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT, nco_dfl_case_nc_type_err(), nco_exit(), prg_nm_get(), and True.

00102 {
00103   /* Purpose: Determine whether NCO should attempt to pack a given type
00104      Packing certain variable types is not recommended, e.g., packing NC_CHAR
00105      and NC_BYTE makes no sense, because precision would needlessly be lost.
00106      Routine should be consistent with nco_pck_plc_typ_get()
00107      NB: Routine is deprecated in favor of more flexible nco_pck_plc_typ_get() */
00108   const char fnc_nm[]="nco_is_packable()"; /* [sng] Function name */
00109 
00110   (void)fprintf(stdout,"%s: ERROR deprecated routine %s should not be called\n",prg_nm_get(),fnc_nm);
00111   nco_exit(EXIT_FAILURE);
00112 
00113   switch(nc_typ_in){ 
00114   case NC_FLOAT: 
00115   case NC_DOUBLE: 
00116   case NC_INT: 
00117     return True;
00118     break;
00119   case NC_SHORT: 
00120   case NC_CHAR: 
00121   case NC_BYTE: 
00122     return False;
00123     break;
00124   default: nco_dfl_case_nc_type_err(); break;
00125   } /* end switch */ 
00126 
00127   /* Some compilers, e.g., SGI cc, need return statement to end non-void functions */
00128   return False;
00129 } /* end nco_is_packable() */

bool nco_pck_dsk_inq const int  nc_id,
var_sct var
 

Definition at line 335 of file nco_pck.c.

References dbg_lvl_get(), False, NC_BYTE, NC_CHAR, NC_ENOTATT, nco_inq_att_flg(), nco_is_rth_opr(), nco_typ_sng(), prg_get(), prg_nm_get(), and True.

Referenced by nco_var_fll(), and nco_var_get().

00337 {
00338   /* Purpose: Check whether variable is packed on disk and set variable members 
00339      pck_dsk, has_scl_fct, has_add_fst, and typ_upk accordingly
00340      nco_pck_dsk_inq() should be called early in application, e.g., in nco_var_fll() 
00341      Call nco_pck_dsk_inq() before copying input list to output list 
00342      Multi-file operators which handle packing must call this routine prior
00343      to each read of a variable, in case that variable has been unpacked. */
00344   /* ncea -O -D 3 -v pck ~/nco/data/in.nc ~/nco/data/foo.nc */
00345   
00346   const char add_fst_sng[]="add_offset"; /* [sng] Unidata standard string for add offset */
00347   const char scl_fct_sng[]="scale_factor"; /* [sng] Unidata standard string for scale factor */
00348   
00349   int rcd; /* [rcd] Return success code */
00350   
00351   long add_fst_lng; /* [idx] Number of elements in add_offset attribute */
00352   long scl_fct_lng; /* [idx] Number of elements in scale_factor attribute */
00353 
00354   nc_type add_fst_typ; /* [idx] Type of add_offset attribute */
00355   nc_type scl_fct_typ; /* [idx] Type of scale_factor attribute */
00356 
00357   /* Set some defaults in variable structure for safety in case of early return
00358      Flags for variables without valid scaling information should appear 
00359      same as flags for variables with _no_ scaling information
00360      Set has_scl_fct, has_add_fst in var_dfl_set()
00361      typ_upk:
00362      1. is required by ncra nco_cnv_mss_val_typ() 
00363      2. depends on var->type and so should not be set in var_dfl_set()
00364      3. is therefore set to default here */
00365   var->typ_upk=var->type; /* [enm] Type of variable when unpacked (expanded) (in memory) */
00366 
00367   /* Vet scale_factor */
00368   rcd=nco_inq_att_flg(nc_id,var->id,scl_fct_sng,&scl_fct_typ,&scl_fct_lng);
00369   if(rcd != NC_ENOTATT){
00370     if(scl_fct_typ == NC_BYTE || scl_fct_typ == NC_CHAR){
00371       (void)fprintf(stdout,"%s: WARNING nco_pck_dsk_inq() reports scale_factor for %s is NC_BYTE or NC_CHAR. Will not attempt to unpack using scale_factor.\n",prg_nm_get(),var->nm); 
00372       return False;
00373     } /* endif */
00374     if(scl_fct_lng != 1){
00375       (void)fprintf(stdout,"%s: WARNING nco_pck_dsk_inq() reports %s has scale_factor of length %li. Will not attempt to unpack using scale_factor\n",prg_nm_get(),var->nm,scl_fct_lng); 
00376       return False;
00377     } /* endif */
00378     var->has_scl_fct=True; /* [flg] Valid scale_factor attribute exists */
00379     var->typ_upk=scl_fct_typ; /* [enm] Type of variable when unpacked (expanded) (in memory) */
00380   } /* endif */
00381 
00382   /* Vet add_offset */
00383   rcd=nco_inq_att_flg(nc_id,var->id,add_fst_sng,&add_fst_typ,&add_fst_lng);
00384   if(rcd != NC_ENOTATT){
00385     if(add_fst_typ == NC_BYTE || add_fst_typ == NC_CHAR){
00386       (void)fprintf(stdout,"%s: WARNING nco_pck_dsk_inq() reports add_offset for %s is NC_BYTE or NC_CHAR. Will not attempt to unpack using add_offset.\n",prg_nm_get(),var->nm); 
00387       return False;
00388     } /* endif */
00389     if(add_fst_lng != 1){
00390       (void)fprintf(stdout,"%s: WARNING nco_pck_dsk_inq() reports %s has add_offset of length %li. Will not attempt to unpack.\n",prg_nm_get(),var->nm,add_fst_lng); 
00391       return False;
00392     } /* endif */
00393     var->has_add_fst=True; /* [flg] Valid add_offset attribute exists */
00394     var->typ_upk=add_fst_typ; /* [enm] Type of variable when unpacked (expanded) (in memory) */
00395   } /* endif */
00396 
00397   if(var->has_scl_fct && var->has_add_fst){
00398     if(scl_fct_typ != add_fst_typ){
00399       (void)fprintf(stdout,"%s: WARNING nco_pck_dsk_inq() reports type of scale_factor does not equal type of add_offset. Will not attempt to unpack.\n",prg_nm_get());
00400       return False;
00401     } /* endif */
00402   } /* endif */
00403 
00404   if(var->has_scl_fct || var->has_add_fst){
00405     /* Variable is considered packed iff either or both valid scale_factor or add_offset exist */
00406     var->pck_dsk=True; /* [flg] Variable is packed on disk */
00407     /* If variable is packed on disk and is in memory then variable is packed in memory */
00408     var->pck_ram=True; /* [flg] Variable is packed in memory */
00409     var->typ_upk=(var->has_scl_fct) ? scl_fct_typ : add_fst_typ; /* [enm] Type of variable when unpacked (expanded) (in memory) */
00410     if(nco_is_rth_opr(prg_get()) && dbg_lvl_get() > 2){
00411       (void)fprintf(stdout,"%s: PACKING Variable %s is type %s packed into type %s\n",prg_nm_get(),var->nm,nco_typ_sng(var->typ_upk),nco_typ_sng(var->typ_dsk));
00412       (void)fprintf(stdout,"%s: DEBUG Packed variables processed by all arithmetic operators are unpacked automatically, and then stored unpacked in the output file. If you wish to repack them in the output file, use, e.g., ncap -O -s \"foo=pack(foo);\" out.nc out.nc. If you wish to pack all variables in a file, use, e.g., ncpdq -P all_new in.nc out.nc.\n",prg_nm_get());
00413     } /* endif print packing information */
00414   }else{
00415     /* Variable is not packed since neither scale factor nor add_offset exist
00416        Insert hooks which depend on variable not being packed here
00417        Currently this is no-op */
00418     ;
00419   } /* end else */
00420 
00421   return var->pck_dsk; /* [flg] Variable is packed on disk (valid scale_factor, add_offset, or both attributes exist) */
00422   
00423 } /* end nco_pck_dsk_inq() */

int nco_pck_map_get const char *  nco_pck_map_sng  ) 
 

Definition at line 133 of file nco_pck.c.

References EXIT_FAILURE, nco_exit(), nco_pck_map_flt_byt, nco_pck_map_flt_chr, nco_pck_map_flt_sht, nco_pck_map_hgh_byt, nco_pck_map_hgh_chr, nco_pck_map_hgh_sht, nco_pck_map_nil, nco_pck_map_nxt_lsr, and prg_nm_get().

Referenced by main().

00134 {
00135   /* Purpose: Process ncpdq '-P' command line argument
00136      Convert user-specified string to packing map
00137      Return nco_pck_map_nil by default */
00138   const char fnc_nm[]="nco_pck_map_get()"; /* [sng] Function name */
00139   char *prg_nm; /* [sng] Program name */
00140   prg_nm=prg_nm_get(); /* [sng] Program name */
00141 
00142   if(nco_pck_map_sng == NULL){ 
00143     (void)fprintf(stderr,"%s: ERROR %s reports empty user-specified packing map string %s\n",prg_nm,fnc_nm,nco_pck_map_sng);
00144     nco_exit(EXIT_FAILURE);
00145   } /* endif */
00146 
00147   if(!strcmp(nco_pck_map_sng,"hgh_sht")) return nco_pck_map_hgh_sht;
00148   if(!strcmp(nco_pck_map_sng,"pck_map_hgh_sht")) return nco_pck_map_hgh_sht;
00149   if(!strcmp(nco_pck_map_sng,"hgh_chr")) return nco_pck_map_hgh_chr;
00150   if(!strcmp(nco_pck_map_sng,"pck_map_hgh_chr")) return nco_pck_map_hgh_chr;
00151   if(!strcmp(nco_pck_map_sng,"hgh_byt")) return nco_pck_map_hgh_byt;
00152   if(!strcmp(nco_pck_map_sng,"pck_map_hgh_byt")) return nco_pck_map_hgh_byt;
00153   if(!strcmp(nco_pck_map_sng,"nxt_lsr")) return nco_pck_map_nxt_lsr;
00154   if(!strcmp(nco_pck_map_sng,"pck_map_nxt_lsr")) return nco_pck_map_nxt_lsr;
00155   if(!strcmp(nco_pck_map_sng,"flt_sht")) return nco_pck_map_flt_sht;
00156   if(!strcmp(nco_pck_map_sng,"pck_map_flt_sht")) return nco_pck_map_flt_sht;
00157   if(!strcmp(nco_pck_map_sng,"flt_chr")) return nco_pck_map_flt_chr;
00158   if(!strcmp(nco_pck_map_sng,"pck_map_flt_chr")) return nco_pck_map_flt_chr;
00159   if(!strcmp(nco_pck_map_sng,"flt_byt")) return nco_pck_map_flt_byt;
00160   if(!strcmp(nco_pck_map_sng,"pck_map_flt_byt")) return nco_pck_map_flt_byt;
00161 
00162   (void)fprintf(stderr,"%s: ERROR %s reports unknown user-specified packing policy %s\n",prg_nm_get(),fnc_nm,nco_pck_map_sng);
00163   nco_exit(EXIT_FAILURE);
00164   return nco_pck_map_nil; /* Statement should not be reached */
00165 } /* end nco_pck_map_get() */

const char* nco_pck_map_sng_get const int  nco_pck_map  ) 
 

Definition at line 25 of file nco_pck.c.

References nco_dfl_case_pck_map_err(), nco_pck_map_flt_byt, nco_pck_map_flt_chr, nco_pck_map_flt_sht, nco_pck_map_hgh_byt, nco_pck_map_hgh_chr, nco_pck_map_hgh_sht, nco_pck_map_nil, and nco_pck_map_nxt_lsr.

Referenced by main(), nco_pck_mtd(), and nco_pck_val().

00026 {
00027   /* Purpose: Convert packing map enum to string */
00028   switch(nco_pck_map){
00029   case nco_pck_map_nil:
00030     return "nil";
00031   case nco_pck_map_hgh_sht:
00032     return "hgh_sht";
00033   case nco_pck_map_hgh_chr:
00034     return "hgh_chr";
00035   case nco_pck_map_hgh_byt:
00036     return "hgh_byt";
00037   case nco_pck_map_nxt_lsr:
00038     return "nxt_lsr";
00039   case nco_pck_map_flt_sht:
00040     return "flt_sht";
00041   case nco_pck_map_flt_chr:
00042     return "flt_chr";
00043   case nco_pck_map_flt_byt:
00044     return "flt_byt";
00045   default: nco_dfl_case_pck_map_err(); break;
00046   } /* end switch */
00047   /* Some compilers, e.g., SGI cc, need return statement to end non-void functions */
00048   return (char *)NULL;
00049 } /* end nco_pck_map_sng_get() */

void nco_pck_mtd const var_sct *const   var_in,
var_sct *const   var_out,
const int  nco_pck_map,
const int  nco_pck_plc
 

Definition at line 427 of file nco_pck.c.

References dbg_lvl_get(), nco_dfl_case_pck_plc_err(), nco_pck_map_sng_get(), nco_pck_plc_all_new_att, nco_pck_plc_all_xst_att, nco_pck_plc_nil, nco_pck_plc_sng_get(), nco_pck_plc_typ_get(), nco_pck_plc_upk, nco_pck_plc_xst_new_att, nco_typ_sng(), var_sct_tag::nm, var_sct_tag::pck_ram, prg_nm_get(), var_sct_tag::typ_upk, and var_sct_tag::type.

Referenced by main().

00431 {
00432   /* Purpose: Alter metadata according to packing specification */
00433   const char fnc_nm[]="nco_pck_mtd()"; /* [sng] Function name */
00434   nc_type nc_typ_pck_out; /* [enm] Type to pack to */
00435   bool nco_pck_plc_alw; /* [flg] Packing policy allows packing nc_typ_in */
00436   
00437   switch(nco_pck_plc){
00438   case nco_pck_plc_all_xst_att:
00439     /* If variable is already packed do nothing otherwise pack to default type */
00440     if(var_in->pck_ram){
00441       if(dbg_lvl_get() > 2) (void)fprintf(stdout,"%s: DEBUG %s keeping existing packing parameters and type (%s) for %s\n",prg_nm_get(),fnc_nm,nco_typ_sng(var_in->type),var_in->nm);
00442     }else{
00443       goto var_upk_try_to_pck;
00444     } /* endif */
00445     break;
00446   case nco_pck_plc_xst_new_att:
00447     /* If variable is already packed then re-pack otherwise do nothing */
00448     if(var_in->pck_ram){
00449       goto var_pck_try_to_rpk;
00450     }else{
00451       /* Variable is not packed so do nothing */
00452       if(dbg_lvl_get() > 2) (void)fprintf(stdout,"%s: INFO %s leaving variable %s of type %s as unpacked\n",prg_nm_get(),fnc_nm,var_in->nm,nco_typ_sng(var_out->typ_upk));
00453     } /* endelse */
00454     break;
00455   case nco_pck_plc_all_new_att:
00456     if(var_in->pck_ram){
00457       goto var_pck_try_to_rpk;
00458     }else{
00459       goto var_upk_try_to_pck;
00460     } /* endif */
00461     break;
00462   case nco_pck_plc_upk:
00463     var_out->type=var_in->typ_upk;
00464     if(dbg_lvl_get() > 3){
00465       if(var_in->pck_ram) (void)fprintf(stdout,"%s: DEBUG %s will unpack variable %s from %s to %s\n",prg_nm_get(),fnc_nm,var_in->nm,nco_typ_sng(var_in->type),nco_typ_sng(var_out->type)); else (void)fprintf(stdout,"%s: DEBUG %s variable %s is already unpacked and of type %s\n",prg_nm_get(),fnc_nm,var_in->nm,nco_typ_sng(var_in->type)); 
00466     } /* endif dbg */
00467     break;
00468   case nco_pck_plc_nil:
00469   default: nco_dfl_case_pck_plc_err(); break;
00470   } /* end case */
00471 
00472   /* Return after finishing switch() statement and before falling through
00473      to code-saving goto branches */
00474   return;
00475 
00476  var_upk_try_to_pck: /* end goto */
00477   /* Variable is not yet packed---try to pack it */
00478   if((nco_pck_plc_alw=nco_pck_plc_typ_get(nco_pck_map,var_in->type,&nc_typ_pck_out))){
00479     var_out->type=nc_typ_pck_out;
00480     if(dbg_lvl_get() > 3) (void)fprintf(stdout,"%s: DEBUG %s will pack variable %s from %s to %s\n",prg_nm_get(),fnc_nm,var_in->nm,nco_typ_sng(var_in->type),nco_typ_sng(var_out->type));
00481   }else{
00482     if(dbg_lvl_get() > 2) (void)fprintf(stdout,"%s: INFO %s packing policy %s with packing map %s does not allow packing variable %s of type %s, skipping...\n",prg_nm_get(),fnc_nm,nco_pck_plc_sng_get(nco_pck_plc),nco_pck_map_sng_get(nco_pck_map),var_in->nm,nco_typ_sng(var_in->type));
00483   } /* endif nco_pck_plc_alw */
00484   return;
00485   
00486  var_pck_try_to_rpk: /* end goto */
00487   /* Variable is already packed---try to re-pack it 
00488      Final packed variable type may differ from original */
00489   if((nco_pck_plc_alw=nco_pck_plc_typ_get(nco_pck_map,var_in->typ_upk,&nc_typ_pck_out))){
00490     var_out->type=nc_typ_pck_out;
00491     if(dbg_lvl_get() > 3) (void)fprintf(stdout,"%s: DEBUG %s will re-pack variable %s of expanded type %s from current packing (type %s) into new packing of type %s\n",prg_nm_get(),fnc_nm,var_in->nm,nco_typ_sng(var_in->typ_upk),nco_typ_sng(var_in->type),nco_typ_sng(var_out->type));
00492   }else{
00493     if(dbg_lvl_get() > 2) (void)fprintf(stdout,"%s: WARNING %s variable %s of expanded type %s is already packed into type %s and re-packing is requested but packing policy %s and packing map %s does not allow re-packing variables of type %s\n",prg_nm_get(),fnc_nm,var_in->nm,nco_typ_sng(var_in->typ_upk),nco_typ_sng(var_in->type),nco_pck_plc_sng_get(nco_pck_plc),nco_pck_map_sng_get(nco_pck_map),nco_typ_sng(var_in->typ_upk));
00494   } /* endif nco_pck_plc_alw */
00495   return;
00496 
00497 } /* end nco_pck_mtd() */

int nco_pck_plc_get const char *  nco_pck_plc_sng  ) 
 

Definition at line 169 of file nco_pck.c.

References EXIT_FAILURE, nco_exit(), nco_pck_plc_all_new_att, nco_pck_plc_all_xst_att, nco_pck_plc_nil, nco_pck_plc_upk, nco_pck_plc_xst_new_att, and prg_nm_get().

Referenced by main().

00170 {
00171   /* Purpose: Process ncpdq '-P' command line argument
00172      Convert user-specified string to packing operation type 
00173      Return nco_pck_plc_nil by default */
00174   const char fnc_nm[]="nco_pck_plc_get()"; /* [sng] Function name */
00175   char *prg_nm; /* [sng] Program name */
00176   prg_nm=prg_nm_get(); /* [sng] Program name */
00177 
00178   if(nco_pck_plc_sng == NULL){
00179     if(strstr(prg_nm,"ncpdq")){
00180       (void)fprintf(stdout,"%s: INFO %s reports %s invoked without explicit packing or dimension permutation options. Defaulting to packing policy \"all_new\".\n",prg_nm,fnc_nm,prg_nm);
00181       return nco_pck_plc_all_new_att;
00182     } /* endif */
00183     if(strstr(prg_nm,"ncpack")) return nco_pck_plc_all_new_att;
00184     if(strstr(prg_nm,"ncunpack")) return nco_pck_plc_upk;
00185     (void)fprintf(stderr,"%s: ERROR %s reports empty user-specified packing string in conjunction with unknown or ambiguous executable name %s\n",prg_nm,fnc_nm,prg_nm);
00186     nco_exit(EXIT_FAILURE);
00187   } /* endif */
00188 
00189   if(!strcmp(nco_pck_plc_sng,"all_xst")) return nco_pck_plc_all_xst_att;
00190   if(!strcmp(nco_pck_plc_sng,"pck_all_xst_att")) return nco_pck_plc_all_xst_att;
00191   if(!strcmp(nco_pck_plc_sng,"all_new")) return nco_pck_plc_all_new_att;
00192   if(!strcmp(nco_pck_plc_sng,"pck_all_new_att")) return nco_pck_plc_all_new_att;
00193   if(!strcmp(nco_pck_plc_sng,"xst_new")) return nco_pck_plc_xst_new_att;
00194   if(!strcmp(nco_pck_plc_sng,"pck_xst_new_att")) return nco_pck_plc_xst_new_att;
00195   if(!strcmp(nco_pck_plc_sng,"upk")) return nco_pck_plc_upk;
00196   if(!strcmp(nco_pck_plc_sng,"unpack")) return nco_pck_plc_upk;
00197   if(!strcmp(nco_pck_plc_sng,"pck_upk")) return nco_pck_plc_upk;
00198 
00199   (void)fprintf(stderr,"%s: ERROR %s reports unknown user-specified packing policy %s\n",prg_nm_get(),fnc_nm,nco_pck_plc_sng);
00200   nco_exit(EXIT_FAILURE);
00201   return nco_pck_plc_nil; /* Statement should not be reached */
00202 } /* end nco_pck_plc_get() */

const char* nco_pck_plc_sng_get const int  nco_pck_plc  ) 
 

Definition at line 53 of file nco_pck.c.

References nco_dfl_case_pck_plc_err(), nco_pck_plc_all_new_att, nco_pck_plc_all_xst_att, nco_pck_plc_nil, nco_pck_plc_upk, and nco_pck_plc_xst_new_att.

Referenced by main(), nco_pck_mtd(), and nco_pck_val().

00054 {
00055   /* Purpose: Convert packing policy enum to string */
00056   switch(nco_pck_plc){
00057   case nco_pck_plc_nil:
00058     return "nil";
00059   case nco_pck_plc_all_xst_att: 
00060     return "all_xst";
00061   case nco_pck_plc_all_new_att: 
00062     return "all_new";
00063   case nco_pck_plc_xst_new_att: 
00064     return "xst_new";
00065   case nco_pck_plc_upk:
00066     return "upk";
00067   default: nco_dfl_case_pck_plc_err(); break;
00068   } /* end switch */
00069   /* Some compilers, e.g., SGI cc, need return statement to end non-void functions */
00070   return (char *)NULL;
00071 } /* end nco_pck_plc_sng_get() */

bool nco_pck_plc_typ_get const int  nco_pck_map,
const nc_type  nc_typ_in,
nc_type nc_typ_pck_out
 

Definition at line 206 of file nco_pck.c.

References False, NC_BYTE, NC_CHAR, NC_DOUBLE, NC_FLOAT, NC_INT, NC_NAT, NC_SHORT, nco_dfl_case_nc_type_err(), nco_err_exit(), nco_pck_map_flt_byt, nco_pck_map_flt_chr, nco_pck_map_flt_sht, nco_pck_map_hgh_byt, nco_pck_map_hgh_chr, nco_pck_map_hgh_sht, nco_pck_map_nil, nco_pck_map_nxt_lsr, prg_nm_get(), and True.

Referenced by main(), nco_pck_mtd(), nco_pck_val(), nco_var_dfn(), and nco_var_lst_dvd().

00209 {
00210   /* Purpose: Determine type, if any, to pack input type to
00211      Routine enforces policy specified by nco_pck_map
00212      Replacement for simple deprecated routine nco_is_packable()
00213      There are two cases:
00214      1. nco_pck_map allows packing nc_typ_in:
00215         Routine returns true and sets nc_typ_pck_out accordingly
00216      2. nco_pck_map does not allow packing nc_typ_in:
00217         Routine returns false and sets nc_typ_pck_out=nc_typ_in
00218      In both cases, nc_typ_pck_out is only set if it is non-NULL */
00219 
00220   const char fnc_nm[]="nco_pck_plc_typ_get()"; /* [sng] Function name */
00221   bool nco_pck_plc_alw; /* O [flg] Packing policy allows packing nc_typ_in */
00222   nc_type nc_typ_pck_out_tmp; /* O [enm] Type to pack variable to */
00223 
00224   /* Initialize output type to NAT and pack allow to False to help catch errors */
00225   nc_typ_pck_out_tmp=NC_NAT;
00226   nco_pck_plc_alw=False;
00227   switch(nco_pck_map){ 
00228   case nco_pck_map_nil:
00229     nc_typ_pck_out_tmp=nc_typ_in; nco_pck_plc_alw=False; break;
00230   case nco_pck_map_hgh_sht:
00231     switch(nc_typ_in){ 
00232     case NC_DOUBLE: 
00233     case NC_FLOAT: 
00234     case NC_INT: 
00235       nc_typ_pck_out_tmp=NC_SHORT; nco_pck_plc_alw=True; break;
00236     case NC_SHORT: 
00237     case NC_CHAR: 
00238     case NC_BYTE: 
00239       nc_typ_pck_out_tmp=nc_typ_in; nco_pck_plc_alw=False; break;
00240     default: nco_dfl_case_nc_type_err(); break;
00241     } /* end nc_type switch */ 
00242     break;
00243   case nco_pck_map_hgh_chr:
00244     switch(nc_typ_in){ 
00245     case NC_DOUBLE: 
00246     case NC_FLOAT: 
00247     case NC_INT: 
00248     case NC_SHORT: 
00249       nc_typ_pck_out_tmp=NC_CHAR; nco_pck_plc_alw=True; break;
00250     case NC_CHAR: 
00251     case NC_BYTE: 
00252       nc_typ_pck_out_tmp=nc_typ_in; nco_pck_plc_alw=False; break;
00253     default: nco_dfl_case_nc_type_err(); break;
00254     } /* end nc_type switch */ 
00255     break;
00256   case nco_pck_map_hgh_byt:
00257     switch(nc_typ_in){ 
00258     case NC_DOUBLE: 
00259     case NC_FLOAT: 
00260     case NC_INT: 
00261     case NC_SHORT: 
00262       nc_typ_pck_out_tmp=NC_BYTE; nco_pck_plc_alw=True; break;
00263     case NC_CHAR: 
00264     case NC_BYTE: 
00265       nc_typ_pck_out_tmp=nc_typ_in; nco_pck_plc_alw=False; break;
00266     default: nco_dfl_case_nc_type_err(); break;
00267     } /* end nc_type switch */ 
00268     break;
00269   case nco_pck_map_nxt_lsr:
00270     switch(nc_typ_in){ 
00271     case NC_DOUBLE: nc_typ_pck_out_tmp=NC_INT; nco_pck_plc_alw=True; break; 
00272     case NC_FLOAT: 
00273     case NC_INT: 
00274       nc_typ_pck_out_tmp=NC_SHORT; nco_pck_plc_alw=True; break;
00275     case NC_SHORT: nc_typ_pck_out_tmp=NC_BYTE; nco_pck_plc_alw=True; break;
00276     case NC_CHAR: 
00277     case NC_BYTE: 
00278       nc_typ_pck_out_tmp=nc_typ_in; nco_pck_plc_alw=False; break;
00279     default: nco_dfl_case_nc_type_err(); break;
00280     } /* end nc_type switch */ 
00281     break;
00282   case nco_pck_map_flt_sht:
00283     switch(nc_typ_in){ 
00284     case NC_DOUBLE: 
00285     case NC_FLOAT: 
00286       nc_typ_pck_out_tmp=NC_SHORT; nco_pck_plc_alw=True; break;
00287     case NC_INT:
00288     case NC_SHORT:
00289     case NC_CHAR:
00290     case NC_BYTE:
00291       nc_typ_pck_out_tmp=nc_typ_in; nco_pck_plc_alw=False; break;
00292     default: nco_dfl_case_nc_type_err(); break;
00293     } /* end nc_type switch */ 
00294     break;
00295   case nco_pck_map_flt_chr:
00296     switch(nc_typ_in){ 
00297     case NC_DOUBLE: 
00298     case NC_FLOAT: 
00299       nc_typ_pck_out_tmp=NC_CHAR; nco_pck_plc_alw=True; break;
00300     case NC_INT:
00301     case NC_SHORT:
00302     case NC_CHAR:
00303     case NC_BYTE:
00304       nc_typ_pck_out_tmp=nc_typ_in; nco_pck_plc_alw=False; break;
00305     default: nco_dfl_case_nc_type_err(); break;
00306     } /* end nc_type switch */ 
00307     break;
00308   case nco_pck_map_flt_byt:
00309     switch(nc_typ_in){ 
00310     case NC_DOUBLE: 
00311     case NC_FLOAT: 
00312       nc_typ_pck_out_tmp=NC_BYTE; nco_pck_plc_alw=True; break;
00313     case NC_INT:
00314     case NC_SHORT:
00315     case NC_CHAR:
00316     case NC_BYTE:
00317       nc_typ_pck_out_tmp=nc_typ_in; nco_pck_plc_alw=False; break;
00318     default: nco_dfl_case_nc_type_err(); break;
00319     } /* end nc_type switch */ 
00320     break;
00321   default: 
00322     (void)fprintf(stdout,"%s: ERROR %s reports switch(nco_pck_map) statement fell through to default case\n",prg_nm_get(),fnc_nm);
00323     nco_err_exit(0,fnc_nm);
00324     break;
00325   } /* end nco_pck_map switch */ 
00326   
00327   /* Only fill in nc_typ_pck_out if it is non-NULL */
00328   if(nc_typ_pck_out != NULL) *nc_typ_pck_out=nc_typ_pck_out_tmp;
00329 
00330   return nco_pck_plc_alw; /* O [flg] Packing policy allows packing nc_typ_in */
00331 } /* end nco_pck_plc_typ_get() */

void nco_pck_val var_sct *const   var_in,
var_sct var_out,
const int  nco_pck_map,
const int  nco_pck_plc,
aed_sct *const   aed_lst_add_fst,
aed_sct *const   aed_lst_scl_fct
 

Definition at line 501 of file nco_pck.c.

References aed_delete, aed_overwrite, dbg_lvl_get(), False, nco_dfl_case_pck_plc_err(), nco_pck_map_sng_get(), nco_pck_plc_all_new_att, nco_pck_plc_all_xst_att, nco_pck_plc_nil, nco_pck_plc_sng_get(), nco_pck_plc_typ_get(), nco_pck_plc_upk, nco_pck_plc_xst_new_att, nco_typ_sng(), nco_var_pck(), nco_var_upk_swp(), var_sct_tag::nm, var_sct_tag::pck_ram, prg_nm_get(), var_sct_tag::typ_dsk, var_sct_tag::val, and ptr_unn::vp.

Referenced by main().

00507 {
00508   /* Purpose: Alter metadata according to packing specification */
00509   const char fnc_nm[]="nco_pck_val()"; /* [sng] Function name */
00510   bool PCK_VAR_WITH_NEW_PCK_ATT=False; /* [flg] Insert new scale_factor and add_offset into lists */
00511   nc_type typ_out; /* [enm] Type in output file */
00512   bool nco_pck_plc_alw; /* [flg] Packing policy allows packing nc_typ_in */
00513   
00514   /* typ_out contains type of variable defined in output file
00515      as defined by var_out->type which was set in var_pck_mtd() 
00516      We will temporarily set var_out->type to RAM type of variable
00517      Packing routine will re-set var_out->type to typ_out if necessary */
00518   typ_out=var_out->type; /* [enm] Type in output file */
00519   
00520   switch(nco_pck_plc){
00521   case nco_pck_plc_all_xst_att:
00522     /* nco_var_pck() expects to alter var_out->type itself, if necessary */
00523     var_out->type=var_in->typ_dsk;
00524     if(var_in->pck_ram){
00525       if(dbg_lvl_get() > 3) (void)fprintf(stdout,"%s: INFO %s keeping existing packing attributes for variable %s\n",prg_nm_get(),fnc_nm,var_in->nm);
00526       /* Warn if packing attribute values are in memory for pre-packed variables */
00527       if(var_out->scl_fct.vp != NULL || var_out->add_fst.vp != NULL) (void)fprintf(stdout,"%s: WARNING %s reports variable %s has packing attribute values in memory. This is not supposed to happen through known code paths, but is not necessarily dangerous.\n",prg_nm_get(),fnc_nm,var_in->nm);
00528       /* Remove dangling pointer, see explanation below */
00529       var_in->val.vp=NULL; 
00530     }else{
00531       goto var_upk_try_to_pck; /* end goto */
00532     } /* endif input variable was not packed */
00533     break;
00534   case nco_pck_plc_xst_new_att:
00535     if(var_in->pck_ram){
00536       nco_var_upk_swp(var_in,var_out);
00537       goto var_upk_try_to_pck;
00538     }else{
00539       /* Remove dangling pointer, see explanation below */
00540       var_in->val.vp=NULL; 
00541     } /* endif */
00542     break;
00543   case nco_pck_plc_all_new_att:
00544     if(var_in->pck_ram){
00545       /* Variable is already packed---unpack it before re-packing it */
00546       nco_var_upk_swp(var_in,var_out);
00547     }else{
00548       /* nco_var_pck() expects to alter var_out->type itself, if necessary */
00549       var_out->type=var_in->typ_dsk;
00550     } /* endif */
00551     goto var_upk_try_to_pck; 
00552     break;
00553   case nco_pck_plc_upk:
00554     /* Unpack if possible, otherwise remove dangling pointer (explanation below) */
00555     if(var_in->pck_ram) nco_var_upk_swp(var_in,var_out); else var_in->val.vp=NULL; 
00556     break;
00557   case nco_pck_plc_nil:
00558   default: nco_dfl_case_pck_plc_err(); break;
00559   } /* end case */
00560 
00561   /* Ensure code goes to final block before falling through to next goto */
00562   goto put_new_pck_att_in_lst;
00563 
00564  var_upk_try_to_pck: /* end goto */
00565   /* Variable is not yet packed---try to pack it */
00566   if((nco_pck_plc_alw=nco_pck_plc_typ_get(nco_pck_map,var_out->type,(nc_type *)NULL))){
00567     if(dbg_lvl_get() > 3) (void)fprintf(stdout,"%s: INFO %s packing variable %s values from %s to %s\n",prg_nm_get(),fnc_nm,var_in->nm,nco_typ_sng(var_out->typ_upk),nco_typ_sng(typ_out));
00568     var_out=nco_var_pck(var_out,typ_out,&PCK_VAR_WITH_NEW_PCK_ATT);
00569   }else{
00570     if(dbg_lvl_get() > 2) (void)fprintf(stdout,"%s: INFO %s packing policy %s with packing map %s does not allow packing variable %s of type %s, skipping...\n",prg_nm_get(),fnc_nm,nco_pck_plc_sng_get(nco_pck_plc),nco_pck_map_sng_get(nco_pck_map),var_in->nm,nco_typ_sng(var_out->typ_upk));
00571   } /* endif nco_pck_plc_alw */ 
00572   /* Packing function nco_var_pck() usually free()'s var_out->val.vp 
00573      Hence var_in->val.vp is left with a dangling pointer
00574      In ncpdq, var_in->val.vp and var_out->val.vp point to same buffer 
00575      This reduces peak memory consumption by ~50%, but is dangerous */
00576   var_in->val.vp=NULL; 
00577   /* Ensure code goes to final block before falling through to next goto */
00578   goto put_new_pck_att_in_lst;
00579   
00580  put_new_pck_att_in_lst: /* end goto */
00581   /* Fill attribute edit structures
00582      Use values directly from variable structures rather than copying
00583      Attribute structure dynamic memory will be free()'d in nco_var_free() call */
00584   if(PCK_VAR_WITH_NEW_PCK_ATT){
00585     aed_lst_add_fst->var_nm=aed_lst_scl_fct->var_nm=var_out->nm;
00586     aed_lst_add_fst->id=aed_lst_scl_fct->id=var_out->id;
00587     aed_lst_add_fst->sz=aed_lst_scl_fct->sz=1L;
00588     aed_lst_add_fst->type=aed_lst_scl_fct->type=var_out->typ_upk;
00589     /* Packing generates at least one of scale_factor or add_offset,
00590        but not necessarily both.
00591        Delete pre-defined attributes for those which were not created */
00592     if(var_out->has_add_fst) aed_lst_add_fst->mode=aed_overwrite; else aed_lst_add_fst->mode=aed_delete;
00593     if(var_out->has_scl_fct) aed_lst_scl_fct->mode=aed_overwrite; else aed_lst_scl_fct->mode=aed_delete;
00594     /* Insert values into attribute structures */
00595     aed_lst_add_fst->val=var_out->add_fst;
00596     aed_lst_scl_fct->val=var_out->scl_fct;
00597   } /* endif */
00598 
00599 } /* end nco_pck_val() */

var_sct* nco_put_var_pck const int  out_id,
var_sct var,
const int  nco_pck_plc
 

Definition at line 603 of file nco_pck.c.

References False, nco_dfl_case_pck_plc_err(), nco_pck_plc_all_new_att, nco_pck_plc_all_xst_att, nco_pck_plc_nil, nco_pck_plc_upk, nco_pck_plc_xst_new_att, nco_put_att(), and nco_var_pck().

Referenced by main().

00606 {
00607   /* Purpose: Pack variable in memory and write packing attributes to disk
00608      NB: Routine is not complete, debugged, or currently used 
00609      ncpdq breaks up writing packed variables into multiple tasks, i.e.,
00610      ncpdq separates variable value writes from packing attribute value writes.
00611      This routine is intended to write a packed variable in one routine */
00612   bool PCK_VAR_WITH_NEW_PCK_ATT=False; /* [flg] Insert new scale_factor and add_offset into lists */
00613   
00614   switch(nco_pck_plc){
00615   case nco_pck_plc_all_xst_att:
00616     break;
00617   case nco_pck_plc_xst_new_att:
00618     break;
00619   case nco_pck_plc_all_new_att:
00620     break;
00621   case nco_pck_plc_upk:
00622     break;
00623   case nco_pck_plc_nil:
00624   default: nco_dfl_case_pck_plc_err(); break;
00625   } /* end switch */
00626 
00627   /* Pack variable */
00628   if(var->xrf->pck_dsk && !var->xrf->pck_ram) var=nco_var_pck(var,var->typ_pck,&PCK_VAR_WITH_NEW_PCK_ATT);
00629 
00630   /* Write/overwrite scale_factor and add_offset attributes */
00631   if(var->pck_ram){ /* [flg] Variable is packed in memory */
00632     if(var->has_scl_fct){ /* [flg] Valid scale_factor attribute exists */
00633       (void)nco_put_att(out_id,var->id,"scale_factor",var->typ_upk,1,var->scl_fct.vp);
00634     } /* endif has_scl_fct */
00635     if(var->has_add_fst){ /* [flg] Valid add_offset attribute exists */
00636       (void)nco_put_att(out_id,var->id,"add_offset",var->typ_upk,1,var->add_fst.vp);
00637     } /* endif has_add_fst */
00638   } /* endif pck_ram */
00639   
00640   return var;
00641   
00642 } /* end nco_put_var_pck() */

var_sct* nco_var_pck var_sct var,
const nc_type  typ_pck,
bool *  PCK_VAR_WITH_NEW_PCK_ATT
 

Definition at line 646 of file nco_pck.c.

References var_sct_tag::add_fst, val_unn::d, dbg_lvl_get(), double_CEWI, ptr_unn::dp, EXIT_FAILURE, False, var_sct_tag::has_add_fst, var_sct_tag::has_mss_val, var_sct_tag::has_scl_fct, var_sct_tag::mss_val, 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_exit(), nco_free(), nco_malloc(), nco_scv_cnf_typ(), nco_typ_lng(), nco_typ_sng(), nco_val_cnf_typ(), nco_var_add(), nco_var_avg_reduce_max(), nco_var_avg_reduce_min(), nco_var_cnf_typ(), nco_var_dpl(), nco_var_dvd(), nco_var_free(), nco_var_mlt(), nco_var_sbt(), var_sct_tag::nm, var_sct_tag::pck_ram, prg_nm_get(), ptr_unn_2_scl_dbl(), var_sct_tag::scl_fct, scl_mk_var(), scl_ptr_mk_var(), var_sct_tag::sz, True, var_sct_tag::typ_pck, var_sct_tag::typ_upk, scv_sct::type, var_sct_tag::type, scv_sct::val, var_sct_tag::val, var_scv_dvd(), var_scv_sub(), and ptr_unn::vp.

Referenced by nco_pck_val(), and nco_put_var_pck().

00649 {
00650   /* Purpose: Pack variable 
00651      Routine is inverse of nco_var_upk(): nco_var_pck[nco_var_upk(var)]=var 
00652      Currently routine outputs same variable structure as given on input
00653      In other words, output structure may be neglected as all changes are made 
00654      to input structure.
00655      NB: Value buffer var->val.vp is usually free()'d here
00656      Variables in calling routine which point to var->val.vp will be left dangling */
00657 
00658   bool PURE_MSS_VAL_FLD=False; /* [flg] Field is pure missing_value, i.e., no valid values */
00659   const char fnc_nm[]="nco_var_pck()"; /* [sng] Function name */
00660   double scl_fct_dbl=double_CEWI; /* [sct] Double precision value of scale_factor */
00661   double add_fst_dbl=double_CEWI; /* [sct] Double precision value of add_offset */
00662 
00663   /* Set flag true once new scale_factor/add_offset generated */
00664   *PCK_VAR_WITH_NEW_PCK_ATT=False;
00665 
00666   /* Return if variable in memory is currently packed and should not be re-packed */
00667   if(var->pck_ram) return var;
00668 
00669   /* Routine should be called with variable already in memory */
00670   if(var->val.vp == NULL) (void)fprintf(stdout,"%s: ERROR %s called with empty var->val.vp\n",prg_nm_get(),fnc_nm);
00671   
00672   /* Packed type must be NC_BYTE, NC_CHAR, NC_SHORT, or NC_INT */
00673   if(nc_typ_pck == NC_FLOAT || nc_typ_pck == NC_DOUBLE){
00674     (void)fprintf(stdout,"%s: ERROR %s called to pack variable %s with invalid packed type nc_typ_pck = %s\n",prg_nm_get(),fnc_nm,var->nm,nco_typ_sng(nc_typ_pck));
00675     nco_exit(EXIT_FAILURE);
00676   } /* endif */
00677 
00678   /* Variable must be packable (usually NC_INT, NC_FLOAT, or NC_DOUBLE)
00679      Definition of "packable" determined by nco_pck_plc_typ_get()
00680      Prefer not to make nco_var_pck() rely directly on nco_pck_plc_typ_get()
00681      However, certain types are never packable */
00682   if(var->type == NC_CHAR || var->type == NC_BYTE){
00683     (void)fprintf(stdout,"%s: ERROR %s is asked to pack variable %s of type %s\n",prg_nm_get(),fnc_nm,var->nm,nco_typ_sng(var->type));
00684     nco_exit(EXIT_FAILURE);
00685   } /* endif */
00686 
00687   if(True){ /* Keep in own scope for eventual functionalization of core packing algorithm */
00688     /* Compute packing parameters to apply to var
00689 
00690        Linear packing in a nutshell:
00691        scale_factor = (max-min)/ndrv <--> (max-min)/scale_factor = ndrv <--> scale_factor*ndrv = max-min
00692        add_offset = 0.5*(min+max)
00693        pck = (upk-add_offset)/scale_factor = (upk-0.5*(min+max))*ndrv/(max-min)
00694        upk = scale_factor*pck + add_offset = (max-min)*pck/ndrv + 0.5*(min+max) 
00695 
00696        where 
00697 
00698        ndrv = number of discrete representable values for given type of packed variable and
00699        ndrv = 256 iff var->typ_pck == NC_CHAR
00700        ndrv = 256*256 iff var->typ_pck == NC_SHORT
00701        ndrv = 256*256*256*256 = 2^32 iff var->typ_pck == NC_INT */
00702 
00703     const double max_mns_min_dbl_wrn=1.0e10; /* [frc] Threshold value for warning */
00704     double ndrv_dbl=double_CEWI; /* [frc] Double precision value of number of discrete representable values */
00705     double max_mns_min_dbl; /* [frc] Maximum value minus minimum value */
00706 
00707     ptr_unn ptr_unn_min; /* [ptr] Pointer union to minimum value of variable */
00708     ptr_unn ptr_unn_max; /* [ptr] Pointer union to maximum value of variable */
00709     ptr_unn ptr_unn_mss_val_dbl; /* [ptr] Pointer union to missing value of variable */
00710     
00711     var_sct *min_var; /* [sct] Minimum value of variable */
00712     var_sct *max_var; /* [sct] Maximum value of variable */
00713     var_sct *max_var_dpl; /* [sct] Copy of Maximum value of variable */
00714     var_sct *hlf_var; /* [sct] NCO variable for value 0.5 */
00715     var_sct *zero_var; /* [sct] NCO variable for value 0.0 */
00716     var_sct *ndrv_var; /* [sct] NCO variable for number of discrete representable values */
00717     
00718     val_unn hlf_unn; /* [frc] Generic container for value 0.5 */
00719     val_unn zero_unn; /* [frc] Generic container for value 0.0 */
00720     val_unn ndrv_unn; /* [nbr] Generic container for number of discrete representable values */
00721 
00722     /* Initialize data */
00723     hlf_unn.d=0.5; /* Generic container for value 0.5 */
00724     zero_unn.d=0.0; /* Generic container for value 0.0 */
00725 
00726     /* Derive scalar values for scale_factor and add_offset */
00727     var->scl_fct.vp=nco_free(var->scl_fct.vp);
00728     var->add_fst.vp=nco_free(var->add_fst.vp);
00729     var->scl_fct.vp=(void *)nco_malloc(nco_typ_lng(var->type));
00730     var->add_fst.vp=(void *)nco_malloc(nco_typ_lng(var->type));
00731     ptr_unn_min.vp=(void *)nco_malloc(nco_typ_lng(var->type));
00732     ptr_unn_max.vp=(void *)nco_malloc(nco_typ_lng(var->type));
00733 
00734     /* Create double precision missing_value for use in min/max arithmetic */
00735     if(var->has_mss_val){
00736       ptr_unn_mss_val_dbl.vp=(void *)nco_malloc(nco_typ_lng((nc_type)NC_DOUBLE));
00737       (void)nco_val_cnf_typ(var->type,var->mss_val,(nc_type)NC_DOUBLE,ptr_unn_mss_val_dbl);
00738     } /* endif has_mss_val */
00739 
00740     /* Find minimum and maximum values in data */
00741     (void)nco_var_avg_reduce_max(var->type,var->sz,1L,var->has_mss_val,var->mss_val,var->val,ptr_unn_min);
00742     (void)nco_var_avg_reduce_min(var->type,var->sz,1L,var->has_mss_val,var->mss_val,var->val,ptr_unn_max);
00743 
00744     /* Convert to NC_DOUBLE before 0.5*(min+max) operation */
00745     min_var=scl_ptr_mk_var(ptr_unn_min,var->type);
00746     min_var=nco_var_cnf_typ((nc_type)NC_DOUBLE,min_var);
00747     max_var=scl_ptr_mk_var(ptr_unn_max,var->type);
00748     max_var=nco_var_cnf_typ((nc_type)NC_DOUBLE,max_var);
00749     /* Copy max_var for use in scale_factor computation */
00750     max_var_dpl=nco_var_dpl(max_var);
00751     hlf_var=scl_mk_var(hlf_unn,NC_DOUBLE); /* [sct] NCO variable for value one half */
00752 
00753     /* Field is pure missing_value iff either extrema is missing_value */
00754     if(var->has_mss_val)
00755       if(min_var->val.dp[0] == ptr_unn_mss_val_dbl.dp[0]) 
00756         PURE_MSS_VAL_FLD=True;
00757 
00758     /* Change value of missing value iff necessary to fit inside packed type */
00759     if(var->has_mss_val && !PURE_MSS_VAL_FLD){
00760       double mss_val_dfl_dbl=0.0; /* CEWI */
00761       switch(nc_typ_pck){ 
00762       case NC_FLOAT: mss_val_dfl_dbl=NC_FILL_FLOAT; break; 
00763       case NC_DOUBLE: mss_val_dfl_dbl=NC_FILL_DOUBLE; break; 
00764       case NC_INT: mss_val_dfl_dbl=NC_FILL_INT; break;
00765       case NC_SHORT: mss_val_dfl_dbl=NC_FILL_SHORT; break;
00766       case NC_CHAR: mss_val_dfl_dbl=NC_FILL_CHAR; break;
00767       case NC_BYTE: mss_val_dfl_dbl=NC_FILL_BYTE; break;
00768       default: nco_dfl_case_nc_type_err(); break;
00769       } /* end switch */ 
00770       if(dbg_lvl_get() > 3) (void)fprintf(stdout,"%s: %s mss_val_dfl = %g\n",prg_nm_get(),fnc_nm,mss_val_dfl_dbl);
00771     } /* endif */
00772 
00773     if(dbg_lvl_get() > 3) (void)fprintf(stdout,"%s: %s: min_var = %g, max_var = %g\n",prg_nm_get(),var->nm,min_var->val.dp[0],max_var->val.dp[0]);
00774 
00775     /* add_offset is 0.5*(min+max) */
00776     /* max_var->val is overridden with add_offset answers, no longer valid as max_var */
00777     (void)nco_var_add((nc_type)NC_DOUBLE,1L,var->has_mss_val,ptr_unn_mss_val_dbl,min_var->val,max_var->val);
00778     (void)nco_var_mlt((nc_type)NC_DOUBLE,1L,var->has_mss_val,ptr_unn_mss_val_dbl,hlf_var->val,max_var->val);
00779     /* Contents of max_var are actually add_offset */
00780     (void)nco_val_cnf_typ((nc_type)NC_DOUBLE,max_var->val,var->type,var->add_fst);
00781 
00782     /* ndrv is 2^{bits per packed value} where bppv = 8 for NC_CHAR and bppv = 16 for NC_SHORT
00783        Subtract one to leave slop for rounding errors
00784        Subtract two to leave room for missing_value? */
00785     if(nc_typ_pck == NC_BYTE || nc_typ_pck == NC_CHAR){
00786       ndrv_dbl=256.0-1.0; /* [sct] Double precision value of number of discrete representable values */
00787     }else if(nc_typ_pck == NC_SHORT){
00788       ndrv_dbl=65536.0-1.0; /* [sct] Double precision value of number of discrete representable values */
00789     }else if(nc_typ_pck == NC_INT){
00790       ndrv_dbl=4294967295.0-1.0; /* [sct] Double precision value of number of discrete representable values */
00791     } /* end else */
00792     ndrv_unn.d=ndrv_dbl; /* Generic container for number of discrete representable values */
00793     ndrv_var=scl_mk_var(ndrv_unn,NC_DOUBLE); /* [sct] Variable structure for number of discrete representable values */
00794 
00795     /* scale_factor is (max-min)/ndrv
00796        If max-min = 0 then variable is constant value so scale_factor=0.0 and add_offset=var
00797        If max-min > ndrv then precision is worse than 1.0
00798        If max-min < ndrv then precision is better than 1.0 */
00799     (void)nco_var_sbt((nc_type)NC_DOUBLE,1L,var->has_mss_val,ptr_unn_mss_val_dbl,min_var->val,max_var_dpl->val);
00800     /* max-min is currently stored in max_var_dpl */
00801     max_mns_min_dbl=ptr_unn_2_scl_dbl(max_var_dpl->val,max_var_dpl->type); 
00802 
00803     /* Manually set max-min=0.0 for pure missing_value fields to set add_offset correctly */
00804     if(PURE_MSS_VAL_FLD) max_mns_min_dbl=0.0;
00805 
00806     if(max_mns_min_dbl != 0.0){
00807       (void)nco_var_dvd((nc_type)NC_DOUBLE,1L,var->has_mss_val,ptr_unn_mss_val_dbl,ndrv_var->val,max_var_dpl->val);
00808       /* Contents of max_var_dpl are actually scale_factor */
00809       (void)nco_val_cnf_typ((nc_type)NC_DOUBLE,max_var_dpl->val,var->type,var->scl_fct);
00810     }else{
00811       /* Variable is constant, i.e., equal values everywhere */
00812       zero_var=scl_mk_var(zero_unn,var->type); /* [sct] NCO variable for value 0.0 */
00813       /* Set scale_factor to 0.0 */
00814       (void)memcpy(var->scl_fct.vp,zero_var->val.vp,nco_typ_lng(var->type));
00815       if(zero_var != NULL) zero_var=nco_var_free(zero_var);
00816       /* Set add_offset to first variable value 
00817          Variable is constant everywhere so particular value copied is unimportant */
00818       (void)memcpy(var->add_fst.vp,var->val.vp,nco_typ_lng(var->type));
00819     } /* end else */
00820 
00821     if(max_mns_min_dbl > max_mns_min_dbl_wrn){
00822       (void)fprintf(stdout,"%s: WARNING %s reports data range of variable %s is = %g. The linear data packing technique defined by netCDF's packing convention and implemented by NCO result in significant precision loss over such a great range.\n",prg_nm_get(),fnc_nm,var->nm,max_mns_min_dbl);
00823       if(var->has_mss_val) (void)fprintf(stdout,"%s: HINT variable %s has missing_value = %g. Consider specifying new missing_value to reduce range of data needing packing. See http://nco.sf.net/nco.html#ncatted for examples of how to change the missing_value attribute.\n",prg_nm_get(),fnc_nm,ptr_unn_mss_val_dbl.dp[0]);
00824     } /* endif large data range */
00825 
00826     /* Free minimum and maximum values */
00827     ptr_unn_min.vp=nco_free(ptr_unn_min.vp);
00828     ptr_unn_max.vp=nco_free(ptr_unn_max.vp);
00829 
00830     /* Free temporary double missing_value */
00831     if(var->has_mss_val) ptr_unn_mss_val_dbl.vp=nco_free(ptr_unn_mss_val_dbl.vp);
00832 
00833     /* Free variables */
00834     if(min_var != NULL) min_var=nco_var_free(min_var);
00835     if(max_var != NULL) max_var=nco_var_free(max_var);
00836     if(max_var_dpl != NULL) max_var_dpl=nco_var_free(max_var_dpl);
00837     if(hlf_var != NULL) hlf_var=nco_var_free(hlf_var);
00838     if(ndrv_var != NULL) ndrv_var=nco_var_free(ndrv_var);
00839 
00840     /* Do not bother creating superfluous scale_factor (0.0 or 1.0) or add_offset (0.0) */
00841     scl_fct_dbl=ptr_unn_2_scl_dbl(var->scl_fct,var->type); 
00842     add_fst_dbl=ptr_unn_2_scl_dbl(var->add_fst,var->type);
00843 
00844     if(scl_fct_dbl != 0.0 && scl_fct_dbl != 1.0) var->has_scl_fct=True; /* [flg] Valid scale_factor attribute exists */
00845     if(add_fst_dbl != 0.0) var->has_add_fst=True; /* [flg] Valid add_offset attribute exists */
00846 
00847     /* However, must create either scale_factor or add_offset
00848        Otherwise, routine fails to pack field uniformly equal to zero (0.0)
00849        In zero corner case, create add_offset (avoids division by zero problems) */
00850     if(scl_fct_dbl == 0.0 && add_fst_dbl == 0.0) var->has_add_fst=True; 
00851 
00852   } /* endif True */
00853 
00854   /* Create double precision value of scale_factor for diagnostics */
00855   if(var->has_scl_fct){ /* [flg] Valid scale_factor attribute exists */
00856     scl_fct_dbl=ptr_unn_2_scl_dbl(var->scl_fct,var->type); 
00857     if(scl_fct_dbl == 0.0) (void)fprintf(stdout,"%s: WARNING %s reports scl_fct_dbl = 0.0\n",prg_nm_get(),fnc_nm);
00858   } /* endif */
00859   
00860   /* Create double precision value of add_offset for diagnostics */
00861   if(var->has_add_fst){ /* [flg] Valid add_offset attribute exists */
00862     add_fst_dbl=ptr_unn_2_scl_dbl(var->add_fst,var->type);
00863   } /* endif */
00864   
00865   if(dbg_lvl_get() > 3) (void)fprintf(stdout,"%s: %s reports variable %s has scl_fct_dbl = %g, add_fst_dbl = %g\n",prg_nm_get(),fnc_nm,var->nm,scl_fct_dbl,add_fst_dbl);
00866   
00867   /* Packing attributes now exist and are same type as variable in memory */
00868 
00869   /* Apply scale_factor and add_offset to reduce variable size
00870      add_offset and scale_factor are always scalars so use var_scv_* functions
00871      var_scv_[sub,multiply] functions avoid cost of broadcasting attributes and doing element-by-element operations 
00872      Using var_scv_[sub,multiply] instead of ncap_var_scv_[sub,multiply] avoids cost of deep copies
00873      Moreover, this keeps variable structure from changing (because ncap_var_scv_* functions all do deep copies before operations) and thus complicating memory management */
00874   if(var->has_add_fst){ /* [flg] Valid add_offset attribute exists */
00875     bool has_mss_val_tmp; /* [flg] Temporary missing_value flag */
00876 
00877     /* Subtract add_offset from var */
00878     scv_sct add_fst_scv;
00879     add_fst_scv.type=NC_DOUBLE;
00880     add_fst_scv.val.d=add_fst_dbl;
00881     (void)nco_scv_cnf_typ(var->type,&add_fst_scv);
00882     /* Pass temporary missing_value flag to accomodate pure missing_value fields */
00883     has_mss_val_tmp=var->has_mss_val;
00884     /* Dupe var_scv_sub() into subtracting missing values when all values are missing */
00885     if(PURE_MSS_VAL_FLD){
00886       has_mss_val_tmp=False;
00887       (void)fprintf(stdout,"%s: INFO %s reports variable %s is completely missing_value = %g. Why do you store variables with no valid values?\n",prg_nm_get(),fnc_nm,var->nm,add_fst_dbl);
00888     } /* !PURE_MSS_VAL_FLD */
00889     (void)var_scv_sub(var->type,var->sz,has_mss_val_tmp,var->mss_val,var->val,&add_fst_scv);
00890   } /* endif */
00891 
00892   if(var->has_scl_fct){ /* [flg] Valid scale_factor attribute exists */
00893     /* Divide var by scale_factor */
00894     scv_sct scl_fct_scv;
00895     scl_fct_scv.type=NC_DOUBLE;
00896     scl_fct_scv.val.d=scl_fct_dbl;
00897     (void)nco_scv_cnf_typ(var->type,&scl_fct_scv);
00898     if(scl_fct_dbl != 0.0) (void)var_scv_dvd(var->type,var->sz,var->has_mss_val,var->mss_val,var->val,&scl_fct_scv);
00899   } /* endif */
00900 
00901   if(!var->has_scl_fct && !var->has_add_fst){
00902     (void)fprintf(stderr,"%s: ERROR Reached end of %s without packing variable\n",prg_nm_get(),fnc_nm);
00903     nco_exit(EXIT_FAILURE);
00904   }else{
00905     *PCK_VAR_WITH_NEW_PCK_ATT=True; /* O [flg] Routine generated new scale_factor/add_offset */
00906   } /* endif */
00907 
00908   /* Tell the world we packed the variable
00909      This is true if input variable satisfied nco_pck_plc_typ_get() criteria
00910      Variables that fail nco_pck_plc_typ_get() (e.g., type == NC_CHAR) are not packed 
00911      and should not have their packing attributes set */
00912   var->pck_ram=True; /* [flg] Variable is packed in memory */
00913   var->typ_pck=nc_typ_pck; /* [enm] Type of variable when packed (on disk). This should be same as typ_dsk except in cases where variable is packed in input file and unpacked in output file. */
00914   var->typ_upk=var->type; /* [enm] Type of variable when unpacked (expanded) (in memory) */
00915 
00916   /* Convert variable to user-specified packed type
00917      This is where var->type is changed from original to packed type */
00918   var=nco_var_cnf_typ(nc_typ_pck,var);
00919 
00920   if(dbg_lvl_get() >= 3) (void)fprintf(stdout,"%s: PACKING %s packed %s into %s\n",prg_nm_get(),fnc_nm,var->nm,nco_typ_sng(var->type));
00921 
00922   return var;
00923 } /* end nco_var_pck() */

var_sct* nco_var_upk var_sct *const   var  ) 
 

Definition at line 927 of file nco_pck.c.

References var_sct_tag::add_fst, dbg_lvl_get(), False, var_sct_tag::has_add_fst, var_sct_tag::has_mss_val, var_sct_tag::has_scl_fct, var_sct_tag::id, var_sct_tag::mss_val, var_sct_tag::nc_id, nco_cnv_mss_val_typ(), nco_free(), nco_get_att(), nco_malloc(), nco_typ_lng(), nco_typ_sng(), nco_var_cnf_typ(), var_sct_tag::nm, var_sct_tag::pck_ram, prg_nm_get(), ptr_unn_2_scv(), var_sct_tag::scl_fct, var_sct_tag::sz, var_sct_tag::typ_upk, var_sct_tag::type, scv_sct::type, var_sct_tag::val, var_scv_add(), var_scv_mlt(), and ptr_unn::vp.

Referenced by nco_var_get(), and nco_var_upk_swp().

00928 {
00929   /* Threads: Routine is thread-safe */
00930   /* Purpose: Unpack variable
00931      Routine is inverse of nco_var_pck(): nco_var_upk[nco_var_pck(var)]=var
00932      Routine handles missing_value's implicitly:
00933      nco_var_cnf_typ() automatically converts missing_value, if any, to unpacked type
00934      This may need to change when nco427 is addressed */
00935 
00936   const char fnc_nm[]="nco_var_upk()";
00937   const char scl_fct_sng[]="scale_factor"; /* [sng] Unidata standard string for scale factor */
00938   const char add_fst_sng[]="add_offset"; /* [sng] Unidata standard string for add offset */
00939 
00940   /* Return if variable in memory is not currently packed */
00941   if(!var->pck_ram) return var;
00942 
00943   /* Routine should be called with variable already in memory */
00944   if(var->val.vp == NULL) (void)fprintf(stdout,"%s: ERROR nco_var_upk() called with empty var->val.vp\n",prg_nm_get());
00945 
00946   /* Packed variables are not guaranteed to have both scale_factor and add_offset
00947      scale_factor is guaranteed to be of type NC_FLOAT or NC_DOUBLE and of size 1 (a scalar) */
00948 
00949   /* Create scalar value structures from values of scale_factor, add_offset */
00950   if(var->has_scl_fct){ /* [flg] Valid scale_factor attribute exists */
00951     scv_sct scl_fct_scv;
00952     var->scl_fct.vp=(void *)nco_malloc(nco_typ_lng(var->typ_upk));
00953     (void)nco_get_att(var->nc_id,var->id,scl_fct_sng,var->scl_fct.vp,var->typ_upk);
00954     scl_fct_scv=ptr_unn_2_scv(var->typ_upk,var->scl_fct);
00955     /* Convert var to type of scale_factor for expansion */
00956     var=nco_var_cnf_typ(scl_fct_scv.type,var);
00957     /* Multiply var by scale_factor */
00958     (void)var_scv_mlt(var->type,var->sz,var->has_mss_val,var->mss_val,var->val,&scl_fct_scv);
00959   } /* endif has_scl_fct */
00960 
00961   if(var->has_add_fst){ /* [flg] Valid add_offset attribute exists */
00962     scv_sct add_fst_scv;
00963     var->add_fst.vp=(void *)nco_malloc(nco_typ_lng(var->typ_upk));
00964     /* fxm TODO nco638 */
00965     (void)nco_get_att(var->nc_id,var->id,add_fst_sng,var->add_fst.vp,var->typ_upk);
00966     add_fst_scv=ptr_unn_2_scv(var->typ_upk,var->add_fst);
00967     /* Convert var to type of scale_factor for expansion */
00968     var=nco_var_cnf_typ(add_fst_scv.type,var);
00969     /* Add add_offset to var */
00970     (void)var_scv_add(var->type,var->sz,var->has_mss_val,var->mss_val,var->val,&add_fst_scv);
00971   } /* endif has_add_fst */
00972 
00973   if(var->has_mss_val) var=nco_cnv_mss_val_typ(var,var->type);
00974 
00975   /* Tell the world */  
00976   var->pck_ram=False;
00977 
00978   /* Clean up tell-tale signs that variable was ever packed */
00979   var->has_scl_fct=False; /* [flg] Valid scale_factor attribute exists */
00980   var->has_add_fst=False; /* [flg] Valid add_offset attribute exists */
00981   var->scl_fct.vp=nco_free(var->scl_fct.vp);
00982   var->add_fst.vp=nco_free(var->add_fst.vp);
00983 
00984   if(dbg_lvl_get() > 2) (void)fprintf(stdout,"%s: PACKING %s unpacked %s into %s\n",prg_nm_get(),fnc_nm,var->nm,nco_typ_sng(var->type));
00985 
00986   return var;
00987 } /* end nco_var_upk() */

void nco_var_upk_swp var_sct *const   var_in,
var_sct *const   var_out
 

Definition at line 991 of file nco_pck.c.

References dbg_lvl_get(), EXIT_FAILURE, var_sct_tag::has_add_fst, var_sct_tag::has_scl_fct, var_sct_tag::mss_val, nco_exit(), nco_free(), nco_typ_sng(), nco_var_dpl(), nco_var_free(), nco_var_upk(), var_sct_tag::nm, var_sct_tag::pck_ram, prg_nm_get(), var_sct_tag::type, var_sct_tag::val, and ptr_unn::vp.

Referenced by nco_pck_val().

00993 {
00994   /* Purpose: Unpack var_in into var_out
00995      Information flow in ncpdq prevents ncpdq from calling nco_var_upk()
00996      directly with either var_in or var_out.
00997      Need combination of var_in (for correct file and variable IDs) 
00998      and var_out (so unpacked variable ends up in correct place)
00999      Accomplish this by unpacking into temporary variable and copying 
01000      needed information from temporary (swap) variable to var_out.
01001      Routine hides gory details of swapped unpacking
01002      var_in is untouched except var_in->val buffer is free()'d
01003 
01004      nco_pck_val() uses this routine for two purposes:
01005      1. Unpack already packed variable prior to re-packing them 
01006      2. Unpack already packed variables permanently */
01007   const char fnc_nm[]="nco_var_upk_swp()";
01008   var_sct *var_tmp; /* [sct] Temporary variable to be unpacked */
01009   
01010   if(var_in->pck_ram){
01011     if(dbg_lvl_get() > 3) (void)fprintf(stdout,"%s: DEBUG %s unpacking variable %s values from %s to %s\n",prg_nm_get(),fnc_nm,var_in->nm,nco_typ_sng(var_out->typ_pck),nco_typ_sng(var_out->typ_upk));
01012   }else{
01013     (void)fprintf(stderr,"%s: ERROR %s variable %s is already unpacked\n",prg_nm_get(),fnc_nm,var_in->nm);
01014     nco_exit(EXIT_FAILURE);
01015   } /* endif not already packed */
01016 
01017   /* Output file does not contain packing attributes yet 
01018      Hence unpacking var_out directly is impossible 
01019      Instead, make var_tmp a copy of var_in and unpack var_tmp 
01020      Then copy needed elements of var_tmp to var_out 
01021      Then delete the rest of var_tmp 
01022      Fields modified in nco_var_upk() must be explicitly updated in var_out */
01023   var_tmp=nco_var_dpl(var_in);
01024   /* Free current input buffer */
01025   var_in->val.vp=nco_free(var_in->val.vp);
01026   /* Unpack temporary variable */
01027   var_tmp=nco_var_upk(var_tmp); 
01028   /* Save relevent parts of temporary variable into output variable */
01029   var_out->type=var_tmp->type;
01030   var_out->val=var_tmp->val;
01031   var_out->pck_ram=var_tmp->pck_ram;
01032   /* nco_var_cnf_typ() in nco_var_upk() automatically converts missing_value, if any, to unpacked type */
01033   if(var_out->has_mss_val){
01034     /* Free current missing value before obtaining new one */
01035     var_out->mss_val.vp=(void *)nco_free(var_out->mss_val.vp);
01036     var_out->mss_val=var_tmp->mss_val;
01037     /* var_out now owns mss_val, make sure nco_var_free(var_tmp) ignores it */
01038     var_tmp->mss_val.vp=NULL;
01039   } /* endif */
01040   var_out->has_scl_fct=var_tmp->has_scl_fct;
01041   var_out->has_add_fst=var_tmp->has_add_fst;
01042   var_out->scl_fct.vp=nco_free(var_out->scl_fct.vp);
01043   var_out->add_fst.vp=nco_free(var_out->add_fst.vp);
01044   /* var_tmp->val buffer now doubles as var_out->val buffer
01045      Prevent nco_var_free() from free()'ing var_tmp->val
01046      Setting var_tmp->val.vp=NULL accomplishes this
01047      Use var_out->val.vp to free() this buffer later with nco_var_free() */
01048   var_tmp->val.vp=NULL;
01049   if(var_tmp != NULL) var_tmp=nco_var_free(var_tmp);
01050 } /* end nco_var_upk_swp() */


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