[Git][debian-gis-team/nco][upstream] New upstream version 5.3.3

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Sat Mar 29 06:18:35 GMT 2025



Bas Couwenberg pushed to branch upstream at Debian GIS Project / nco


Commits:
ef52a766 by Bas Couwenberg at 2025-03-29T06:23:08+01:00
New upstream version 5.3.3
- - - - -


30 changed files:

- bld/nco.spec
- bm/NCO_rgr.pm
- configure
- configure.ac
- configure.eg
- data/in.cdl
- data/ncclimo
- debian/changelog
- doc/ANNOUNCE
- doc/ChangeLog
- doc/VERSION
- doc/debian.txt
- doc/index.shtml
- doc/nco.texi
- man/ncks.1
- man/ncra.1
- src/nco/ncks.c
- src/nco/nco.h
- src/nco/nco_ctl.c
- src/nco/nco_grp_utl.c
- src/nco/nco_grp_utl.h
- src/nco/nco_map.c
- src/nco/nco_mta.c
- src/nco/nco_ply_lst.c
- src/nco/nco_ppc.c
- src/nco/nco_rec_var.c
- src/nco/nco_rgr.c
- src/nco/nco_s1d.c
- src/nco/nco_scm.c
- src/nco/ncrename.c


Changes:

=====================================
bld/nco.spec
=====================================
@@ -2,17 +2,17 @@
 # http://cvs.fedoraproject.org/viewvc/devel/nco/nco.spec?view=co
 
 Name:           nco
-Version:        5.3.2
+Version:        5.3.3
 Release:        1%{?dist}
 Summary:        Programs that manipulate netCDF files
 Group:          Applications/Engineering
 License:        BSD
 URL:            http://nco.sf.net/
 
-# Obtain NCO version 5.3.2-1 tar.gz from Sourceforge using CVS:
+# Obtain NCO version 5.3.3-1 tar.gz from Sourceforge using CVS:
 # cvs -d:pserver:anonymous at nco.cvs.sf.net:/cvsroot/nco login
-# cvs -z3 -d:pserver:anonymous at nco.cvs.sf.net:/cvsroot/nco co -r nco-5.3.2-1 -d nco-%{version} nco
-# tar czf nco-%{version}.tar.gz --exclude='nco-5.3.2/debian*' --exclude='.cvsignore' --exclude=ncap_lex.c --exclude='ncap_yacc.[ch]' ./nco-%{version}
+# cvs -z3 -d:pserver:anonymous at nco.cvs.sf.net:/cvsroot/nco co -r nco-5.3.3-1 -d nco-%{version} nco
+# tar czf nco-%{version}.tar.gz --exclude='nco-5.3.3/debian*' --exclude='.cvsignore' --exclude=ncap_lex.c --exclude='ncap_yacc.[ch]' ./nco-%{version}
 Source0:        nco-%{version}.tar.gz
 #Patch0:		nco_install_C_headers.patch
 #Patch1:         nco_find_udunits-dat.patch
@@ -108,6 +108,9 @@ fi
 # %{_libdir}/libnco++.so
 
 %changelog
+* Fri Mar 28 2025 Charlie Zender <zender at uci.edu> - 5.3.3-1
+- new upstream 5.3.3
+
 * Wed Feb 05 2025 Charlie Zender <zender at uci.edu> - 5.3.2-1
 - new upstream 5.3.2
 


