NetCDF 4.9.3
Loading...
Searching...
No Matches
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.*/
12
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
47typedef 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
71int
72NC4_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
119int
120nc_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
178int
179NC4_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
300int
301nc_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
350int
351NC4_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
402int
403NC4_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
483int
484nc4_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
1528int
1529nc4_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
1610int
1611nc4_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
1678int
1679nc4_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
1712int
1713nc4_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
1841int
1842nc4_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
1873int
1874nc4_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
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 M_LN10
log_e 10
Definition nc4var.c:28
#define BIT_XPL_NBR_SGN_DBL
Used in quantize code.
Definition nc4var.c:44
#define M_LN2
log_e 2
Definition nc4var.c:31
#define BIT_XPL_NBR_SGN_FLT
Used in quantize code.
Definition nc4var.c:38
#define NC_EBADTYPE
Not a netcdf data type.
Definition netcdf.h:420
#define NC_UINT
unsigned 4-byte int
Definition netcdf.h:44
#define NC_FILL_BYTE
Default fill value.
Definition netcdf.h:67
void * p
Pointer to VL data.
Definition netcdf.h:763
#define NC_EFILTER
Filter operation failed.
Definition netcdf.h:523
#define NC_INT
signed 4 byte integer
Definition netcdf.h:38
#define NC_FILL_INT
Default fill value.
Definition netcdf.h:70
#define NC_BYTE
signed 1 byte integer
Definition netcdf.h:35
#define NC_QUANTIZE_BITROUND
Use BitRound quantization.
Definition netcdf.h:348
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_FILL_UBYTE
Default fill value.
Definition netcdf.h:73
#define NC_NAT
Not A Type.
Definition netcdf.h:34
#define NC_MAX_UINT
Max or min values for a type.
Definition netcdf.h:102
#define NC_DOUBLE
double precision floating point number
Definition netcdf.h:41
#define NC_UBYTE
unsigned 1 byte int
Definition netcdf.h:42
#define NC_FLOAT
single precision floating point number
Definition netcdf.h:40
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition netcdf.h:458
#define NC_MAX_INT
Max or min values for a type.
Definition netcdf.h:94
#define NC_COMPOUND
compound types
Definition netcdf.h:56
#define NC_CHUNKED
In HDF5 files you can set storage for each variable to be either contiguous or chunked,...
Definition netcdf.h:314
#define NC_SHORT
signed 2 byte integer
Definition netcdf.h:37
#define NC_QUANTIZE_GRANULARBR
Use Granular BitRound quantization.
Definition netcdf.h:347
#define NC_FILL_UINT64
Default fill value.
Definition netcdf.h:77
#define NC_QUANTIZE_BITGROOM
Use BitGroom quantization.
Definition netcdf.h:346
#define NC_ENUM
enum types
Definition netcdf.h:55
#define NC_INT64
signed 8-byte int
Definition netcdf.h:45
#define NC_GLOBAL
Attribute id to put/get a global attribute.
Definition netcdf.h:264
#define NC_FILL_UINT
Default fill value.
Definition netcdf.h:75
#define NC_FILL_CHAR
Default fill value.
Definition netcdf.h:68
#define NC_UINT64
unsigned 8-byte int
Definition netcdf.h:46
#define NC_ENOTVAR
Variable not found.
Definition netcdf.h:432
#define NC_EINVAL
Invalid Argument.
Definition netcdf.h:388
#define NC_MAX_NAME
Maximum for classic library.
Definition netcdf.h:291
#define NC_NOERR
No Error.
Definition netcdf.h:378
#define NC_FILL_USHORT
Default fill value.
Definition netcdf.h:74
#define NC_FILL_SHORT
Default fill value.
Definition netcdf.h:69
#define NC_FILL_INT64
Default fill value.
Definition netcdf.h:76
#define NC_NOQUANTIZE
No quantization in use.
Definition netcdf.h:345
#define NC_USHORT
unsigned 2-byte int
Definition netcdf.h:43
#define NC_OPAQUE
opaque types
Definition netcdf.h:54
#define NC_ENOPAR
Parallel operation on file opened for non-parallel access.
Definition netcdf.h:504
#define NC_STRING
string
Definition netcdf.h:47
#define NC_EBADCHUNK
Bad chunksize.
Definition netcdf.h:517
#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_FILL_DOUBLE
Default fill value.
Definition netcdf.h:72
#define NC_CHAR
ISO/ASCII character.
Definition netcdf.h:36
#define NC_ERANGE
Math result not representable.
Definition netcdf.h:457
#define NC_FILL_STRING
Default fill value.
Definition netcdf.h:78
int nc_type
The nc_type type is just an int.
Definition netcdf.h:25
This is the type of arrays of vlens.
Definition netcdf.h:761
#define NC_COLLECTIVE
Use with nc_var_par_access() to set parallel access to collective.
Definition netcdf_par.h:28
#define NC_INDEPENDENT
Use with nc_var_par_access() to set parallel access to independent.
Definition netcdf_par.h:26