NetCDF  4.9.3
nc4var.c
Go to the documentation of this file.
1 /* Copyright 2003-2018, University Corporation for Atmospheric
2  * Research. See COPYRIGHT file for copying and redistribution
3  * conditions.*/
13 #include "config.h"
14 #include "nc4internal.h"
15 #include "nc4dispatch.h"
16 #ifdef USE_HDF5
17 #include "hdf5internal.h"
18 #endif
19 #include <math.h>
20 
22 #define DEFAULT_1D_UNLIM_SIZE (4096)
23 
24 /* Define log_e for 10 and 2. Prefer constants defined in math.h,
25  * however, GCC environments can have hard time defining M_LN10/M_LN2
26  * despite finding math.h */
27 #ifndef M_LN10
28 # define M_LN10 2.30258509299404568402
29 #endif /* M_LN10 */
30 #ifndef M_LN2
31 # define M_LN2 0.69314718055994530942
32 #endif /* M_LN2 */
33 
38 #define BIT_XPL_NBR_SGN_FLT (23)
39 
44 #define BIT_XPL_NBR_SGN_DBL (52)
45 
47 typedef union { /* ptr_unn */
48  float *fp;
49  double *dp;
50  unsigned int *ui32p;
51  unsigned long long *ui64p;
52  void *vp;
53 } ptr_unn;
54 
71 int
72 NC4_get_var_chunk_cache(int ncid, int varid, size_t *sizep,
73  size_t *nelemsp, float *preemptionp)
74 {
75  NC *nc;
76  NC_GRP_INFO_T *grp;
77  NC_FILE_INFO_T *h5;
78  NC_VAR_INFO_T *var;
79  int retval;
80 
81  /* Find info for this file and group, and set pointer to each. */
82  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
83  return retval;
84  assert(nc && grp && h5);
85 
86  /* Find the var. */
87  var = (NC_VAR_INFO_T*)ncindexith(grp->vars,(size_t)varid);
88  if(!var)
89  return NC_ENOTVAR;
90  assert(var && var->hdr.id == varid);
91 
92  /* Give the user what they want. */
93  if (sizep)
94  *sizep = var->chunkcache.size;
95  if (nelemsp)
96  *nelemsp = var->chunkcache.nelems;
97  if (preemptionp)
98  *preemptionp = var->chunkcache.preemption;
99 
100  return NC_NOERR;
101 }
102 
119 int
120 nc_get_var_chunk_cache_ints(int ncid, int varid, int *sizep,
121  int *nelemsp, int *preemptionp)
122 {
123  size_t real_size, real_nelems;
124  float real_preemption;
125  int ret;
126 
127  if ((ret = NC4_get_var_chunk_cache(ncid, varid, &real_size,
128  &real_nelems, &real_preemption)))
129  return ret;
130 
131  if (sizep)
132  *sizep = (int)(real_size / MEGABYTE);
133  if (nelemsp)
134  *nelemsp = (int)real_nelems;
135  if(preemptionp)
136  *preemptionp = (int)(real_preemption * 100);
137 
138  return NC_NOERR;
139 }
140 
178 int
179 NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
180  int *ndimsp, int *dimidsp, int *nattsp,
181  int *shufflep, int *deflatep, int *deflate_levelp,
182  int *fletcher32p, int *storagep, size_t *chunksizesp,
183  int *no_fill, void *fill_valuep, int *endiannessp,
184  unsigned int *idp, size_t *nparamsp, unsigned int *params)
185 {
186  NC_GRP_INFO_T *grp;
187  NC_FILE_INFO_T *h5;
188  NC_VAR_INFO_T *var;
189  int d;
190  int retval;
191 
192  LOG((2, "%s: ncid 0x%x varid %d", __func__, ncid, varid));
193 
194  /* Find info for this file and group, and set pointer to each. */
195  if ((retval = nc4_find_nc_grp_h5(ncid, NULL, &grp, &h5)))
196  return retval;
197  assert(grp && h5);
198 
199  /* If the varid is -1, find the global atts and call it a day. */
200  if (varid == NC_GLOBAL && nattsp)
201  {
202  *nattsp = ncindexcount(grp->att);
203  return NC_NOERR;
204  }
205 
206  /* Find the var. */
207  if (!(var = (NC_VAR_INFO_T *)ncindexith(grp->vars, (size_t)varid)))
208  return NC_ENOTVAR;
209  assert(var && var->hdr.id == varid);
210 
211  /* Copy the data to the user's data buffers. */
212  if (name)
213  strcpy(name, var->hdr.name);
214  if (xtypep)
215  *xtypep = var->type_info->hdr.id;
216  if (ndimsp)
217  *ndimsp = (int)var->ndims;
218  if (dimidsp)
219  for (d = 0; d < var->ndims; d++)
220  dimidsp[d] = var->dimids[d];
221  if (nattsp)
222  *nattsp = ncindexcount(var->att);
223 
224  /* Did the user want the chunksizes? */
225  if (var->storage == NC_CHUNKED && chunksizesp)
226  {
227  for (d = 0; d < var->ndims; d++)
228  {
229  chunksizesp[d] = var->chunksizes[d];
230  LOG((4, "chunksizesp[%d]=%d", d, chunksizesp[d]));
231  }
232  }
233 
234  /* Did the user inquire about the storage? */
235  if (storagep)
236  *storagep = var->storage;
237 
238  /* Filter stuff. */
239  if (shufflep) {
240  retval = nc_inq_var_filter_info(ncid,varid,H5Z_FILTER_SHUFFLE,0,NULL);
241  if(retval && retval != NC_ENOFILTER) return retval;
242  *shufflep = (retval == NC_NOERR?1:0);
243  }
244  if (fletcher32p) {
245  retval = nc_inq_var_filter_info(ncid,varid,H5Z_FILTER_FLETCHER32,0,NULL);
246  if(retval && retval != NC_ENOFILTER) return retval;
247  *fletcher32p = (retval == NC_NOERR?1:0);
248  }
249  if (deflatep)
250  return NC_EFILTER;
251 
252  if (idp) {
253  return NC_EFILTER;
254  }
255 
256  /* Fill value stuff. */
257  if (no_fill)
258  *no_fill = (int)var->no_fill;
259 
260  /* Don't do a thing with fill_valuep if no_fill mode is set for
261  * this var, or if fill_valuep is NULL. */
262  if (!var->no_fill && fill_valuep)
263  {
264  /* Do we have a fill value for this var? */
265  if (var->fill_value)
266  {
267  int xtype = var->type_info->hdr.id;
268  if((retval = NC_copy_data(h5->controller,xtype,var->fill_value,1,fill_valuep))) return retval;
269  }
270  else
271  {
272  if ((retval = nc4_get_default_fill_value(var->type_info, fill_valuep)))
273  return retval;
274  }
275  }
276 
277  /* Does the user want the endianness of this variable? */
278  if (endiannessp)
279  *endiannessp = var->endianness;
280 
281  return NC_NOERR;
282 }
283 
300 int
301 nc_inq_var_chunking_ints(int ncid, int varid, int *storagep, int *chunksizesp)
302 {
303  NC_VAR_INFO_T *var;
304  size_t *cs = NULL;
305  int i, retval;
306 
307  /* Get pointer to the var. */
308  if ((retval = nc4_find_grp_h5_var(ncid, varid, NULL, NULL, &var)))
309  return retval;
310  assert(var);
311 
312  /* Allocate space for the size_t copy of the chunksizes array. */
313  if (var->ndims)
314  if (!(cs = malloc(var->ndims * sizeof(size_t))))
315  return NC_ENOMEM;
316 
317  /* Call the netcdf-4 version directly. */
318  retval = NC4_inq_var_all(ncid, varid, NULL, NULL, NULL, NULL, NULL,
319  NULL, NULL, NULL, NULL, storagep, cs, NULL,
320  NULL, NULL, NULL, NULL, NULL);
321 
322  /* Copy from size_t array. */
323  if (!retval && chunksizesp && var->storage == NC_CHUNKED)
324  {
325  for (i = 0; i < var->ndims; i++)
326  {
327  chunksizesp[i] = (int)cs[i];
328  if (cs[i] > NC_MAX_INT)
329  retval = NC_ERANGE;
330  }
331  }
332 
333  if (var->ndims)
334  free(cs);
335  return retval;
336 }
337 
350 int
351 NC4_inq_varid(int ncid, const char *name, int *varidp)
352 {
353  NC *nc;
354  NC_GRP_INFO_T *grp;
355  NC_VAR_INFO_T *var;
356  char norm_name[NC_MAX_NAME + 1];
357  int retval;
358 
359  if (!name)
360  return NC_EINVAL;
361  if (!varidp)
362  return NC_NOERR;
363 
364  LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name));
365 
366  /* Find info for this file and group, and set pointer to each. */
367  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, NULL)))
368  return retval;
369 
370  /* Normalize name. */
371  if ((retval = nc4_normalize_name(name, norm_name)))
372  return retval;
373 
374  /* Find var of this name. */
375  var = (NC_VAR_INFO_T*)ncindexlookup(grp->vars,norm_name);
376  if(var)
377  {
378  *varidp = var->hdr.id;
379  return NC_NOERR;
380  }
381  return NC_ENOTVAR;
382 }
383 
402 int
403 NC4_var_par_access(int ncid, int varid, int par_access)
404 {
405 #ifndef USE_PARALLEL4
406  NC_UNUSED(ncid);
407  NC_UNUSED(varid);
408  NC_UNUSED(par_access);
409  return NC_ENOPAR;
410 #else
411  NC *nc;
412  NC_GRP_INFO_T *grp;
413  NC_FILE_INFO_T *h5;
414  NC_VAR_INFO_T *var;
415  int retval;
416 
417  LOG((1, "%s: ncid 0x%x varid %d par_access %d", __func__, ncid,
418  varid, par_access));
419 
420  if (par_access != NC_INDEPENDENT && par_access != NC_COLLECTIVE)
421  return NC_EINVAL;
422 
423  /* Find info for this file and group, and set pointer to each. */
424  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
425  return retval;
426 
427  /* This function only for files opened with nc_open_par or nc_create_par. */
428  if (!h5->parallel)
429  return NC_ENOPAR;
430 
431  /* Find the var, and set its preference. */
432  var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
433  if (!var) return NC_ENOTVAR;
434  assert(var->hdr.id == varid);
435 
436  /* If zlib, shuffle, or fletcher32 filters are in use, then access
437  * must be collective. Fail an attempt to set such a variable to
438  * independent access. */
439  if (nclistlength((NClist*)var->filters) > 0 &&
440  par_access == NC_INDEPENDENT)
441  return NC_EINVAL;
442 
443  if (par_access)
444  var->parallel_access = NC_COLLECTIVE;
445  else
446  var->parallel_access = NC_INDEPENDENT;
447  return NC_NOERR;
448 #endif /* USE_PARALLEL4 */
449 }
450 
483 int
484 nc4_convert_type(const void *src, void *dest, const nc_type src_type,
485  const nc_type dest_type, const size_t len, int *range_error,
486  const void *fill_value, int strict_nc3, int quantize_mode,
487  int nsd)
488 {
489  /* These vars are used with quantize feature. */
490  const double bit_per_dgt = M_LN10 / M_LN2; /* 3.32 [frc] Bits per decimal digit of precision = log2(10) */
491  const double dgt_per_bit= M_LN2 / M_LN10; /* 0.301 [frc] Decimal digits per bit of precision = log10(2) */
492  double mnt; /* [frc] Mantissa, 0.5 <= mnt < 1.0 */
493  double mnt_fabs; /* [frc] fabs(mantissa) */
494  double mnt_log10_fabs; /* [frc] log10(fabs(mantissa))) */
495  double val; /* [frc] Copy of input value to avoid indirection */
496  double mss_val_cmp_dbl; /* Missing value for comparison to double precision values */
497  float mss_val_cmp_flt; /* Missing value for comparison to single precision values */
498  int bit_xpl_nbr_zro; /* [nbr] Number of explicit bits to zero */
499  int dgt_nbr; /* [nbr] Number of digits before decimal point */
500  int qnt_pwr; /* [nbr] Power of two in quantization mask: qnt_msk = 2^qnt_pwr */
501  int xpn_bs2; /* [nbr] Binary exponent xpn_bs2 in val = sign(val) * 2^xpn_bs2 * mnt, 0.5 < mnt <= 1.0 */
502  size_t idx;
503  unsigned int *u32_ptr;
504  unsigned int msk_f32_u32_zro;
505  unsigned int msk_f32_u32_one;
506  unsigned int msk_f32_u32_hshv;
507  unsigned long long int *u64_ptr;
508  unsigned long long int msk_f64_u64_zro;
509  unsigned long long int msk_f64_u64_one;
510  unsigned long long int msk_f64_u64_hshv;
511  unsigned short prc_bnr_xpl_rqr; /* [nbr] Explicitly represented binary digits required to retain */
512  ptr_unn op1; /* I/O [frc] Values to quantize */
513 
514  char *cp, *cp1;
515  float *fp, *fp1;
516  double *dp, *dp1;
517  int *ip, *ip1;
518  short *sp, *sp1;
519  signed char *bp, *bp1;
520  unsigned char *ubp, *ubp1;
521  unsigned short *usp, *usp1;
522  unsigned int *uip, *uip1;
523  long long *lip, *lip1;
524  unsigned long long *ulip, *ulip1;
525  size_t count = 0;
526 
527  *range_error = 0;
528  LOG((3, "%s: len %d src_type %d dest_type %d", __func__, len, src_type,
529  dest_type));
530 
531  /* If quantize is in use, set up some values. Quantize can only be
532  * used when the destination type is NC_FLOAT or NC_DOUBLE. */
533  if (quantize_mode != NC_NOQUANTIZE)
534  {
535  assert(dest_type == NC_FLOAT || dest_type == NC_DOUBLE);
536 
537  /* Parameters shared by all quantization codecs */
538  if (dest_type == NC_FLOAT)
539  {
540  /* Determine the fill value. */
541  if (fill_value)
542  mss_val_cmp_flt = *(float *)fill_value;
543  else
544  mss_val_cmp_flt = NC_FILL_FLOAT;
545 
546  }
547  else
548  {
549 
550  /* Determine the fill value. */
551  if (fill_value)
552  mss_val_cmp_dbl = *(double *)fill_value;
553  else
554  mss_val_cmp_dbl = NC_FILL_DOUBLE;
555 
556  }
557 
558  /* Set parameters used by BitGroom and BitRound here, outside value loop.
559  Equivalent parameters used by GranularBR are set inside value loop,
560  since keep bits and thus masks can change for every value. */
561  if (quantize_mode == NC_QUANTIZE_BITGROOM ||
562  quantize_mode == NC_QUANTIZE_BITROUND )
563  {
564 
565  if (quantize_mode == NC_QUANTIZE_BITGROOM){
566 
567  /* BitGroom interprets nsd as number of significant decimal digits
568  * Must convert that to number of significant bits to preserve
569  * How many bits to preserve? Being conservative, we round up the
570  * exact binary digits of precision. Add one because the first bit
571  * is implicit not explicit but corner cases prevent our taking
572  * advantage of this. */
573  prc_bnr_xpl_rqr = (unsigned short)ceil(nsd * bit_per_dgt) + 1;
574 
575  }else if (quantize_mode == NC_QUANTIZE_BITROUND){
576 
577  /* BitRound interprets nsd as number of significant binary digits (bits) */
578  prc_bnr_xpl_rqr = (unsigned short)nsd;
579 
580  }
581 
582  if (dest_type == NC_FLOAT)
583  {
584 
585  bit_xpl_nbr_zro = BIT_XPL_NBR_SGN_FLT - prc_bnr_xpl_rqr;
586 
587  /* Create mask */
588  msk_f32_u32_zro = 0U; /* Zero all bits */
589  msk_f32_u32_zro = ~msk_f32_u32_zro; /* Turn all bits to ones */
590 
591  /* BitShave mask for AND: Left shift zeros into bits to be
592  * rounded, leave ones in untouched bits. */
593  msk_f32_u32_zro <<= bit_xpl_nbr_zro;
594 
595  /* BitSet mask for OR: Put ones into bits to be set, zeros in
596  * untouched bits. */
597  msk_f32_u32_one = ~msk_f32_u32_zro;
598 
599  /* BitRound mask for ADD: Set one bit: the MSB of LSBs */
600  msk_f32_u32_hshv=msk_f32_u32_one & (msk_f32_u32_zro >> 1);
601 
602  }
603  else
604  {
605 
606  bit_xpl_nbr_zro = BIT_XPL_NBR_SGN_DBL - prc_bnr_xpl_rqr;
607  /* Create mask. */
608  msk_f64_u64_zro = 0UL; /* Zero all bits. */
609  msk_f64_u64_zro = ~msk_f64_u64_zro; /* Turn all bits to ones. */
610 
611  /* BitShave mask for AND: Left shift zeros into bits to be
612  * rounded, leave ones in untouched bits. */
613  msk_f64_u64_zro <<= bit_xpl_nbr_zro;
614 
615  /* BitSet mask for OR: Put ones into bits to be set, zeros in
616  * untouched bits. */
617  msk_f64_u64_one =~ msk_f64_u64_zro;
618 
619  /* BitRound mask for ADD: Set one bit: the MSB of LSBs */
620  msk_f64_u64_hshv = msk_f64_u64_one & (msk_f64_u64_zro >> 1);
621 
622  }
623 
624  }
625 
626  } /* endif quantize */
627 
628  /* OK, this is ugly. If you can think of anything better, I'm open
629  to suggestions!
630 
631  Note that we don't use a default fill value for type
632  NC_BYTE. This is because Lord Voldemort cast a nofilleramous spell
633  at Harry Potter, but it bounced off his scar and hit the netcdf-4
634  code.
635  */
636  switch (src_type)
637  {
638  case NC_CHAR:
639  switch (dest_type)
640  {
641  case NC_CHAR:
642  for (cp = (char *)src, cp1 = dest; count < len; count++)
643  *cp1++ = *cp++;
644  break;
645  default:
646  LOG((0, "%s: Unknown destination type.", __func__));
647  }
648  break;
649 
650  case NC_BYTE:
651  switch (dest_type)
652  {
653  case NC_BYTE:
654  for (bp = (signed char *)src, bp1 = dest; count < len; count++)
655  *bp1++ = *bp++;
656  break;
657  case NC_UBYTE:
658  for (bp = (signed char *)src, ubp = dest; count < len; count++)
659  {
660  if (*bp < 0)
661  (*range_error)++;
662  *ubp++ = (unsigned char)*bp++;
663  }
664  break;
665  case NC_SHORT:
666  for (bp = (signed char *)src, sp = dest; count < len; count++)
667  *sp++ = *bp++;
668  break;
669  case NC_USHORT:
670  for (bp = (signed char *)src, usp = dest; count < len; count++)
671  {
672  if (*bp < 0)
673  (*range_error)++;
674  *usp++ = (unsigned short)*bp++;
675  }
676  break;
677  case NC_INT:
678  for (bp = (signed char *)src, ip = dest; count < len; count++)
679  *ip++ = *bp++;
680  break;
681  case NC_UINT:
682  for (bp = (signed char *)src, uip = dest; count < len; count++)
683  {
684  if (*bp < 0)
685  (*range_error)++;
686  *uip++ = (unsigned int)*bp++;
687  }
688  break;
689  case NC_INT64:
690  for (bp = (signed char *)src, lip = dest; count < len; count++)
691  *lip++ = *bp++;
692  break;
693  case NC_UINT64:
694  for (bp = (signed char *)src, ulip = dest; count < len; count++)
695  {
696  if (*bp < 0)
697  (*range_error)++;
698  *ulip++ = (unsigned long long)*bp++;
699  }
700  break;
701  case NC_FLOAT:
702  for (bp = (signed char *)src, fp = dest; count < len; count++)
703  *fp++ = *bp++;
704  break;
705  case NC_DOUBLE:
706  for (bp = (signed char *)src, dp = dest; count < len; count++)
707  *dp++ = *bp++;
708  break;
709  default:
710  LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d",
711  __func__, src_type, dest_type));
712  return NC_EBADTYPE;
713  }
714  break;
715 
716  case NC_UBYTE:
717  switch (dest_type)
718  {
719  case NC_BYTE:
720  for (ubp = (unsigned char *)src, bp = dest; count < len; count++)
721  {
722  if (!strict_nc3 && *ubp > X_SCHAR_MAX)
723  (*range_error)++;
724  *bp++ = (signed char)*ubp++;
725  }
726  break;
727  case NC_SHORT:
728  for (ubp = (unsigned char *)src, sp = dest; count < len; count++)
729  *sp++ = *ubp++;
730  break;
731  case NC_UBYTE:
732  for (ubp = (unsigned char *)src, ubp1 = dest; count < len; count++)
733  *ubp1++ = *ubp++;
734  break;
735  case NC_USHORT:
736  for (ubp = (unsigned char *)src, usp = dest; count < len; count++)
737  *usp++ = *ubp++;
738  break;
739  case NC_INT:
740  for (ubp = (unsigned char *)src, ip = dest; count < len; count++)
741  *ip++ = *ubp++;
742  break;
743  case NC_UINT:
744  for (ubp = (unsigned char *)src, uip = dest; count < len; count++)
745  *uip++ = *ubp++;
746  break;
747  case NC_INT64:
748  for (ubp = (unsigned char *)src, lip = dest; count < len; count++)
749  *lip++ = *ubp++;
750  break;
751  case NC_UINT64:
752  for (ubp = (unsigned char *)src, ulip = dest; count < len; count++)
753  *ulip++ = *ubp++;
754  break;
755  case NC_FLOAT:
756  for (ubp = (unsigned char *)src, fp = dest; count < len; count++)
757  *fp++ = *ubp++;
758  break;
759  case NC_DOUBLE:
760  for (ubp = (unsigned char *)src, dp = dest; count < len; count++)
761  *dp++ = *ubp++;
762  break;
763  default:
764  LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d",
765  __func__, src_type, dest_type));
766  return NC_EBADTYPE;
767  }
768  break;
769 
770  case NC_SHORT:
771  switch (dest_type)
772  {
773  case NC_UBYTE:
774  for (sp = (short *)src, ubp = dest; count < len; count++)
775  {
776  if (*sp > X_UCHAR_MAX || *sp < 0)
777  (*range_error)++;
778  *ubp++ = (unsigned char)*sp++;
779  }
780  break;
781  case NC_BYTE:
782  for (sp = (short *)src, bp = dest; count < len; count++)
783  {
784  if (*sp > X_SCHAR_MAX || *sp < X_SCHAR_MIN)
785  (*range_error)++;
786  *bp++ = (signed char)*sp++;
787  }
788  break;
789  case NC_SHORT:
790  for (sp = (short *)src, sp1 = dest; count < len; count++)
791  *sp1++ = *sp++;
792  break;
793  case NC_USHORT:
794  for (sp = (short *)src, usp = dest; count < len; count++)
795  {
796  if (*sp < 0)
797  (*range_error)++;
798  *usp++ = (unsigned short)*sp++;
799  }
800  break;
801  case NC_INT:
802  for (sp = (short *)src, ip = dest; count < len; count++)
803  *ip++ = *sp++;
804  break;
805  case NC_UINT:
806  for (sp = (short *)src, uip = dest; count < len; count++)
807  {
808  if (*sp < 0)
809  (*range_error)++;
810  *uip++ = (unsigned int)*sp++;
811  }
812  break;
813  case NC_INT64:
814  for (sp = (short *)src, lip = dest; count < len; count++)
815  *lip++ = *sp++;
816  break;
817  case NC_UINT64:
818  for (sp = (short *)src, ulip = dest; count < len; count++)
819  {
820  if (*sp < 0)
821  (*range_error)++;
822  *ulip++ = (unsigned long long)*sp++;
823  }
824  break;
825  case NC_FLOAT:
826  for (sp = (short *)src, fp = dest; count < len; count++)
827  *fp++ = *sp++;
828  break;
829  case NC_DOUBLE:
830  for (sp = (short *)src, dp = dest; count < len; count++)
831  *dp++ = *sp++;
832  break;
833  default:
834  LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d",
835  __func__, src_type, dest_type));
836  return NC_EBADTYPE;
837  }
838  break;
839 
840  case NC_USHORT:
841  switch (dest_type)
842  {
843  case NC_UBYTE:
844  for (usp = (unsigned short *)src, ubp = dest; count < len; count++)
845  {
846  if (*usp > X_UCHAR_MAX)
847  (*range_error)++;
848  *ubp++ = (unsigned char)*usp++;
849  }
850  break;
851  case NC_BYTE:
852  for (usp = (unsigned short *)src, bp = dest; count < len; count++)
853  {
854  if (*usp > X_SCHAR_MAX)
855  (*range_error)++;
856  *bp++ = (signed char)*usp++;
857  }
858  break;
859  case NC_SHORT:
860  for (usp = (unsigned short *)src, sp = dest; count < len; count++)
861  {
862  if (*usp > X_SHORT_MAX)
863  (*range_error)++;
864  *sp++ = (signed short)*usp++;
865  }
866  break;
867  case NC_USHORT:
868  for (usp = (unsigned short *)src, usp1 = dest; count < len; count++)
869  *usp1++ = *usp++;
870  break;
871  case NC_INT:
872  for (usp = (unsigned short *)src, ip = dest; count < len; count++)
873  *ip++ = *usp++;
874  break;
875  case NC_UINT:
876  for (usp = (unsigned short *)src, uip = dest; count < len; count++)
877  *uip++ = *usp++;
878  break;
879  case NC_INT64:
880  for (usp = (unsigned short *)src, lip = dest; count < len; count++)
881  *lip++ = *usp++;
882  break;
883  case NC_UINT64:
884  for (usp = (unsigned short *)src, ulip = dest; count < len; count++)
885  *ulip++ = *usp++;
886  break;
887  case NC_FLOAT:
888  for (usp = (unsigned short *)src, fp = dest; count < len; count++)
889  *fp++ = *usp++;
890  break;
891  case NC_DOUBLE:
892  for (usp = (unsigned short *)src, dp = dest; count < len; count++)
893  *dp++ = *usp++;
894  break;
895  default:
896  LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d",
897  __func__, src_type, dest_type));
898  return NC_EBADTYPE;
899  }
900  break;
901 
902  case NC_INT:
903  switch (dest_type)
904  {
905  case NC_UBYTE:
906  for (ip = (int *)src, ubp = dest; count < len; count++)
907  {
908  if (*ip > X_UCHAR_MAX || *ip < 0)
909  (*range_error)++;
910  *ubp++ = (unsigned char)*ip++;
911  }
912  break;
913  case NC_BYTE:
914  for (ip = (int *)src, bp = dest; count < len; count++)
915  {
916  if (*ip > X_SCHAR_MAX || *ip < X_SCHAR_MIN)
917  (*range_error)++;
918  *bp++ = (signed char)*ip++;
919  }
920  break;
921  case NC_SHORT:
922  for (ip = (int *)src, sp = dest; count < len; count++)
923  {
924  if (*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
925  (*range_error)++;
926  *sp++ = (short)*ip++;
927  }
928  break;
929  case NC_USHORT:
930  for (ip = (int *)src, usp = dest; count < len; count++)
931  {
932  if (*ip > X_USHORT_MAX || *ip < 0)
933  (*range_error)++;
934  *usp++ = (unsigned short)*ip++;
935  }
936  break;
937  case NC_INT: /* src is int */
938  for (ip = (int *)src, ip1 = dest; count < len; count++)
939  {
940  if (*ip > X_INT_MAX || *ip < X_INT_MIN)
941  (*range_error)++;
942  *ip1++ = *ip++;
943  }
944  break;
945  case NC_UINT:
946  for (ip = (int *)src, uip = dest; count < len; count++)
947  {
948  if (*ip > X_UINT_MAX || *ip < 0)
949  (*range_error)++;
950  *uip++ = (unsigned int)*ip++;
951  }
952  break;
953  case NC_INT64:
954  for (ip = (int *)src, lip = dest; count < len; count++)
955  *lip++ = *ip++;
956  break;
957  case NC_UINT64:
958  for (ip = (int *)src, ulip = dest; count < len; count++)
959  {
960  if (*ip < 0)
961  (*range_error)++;
962  *ulip++ = (unsigned long long)*ip++;
963  }
964  break;
965  case NC_FLOAT:
966  for (ip = (int *)src, fp = dest; count < len; count++)
967  *fp++ = (float)*ip++;
968  break;
969  case NC_DOUBLE:
970  for (ip = (int *)src, dp = dest; count < len; count++)
971  *dp++ = (double)*ip++;
972  break;
973  default:
974  LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d",
975  __func__, src_type, dest_type));
976  return NC_EBADTYPE;
977  }
978  break;
979 
980  case NC_UINT:
981  switch (dest_type)
982  {
983  case NC_UBYTE:
984  for (uip = (unsigned int *)src, ubp = dest; count < len; count++)
985  {
986  if (*uip > X_UCHAR_MAX)
987  (*range_error)++;
988  *ubp++ = (unsigned char)*uip++;
989  }
990  break;
991  case NC_BYTE:
992  for (uip = (unsigned int *)src, bp = dest; count < len; count++)
993  {
994  if (*uip > X_SCHAR_MAX)
995  (*range_error)++;
996  *bp++ = (signed char)*uip++;
997  }
998  break;
999  case NC_SHORT:
1000  for (uip = (unsigned int *)src, sp = dest; count < len; count++)
1001  {
1002  if (*uip > X_SHORT_MAX)
1003  (*range_error)++;
1004  *sp++ = (signed short)*uip++;
1005  }
1006  break;
1007  case NC_USHORT:
1008  for (uip = (unsigned int *)src, usp = dest; count < len; count++)
1009  {
1010  if (*uip > X_USHORT_MAX)
1011  (*range_error)++;
1012  *usp++ = (unsigned short)*uip++;
1013  }
1014  break;
1015  case NC_INT:
1016  for (uip = (unsigned int *)src, ip = dest; count < len; count++)
1017  {
1018  if (*uip > X_INT_MAX)
1019  (*range_error)++;
1020  *ip++ = (int)*uip++;
1021  }
1022  break;
1023  case NC_UINT:
1024  for (uip = (unsigned int *)src, uip1 = dest; count < len; count++)
1025  {
1026  if (*uip > X_UINT_MAX)
1027  (*range_error)++;
1028  *uip1++ = *uip++;
1029  }
1030  break;
1031  case NC_INT64:
1032  for (uip = (unsigned int *)src, lip = dest; count < len; count++)
1033  *lip++ = *uip++;
1034  break;
1035  case NC_UINT64:
1036  for (uip = (unsigned int *)src, ulip = dest; count < len; count++)
1037  *ulip++ = *uip++;
1038  break;
1039  case NC_FLOAT:
1040  for (uip = (unsigned int *)src, fp = dest; count < len; count++)
1041  *fp++ = (float)*uip++;
1042  break;
1043  case NC_DOUBLE:
1044  for (uip = (unsigned int *)src, dp = dest; count < len; count++)
1045  *dp++ = *uip++;
1046  break;
1047  default:
1048  LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d",
1049  __func__, src_type, dest_type));
1050  return NC_EBADTYPE;
1051  }
1052  break;
1053 
1054  case NC_INT64:
1055  switch (dest_type)
1056  {
1057  case NC_UBYTE:
1058  for (lip = (long long *)src, ubp = dest; count < len; count++)
1059  {
1060  if (*lip > X_UCHAR_MAX || *lip < 0)
1061  (*range_error)++;
1062  *ubp++ = (unsigned char)*lip++;
1063  }
1064  break;
1065  case NC_BYTE:
1066  for (lip = (long long *)src, bp = dest; count < len; count++)
1067  {
1068  if (*lip > X_SCHAR_MAX || *lip < X_SCHAR_MIN)
1069  (*range_error)++;
1070  *bp++ = (signed char)*lip++;
1071  }
1072  break;
1073  case NC_SHORT:
1074  for (lip = (long long *)src, sp = dest; count < len; count++)
1075  {
1076  if (*lip > X_SHORT_MAX || *lip < X_SHORT_MIN)
1077  (*range_error)++;
1078  *sp++ = (short)*lip++;
1079  }
1080  break;
1081  case NC_USHORT:
1082  for (lip = (long long *)src, usp = dest; count < len; count++)
1083  {
1084  if (*lip > X_USHORT_MAX || *lip < 0)
1085  (*range_error)++;
1086  *usp++ = (unsigned short)*lip++;
1087  }
1088  break;
1089  case NC_UINT:
1090  for (lip = (long long *)src, uip = dest; count < len; count++)
1091  {
1092  if (*lip > X_UINT_MAX || *lip < 0)
1093  (*range_error)++;
1094  *uip++ = (unsigned int)*lip++;
1095  }
1096  break;
1097  case NC_INT:
1098  for (lip = (long long *)src, ip = dest; count < len; count++)
1099  {
1100  if (*lip > X_INT_MAX || *lip < X_INT_MIN)
1101  (*range_error)++;
1102  *ip++ = (int)*lip++;
1103  }
1104  break;
1105  case NC_INT64:
1106  for (lip = (long long *)src, lip1 = dest; count < len; count++)
1107  *lip1++ = *lip++;
1108  break;
1109  case NC_UINT64:
1110  for (lip = (long long *)src, ulip = dest; count < len; count++)
1111  {
1112  if (*lip < 0)
1113  (*range_error)++;
1114  *ulip++ = (unsigned long long)*lip++;
1115  }
1116  break;
1117  case NC_FLOAT:
1118  for (lip = (long long *)src, fp = dest; count < len; count++)
1119  *fp++ = (float)*lip++;
1120  break;
1121  case NC_DOUBLE:
1122  for (lip = (long long *)src, dp = dest; count < len; count++)
1123  *dp++ = (double)*lip++;
1124  break;
1125  default:
1126  LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d",
1127  __func__, src_type, dest_type));
1128  return NC_EBADTYPE;
1129  }
1130  break;
1131 
1132  case NC_UINT64:
1133  switch (dest_type)
1134  {
1135  case NC_UBYTE:
1136  for (ulip = (unsigned long long *)src, ubp = dest; count < len; count++)
1137  {
1138  if (*ulip > X_UCHAR_MAX)
1139  (*range_error)++;
1140  *ubp++ = (unsigned char)*ulip++;
1141  }
1142  break;
1143  case NC_BYTE:
1144  for (ulip = (unsigned long long *)src, bp = dest; count < len; count++)
1145  {
1146  if (*ulip > X_SCHAR_MAX)
1147  (*range_error)++;
1148  *bp++ = (signed char)*ulip++;
1149  }
1150  break;
1151  case NC_SHORT:
1152  for (ulip = (unsigned long long *)src, sp = dest; count < len; count++)
1153  {
1154  if (*ulip > X_SHORT_MAX)
1155  (*range_error)++;
1156  *sp++ = (short)*ulip++;
1157  }
1158  break;
1159  case NC_USHORT:
1160  for (ulip = (unsigned long long *)src, usp = dest; count < len; count++)
1161  {
1162  if (*ulip > X_USHORT_MAX)
1163  (*range_error)++;
1164  *usp++ = (unsigned short)*ulip++;
1165  }
1166  break;
1167  case NC_UINT:
1168  for (ulip = (unsigned long long *)src, uip = dest; count < len; count++)
1169  {
1170  if (*ulip > X_UINT_MAX)
1171  (*range_error)++;
1172  *uip++ = (unsigned int)*ulip++;
1173  }
1174  break;
1175  case NC_INT:
1176  for (ulip = (unsigned long long *)src, ip = dest; count < len; count++)
1177  {
1178  if (*ulip > X_INT_MAX)
1179  (*range_error)++;
1180  *ip++ = (int)*ulip++;
1181  }
1182  break;
1183  case NC_INT64:
1184  for (ulip = (unsigned long long *)src, lip = dest; count < len; count++)
1185  {
1186  if (*ulip > X_INT64_MAX)
1187  (*range_error)++;
1188  *lip++ = (long long)*ulip++;
1189  }
1190  break;
1191  case NC_UINT64:
1192  for (ulip = (unsigned long long *)src, ulip1 = dest; count < len; count++)
1193  *ulip1++ = *ulip++;
1194  break;
1195  case NC_FLOAT:
1196  for (ulip = (unsigned long long *)src, fp = dest; count < len; count++)
1197  *fp++ = (float)*ulip++;
1198  break;
1199  case NC_DOUBLE:
1200  for (ulip = (unsigned long long *)src, dp = dest; count < len; count++)
1201  *dp++ = (double)*ulip++;
1202  break;
1203  default:
1204  LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d",
1205  __func__, src_type, dest_type));
1206  return NC_EBADTYPE;
1207  }
1208  break;
1209 
1210  case NC_FLOAT:
1211  switch (dest_type)
1212  {
1213  case NC_UBYTE:
1214  for (fp = (float *)src, ubp = dest; count < len; count++)
1215  {
1216  if (*fp > X_UCHAR_MAX || *fp < 0)
1217  (*range_error)++;
1218  *ubp++ = (unsigned char)*fp++;
1219  }
1220  break;
1221  case NC_BYTE:
1222  for (fp = (float *)src, bp = dest; count < len; count++)
1223  {
1224  if (*fp > (double)X_SCHAR_MAX || *fp < (double)X_SCHAR_MIN)
1225  (*range_error)++;
1226  *bp++ = (signed char)*fp++;
1227  }
1228  break;
1229  case NC_SHORT:
1230  for (fp = (float *)src, sp = dest; count < len; count++)
1231  {
1232  if (*fp > (double)X_SHORT_MAX || *fp < (double)X_SHORT_MIN)
1233  (*range_error)++;
1234  *sp++ = (short)*fp++;
1235  }
1236  break;
1237  case NC_USHORT:
1238  for (fp = (float *)src, usp = dest; count < len; count++)
1239  {
1240  if (*fp > X_USHORT_MAX || *fp < 0)
1241  (*range_error)++;
1242  *usp++ = (unsigned short)*fp++;
1243  }
1244  break;
1245  case NC_UINT:
1246  for (fp = (float *)src, uip = dest; count < len; count++)
1247  {
1248  if (*fp > (float)X_UINT_MAX || *fp < 0)
1249  (*range_error)++;
1250  *uip++ = (unsigned int)*fp++;
1251  }
1252  break;
1253  case NC_INT:
1254  for (fp = (float *)src, ip = dest; count < len; count++)
1255  {
1256  if (*fp > (double)X_INT_MAX || *fp < (double)X_INT_MIN)
1257  (*range_error)++;
1258  *ip++ = (int)*fp++;
1259  }
1260  break;
1261  case NC_INT64:
1262  for (fp = (float *)src, lip = dest; count < len; count++)
1263  {
1264  if (*fp > (float)X_INT64_MAX || *fp <X_INT64_MIN)
1265  (*range_error)++;
1266  *lip++ = (long long)*fp++;
1267  }
1268  break;
1269  case NC_UINT64:
1270  for (fp = (float *)src, ulip = dest; count < len; count++)
1271  {
1272  if (*fp > (float)X_UINT64_MAX || *fp < 0)
1273  (*range_error)++;
1274  *ulip++ = (unsigned long long)*fp++;
1275  }
1276  break;
1277  case NC_FLOAT:
1278  for (fp = (float *)src, fp1 = dest; count < len; count++)
1279  *fp1++ = *fp++;
1280  break;
1281  case NC_DOUBLE:
1282  for (fp = (float *)src, dp = dest; count < len; count++)
1283  *dp++ = *fp++;
1284  break;
1285  default:
1286  LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d",
1287  __func__, src_type, dest_type));
1288  return NC_EBADTYPE;
1289  }
1290  break;
1291 
1292  case NC_DOUBLE:
1293  switch (dest_type)
1294  {
1295  case NC_UBYTE:
1296  for (dp = (double *)src, ubp = dest; count < len; count++)
1297  {
1298  if (*dp > X_UCHAR_MAX || *dp < 0)
1299  (*range_error)++;
1300  *ubp++ = (unsigned char)*dp++;
1301  }
1302  break;
1303  case NC_BYTE:
1304  for (dp = (double *)src, bp = dest; count < len; count++)
1305  {
1306  if (*dp > X_SCHAR_MAX || *dp < X_SCHAR_MIN)
1307  (*range_error)++;
1308  *bp++ = (signed char)*dp++;
1309  }
1310  break;
1311  case NC_SHORT:
1312  for (dp = (double *)src, sp = dest; count < len; count++)
1313  {
1314  if (*dp > X_SHORT_MAX || *dp < X_SHORT_MIN)
1315  (*range_error)++;
1316  *sp++ = (short)*dp++;
1317  }
1318  break;
1319  case NC_USHORT:
1320  for (dp = (double *)src, usp = dest; count < len; count++)
1321  {
1322  if (*dp > X_USHORT_MAX || *dp < 0)
1323  (*range_error)++;
1324  *usp++ = (unsigned short)*dp++;
1325  }
1326  break;
1327  case NC_UINT:
1328  for (dp = (double *)src, uip = dest; count < len; count++)
1329  {
1330  if (*dp > X_UINT_MAX || *dp < 0)
1331  (*range_error)++;
1332  *uip++ = (unsigned int)*dp++;
1333  }
1334  break;
1335  case NC_INT:
1336  for (dp = (double *)src, ip = dest; count < len; count++)
1337  {
1338  if (*dp > X_INT_MAX || *dp < X_INT_MIN)
1339  (*range_error)++;
1340  *ip++ = (int)*dp++;
1341  }
1342  break;
1343  case NC_INT64:
1344  for (dp = (double *)src, lip = dest; count < len; count++)
1345  {
1346  if (*dp > (double)X_INT64_MAX || *dp < X_INT64_MIN)
1347  (*range_error)++;
1348  *lip++ = (long long)*dp++;
1349  }
1350  break;
1351  case NC_UINT64:
1352  for (dp = (double *)src, ulip = dest; count < len; count++)
1353  {
1354  if (*dp > (double)X_UINT64_MAX || *dp < 0)
1355  (*range_error)++;
1356  *ulip++ = (unsigned long long)*dp++;
1357  }
1358  break;
1359  case NC_FLOAT:
1360  for (dp = (double *)src, fp = dest; count < len; count++)
1361  {
1362  if (isgreater(*dp, X_FLOAT_MAX) || isless(*dp, X_FLOAT_MIN))
1363  (*range_error)++;
1364  *fp++ = (float)*dp++;
1365  }
1366  break;
1367  case NC_DOUBLE:
1368  for (dp = (double *)src, dp1 = dest; count < len; count++)
1369  *dp1++ = *dp++;
1370  break;
1371  default:
1372  LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d",
1373  __func__, src_type, dest_type));
1374  return NC_EBADTYPE;
1375  }
1376  break;
1377 
1378  default:
1379  LOG((0, "%s: unexpected src type. src_type %d, dest_type %d",
1380  __func__, src_type, dest_type));
1381  return NC_EBADTYPE;
1382  }
1383 
1384  /* If quantize is in use, determine masks, copy the data, do the
1385  * quantization. */
1386  if (quantize_mode == NC_QUANTIZE_BITGROOM)
1387  {
1388  if (dest_type == NC_FLOAT)
1389  {
1390  /* BitGroom: alternately shave and set LSBs */
1391  op1.fp = (float *)dest;
1392  u32_ptr = op1.ui32p;
1393  for (idx = 0L; idx < len; idx += 2L)
1394  if (op1.fp[idx] != mss_val_cmp_flt)
1395  u32_ptr[idx] &= msk_f32_u32_zro;
1396  for (idx = 1L; idx < len; idx += 2L)
1397  if (op1.fp[idx] != mss_val_cmp_flt && u32_ptr[idx] != 0U) /* Never quantize upwards floating point values of zero */
1398  u32_ptr[idx] |= msk_f32_u32_one;
1399  }
1400  else
1401  {
1402  /* BitGroom: alternately shave and set LSBs. */
1403  op1.dp = (double *)dest;
1404  u64_ptr = op1.ui64p;
1405  for (idx = 0L; idx < len; idx += 2L)
1406  if (op1.dp[idx] != mss_val_cmp_dbl)
1407  u64_ptr[idx] &= msk_f64_u64_zro;
1408  for (idx = 1L; idx < len; idx += 2L)
1409  if (op1.dp[idx] != mss_val_cmp_dbl && u64_ptr[idx] != 0ULL) /* Never quantize upwards floating point values of zero */
1410  u64_ptr[idx] |= msk_f64_u64_one;
1411  }
1412  } /* endif BitGroom */
1413 
1414  if (quantize_mode == NC_QUANTIZE_BITROUND)
1415  {
1416  if (dest_type == NC_FLOAT)
1417  {
1418  /* BitRound: Quantize to user-specified NSB with IEEE-rounding */
1419  op1.fp = (float *)dest;
1420  u32_ptr = op1.ui32p;
1421  for (idx = 0L; idx < len; idx++){
1422  if (op1.fp[idx] != mss_val_cmp_flt){
1423  u32_ptr[idx] += msk_f32_u32_hshv; /* Add 1 to the MSB of LSBs, carry 1 to mantissa or even exponent */
1424  u32_ptr[idx] &= msk_f32_u32_zro; /* Shave it */
1425  }
1426  }
1427  }
1428  else
1429  {
1430  /* BitRound: Quantize to user-specified NSB with IEEE-rounding */
1431  op1.dp = (double *)dest;
1432  u64_ptr = op1.ui64p;
1433  for (idx = 0L; idx < len; idx++){
1434  if (op1.dp[idx] != mss_val_cmp_dbl){
1435  u64_ptr[idx] += msk_f64_u64_hshv; /* Add 1 to the MSB of LSBs, carry 1 to mantissa or even exponent */
1436  u64_ptr[idx] &= msk_f64_u64_zro; /* Shave it */
1437  }
1438  }
1439  }
1440  } /* endif BitRound */
1441 
1442  if (quantize_mode == NC_QUANTIZE_GRANULARBR)
1443  {
1444  if (dest_type == NC_FLOAT)
1445  {
1446  /* Granular BitRound */
1447  op1.fp = (float *)dest;
1448  u32_ptr = op1.ui32p;
1449  for (idx = 0L; idx < len; idx++)
1450  {
1451 
1452  if((val = op1.fp[idx]) != mss_val_cmp_flt && u32_ptr[idx] != 0U)
1453  {
1454  mnt = frexp(val, &xpn_bs2); /* DGG19 p. 4102 (8) */
1455  mnt_fabs = fabs(mnt);
1456  mnt_log10_fabs = log10(mnt_fabs);
1457  /* 20211003 Continuous determination of dgt_nbr improves CR by ~10% */
1458  dgt_nbr = (int)floor(xpn_bs2 * dgt_per_bit + mnt_log10_fabs) + 1; /* DGG19 p. 4102 (8.67) */
1459  qnt_pwr = (int)floor(bit_per_dgt * (dgt_nbr - nsd)); /* DGG19 p. 4101 (7) */
1460  prc_bnr_xpl_rqr = mnt_fabs == 0.0 ? 0 : (unsigned short)abs((int)floor(xpn_bs2 - bit_per_dgt*mnt_log10_fabs) - qnt_pwr); /* Protect against mnt = -0.0 */
1461  prc_bnr_xpl_rqr--; /* 20211003 Reduce formula result by 1 bit: Passes all tests, improves CR by ~10% */
1462 
1463  bit_xpl_nbr_zro = BIT_XPL_NBR_SGN_FLT - prc_bnr_xpl_rqr;
1464  msk_f32_u32_zro = 0U; /* Zero all bits */
1465  msk_f32_u32_zro = ~msk_f32_u32_zro; /* Turn all bits to ones */
1466  /* Bit Shave mask for AND: Left shift zeros into bits to be rounded, leave ones in untouched bits */
1467  msk_f32_u32_zro <<= bit_xpl_nbr_zro;
1468  /* Bit Set mask for OR: Put ones into bits to be set, zeros in untouched bits */
1469  msk_f32_u32_one = ~msk_f32_u32_zro;
1470  msk_f32_u32_hshv = msk_f32_u32_one & (msk_f32_u32_zro >> 1); /* Set one bit: the MSB of LSBs */
1471  u32_ptr[idx] += msk_f32_u32_hshv; /* Add 1 to the MSB of LSBs, carry 1 to mantissa or even exponent */
1472  u32_ptr[idx] &= msk_f32_u32_zro; /* Shave it */
1473 
1474  } /* !mss_val_cmp_flt */
1475 
1476  }
1477  }
1478  else
1479  {
1480  /* Granular BitRound */
1481  op1.dp = (double *)dest;
1482  u64_ptr = op1.ui64p;
1483  for (idx = 0L; idx < len; idx++)
1484  {
1485 
1486  if((val = op1.dp[idx]) != mss_val_cmp_dbl && u64_ptr[idx] != 0ULL)
1487  {
1488  mnt = frexp(val, &xpn_bs2); /* DGG19 p. 4102 (8) */
1489  mnt_fabs = fabs(mnt);
1490  mnt_log10_fabs = log10(mnt_fabs);
1491  /* 20211003 Continuous determination of dgt_nbr improves CR by ~10% */
1492  dgt_nbr = (int)floor(xpn_bs2 * dgt_per_bit + mnt_log10_fabs) + 1; /* DGG19 p. 4102 (8.67) */
1493  qnt_pwr = (int)floor(bit_per_dgt * (dgt_nbr - nsd)); /* DGG19 p. 4101 (7) */
1494  prc_bnr_xpl_rqr = mnt_fabs == 0.0 ? 0 : (unsigned short)abs((int)floor(xpn_bs2 - bit_per_dgt*mnt_log10_fabs) - qnt_pwr); /* Protect against mnt = -0.0 */
1495  prc_bnr_xpl_rqr--; /* 20211003 Reduce formula result by 1 bit: Passes all tests, improves CR by ~10% */
1496 
1497  bit_xpl_nbr_zro = BIT_XPL_NBR_SGN_DBL - prc_bnr_xpl_rqr;
1498  msk_f64_u64_zro = 0ULL; /* Zero all bits */
1499  msk_f64_u64_zro = ~msk_f64_u64_zro; /* Turn all bits to ones */
1500  /* Bit Shave mask for AND: Left shift zeros into bits to be rounded, leave ones in untouched bits */
1501  msk_f64_u64_zro <<= bit_xpl_nbr_zro;
1502  /* Bit Set mask for OR: Put ones into bits to be set, zeros in untouched bits */
1503  msk_f64_u64_one = ~msk_f64_u64_zro;
1504  msk_f64_u64_hshv = msk_f64_u64_one & (msk_f64_u64_zro >> 1); /* Set one bit: the MSB of LSBs */
1505  u64_ptr[idx] += msk_f64_u64_hshv; /* Add 1 to the MSB of LSBs, carry 1 to mantissa or even exponent */
1506  u64_ptr[idx] &= msk_f64_u64_zro; /* Shave it */
1507 
1508  } /* !mss_val_cmp_dbl */
1509 
1510  }
1511  }
1512  } /* endif GranularBR */
1513 
1514  return NC_NOERR;
1515 }
1516 
1528 int
1529 nc4_get_fill_value(NC_FILE_INFO_T *h5, NC_VAR_INFO_T *var, void **fillp)
1530 {
1531  size_t size;
1532  int retval;
1533 
1534  /* Find out how much space we need for this type's fill value. */
1535  if (var->type_info->nc_type_class == NC_VLEN)
1536  size = sizeof(nc_vlen_t);
1537  else if (var->type_info->nc_type_class == NC_STRING)
1538  size = sizeof(char *);
1539  else
1540  {
1541  if ((retval = nc4_get_typelen_mem(h5, var->type_info->hdr.id, &size)))
1542  return retval;
1543  }
1544  assert(size);
1545 
1546  /* Allocate the space. */
1547  if (!((*fillp) = calloc(1, size)))
1548  return NC_ENOMEM;
1549 
1550  /* If the user has set a fill_value for this var, use, otherwise
1551  * find the default fill value. */
1552  if (var->fill_value)
1553  {
1554  LOG((4, "Found a fill value for var %s", var->hdr.name));
1555  if (var->type_info->nc_type_class == NC_VLEN)
1556  {
1557  nc_vlen_t *in_vlen = (nc_vlen_t *)(var->fill_value), *fv_vlen = (nc_vlen_t *)(*fillp);
1558  size_t basetypesize = 0;
1559 
1560  if((retval=nc4_get_typelen_mem(h5, var->type_info->u.v.base_nc_typeid, &basetypesize)))
1561  return retval;
1562 
1563  fv_vlen->len = in_vlen->len;
1564  if (!(fv_vlen->p = malloc(basetypesize * in_vlen->len)))
1565  {
1566  free(*fillp);
1567  *fillp = NULL;
1568  return NC_ENOMEM;
1569  }
1570  memcpy(fv_vlen->p, in_vlen->p, in_vlen->len * basetypesize);
1571  }
1572  else if (var->type_info->nc_type_class == NC_STRING)
1573  {
1574  if (*(char **)var->fill_value)
1575  if (!(**(char ***)fillp = strdup(*(char **)var->fill_value)))
1576  {
1577  free(*fillp);
1578  *fillp = NULL;
1579  return NC_ENOMEM;
1580  }
1581  }
1582  else
1583  memcpy((*fillp), var->fill_value, size);
1584  }
1585  else
1586  {
1587  if (nc4_get_default_fill_value(var->type_info, *fillp))
1588  {
1589  /* Note: release memory, but don't return error on failure */
1590  free(*fillp);
1591  *fillp = NULL;
1592  }
1593  }
1594 
1595  return NC_NOERR;
1596 }
1597 
1610 int
1611 nc4_get_typelen_mem(NC_FILE_INFO_T *h5, nc_type xtype, size_t *len)
1612 {
1613  NC_TYPE_INFO_T *type;
1614  int retval;
1615 
1616  LOG((4, "%s xtype: %d", __func__, xtype));
1617  assert(len);
1618 
1619  /* If this is an atomic type, the answer is easy. */
1620  switch (xtype)
1621  {
1622  case NC_BYTE:
1623  case NC_CHAR:
1624  case NC_UBYTE:
1625  *len = sizeof(char);
1626  return NC_NOERR;
1627  case NC_SHORT:
1628  case NC_USHORT:
1629  *len = sizeof(short);
1630  return NC_NOERR;
1631  case NC_INT:
1632  case NC_UINT:
1633  *len = sizeof(int);
1634  return NC_NOERR;
1635  case NC_FLOAT:
1636  *len = sizeof(float);
1637  return NC_NOERR;
1638  case NC_DOUBLE:
1639  *len = sizeof(double);
1640  return NC_NOERR;
1641  case NC_INT64:
1642  case NC_UINT64:
1643  *len = sizeof(long long);
1644  return NC_NOERR;
1645  case NC_STRING:
1646  *len = sizeof(char *);
1647  return NC_NOERR;
1648  }
1649 
1650  /* See if var is compound type. */
1651  if ((retval = nc4_find_type(h5, xtype, &type)))
1652  return retval;
1653 
1654  if (!type)
1655  return NC_EBADTYPE;
1656 
1657  *len = type->size;
1658 
1659  LOG((5, "type->size: %d", type->size));
1660 
1661  return NC_NOERR;
1662 }
1663 
1664 
1678 int
1679 nc4_check_chunksizes(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, const size_t *chunksizes)
1680 {
1681  double dprod;
1682  size_t type_len;
1683  int d;
1684  int retval;
1685 
1686  if ((retval = nc4_get_typelen_mem(grp->nc4_info, var->type_info->hdr.id, &type_len)))
1687  return retval;
1688  if (var->type_info->nc_type_class == NC_VLEN)
1689  dprod = (double)sizeof(nc_vlen_t);
1690  else
1691  dprod = (double)type_len;
1692  for (d = 0; d < var->ndims; d++)
1693  dprod *= (double)chunksizes[d];
1694 
1695  if (dprod > (double) NC_MAX_UINT)
1696  return NC_EBADCHUNK;
1697 
1698  return NC_NOERR;
1699 }
1700 
1712 int
1713 nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
1714 {
1715  int d;
1716  size_t type_size;
1717  float num_values = 1, num_unlim = 0;
1718  int retval;
1719  size_t suggested_size;
1720 #ifdef LOGGING
1721  double total_chunk_size;
1722 #endif
1723 
1724  if (var->type_info->nc_type_class == NC_STRING)
1725  type_size = sizeof(char *);
1726  else
1727  type_size = var->type_info->size;
1728 
1729 #ifdef LOGGING
1730  /* Later this will become the total number of bytes in the default
1731  * chunk. */
1732  total_chunk_size = (double) type_size;
1733 #endif
1734 
1735  if(var->chunksizes == NULL) {
1736  if((var->chunksizes = calloc(1,sizeof(size_t)*var->ndims)) == NULL)
1737  return NC_ENOMEM;
1738  }
1739 
1740  /* How many values in the variable (or one record, if there are
1741  * unlimited dimensions). */
1742  for (d = 0; d < var->ndims; d++)
1743  {
1744  assert(var->dim[d]);
1745  if (! var->dim[d]->unlimited)
1746  num_values *= (float)var->dim[d]->len;
1747  else {
1748  num_unlim++;
1749  var->chunksizes[d] = 1; /* overwritten below, if all dims are unlimited */
1750  }
1751  }
1752  /* Special case to avoid 1D vars with unlim dim taking huge amount
1753  of space (DEFAULT_CHUNK_SIZE bytes). Instead we limit to about
1754  4KB */
1755  if (var->ndims == 1 && num_unlim == 1) {
1756  if (DEFAULT_CHUNK_SIZE / type_size <= 0)
1757  suggested_size = 1;
1758  else if (DEFAULT_CHUNK_SIZE / type_size > DEFAULT_1D_UNLIM_SIZE)
1759  suggested_size = DEFAULT_1D_UNLIM_SIZE;
1760  else
1761  suggested_size = DEFAULT_CHUNK_SIZE / type_size;
1762  var->chunksizes[0] = suggested_size / type_size;
1763  LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
1764  "chunksize %ld", __func__, var->hdr.name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[0]));
1765  }
1766  if (var->ndims > 1 && (float)var->ndims == num_unlim) { /* all dims unlimited */
1767  suggested_size = (size_t)pow((double)DEFAULT_CHUNK_SIZE/(double)type_size, 1.0/(double)(var->ndims));
1768  for (d = 0; d < var->ndims; d++)
1769  {
1770  var->chunksizes[d] = suggested_size ? suggested_size : 1;
1771  LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
1772  "chunksize %ld", __func__, var->hdr.name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
1773  }
1774  }
1775 
1776  /* Pick a chunk length for each dimension, if one has not already
1777  * been picked above. */
1778  for (d = 0; d < var->ndims; d++)
1779  if (!var->chunksizes[d])
1780  {
1781  suggested_size = (size_t)(pow((double)DEFAULT_CHUNK_SIZE/(num_values * (double)type_size),
1782  1.0/(double)((double)var->ndims - num_unlim)) * (double)var->dim[d]->len - .5);
1783  if (suggested_size > var->dim[d]->len)
1784  suggested_size = var->dim[d]->len;
1785  var->chunksizes[d] = suggested_size ? suggested_size : 1;
1786  LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
1787  "chunksize %ld", __func__, var->hdr.name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
1788  }
1789 
1790 #ifdef LOGGING
1791  /* Find total chunk size. */
1792  for (d = 0; d < var->ndims; d++)
1793  total_chunk_size *= (double) var->chunksizes[d];
1794  LOG((4, "total_chunk_size %f", total_chunk_size));
1795 #endif
1796 
1797  /* But did this result in a chunk that is too big? */
1798  retval = nc4_check_chunksizes(grp, var, var->chunksizes);
1799  if (retval)
1800  {
1801  /* Other error? */
1802  if (retval != NC_EBADCHUNK)
1803  return retval;
1804 
1805  /* Chunk is too big! Reduce each dimension by half and try again. */
1806  for ( ; retval == NC_EBADCHUNK; retval = nc4_check_chunksizes(grp, var, var->chunksizes))
1807  for (d = 0; d < var->ndims; d++)
1808  var->chunksizes[d] = var->chunksizes[d]/2 ? var->chunksizes[d]/2 : 1;
1809  }
1810 
1811  /* Do we have any big data overhangs? They can be dangerous to
1812  * babies, the elderly, or confused campers who have had too much
1813  * beer. */
1814  for (d = 0; d < var->ndims; d++)
1815  {
1816  size_t num_chunks;
1817  size_t overhang;
1818  assert(var->chunksizes[d] > 0);
1819  num_chunks = (var->dim[d]->len + var->chunksizes[d] - 1) / var->chunksizes[d];
1820  if(num_chunks > 0) {
1821  overhang = (num_chunks * var->chunksizes[d]) - var->dim[d]->len;
1822  var->chunksizes[d] -= overhang / num_chunks;
1823  }
1824  }
1825 
1826 
1827  return NC_NOERR;
1828 }
1829 
1841 int
1842 nc4_get_default_fill_value(NC_TYPE_INFO_T* tinfo, void *fill_value)
1843 {
1844  if(tinfo->hdr.id > NC_NAT && tinfo->hdr.id <= NC_MAX_ATOMIC_TYPE)
1845  return nc4_get_default_atomic_fill_value(tinfo->hdr.id,fill_value);
1846 #ifdef USE_NETCDF4
1847  switch(tinfo->nc_type_class) {
1848  case NC_ENUM:
1849  return nc4_get_default_atomic_fill_value(tinfo->u.e.base_nc_typeid,fill_value);
1850  case NC_OPAQUE:
1851  case NC_VLEN:
1852  case NC_COMPOUND:
1853  if(fill_value)
1854  memset(fill_value,0,tinfo->size);
1855  break;
1856  default: return NC_EBADTYPE;
1857  }
1858 #endif
1859  return NC_NOERR;
1860 }
1861 
1873 int
1874 nc4_get_default_atomic_fill_value(nc_type xtype, void *fill_value)
1875 {
1876  switch (xtype)
1877  {
1878  case NC_CHAR:
1879  *(char *)fill_value = NC_FILL_CHAR;
1880  break;
1881 
1882  case NC_STRING:
1883  *(char **)fill_value = strdup(NC_FILL_STRING);
1884  break;
1885 
1886  case NC_BYTE:
1887  *(signed char *)fill_value = NC_FILL_BYTE;
1888  break;
1889 
1890  case NC_SHORT:
1891  *(short *)fill_value = NC_FILL_SHORT;
1892  break;
1893 
1894  case NC_INT:
1895  *(int *)fill_value = NC_FILL_INT;
1896  break;
1897 
1898  case NC_UBYTE:
1899  *(unsigned char *)fill_value = NC_FILL_UBYTE;
1900  break;
1901 
1902  case NC_USHORT:
1903  *(unsigned short *)fill_value = NC_FILL_USHORT;
1904  break;
1905 
1906  case NC_UINT:
1907  *(unsigned int *)fill_value = NC_FILL_UINT;
1908  break;
1909 
1910  case NC_INT64:
1911  *(long long *)fill_value = NC_FILL_INT64;
1912  break;
1913 
1914  case NC_UINT64:
1915  *(unsigned long long *)fill_value = NC_FILL_UINT64;
1916  break;
1917 
1918  case NC_FLOAT:
1919  *(float *)fill_value = NC_FILL_FLOAT;
1920  break;
1921 
1922  case NC_DOUBLE:
1923  *(double *)fill_value = NC_FILL_DOUBLE;
1924  break;
1925 
1926  default:
1927  return NC_EINVAL;
1928  }
1929  return NC_NOERR;
1930 }
1931 
#define NC_FILL_UBYTE
Default fill value.
Definition: netcdf.h:73
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:458
#define NC_CHUNKED
In HDF5 files you can set storage for each variable to be either contiguous or chunked, with nc_def_var_chunking().
Definition: netcdf.h:314
#define NC_CHAR
ISO/ASCII character.
Definition: netcdf.h:36
#define NC_MAX_INT
Max or min values for a type.
Definition: netcdf.h:94
#define NC_FILL_CHAR
Default fill value.
Definition: netcdf.h:68
#define NC_UBYTE
unsigned 1 byte int
Definition: netcdf.h:42
#define NC_ERANGE
Math result not representable.
Definition: netcdf.h:457
#define NC_FILL_UINT
Default fill value.
Definition: netcdf.h:75
#define NC_UINT
unsigned 4-byte int
Definition: netcdf.h:44
#define NC_OPAQUE
opaque types
Definition: netcdf.h:54
#define M_LN2
log_e 2
Definition: nc4var.c:31
#define NC_INT64
signed 8-byte int
Definition: netcdf.h:45
#define NC_STRING
string
Definition: netcdf.h:47
#define BIT_XPL_NBR_SGN_DBL
Used in quantize code.
Definition: nc4var.c:44
#define NC_DOUBLE
double precision floating point number
Definition: netcdf.h:41
#define NC_NOQUANTIZE
No quantization in use.
Definition: netcdf.h:345
#define NC_FILL_UINT64
Default fill value.
Definition: netcdf.h:77
#define NC_INDEPENDENT
Use with nc_var_par_access() to set parallel access to independent.
Definition: netcdf_par.h:26
int nc_type
The nc_type type is just an int.
Definition: netcdf.h:25
#define NC_FILL_STRING
Default fill value.
Definition: netcdf.h:78
#define NC_COLLECTIVE
Use with nc_var_par_access() to set parallel access to collective.
Definition: netcdf_par.h:28
#define NC_BYTE
signed 1 byte integer
Definition: netcdf.h:35
#define NC_FILL_INT
Default fill value.
Definition: netcdf.h:70
size_t len
Length of VL data (in base type units)
Definition: netcdf.h:762
#define NC_VLEN
vlen (variable-length) types
Definition: netcdf.h:53
#define NC_EFILTER
Filter operation failed.
Definition: netcdf.h:523
#define NC_EBADTYPE
Not a netcdf data type.
Definition: netcdf.h:420
#define NC_EINVAL
Invalid Argument.
Definition: netcdf.h:388
#define NC_INT
signed 4 byte integer
Definition: netcdf.h:38
#define NC_QUANTIZE_BITGROOM
Use BitGroom quantization.
Definition: netcdf.h:346
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:291
void * p
Pointer to VL data.
Definition: netcdf.h:763
#define NC_NAT
Not A Type.
Definition: netcdf.h:34
EXTERNL int nc_inq_var_filter_info(int ncid, int varid, unsigned int id, size_t *nparams, unsigned int *params)
Find the the param info about filter (if any) associated with a variable and with specified id...
Definition: dfilter.c:95
#define NC_USHORT
unsigned 2-byte int
Definition: netcdf.h:43
#define NC_FILL_FLOAT
Default fill value.
Definition: netcdf.h:71
#define NC_ENOFILTER
Filter not defined on variable.
Definition: netcdf.h:527
#define NC_ENOPAR
Parallel operation on file opened for non-parallel access.
Definition: netcdf.h:504
This is the type of arrays of vlens.
Definition: netcdf.h:761
#define NC_MAX_UINT
Max or min values for a type.
Definition: netcdf.h:102
#define NC_SHORT
signed 2 byte integer
Definition: netcdf.h:37
#define NC_ENOTVAR
Variable not found.
Definition: netcdf.h:432
#define NC_QUANTIZE_BITROUND
Use BitRound quantization.
Definition: netcdf.h:348
#define NC_NOERR
No Error.
Definition: netcdf.h:378
#define NC_QUANTIZE_GRANULARBR
Use Granular BitRound quantization.
Definition: netcdf.h:347
#define NC_ENUM
enum types
Definition: netcdf.h:55
#define NC_FILL_SHORT
Default fill value.
Definition: netcdf.h:69
#define NC_FILL_DOUBLE
Default fill value.
Definition: netcdf.h:72
#define NC_COMPOUND
compound types
Definition: netcdf.h:56
#define NC_FILL_USHORT
Default fill value.
Definition: netcdf.h:74
#define NC_FILL_BYTE
Default fill value.
Definition: netcdf.h:67
#define NC_GLOBAL
Attribute id to put/get a global attribute.
Definition: netcdf.h:264
#define NC_FLOAT
single precision floating point number
Definition: netcdf.h:40
#define M_LN10
log_e 10
Definition: nc4var.c:28
#define NC_FILL_INT64
Default fill value.
Definition: netcdf.h:76
#define NC_UINT64
unsigned 8-byte int
Definition: netcdf.h:46
#define BIT_XPL_NBR_SGN_FLT
Used in quantize code.
Definition: nc4var.c:38
#define NC_EBADCHUNK
Bad chunksize.
Definition: netcdf.h:517