=====================================
bm/NCO_rgr.pm
=====================================
@@ -95,7 +95,7 @@ sub tst_rgr {
     
     # 20150619: nco_ctl.c/nco_exit_lbr_rcd() deducts offset of 300 so rcd < 255
     # Verify exit status in shell with "echo $?"
-    # Library 4.3.3 should return $? = 133
+    # Library 4.3.3 should return $? = 133 and Library 4.9.4 should return $? = 194
     $exit_value+=300;
 
     # nco_exit_lbr_rcd() returns codes from nco_ctl.c:
@@ -127,7 +127,8 @@ sub tst_rgr {
     # 492 (for library 4.9.2)
     # 493 (for library 4.9.3)
     # 494 (for library 4.9.4)
-    # 495 (for library 4.9.5)
+    # 500 (for library 4.10.0)
+    # 501 (for library 4.10.1)
 
   if($exit_value == 410){print "netCDF version 4.1.x detected\n";}
   if($exit_value == 431){print "netCDF version 4.3.1 detected\n";}
@@ -155,7 +156,10 @@ sub tst_rgr {
   if($exit_value == 492){print "netCDF version 4.9.2 detected\n";}
   if($exit_value == 493){print "netCDF version 4.9.3 detected\n";}
   if($exit_value == 494){print "netCDF version 4.9.4 detected\n";}
-  if($exit_value == 495){print "netCDF version 4.9.5 detected\n";}
+    # 20250215: New convention required to support netCDF library 4.10.0 and beyond
+    # exit_value=300 refers to netCDF library 4.10.0, not 5.0.0
+  if($exit_value == 500){print "netCDF version 4.10.0 detected\n";}
+  if($exit_value == 501){print "netCDF version 4.10.1 detected\n";}
 
   if($exit_value >= 400){$RUN_NETCDF4_TESTS=1;}
   if($exit_value >= 431){$RUN_NETCDF4_TESTS_VERSION_GE_431=1;}


=====================================
configure
=====================================
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for NCO netCDF Operators 5.3.2.
+# Generated by GNU Autoconf 2.72 for NCO netCDF Operators 5.3.3.
 #
 # Report bugs to <nco-bugs at lists.sourceforge.net>.
 #
@@ -616,8 +616,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='NCO netCDF Operators'
 PACKAGE_TARNAME='nco'
-PACKAGE_VERSION='5.3.2'
-PACKAGE_STRING='NCO netCDF Operators 5.3.2'
+PACKAGE_VERSION='5.3.3'
+PACKAGE_STRING='NCO netCDF Operators 5.3.3'
 PACKAGE_BUGREPORT='nco-bugs at lists.sourceforge.net'
 PACKAGE_URL=''
 
@@ -1426,7 +1426,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-'configure' configures NCO netCDF Operators 5.3.2 to adapt to many kinds of systems.
+'configure' configures NCO netCDF Operators 5.3.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1498,7 +1498,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of NCO netCDF Operators 5.3.2:";;
+     short | recursive ) echo "Configuration of NCO netCDF Operators 5.3.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1670,7 +1670,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-NCO netCDF Operators configure 5.3.2
+NCO netCDF Operators configure 5.3.3
 generated by GNU Autoconf 2.72
 
 Copyright (C) 2023 Free Software Foundation, Inc.
@@ -2449,7 +2449,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by NCO netCDF Operators $as_me 5.3.2, which was
+It was created by NCO netCDF Operators $as_me 5.3.3, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -4549,7 +4549,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='nco'
- VERSION='5.3.2'
+ VERSION='5.3.3'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -23047,7 +23047,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by NCO netCDF Operators $as_me 5.3.2, which was
+This file was extended by NCO netCDF Operators $as_me 5.3.3, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -23115,7 +23115,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-NCO netCDF Operators config.status 5.3.2
+NCO netCDF Operators config.status 5.3.3
 configured by $0, generated by GNU Autoconf 2.72,
   with options \\"\$ac_cs_config\\"
 


=====================================
configure.ac
=====================================
@@ -56,7 +56,7 @@
 # 20170808: Choose between traditional version and Git-based version
 # If Git, consider that Linux dynamic libraries will have full messy name, MacOS will not
 # https://stackoverflow.com/questions/43526939/how-to-insert-git-based-version-in-autoconf-managed-project
-AC_INIT([NCO netCDF Operators],[5.3.2],[nco-bugs at lists.sourceforge.net],[nco])
+AC_INIT([NCO netCDF Operators],[5.3.3],[nco-bugs at lists.sourceforge.net],[nco])
 
 # Print GNU copyright in configure script
 AC_COPYRIGHT


=====================================
configure.eg
=====================================
@@ -520,27 +520,9 @@ cd ~/nco/bld;make ANTLR_ROOT=${HOME} ANTLR_LIB=${MY_LIB_DIR} NETCDF_ROOT='/ccs/p
 # Personal recipe last modified: 20240118 (remove gcc/11.2.0, update to cray-hdf5/1.12.2.9 cray-netcdf/4.9.0.9)
 # Personal recipe last borken: 20231103
 # Personal recipe last successful: 20240214
-module load PrgEnv-gnu
-module load cray-hdf5/1.12.2.9
-module load cray-netcdf/4.9.0.9
-export HDF5_DISABLE_VERSION_CHECK=1
-export HDF5_USE_FILE_LOCKING=FALSE
+# 20250317 NB: /usr/bin/insall dumps core on PM, must install and use Anaconda coreutils version of 'install' to install into /global/cfs/cdirs/e3sm/zender
+# 20250321 Build on PM in $DATA using entirely public directories
 cd ~/nco;/bin/rm -f *.foo;make distclean
-cd ~/nco;ANTLR_ROOT=${HOME} ANTLR_LIB=${HOME}/lib_perlmutter CC='gcc' CXX='g++' NETCDF_DIR='/opt/cray/pe/netcdf/4.9.0.9/gnu/12.3' NETCDF_INC='/opt/cray/pe/netcdf/4.9.0.9/gnu/12.3/include' NETCDF_LIB='/opt/cray/pe/netcdf/4.9.0.9/gnu/12.3/lib' NETCDF_ROOT='/opt/cray/pe/netcdf/4.9.0.9' UDUNITS2_ROOT=${HOME} ./configure --prefix=${HOME} --bindir=${HOME}/bin_perlmutter --datadir=${HOME}/nco/data --libdir=${HOME}/lib_perlmutter --mandir=${HOME}/man > nco.configure.foo 2>&1
-/bin/cp -f config.log nco.config.log.foo
-/bin/cp -f libtool nco.libtool.foo
-make clean;make > nco.make.foo 2>&1
-make check >> nco.make.foo 2>&1
-make install >> nco.make.foo 2>&1
-scp nco.configure.foo nco.config.log.foo nco.libtool.foo nco.make.foo dust.ess.uci.edu:Sites/nco/rgr
-
-# 20250102 Attempt to build on PM using entirely public directories
-export PATH="./:/global/cfs/cdirs/e3sm/zender/sh:/global/cfs/cdirs/e3sm/zender/bin_perlmutter:/global/cfs/cdirs/e3sm/zender/anaconda/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/usr/bin:/opt/cray/pe/netcdf/4.8.1.1/gnu/9.1/bin"
-export LD_LIBRARY_PATH="./:/global/cfs/cdirs/e3sm/zender/lib_perlmutter:/global/cfs/cdirs/e3sm/zender/anaconda/lib:/usr/local/lib:/lib:/usr/lib:/usr/lib:/opt/cray/pe/netcdf/4.8.1.1/gnu/9.1/lib:/global/common/software/spackecp/perlmutter/e4s-21.11/software/cray-sles15-zen3/gcc-11.2.0/gsl-2.7-2p3pcjckzogek2dubph7q4yd5msjuhxt/lib"
-export MY_BIN_DIR=/global/cfs/cdirs/e3sm/zender/bin_perlmutter
-export MY_LIB_DIR=/global/cfs/cdirs/e3sm/zender/lib_perlmutter
-export MY_OBJ_DIR=/global/cfs/cdirs/e3sm/zender/obj_perlmutter
-
 export LINUX_CC='gcc -std=c99 -pedantic -D_DEFAULT_SOURCE'
 export LINUX_CXX='g++ -std=c++11'
 export LINUX_FC='gfortran'
@@ -548,7 +530,14 @@ export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/global/common/software/e3sm/anaconda_
 export NETCDF_ROOT=/global/common/software/e3sm/anaconda_envs/base/envs/e3sm_unified_latest
 export PATH=${PATH}:/global/common/software/e3sm/anaconda_envs/base/envs/e3sm_unified_latest/bin
 cd ~/nco;git reset --hard origin/master
-cd ~/nco;CC=${LINUX_CC} CPPFLAGS="-I${DATA}/anaconda/include -I/global/common/software/e3sm/anaconda_envs/base/envs/e3sm_unified_latest/include" CXX=${LINUX_CXX} LDFLAGS="-L${DATA}/anaconda/lib -L/global/common/software/e3sm/anaconda_envs/base/envs/e3sm_unified_latest/lib" NETCDF_ROOT=${DATA}/anaconda ./configure --prefix=${DATA} --bindir=${MY_BIN_DIR} --datadir=${HOME}/nco/data --libdir=${MY_LIB_DIR} --mandir=${HOME}/nco/man > nco.configure.foo 2>&1
+cd ~/nco;CC=${LINUX_CC} CXX=${LINUX_CXX} NETCDF_ROOT=${HOME}/anaconda ./configure --prefix=${HOME} --bindir=${MY_BIN_DIR} --datadir=${HOME}/nco/data --libdir=${MY_LIB_DIR} --mandir=${HOME}/nco/man > nco.configure.foo 2>&1
+cd ~/nco;CC=${LINUX_CC} CPPFLAGS="-I${DATA}/anaconda/include -I/global/common/software/e3sm/anaconda_envs/base/envs/e3sm_unified_latest/include" CXX=${LINUX_CXX} LDFLAGS="-L${DATA}/anaconda/lib -L/global/common/software/e3sm/anaconda_envs/base/envs/e3sm_unified_latest/lib" NETCDF_ROOT=${DATA}/anaconda UDUNITS2_ROOT=${HOME} ./configure --prefix=${DATA} --bindir=${MY_BIN_DIR} --datadir=${HOME}/nco/data --libdir=${MY_LIB_DIR} --mandir=${HOME}/nco/man > nco.configure.foo 2>&1
+/bin/cp -f config.log nco.config.log.foo
+/bin/cp -f libtool nco.libtool.foo
+make clean;make > nco.make.foo 2>&1
+make check >> nco.make.foo 2>&1
+make install >> nco.make.foo 2>&1
+scp nco.configure.foo nco.config.log.foo nco.libtool.foo nco.make.foo dust.ess.uci.edu:Sites/nco/rgr
 # !Perlmutter
 
 # gcc/g++ Zender uses this to develop/install/update netCDF4-enabled NCO in personal directories on greenplanet


=====================================
data/in.cdl
=====================================
@@ -443,6 +443,11 @@ variables:
         ppc_flt:purpose = "test --ppc switches";
         ppc_flt:original_values="0.0,0.1,0.12,0.123,0.1234,0.12345,0.123456,0.1234567,0.12345678,0.123456789";
 
+	float ppc_cmor(time);
+        ppc_cmor:long_name = "Precision-Preserving Compression, single precision, CMOR example";
+        ppc_cmor:purpose = "test --ppc switches";
+        ppc_cmor:original_values="289.5131,288.9269,287.7451,287.6399,287.6637,287.7289,287.6711,287.2469,286.6356,286.3299"; 
+
 	double ppc_big(time);
         ppc_big:long_name = "Precision-Preserving Compression, big numbers";
         ppc_big:purpose = "test --ppc switches";
@@ -482,6 +487,12 @@ variables:
 	double ppc_zro_dbl(time);
 	ppc_zro_dbl:long_name = "array of double precision floating point zeros";
 
+	float ppc_zro_ngt_nan_flt(time);
+	ppc_zro_ngt_nan_flt:long_name = "array of single precision floating point NaNs and negative zeros";
+
+	double ppc_zro_ngt_nan_dbl(time);
+	ppc_zro_ngt_nan_dbl:long_name = "array of double precision floating point NaNs and negative zeros";
+
 	int ppc_zro_int(time);
 	ppc_zro_int:long_name = "array of integer zeros";
 
@@ -1619,6 +1630,7 @@ data:
 	               -11,-12,-13,-14,-15,-16,-17,-18,-19,-20;
 	ppc_dbl=0.0,0.1,0.12,0.123,0.1234,0.12345,0.123456,0.1234567,0.12345678,0.123456789;
 	ppc_flt=0.0,0.1,0.12,0.123,0.1234,0.12345,0.123456,0.1234567,0.12345678,0.123456789;
+	ppc_cmor=289.5131,288.927,287.7451,287.6399,287.6637,287.7289,287.671,287.2469,286.6355,286.3299;
 	ppc_big=123456789e-10,123456789e-9,123456789e-8,123456789e-7,123456789e-6,123456789e-5,123456789e-4,123456789e-3,123456789e-2,123456789e-1;
 	ppc_btg=1234567890e20,1234567890e19,1234567890e18,1234567890e17,1234567890e16,1234567890e15,1234567890e14,1234567890e13,1234567890e12,1234567890e11;
 	ppc_btg_scl=1234567890e11;
@@ -1628,11 +1640,13 @@ data:
         ppc_tst=0.0,_,0.1234567,-0.1234567,64,-64,123456789e25,123456789e-25,3.1415926535897932384626433832795029,-3.1415926535897932384626433832795029;
 	ppc_zro_flt=0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0;
 	ppc_zro_dbl=0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0;
+	ppc_zro_ngt_nan_flt=-0.0,0.0,NaNf,-0.0,0.0,NaNf,-0.0,-0.0,NaNf,3.1415926535897932384626433832795029;
+	ppc_zro_ngt_nan_dbl=-0.0,0.0,NaN,-0.0,0.0,NaN,-0.0,-0.0,NaN,3.14159265358;
 	ppc_zro_int=0,0,0,0,0,0,0,0,0,0;
 	qnt_flt_tst1=1.1111111;
 	qnt_dbl_tst1=1.111111111111;
-	qnt_flt_tst2=1.11111111, 1.0, 9.99999999, 12345.67, .1234567;
-	qnt_dbl_tst2=1.1111111, 1.0, 9.999999999, 1234567890.12345, 123456789012345.0;
+	qnt_flt_tst2=1.11111111,1.0,9.99999999,12345.67,.1234567;
+	qnt_dbl_tst2=1.1111111,1.0,9.999999999,1234567890.12345,123456789012345.0;
 	var_msk=0.,1.,0.,0.,1.,1.,0.,2.;
 	var_mss_nil=0.,1.,2.,3.;
 	var_mss_0=_,1.,2.,3.;


=====================================
data/ncclimo
=====================================
@@ -1570,7 +1570,15 @@ if [ "${tms_flg}" = 'Yes' ]; then
 	if [ -z "${var_lst}" ]; then
 	    echo "${spt_nm}: WARNING Splitter mode without explicitly specified variable list (i.e., -v var_lst) splits all variables of rank >= 2 into separate files, thus doubling the on-disk data amount"
 	fi # !var_lst
-	var_lst=`ncks --lst_rnk_ge2 ${ppn_opt} ${fl_in[0]}`
+	if [ "${rgn_stt}" != 'No' ]; then 
+	    # 20250327 Restrict regional statistics to horizontal-only (lat, lon, ncol) timeseries
+	    # ncap2 regional timeseries will break when extra (e.g., vertical) dimensions are present
+	    var_lst_flg_opt='--lst_hrz'
+	else # !rgn_stt
+	    # Timeseries of any rank >= 2 are OK
+	    var_lst_flg_opt='--lst_rnk_ge2'
+	fi # !rgn_stt
+	var_lst=`ncks ${var_lst_flg_opt} ${ppn_opt} ${fl_in[0]}`
 	if [ "${xcl_flg}" = 'Yes' ]; then
 	    var_lst_all=( ${var_lst//,/ } )
 	fi # !xcl_flg


=====================================
debian/changelog
=====================================
@@ -1,3 +1,9 @@
+nco (5.3.3-1) unstable; urgency=low
+
+  * new upstream version Sea Shanty: all: qnt ngt zro NaN; ncks: --fpe, ngl rsn chk map, s1d frc_column frc_landunit attribute fix; ncclimo: rgn_stt uses --lst_hrz; ncremap: fix prs->hyb w/fat tpl; ncrename: WARN crd/dmn netCDF4
+
+ -- Charlie Zender <zender at uci.edu> Fri, 28 Mar 2025 12:26:20 -0700
+
 nco (5.3.2-1) unstable; urgency=low
 
   * new upstream version Prime Rib: all: fix qnt w/ grp; ncremap: ECMWF/IFS CAMS lnsp lev_2, ps_nm_out mtd, hyb cff cf mtd, fix ECMWF/IFS ntp ERROR/HINT, inode dpl, srun default


=====================================
doc/ANNOUNCE
=====================================
@@ -1,81 +1,138 @@
 $Header$ -*-text-*-
 
-netCDF Operators NCO version 5.3.2 hit the streets
+netCDF Operators NCO version 5.3.3 split the uprights
 
 http://nco.sf.net (Homepage, Mailing lists, Help)
 http://github.com/nco/nco (Source Code, Issues, Releases)
 
 What's new?
-Version 5.3.2 mainly adds features and fixes to ncremap and
-quantization. Support for vertical interpolation of ECMWF
-IFS, and CAMS-format hybrid sigma-pressure vertical coordinate
-datasets has been improved. And the output is more CF-compliant.
-All arithmetic operators are once again able to use NCO quantization
-algorithms on variables in non-root groups.
+Version 5.3.3 adds IEEE floating-point exception testing to ncks.
+All operators include corner-case quantization fixes for strange
+numbers (-0.0, NaN) that are also now in the netCDF-C Library.
+ncclimo now only tries to create regional timeseries statistics
+on variables that are single-level horizontal lat/lon/ncol fields.
+ncremap supports interpolation of pure-pressure to hybrid
+sigma-pressure coordinates with distinct source and destination
+surface pressure fields. And ncrename adds some words of caution.
 Skip this release if these changes do not interest you. 
 
-Work on 5.3.3 is underway and includes improved NC_STRING
-autoconversion support for other NCO operators.
+Did you realize that the first public release of ncks was May 2, 1995?
+https://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/1995/msg00069.html
+Happy 30th birthday ncks! 
 
 Enjoy,
 Charlie
 
 NEW FEATURES (full details always in ChangeLog):
 
-A. ncremap will vertically interpolate a broader array of ECMWF
-IFS and CAMS-format hybrid sigma-pressure vertical coordinate
-datasets. Recent NCO versions required the log of the surface
-pressure to be in the template vertical coordinate file, rather
-than in the main dataset. Now the (log of) surface pressure can 
-be either in the source dataset or the vertical grid file.
-Previous versions requires the lnsp variable to contain a dimension
-named lev_2 (as in IFS data). Now the regridder also accomodates
-CAMS-format data that does not contain the lev_2 dimension.
-Thanks to Erik Koene (LLNL) for persistently reporting this :)
+A. The new ncks --fpe option reports the status of all IEEE Floating
+Point Exceptions (FPEs) after execution. This can be useful to verify
+whether input datasets contain strange numbers that could be
+arithmetically processed, and to ensure the integrity of NCO
+arithmetic. 
+
+% ncks --fpe -O -7 -L 1 -C -v ppc_zro_ngt_nan_flt --qnt_alg=gbr \
+       --qnt default=3 --cmp='shf|zst' in.nc out.nc
+ncks: Successfully set FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW exception flags
+ncks: FE_DIVBYZERO is not raised
+ncks: FE_INEXACT is raised
+ncks: FE_INVALID is not raised
+ncks: FE_OVERFLOW is not raised
+ncks: FE_UNDERFLOW is not raised
+
+http://nco.sf.net/nco.html#fpe
+http://nco.sf.net/nco.html#ncks
+
+B. All operators can now quantize -0.0 (a legal number) without
+triggering any IEEE Floating Point Exceptions (FPEs). Other weird
+numbers, like NaN, already avoided FPEs. Moreover, the necessary
+changes to avoid FPEs have been merged upstream into the quantization
+algorithms in libnetcdf version 4.10-development. Thanks to Jeff
+Whitaker (NOAA) for bringing this to our attention, to M. Garcia
+for the original bug report, and to Ward Fisher for merging.
+http://nco.sf.net/nco.html#qnt
 
-ncremap --ps_nm=lnsp --vrt_fl=era5.nc cams_in.nc cams_out.nc
+C. When no explicit variable extraction list is specified in
+timeseries mode, ncclimo automatically creates timeseries for all
+input variables with at least two dimension. However, when regional
+statistics are also requested with --rgn_stt, these statistics are
+only meaningful for spatial timeseries, i.e., single level fields with
+latitude, longitude, and time. Under these circumstances ncclimo now
+only creates regional statistics for single level spatial timeseries.
+Previously it would try (and fail) to generate regional statistics 
+for multi-level or otherwise inappropriate rank >=2 variables.
 
-http://nco.sf.net/nco.html#ifs
-http://nco.sf.net/nco.html#vrt
+ls caseid*.nc | ncclimo --split --rgn_avg -s 2013 -e 2014 -o foo
 
-B. ncremap's vertical interpolator now attaches CF metadata
-(standard_name), units, and long_name attributes to output files
-stored on hybrid sigma-pressure vertical coordinate grids, e.g.,
-  double P0 ;
-      P0:long_name = "Reference pressure" ;
-      P0:standard_name = "reference_air_pressure_for_atmosphere_vertical_coordinate" ;
-      P0:units = "Pa" ;
-    double hybm(nhym) ;
-      hybm:long_name = "hybrid B coefficient at layer midpoints" ;
-      hybm:units = "1" ;
-      hybm:standard_name = "atmosphere_hybrid_sigma_pressure_coordinate" ;
-
-C. ncremap and ncclimo previously prevented refused to overwrite
-input files with the same name as output files. However, this safety
-feature failed to detect when input and output filenames were symbolic
-links to the same file. Now ncremap and ncclimo refuse to overwrite
-input files that are the same inode/device as output files.
-Thanks to Juan Tolento (UCI) for reporting this.
-
-D. ncremap and ncclimo previously defaulted to using PBS "mpi_run -n
-nd_nbr" to manage MPI-mode climatologies and regridding. Now
-ncremap and ncclimo previously default to using SLURM "srun -n
-nd_nbr". This make supporting MPI-mode on unknown (not in the internal
-database of ncremap/ncclimo) machines more likely to work on SLURM,
-which has become increasingly popular (at least at DOE).
-Thanks to Jason Boutte (LLNL) for suggesting this.
-http://nco.sf.net/nco.html#mpi
+http://nco.sf.net/nco.html#ncclimo
 
-BUG FIXES:
-   
-A. Previous versions of NCO would sometimes fail to store
-quantization metadata for variables in non-root groups. Now
-quantization metadata works on variables in non-root groups.
+D. Previous versions of NCO could only interpolate ECMWF/IFS
+data to hybrid sigma-pressure coordinates when the input
+surface pressure (lnsp) was for the output as well. Now NCO
+can interpolate to a distinct output surface pressure that
+is storeed in the vertical template file (a so-called "fat"
+template that includes the surface pressure, rather than a
+"skinny" template that does not).
 
-ncks -O --qnt=btr --ppc dfl=6 -g g1 in_grp.nc out.nc
+ncremap --ps_nm=lnsp --vrt_fl=vrt.nc in.nc out.nc
 
-Thanks to Matt Thompson (GSFC) for reporting this.
-http://nco.sf.net/nco.html#qnt
+http://nco.sf.net/nco.html#vrt
+http://nco.sf.net/nco.html#ncremap
+
+E. ncks --chk_map now prints the minimum and maximum angular
+and horizontal resolution of the source and destination grids.
+The angular resolution is estimated as the square-root of the area
+(in sr) of the smallest/largest gridcells, and is expressed in
+degrees. The spatial resolution is estimated 
+This is the angle subtended by a spherical cap with the same area
+as the gridcell.
+
+% ncks --chk_map map_ne30pg2_to_cmip6_180x360_ncoaave.20231201.nc
+...
+area_a min, ~dx: 4.9093515660647374e-04 sr, ~141.14 km, ~1.27 degrees in grid A cell [14462,-45.7267,+177.69]
+area_a max, ~dx: 6.8523331840188574e-04 sr, ~166.75 km, ~1.50 degrees in grid A cell [1858,+0.749936,+359.25]
+...
+area_b min, ~dx: 2.6580860638549116e-06 sr, ~10.39 km, ~0.09 degrees in grid B cell [60,-89.5,+59.5]
+area_b max, ~dx: 3.0460968486221404e-04 sr, ~111.18 km, ~1.50 degrees in grid B cell [32272,-0.5,+231.5]
+...
+
+This feature can be useful in assessing the uniformity of grids, and
+http://nco.sf.net/nco.html#chk_map
+http://nco.sf.net/nco.html#ncks
+
+F. ncrename now WARNs users attempting to rename coordinates in
+netCDF4 files. The WARNING, which prints only when debugging level
+> 0, the input file is in netCDF4 format, and the user tries to
+rename a variable or dimension, is self-explanatory:
+
+zender at spectral:~$ ncrename -D 1 -O -v lat,latitude in.nc out.nc
+ncrename: WARNING Renaming variables, dimensions, and attributes in any netCDF3-format file (i.e., classic, 64-bit, and CDF5) ALWAYS works. Moreover, renaming groups and attributes in any netCDF4-format file always works. However, these re-assuring notes precede a discomfitting message: A longstanding problem in the netCDF library (it is not an NCO issue per se) sometimes crashes ncrename or, even worse, silently corrupts data in the output file when input file is netCDF4-format. These outcomes are only known to occur when attempting to rename variables to/from the same names as dimensions (i.e., coordinate variables), and or dimensions to/from the same names as variables. A long thread describing the status of this issue since 2017 is at https://github.com/Unidata/netcdf-c/issues/597. A chronology of the issue dating back to 2007 is at https://nco.sourceforge.net/nco.html#bug_nc4_rename.
+ncrename HINT: Do not expect this issue to be fixed in the near future :)
+ncrename HINT: There is a straightforward two- or three-step workaround that ALWAYS works: 1. Translate the file to any netCDF3 format (e.g., with "ncks -5 in.nc out.nc"). 2. Perform the renaming. 3. (Optional, only necessary if you wish to recover the netCDF4 features like compression) Translate back to a netCDF4-format (e.g., with "ncks -7 in.nc out.nc").
+ncrename: In total renamed 0 attributes, 0 dimensions, 0 groups, and 1 variable
+zender at spectral:~$ ncrename -O -v lat,latitude in.nc out.nc
+zender at spectral:~$ ncrename -D 1 -O -a lat at units,meaning in.nc out.nc
+ncrename: In total renamed 1 attribute, 0 dimensions, 0 groups, and 0 variables
+zender at spectral:~$ ncrename -D 1 -O -v lat,latitude in3.nc out.nc
+zender at spectral:~$ 
+
+The second and third and fourth examples show no WARNING output
+because the debugging level is the default (0) in the second, and
+because the user is not renaming a variable or dimension in the
+third, and because the input file is netCDF3-format in the fourth.
+The decision was made to turn-on this WARNING only in a non-default
+debug level to avoid annoying users with existing workflows that
+expect no text output from ncrename. This compromise is intended
+to prevent widespread panic and mass hysteria. Thanks to Toby Searle
+(UKMO) for prompting this change.
+
+BUG FIXES:
+   
+A. Previous versions of NCO could omit storing the attributes
+for the frc_column and frc_landunit variables created by the S1D
+feature. This is fixed. There is no workaround. The solution is
+to upgrade
+http://nco.sf.net/nco.html#s1d
 
 Full release statement at http://nco.sf.net/ANNOUNCE
     
@@ -84,7 +141,7 @@ KNOWN PROBLEMS DUE TO NCO:
 This section of ANNOUNCE reports and reminds users of the
 existence and severity of known, not yet fixed, problems. 
 These problems occur with NCO 5.2.7 built/tested under
-MacOS 15.3 with netCDF 4.9.4-development on HDF5 1.14.3
+MacOS 15.3.1 with netCDF 4.9.4-development on HDF5 1.14.3
 and with Linux FC40 with netCDF 4.9.2 on HDF5 1.14.3.
 
 A. NOT YET FIXED (NCO problem)


=====================================
doc/ChangeLog
=====================================
@@ -1,3 +1,77 @@
+2025-03-28  Charlie Zender  <zender at uci.edu>
+
+	* NCO 5.3.3 release procedure:
+	cd ~/nco;git commit -a -m 'Version 5.3.3: Sea Shanty';git push
+	git tag -a 5.3.3 -m 'all: qnt ngt zro NaN; ncks: --fpe, ngl rsn	chk map, s1d frc_column frc_landunit attribute fix; ncclimo: rgn_stt uses --lst_hrz; ncremap: fix prs->hyb w/fat tpl; ncrename: WARN crd/dmn netCDF4';git push --tags
+
+	* Acceptance tests pass again on Perlmutter after switching from private to Conda-Forge UDUnits
+
+	* Document ncra -Y --prg_nm --pseudonym
+
+2025-03-27  Charlie Zender  <zender at uci.edu>
+
+	* Add nCells, Time to allowed horizontal dimensions in ncks --lst_hrz
+
+	* ncks --lst_hrz seems to work in ncclimo
+
+	* Add stubs for ncks --lst_hrz, nco_xtr_hrz_lst() customized for ncap2 splitter
+
+2025-03-21  Charlie Zender  <zender at uci.edu>
+
+	* Simplify Perlmutter build to be nearly identical to Chrysalis, Andes
+
+	* Document --fpe, add to man and usage pages
+
+	* NCO 5.3.3-alpha03 release procedure:
+	cd ~/nco;git commit -a -m 'Version 5.3.3-alpha03: Equalizer';git push
+	git tag -a 5.3.3-alpha03 -m 'all: perlmutter bld; ncks: ngl rsn chk map, s1d frc_column frc_landunit attribute fix';git push --tags
+
+2025-03-19  Charlie Zender  <zender at uci.edu>
+
+	* Fix Perlmutter environment to avoid /usr/bin/install and use Conda coreutils install to install in ${DATA}/[bin,lib]
+
+2025-02-27  Charlie Zender  <zender at uci.edu>
+
+	* Tidy nco_ply_lst.c
+
+2025-02-21  Charlie Zender  <zender at uci.edu>
+
+	* nco_s1d.c: Move location where frc_column, frc_landunit attributes written
+
+	* nco_map.c: Add min/max angular resolution to --chk_map
+
+2025-02-16  Charlie Zender  <zender at uci.edu>
+
+	* NCO 5.3.3-alpha02 release procedure:
+	cd ~/nco;git commit -a -m 'Version 5.3.3-alpha02: Toyota Matrix';git push
+	git tag -a 5.3.3-alpha02 -m 'all: qnt ngt zro NaN; ncks: --fpe; ncremap: fix prs->hyb w/fat tpl';git push --tags
+
+	* Migrate to netcdf-c 4.10.0-development
+
+	* nco_rgr.c: Fix write of PS to output from fat templates when input is pure-pressure output is hybrid
+
+2025-02-15  Charlie Zender  <zender at uci.edu>
+
+	* Verify --fpe test passes when using either internal NCO or patched libnetcdf.a quantize algorithms
+
+	* Distinguish val_flt and val_dbl de-reference where appropriate (except DigitRound and Granular BitRound, for now)
+
+	* nco_exit_lbr_rcd() implement new rcd convention for netCDF versions 4.10.0 and beyond
+
+2025-02-14  Charlie Zender  <zender at uci.edu>
+
+	* nco_ppc.c: nco_ppc_bitmask() protect all quantization algorithms from modifying negative zero and NaN
+
+	* ncks: Add --fpe to test floating point exceptions
+
+2025-02-08  Charlie Zender  <zender at uci.edu>
+
+	* NCO 5.3.3-alpha01 release procedure:
+	cd ~/nco;git commit -a -m 'Version 5.3.3-alpha01: Arcane';git push
+	git tag -a 5.3.3-alpha01 -m 'Functionally identical to 5.3.2; ncrename WARN on netCDF4';git push --tags
+
+	* ncrename: WARN when renaming variables or dimensions in netCDF4 files
+
 2025-02-05  Charlie Zender  <zender at uci.edu>
 
 	* NCO 5.3.2 release procedure:


=====================================
doc/VERSION
=====================================
@@ -1 +1 @@
-5.3.2
+5.3.3


=====================================
doc/debian.txt
=====================================
@@ -29,18 +29,18 @@ apt-get install dh-make debhelper devscripts fakeroot gnupg debian-policy develo
 
 2. Debian build procedure recommends placing entire package source in
    subdirectory of main package. 
-   For starters, we wish to create .debs of tagged releases, e.g., nco-5.3.2
-   First we create a clean source distribution of nco and place it in nco-5.3.2
+   For starters, we wish to create .debs of tagged releases, e.g., nco-5.3.3
+   First we create a clean source distribution of nco and place it in nco-5.3.3
    Until we know what is necessary, however, we just copy a snapshot
    
    2.1 Clean all build files from development directory
 
 cd ~/nco;make distclean;cd bld;make clean;cd ~
 tar cvzf ./nco/nco.tar.gz ./nco/*
-cd ~/nco;tar xvzf nco.tar.gz;mv nco nco-5.3.2
-/bin/rm nco.tar.gz;tar cvzf nco-5.3.2.tar.gz ./nco-5.3.2/*
-cd ~/nco/nco-5.3.2
-dh_make -e zender at uci.edu -f ../nco-5.3.2.tar.gz
+cd ~/nco;tar xvzf nco.tar.gz;mv nco nco-5.3.3
+/bin/rm nco.tar.gz;tar cvzf nco-5.3.3.tar.gz ./nco-5.3.3/*
+cd ~/nco/nco-5.3.3
+dh_make -e zender at uci.edu -f ../nco-5.3.3.tar.gz
 
     2.2 The preceding steps created template debian files for a .deb,
     Those files now reside in ~/nco/debian.
@@ -55,7 +55,7 @@ dh_make -e zender at uci.edu -f ../nco-5.3.2.tar.gz
    from previous build
 
    cd ~/nco;/bin/rm *.gz
-   cd ~/nco/nco-5.3.2
+   cd ~/nco/nco-5.3.3
    dpkg-buildpackage -rfakeroot > foo 2>&1
    dpkg-buildpackage -rsudo > foo 2>&1
 
@@ -84,33 +84,33 @@ patch -p0 < nco_X.Y.Z-3.diff   # Patch destination with Debian diff
    make tags
 # Put cute version-specific string in nco_ctl.c:nco_nmn_get()
 # Install correct version numbers before updating Debian
-# tags-query replace 5.3.2 with X.Y.Z+1
+# tags-query replace 5.3.3 with X.Y.Z+1
 # If tags-query replace does not work, be sure to manually change
 # versions in configure.ac, debian/files, doc/ANNOUNCE, doc/debian.txt,
 # doc/index.shtml, doc/nco.texi, bld/nco_dst.pl, doc/VERSION
 # 20141201: Change NCO_VERSION_PATCH in src/nco.h!!!!!!!!!!!!!!!!!!!!!!
-   cd ~/nco/debian;dch -b --force-distribution --distribution=unstable -v 5.3.2-1 # Update changelog (-b forces this version number)
+   cd ~/nco/debian;dch -b --force-distribution --distribution=unstable -v 5.3.3-1 # Update changelog (-b forces this version number)
    emacs ~/nco/bld/nco.spec # Update changelog
 # For unknown reason rules file may lose its executable bit
    chmod a+x ~/nco/debian/rules
 # Rebuild autotools so new version # propagates
    cd ~/nco;aclocal;autoheader;automake --foreign;autoconf
 # Save all files in emacs before tagging
-   ${HOME}/nco/bld/nco_dst.pl --dbg=2 --bld --cln nco-5.3.2
+   ${HOME}/nco/bld/nco_dst.pl --dbg=2 --bld --cln nco-5.3.3
 # Upload tarball to SF https://sourceforge.net/projects/nco/files 
-   cd;scp dust.ess.uci.edu:/var/www/html/nco/src/nco-5.3.2.tar.gz .
+   cd;scp dust.ess.uci.edu:/var/www/html/nco/src/nco-5.3.3.tar.gz .
 
 7. Ubuntu PPA
 https://help.launchpad.net/Packaging/PPA
-dput NCO nco_5.3.2-2~ppa1_source.changes
+dput NCO nco_5.3.3-2~ppa1_source.changes
 sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com
 
 # Location of build diagnostics for mentors to help 
-http://dust.ess.uci.edu/nco/src/nco_5.3.2-1.dpkg-buildpackage.txt
-http://dust.ess.uci.edu/nco/src/nco_5.3.2-1.dsc
-http://dust.ess.uci.edu/nco/src/nco_5.3.2-1_i386.changes
-http://dust.ess.uci.edu/nco/src/nco_5.3.2-1_i386.deb
-http://dust.ess.uci.edu/nco/src/nco_5.3.2.orig.tar.gz
+http://dust.ess.uci.edu/nco/src/nco_5.3.3-1.dpkg-buildpackage.txt
+http://dust.ess.uci.edu/nco/src/nco_5.3.3-1.dsc
+http://dust.ess.uci.edu/nco/src/nco_5.3.3-1_i386.changes
+http://dust.ess.uci.edu/nco/src/nco_5.3.3-1_i386.deb
+http://dust.ess.uci.edu/nco/src/nco_5.3.3.orig.tar.gz
 
 # Becoming a Debian developer
 http://www.debian.org/devel/join/newmaint
@@ -164,31 +164,31 @@ Matej Vela <vela at debian.org>, Daniel Baumann <daniel at debian.org>, Warren Turkal
 # export LD_LIBRARY_PATH=/usr/lib:/lib:/usr/X11R6/lib
 # sudo aptitude install antlr bison flex gsl-bin libgsl0-dev libantlr-dev netcdf-bin libnetcdfc7 libnetcdf-dev texinfo libcurl4-gnutls-dev libexpat1-dev libxml2-dev udunits-bin libudunits2-0 libudunits2-dev
 cd ~/nco;cvc
-sudo /bin/rm -rf ${DATA}/nco-5.3.2 ${DATA}/nco_5.3.2* ${DATA}/debian # Cleanup last build. sudo necessary for removal because dpkg-buildpackage uses sudo?
-# cd ${DATA};cvs -d zender at nco.cvs.sf.net:/cvsroot/nco export -kkv -r nco-5.3.2-1 -d nco-5.3.2 nco # Export based on tag
-cd ${DATA};cvs -d zender at nco.cvs.sf.net:/cvsroot/nco export -kkv -D "1 second ago" -d nco-5.3.2 nco # Export most recent
-tar cvzf ./nco_5.3.2.orig.tar.gz --exclude='nco-5.3.2/debian*' --exclude='.cvsignore' --exclude='ncap_lex.c' --exclude='ncap_yacc.[ch]' ./nco-5.3.2 
-/bin/rm -rf ${DATA}/nco-5.3.2 # Remove cvs-exported directory
-tar xvzf ./nco_5.3.2.orig.tar.gz # Untar to get directory without excluded files
-mkdir -p ${DATA}/nco-5.3.2/debian/source;cd ~/nco/debian;/bin/cp changelog compat control convert copyright doc-base files info rules ${DATA}/nco-5.3.2/debian;cd ~/nco/debian/source;/bin/cp format ${DATA}/nco-5.3.2/debian/source # Replace debian directory with _CURRENT_ (main trunk) settings
+sudo /bin/rm -rf ${DATA}/nco-5.3.3 ${DATA}/nco_5.3.3* ${DATA}/debian # Cleanup last build. sudo necessary for removal because dpkg-buildpackage uses sudo?
+# cd ${DATA};cvs -d zender at nco.cvs.sf.net:/cvsroot/nco export -kkv -r nco-5.3.3-1 -d nco-5.3.3 nco # Export based on tag
+cd ${DATA};cvs -d zender at nco.cvs.sf.net:/cvsroot/nco export -kkv -D "1 second ago" -d nco-5.3.3 nco # Export most recent
+tar cvzf ./nco_5.3.3.orig.tar.gz --exclude='nco-5.3.3/debian*' --exclude='.cvsignore' --exclude='ncap_lex.c' --exclude='ncap_yacc.[ch]' ./nco-5.3.3 
+/bin/rm -rf ${DATA}/nco-5.3.3 # Remove cvs-exported directory
+tar xvzf ./nco_5.3.3.orig.tar.gz # Untar to get directory without excluded files
+mkdir -p ${DATA}/nco-5.3.3/debian/source;cd ~/nco/debian;/bin/cp changelog compat control convert copyright doc-base files info rules ${DATA}/nco-5.3.3/debian;cd ~/nco/debian/source;/bin/cp format ${DATA}/nco-5.3.3/debian/source # Replace debian directory with _CURRENT_ (main trunk) settings
 #export DEB_BUILD_OPTIONS='disable-dap-netcdf disable-netcdf4 disable-udunits2'; # Disable optional packages based on available Debian support
-#cd ${DATA}/nco-5.3.2;dpkg-buildpackage -rsudo -uc -us > ~/foo.nco 2>&1 # -uc -us: Do not sign changes or source files
-#cd ${DATA}/nco-5.3.2;dpkg-buildpackage -rsudo -sa > ~/foo.nco 2>&1 # -sa: Include _orig.tar.gz in .changes 
-cd ${DATA}/nco-5.3.2;dpkg-buildpackage -rsudo > ~/foo.nco 2>&1
+#cd ${DATA}/nco-5.3.3;dpkg-buildpackage -rsudo -uc -us > ~/foo.nco 2>&1 # -uc -us: Do not sign changes or source files
+#cd ${DATA}/nco-5.3.3;dpkg-buildpackage -rsudo -sa > ~/foo.nco 2>&1 # -sa: Include _orig.tar.gz in .changes 
+cd ${DATA}/nco-5.3.3;dpkg-buildpackage -rsudo > ~/foo.nco 2>&1
 sudo dpkg --remove nco
-sudo dpkg --install ${DATA}/nco_5.3.2-1_*.deb
+sudo dpkg --install ${DATA}/nco_5.3.3-1_*.deb
 cd ~/nco/bld;MY_BIN_DIR=/usr/bin ../bm/nco_bm.pl --regress
 # http://lintian.debian.org/full/zender@uci.edu.html
-lintian ${DATA}/nco_5.3.2-1_*.deb
-ls -l ${DATA}/nco_5.3.2*
+lintian ${DATA}/nco_5.3.3-1_*.deb
+ls -l ${DATA}/nco_5.3.3*
 m ~/foo.nco
 # Upload Ubuntu (rather than Debian) packages to websites
-scp ${DATA}/nco_5.3.2* dust.ess.uci.edu:/var/www/html/nco/src
-scp ${DATA}/nco_5.3.2* zender,nco at web.sf.net:/home/project-web/nco/htdocs/src
+scp ${DATA}/nco_5.3.3* dust.ess.uci.edu:/var/www/html/nco/src
+scp ${DATA}/nco_5.3.3* zender,nco at web.sf.net:/home/project-web/nco/htdocs/src
 # NB: Make sure RPMs build before uploading to debian, since changing
 # Debian versions is a PITA
 # NB: Only upload pbuilder Debian Sid (not personal Ubuntu) .deb builds to Debian mentors
-# cd ${DATA};dupload -t mentors nco_5.3.2-1_*.changes
+# cd ${DATA};dupload -t mentors nco_5.3.3-1_*.changes
 bsrc # Reset shell environment for regular development
 
 # New build system #2
@@ -202,52 +202,52 @@ DIST=sid sudo pbuilder update # Update chroot before building package in it
 # dget http://ftp.debian.org/debian/pool/main/n/nco/nco_3.9.0-1.dsc
 # dget http://ftp.debian.org/debian/pool/main/n/netcdf/netcdf_3.6.1-1.dsc
 # apt-get source nco # Get package source
-sudo /bin/rm /var/cache/pbuilder/result/nco_5.3.2* # Cleanup prior build
+sudo /bin/rm /var/cache/pbuilder/result/nco_5.3.3* # Cleanup prior build
 # To pass DEB_BUILD_OPTIONS to pbuilder while using sudo, one must first
 # modify sudoers with visudo to prevent sudo from resetting environment
 #export DEB_BUILD_OPTIONS='disable-dap-netcdf disable-netcdf4 disable-udunits2'; # Disable optional packages based on available Debian support
-cd ${DATA};DIST=sid sudo pbuilder build nco_5.3.2-1.dsc > ~/foo.nco.pbuilder 2>&1
-cd /var/cache/pbuilder/result;debsign -k6F635D10 nco_5.3.2-1_*.changes
-lintian /var/cache/pbuilder/result/nco_5.3.2-1_*.deb
+cd ${DATA};DIST=sid sudo pbuilder build nco_5.3.3-1.dsc > ~/foo.nco.pbuilder 2>&1
+cd /var/cache/pbuilder/result;debsign -k6F635D10 nco_5.3.3-1_*.changes
+lintian /var/cache/pbuilder/result/nco_5.3.3-1_*.deb
 sudo dpkg --remove nco
-sudo dpkg --install /var/cache/pbuilder/result/nco_5.3.2-1_*.deb
+sudo dpkg --install /var/cache/pbuilder/result/nco_5.3.3-1_*.deb
 cd ~/nco/bld;MY_BIN_DIR=/usr/bin ../bm/nco_bm.pl --regress
 # NB: Upload pbuilder Debian Sid packages to Debian mentors, but not
 # to personal or NCO websites since most people use Ubuntu not Debian
 # NB: Debian versions are a PITA, ensure RPMs build before uploading to Debian
-cd /var/cache/pbuilder/result;dupload -t mentors nco_5.3.2-1_*.changes
+cd /var/cache/pbuilder/result;dupload -t mentors nco_5.3.3-1_*.changes
 
 # RPM builds as root
 export rpm_root='/usr/src/redhat'
 # export sudo_sng='' # sudo not-necessary when builing in user directories
 export sudo_sng='sudo' # sudo necessary when building in system directories
 cd ~/nco;cvc;cvu
-/bin/rm -rf ${DATA}/nco-5.3.2 ${DATA}/nco-5.3.2* # Cleanup last build
+/bin/rm -rf ${DATA}/nco-5.3.3 ${DATA}/nco-5.3.3* # Cleanup last build
 ${sudo_sng} /bin/rm -r -f \
-${rpm_root}/BUILD/nco-5.3.2 \
-${rpm_root}/RPMS/i386/nco-5.3.2-?.i386.rpm \
-${rpm_root}/RPMS/i386/nco-debuginfo-5.3.2-?.i386.rpm \
-${rpm_root}/RPMS/i386/nco-devel-5.3.2-?.i386.rpm \
-${rpm_root}/SOURCES/nco-5.3.2.tar.gz \
-${rpm_root}/SPECS/nco-5.3.2.spec \
-${rpm_root}/SRPMS/nco-5.3.2-?.src.rpm
-cd ${DATA};cvs -d zender at nco.cvs.sf.net:/cvsroot/nco export -kkv -r nco-5.3.2-1 -d nco-5.3.2 nco # Export based on tag
-${sudo_sng} ln -s ${HOME}/nco/bld/nco.spec ${rpm_root}/SPECS/nco-5.3.2.spec
-tar cvzf ./nco-5.3.2.tar.gz --exclude='nco-5.3.2/debian*' --exclude='.cvsignore' --exclude='ncap_lex.c' --exclude='ncap_yacc.[ch]' ./nco-5.3.2 
-${sudo_sng} /bin/cp ${DATA}/nco-5.3.2.tar.gz ${rpm_root}/SOURCES
+${rpm_root}/BUILD/nco-5.3.3 \
+${rpm_root}/RPMS/i386/nco-5.3.3-?.i386.rpm \
+${rpm_root}/RPMS/i386/nco-debuginfo-5.3.3-?.i386.rpm \
+${rpm_root}/RPMS/i386/nco-devel-5.3.3-?.i386.rpm \
+${rpm_root}/SOURCES/nco-5.3.3.tar.gz \
+${rpm_root}/SPECS/nco-5.3.3.spec \
+${rpm_root}/SRPMS/nco-5.3.3-?.src.rpm
+cd ${DATA};cvs -d zender at nco.cvs.sf.net:/cvsroot/nco export -kkv -r nco-5.3.3-1 -d nco-5.3.3 nco # Export based on tag
+${sudo_sng} ln -s ${HOME}/nco/bld/nco.spec ${rpm_root}/SPECS/nco-5.3.3.spec
+tar cvzf ./nco-5.3.3.tar.gz --exclude='nco-5.3.3/debian*' --exclude='.cvsignore' --exclude='ncap_lex.c' --exclude='ncap_yacc.[ch]' ./nco-5.3.3 
+${sudo_sng} /bin/cp ${DATA}/nco-5.3.3.tar.gz ${rpm_root}/SOURCES
 cd ${rpm_root}/SPECS
-${sudo_sng} rpmbuild -ba --sign nco-5.3.2.spec > ~/foo.nco 2>&1
+${sudo_sng} rpmbuild -ba --sign nco-5.3.3.spec > ~/foo.nco 2>&1
 scp \
-${rpm_root}/RPMS/i386/nco-5.3.2-?.i386.rpm \
-${rpm_root}/RPMS/i386/nco-debuginfo-5.3.2-?.i386.rpm \
-${rpm_root}/RPMS/i386/nco-devel-5.3.2-?.i386.rpm \
-${rpm_root}/SRPMS/nco-5.3.2-?.src.rpm \
+${rpm_root}/RPMS/i386/nco-5.3.3-?.i386.rpm \
+${rpm_root}/RPMS/i386/nco-debuginfo-5.3.3-?.i386.rpm \
+${rpm_root}/RPMS/i386/nco-devel-5.3.3-?.i386.rpm \
+${rpm_root}/SRPMS/nco-5.3.3-?.src.rpm \
 dust.ess.uci.edu:/var/www/html/nco/src
 scp \
-${rpm_root}/RPMS/i386/nco-5.3.2-?.i386.rpm \
-${rpm_root}/RPMS/i386/nco-debuginfo-5.3.2-?.i386.rpm \
-${rpm_root}/RPMS/i386/nco-devel-5.3.2-?.i386.rpm \
-${rpm_root}/SRPMS/nco-5.3.2-?.src.rpm \
+${rpm_root}/RPMS/i386/nco-5.3.3-?.i386.rpm \
+${rpm_root}/RPMS/i386/nco-debuginfo-5.3.3-?.i386.rpm \
+${rpm_root}/RPMS/i386/nco-devel-5.3.3-?.i386.rpm \
+${rpm_root}/SRPMS/nco-5.3.3-?.src.rpm \
 zender,nco at web.sf.net:/home/project-web/nco/htdocs/src
 
 # RPM builds as user
@@ -256,33 +256,33 @@ zender,nco at web.sf.net:/home/project-web/nco/htdocs/src
 export rpm_root="${DATA}/rpm/nco"
 #cd ~/nco;cvc;cvu # This risks committing unwanted *.[ch]pp files
 mkdir -p ${DATA}/rpm/nco/TMP ${DATA}/rpm/nco/BUILD
-/bin/rm -rf ${DATA}/nco-5.3.2 ${DATA}/nco-5.3.2* # Cleanup last build
+/bin/rm -rf ${DATA}/nco-5.3.3 ${DATA}/nco-5.3.3* # Cleanup last build
 /bin/rm -r -f \
-${rpm_root}/nco-5.3.2-?.src.rpm \
-${rpm_root}/nco-5.3.2.spec \
-${rpm_root}/nco-5.3.2.tar.gz \
-${rpm_root}/*/nco-5.3.2-?.*.rpm \
-${rpm_root}/*/nco-debuginfo-5.3.2-?.*.rpm \
-${rpm_root}/*/nco-devel-5.3.2-?.*.rpm
-# cd ${DATA};cvs -d zender at nco.cvs.sf.net:/cvsroot/nco export -kkv -r nco-5.3.2-1 -d nco-5.3.2 nco # Export based on tag
-cd ${DATA};cvs -d zender at nco.cvs.sf.net:/cvsroot/nco export -kkv -D "1 second ago" -dnco-5.3.2 nco # Export most recent and build as 5.3.2-1
-tar cvzf ./nco-5.3.2.tar.gz --exclude='nco-5.3.2/debian*' --exclude='.cvsignore' --exclude='ncap_lex.c' --exclude='ncap_yacc.[ch]' ./nco-5.3.2 
-/bin/cp ${DATA}/nco-5.3.2.tar.gz ${rpm_root}
+${rpm_root}/nco-5.3.3-?.src.rpm \
+${rpm_root}/nco-5.3.3.spec \
+${rpm_root}/nco-5.3.3.tar.gz \
+${rpm_root}/*/nco-5.3.3-?.*.rpm \
+${rpm_root}/*/nco-debuginfo-5.3.3-?.*.rpm \
+${rpm_root}/*/nco-devel-5.3.3-?.*.rpm
+# cd ${DATA};cvs -d zender at nco.cvs.sf.net:/cvsroot/nco export -kkv -r nco-5.3.3-1 -d nco-5.3.3 nco # Export based on tag
+cd ${DATA};cvs -d zender at nco.cvs.sf.net:/cvsroot/nco export -kkv -D "1 second ago" -dnco-5.3.3 nco # Export most recent and build as 5.3.3-1
+tar cvzf ./nco-5.3.3.tar.gz --exclude='nco-5.3.3/debian*' --exclude='.cvsignore' --exclude='ncap_lex.c' --exclude='ncap_yacc.[ch]' ./nco-5.3.3 
+/bin/cp ${DATA}/nco-5.3.3.tar.gz ${rpm_root}
 ln -s ${HOME}/nco/bld/nco.spec ${rpm_root}/nco.spec
 cd ${rpm_root}
 rpmbuild -ba --sign nco.spec > ~/foo.nco 2>&1
-rpmlint ${rpm_root}/*/nco-5.3.2-?.*.rpm
+rpmlint ${rpm_root}/*/nco-5.3.3-?.*.rpm
 sudo yum remove nco
-sudo yum install ${rpm_root}/*/nco-5.3.2-?.*.rpm
+sudo yum install ${rpm_root}/*/nco-5.3.3-?.*.rpm
 scp \
-${rpm_root}/*/nco-5.3.2-?.*.rpm \
-${rpm_root}/*/nco-debuginfo-5.3.2-?.*.rpm \
-${rpm_root}/*/nco-devel-5.3.2-?.*.rpm \
-${rpm_root}/nco-5.3.2-?.*.src.rpm \
+${rpm_root}/*/nco-5.3.3-?.*.rpm \
+${rpm_root}/*/nco-debuginfo-5.3.3-?.*.rpm \
+${rpm_root}/*/nco-devel-5.3.3-?.*.rpm \
+${rpm_root}/nco-5.3.3-?.*.src.rpm \
 dust.ess.uci.edu:/var/www/html/nco/src
 scp \
-${rpm_root}/*/nco-5.3.2-?.*.rpm \
-${rpm_root}/*/nco-debuginfo-5.3.2-?.*.rpm \
-${rpm_root}/*/nco-devel-5.3.2-?.*.rpm \
-${rpm_root}/nco-5.3.2-?.*.src.rpm \
+${rpm_root}/*/nco-5.3.3-?.*.rpm \
+${rpm_root}/*/nco-debuginfo-5.3.3-?.*.rpm \
+${rpm_root}/*/nco-devel-5.3.3-?.*.rpm \
+${rpm_root}/nco-5.3.3-?.*.src.rpm \
 zender,nco at web.sf.net:/home/project-web/nco/htdocs/src


=====================================
doc/index.shtml
=====================================
@@ -71,7 +71,7 @@ Try to disable Spammers' machines:
 <p><h1 align="center">Bienvenue sur le netCDF Operator (NCO) site</h1>
 
 <p><h2>
-Current stable NCO version is 5.3.2 released <!--#flastmod file="src/nco-5.3.2.tar.gz"-->
+Current stable NCO version is 5.3.3 released <!--#flastmod file="src/nco-5.3.3.tar.gz"-->
 </h2>
 
 <table border=0 width=100%>
@@ -155,8 +155,9 @@ and
 <h2>Recent Releases & Milestones</h2>
 
 <ul>
-<li>2025 Mar ??: 5.3.3 <i>In Progress...</i>
-<li>2025 Feb ??: 5.3.2 ECMWF/IFS/CAMS support
+<li>2025 May ??: 5.3.4 <i>In Progress...</i>
+<li>2025 Mar 28: 5.3.3 Minor features + fixes
+<li>2025 Feb 05: 5.3.2 ECMWF/IFS/CAMS support
 <li>2025 Jan 12: 5.3.1 ncclimo/ncremap features
 <li>2024 Dec 23: 5.3.0 S1D more features
 <li>2024 Oct 18: 5.2.9 S1D features
@@ -663,21 +664,30 @@ Identical copies of those tarballs are also stored
 <a href="http://nco.sf.net/src">here</a> on SourceForge for historical
 continuity.
 You may retrieve the source of tagged versions directly with, e.g.,
-<tt>git clone -b 5.3.2 http://github.com/nco/nco.git nco-5.3.2</tt></a>.
+<tt>git clone -b 5.3.3 http://github.com/nco/nco.git nco-5.3.3</tt></a>.
 <ul>
-<li><b>NCO 5.3.4</b>: (<i>Future</i>)
+<li><b>NCO 5.3.5</b>: (<i>Future</i>)
 netCDF4 user-defined types support;
 <tt>ncks --xtn</tt> better extensive variable treatment?;
 <tt>ncks --bsa</tt> Byte-swap algoritm;
 <tt>ncremap</tt> CF Convention for longitude vertices in map-files;
-<tt>ncremap</tt> small-circle weights;</li>
-<li><b>NCO 5.3.3</b>: (<i>In Progress, features in-progress or complete include</i>)
 <tt>ncremap</tt> Gracefully autoconvert N-D NC_STRING->(N+1)-D NC_CHAR variables</li>
-<li><b>NCO 5.3.2</b>: (<i>Current Stable Release</i>)
+<tt>ncremap</tt> small-circle weights;</li>
+<li><b>NCO 5.3.4</b>: (<i>In Progress, features in-progress or complete include</i>)
+<tt>ncremap --vrt</tt> works with 3D pressure fields (e.g., MERRA2)</li>
+<li><b>NCO 5.3.3</b>: (<i>Current Stable Release</i>)
+<tt>all</tt> Quantization fix so -0.0, NaN do not trigger SIGFPE;
+<tt>ncks --fpe</tt> activates IEEE Floating Point Exception WARNINGs;
+<tt>ncks --chk_map</tt> prints grids' angular resolutions;
+<tt>ncks --s1d</tt> saves frc_column frc_landunit correctly;
+<tt>ncremap --vrt</tt> interpolates prs->hyb with fat templates;
+<tt>ncclimo --rgn_stt</tt> selects only 2D spatial variables;
+<tt>ncrename</tt> WARNs on coordinate renaming in netCDF4 files;</li>
+<li><b>NCO 5.3.2</b>: 
 <tt>all</tt> Quantization fix for non-root group variables;
 <tt>ncclimo/ncremap</tt> <tt>srun</tt> default;
 <tt>ncclimo/ncremap</tt> prohibit overwriting input Inode;
-<tt>ncremap</tt> improved ECMWF/IFS/CAMS support;
+<tt>ncremap</tt> improved ECMWF/IFS/CAMS support;</li>
 <li><b>NCO 5.3.1</b>: 
 <tt>ncclimo/ncremap</tt> <tt>--npo</tt>, build revamp;
 <tt>ncremap</tt> Gracefully autoconvert 0-D NC_STRING->1-D NC_CHAR variables;
@@ -865,7 +875,7 @@ Or, alternatively, permanently add conda-forge (which teems with goodies besides
 ‘<tt>conda config --add channels conda-forge</tt>’, then
 install NCO with ‘<tt>conda install nco</tt>’.
 The default NCO installed by <tt>conda</tt> is generally within a month of the latest release. 
-<li><a href="https://github.com/conda-forge/nco-feedstock">nco-5.3.2</a> Executables Anaconda-compatible. Maintained by Filipe Fernandes.</li>
+<li><a href="https://github.com/conda-forge/nco-feedstock">nco-5.3.3</a> Executables Anaconda-compatible. Maintained by Filipe Fernandes.</li>
 Thanks to Rich Signell, Filipe Fernandes, Pedro Vicente, Xylar Asay-Davis and others for developing and maintaining the NCO package for conda.
 </ul>
 
@@ -874,7 +884,7 @@ Thanks to Rich Signell, Filipe Fernandes, Pedro Vicente, Xylar Asay-Davis and ot
 <h3><a href="http://www.debian.org">Debian</a> and <a href="http://www.ubuntu.com">Ubuntu</a> GNU/Linux</a></h3>
 <ul>
 <!--
-<li><a href="http://www.debian.org">Debian</a> and <a href="http://www.ubuntu.com">Ubuntu</a> GNU/Linux-compatible Intel systems, prebuilt binary executable <a href="http://www.debian.org">deb</a>: <a href="http://packages.debian.org/testing/math/nco.html">nco-5.3.2</a></li>
+<li><a href="http://www.debian.org">Debian</a> and <a href="http://www.ubuntu.com">Ubuntu</a> GNU/Linux-compatible Intel systems, prebuilt binary executable <a href="http://www.debian.org">deb</a>: <a href="http://packages.debian.org/testing/math/nco.html">nco-5.3.3</a></li>
 -->
 <a href="http://packages.debian.org/unstable/science/nco">Debian NCO</a> and 
 <a href="https://launchpad.net/ubuntu/+source/nco">Ubuntu NCO</a> homepages.
@@ -882,8 +892,8 @@ Thanks to Rich Signell, Filipe Fernandes, Pedro Vicente, Xylar Asay-Davis and ot
 NCO packages in the Debian/Ubuntu repositories (e.g., Sid and Raring) generally lag the packages distributed here by 6–12 months.
 <a name="beta"></a><a name="prerelease"> <!-- http://nco.sf.net#beta -->
 Newer (beta- or pre-release) packages are often available for intrepid Debian/Ubuntu users as described <a href="https://github.com/nco/nco/tree/master/doc/beta.txt">here</a>.
-<dt>Debian package for most recent NCO release (install with, e.g., ‘<tt>dpkg --install nco_5.3.2-1_i386.deb</tt>’):</dt>
-<li><a href="https://launchpad.net/ubuntu/+source/nco/5.3.2-1">nco_5.3.2-1_amd64.deb</a> : Executables AMD64-compatible</li>
+<dt>Debian package for most recent NCO release (install with, e.g., ‘<tt>dpkg --install nco_5.3.3-1_i386.deb</tt>’):</dt>
+<li><a href="https://launchpad.net/ubuntu/+source/nco/5.3.3-1">nco_5.3.3-1_amd64.deb</a> : Executables AMD64-compatible</li>
 Thanks to Daniel Baumann, Sebastian Couwenberg, Barry deFreese, Francesco Lovergine, 
 Brian Mays, Rorik Peterson, and Matej Vela for their help packaging
 NCO for Debian over the years. 
@@ -927,10 +937,10 @@ Thanks to Gavin Burris and Kyle Wilcox for documenting build procedures for RHEL
 <!-- 
 # MacOS 15.3 (Sequoia) systems (firn, sastrugi, spectral):
 /usr/bin/scp ~/nco/doc/index.shtml zender,nco at web.sf.net:/home/project-web/nco/htdocs
-cd ~/bin;tar cvzf ${DATA}/nco-5.3.2.macos.15.3.tar.gz nc*;scp ${DATA}/nco-5.3.2.macos.15.3.tar.gz zender,nco at web.sf.net:/home/project-web/nco/htdocs/src
+cd ~/bin;tar cvzf ${DATA}/nco-5.3.3.macos.15.3.tar.gz nc*;scp ${DATA}/nco-5.3.3.macos.15.3.tar.gz zender,nco at web.sf.net:/home/project-web/nco/htdocs/src
 -->
 The most up-to-date executables are probably those in the tarball below. Those unfamiliar with installing executables from tarballs may try the (older) <a href="http://en.wikipedia.org/wiki/Apple_Disk_Image">DMG</a> files (you may need to add <tt>/opt/local/bin</tt> to your executable path to access those operators).
-<li><a href="src/nco-5.3.2.macos.15.3.tar.gz">nco-5.3.2.macos.15.3.tar.gz</a> (<!--#fsize file="src/nco-5.3.2.macos.15.3.tar.gz"-->): Executables MacOS 15.3-compatible (last updated <!--#flastmod file="src/nco-5.3.2.macos.15.3.tar.gz"-->). Maintained by NCO Project.</li>
+<li><a href="src/nco-5.3.3.macos.15.3.tar.gz">nco-5.3.3.macos.15.3.tar.gz</a> (<!--#fsize file="src/nco-5.3.3.macos.15.3.tar.gz"-->): Executables MacOS 15.3-compatible (last updated <!--#flastmod file="src/nco-5.3.3.macos.15.3.tar.gz"-->). Maintained by NCO Project.</li>
 <li><a href="http://fink.sf.net">Fink</a> packages for <a href="http://fink.sf.net/pdb/package.php/nco">NCO</a>: Currently NCO 4.9.5. Maintained by Alexander Hansen.</li> 
 <li><a href="http://brew.sh">Homebrew</a> packages for <a href="https://formulae.brew.sh/formula/nco">NCO</a>: Currently NCO 5.1.5. Install with ‘<tt>brew install nco</tt>’. Maintained by Carlo Cabrera, Ian Lancaster, Alejandro Soto, and others over the years.</li> 
 <li><a href="http://trac.macosforge.org/projects/macports/wiki">MacPorts</a> infrastructure for <a href="https://ports.macports.org/port/nco">NCO</a>: <a href="https://ports.macports.org/port/nco">Portfile</a>: Currently NCO 5.1.1. Install with ‘<tt>sudo port install nco</tt>’. Maintained by Takeshi Enomoto.</li>
@@ -1133,12 +1143,12 @@ On the <a href="https://sourceforge.net/p/nco/bugs">Bug Tickets</a> site.</li>
 The simplest way to acquire the source is to download the compressed tarball:
 <ul>
 <li>
-<!-- scp ${DATA}/nco-5.3.2.tar.gz zender,nco at web.sf.net:/home/project-web/nco/htdocs/src -->
-<a href="https://github.com/nco/nco/archive/5.3.2.tar.gz">nco-5.3.2.tar.gz</a> 
-(<!--#fsize file="src/nco-5.3.2.tar.gz"--> compressed tar-file)<br>
-<!--#exec cmd="openssl dgst -md5 src/nco-5.3.2.tar.gz"--><br>
-<!--#exec cmd="openssl dgst -sha1 src/nco-5.3.2.tar.gz"--><br>
-<!--#exec cmd="openssl dgst -sha256 src/nco-5.3.2.tar.gz"--> 
+<!-- scp ${DATA}/nco-5.3.3.tar.gz zender,nco at web.sf.net:/home/project-web/nco/htdocs/src -->
+<a href="https://github.com/nco/nco/archive/5.3.3.tar.gz">nco-5.3.3.tar.gz</a> 
+(<!--#fsize file="src/nco-5.3.3.tar.gz"--> compressed tar-file)<br>
+<!--#exec cmd="openssl dgst -md5 src/nco-5.3.3.tar.gz"--><br>
+<!--#exec cmd="openssl dgst -sha1 src/nco-5.3.3.tar.gz"--><br>
+<!--#exec cmd="openssl dgst -sha256 src/nco-5.3.3.tar.gz"--> 
 </li>
 </ul>
 
@@ -1159,8 +1169,8 @@ To avoid the churn that comes with using the latest snapshot,
 potential contributors may wish to retrieve a recent tagged (i.e.,
 stable and released) version, 
 This command retrieves the entire NCO repository (< 20 MB) and
-then checks out NCO version <tt>5.3.2</tt>:
-<p><tt>git clone https://github.com/nco/nco.git;cd nco;git checkout 5.3.2</tt></p>
+then checks out NCO version <tt>5.3.3</tt>:
+<p><tt>git clone https://github.com/nco/nco.git;cd nco;git checkout 5.3.3</tt></p>
 However, the most efficient way to actively track and develop NCO is to
 retrieve the current (“bleeding edge”) NCO snapshot.
 This command retrieves the latest NCO master branch into a local
@@ -1170,12 +1180,12 @@ directory named <tt>nco</tt>:
 Track changes to the development version using
 <p><tt>cd nco;git pull</tt></p>
 One difference between running a "tagged" release 
-(e.g., <tt>5.3.2</tt>) and the development version is that the
+(e.g., <tt>5.3.3</tt>) and the development version is that the
 tagged release operators will print a valid version number (e.g.,
-<tt>5.3.2</tt>) when asked to do so with the <tt>-r</tt> flag
+<tt>5.3.3</tt>) when asked to do so with the <tt>-r</tt> flag
 (e.g., <tt>ncks -r</tt>).
 Snapshots will include the sub-version and patch-level in the version
-information (e.g., <tt>5.3.2-alpha06</tt>). 
+information (e.g., <tt>5.3.3-alpha06</tt>). 
 
 <!--
 <a name="doxy"></a>
@@ -1358,9 +1368,9 @@ As of 20131101 there is no Cygwin package for ANTLR, and the Cygwin netCDF packa
 
 <li>Once you have installed the pre-requisites as shown above, you may then build the latest stable NCO and install it in, e.g., <tt>/usr/local</tt> with: 
 <tt>
-<dt>wget https://github.com/nco/nco/archive/5.3.2.tar.gz</dt>
-<dt>tar xvzf 5.3.2.tar.gz</dt>
-<dt>cd nco-5.3.2</dt>
+<dt>wget https://github.com/nco/nco/archive/5.3.3.tar.gz</dt>
+<dt>tar xvzf 5.3.3.tar.gz</dt>
+<dt>cd nco-5.3.3</dt>
 <dt>./configure --prefix=/usr/local</dt>
 <dt>make</dt>
 <dt>sudo make install</dt>


=====================================
doc/nco.texi
=====================================
@@ -128,12 +128,12 @@ Octave TeXInfo manual shows clean TeXInfo structure
 @setfilename nco.info
 
 @c Define edition, date, ...
- at set nco-edition 5.3.2
- at set doc-edition 5.3.2
+ at set nco-edition 5.3.3
+ at set doc-edition 5.3.3
 @set copyright-years 1995--2025
 @set update-year 2025
- at set update-date 5 February 2025
- at set update-month February 2025
+ at set update-date 28 March 2025
+ at set update-month March 2025
 
 @settitle @acronym{NCO} @value{nco-edition} User Guide
 
@@ -16290,7 +16290,7 @@ print(idx);
 print(idx);
 
 // Add 200 (long method)
-*@vpx=*@vpx+200; //idx now 250
+*@vpx=*@vpx+200; // idx now 250
 print(idx);
 
 @vpy="idy";
@@ -16320,7 +16320,7 @@ expression.
 Thus in the below script using @code{*all(idx)} would be a fundamental
 mistake.
 In the below example the vpointer @code{var_nm} is of type
- at code{NC_STRING}. 
+ at code{NC_STRING}.  
 @example
 @verbatim
 @all=get_vars_in();
@@ -22668,7 +22668,7 @@ ncks [-3] [-4] [-5] [-6] [-7] [-A] [-a] [--area_wgt] [-b @var{fl_bnr}]
 [--cmp @var{cmp_sng}] [--cnk_byt @var{sz_byt}] [--cnk_csh @var{sz_byt}] [--cnk_dmn @var{nm}, at var{sz_lmn}]
 [--cnk_map @var{map}] [--cnk_min @var{sz_byt}] [--cnk_plc @var{plc}] [--cnk_scl @var{sz_lmn}]
 [-D @var{dbg}] [-d @var{dim},[@var{min}][,[@var{max}][,[@var{stride}]]]
-[-F] [--fix_rec_dmn @var{dim}] [--fl_fmt @var{fl_fmt}] [--fmt_val @var{format}]
+[-F] [--fix_rec_dmn @var{dim}] [--fl_fmt @var{fl_fmt}] [--fmt_val @var{format}] [--fpe]
 [-G @var{gpe_dsc}] [-g @var{grp}[, at dots{}]] [--glb ...] [--grp_xtr_var_xcl]
 [-H] [-h] [--hdn] [--hdr_pad @var{nbr}] [--hpss] [--hrz @var{fl_hrz}] [--jsn] [--jsn_fmt @var{lvl}] 
 [-L @var{dfl_lvl}] [-l @var{path}]
@@ -23532,6 +23532,44 @@ This is useful (and nearly mandatory) when flattening netCDF4 files that
 have multiple record dimensions per group into netCDF3 files (which are
 limited to at most one record dimension) (@pxref{Group Path Editing}). 
 
+ at html
+<a name="fpe"></a> <!-- http://nco.sf.net/nco.html#fpe -->
+<a name="floating_point_exceptions"></a> <!-- http://nco.sf.net/nco.html#floating_point_exceptions -->
+ at end html
+ at cindex @code{--fpe}
+ at cindex @code{--floating_point_exceptions}
+ at cindex @acronym{IEEE}
+ at cindex @acronym{FPE}
+ at cindex @code{FE_DIVBYZERO}
+ at cindex @code{FE_INEXACT}
+ at cindex @code{FE_INVALID}
+ at cindex @code{FE_OVERFLOW}
+ at cindex @code{FE_UNDERFLOW}
+ at item --fpe
+As of @acronym{NCO} version 5.3.3 (March, 2025), @command{ncks}
+accepts the flag @samp{--fpe} (or long-option equivalent
+ at samp{--floating_point_exception}) to report the status of all
+ at acronym{IEEE} @acronym{FPE} status after command execution. 
+This can be useful to verify whether @acronym{NCO} produced any
+arithmetically questionable results:
+ at example
+ at verbatim
+% ncks --fpe -O -7 -L 1 -C -v ppc_zro_ngt_nan_flt --qnt_alg=gbr \
+       --qnt default=3 --cmp='shf|zst' in.nc out.nc
+ncks: Successfully set FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW exception flags
+ncks: FE_DIVBYZERO is not raised
+ncks: FE_INEXACT is raised
+ncks: FE_INVALID is not raised
+ncks: FE_OVERFLOW is not raised
+ncks: FE_UNDERFLOW is not raised
+ at end verbatim
+ at end example
+Note that @code{FE_INEXACT} can be ignored since it is triggered by
+common numbers like @code{1.0/3.0} and @code{sqrt(2.0)}.
+The other conditions may warrant further investigation.
+Note that the regridder @emph{is} @command{ncks}, and can be passed
+this flag with @samp{ncreamp --nco_opt='--fpe'}.
+
 @html
 <a name="hdn"></a> <!-- http://nco.sf.net/nco.html#hdn -->
 <a name="hidden"></a> <!-- http://nco.sf.net/nco.html#hidden -->
@@ -24365,8 +24403,8 @@ lut_out Output will be value of column(s) in this andunit
 This feature is necessarily restricted to restart datasets, e.g.,
 @example
 @verbatim
-ncks --s1d --lut_out=1 --hrz=hst.nc rst.nc s1d.nc # Output Soil LUT
-ncks --s1d --lut_out=13 --hrz=hst.nc rst.nc s1d.nc # Avg Soil+Glacier
+ncks --s1d --rgr lut_out=1 --hrz=hst.nc rst.nc s1d.nc # Output Soil LUT
+ncks --s1d --rgr lut_out=13 --hrz=hst.nc rst.nc s1d.nc # Avg Soil+Glacier
 @end verbatim
 @end example
 
@@ -25557,6 +25595,9 @@ The first command re-orders every variable in the input file.
 The second command extracts and re-orders only the variable
 @code{three_dmn_var}. 
 
+ at html
+<a name="xmp_rvr"></a> <!-- http://nco.sf.net/nco.html#xmp_rvr -->
+ at end html
 @cindex reverse dimensions
 Suppose the dimension @code{lat} represents latitude and monotonically 
 increases increases from south to north. 
@@ -25719,7 +25760,8 @@ ncra [-3] [-4] [-5] [-6] [-7] [-A] [-C] [-c]
 [--no_cll_msr] [--no_cll_mth] [--no_frm_trm] [--no_tmp_fl] 
 [-O] [-o @var{output-file}] [-p @var{path}] [--qnt ...] [--qnt_alg @var{alg_nm}]
 [--prm_int] [--prw wgt_arr] [-R] [-r] [--ram_all] [--rec_apn] [--rth_dbl|flt]
-[-t @var{thr_nbr}] [--unn] [-v @var{var}[, at dots{}]] [-w wgt] [-X ...] [-x] [-y @var{op_typ}]
+[-t @var{thr_nbr}] [--unn] [-v @var{var}[, at dots{}]] [-w wgt] [-X ...] [-x]
+[-Y @var{prg_nm}] [-y @var{op_typ}]
 [@var{input-files}] [@var{output-file}]
 @end example
 
@@ -25876,6 +25918,37 @@ in the space-conserving @code{NC_BYTE} (single-byte) format.
 ncra --prm_ints in*.nc out.nc
 @end example
 
+ at html
+<a name="pseudonym"></a> <!-- http://nco.sf.net/nco.html#pseudonym -->
+<a name="prg_nm"></a> <!-- http://nco.sf.net/nco.html#prg_nm -->
+ at end html
+ at cindex @code{--pseudonym}
+ at cindex @code{--prg_nm}
+ at cindex @code{-Y}
+ at cindex pseudonym
+One odd feature of @command{ncra} is that its source code is also the
+source code for @command{ncrcat} and @command{nces}.
+In the @acronym{NCO} @acronym{UNIX} installation, @command{ncrcat} and
+ at command{nces} are symbolic links to the @command{ncra} executable.
+The binary executable determines how to behave based on the name with
+which it was invoked.
+(This is not good programming style, do not try this at home).
+The @samp{-Y @var{prg_nm}} option (and long-option equivalents
+ at samp{--prg_nm=@var{prg_nm}} or @samp{--pseudonym=@var{prg_nm}})
+can also be used to tell the @command{ncra} binary to behave like
+program specified by @var{prg_nm}.
+Valid values of @var{prg_nm} are @code{nces}, @code{ncra}, and
+ at code{ncrcat}. 
+These three examples produce identical result via three different
+invocations:
+ at example
+ at verbatim
+nces in*.nc out.nc
+ncra -Y nces in*.nc out.nc
+ncra --prg_nm=nces in*.nc out.nc
+ at end verbatim
+ at end example
+
 @ignore
 @c Old, and possibly future, documentation
 @html
@@ -30247,7 +30320,7 @@ whose attributes are to be renamed.
 <a name="bug_nc4_rename"></a> <!-- http://nco.sf.net/nco.html#bug_nc4_rename -->
 @end html
 @cartouche
-Caveat lector: Unforunately from 2007--present (January, 2025) the
+Caveat lector: Unforunately from 2007--present (February, 2025) the
 netCDF library (versions 4.0.0--4.9.3) contains bugs or limitations
 that sometimes prevent @acronym{NCO} from correctly renaming coordinate
 variables, dimensions, and groups in netCDF4 files. 
@@ -30560,6 +30633,40 @@ ncrename -O -d grid_xt,lon -d grid_yt,lat -v grid_xt,lon -v grid_yt,lat \
 @end example
 The fix is to upgrade to netCDF version 4.6.1.
 
+The preceding list of failures with renaming netCDF4 coordinates
+became too tedious to maintain in 2017.
+Moreover, most users are unlikely to read this manual and to learn of
+the pitfalls and worksarounds in renaming netCDF4 coordinates.
+Thus, as of @acronym{NCO} @w{version 4.3.3}, released in February, 2025, 
+ at command{ncrename} warns users attempting to rename coordinates in
+netCDF4 files. The warning, which prints only when the debugging level
+is non-default (i.e., is greater than 0), the input file is in netCDF4
+format, and the user tries to rename a variable or dimension, is
+self-explanatory: 
+ at example
+ at verbatim
+zender at spectral:~$ ncrename -D 1 -O -v lat,latitude in.nc out.nc
+ncrename: WARNING Renaming variables, dimensions, and attributes in any netCDF3-format file (i.e., classic, 64-bit, and CDF5) ALWAYS works. Moreover, renaming groups and attributes in any netCDF4-format file always works. However, these re-assuring notes precede a discomfitting message: A longstanding problem in the netCDF library (it is not an NCO issue per se) sometimes crashes ncrename or, even worse, silently corrupts data in the output file when input file is netCDF4-format. These outcomes are only known to occur when attempting to rename variables to/from the same names as dimensions (i.e., coordinate variables), and or dimensions to/from the same names as variables. If you are doing that, and the command completes, we suggest that you manually inspect the output coordinate values for corruption. A long thread describing the status of this issue since 2017 is at https://github.com/Unidata/netcdf-c/issues/597. A tedious chronology of the issue dating back to 2007 is at https://nco.sourceforge.net/nco.html#bug_nc4_rename.
+ncrename: HINT Do not expect this issue to be fixed in the near future :)
+ncrename: HINT There is a straightforward two- or three-step workaround that ALWAYS works: 1. Translate the file to any netCDF3 format (e.g., with "ncks -5 in.nc out.nc"). 2. Perform the renaming. 3. (Optional, only necessary if you wish to recover the netCDF4 features like compression) Translate back to a netCDF4-format (e.g., with "ncks -7 in.nc out.nc").
+ncrename: In total renamed 0 attributes, 0 dimensions, 0 groups, and 1 variable
+zender at spectral:~$ ncrename -O -v lat,latitude in.nc out.nc
+zender at spectral:~$ ncrename -D 1 -O -a lat at units,meaning in.nc out.nc
+ncrename: In total renamed 1 attribute, 0 dimensions, 0 groups, and 0 variables
+zender at spectral:~$ ncrename -D 1 -O -v lat,latitude in3.nc out.nc
+zender at spectral:~$ 
+ at end verbatim
+ at end example
+The second and third and fourth examples show no WARNING output
+because the debugging level is the default (0) in the second, and
+because the user is not renaming a variable or dimension in the
+third, and because the input file is netCDF3-format in the fourth.
+The decision was made to turn-on this WARNING only in a non-default
+debug level to avoid annoying users with existing workflows that
+expect no text output from @command{ncrename}.
+This compromise is intended to prevent widespread panic and mass
+hysteria. 
+
 @cindex global attributes
 @cindex group attributes
 @cindex attributes, global
@@ -31337,9 +31444,10 @@ Excellent bug reports and feature requests.
 @cindex Craig MacLachlan
 @cindex Hugo Oliveira
 @cindex Rich Signell
+ at cindex Jeff Whitaker
 @cindex Kyle Wilcox
 @cindex Klaus Zimmermann
- at item Filipe Fernandes, Isuru Fernando, Craig MacLachlan, Hugo Oliveira, Rich Signell, Kyle Wilcox, Klaus Zimmermann
+ at item Filipe Fernandes, Isuru Fernando, Craig MacLachlan, Hugo Oliveira, Rich Signell, Jeff Whitaker, Kyle Wilcox, Klaus Zimmermann
 Anaconda packaging
 @cindex Xylar Asay-Davis
 @cindex Daniel Baumann


=====================================
man/ncks.1
=====================================
@@ -53,6 +53,7 @@ dbg_lvl]
 .IR dim ]
 [\-\-fmt_val
 .IR fmt ]
+[\-\-fpe]
 [\-G
 .IR gpe_dsc ]
 [\-g  


=====================================
man/ncra.1
=====================================
@@ -94,6 +94,8 @@ ncra [\-3] [\-4] [\-5] [\-6] [\-7]
 [\-X 
 .IR box ] 
 [\-x]
+[\-Y 
+.IR prg_nm ]
 [\-y 
 .IR op_typ ]
 .I input-files


=====================================
src/nco/ncks.c
=====================================
@@ -70,6 +70,7 @@
 
 /* Standard C headers */
 #include <assert.h> /* assert() */
+#include <fenv.h> /* fesetexceptflag() */
 #include <stdio.h> /* stderr, FILE, NULL, etc. */
 #include <stdlib.h> /* abs, getopt, malloc, strtol */
 #include <string.h> /* strcmp() */
@@ -271,6 +272,7 @@ main(int argc,char **argv)
   nco_bool HAVE_LIMITS=False; /* [flg] Are there user limits? (-d) */
   nco_bool HISTORY_APPEND=True; /* Option h */
   nco_bool HPSS_TRY=False; /* [flg] Search HPSS for unfound files */
+  nco_bool LST_HRZ=False; /* [flg] Print extraction list of horizontal (lat,lon,ncol,time) variables */
   nco_bool LST_RNK_GE2=False; /* [flg] Print extraction list of rank >= 2 variables */
   nco_bool LST_XTR=False; /* [flg] Print extraction list */
   nco_bool MSA_USR_RDR=False; /* [flg] Multi-Slab Algorithm returns hyperslabs in user-specified order */
@@ -305,6 +307,7 @@ main(int argc,char **argv)
   nco_bool WRT_TMP_FL=True; /* [flg] Write output to temporary file */
   nco_bool flg_area_wgt=False; /* [flg] Area-weight map-file statistics */
   nco_bool flg_dmm_in=False; /* [flg] Make dummy input file */
+  nco_bool flg_fpe=False; /* [flg] Activate/report floating-point-exceptions */
   nco_bool flg_frac_b_nrm=False; /* [flg] Normalize map-file weights when frac_b >> 1 */
   nco_bool flg_mmr_cln=True; /* [flg] Clean memory prior to exit */
   nco_bool flg_rgr=False; /* [flg] Regrid */
@@ -375,6 +378,8 @@ main(int argc,char **argv)
     {"cpy",no_argument,0,0},
     {"dmm_in_mk",no_argument,0,0}, /* [flg] Make dummy input file */
     {"fl_dmm",no_argument,0,0}, /* [flg] Make dummy input file */
+    {"fpe",no_argument,0,0}, /* [flg] Activate floating-point-exceptions */
+    {"floating_point_exceptions",no_argument,0,0}, /* [flg] Activate floating-point-exceptions */
     {"license",no_argument,0,0},
     {"hdf4",no_argument,0,0}, /* [flg] Treat file as HDF4 */
     {"hdn",no_argument,0,0}, /* [flg] Print hidden attributes */
@@ -385,6 +390,7 @@ main(int argc,char **argv)
     {"id",no_argument,0,0}, /* [flg] Print normally hidden information, like file, group, and variable IDs */
     {"lbr",no_argument,0,0},
     {"library",no_argument,0,0},
+    {"lst_hrz",no_argument,0,0}, /* [flg] Print extraction list of horizontal (lat,lon,ncol,time) variables */
     {"lst_rnk_ge2",no_argument,0,0}, /* [flg] Print extraction list of rank >= 2 variables */
     {"lst_xtr",no_argument,0,0}, /* [flg] Print extraction list */
     {"frac_b_nrm",no_argument,0,0}, /* [flg] Normalize map-file weights when frac_b >> 1 */
@@ -758,6 +764,18 @@ main(int argc,char **argv)
         rec_dmn_nm=strcat(rec_dmn_nm,optarg);
         rec_dmn_nm_fix=strdup(optarg);
       } /* !fix_rec_dmn */
+      if(!strcmp(opt_crr,"fpe") || !strcmp(opt_crr,"floating_point_exceptions")){
+	flg_fpe=True;
+	/* https://www.tutorialspoint.com/c_standard_library/c_function_fesetexceptflag.htm */
+	fexcept_t flg_xcp;
+	// Clear all exceptions
+	feclearexcept(FE_ALL_EXCEPT);
+	if(fesetexceptflag(&flg_xcp,FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW) != 0){
+	  (void)fprintf(stdout,"%s: Failed to set FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW exception flags\n",nco_prg_nm_get());
+	}else{
+	  (void)fprintf(stdout,"%s: Successfully set FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW exception flags\n",nco_prg_nm_get());
+	} /* !fesetexceptflag() */
+      } /* !fpe */
       if(!strcmp(opt_crr,"cmp") || !strcmp(opt_crr,"cmp_sng") || !strcmp(opt_crr,"ccr") || !strcmp(opt_crr,"cdc") || !strcmp(opt_crr,"codec") || !strcmp(opt_crr,"compress")) cmp_sng=(char *)strdup(optarg);
       if(!strcmp(opt_crr,"fl_fmt") || !strcmp(opt_crr,"file_format")) rcd=nco_create_mode_prs(optarg,&fl_out_fmt);
       if(!strcmp(opt_crr,"fl_prn") || !strcmp(opt_crr,"file_print") || !strcmp(opt_crr,"prn_fl") || !strcmp(opt_crr,"print_file")) fl_prn=(char *)strdup(optarg);
@@ -792,7 +810,8 @@ main(int argc,char **argv)
 	if(*sng_cnv_rcd) nco_sng_cnv_err(optarg,"strtol",sng_cnv_rcd);
 	nc_set_log_level(log_lvl);
       } /* !log_lvl */
-      if(!strcmp(opt_crr,"lst_rnk_ge2") || !strcmp(opt_crr,"rank_ge2"))	LST_RNK_GE2=True; /* [flg] Print extraction list of rank >= 2 variables */
+      if(!strcmp(opt_crr,"lst_hrz")) LST_HRZ=True; /* [flg] Print extraction list of horizontal (lat,lon,ncol,time) */
+      if(!strcmp(opt_crr,"lst_rnk_ge2")) LST_RNK_GE2=True; /* [flg] Print extraction list of rank >= 2 variables */
       if(!strcmp(opt_crr,"lst_xtr") || !strcmp(opt_crr,"xtr_lst")) LST_XTR=True; /* [flg] Print extraction list */
       if(!strcmp(opt_crr,"mk_rec_dmn") || !strcmp(opt_crr,"mk_rec_dim")){
 	if(strchr(optarg,',')){
@@ -874,7 +893,7 @@ main(int argc,char **argv)
 	rgr_var=(char *)strdup(optarg);
       } /* !rgr_var */
       if(!strcmp(opt_crr,"secret") || !strcmp(opt_crr,"scr") || !strcmp(opt_crr,"shh")){
-        (void)fprintf(stdout,"Hidden/unsupported NCO options:\nBit-Adjustment Alg.\t--baa, --bit_alg\nBuild-engine\t\t--bld, --build_engine\nByte-swap algorithm\t--bsa, --byte_swap\nCompiler used\t\t--cpl, --compiler\nCopyright\t\t--cpy, --copyright, --license\nHidden functions\t--scr, --shh, --secret\nLibrary used\t\t--lbr, --library\nLog level\t\t--log_lvl, --log_level\nList rank >= 2 vars\t--lst_rnk_ge2\nList extracted vars\t--lst_xtr\nMemory clean\t\t--mmr_cln, --cln, --clean\nMemory dirty\t\t--mmr_drt, --drt, --dirty\nMPI implementation\t--mpi_implementation\nNo-clobber files\t--no_clb, --no-clobber\nPseudonym\t\t--pseudonym, -Y (ncra only)\nSpinlock\t\t--spinlock\nStreams\t\t\t--srm\nSysconf\t\t\t--sysconf\nTest UDUnits\t\t--tst_udunits,'units_in','units_out','cln_sng'? \nVersion\t\t\t--vrs, --version\n\n");
+        (void)fprintf(stdout,"Hidden/unsupported NCO options:\nBit-Adjustment Alg.\t--baa, --bit_alg\nBuild-engine\t\t--bld, --build_engine\nByte-swap algorithm\t--bsa, --byte_swap\nCompiler used\t\t--cpl, --compiler\nCopyright\t\t--cpy, --copyright, --license\nHidden functions\t--scr, --shh, --secret\nLibrary used\t\t--lbr, --library\nLog level\t\t--log_lvl, --log_level\nList horizontal vars\t--lst_hrz\nList rank >= 2 vars\t--lst_rnk_ge2\nList extracted vars\t--lst_xtr\nMemory clean\t\t--mmr_cln, --cln, --clean\nMemory dirty\t\t--mmr_drt, --drt, --dirty\nMPI implementation\t--mpi_implementation\nNo-clobber files\t--no_clb, --no-clobber\nPseudonym\t\t--pseudonym, -Y (ncra only)\nSpinlock\t\t--spinlock\nStreams\t\t\t--srm\nSysconf\t\t\t--sysconf\nTest UDUnits\t\t--tst_udunits,'units_in','units_out','cln_sng'? \nVersion\t\t\t--vrs, --version\n\n");
         nco_exit(EXIT_SUCCESS);
       } /* endif "shh" */
       if(!strcmp(opt_crr,"srm")) PRN_SRM=True; /* [flg] Print ncStream */
@@ -1193,6 +1212,9 @@ main(int argc,char **argv)
   /* [fnc] Print extraction list of N>=D variables and exit */
   if(LST_RNK_GE2) nco_xtr_ND_lst(trv_tbl);
 
+  /* [fnc] Print extraction list of horizontal (lat,lon,ncol,time) variables and exit */
+  if(LST_HRZ) nco_xtr_hrz_lst(trv_tbl);
+
   /* Were all user-specified dimensions found? */ 
   (void)nco_chk_dmn(lmt_nbr,flg_dne);    
 
@@ -1664,6 +1686,16 @@ close_and_free:
   MPI_Finalize();
 #endif /* !ENABLE_MPI */
   
+  if(flg_fpe){
+    int exceptions;
+    exceptions=fetestexcept(FE_ALL_EXCEPT);
+    (void)fprintf(stdout,"%s: FE_DIVBYZERO %s raised\n",nco_prg_nm_get(),(exceptions & FE_DIVBYZERO) ? "is" : "is not");
+    (void)fprintf(stdout,"%s: FE_INEXACT %s raised\n",nco_prg_nm_get(),(exceptions & FE_INEXACT) ? "is" : "is not");
+    (void)fprintf(stdout,"%s: FE_INVALID %s raised\n",nco_prg_nm_get(),(exceptions & FE_INVALID) ? "is" : "is not");
+    (void)fprintf(stdout,"%s: FE_OVERFLOW %s raised\n",nco_prg_nm_get(),(exceptions & FE_OVERFLOW) ? "is" : "is not");
+    (void)fprintf(stdout,"%s: FE_UNDERFLOW %s raised\n",nco_prg_nm_get(),(exceptions & FE_UNDERFLOW) ? "is" : "is not");
+  } /* !flg_fpe */
+
   /* End timer */ 
   ddra_info.tmr_flg=nco_tmr_end; /* [enm] Timer flag */
   rcd+=nco_ddra((char *)NULL,(char *)NULL,&ddra_info);


=====================================
src/nco/nco.h
=====================================
@@ -380,7 +380,7 @@ extern "C" {
 # define NCO_VERSION_MINOR 3
 #endif /* !NCO_VERSION_MINOR */
 #ifndef NCO_VERSION_PATCH
-# define NCO_VERSION_PATCH 1
+# define NCO_VERSION_PATCH 3
 #endif /* !NCO_VERSION_PATCH */
 #ifndef NCO_VERSION_NOTE
 # define NCO_VERSION_NOTE "" /* Blank for final versions, non-blank (e.g., "-beta73") for pre-release versions */
@@ -390,7 +390,7 @@ extern "C" {
 # define NCO_LIB_VERSION ( NCO_VERSION_MAJOR * 100 + NCO_VERSION_MINOR * 10 + NCO_VERSION_PATCH )
 #endif /* !NCO_LIB_VERSION */
 #ifndef NCO_VERSION
-# define NCO_VERSION "5.3.2"
+# define NCO_VERSION "5.3.3"
 #endif /* !NCO_VERSION */
 
 /* Compatibility tokens new to netCDF4 netcdf.h: */


=====================================
src/nco/nco_ctl.c
=====================================
@@ -582,9 +582,13 @@ void
 nco_exit_lbr_rcd(void) /* [fnc] Exit with netCDF library version as return code */
 {
   /* Purpose: Exit with status equaling a numeric code determined by netCDF library version
-     Exit status must be 0-255
-     Modern netCDF versions range from 300-493
-     Hence program returns netCDF version minus an offset of 300 so version 4.4.0 exit()s with $?=140
+     UNIX exit status must be 0-255
+     Modern netCDF versions ranged from 300-493 from 1997--2025
+     Hence program returns netCDF version minus an offset of 300 so, e.g., version 4.4.0 exit()s with $?=140 and 4.9.4 exit()s with $?=194 
+     20250215: netCDF development version 4.10.0 released 20250207 changes that!
+     What convention to adopt for versions 4.10.0 and beyond?
+     Ugly yet workable convention is to pretend verion 4.10.0 is version 5.0.0 so rcd=500 and $?=200 ...
+     This buys us another decade or so
      Usage: ncks --lbr_rcd
      Verify exit status with "echo $?" */
   char lbr_sng[NC_MAX_NAME+1];
@@ -594,8 +598,13 @@ nco_exit_lbr_rcd(void) /* [fnc] Exit with netCDF library version as return code
   strcpy(lbr_sng,nc_inq_libvers());
   rcd=400;
   /* Detect buggy netCDF version 4.1 so that workarounds may be implemented
-     Other versions used to enable version-specific regression tests in NCO_rgr.pm */
-  if(lbr_sng[0] == '4' && lbr_sng[1] == '.' && lbr_sng[2] == '1'){rcd=410;}
+     Other versions used to enable version-specific regression tests in NCO_rgr.pm
+     20250215: Modify identification of version 4.1 to disambiguate identification of version 4.10 (below) */
+  if(lbr_sng[0] == '4' && lbr_sng[1] == '.' && lbr_sng[2] == '1'){
+    if(lbr_sng[3] == '.'){rcd=410;}
+    else if(lbr_sng[3] == '0' && lbr_sng[4] == '.' && lbr_sng[5] == '0' ){rcd=500;}
+    else if(lbr_sng[3] == '0' && lbr_sng[4] == '.' && lbr_sng[5] == '1' ){rcd=501;}
+  }
   else if(lbr_sng[0] == '4' && lbr_sng[1] == '.' && lbr_sng[2] == '3' && lbr_sng[3] == '.' && lbr_sng[4] == '0'){rcd=430;}
   else if(lbr_sng[0] == '4' && lbr_sng[1] == '.' && lbr_sng[2] == '3' && lbr_sng[3] == '.' && lbr_sng[4] == '1'){rcd=431;}
   else if(lbr_sng[0] == '4' && lbr_sng[1] == '.' && lbr_sng[2] == '3' && lbr_sng[3] == '.' && lbr_sng[4] == '2'){rcd=432;}
@@ -627,8 +636,8 @@ nco_exit_lbr_rcd(void) /* [fnc] Exit with netCDF library version as return code
   else if(lbr_sng[0] == '4' && lbr_sng[1] == '.' && lbr_sng[2] == '9' && lbr_sng[3] == '.' && lbr_sng[4] == '1'){rcd=491;}
   else if(lbr_sng[0] == '4' && lbr_sng[1] == '.' && lbr_sng[2] == '9' && lbr_sng[3] == '.' && lbr_sng[4] == '2'){rcd=492;}
   else if(lbr_sng[0] == '4' && lbr_sng[1] == '.' && lbr_sng[2] == '9' && lbr_sng[3] == '.' && lbr_sng[4] == '3'){rcd=493;}
+  /* NB: 4.9.4 was never released, though some development branches employ this version number */
   else if(lbr_sng[0] == '4' && lbr_sng[1] == '.' && lbr_sng[2] == '9' && lbr_sng[3] == '.' && lbr_sng[4] == '4'){rcd=494;}
-  else if(lbr_sng[0] == '4' && lbr_sng[1] == '.' && lbr_sng[2] == '9' && lbr_sng[3] == '.' && lbr_sng[4] == '5'){rcd=495;}
 #endif /* HAVE_NETCDF4_H */
   /* Use exit() not nco_exit(), because behavior of latter depends on NCO_ABORT_ON_ERROR
      When True, NCO_ABORT_ON_ERROR causes NCO to abort() not exit(rcd)
@@ -970,13 +979,13 @@ nco_usg_prn(void)
     opt_sng=(char *)strdup("[-3] [-4] [-5] [-6] [-7] [-A] [--bfr byt] [-C] [-c] [--cmp sng] [--cnk_byt byt] [--cnk_csh byt] [--cnk_dmn nm,lmn] [--cnk_map map] [--cnk_min byt] [--cnk_plc plc] [--cnk_scl sz] [-D dbg_lvl] [-d ...] [-F] [--fix_rec_crd] [--fl_fmt fmt] [--glb ...] [-H] [-h] [--hdf] [--hdr_pad nbr] [--hpss] [-i var,val] [-L lvl] [-l path] [--msa] [--no_cll_msr] [--no_frm_trm] [--no_tmp_fl] [-O] [-o out.nc] [-p path] [--qnt ...] [--qnt_alg alg_nm] [-R] [-r] [--ram_all] [-t thr_nbr] [--uio] [-v ...] [-X box] [-x] [-w wgt_1[,wgt_2]] in1.nc in2.nc [out.nc]\n");
     break;
   case ncks:
-    opt_sng=(char *)strdup("[-3] [-4] [-5] [-6] [-7] [-A] [-a] [--area_wgt] [-b fl_bnr] [--bfr byt] [-C] [-c] [--cal] [--cdl] [--chk_bnd] [--chk_chr] [--chk_map] [--chk_mss] [--chk_nan] [--chk_xtn] [--cmp sng] [--cnk_byt byt] [--cnk_csh byt] [--cnk_dmn nm,lmn] [--cnk_map map] [--cnk_min byt] [--cnk_plc plc] [--cnk_scl sz] [-D dbg_lvl] [-d ...] [--dt_fmt fmt] [-F] [--fix_rec_dmn dim] [--fl_fmt fmt] [--fmt_val fmt] [-G grp:lvl] [-g ...] [--glb ...] [--grp_xtr_var_xcl] [-H] [-h] [--hdn] [--hdr_pad nbr] [--hpss] [--hrz hrz.nc] [--jsn] [--jsn_fmt lvl] [-L lvl] [-l path] [-M] [-m] [--map map.nc] [--md5_dgs] [--md5_wrt] [--mk_rec_dmn dim] [--msa] [--no_blank] [--no_cll_msr] [--no_frm_trm] [--no_tmp_fl] [-O] [-o out.nc] [-P] [-p path] [-Q] [-q] [--qnt ...] [--qnt_alg alg_nm] [-R] [-r] [--rad] [--rgr] [--ram_all] [--rnr=wgt] [-s format] [--sparse] [-t thr_nbr] [-u] [--uio] [--unn] [-V] [-v ...] [--vrt_in vrt.nc] [--vrt_out vrt.nc] [-X box] [-x] [--xml] [--xml_no_loc] [--xml_spr_chr sng] [--xml_spr_nmr sng] [--xtn_var ...] in.nc [[out.nc]]\n");
+    opt_sng=(char *)strdup("[-3] [-4] [-5] [-6] [-7] [-A] [-a] [--area_wgt] [-b fl_bnr] [--bfr byt] [-C] [-c] [--cal] [--cdl] [--chk_bnd] [--chk_chr] [--chk_map] [--chk_mss] [--chk_nan] [--chk_xtn] [--cmp sng] [--cnk_byt byt] [--cnk_csh byt] [--cnk_dmn nm,lmn] [--cnk_map map] [--cnk_min byt] [--cnk_plc plc] [--cnk_scl sz] [-D dbg_lvl] [-d ...] [--dt_fmt fmt] [-F] [--fix_rec_dmn dim] [--fl_fmt fmt] [--fmt_val fmt] [--fpe] [-G grp:lvl] [-g ...] [--glb ...] [--grp_xtr_var_xcl] [-H] [-h] [--hdn] [--hdr_pad nbr] [--hpss] [--hrz hrz.nc] [--jsn] [--jsn_fmt lvl] [-L lvl] [-l path] [-M] [-m] [--map map.nc] [--md5_dgs] [--md5_wrt] [--mk_rec_dmn dim] [--msa] [--no_blank] [--no_cll_msr] [--no_frm_trm] [--no_tmp_fl] [-O] [-o out.nc] [-P] [-p path] [-Q] [-q] [--qnt ...] [--qnt_alg alg_nm] [-R] [-r] [--rad] [--rgr] [--ram_all] [--rnr=wgt] [-s format] [--sparse] [-t thr_nbr] [-u] [--uio] [--unn] [-V] [-v ...] [--vrt_in vrt.nc] [--vrt_out vrt.nc] [-X box] [-x] [--xml] [--xml_no_loc] [--xml_spr_chr sng] [--xml_spr_nmr sng] [--xtn_var ...] in.nc [[out.nc]]\n");
     break;
   case ncpdq:
     opt_sng=(char *)strdup("[-3] [-4] [-5] [-6] [-7] [-A] [-a ...] [--bfr byt] [-C] [-c] [--cmp sng] [--cnk_byt byt] [--cnk_csh byt] [--cnk_dmn nm,lmn] [--cnk_map map] [--cnk_min byt] [--cnk_plc plc] [--cnk_scl sz] [-D dbg_lvl] [-d ...] [-F] [--fl_fmt fmt] [-G grp:lvl] [-g ...] [--glb ...] [-H] [-h] [--hdf] [--hdr_pad nbr] [--hpss] [-L lvl] [-l path] [-M pck_map] [--mrd] [--msa] [--no_cll_msr] [--no_frm_trm] [--no_tmp_fl] [-O] [-o out.nc] [-P pck_plc] [-p path] [--qnt ...] [--qnt_alg alg_nm] [-R] [-r] [--ram_all] [-t thr_nbr] [--uio] [--unn] [-U] [-v ...] [-X box] [-x] in.nc [out.nc]\n");
     break;
   case ncra:
-    opt_sng=(char *)strdup("[-3] [-4] [-5] [-6] [-7] [-A] [--bfr byt] [-C] [-c] [--cb ...] [--cmp sng] [--cnk_byt byt] [--cnk_csh byt] [--cnk_dmn nm,lmn] [--cnk_map map] [--cnk_min byt] [--cnk_plc plc] [--cnk_scl sz] [-D dbg_lvl] [-d ...]  [--dbl|flt] [-F] [--fl_fmt fmt] [-G grp:lvl] [-g ...] [--glb ...] [-H] [-h] [--hdf] [--hdr_pad nbr] [--hpss] [-L lvl] [-l path] [--mro] [--msa] [-N] [-n ...] [--no_cll_msr] [--no_cll_mth] [--no_frm_trm] [--no_tmp_fl] [-O] [-o out.nc] [-p path] [--prm_ints] [--prw] [--qnt ...] [--qnt_alg alg_nm] [-R] [-r] [--ram_all] [--rec_apn] [-t thr_nbr] [--uio] [--unn] [-w wgt] [-v ...] [-X box] [-x] [-y op_typ] in1.nc in2.nc [...] [out.nc]\n");
+    opt_sng=(char *)strdup("[-3] [-4] [-5] [-6] [-7] [-A] [--bfr byt] [-C] [-c] [--cb ...] [--cmp sng] [--cnk_byt byt] [--cnk_csh byt] [--cnk_dmn nm,lmn] [--cnk_map map] [--cnk_min byt] [--cnk_plc plc] [--cnk_scl sz] [-D dbg_lvl] [-d ...]  [--dbl|flt] [-F] [--fl_fmt fmt] [-G grp:lvl] [-g ...] [--glb ...] [-H] [-h] [--hdf] [--hdr_pad nbr] [--hpss] [-L lvl] [-l path] [--mro] [--msa] [-N] [-n ...] [--no_cll_msr] [--no_cll_mth] [--no_frm_trm] [--no_tmp_fl] [-O] [-o out.nc] [-p path] [--prm_ints] [--prw] [--qnt ...] [--qnt_alg alg_nm] [-R] [-r] [--ram_all] [--rec_apn] [-t thr_nbr] [--uio] [--unn] [-w wgt] [-v ...] [-X box] [-x] [-y op_typ] [-Y prg_nm] in1.nc in2.nc [...] [out.nc]\n");
     break;
   case ncfe:
     opt_sng=(char *)strdup("[-3] [-4] [-5] [-6] [-7] [-A] [--bfr byt] [-C] [-c] [--cb ...] [--cmp sng] [--cnk_byt byt] [--cnk_csh byt] [--cnk_dmn nm,lmn] [--cnk_map map] [--cnk_min byt] [--cnk_plc plc] [--cnk_scl sz] [-D dbg_lvl] [-d ...]  [--dbl|flt] [-F] [--fl_fmt fmt] [-G grp:lvl] [-g ...] [--glb ...] [-H] [-h] [--hdf] [--hdr_pad nbr] [--hpss] [-L lvl] [-l path] [--msa] [-n ...] [--no_cll_msr] [--no_frm_trm] [--no_tmp_fl] [--nsm_fl] [--nsm_grp] [--nsm_sfx] [-O] [-o out.nc] [-p path] [--qnt ...] [--qnt_alg alg_nm] [-R] [-r] [--ram_all] [-t thr_nbr] [--uio] [--unn] [-v ...] [-w wgt] [-X box] [-x] [-y op_typ] in1.nc in2.nc [...] [out.nc]\n");
@@ -1070,6 +1079,7 @@ nco_usg_prn(void)
 #else /* !ENABLE_NETCDF4 */
   if(strstr(opt_sng,"--fl_fmt")) (void)fprintf(stdout,"    --fl_fmt, file_format fmt\tFile format for output [classic,64bit_offset,64bit_data]\n");
 #endif /* !ENABLE_NETCDF4 */
+  if(strstr(opt_sng,"--fpe")) (void)fprintf(stdout,"    --fpe\t\tReport all IEEE floating-point-exception flags after execution\n");
 #ifdef ENABLE_NETCDF4
   if(strstr(opt_sng,"--gag")) (void)fprintf(stdout,"    --gag, aggregate_group\tGroup Aggregation (not Record Aggregation)\n");
   if(strstr(opt_sng,"[-G")) (void)fprintf(stdout,"-G, --gpe [grp_nm][:[lvl]]\tGroup Path Editing path, levels to replace\n");
@@ -1192,6 +1202,7 @@ nco_usg_prn(void)
   if(strstr(opt_sng,"--xml_spr_chr")) (void)fprintf(stdout,"    --xml_spr_chr sng\tSeparator for NcML character types\n");
   if(strstr(opt_sng,"--xml_spr_nmr")) (void)fprintf(stdout,"    --xml_spr_nmr sng\tSeparator for NcML numeric types\n");
   if(strstr(opt_sng,"--xtn_var")) (void)fprintf(stdout,"    --xtn_var, extensive var\tExtensive variables for regridding (summed not averaged)\n");
+  if(strstr(opt_sng,"[-Y")) (void)fprintf(stdout,"-Y, --prg_nm, pseudonym\tBehavior to invoke: nces,ncra,ncrcat\n");
   if(strstr(opt_sng,"[-y op_typ]")){
     if(prg_lcl == ncbo)(void)fprintf(stdout,"-y, --op_typ, operation op_typ\tBinary arithmetic operation: add,sbt,mlt,dvd (+,-,*,/)\n");
     if(prg_lcl == ncra || prg_lcl == ncfe || prg_lcl == ncge || prg_lcl == ncwa)(void)fprintf(stdout,"-y, --op_typ, operation op_typ\tArithmetic operation: avg,mabs,mebs,mibs,min,max,tabs,ttl,sqravg,avgsqr,sqrt,rms,rmssdn\n");


=====================================
src/nco/nco_grp_utl.c
=====================================
@@ -1276,7 +1276,92 @@ nco_xtr_ND_lst /* [fnc] Print extraction list of N>=D variables and exit */
   } /* !xtr_nbr_crr */
     
   return;
-} /* end nco_xtr_ND_lst() */
+} /* !nco_xtr_ND_lst() */
+
+void
+nco_xtr_hrz_lst /* [fnc] Print extraction list of horizontal (lat, lon, no lev) variables and exit */
+(trv_tbl_sct * const trv_tbl) /* I [sct] GTT (Group Traversal Table) */
+{
+  /* Purpose: Print extraction list of horizontal (lat, lon, no lev) variables and exit
+     ncclimo calls ncks for an extraction list of variables when users do not specify explicit extraction list
+     When ncclimo is in timeseries mode and creating regional statistics, variables must be horizontal-only
+     Otherwise ncap2 call in ncclimo will fail
+     Used by ncks to supply arguments to splitter that will work in ncap2 regional averaging
+     Hence we restrict returned list to non-coordinate record variables
+     Based on nco_xtr_ND_lst()
+     Usage:
+     ncks --lst_hrz ~/nco/data/in.nc
+     ncks --lst_hrz ~/data/bm/elmv3_r05l15.nc
+     ncks --lst_hrz ~/data/ne30/rgr/ */
+
+  const char fnc_nm[]="nco_xtr_hrz_lst()"; /* [sng] Function name */
+
+  const int rnk_min=2; /* [nbr] Minimum rank to extract */
+  const int rnk_max=3; /* [nbr] Maximum rank to extract */
+
+  char *dmn_nm_cp; /* [sng] Dimension name as char * to reduce indirection */
+
+  int xtr_nbr_crr=0; /* [nbr] Number of N>=D variables found so far */
+
+  int dmn_idx; /* [idx] Dimension index */
+  int dmn_nbr_in; /* [nbr] Number of dimensions in input variable */
+  int grp_id; /* [id] Group ID */
+  int nc_id; /* [id] File ID */
+  int var_id; /* [id] Variable ID */
+
+  trv_sct var_trv;
+
+  nc_id=trv_tbl->in_id_arr[0];
+
+  /* 20170414: csz add new definitions is_crd_lk_var and is_rec_lk_var, avoid PVN definitions for sanity */
+  for(unsigned idx_var=0;idx_var<trv_tbl->nbr;idx_var++){
+    var_trv=trv_tbl->lst[idx_var];
+    if(var_trv.nco_typ == nco_obj_typ_var){
+      (void)nco_inq_grp_full_ncid(nc_id,var_trv.grp_nm_fll,&grp_id);
+      (void)nco_inq_varid(grp_id,var_trv.nm,&var_id);
+      trv_tbl->lst[idx_var].is_crd_lk_var=trv_tbl->lst[idx_var].is_crd_lk_var;
+      if(nco_is_spc_in_cf_att(grp_id,"bounds",var_id,NULL)) trv_tbl->lst[idx_var].is_crd_lk_var=True;
+      if(nco_is_spc_in_cf_att(grp_id,"cell_measures",var_id,NULL)) trv_tbl->lst[idx_var].is_crd_lk_var=True;
+      if(nco_is_spc_in_cf_att(grp_id,"climatology",var_id,NULL)) trv_tbl->lst[idx_var].is_crd_lk_var=True;
+      for(dmn_idx=0;dmn_idx<var_trv.nbr_dmn;dmn_idx++){
+	if(var_trv.var_dmn[dmn_idx].is_rec_dmn) trv_tbl->lst[idx_var].is_rec_lk_var=True;
+      } /* !dmn_idx */
+    } /* !nco_typ */
+  } /* !idx_var */
+
+  /* If variable has rnk_min <= N <= rnk_max dimensions, then examine for lev dimensions */
+  for(unsigned idx_var=0;idx_var<trv_tbl->nbr;idx_var++){
+    if(trv_tbl->lst[idx_var].nco_typ == nco_obj_typ_var){
+      if(
+	 (trv_tbl->lst[idx_var].nbr_dmn >= rnk_min) && /* Rank at least 2 */
+	 (trv_tbl->lst[idx_var].nbr_dmn <= rnk_max) && /* Rank at most 3 */
+	 (!trv_tbl->lst[idx_var].is_crd_lk_var) && /* Not a coordinate-like variable */
+	 (trv_tbl->lst[idx_var].is_rec_lk_var) && /* Is a record variable */
+	 (trv_tbl->lst[idx_var].var_typ != NC_CHAR) && /* Not an array of characters */
+	 True){
+	/* 20250327: Ensure dimension names are only lat, lon, ncol, or time */
+	dmn_nbr_in=trv_tbl->lst[idx_var].nbr_dmn;
+	for(dmn_idx=0;dmn_idx<dmn_nbr_in;dmn_idx++){
+	  dmn_nm_cp=trv_tbl->lst[idx_var].var_dmn[dmn_idx].dmn_nm;
+	  if(strcmp(dmn_nm_cp,"lat") && strcmp(dmn_nm_cp,"lon") && strcmp(dmn_nm_cp,"ncol") && strcmp(dmn_nm_cp,"nCells") && strcasecmp(dmn_nm_cp,"time")) break;
+	} /* !dmn_idx */	
+	if(dmn_idx == dmn_nbr_in){
+	  (void)fprintf(stdout,"%s%s",(xtr_nbr_crr > 0) ? "," : "",trv_tbl->lst[idx_var].nm);
+	  xtr_nbr_crr++;
+	} /* !dmn_idx */
+      } /* !N>=D */
+    } /* !nco_typ */
+  } /* !idx_var */
+  if(xtr_nbr_crr > 0){
+    (void)fprintf(stdout,"\n");
+    nco_exit(EXIT_SUCCESS);
+  }else{
+    (void)fprintf(stdout,"%s: ERROR %s reports no horizontal-only (lat, lon, ncol, time-only) variables found with %d <= rank <= %d\n",nco_prg_nm_get(),fnc_nm,rnk_min,rnk_max);
+    nco_exit(EXIT_FAILURE);
+  } /* !xtr_nbr_crr */
+    
+  return;
+} /* !nco_xtr_hrz_lst() */
 
 void
 nco_xtr_cf_add /* [fnc] Add to extraction list variables associated with CF convention */


=====================================
src/nco/nco_grp_utl.h
=====================================
@@ -202,6 +202,10 @@ void
 nco_xtr_ND_lst /* [fnc] Print extraction list of N>=D variables and exit */
 (trv_tbl_sct * const trv_tbl); /* I [sct] GTT (Group Traversal Table) */
 
+void
+nco_xtr_hrz_lst /* [fnc] Print extraction list of horizontal (lat, lon, no lev) variables and exit */
+(trv_tbl_sct * const trv_tbl); /* I [sct] GTT (Group Traversal Table) */
+
 void
 nco_xtr_mpas_zmid_add /* [fnc] Add MPAS timeMonthly_avg_zMid auxiliary coordinate variable to extraction list */
 (trv_tbl_sct * const trv_tbl); /* I/O [sct] Traversal table */


=====================================
src/nco/nco_map.c
=====================================
@@ -2390,7 +2390,6 @@ nco_map_chk /* Map-file evaluation */
     double s_min,s_max,s_ttl;
     size_t idx_min_area_a,idx_max_area_a;;
     size_t idx_min_area_b,idx_max_area_b;;
-    size_t idx_max;
 
     nco_map_var_min_max_ttl(var_col,(double *)NULL,flg_area_wgt,(int *)NULL,&col_min,&idx_min,&col_max,&idx_max,&col_ttl,&avg,&mebs,&rms,&sdn);
     nco_map_var_min_max_ttl(var_row,(double *)NULL,flg_area_wgt,(int *)NULL,&row_min,&idx_min,&row_max,&idx_max,&row_ttl,&avg,&mebs,&rms,&sdn);
@@ -2469,8 +2468,8 @@ nco_map_chk /* Map-file evaluation */
       fprintf(stdout,"area_a sum/4*pi: %0.16f = 1.0%s%0.1e // Perfect is 1.0 for global Grid A\n",area_a_ttl/4.0/M_PI,area_a_ttl/4.0/M_PI > 1 ? "+" : "-",fabs(1.0-area_a_ttl/4.0/M_PI));
       // 20240708: Output radius (rds) or diameter (dmt) of circle with same area as smallest/largest gridcell A_g:
       // s=r_e*theta, A=r_e^2*sr=pi*rds^2 -> rds=r_e*sqrt(sr/pi), dmt=2*r_e*sqrt(sr/pi), dx=r_e*sqrt(sr) <--dx is side of square
-      fprintf(stdout,"area_a min, ~dx: %0.16e sr, %0.2f km in grid A cell [%lu,%+g,%+g]\n",area_a_min,rds_earth*sqrt(area_a_min)/1000.0,idx_min_area_a+1UL,var_yc_a->val.dp[idx_min_area_a],var_xc_a->val.dp[idx_min_area_a]);
-      fprintf(stdout,"area_a max, ~dx: %0.16e sr, %0.2f km in grid A cell [%lu,%+g,%+g]\n",area_a_max,rds_earth*sqrt(area_a_max)/1000.0,idx_max_area_a+1UL,var_yc_a->val.dp[idx_max_area_a],var_xc_a->val.dp[idx_max_area_a]);
+      fprintf(stdout,"area_a min, ~dx: %0.16e sr, ~%0.2f km, ~%0.2f degrees in grid A cell [%lu,%+g,%+g]\n",area_a_min,rds_earth*sqrt(area_a_min)/1000.0,sqrt(area_a_min)*180.0/M_PI,idx_min_area_a+1UL,var_yc_a->val.dp[idx_min_area_a],var_xc_a->val.dp[idx_min_area_a]);
+      fprintf(stdout,"area_a max, ~dx: %0.16e sr, ~%0.2f km, ~%0.2f degrees in grid A cell [%lu,%+g,%+g]\n",area_a_max,rds_earth*sqrt(area_a_max)/1000.0,sqrt(area_a_max)*180.0/M_PI,idx_max_area_a+1UL,var_yc_a->val.dp[idx_max_area_a],var_xc_a->val.dp[idx_max_area_a]);
       if(fabs(1.0-area_a_ttl/4.0/M_PI) < 1.0e-2) grid_a_tiles_sphere=True;
     }else{
       fprintf(stdout,"area_a sum/4*pi: map-file does not provide completely non-zero area_a\n");
@@ -2489,8 +2488,8 @@ nco_map_chk /* Map-file evaluation */
     if(var_mask_b) fprintf(stdout,"mask_b S errors: %lu%s\n",mask_b_err,mask_b_err ? " <--- # of weights that, in violation of mask_b, contribute from source gridcells to masked destination gridcells WARNING WARNING WARNING" : ""); else fprintf(stdout,"mask_b S errors: map-file omits mask_b\n");
     if(has_area_b){
       fprintf(stdout,"area_b sum/4*pi: %0.16f = 1.0%s%0.1e // Perfect is 1.0 for global Grid B\n",area_b_ttl/4.0/M_PI,area_b_ttl/4.0/M_PI > 1 ? "+" : "-",fabs(1.0-area_b_ttl/4.0/M_PI));
-      fprintf(stdout,"area_b min, ~dx: %0.16e sr, %0.2f km in grid B cell [%lu,%+g,%+g]\n",area_b_min,rds_earth*sqrt(area_b_min)/1000.0,idx_min_area_b+1UL,var_yc_b->val.dp[idx_min_area_b],var_xc_b->val.dp[idx_min_area_b]);
-      fprintf(stdout,"area_b max, ~dx: %0.16e sr, %0.2f km in grid B cell [%lu,%+g,%+g]\n",area_b_max,rds_earth*sqrt(area_b_max)/1000.0,idx_max_area_b+1UL,var_yc_b->val.dp[idx_max_area_b],var_xc_b->val.dp[idx_max_area_b]);
+      fprintf(stdout,"area_b min, ~dx: %0.16e sr, ~%0.2f km, ~%0.2f degrees in grid B cell [%lu,%+g,%+g]\n",area_b_min,rds_earth*sqrt(area_b_min)/1000.0,sqrt(area_b_min)*180.0/M_PI,idx_min_area_b+1UL,var_yc_b->val.dp[idx_min_area_b],var_xc_b->val.dp[idx_min_area_b]);
+      fprintf(stdout,"area_b max, ~dx: %0.16e sr, ~%0.2f km, ~%0.2f degrees in grid B cell [%lu,%+g,%+g]\n",area_b_max,rds_earth*sqrt(area_b_max)/1000.0,sqrt(area_a_max)*180.0/M_PI,idx_max_area_b+1UL,var_yc_b->val.dp[idx_max_area_b],var_xc_b->val.dp[idx_max_area_b]);
       if(fabs(1.0-area_b_ttl/4.0/M_PI) < 1.0e-2) grid_b_tiles_sphere=True;
     }else{
       fprintf(stdout,"area_b sum/4*pi: map-file does not provide completely non-zero area_b\n");


=====================================
src/nco/nco_mta.c
=====================================
@@ -277,7 +277,7 @@ nco_input_check /* [fnc] Check whether input has valid syntax */
     return NCO_ERR;
   }
   if(strstr(arg,"=") == arg+strlen(arg)-1L){ // Equal sign is at argument end
-    (void)fprintf(stderr,"%s: ERROR %s reports no value in key-value pair for argument \"%s\".\n%s: HINT This usually occurs when the value of a key is unintentionally omitted, e.g., --gaa foo= , --ppc foo= , --rgr foo= , or --trr foo= . Each equal sign must immediatte precede a value for the specified key(s).\n",nco_prg_nm_get(),fnc_nm,arg,nco_prg_nm_get());
+    (void)fprintf(stderr,"%s: ERROR %s reports no value in key-value pair for argument \"%s\".\n%s: HINT This usually occurs when the value of a key is unintentionally omitted, e.g., --gaa foo= , --ppc foo= , --rgr foo= , or --trr foo= . Each equal sign must immediately precede a value for the specified key(s).\n",nco_prg_nm_get(),fnc_nm,arg,nco_prg_nm_get());
     return NCO_ERR;
   }
   return NCO_NOERR;


=====================================
src/nco/nco_ply_lst.c
=====================================
@@ -90,7 +90,6 @@ int *pl_nbr)
 
   nco_bool bwrp;
 
-
   double *lat_ptr=lat_crn;
   double *lon_ptr=lon_crn;
 
@@ -114,7 +113,6 @@ int *pl_nbr)
     if( msk[idx]==0 || area[idx] == 0.0)
       continue;
 
-
     pl=nco_poly_init_lst(pl_typ, grd_crn_nbr,0, idx, lon_ptr, lat_ptr);
     lon_ptr+=(size_t)grd_crn_nbr;
     lat_ptr+=(size_t)grd_crn_nbr;
@@ -123,7 +121,6 @@ int *pl_nbr)
     if(!pl)
       continue;
 
-
     /* add min max */
     nco_poly_minmax_add(pl, grd_lon_typ, False);
 
@@ -132,32 +129,24 @@ int *pl_nbr)
     /* use Charlie's formula */
     nco_poly_area_add(pl);
 
-
     //if(pl->dp_x_minmax[0] <0.0 || (pl->dp_x_minmax[1] - pl->dp_x_minmax[0]) > 30  )
     if( !(pl->dp_x_minmax[1] - pl->dp_x_minmax[0] < 180.0
              &&  lon_ctr[idx] >= pl->dp_x_minmax[0] && lon_ctr[idx] <= pl->dp_x_minmax[1] ))
-
     {
       (void)fprintf(stdout, "/***%s: %s: invalid polygon to follow *******?", nco_prg_nm_get(), fnc_nm);
       nco_poly_prn(pl, 0);
       pl=nco_poly_free(pl);
       continue;
-
     }
 
     //fprintf(stdout,"/***** input polygon pl lon center=%f   convex=%s\n    ********************/\n", lon_ctr[idx],   (nco_poly_is_convex(pl) ? "True": "False") );
     //nco_poly_prn(pl, 0);
 
-
-
     /* check for wrapping -center outside min/max range */
     bwrp=(  lon_ctr[idx] < pl->dp_x_minmax[0] || lon_ctr[idx] > pl->dp_x_minmax[1] );
 
     if( grd_lon_typ == nco_grd_lon_nil || grd_lon_typ == nco_grd_lon_unk )
     {
-
-
-
       if( !bwrp  )
       {
         pl_lst[idx_cnt++]=pl;
@@ -168,12 +157,10 @@ int *pl_nbr)
         (void)fprintf(stdout, "/*******************************************/\n");
 
         pl=nco_poly_free(pl);
-
       }
       continue;
     }
 
-
     /* if we are here then grd_lon_typ specifys a grid type  */
     if( !bwrp)
     {
@@ -182,16 +169,13 @@ int *pl_nbr)
       /* cell width exceeds max so assume wrapping */
     else if(  nco_poly_wrp_splt(pl, grd_lon_typ, &pl_wrp_left, &pl_wrp_right ) == NCO_NOERR )
     {
-
       fprintf(stdout,"/***** pl, wrp_left, wrp_right ********************/\n");
 
-
       if(pl_wrp_left)
       {
         nco_poly_re_org(pl_wrp_left, lcl_dp_x, lcl_dp_y);
         pl_lst[idx_cnt++]=pl_wrp_left;
         nco_poly_prn(pl_wrp_left, 2);
-
       }
 
       if(pl_wrp_right)
@@ -199,14 +183,10 @@ int *pl_nbr)
         nco_poly_re_org(pl_wrp_right, lcl_dp_x, lcl_dp_y);
         pl_lst[idx_cnt++]=pl_wrp_right;
         nco_poly_prn(pl_wrp_right, 2);
-
       }
 
       pl=nco_poly_free(pl);
-
-
       fprintf(stdout,"/**********************************/\n");
-
       cnt_wrp_good++;
     }
     else
@@ -215,11 +195,8 @@ int *pl_nbr)
         (void)fprintf(stdout, "%s: split wrapping didn't work on this polygon(%d)\n", nco_prg_nm_get(), idx );
         (void)fprintf(stdout, "/********************************/\n");
       }
-
       pl=nco_poly_free(pl);
     }
-
-
   }
 
   if(nco_dbg_lvl_get() >=  nco_dbg_std )
@@ -230,10 +207,8 @@ int *pl_nbr)
   *pl_nbr=idx_cnt;
 
   return pl_lst;
-
 }
 
-
 poly_sct **             /* [O] [nbr]  size of array */
 nco_poly_lst_mk_rll(
 double *area, /* I [sr] Area of source grid */
@@ -246,7 +221,6 @@ size_t grd_sz, /* I [nbr] Number of elements in single layer of source grid */
 long grd_crn_nbr, /* I [nbr] Maximum number of corners in source gridcell */
 nco_grd_lon_typ_enm grd_lon_typ) /* I [num]  */
 {
-
   int idx=0;
   int wrp_cnt=0;
   int wrp_y_cnt=0;
@@ -263,23 +237,17 @@ nco_grd_lon_typ_enm grd_lon_typ) /* I [num]  */
   double *lat_ptr=lat_crn;
   double *lon_ptr=lon_crn;
 
-
   poly_sct *pl=(poly_sct*)NULL_CEWI;
-
   /* contains plain struct  sct with bmsk=False; */
   poly_sct *pl_msk=((poly_sct*)NULL_CEWI);
-
   poly_sct **pl_lst;
 
-
-
   /* list size is grd_sz - invalid or masked polygons are repesented by a poly_sct->bmsk=False */
   pl_lst=(poly_sct**)nco_malloc( sizeof (poly_sct*) * grd_sz);
 
   pl_msk=nco_poly_init();
   pl_msk->bmsk=False;
 
-
   /* filter out wrapped lon cells */
   if( grd_lon_typ == nco_grd_lon_nil || grd_lon_typ == nco_grd_lon_unk || grd_lon_typ == nco_grd_lon_bb )
     bwrp=False;
@@ -341,7 +309,6 @@ nco_grd_lon_typ_enm grd_lon_typ) /* I [num]  */
     if(!msk[idx])
       pl->bmsk=False;
 
-
     /* simple center of a rll cell - should always be inside of polygon */
     nco_poly_ctr_add(pl, grd_lon_typ);
 
@@ -355,7 +322,6 @@ nco_grd_lon_typ_enm grd_lon_typ) /* I [num]  */
     /* for debugging total number of wrapped cells */
     wrp_cnt+=pl->bwrp;
 
-
     pl_lst[idx]=pl;
   }
 
@@ -365,7 +331,6 @@ nco_grd_lon_typ_enm grd_lon_typ) /* I [num]  */
   pl_msk=nco_poly_free(pl_msk);
 
   return pl_lst;
-
 }
 
 poly_sct **             /* [O] [nbr]  size of array */
@@ -380,7 +345,6 @@ size_t grd_sz, /* I [nbr] Number of elements in single layer of source grid */
 long grd_crn_nbr, /* I [nbr] Maximum number of corners in source gridcell */
 nco_grd_lon_typ_enm grd_lon_typ) /* I [num]  */
 {
-
   int idx=0;
   int wrp_cnt=0;
   int wrp_y_cnt=0;
@@ -398,75 +362,56 @@ nco_grd_lon_typ_enm grd_lon_typ) /* I [num]  */
   double *lon_ptr=lon_crn;
 
   /* buffers  used in nco-poly_re_org() */
-  
-
-
   poly_sct *pl=(poly_sct*)NULL_CEWI;
-
   /* contains plain struct  sct with bmsk=False; */
   poly_sct *pl_msk=((poly_sct*)NULL_CEWI);
-
   poly_sct **pl_lst;
 
-
-
   /* list size is grd_sz - invalid or masked polygons are repesented by a poly_sct->bmsk=False */
   pl_lst=(poly_sct**)nco_malloc( sizeof (poly_sct*) * grd_sz);
-
   pl_msk=nco_poly_init();
   pl_msk->bmsk=False;
 
-
   /* filter out wrapped lon cells */
   if( grd_lon_typ == nco_grd_lon_nil || grd_lon_typ == nco_grd_lon_unk || grd_lon_typ == nco_grd_lon_bb )
    bwrp=False;
   else
     bwrp=True;
 
-
   // printf("About to print poly sct   grd_sz=%d grd_crn_nbr=%d\n", grd_sz, grd_crn_nbr);
   for(idx=0;idx<grd_sz; idx++)
   {
-
     /* check area */
     if(area[idx] == 0.0 ) {
       pl_lst[idx]= nco_poly_dpl(pl_msk);
       msk_cnt++;
       continue;
-
     }
 
-
-
     pl=nco_poly_init_lst(poly_sph, grd_crn_nbr,0, idx, lon_ptr, lat_ptr);
     lon_ptr+=(size_t)grd_crn_nbr;
     lat_ptr+=(size_t)grd_crn_nbr;
 
     /* if poly is less  than a triangle then  null is returned*/
     if(!pl ) {
-
       if(nco_dbg_lvl_get()>= nco_dbg_dev)
          fprintf(stderr, "%s(): WARNING cell(id=%d) less than a triange\n", fnc_nm, idx);
 
       pl_lst[idx]= nco_poly_dpl(pl_msk);
       msk_cnt++;
       continue;
-
     }
     
     /* add centroid from input  */
     pl->dp_x_ctr=lon_ctr[idx];
     pl->dp_y_ctr=lat_ctr[idx];
 
-    
-
     /* pop shp */
     nco_poly_shp_pop(pl);
 
     /* add min max */
     nco_poly_minmax_add(pl, grd_lon_typ, bchk_caps);
 
-
     /* if coords cannot deal with wrapping */
     if( pl->bwrp  && bwrp==False   )
     {
@@ -474,10 +419,8 @@ nco_grd_lon_typ_enm grd_lon_typ) /* I [num]  */
       pl_lst[idx]= nco_poly_dpl(pl_msk);
       msk_cnt++;
       continue;
-
     }
 
-
     /* The area of an RLL grid needs to be re-calculated  as we have to take account of lines of latitude as great circles */
     nco_poly_area_add(pl);
 
@@ -517,10 +460,8 @@ nco_grd_lon_typ_enm grd_lon_typ) /* I [num]  */
        */
        pl->bmsk=False;
        msk_cnt++;
-
      }
 
-
     if(nco_dbg_lvl_get()>= nco_dbg_dev  )
       if(pl->bwrp)
         nco_poly_prn(pl,0);
@@ -533,19 +474,14 @@ nco_grd_lon_typ_enm grd_lon_typ) /* I [num]  */
     wrp_y_cnt+=pl->bwrp_y;
 
     pl_lst[idx]=pl;
-
-
   }
 
   if(nco_dbg_lvl_get() >=  nco_dbg_dev )
     (void)fprintf(stderr, "%s: %s size input list(%lu), size output list(%lu)  total area=%.15e  num wrapped= %d num caps=%d num masked=%d\n", nco_prg_nm_get(),fnc_nm, grd_sz, grd_sz, tot_area, wrp_cnt, wrp_y_cnt, msk_cnt);
 
-
-
   pl_msk=nco_poly_free(pl_msk);
 
   return pl_lst;
-
 }
 
 poly_sct **
@@ -561,25 +497,20 @@ int arr_nbr)
   pl_lst=(poly_sct**)nco_free(pl_lst);
 
   return pl_lst;
-
 }
 
-
 void
 nco_poly_set_priority(
 int nbr_lst,
 KDPriority *list){
-
   int idx;
 
   for(idx=0;idx<nbr_lst;idx++){
-
     list[idx].dist = 1.1;
     list[idx].elem = (KDElem*)NULL;
   }
 
   return ;
-
 }
 
 poly_sct **
@@ -589,8 +520,7 @@ int pl_cnt_in,
 KDTree *rtree,
 int *pl_cnt_vrl_ret){
 
-/* just duplicate output list to overlap */
-
+  /* just duplicate output list to overlap */
   size_t idx;
   size_t jdx;
 
@@ -629,18 +559,13 @@ int *pl_cnt_vrl_ret){
     size[KD_TOP]    = pl_lst_in[idx]->dp_y_minmax[1];
 
     /* find overlapping polygons */
-
     // cnt_vrl=kd_nearest_intersect(rtree, size, max_nbr_vrl,list,bSort );
-
     /* nco_poly_prn(2, pl_lst_in[idx] ); */
 
-
     for(jdx=0; jdx <cnt_vrl ;jdx++){
 
       poly_sct *pl_vrl=(poly_sct*)NULL_CEWI;
       poly_sct *pl_out=(poly_sct*)list[jdx].elem->item;           ;
-
-
       // nco_poly_prn(2, pl_out);
 
       /* check for polygon in polygon first */
@@ -673,10 +598,8 @@ int *pl_cnt_vrl_ret){
 
         //fprintf(stderr,"Overlap polygon to follow\n");
         //nco_poly_prn(2, pl_vrl);
-
       }
     }
-
     if(nco_dbg_lvl_get() >= nco_dbg_dev) (void) fprintf(stderr, "%s: total overlaps=%d for polygon %lu - potential overlaps=%d actual overlaps=%d\n", nco_prg_nm_get(), pl_cnt_vrl,  idx, cnt_vrl, cnt_vrl_on);
   }
   list = (KDPriority *)nco_free(list);
@@ -702,7 +625,6 @@ int *pl_cnt_vrl_ret){
   nco_bool bDirtyRats=False;
 
   int pl_cnt_vrl=0;
-
   int thr_idx=0;
   int pl_cnt_dbg=0;
   int tot_nan_cnt=0;
@@ -801,10 +723,8 @@ int *pl_cnt_vrl_ret){
     /* if a wrapped polygon then split and do two searches  */
     bSplit=nco_poly_minmax_split(pl_lst_in[idx],grd_lon_typ,size1,size2);
     if(bSplit){
-
       vrl_cnt=kd_nearest_intersect(tree, nbr_tr, size1, &mem_lst[thr_idx], False);
       vrl_cnt=kd_nearest_intersect(tree, nbr_tr, size2, &mem_lst[thr_idx], False);
-
     }else{
       vrl_cnt=kd_nearest_intersect(tree, nbr_tr, size1, &mem_lst[thr_idx], False);
     }
@@ -822,7 +742,6 @@ int *pl_cnt_vrl_ret){
       /* for area debug only */
       mem_lst[thr_idx].kd_list[jdx]->area=-1.0;
       mem_lst[thr_idx].kd_list[jdx]->dbg_sng[0]='\0';
-
       /*
       if (pl_lst_in[idx]->pl_typ != pl_out->pl_typ) {
         fprintf(stderr, "%s: %s poly type mismatch\n", nco_prg_nm_get(), fnc_nm);
@@ -831,7 +750,6 @@ int *pl_cnt_vrl_ret){
       */
 
       if(pl_typ== poly_rll){
-
         pl_vrl = nco_poly_vrl_do(pl_lst_in[idx], pl_out, 0, (char*)NULL);
 
         /* if pl_vrl is NULL from,  nco_poly_do_vrl()  then there are 3 possible senario's
@@ -854,7 +772,6 @@ int *pl_cnt_vrl_ret){
           else if(nco_poly_in_poly_minmax(pl_out,pl_lst_in[idx]))
             pl_vrl=nco_poly_dpl(pl_lst_in[idx]);
         }
-
         if(pl_vrl){
           /* add area nb also sets wrapping */
           nco_poly_minmax_add(pl_vrl, grd_lon_typ, False);
@@ -960,7 +877,6 @@ int *pl_cnt_vrl_ret){
           nco_poly_prn(pl_vrl, 0);
           (void) fprintf(stderr, "/***********************************************/\n");
         }
-
       } /* end if poly_sph */
 
       if (pl_vrl) {
@@ -984,7 +900,6 @@ int *pl_cnt_vrl_ret){
         if(isnan(pl_vrl->area) || pl_vrl->area == 0.0){
 	  nan_cnt++;
           pl_vrl->area=0.0;
-
           pl_vrl=nco_poly_free(pl_vrl);
           continue;
         }
@@ -998,7 +913,6 @@ int *pl_cnt_vrl_ret){
 #endif
         {
           pl_out->wgt+=pl_vrl->wgt;
-
         }
 */
         vrl_area += pl_vrl->area;
@@ -1025,13 +939,11 @@ int *pl_cnt_vrl_ret){
           mem_lst[thr_idx].pl_lst[mem_lst[thr_idx].pl_cnt++] = pl_vrl;
 
         vrl_cnt_on++;
-
         /* for area debug only */
       }
     } /* end jdx */
 
     if (nco_dbg_lvl_get() >= nco_dbg_dev) {
-
 #ifdef _OPENMP
 #pragma omp critical
 #endif
@@ -1149,7 +1061,6 @@ int pl_cnt_vrl)
 
     if(jdx < pl_cnt_in )
       pl_lst_in[jdx]->area-=pl_lst_vrl[idx]->area;
-
   }
 
   fprintf(stderr, "%s():WARNING following is list of incomplete src cells, by src_id no\n",fnc_nm);
@@ -1157,7 +1068,6 @@ int pl_cnt_vrl)
     if( fabs(  pl_lst_in[idx]->area) > epsilon)
       fprintf(stderr, "src_id=%d area=%.10f\n", pl_lst_in[idx]->src_id, pl_lst_in[idx]->area );
 
-
   for(idx=0;idx<pl_cnt_vrl;idx++)
   {
     id=pl_lst_vrl[idx]->dst_id;
@@ -1167,14 +1077,12 @@ int pl_cnt_vrl)
 
     if(jdx < pl_cnt_out )
       pl_lst_out[jdx]->area-=pl_lst_vrl[idx]->area;
-
   }
 
   fprintf(stderr, "%s():WARNING following is list of incomplete dst cells, by src_id no\n",fnc_nm);
   for(idx=0;idx<pl_cnt_out;idx++)
     if( fabs(  pl_lst_out[idx]->area) > epsilon)
       fprintf(stderr, "src_id=%d area=%.10f\n", pl_lst_out[idx]->src_id, pl_lst_out[idx]->area );
-
    return;
 } /* !nco_poly_lst_chk() */
 
@@ -1211,14 +1119,9 @@ int *pl_cnt_dbg) /* size of output dbg grid */
     else
       area[idx]=pl_lst[idx]->area;
 
-
-
-
   for(idx=0;idx<pl_cnt_vrl;idx++)
   {
-
     id = (io_flg ? pl_lst_vrl[idx]->dst_id : pl_lst_vrl[idx]->src_id);
-
     if(is_lst_cnt )
       area[id] -= pl_lst_vrl[idx]->area;
     else
@@ -1230,13 +1133,10 @@ int *pl_cnt_dbg) /* size of output dbg grid */
       if (jdx < pl_cnt)
         area[jdx] -= pl_lst_vrl[idx]->area;
     }
-
   }
 
-
   for(idx=0;idx<pl_cnt;idx++) {
     if (fabs(area[idx]) > epsilon) {
-
       if (nco_dbg_lvl_get() >= nco_dbg_dev)
         fprintf(stderr, "%s() src_id=%d area=%.15e\n", fnc_nm, pl_lst[idx]->src_id, area[idx]);
 
@@ -1246,7 +1146,6 @@ int *pl_cnt_dbg) /* size of output dbg grid */
     }
   }
 
-
   area=(double*)nco_free(area);
 
   *pl_cnt_dbg=pl_nbr_dbg;
@@ -1308,13 +1207,9 @@ int *wgt_cnt_bln_ret) {
   FILE *const fp_stderr = stderr;
 
   pl_typ = pl_lst_out[0]->pl_typ;
-
   lcl_thr_nbr = omp_get_max_threads();
-
   nbr_idw= ( rgr_nfo->xtr_nsp > max_nbr_idw ? max_nbr_idw : rgr_nfo->xtr_nsp );
-
   pow_idw=rgr_nfo->xtr_xpn;
-
   mem_lst = (omp_mem_sct *) nco_malloc(sizeof(omp_mem_sct) * lcl_thr_nbr);
 
   for (idx = 0; idx < lcl_thr_nbr; idx++) {
@@ -1328,7 +1223,6 @@ int *wgt_cnt_bln_ret) {
     mem_lst[idx].idx_cnt = 0;
 
     kd_list_realloc(&mem_lst[idx],1);
-
   }
 
   thr_quota = pl_cnt / lcl_thr_nbr;
@@ -1370,7 +1264,6 @@ int *wgt_cnt_bln_ret) {
     size_t nbr_lst_lcl;
 
     // (void) nco_poly_set_priority(max_nbr_vrl, list);
-
     thr_idx = omp_get_thread_num();
 
     if (0 && nco_dbg_lvl_get() >= nco_dbg_dev)
@@ -1384,8 +1277,6 @@ int *wgt_cnt_bln_ret) {
     if (mem_lst[thr_idx].kd_blk_nbr > 1)
       kd_list_realloc(&mem_lst[thr_idx], 1);
 
-
-
     /* get bounds of polygon in */
     //bSplit = nco_poly_minmax_split(pl_lst_out[idx], grd_lon_typ, size1, size2);
 
@@ -1451,9 +1342,7 @@ int *wgt_cnt_bln_ret) {
 
       if (nco_dbg_lvl_get() >= nco_dbg_dev)
         (void)fprintf(fp_stderr,"%s:%s: singleton  x_ctr=%f  y_ctr=%f\n", nco_prg_nm_get(), fnc_nm, pl_lst_out[idx]->dp_x_ctr, pl_lst_out[idx]->dp_y_ctr );
-
     }else{
-
       /* check for duplicates in first nbr_nni by sorting again with ->item  !!!*/
       // kd_priority_list_sort(mem_lst[thr_idx].kd_list,nbr_idw, nbr_idw,&nbr_idw_cnt );
       nbr_idw_cnt=kd_list_sort_omp(&mem_lst[thr_idx], nbr_idw);
@@ -1463,9 +1352,7 @@ int *wgt_cnt_bln_ret) {
 
       /* output at least one */
       for (jdx = 0; jdx < nbr_idw_cnt; jdx++) {
-
         pl = (poly_sct *) mem_lst[thr_idx].kd_list[jdx]->elem->item;
-
         /* remember src is in tree and dst is in list */
         wgt_pre[jdx].src_id = pl->src_id;
         wgt_pre[jdx].dst_id = pl_lst_out[idx]->src_id;
@@ -1478,13 +1365,11 @@ int *wgt_cnt_bln_ret) {
       /* find weights total */
       for (jdx = 0; jdx < nbr_idw_cnt; jdx++)
         wgt_ttl += wgt_pre[jdx].wgt;
-
       /* normalize weights */
       for (jdx = 0; jdx < nbr_idw_cnt; jdx++)
         wgt_pre[jdx].wgt /= wgt_ttl;
 
       for (jdx = 0; jdx < nbr_idw_cnt; jdx++) {
-
         if (wgt_pre[jdx].wgt < min_wgt)
           continue;
 
@@ -1495,9 +1380,7 @@ int *wgt_cnt_bln_ret) {
           mem_lst[thr_idx].wgt_lst = (wgt_sct **) nco_realloc(mem_lst[thr_idx].wgt_lst,sizeof(wgt_sct *) * ++mem_lst[thr_idx].blk_nbr *NCO_VRL_BLOCKSIZE);
 
         mem_lst[thr_idx].wgt_lst[mem_lst[thr_idx].pl_cnt++] = wgt_lcl;
-
         //(void)fprintf(stderr,"%s: weight(%lu)=%f ",fnc_nm, mem_lst[thr_idx].pl_cnt, wgt_lcl->wgt);
-
       } /* end jdx */
     }
 
@@ -1512,12 +1395,8 @@ int *wgt_cnt_bln_ret) {
   for(idx=0;idx<lcl_thr_nbr;idx++)
     kd_list_realloc(&mem_lst[idx],0);
 
-
-
   wgt_lst_idw=mem_lst[0].wgt_lst;
-
   *wgt_cnt_bln_ret=mem_lst[0].pl_cnt;
-
   mem_lst=(omp_mem_sct*)nco_free(mem_lst);
 
   return wgt_lst_idw;
@@ -1529,9 +1408,7 @@ int pl_cnt,
 int ctr_typ)
 {
   int idx;
-
   double pControl[NBR_SPH];
-
   for(idx=0;idx<pl_cnt;idx++)
   {
     if(pl_lst[idx]->crn_nbr <3 || pl_lst[idx]->area==0.0  )
@@ -1578,7 +1455,6 @@ int sz_lst)
     wgt_sct **tmp_wgt_lst = NULL;
 
     tmp_wgt_lst = mem_lst[0].wgt_lst = (wgt_sct **) nco_realloc(mem_lst[0].wgt_lst, sizeof(wgt_sct *) * tot_cnt);
-
     tmp_wgt_lst += mem_lst[0].pl_cnt;
 
     for (idx = 1; idx < sz_lst; idx++) {
@@ -1613,4 +1489,3 @@ int sz_lst)
 
   return;
 } /* !nco_mem_lst_cat() */
-


=====================================
src/nco/nco_ppc.c
=====================================
@@ -553,7 +553,7 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
   /* Threads: Routine is thread safe and calls no unsafe routines */
 
   /* Purpose: Implement NCO NSD PPC algorithm (BitGroom) from Zen16 by masking-out insignificant bits of op1 values
-     Also performs all other bitmasking algorithms, including BitRound, Granular BitGroom, BitSet, BitShave, ... 
+     Also performs all other bitmasking algorithms, including BitRound, Granular BitRound, BitSet, BitShave, ... 
      As of 20240408 (total solar eclipse day!), also calls nco_qnt_mtd() to write CF-compliant lossy metadata */
 
   /* Bitmask is currently defined as op1:=bitmask(op1,ppc) */  
@@ -619,7 +619,7 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
     }; /* !mnt_log10_tbl_dgr */
 #if false /* Not currently used */
   const double mnt_log10_tbl_gbr[5][2]=
-    { /* NB: Granular BitGroom extends Digit Round tabular precision from 9 to 15 digits */
+    { /* NB: Granular BitRound extends Digit Round tabular precision from 9 to 15 digits */
      {0.6,-dgt_per_bit}, /* Approximate log10(mnt) for mantissas in [0.5,0.6) as log10(0.5) = log10(2^(-1)) = -log10(2) = -dgt_per_bit = -0.301 */
      {0.7,-0.221848749616356}, /* Approximate log10(mnt) for mantissas in [0.6,0.7) as log10(0.6) = -0.222 */
      {0.8,-0.154901959985743}, /* Approximate log10(mnt) for mantissas in [0.7,0.8) as log10(0.7) = -0.155 */
@@ -635,7 +635,8 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
   double qnt_grr; /* [frc] Guaranteed maximum allowed quantization error */ 
   double qnt_prx; /* [frc] Quantization approximation */
   double qnt_val; /* [frc] Quantized value */
-  double val; /* [frc] Copy of input value to avoid indirection */
+  double val_dbl; /* [frc] Copy of input value to avoid indirection */
+  float val_flt; /* [frc] Copy of input value to avoid indirection */
   
   int dgt_nbr; /* [nbr] Number of digits before decimal point */
   int qnt_pwr; /* [nbr] Power of two in quantization mask: qnt_msk = 2^qnt_pwr */
@@ -819,21 +820,23 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
     case nco_baa_btg:
       /* Bit-Groom: alternately shave and set LSBs */
       for(idx=0L;idx<sz;idx+=2L)
-	if(op1.fp[idx] != mss_val_cmp_flt) u32_ptr[idx]&=msk_f32_u32_zro;
+	/* 20250215 Do not quantize _FillValue, +/- zero, or NaN */
+	if((val_flt=op1.fp[idx]) != mss_val_cmp_flt && val_flt != 0.0f && !isnan(val_flt))
+	  u32_ptr[idx]&=msk_f32_u32_zro;
       for(idx=1L;idx<sz;idx+=2L)
-	if(op1.fp[idx] != mss_val_cmp_flt && u32_ptr[idx] != 0U) /* Never quantize upwards floating point values of zero */
+	if((val_flt=op1.fp[idx]) != mss_val_cmp_flt && val_flt != 0.0f && !isnan(val_flt))
 	  u32_ptr[idx]|=msk_f32_u32_one;
       break;
       /* !BitGroom = BTG */
     case nco_baa_shv:
       /* Bit-Shave: always shave LSBs */
       for(idx=0L;idx<sz;idx++)
-	if(op1.fp[idx] != mss_val_cmp_flt) u32_ptr[idx]&=msk_f32_u32_zro;
+	if((val_flt=op1.fp[idx]) != mss_val_cmp_flt && val_flt != 0.0f && !isnan(val_flt)) u32_ptr[idx]&=msk_f32_u32_zro;
       break;
     case nco_baa_set:
       /* Bit-Set: always set LSBs */
       for(idx=0L;idx<sz;idx++)
-	if(op1.fp[idx] != mss_val_cmp_flt && u32_ptr[idx] != 0U) /* Never quantize upwards floating point values of zero */
+	if((val_flt=op1.fp[idx]) != mss_val_cmp_flt && val_flt != 0.0f && !isnan(val_flt))
 	  u32_ptr[idx]|=msk_f32_u32_one;
       break;
     case nco_baa_dgr:
@@ -874,7 +877,8 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
 	 LOG2_10 bit_per_dgt
 	 LOG10_2 dgt_per_bit_dgr */
       for(idx=0L;idx<sz;idx++){
-	if((val=op1.fp[idx]) != mss_val_cmp_flt && u32_ptr[idx] != 0U){
+	/* 20250215: NB DigitRound implementation continues to use double precision "val", isnan(), etc. */
+	if((val_dbl=op1.fp[idx]) != mss_val_cmp_flt && val_dbl != 0.0 && !isnan(val_dbl)){
 	  /* Algorithm flow chart in DCG19 has equation numbers one less than actual
 	     Equations indicated below are the actual equation numbers in DCG19 */
 
@@ -883,7 +887,7 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
 	     NB: DCG19 filter code is incorrectly commented with:
 	     Value val = 10^d + eps = sign(val) * 2^xpn_bs2 + mnt, 0 <= mnt < 0.5 <--Incorrect
 	     double frexp(double x, int *y) returns double mnt=mantissa, exponent y (no FP math) */
-	  mnt=frexp(val,&xpn_bs2); /* DGG19 p. 4102 (8) */
+	  mnt=frexp(val_dbl,&xpn_bs2); /* DGG19 p. 4102 (8) */
 	  /* Initialize bin index */
 	  tbl_idx=0;
 	  /* Search upper bounds to identify appropriate mantissa bin */
@@ -924,14 +928,14 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
 	     Add 0.5 prior to floor to ensure IEEE-rounded value emerges
 	     NB: Adding 0.5 produces poorer-than necessary accuracy for some numbers
 	     However, it is guaranteed to be bias-free for random distributions */
-	  qnt_val=SIGN(val)*(floor(fabs(val)/qnt_fct)+0.5)*qnt_fct; /* DGG19 p. 4101 (1) */
+	  qnt_val=SIGN(val_dbl)*(floor(fabs(val_dbl)/qnt_fct)+0.5)*qnt_fct; /* DGG19 p. 4101 (1) */
 	  /* Implicit conversion casts double to float */
 	  op1.fp[idx]=qnt_val;
 	  if(nco_dbg_lvl_get() >= nco_dbg_var){
 	    /* Verify NSD precision guarantee NB: this check increases time ~30% */
-	    qnt_prx=fabs(val-qnt_val);
+	    qnt_prx=fabs(val_dbl-qnt_val);
 	    qnt_grr=0.5*pow(10.0,dgt_nbr-nsd);
-	    if(nco_dbg_lvl_get() >= nco_dbg_crr || qnt_prx > qnt_grr) (void)fprintf(stdout,"%s: %g = %g * %d^%d, dgt_nbr = %d, qnt_pwr = %d, qnt_val = %g, qnt_prx = %g\n",nco_prg_nm_get(),val,mnt,FLT_RADIX,xpn_bs2,dgt_nbr,qnt_pwr,qnt_val,qnt_prx);
+	    if(nco_dbg_lvl_get() >= nco_dbg_crr || qnt_prx > qnt_grr) (void)fprintf(stdout,"%s: %g = %g * %d^%d, dgt_nbr = %d, qnt_pwr = %d, qnt_val = %g, qnt_prx = %g\n",nco_prg_nm_get(),val_dbl,mnt,FLT_RADIX,xpn_bs2,dgt_nbr,qnt_pwr,qnt_val,qnt_prx);
 	    assert(qnt_prx <= qnt_grr);
 	  } /* !dbg */
 	} /* !mss_val_cmp_flt */
@@ -939,14 +943,17 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
       break;
       /* !DigitRound = DGR */
     case nco_baa_gbr:
-      /* Granular BitGroom
+      /* Granular BitRound
 	 Test GBR:
 	 ccc --tst=bnr --flt_foo=8 2> /dev/null | grep "Binary of float"
 	 ncks -O -7 -C -D 1 --baa=4 -v ppc_btg --ppc default=3 ~/nco/data/in.nc ~/foo.nc
 	 ncks -O -7 -C -D 1 --baa=4 -v one_dmn_rec_var_flt --ppc default=3 ~/nco/data/in.nc ~/foo.nc */
       for(idx=0L;idx<sz;idx++){
-	if((val=op1.fp[idx]) != mss_val_cmp_flt && u32_ptr[idx] != 0U){
-	  mnt=frexp(val,&xpn_bs2); /* DGG19 p. 4102 (8) */
+	// 20250214: Eliminate floating point exceptions (FPEs) cased by negative zero and NaNf
+	//if((val=op1.fp[idx]) != mss_val_cmp_flt && u32_ptr[idx] != 0U){
+	/* 20250215: NB Granular BitRound implementation continues to use double precision "val_dbl", isnan(), etc. */
+	if((val_dbl=op1.fp[idx]) != mss_val_cmp_flt && val_dbl != 0.0 && !isnan(val_dbl)){
+	  mnt=frexp(val_dbl,&xpn_bs2); /* DGG19 p. 4102 (8) */
 	  //tbl_idx=0;
 	  //while(mnt_log10_tbl_gbr[tbl_idx][0] < mnt) tbl_idx++;
 	  //mnt_log10_prx=mnt_log10_tbl_gbr[tbl_idx][1];
@@ -984,9 +991,9 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
 	  qnt_val=op1.fp[idx];
 	  if(nco_dbg_lvl_get() >= nco_dbg_var){
 	    /* Verify NSD precision guarantee NB: this assert() increases time ~30% */
-	    qnt_prx=fabs(val-qnt_val);
+	    qnt_prx=fabs(val_dbl-qnt_val);
 	    qnt_grr=0.5*pow(10.0,dgt_nbr-nsd);
-	    if(nco_dbg_lvl_get() >= nco_dbg_crr || qnt_prx > qnt_grr) (void)fprintf(stdout,"%s: %g = %g * %d^%d, dgt_nbr = %d, qnt_pwr = %d, pbxr = %d, bxnz = %d, qnt_val = %g, qnt_prx = %g\n",nco_prg_nm_get(),val,mnt,FLT_RADIX,xpn_bs2,dgt_nbr,qnt_pwr,prc_bnr_xpl_rqr,bit_xpl_nbr_zro,qnt_val,qnt_prx);
+	    if(nco_dbg_lvl_get() >= nco_dbg_crr || qnt_prx > qnt_grr) (void)fprintf(stdout,"%s: %g = %g * %d^%d, dgt_nbr = %d, qnt_pwr = %d, pbxr = %d, bxnz = %d, qnt_val = %g, qnt_prx = %g\n",nco_prg_nm_get(),val_dbl,mnt,FLT_RADIX,xpn_bs2,dgt_nbr,qnt_pwr,prc_bnr_xpl_rqr,bit_xpl_nbr_zro,qnt_val,qnt_prx);
 	    assert(qnt_prx <= qnt_grr);
 	    assert(bit_xpl_nbr_zro >= -1); /* NB: 0.0 might require -1 bits, i.e., "setting" the implicit first bit to zero */
 	  } /* !dbg */
@@ -1001,7 +1008,8 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
 	 Round mantissa, LSBs to zero contributed by Rostislav Kouznetsov 20200711
 	 Round mantissa using IEEE floating-point arithmetic, shave LSB using bit-mask */
       for(idx=0L;idx<sz;idx++){
-	if(op1.fp[idx] != mss_val_cmp_flt){
+	/* 20250215 Do not quantize _FillValue, +/- zero, or NaN */
+	if((val_flt=op1.fp[idx]) != mss_val_cmp_flt && val_flt != 0.0f && !isnan(val_flt)){
 	  u32_ptr[idx]+=msk_f32_u32_hshv; /* Add 1 to the MSB of LSBs, carry 1 to mantissa or even exponent */
 	  u32_ptr[idx]&=msk_f32_u32_zro; /* Shave it */
 	} /* !mss_val_cmp_flt */
@@ -1014,7 +1022,7 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
 	 Shave LSBs and set MSB of them
 	 See figures at https://github.com/nco/nco/pull/200 */
       for(idx=0L;idx<sz;idx++){
-	if(op1.fp[idx] != mss_val_cmp_flt){
+	if((val_flt=op1.fp[idx]) != mss_val_cmp_flt && val_flt != 0.0f && !isnan(val_flt)){
 	  u32_ptr[idx]&=msk_f32_u32_zro; /* Shave as normal */
 	  u32_ptr[idx]|=msk_f32_u32_hshv; /* Set MSB of LSBs */
 	} /* !mss_val_cmp_flt */
@@ -1081,21 +1089,22 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
     case nco_baa_btg:
       /* Bit-Groom: alternately shave and set LSBs */
       for(idx=0L;idx<sz;idx+=2L)
-	if(op1.dp[idx] != mss_val_cmp_dbl)
+	/* Do not quantize _FillValue, +/- zero, or NaN */
+	if((val_dbl=op1.dp[idx]) != mss_val_cmp_dbl && val_dbl != 0.0 && !isnan(val_dbl))
 	  u64_ptr[idx]&=msk_f64_u64_zro;
       for(idx=1L;idx<sz;idx+=2L)
-	if(op1.dp[idx] != mss_val_cmp_dbl && u64_ptr[idx] != 0ULL) /* Never quantize upwards floating point values of zero */
+	if((val_dbl=op1.dp[idx]) != mss_val_cmp_dbl && val_dbl != 0.0 && !isnan(val_dbl)) /* Never quantize upwards floating point values of zero */
 	  u64_ptr[idx]|=msk_f64_u64_one;
       break;
     case nco_baa_shv:
       /* Bit-Shave: always shave LSBs */
       for(idx=0L;idx<sz;idx++)
-	if(op1.dp[idx] != mss_val_cmp_dbl) u64_ptr[idx]&=msk_f64_u64_zro;
+	if((val_dbl=op1.dp[idx]) != mss_val_cmp_dbl && val_dbl != 0.0 && !isnan(val_dbl)) u64_ptr[idx]&=msk_f64_u64_zro;
       break;
     case nco_baa_set:
       /* Bit-Set: always set LSBs */
       for(idx=0L;idx<sz;idx++)
-	if(op1.dp[idx] != mss_val_cmp_dbl && u64_ptr[idx] != 0ULL) /* Never quantize upwards floating point values of zero */
+	if((val_dbl=op1.dp[idx]) != mss_val_cmp_dbl && val_dbl != 0.0 && !isnan(val_dbl)) /* Never quantize upwards floating point values of zero */
 	  u64_ptr[idx]|=msk_f64_u64_one;
       break;
     case nco_baa_dgr:
@@ -1105,27 +1114,27 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
 	 3. Compare u64_ptr (not u32_ptr) to zero
 	 DO NOT EDIT the NC_DOUBLE code except for dp-specific changes, use fp code as template */
       for(idx=0L;idx<sz;idx++){
-	if((val=op1.dp[idx]) != mss_val_cmp_dbl && u64_ptr[idx] != 0ULL){
+	if((val_dbl=op1.dp[idx]) != mss_val_cmp_dbl && val_dbl != 0.0 && !isnan(val_dbl)){
 	  /* Compute number of digits before decimal point of input floating-point value val
 	     Value val = 10^d + eps = sign(val) * 2^xpn_bs2 * mnt, 0.5 <= mnt < 1.0 <--Correct 
 	     Note that DCG19 filter code is incorrectly commented with:
 	     Value val = 10^d + eps = sign(val) * 2^xpn_bs2 + mnt, 0 <= mnt < 0.5 <--Incorrect
 	     Note that algorithm flow chart in DCG19 has equation numbers one less than actual
 	     Equations indicated below are the actual equations in DCG19 */
-	  mnt=frexp(val,&xpn_bs2); /* DGG19 p. 4102 (8) */
+	  mnt=frexp(val_dbl,&xpn_bs2); /* DGG19 p. 4102 (8) */
 	  tbl_idx=0;
 	  while(mnt_log10_tbl_dgr[tbl_idx][0] < mnt) tbl_idx++;
 	  mnt_log10_prx=mnt_log10_tbl_dgr[tbl_idx][1];
 	  dgt_nbr=(int)floor(xpn_bs2*dgt_per_bit_dgr+mnt_log10_prx)+1; /* DGG19 p. 4102 (9) */
 	  qnt_pwr=(int)floor(bit_per_dgt*(dgt_nbr-nsd)); /* DGG19 p. 4101 (7) */
 	  qnt_fct=ldexp(1.0,qnt_pwr); /* DGG19 p. 4101 (5) */
-	  qnt_val=SIGN(val)*(floor(fabs(val)/qnt_fct)+0.5)*qnt_fct; /* DGG19 p. 4101 (1) */
+	  qnt_val=SIGN(val_dbl)*(floor(fabs(val_dbl)/qnt_fct)+0.5)*qnt_fct; /* DGG19 p. 4101 (1) */
 	  op1.dp[idx]=qnt_val;
 	  if(nco_dbg_lvl_get() >= nco_dbg_var){
 	    /* Verify NSD precision guarantee NB: this check increases time ~30% */
-	    qnt_prx=fabs(val-qnt_val);
+	    qnt_prx=fabs(val_dbl-qnt_val);
 	    qnt_grr=0.5*pow(10.0,dgt_nbr-nsd);
-	    if(nco_dbg_lvl_get() >= nco_dbg_crr || qnt_prx > qnt_grr) (void)fprintf(stdout,"%s: %g = %g * %d^%d, dgt_nbr = %d, qnt_pwr = %d, qnt_val = %g, qnt_prx = %g\n",nco_prg_nm_get(),val,mnt,FLT_RADIX,xpn_bs2,dgt_nbr,qnt_pwr,qnt_val,qnt_prx);
+	    if(nco_dbg_lvl_get() >= nco_dbg_crr || qnt_prx > qnt_grr) (void)fprintf(stdout,"%s: %g = %g * %d^%d, dgt_nbr = %d, qnt_pwr = %d, qnt_val = %g, qnt_prx = %g\n",nco_prg_nm_get(),val_dbl,mnt,FLT_RADIX,xpn_bs2,dgt_nbr,qnt_pwr,qnt_val,qnt_prx);
 	    assert(qnt_prx <= qnt_grr);
 	  } /* !dbg */
 	} /* !mss_val_cmp_dbl */
@@ -1134,8 +1143,10 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
       /* !DigitRound = DGR */
     case nco_baa_gbr:
       for(idx=0L;idx<sz;idx++){
-	if((val=op1.dp[idx]) != mss_val_cmp_dbl && u64_ptr[idx] != 0ULL){
-	  mnt=frexp(val,&xpn_bs2); /* DGG19 p. 4102 (8) */
+	// 20250214: Eliminate floating point exceptions (FPEs) cased by negative zero and NaNf
+	//	if((val=op1.dp[idx]) != mss_val_cmp_dbl && u64_ptr[idx] != 0ULL){
+	if((val_dbl=op1.dp[idx]) != mss_val_cmp_dbl && val_dbl != 0.0 && !isnan(val_dbl)){
+	  mnt=frexp(val_dbl,&xpn_bs2); /* DGG19 p. 4102 (8) */
 	  mnt_fabs=fabs(mnt);
 	  mnt_log10_fabs=log10(mnt_fabs);
 	  /* 20211003 Continuous determination of dgt_nbr improves CR by ~10% */
@@ -1156,23 +1167,24 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
 	  qnt_val=op1.dp[idx];
 	  if(nco_dbg_lvl_get() >= nco_dbg_var){
 	    /* Verify NSD precision guarantee NB: this assert() increases time ~30% */
-	    qnt_prx=fabs(val-qnt_val);
+	    qnt_prx=fabs(val_dbl-qnt_val);
 	    qnt_grr=0.5*pow(10.0,dgt_nbr-nsd);
-	    if(nco_dbg_lvl_get() >= nco_dbg_crr || qnt_prx > qnt_grr) (void)fprintf(stdout,"%s: %g = %g * %d^%d, dgt_nbr = %d, qnt_pwr = %d, pbxr = %d, bxnz = %d, qnt_val = %g, qnt_prx = %g\n",nco_prg_nm_get(),val,mnt,FLT_RADIX,xpn_bs2,dgt_nbr,qnt_pwr,prc_bnr_xpl_rqr,bit_xpl_nbr_zro,qnt_val,qnt_prx);
+	    if(nco_dbg_lvl_get() >= nco_dbg_crr || qnt_prx > qnt_grr) (void)fprintf(stdout,"%s: %g = %g * %d^%d, dgt_nbr = %d, qnt_pwr = %d, pbxr = %d, bxnz = %d, qnt_val = %g, qnt_prx = %g\n",nco_prg_nm_get(),val_dbl,mnt,FLT_RADIX,xpn_bs2,dgt_nbr,qnt_pwr,prc_bnr_xpl_rqr,bit_xpl_nbr_zro,qnt_val,qnt_prx);
 	    assert(qnt_prx <= qnt_grr);
 	    assert(bit_xpl_nbr_zro >= -1); /* NB: 0.0 might require -1 bits, i.e., "setting" the implicit first bit to zero */
 	  } /* !dbg */
 	} /* !mss_val_cmp_dbl */
       } /* !idx */
       break;
-      /* !GranularBitRound = GBG */
+      /* !GranularBitRound = GBR */
     case nco_baa_bgr:
     case nco_baa_btr:
       /* Round mantissa, LSBs to zero contributed by Rostislav Kouznetsov 20200711
 	 Round mantissa using software emulation of IEEE arithmetic, shave LSB using bit-mask
 	 See figures at https://github.com/nco/nco/pull/199 */
       for(idx=0L;idx<sz;idx++){
-	if(op1.dp[idx] != mss_val_cmp_dbl){
+	/* 20250215 Do not quantize _FillValue, +/- zero, or NaN */
+	if((val_dbl=op1.dp[idx]) != mss_val_cmp_dbl && val_dbl != 0.0 && !isnan(val_dbl)){
 	  u64_ptr[idx]+=msk_f64_u64_hshv; /* Add 1 at MSB of LSBs */
 	  u64_ptr[idx]&=msk_f64_u64_zro; /* Shave it */
 	} /* !mss_val_cmp_dbl */
@@ -1185,7 +1197,7 @@ nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
 	 Shave LSBs and set MSB of them
 	 See figures at https://github.com/nco/nco/pull/200 */
       for(idx=0L;idx<sz;idx++){
-	if(op1.dp[idx] != mss_val_cmp_dbl){
+	if((val_dbl=op1.dp[idx]) != mss_val_cmp_dbl && val_dbl != 0.0 && !isnan(val_dbl)){
 	  u64_ptr[idx]&=msk_f64_u64_zro; /* Shave as normal */
 	  u64_ptr[idx]|=msk_f64_u64_hshv; /* Set MSB of LSBs */
 	} /* !mss_val_cmp_dbl */


=====================================
src/nco/nco_rec_var.c
=====================================
@@ -92,7 +92,7 @@ nco_rec_crd_chk /* Check for monotonicity of coordinate values */
        ((rec_crd_val_crr < rec_crd_val_lst) && monotonic_direction == increasing)){
       if(idx_rec-1 == -1){
 	/* Inter-file non-monotonicity */
-	if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: INFO/WARNING Inter-file non-monotonicity. Record coordinate \"%s\" does not monotonically %s between last specified record of previous input file (whose name is not cached locally and thus currently unavailable for printing) and first specified record (i.e., record index = %ld) of current input file (%s). This message is often informational only and may usually be safely ignored. It is quite common when joining files with \"wrapped\" record coordinates, e.g., joining a January file to a December file when the time coordinate is enumerated as day of year. It is also common when joining files which employ a \"time=base_time+time_offset\" convention. Sometimes, however, this message is a warning which signals that the user has joined files together in a different order than intended and that corrective action should be taken to re-order the input files. Output file %s will contain these non-monotonic record coordinate values (%f, %f) at record indices %ld, %ld.\n",nco_prg_nm_get(),var->nm,(monotonic_direction == decreasing ? "decrease" : "increase"),idx_rec,fl_in,fl_out,rec_crd_val_lst,rec_crd_val_crr,idx_rec_out-1L,idx_rec_out);
+	if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: INFO/WARNING Inter-file non-monotonicity. Record coordinate \"%s\" does not monotonically %s between last specified record of previous input file (whose name is not cached locally and thus currently unavailable for printing) and first specified record (i.e., record index = %ld) of current input file (%s). This message is often informational only and may usually be safely ignored. It is quite common when joining files with \"wrapped\" record coordinates, e.g., joining a January file to a December file when the time coordinate is enumerated as day of year. It is also common when joining files that employ a \"time=base_time+time_offset\" convention. Sometimes, however, this message is a warning which signals that the user has joined files together in a different order than intended and that corrective action should be taken to re-order the input files. Output file %s will contain these non-monotonic record coordinate values (%f, %f) at record indices %ld, %ld.\n",nco_prg_nm_get(),var->nm,(monotonic_direction == decreasing ? "decrease" : "increase"),idx_rec,fl_in,fl_out,rec_crd_val_lst,rec_crd_val_crr,idx_rec_out-1L,idx_rec_out);
       }else{ /* !idx_rec */
 	/* Intra-file non-monotonicity */
 	(void)fprintf(stderr,"%s: WARNING Intra-file non-monotonicity. Record coordinate \"%s\" does not monotonically %s between (input file %s record indices: %ld, %ld) (output file %s record indices %ld, %ld) record coordinate values %f, %f\n",nco_prg_nm_get(),var->nm,(monotonic_direction == decreasing ? "decrease" : "increase"),fl_in,idx_rec-1L,idx_rec,fl_out,idx_rec_out-1,idx_rec_out,rec_crd_val_lst,rec_crd_val_crr);


=====================================
src/nco/nco_rgr.c
=====================================
@@ -1776,10 +1776,14 @@ nco_ntp_vrt /* [fnc] Interpolate vertically */
       if(flg_grd_out_hyb && (ps_id_tpl == NC_MIN_INT)) (void)fprintf(stderr,"%s: INFO %s detects spatially varying surface pressure field %s in pure-pressure input data file. %s will be copied directly from pure-pressure grid input dataset to, and used as the reference surface pressure of, the output hybrid sigma-pressure coordinate data file, where it will be named %s.\n",nco_prg_nm_get(),fnc_nm,ps_nm_in,ps_nm_in,ps_nm_out);
       if(flg_grd_out_hyb && (ps_id_tpl != NC_MIN_INT)) (void)fprintf(stderr,"%s: INFO %s detects spatially varying surface pressure field in both vertical-grid file as %s, and in pure-pressure input data file as %s. The vertical grid-file takes precedence. %s will be copied directly from vertical-grid file to, and used as the reference surface pressure of, the output hybrid sigma-pressure coordinate data file, where it will be named %s. %s in input pure-pressure file will be ignored.\n",nco_prg_nm_get(),fnc_nm,ps_nm_tpl,ps_nm_in,ps_nm_tpl,ps_nm_out,ps_nm_in);
     }else{
-      if(flg_grd_out_hyb && (ps_id_tpl == NC_MIN_INT)){
-	(void)fprintf(stderr,"%s: ERROR %s does not find spatially varying surface pressure field %s in pure-pressure input data file or as %s in vertical grid-file for hybrid sigma-pressure output. A surface pressure field must be present in at least one of these files in order to construct the output hybrid sigma-pressure coordinate pressures.\nHINT: Append a valid surface pressure field to the input data file or to the vertical grid-file.\n",nco_prg_nm_get(),fnc_nm,ps_nm_in,ps_nm_tpl);
-	nco_exit(EXIT_FAILURE);
-      } /* !ps_id_tpl */
+      if(flg_grd_out_hyb){
+	if(ps_id_tpl == NC_MIN_INT){
+	  (void)fprintf(stderr,"%s: ERROR %s does not find spatially varying surface pressure field %s in pure-pressure input data file or as %s in vertical grid-file for hybrid sigma-pressure output. A surface pressure field must be present in at least one of these files in order to construct the output hybrid sigma-pressure coordinate pressures.\nHINT: Append a valid surface pressure field to the input data file or to the vertical grid-file.\n",nco_prg_nm_get(),fnc_nm,ps_nm_in,ps_nm_tpl);
+	  nco_exit(EXIT_FAILURE);
+	}else{ /* !ps_id_tpl */
+	  flg_grd_hyb_cameam=True;
+	} /* !ps_id_tpl */
+      } /* !flg_grd_out_hyb */
     } /* !ps_id */
   } /* !flg_grd_in_prs */
 


=====================================
src/nco/nco_s1d.c
=====================================
@@ -1213,8 +1213,6 @@ nco_s1d_unpack /* [fnc] Unpack sparse-1D ELM/CLM variables into full file */
       rcd+=nco_def_var(out_id,frc_column_nm,crd_typ_out,dmn_nbr_2D,dmn_ids_out,&frc_column_out_id);
       if(nco_cmp_glb_get()) rcd+=nco_flt_def_out(out_id,frc_column_out_id,NULL,nco_flt_flg_prc_fll);
       var_crt_nbr++;
-      rcd=nco_char_att_put(out_id,frc_column_nm,"long_name","Fraction of gridcell occupied by snow-related columns");
-      rcd=nco_char_att_put(out_id,frc_column_nm,"legend","For datasets with Multiple Elevation Classes (MECs): index = 0 is soil column, index = 1 is MEC == 1, indexes 2..10 are remaining MEC columns, index 11 is sub-total of MEC columns, index = 12 is deep lake column, index = 13 is wetland column, and index = 14 is grand total of natural columns. For non-MEC datasets, index = 0 is soil column, index = 1 is glaciated column, index = 2 is deep lake column, index = 3 is wetland column, and index = 4 is grand total of natural columns.");
     } /* !flg_frc_column_out */
     if(flg_frc_landunit_out){
       dmn_ids_out[0]=dmn_id_lnd_out;
@@ -1222,8 +1220,6 @@ nco_s1d_unpack /* [fnc] Unpack sparse-1D ELM/CLM variables into full file */
       rcd+=nco_def_var(out_id,frc_landunit_nm,crd_typ_out,dmn_nbr_2D,dmn_ids_out,&frc_landunit_out_id);
       if(nco_cmp_glb_get()) rcd+=nco_flt_def_out(out_id,frc_landunit_out_id,NULL,nco_flt_flg_prc_fll);
       var_crt_nbr++;
-      rcd=nco_char_att_put(out_id,frc_landunit_nm,"long_name","Fraction of gridcell occupied by Landunit");
-      rcd=nco_char_att_put(out_id,frc_landunit_nm,"legend","landunit index = 0 is sum of all landunit fractions, indexes = 1..9 are standard landunit types");
     } /* !flg_frc_landunit_out */
     if(flg_area_out){
       rcd+=nco_def_var(out_id,area_nm,crd_typ_out,dmn_nbr_1D,&dmn_id_col_out,&area_out_id);
@@ -1307,6 +1303,16 @@ nco_s1d_unpack /* [fnc] Unpack sparse-1D ELM/CLM variables into full file */
     } /* !flg_sgs_msk_out */
   } /* !flg_grd_2D */
 
+  /* Write new attributes here so they apply to both 1D and 2D output datasets */
+  if(flg_frc_column_out){
+    rcd=nco_char_att_put(out_id,frc_column_nm,"long_name","Fraction of gridcell occupied by snow-related columns");
+    rcd=nco_char_att_put(out_id,frc_column_nm,"legend","For datasets with Multiple Elevation Classes (MECs): index = 0 is soil column, index = 1 is MEC == 1, indexes 2..10 are remaining MEC columns, index 11 is sub-total of MEC columns, index = 12 is deep lake column, index = 13 is wetland column, and index = 14 is grand total of natural columns. For non-MEC datasets, index = 0 is soil column, index = 1 is glaciated column, index = 2 is deep lake column, index = 3 is wetland column, and index = 4 is grand total of natural columns.");
+  } /* !flg_frc_column_out */
+  if(flg_frc_landunit_out){
+    rcd=nco_char_att_put(out_id,frc_landunit_nm,"long_name","Fraction of gridcell occupied by Landunit");
+    rcd=nco_char_att_put(out_id,frc_landunit_nm,"legend","landunit index = 0 is sum of all landunit fractions, indexes = 1..9 are standard landunit types");
+  } /* !flg_frc_landunit_out */
+  
   /* levgrnd coordinate: ncks -v lev.? ${DATA}/bm/elmv3_r05l15.nc */
   const double levgrnd[15]={0.007100635,0.027925,0.06225858,0.1188651,0.2121934,0.3660658,0.6197585,1.038027,1.727635,2.864607,4.739157,7.829766,12.92532,21.32647,35.17762}; /* [m] Coordinate lake levels */
   int levgrnd_out_id=NC_MIN_INT; /* [id] Variable ID for levgrnd */


=====================================
src/nco/nco_scm.c
=====================================
@@ -210,7 +210,7 @@ nco_nmn_get(void) /* [fnc] Return mnemonic that describes current NCO version */
   /* Purpose: Return mnemonic describing current NCO version
      20191221: ncremap/ncclimo print left quote and first word of this string, so one-word strings look best
      20200117: fixed this limitation, multi-word versions work fine */
-  return "Prime Rib";
+  return "Sea Shanty";
 } /* !nco_nmn_get() */
 
 void


=====================================
src/nco/ncrename.c
=====================================
@@ -410,6 +410,13 @@ main(int argc,char **argv)
   (void)nco_inq_format(nc_id,&fl_fmt);
   if(fl_fmt != NC_FORMAT_NETCDF4) rcd+=nco_redef(nc_id);
 
+  /* 20250208: WARN user about dicey types of renaming netCDF4 files */
+  if(fl_fmt == NC_FORMAT_NETCDF4 || fl_fmt == NC_FORMAT_NETCDF4_CLASSIC){
+    if(nbr_var_rnm || nbr_dmn_rnm){
+      if(nco_dbg_lvl >= nco_dbg_std) (void)fprintf(stdout,"%s: WARNING Renaming variables, dimensions, and attributes in any netCDF3-format file (i.e., classic, 64-bit, and CDF5) ALWAYS works. Moreover, renaming groups and attributes in any netCDF4-format file always works. However, these re-assuring notes precede a discomfitting message: A longstanding problem in the netCDF library (it is not an NCO issue per se) sometimes crashes %s or, even worse, silently corrupts data in the output file when input file is netCDF4-format. These outcomes are only known to occur when attempting to rename variables to/from the same names as dimensions (i.e., coordinate variables), and or dimensions to/from the same names as variables. If you are doing that, and the command completes, we suggest that you manually inspect the output coordinate values for corruption. A long thread describing the status of this issue since 2017 is at https://github.com/Unidata/netcdf-c/issues/597. A tedious chronology of the issue dating back to 2007 is at https://nco.sourceforge.net/nco.html#bug_nc4_rename.\n%s: HINT Do not expect this issue to be fixed in the near future :)\n%s: HINT There is a straightforward two- or three-step workaround that ALWAYS works: 1. Translate the file to any netCDF3 format (e.g., with \"ncks -5 in.nc out.nc\"). 2. Perform the renaming. 3. (Optional, only necessary if you wish to recover the netCDF4 features like compression) Translate back to a netCDF4-format (e.g., with \"ncks -7 in.nc out.nc\").\n",nco_prg_nm,nco_prg_nm,nco_prg_nm,nco_prg_nm);
+    } /* !nbr_var_rnm nbr_dmn_rnm */
+  } /* !fl_fmt */
+
   /* Timestamp end of metadata setup and disk layout */
   rcd+=nco_ddra((char *)NULL,(char *)NULL,&ddra_info);
   ddra_info.tmr_flg=nco_tmr_rgl;



View it on GitLab: https://salsa.debian.org/debian-gis-team/nco/-/commit/ef52a7661cce3218ce83b7b361fcbcb1efe0b207

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/nco/-/commit/ef52a7661cce3218ce83b7b361fcbcb1efe0b207
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20250329/3714b2a4/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list