[eccodes] 01/01: upstream release 2.4.1

Alastair McKinstry mckinstry at moszumanska.debian.org
Sun Aug 13 10:24:43 UTC 2017


This is an automated email from the git hooks/post-receive script.

mckinstry pushed a commit to tag upstream/2.4.1
in repository eccodes.

commit 1f30c780e8f1e69cc13c1e006549da6370e61ca3
Author: Alastair McKinstry <mckinstry at debian.org>
Date:   Sun Aug 13 11:21:38 2017 +0100

    upstream release 2.4.1
---
 CMakeLists.txt                                  |  42 ++--
 VERSION.cmake                                   |   2 +-
 cmake/FindGd.cmake                              |  59 ++++++
 cmake/FindPangoCairo.cmake                      |  25 ++-
 cmake/VERSION.cmake                             |   4 +-
 cmake/contrib/FindNetCDF4.cmake                 |   4 +-
 cmake/ecbuild_add_library.cmake                 |  56 ++---
 cmake/ecbuild_add_test.cmake                    |  48 ++---
 cmake/ecbuild_define_options.cmake              |   6 +
 cmake/ecbuild_find_package.cmake                |   4 +
 definitions/CMakeLists.txt                      |  36 ++--
 definitions/grib1/boot.def                      |   1 +
 definitions/grib2/section.6.def                 |  10 +-
 definitions/grib3/template.component.9.0.def    |   1 +
 definitions/mars/class.table                    |   1 +
 fortran/CMakeLists.txt                          |   7 +-
 ifs_samples/CMakeLists.txt                      |  15 +-
 samples/CMakeLists.txt                          |  10 +-
 share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake  |   6 +
 share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake   |   6 +
 share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake |   6 +
 src/CMakeLists.txt                              |   5 +-
 src/grib_accessor_class_bufr_data_array.c       |   5 +-
 src/grib_accessor_class_data_g22order_packing.c | 205 ++++++++++++++-----
 src/grib_accessor_class_offset_values.c         |  79 +++----
 src/grib_accessor_class_scale_values.c          |  80 ++++----
 src/grib_accessor_class_statistics.c            |  50 +++--
 src/grib_api_prototypes.h                       |   2 +-
 src/grib_api_version.c                          |   2 +-
 src/grib_bits.c                                 |  37 ++--
 src/grib_bits_any_endian.c                      |  14 +-
 src/grib_bits_fast_big_endian.c                 | 233 +++++++++++----------
 tests/grib_statistics.sh                        |  23 ++-
 tests/grib_util_set_spec.sh                     |  18 +-
 tools/grib_get_data.c                           |  54 ++++-
 tools/grib_histogram.c                          | 260 +++++++++++-------------
 tools/grib_to_netcdf.c                          |   6 +-
 version.sh                                      |   2 +-
 38 files changed, 872 insertions(+), 552 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2b0c3c5..db4cdeb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,13 +39,25 @@ ecbuild_add_option( FEATURE EXAMPLES
     DEFAULT ON
 )
 
+# controls installation of files in definitions/ -- note that it still creates the symlinks in the build dir
+ecbuild_add_option( FEATURE INSTALL_ECCODES_DEFINITIONS
+    DESCRIPTION "Install the ecCodes definitions"
+    DEFAULT ON
+)
+
+# controls installation of files in samples/ and ifs_samples/ -- note that it still creates the symlinks in the build dir
+ecbuild_add_option( FEATURE INSTALL_ECCODES_SAMPLES
+    DESCRIPTION "Install the ecCodes samples, including IFS samples"
+    DEFAULT ON
+)
+
 ecbuild_add_option( FEATURE JPG
-    DESCRIPTION "support for JPG decoding/encoding"
+    DESCRIPTION "Support for JPG decoding/encoding"
     DEFAULT ON
 )
 
 ecbuild_add_option( FEATURE PNG
-    DESCRIPTION "support for PNG decoding/encoding"
+    DESCRIPTION "Support for PNG decoding/encoding"
     DEFAULT OFF
     REQUIRED_PACKAGES PNG
 )
@@ -58,26 +70,26 @@ else()
 endif()
 
 ecbuild_add_option( FEATURE NETCDF
-    DESCRIPTION "support for GRIB to NetCDF conversion"
+    DESCRIPTION "Support for GRIB to NetCDF conversion"
     DEFAULT ON
     REQUIRED_PACKAGES NetCDF
     NO_TPL
 )
 
 ecbuild_add_option( FEATURE AEC
-    DESCRIPTION "support for Adaptive Entropy Coding"
+    DESCRIPTION "Support for Adaptive Entropy Coding"
     DEFAULT OFF
     REQUIRED_PACKAGES AEC
 )
 
 ecbuild_add_option( FEATURE PYTHON
-    DESCRIPTION "build the ecCodes Python interface"
+    DESCRIPTION "Build the ecCodes Python interface"
     DEFAULT ON
     REQUIRED_PACKAGES "Python VERSION 2.6 NO_LIBS" NumPy
 )
 
 ecbuild_add_option( FEATURE FORTRAN
-    DESCRIPTION "build the ecCodes Fortran interface"
+    DESCRIPTION "Build the ecCodes Fortran interface"
     DEFAULT ON
     # REQUIRED_LANGUAGES Fortran # TODO
 )
@@ -106,12 +118,12 @@ ecbuild_add_option( FEATURE MEMFS
 
 # advanced options (not visible in cmake-gui )
 
-ecbuild_add_option( FEATURE MEMORY_MANAGEMENT   DESCRIPTION "enable memory management" DEFAULT OFF ADVANCED )
-ecbuild_add_option( FEATURE ALIGN_MEMORY        DESCRIPTION "enable memory alignment"  DEFAULT OFF ADVANCED )
-ecbuild_add_option( FEATURE GRIB_TIMER          DESCRIPTION "enable timer" DEFAULT OFF ADVANCED )
-ecbuild_add_option( FEATURE ECCODES_THREADS     DESCRIPTION "enable POSIX threads" DEFAULT OFF ADVANCED )
-ecbuild_add_option( FEATURE ECCODES_OMP_THREADS DESCRIPTION "enable OMP threads" DEFAULT OFF ADVANCED )
-ecbuild_add_option( FEATURE EXTRA_TESTS         DESCRIPTION "enable extended regression testing" DEFAULT OFF ADVANCED )
+ecbuild_add_option( FEATURE MEMORY_MANAGEMENT   DESCRIPTION "Enable memory management" DEFAULT OFF ADVANCED )
+ecbuild_add_option( FEATURE ALIGN_MEMORY        DESCRIPTION "Enable memory alignment"  DEFAULT OFF ADVANCED )
+ecbuild_add_option( FEATURE GRIB_TIMER          DESCRIPTION "Enable timer" DEFAULT OFF ADVANCED )
+ecbuild_add_option( FEATURE ECCODES_THREADS     DESCRIPTION "Enable POSIX threads" DEFAULT OFF ADVANCED )
+ecbuild_add_option( FEATURE ECCODES_OMP_THREADS DESCRIPTION "Enable OMP threads" DEFAULT OFF ADVANCED )
+ecbuild_add_option( FEATURE EXTRA_TESTS         DESCRIPTION "Enable extended regression testing" DEFAULT OFF ADVANCED )
 
 ###############################################################################
 # macro processing
@@ -330,7 +342,7 @@ if( NOT PROJECT_NAME STREQUAL CMAKE_PROJECT_NAME )
   set( ECCODES_FOUND            TRUE PARENT_SCOPE )
   set( ECCODES_DEFINITIONS      ${ECCODES_DEFINITIONS}  PARENT_SCOPE )# includes already TPL definitions
   set( ECCODES_INCLUDE_DIRS     ${ECCODES_INCLUDE_DIRS} ${ECCODES_EXTRA_INCLUDE_DIRS} PARENT_SCOPE )
-  set( ECCODES_LIBRARIES        ${ECCODES_LIBRARIES}    ${ECCODES_EXTRA_LIBRARIES} ${CMATH_LIBRARIES} PARENT_SCOPE )
+  set( ECCODES_LIBRARIES        ${ECCODES_LIBRARIES}    ${ECCODES_EXTRA_LIBRARIES} PARENT_SCOPE )
   set( ECCODES_INSTALL_EXTRA_TOOLS  ${ECCODES_INSTALL_EXTRA_TOOLS} PARENT_SCOPE )
   set( ECCODES_DEFINITION_PATH  ${CMAKE_BINARY_DIR}/${ECCODES_DEFINITION_SUFF}  PARENT_SCOPE )
   set( ECCODES_SAMPLES_PATH     ${CMAKE_BINARY_DIR}/${ECCODES_SAMPLES_SUFF}     PARENT_SCOPE )
@@ -344,7 +356,7 @@ ecbuild_pkgconfig(
   DESCRIPTION    "The ecCodes library"
   LIBRARIES      eccodes
   IGNORE_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS} ${NETCDF_INCLUDE_DIRS}
-  VARIABLES      HAVE_JPEG HAVE_LIBJASPER HAVE_LIBOPENJPEG
+  VARIABLES      HAVE_MEMFS HAVE_JPEG HAVE_LIBJASPER HAVE_LIBOPENJPEG
                  HAVE_ECCODES_THREADS HAVE_ECCODES_OMP_THREADS
                  HAVE_NETCDF HAVE_PYTHON HAVE_FORTRAN HAVE_PNG HAVE_AEC
 )
@@ -356,7 +368,7 @@ if( EC_HAVE_FORTRAN )
     DESCRIPTION         "The ecCodes library for Fortran 90"
     IGNORE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/fortran ${PROJECT_BINARY_DIR}/fortran
                         ${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS} ${NETCDF_INCLUDE_DIRS}
-    VARIABLES           HAVE_JPEG HAVE_LIBJASPER HAVE_LIBOPENJPEG
+    VARIABLES           HAVE_MEMFS HAVE_JPEG HAVE_LIBJASPER HAVE_LIBOPENJPEG
                         HAVE_ECCODES_THREADS HAVE_ECCODES_OMP_THREADS
                         HAVE_NETCDF HAVE_PYTHON HAVE_PNG HAVE_AEC
   )
diff --git a/VERSION.cmake b/VERSION.cmake
index f2aa03f..973f50d 100644
--- a/VERSION.cmake
+++ b/VERSION.cmake
@@ -1 +1 @@
-set( ${PROJECT_NAME}_VERSION_STR  "2.4.0" )
+set( ${PROJECT_NAME}_VERSION_STR  "2.4.1" )
diff --git a/cmake/FindGd.cmake b/cmake/FindGd.cmake
new file mode 100644
index 0000000..01b2586
--- /dev/null
+++ b/cmake/FindGd.cmake
@@ -0,0 +1,59 @@
+# - Try to find the GD library
+# Once done this will define
+#
+# GD_FOUND - system has GD
+# GD_INCLUDE_DIRS - the GD include directory
+# GD_LIBRARIES - Link these to use GD
+#
+# Define GD_MIN_VERSION for which version desired.
+
+
+if( NOT DEFINED GD_PATH AND NOT "$ENV{GD_PATH}" STREQUAL "" )
+    set( APPEND GD_PATH "$ENV{GD_PATH}" )
+endif()
+
+if( NOT DEFINED GD_PATH )
+
+    include(FindPkgConfig)
+
+    if(GD_FIND_REQUIRED)
+        set(_pkgconfig_REQUIRED "REQUIRED")
+    else()
+        set(_pkgconfig_REQUIRED "")
+    endif()
+
+    if(GD_MIN_VERSION)
+        pkg_check_modules(PKGD ${_pkgconfig_REQUIRED} GD>=${GD_MIN_VERSION})
+    else()
+        pkg_check_modules(PKGD ${_pkgconfig_REQUIRED} GD)
+    endif()
+
+    if( PKG_CONFIG_FOUND AND PKGD_FOUND )
+
+        find_path(GD_INCLUDE_DIR gd.h HINTS ${PKGD_INCLUDEDIR} ${PKGD_INCLUDE_DIRS} PATH_SUFFIXES GD NO_DEFAULT_PATH )
+        find_library(GD_LIBRARY  gd   HINTS ${PKGD_LIBDIR}     ${PKGD_LIBRARY_DIRS} PATH_SUFFIXES GD NO_DEFAULT_PATH )
+
+    endif()
+
+else()
+
+    find_path(GD_INCLUDE_DIR gd.h PATHS ${GD_PATH}/include PATH_SUFFIXES GD NO_DEFAULT_PATH )
+    find_library(GD_LIBRARY  gd   PATHS ${GD_PATH}/lib     PATH_SUFFIXES GD NO_DEFAULT_PATH )
+
+endif()
+
+find_path(GD_INCLUDE_DIR gd.h PATH_SUFFIXES GD )
+find_library( GD_LIBRARY gd   PATH_SUFFIXES GD )
+
+set( GD_LIBRARIES    ${GD_LIBRARY} )
+set( GD_INCLUDE_DIRS ${GD_INCLUDE_DIR} )
+
+include(FindPackageHandleStandardArgs)
+
+# handle the QUIET and REQUIRED arguments and set GD_FOUND to TRUE
+# if all listed variables are TRUE
+# Note: capitalisation of the package name must be the same as in the file name
+find_package_handle_standard_args(GD  DEFAULT_MSG
+                                  GD_LIBRARY GD_INCLUDE_DIR)
+
+mark_as_advanced( GD_INCLUDE_DIR GD_LIBRARY )
diff --git a/cmake/FindPangoCairo.cmake b/cmake/FindPangoCairo.cmake
index cb70737..15e2da4 100644
--- a/cmake/FindPangoCairo.cmake
+++ b/cmake/FindPangoCairo.cmake
@@ -3,8 +3,8 @@
 # This software is licensed under the terms of the Apache Licence Version 2.0
 # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 # In applying this licence, ECMWF does not waive the privileges and immunities
-# granted to it by virtue of its status as an intergovernmental organisation nor
-# does it submit to any jurisdiction.
+# granted to it by virtue of its status as an intergovernmental organisation
+# nor does it submit to any jurisdiction.
 
 # - Try to find PangoCairo
 
@@ -40,8 +40,6 @@ else()
 
     # this is to get magics compiling on mac with macbrew
 
-    include(FindPackageHandleStandardArgs)
-
     set(PANGO_VERSION 1.0)
     set(GLIB_VERSION 2.0)
 
@@ -69,7 +67,7 @@ else()
         ${_CAIRO_INCLUDE_DIRS}
         ${_GLIB_INCLUDE_DIRS_1}
         ${_GLIB_INCLUDE_DIRS_2}
-	${X11_INCLUDE_DIR}
+        ${X11_INCLUDE_DIR}
     )
 
     find_library( _PANGOCAIRO_LIBRARIES NAMES pangocairo pangocairo-${PANGO_VERSION})
@@ -82,15 +80,26 @@ else()
         ${_PANGO_LIBRARIES}
         ${_CAIRO_LIBRARIES}
         ${_GLIB_LIBRARIES}
-	${X11_LIBRARIES}
+        ${X11_LIBRARIES}
     )
 
+    include(FindPackageHandleStandardArgs)
+
     # Handle the QUIET and REQUIRED arguments and set PANGOCAIRO_FOUND to TRUE
     # if all listed variables are TRUE
     # Note: capitalisation of the package name must be the same as in file name
     find_package_handle_standard_args( PangoCairo  DEFAULT_MSG
-                                       PANGOCAIRO_LIBRARIES
-                                       PANGOCAIRO_INCLUDE_DIRS  )
+                                       _PANGOCAIRO_INCLUDE_DIRS
+                                       _CAIRO_INCLUDE_DIRS
+                                       _GLIB_INCLUDE_DIRS_1
+                                       _GLIB_INCLUDE_DIRS_2
+                                       X11_INCLUDE_DIR
+                                       _PANGOCAIRO_LIBRARIES
+                                       _PANGO_LIBRARIES
+                                       _CAIRO_LIBRARIES
+                                       _GLIB_LIBRARIES
+                                       X11_LIBRARIES )
 
 endif()
 
+mark_as_advanced( PANGOCAIRO_INCLUDE_DIRS PANGOCAIRO_LIBRARIES )
diff --git a/cmake/VERSION.cmake b/cmake/VERSION.cmake
index af2b0d2..3449f42 100644
--- a/cmake/VERSION.cmake
+++ b/cmake/VERSION.cmake
@@ -1,7 +1,7 @@
 set( ECBUILD_MAJOR_VERSION "2" )
 set( ECBUILD_MINOR_VERSION "7" )
-set( ECBUILD_PATCH_VERSION "1" )
+set( ECBUILD_PATCH_VERSION "2" )
 
-set( ECBUILD_VERSION_STR  "2.7.1" )
+set( ECBUILD_VERSION_STR  "2.7.2" )
 
 set( ECBUILD_MACRO_VERSION "${ECBUILD_VERSION_STR}" )
diff --git a/cmake/contrib/FindNetCDF4.cmake b/cmake/contrib/FindNetCDF4.cmake
index 70e54af..d050f01 100644
--- a/cmake/contrib/FindNetCDF4.cmake
+++ b/cmake/contrib/FindNetCDF4.cmake
@@ -195,15 +195,13 @@ else()
             list( APPEND NETCDF_INCLUDE_DIRS ${NETCDF_${INC}_INCLUDE_DIR} )
           else()
             list( FIND NETCDF_REQUIRED ${INC} location )
-            if( ${location} EQUAL -1 )
-              else()
+            if( ${location} GREATER -1 )
               if(NETCDF_FIND_REQUIRED)
                 ecbuild_error( "\"${INC}\" is not found for NetCDF component ${LANGUAGE}" )
               elseif( NOT NETCDF_FIND_QUIETLY )
                 message( STATUS "\"${INC}\" is not found for NetCDF component ${LANGUAGE}" )
               endif()
               set( NETCDF_${LANGUAGE}_FOUND 0 )
-            else()
             endif()
           endif()
         endforeach()
diff --git a/cmake/ecbuild_add_library.cmake b/cmake/ecbuild_add_library.cmake
index f9f567f..9dfe25b 100644
--- a/cmake/ecbuild_add_library.cmake
+++ b/cmake/ecbuild_add_library.cmake
@@ -445,41 +445,45 @@ function( ecbuild_add_library_impl )
         set( _h_destination "${INSTALL_INCLUDE_DIR}" )
       endif()
 
-      if( _PAR_INSTALL_HEADERS )
-        if( _PAR_INSTALL_HEADERS MATCHES "LISTED" )
-          foreach( file ${${_PAR_TARGET}_h_srcs} )
-            get_filename_component( _file_dir ${file} PATH )
-            install( FILES ${file} DESTINATION "${_h_destination}/${_file_dir}" )
-          endforeach()
-          if( DEFINED _PAR_TEMPLATES )
-            foreach( file ${_PAR_TEMPLATES} )
+      if(ECBUILD_INSTALL_LIBRARY_HEADERS)
+
+        if( _PAR_INSTALL_HEADERS )
+          if( _PAR_INSTALL_HEADERS MATCHES "LISTED" )
+            foreach( file ${${_PAR_TARGET}_h_srcs} )
               get_filename_component( _file_dir ${file} PATH )
               install( FILES ${file} DESTINATION "${_h_destination}/${_file_dir}" )
             endforeach()
+            if( DEFINED _PAR_TEMPLATES )
+              foreach( file ${_PAR_TEMPLATES} )
+                get_filename_component( _file_dir ${file} PATH )
+                install( FILES ${file} DESTINATION "${_h_destination}/${_file_dir}" )
+              endforeach()
+            endif()
+            if( DEFINED _PAR_PERSISTENT )
+              foreach( file ${_PAR_PERSISTENT} )
+                get_filename_component( _file_dir ${file} PATH )
+                get_filename_component( _file_we  ${file} NAME_WE )
+                set( pfile "${CMAKE_CURRENT_BINARY_DIR}/${_file_dir}/${_file_we}.b" )
+                install( FILES ${pfile} DESTINATION "${_h_destination}/${_file_dir}" )
+              endforeach()
+            endif()
           endif()
-          if( DEFINED _PAR_PERSISTENT )
-            foreach( file ${_PAR_PERSISTENT} )
-              get_filename_component( _file_dir ${file} PATH )
-              get_filename_component( _file_we  ${file} NAME_WE )
-              set( pfile "${CMAKE_CURRENT_BINARY_DIR}/${_file_dir}/${_file_we}.b" )
-              install( FILES ${pfile} DESTINATION "${_h_destination}/${_file_dir}" )
-            endforeach()
+          if( _PAR_INSTALL_HEADERS MATCHES "ALL" ) # "(\\.h|\\.b|\\.hxx|\\.hh|\\.hpp|\\.H)" ????
+            install( DIRECTORY ./  DESTINATION ${_h_destination} FILES_MATCHING PATTERN "*.h" )
+            install( DIRECTORY ./  DESTINATION ${_h_destination} FILES_MATCHING PATTERN "*.hh" )
+            install( DIRECTORY ./  DESTINATION ${_h_destination} FILES_MATCHING PATTERN "*.hpp" )
+            install( DIRECTORY ./  DESTINATION ${_h_destination} FILES_MATCHING PATTERN "*.H" )
           endif()
         endif()
-        if( _PAR_INSTALL_HEADERS MATCHES "ALL" ) # "(\\.h|\\.b|\\.hxx|\\.hh|\\.hpp|\\.H)" ????
-          install( DIRECTORY ./  DESTINATION ${_h_destination} FILES_MATCHING PATTERN "*.h" )
-          install( DIRECTORY ./  DESTINATION ${_h_destination} FILES_MATCHING PATTERN "*.hh" )
-          install( DIRECTORY ./  DESTINATION ${_h_destination} FILES_MATCHING PATTERN "*.hpp" )
-          install( DIRECTORY ./  DESTINATION ${_h_destination} FILES_MATCHING PATTERN "*.H" )
+
+        if( DEFINED _PAR_INSTALL_HEADERS_LIST )
+          install( FILES ${_PAR_INSTALL_HEADERS_LIST} DESTINATION ${_h_destination} )
         endif()
-      endif()
 
-      if( DEFINED _PAR_INSTALL_HEADERS_LIST )
-        install( FILES ${_PAR_INSTALL_HEADERS_LIST} DESTINATION ${_h_destination} )
-      endif()
+        if( DEFINED _PAR_INSTALL_HEADERS_REGEX )
+          install( DIRECTORY ./  DESTINATION ${_h_destination} FILES_MATCHING PATTERN "${_PAR_INSTALL_HEADERS_REGEX}")
+        endif()
 
-      if( DEFINED _PAR_INSTALL_HEADERS_REGEX )
-        install( DIRECTORY ./  DESTINATION ${_h_destination} FILES_MATCHING PATTERN "${_PAR_INSTALL_HEADERS_REGEX}")
       endif()
 
       # set build location
diff --git a/cmake/ecbuild_add_test.cmake b/cmake/ecbuild_add_test.cmake
index da0bd22..7050159 100644
--- a/cmake/ecbuild_add_test.cmake
+++ b/cmake/ecbuild_add_test.cmake
@@ -224,30 +224,6 @@ macro( ecbuild_add_test )
     endif()
   endif()
 
-  if( _PAR_TYPE MATCHES "PYTHON" )
-    if( PYTHONINTERP_FOUND )
-      set( _PAR_COMMAND ${PYTHON_EXECUTABLE} )
-      set( _PAR_LABELS python ${_PAR_LABELS} )
-    else()
-      ecbuild_warn( "Requested a python test but python interpreter not found - disabling test\nPYTHON_EXECUTABLE: [${PYTHON_EXECUTABLE}]" )
-      set( _PAR_ENABLED 0 )
-    endif()
-  endif()
-
-  ### further checks
-
-  if( _PAR_ENABLED AND NOT _PAR_TARGET AND NOT _PAR_COMMAND )
-    ecbuild_critical("The call to ecbuild_add_test() defines neither a TARGET nor a COMMAND.")
-  endif()
-
-  if( _PAR_ENABLED AND NOT _PAR_COMMAND AND NOT _PAR_SOURCES )
-    ecbuild_critical("The call to ecbuild_add_test() defines neither a COMMAND nor SOURCES, so no test can be defined or built.")
-  endif()
-
-  if( _PAR_TYPE MATCHES "SCRIPT" AND NOT _PAR_COMMAND )
-    ecbuild_critical("The call to ecbuild_add_test() defines a 'script' but doesn't specify the COMMAND.")
-  endif()
-
   ### conditional build
 
   if( DEFINED _PAR_CONDITION )
@@ -285,6 +261,30 @@ macro( ecbuild_add_test )
 
   if( ENABLE_TESTS AND _${_PAR_TARGET}_condition )
 
+    if( _PAR_TYPE MATCHES "PYTHON" )
+      if( PYTHONINTERP_FOUND )
+        set( _PAR_COMMAND ${PYTHON_EXECUTABLE} )
+        set( _PAR_LABELS python ${_PAR_LABELS} )
+      else()
+        ecbuild_warn( "Requested a python test but python interpreter not found - disabling test\nPYTHON_EXECUTABLE: [${PYTHON_EXECUTABLE}]" )
+        set( _PAR_ENABLED 0 )
+      endif()
+    endif()
+
+    ### further checks
+
+    if( _PAR_ENABLED AND NOT _PAR_TARGET AND NOT _PAR_COMMAND )
+      ecbuild_critical("The call to ecbuild_add_test() defines neither a TARGET nor a COMMAND.")
+    endif()
+
+    if( _PAR_ENABLED AND NOT _PAR_COMMAND AND NOT _PAR_SOURCES )
+      ecbuild_critical("The call to ecbuild_add_test() defines neither a COMMAND nor SOURCES, so no test can be defined or built.")
+    endif()
+
+    if( _PAR_TYPE MATCHES "SCRIPT" AND NOT _PAR_COMMAND )
+      ecbuild_critical("The call to ecbuild_add_test() defines a 'script' but doesn't specify the COMMAND.")
+    endif()
+
     # add resources
 
     if( DEFINED _PAR_RESOURCES )
diff --git a/cmake/ecbuild_define_options.cmake b/cmake/ecbuild_define_options.cmake
index fc6376e..cf5ff00 100644
--- a/cmake/ecbuild_define_options.cmake
+++ b/cmake/ecbuild_define_options.cmake
@@ -33,6 +33,12 @@ option( CHECK_UNUSED_FILES       "check for unused project files (slow)"  OFF )
 mark_as_advanced( DEVELOPER_MODE  )
 mark_as_advanced( CHECK_UNUSED_FILES  )
 
+option( ECBUILD_INSTALL_LIBRARY_HEADERS "Will install library headers" ON )
+mark_as_advanced( ECBUILD_INSTALL_LIBRARY_HEADERS )
+
+option( ECBUILD_INSTALL_FORTRAN_MODULES "Will install Fortran modules" ON )
+mark_as_advanced( ECBUILD_INSTALL_FORTRAN_MODULES )
+
 include( CMakeDependentOption ) # make options depend on one another
 
 cmake_dependent_option( ENABLE_OS_TYPES_TEST     "Run sizeof tests on C types" ON "ENABLE_OS_TESTS" OFF)
diff --git a/cmake/ecbuild_find_package.cmake b/cmake/ecbuild_find_package.cmake
index b69741e..3f5d72a 100644
--- a/cmake/ecbuild_find_package.cmake
+++ b/cmake/ecbuild_find_package.cmake
@@ -125,6 +125,10 @@ macro( ecbuild_find_package )
     ecbuild_critical("Call to ecbuild_find_package() requests EXACT but doesn't specify VERSION.")
   endif()
 
+  if( _PAR_QUIET )
+    set( _find_quiet QUIET )
+  endif()
+
   # If the package is required, set TYPE to REQUIRED
   # Due to shortcomings in CMake's argument parser, passing TYPE REQUIRED has no effect
   if( _PAR_REQUIRED )
diff --git a/definitions/CMakeLists.txt b/definitions/CMakeLists.txt
index b01e14c..5ddcb11 100644
--- a/definitions/CMakeLists.txt
+++ b/definitions/CMakeLists.txt
@@ -5,22 +5,26 @@ set(definition_files ${definition_files} PARENT_SCOPE) # needed for memfs
 file( GLOB table_files      RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.table" )
 file( GLOB text_files       RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.txt" )
 
-install( FILES ${definition_files} ${table_files} ${text_files}
-         DESTINATION ${ECCODES_DEFINITION_SUFF}
-         PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ )
-
-install( FILES installDefinitions.sh
-         DESTINATION ${ECCODES_DEFINITION_SUFF})
-
-install(  DIRECTORY budg bufr cdf common grib1 grib2 grib3 gts mars metar tide hdf5 wrap
-          DESTINATION ${ECCODES_DEFINITION_SUFF}
-          FILES_MATCHING 
-          PATTERN "*.def"
-          PATTERN "*.txt"
-          PATTERN "*.list"
-          PATTERN "*.table"
-          PATTERN "4.2.192.*.table" EXCLUDE
-          PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ )
+if(HAVE_INSTALL_ECCODES_DEFINITIONS)
+
+  install( FILES ${definition_files} ${table_files} ${text_files}
+           DESTINATION ${ECCODES_DEFINITION_SUFF}
+           PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ )
+
+  install( FILES installDefinitions.sh
+           DESTINATION ${ECCODES_DEFINITION_SUFF})
+
+  install(  DIRECTORY budg bufr cdf common grib1 grib2 grib3 gts mars metar tide hdf5 wrap
+            DESTINATION ${ECCODES_DEFINITION_SUFF}
+            FILES_MATCHING
+            PATTERN "*.def"
+            PATTERN "*.txt"
+            PATTERN "*.list"
+            PATTERN "*.table"
+            PATTERN "4.2.192.*.table" EXCLUDE
+            PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ )
+
+endif()
 
 # link to the definitions. See GRIB-786
 file( MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/${INSTALL_DATA_DIR} )
diff --git a/definitions/grib1/boot.def b/definitions/grib1/boot.def
index a924b6c..501f761 100644
--- a/definitions/grib1/boot.def
+++ b/definitions/grib1/boot.def
@@ -45,6 +45,7 @@ meta GDSPresent gds_is_present(gridDescriptionSectionPresent,gridDefinition,bitm
 flagbit bitmapPresent(section1Flags,6) :dump;
 alias bitmapSectionPresent=bitmapPresent;
 alias geography.bitmapPresent=bitmapPresent;
+alias missingValuesPresent=bitmapPresent : read_only;
 transient angularPrecision=1000;  # milli degrees
 
 if(gridDescriptionSectionPresent){
diff --git a/definitions/grib2/section.6.def b/definitions/grib2/section.6.def
index ac24601..5e91955 100644
--- a/definitions/grib2/section.6.def
+++ b/definitions/grib2/section.6.def
@@ -27,11 +27,11 @@ codetable[1] bitMapIndicator ('6.0.table',masterDir,localDir) = 255 : dump;
 
 #transient bitmapPresent=1;
 meta geography.bitmapPresent g2bitmap_present(bitMapIndicator): dump;
+transient missingValuesPresent = bitmapPresent : hidden, read_only;
 
 # Bitmap...
 if(bitMapIndicator == 0)
 {
-
   if(dataRepresentationTemplateNumber == 1)
   {
     if(matrixBitmapsPresent == 1)
@@ -61,4 +61,12 @@ if(bitMapIndicator == 0)
   }
 }
 
+if(bitMapIndicator == 255)
+{
+  # No bitmap is used but some complex packing schemes embed the missing values in the data section
+  if (dataRepresentationTemplateNumber == 2 || dataRepresentationTemplateNumber == 3) {
+    transient missingValuesPresent = (missingValueManagementUsed != 0) : read_only;
+  }
+}
+
 meta md5Section6 md5(offsetSection6,section6Length);
diff --git a/definitions/grib3/template.component.9.0.def b/definitions/grib3/template.component.9.0.def
index 8354b51..32ce023 100644
--- a/definitions/grib3/template.component.9.0.def
+++ b/definitions/grib3/template.component.9.0.def
@@ -7,6 +7,7 @@
 codetable[1] bitMapIndicator ('6.0.table',masterDir,localDir) = 255 : dump;
 
 meta geography.bitmapPresent g2bitmap_present(bitMapIndicator): dump;
+transient missingValuesPresent = bitmapPresent : hidden;
 
 # Bitmap...
 if(bitMapIndicator == 0)
diff --git a/definitions/mars/class.table b/definitions/mars/class.table
index ce9460c..2749a00 100644
--- a/definitions/mars/class.table
+++ b/definitions/mars/class.table
@@ -31,6 +31,7 @@
 30 et CERA-SAT: ERA-CLIM2 coupled reanalysis of the satellite era
 31 c3 C3S: Copernicus Climate Change Service
 32 yp YOPP
+33 l5 ERA5L: ERA5 of land surface parameters
 99 te Test
 100 at Austria
 101 be Belgium
diff --git a/fortran/CMakeLists.txt b/fortran/CMakeLists.txt
index 0aa962f..e815550 100644
--- a/fortran/CMakeLists.txt
+++ b/fortran/CMakeLists.txt
@@ -66,7 +66,7 @@ if( HAVE_FORTRAN )
     #add_custom_target(add_eccodes_mod ALL DEPENDS ${_eccodes_mod})
 
     ecbuild_add_resources( TARGET fortran_resources
-                           PACK 
+                           PACK
                             grib_fortran_prototypes.h grib_api_constants.h grib_api_externals.h
                             grib_api_visibility.h grib_types.f90 create_grib_f90.sh
                             grib_f90.f90.head grib_f90.f90.tail grib_f90_int.f90 grib_f90_long_int.f90
@@ -87,8 +87,9 @@ if( HAVE_FORTRAN )
     # install( CODE "EXECUTE_PROCESS (COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_Fortran_MODULE_DIRECTORY}/${CMAKE_CFG_INTDIR} ${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR})" )
 
     # Install the contents of the fortran module directory
-    install( DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY}/${CMAKE_CFG_INTDIR}/
-                     DESTINATION ${INSTALL_INCLUDE_DIR} )
+    if(ECBUILD_INSTALL_FORTRAN_MODULES)
+        install( DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY}/${CMAKE_CFG_INTDIR}/  DESTINATION ${INSTALL_INCLUDE_DIR} )
+    endif()
 
     # Install the eccodes module file as a copy of the grib api mod file.
     # Note: the mod filename can be lowercase or uppercase!
diff --git a/ifs_samples/CMakeLists.txt b/ifs_samples/CMakeLists.txt
index eb2507a..1e25c2f 100644
--- a/ifs_samples/CMakeLists.txt
+++ b/ifs_samples/CMakeLists.txt
@@ -1,15 +1,20 @@
 function( install_samples samples destination_install destination_build )
   set( _samples ${${samples}} )
-  # To install the samples
-  install( FILES  ${_samples}
-           DESTINATION ${destination_install}
-           PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ )
+
+  if(HAVE_INSTALL_ECCODES_SAMPLES)
+
+    # To install the samples
+    install( FILES  ${_samples}
+             DESTINATION ${destination_install}
+             PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ )
+
+  endif()
 
   # To symlink the samples to the build-dir for developers
   execute_process( COMMAND ${CMAKE_COMMAND} -E make_directory ${destination_build} )
   foreach( _file ${_samples} )
     get_filename_component(_filename ${_file} NAME)
-    execute_process( COMMAND ${CMAKE_COMMAND} -E create_symlink 
+    execute_process( COMMAND ${CMAKE_COMMAND} -E create_symlink
        ${_file} ${destination_build}/${_filename} )
   endforeach()
 endfunction()
diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt
index 1a84b31..2dbf37b 100644
--- a/samples/CMakeLists.txt
+++ b/samples/CMakeLists.txt
@@ -1,12 +1,14 @@
 file( GLOB samples_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.tmpl" )
 
-install( FILES ${samples_files}
-         DESTINATION ${ECCODES_SAMPLES_SUFF}
-         PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ )
+if(HAVE_INSTALL_ECCODES_SAMPLES)
+    install( FILES ${samples_files}
+             DESTINATION ${ECCODES_SAMPLES_SUFF}
+             PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ )
+endif()
 
 foreach( tmpl ${samples_files} )
     list( APPEND ECCODES_SAMPLES_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${tmpl} )
-endforeach() 
+endforeach()
 
 set( ECCODES_SAMPLES_DIR   ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE )
 set( ECCODES_SAMPLES_FILES ${ECCODES_SAMPLES_FILES}    PARENT_SCOPE )
diff --git a/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake b/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake
index be3ed8f..a4d1813 100644
--- a/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake
+++ b/share/ecbuild/toolchains/ecmwf-XC30-Cray.cmake
@@ -3,6 +3,11 @@
 ####################################################################
 
 set( EC_HAVE_C_INLINE 1 )
+set( EC_HAVE_FUNCTION_DEF 1 )
+set( EC_HAVE_CXXABI_H 1 )
+set( EC_HAVE_CXX_BOOL 1 )
+set( EC_HAVE_CXX_SSTREAM 1 )
+set( EC_HAVE_CXX_INT_128 0 )
 set( CMAKE_SIZEOF_VOID_P 8 )
 set( EC_SIZEOF_PTR 8 )
 set( EC_SIZEOF_CHAR 1 )
@@ -83,6 +88,7 @@ set( EC_HAVE_GMTIME_R 1 )
 set( EC_HAVE_GETPWUID_R 1 )
 set( EC_HAVE_GETPWNAM_R 1 )
 set( EC_HAVE_READDIR_R 1 )
+set( EC_HAVE_DIRENT_D_TYPE 1 )
 set( EC_HAVE_GETHOSTBYNAME_R 1 )
 set( EC_HAVE_ATTRIBUTE_CONSTRUCTOR 1 )
 set( EC_ATTRIBUTE_CONSTRUCTOR_INITS_ARGV 0 )
diff --git a/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake b/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake
index 5acd12e..d98fe29 100644
--- a/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake
+++ b/share/ecbuild/toolchains/ecmwf-XC30-GNU.cmake
@@ -3,6 +3,11 @@
 ####################################################################
 
 set( EC_HAVE_C_INLINE 1 )
+set( EC_HAVE_FUNCTION_DEF 1 )
+set( EC_HAVE_CXXABI_H 1 )
+set( EC_HAVE_CXX_BOOL 1 )
+set( EC_HAVE_CXX_SSTREAM 1 )
+set( EC_HAVE_CXX_INT_128 1 )
 set( CMAKE_SIZEOF_VOID_P 8 )
 set( EC_SIZEOF_PTR 8 )
 set( EC_SIZEOF_CHAR 1 )
@@ -83,6 +88,7 @@ set( EC_HAVE_GMTIME_R 1 )
 set( EC_HAVE_GETPWUID_R 1 )
 set( EC_HAVE_GETPWNAM_R 1 )
 set( EC_HAVE_READDIR_R 1 )
+set( EC_HAVE_DIRENT_D_TYPE 1 )
 set( EC_HAVE_GETHOSTBYNAME_R 1 )
 set( EC_HAVE_ATTRIBUTE_CONSTRUCTOR 1 )
 set( EC_ATTRIBUTE_CONSTRUCTOR_INITS_ARGV 0 )
diff --git a/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake b/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake
index 8e6b41d..042d3da 100644
--- a/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake
+++ b/share/ecbuild/toolchains/ecmwf-XC30-Intel.cmake
@@ -3,6 +3,11 @@
 ####################################################################
 
 set( EC_HAVE_C_INLINE 1 )
+set( EC_HAVE_FUNCTION_DEF 1 )
+set( EC_HAVE_CXXABI_H 1 )
+set( EC_HAVE_CXX_BOOL 1 )
+set( EC_HAVE_CXX_SSTREAM 1 )
+set( EC_HAVE_CXX_INT_128 1 )
 set( CMAKE_SIZEOF_VOID_P 8 )
 set( EC_SIZEOF_PTR 8 )
 set( EC_SIZEOF_CHAR 1 )
@@ -83,6 +88,7 @@ set( EC_HAVE_GMTIME_R 1 )
 set( EC_HAVE_GETPWUID_R 1 )
 set( EC_HAVE_GETPWNAM_R 1 )
 set( EC_HAVE_READDIR_R 1 )
+set( EC_HAVE_DIRENT_D_TYPE 1 )
 set( EC_HAVE_GETHOSTBYNAME_R 1 )
 set( EC_HAVE_ATTRIBUTE_CONSTRUCTOR 1 )
 set( EC_ATTRIBUTE_CONSTRUCTOR_INITS_ARGV 0 )
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 04b8c75..f385bb5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -432,9 +432,8 @@ ecbuild_add_library(TARGET    eccodes
                               # griby.c gribl.c
                              ${grib_api_srcs}
                     GENERATED grib_api_version.c
-                    LIBS      ${ECCODES_EXTRA_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
-                    TEMPLATES ${grib_api_extra_srcs}
-                    ${CMATH_LIBRARIES}  )
+                    LIBS      ${ECCODES_EXTRA_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${CMATH_LIBRARIES}
+                    TEMPLATES ${grib_api_extra_srcs})
 
 
 install( FILES grib_api.h eccodes.h eccodes_windef.h DESTINATION ${INSTALL_INCLUDE_DIR} )
diff --git a/src/grib_accessor_class_bufr_data_array.c b/src/grib_accessor_class_bufr_data_array.c
index 0cb4d05..e1d1fe8 100644
--- a/src/grib_accessor_class_bufr_data_array.c
+++ b/src/grib_accessor_class_bufr_data_array.c
@@ -919,7 +919,7 @@ static int decode_element(grib_context* c,grib_accessor_bufr_data_array* self,in
         double new_ref_val = (double)grib_decode_signed_longb(data, pos, number_of_bits);
         grib_context_log(c, GRIB_LOG_DEBUG,"BUFR data decoding: -**- \tcode=203YYY width=%ld pos=%ld -> %ld",
                 number_of_bits,(long)*pos,(long)(*pos-a->offset*8));
-        grib_context_log(c, GRIB_LOG_DEBUG, "Operator 203YYY: Store %ld = %g", bd->code, new_ref_val);
+        grib_context_log(c, GRIB_LOG_DEBUG, "Operator 203YYY: Store for code %6.6ld => new ref val %g", bd->code, new_ref_val);
         tableB_override_store_ref_val(c, self, bd->code, new_ref_val);
         bd->nokey=1;
         err=check_end_data(c, self, number_of_bits); /*advance bitsToEnd*/
@@ -957,7 +957,7 @@ static int decode_element(grib_context* c,grib_accessor_bufr_data_array* self,in
         /* numeric or codetable or flagtable */
         /* Operator 203: Check if we have changed ref value for this element. If so modify bd->reference */
         if (self->change_ref_value_operand!=0 && tableB_override_get_ref_val(self, bd->code, &(bd->reference)) == GRIB_SUCCESS) {
-            grib_context_log(c, GRIB_LOG_DEBUG,"Operator 203YYY: Changed ref val: %g\n", bd->reference);
+            grib_context_log(c, GRIB_LOG_DEBUG,"Operator 203YYY: For code %6.6ld, changed ref val: %g", bd->code, bd->reference);
         }
 
         if (self->compressedData) {
@@ -995,6 +995,7 @@ static int decode_replication(grib_context* c,grib_accessor_bufr_data_array* sel
           grib_context_log(c, GRIB_LOG_DEBUG,"BUFR data decoding: \tdelayed replication localWidth width=6");
           width=grib_decode_unsigned_long(data,pos,6);
           if (width) {
+              grib_context_log(c, GRIB_LOG_DEBUG,"BUFR data decoding: \tdelayed replication is NOT constant for compressed data!");
             /* delayed replication number is not constant. NOT IMPLEMENTED */
             return GRIB_NOT_IMPLEMENTED;
           } else {
diff --git a/src/grib_accessor_class_data_g22order_packing.c b/src/grib_accessor_class_data_g22order_packing.c
index 535d012..3db7d94 100644
--- a/src/grib_accessor_class_data_g22order_packing.c
+++ b/src/grib_accessor_class_data_g22order_packing.c
@@ -240,12 +240,15 @@ static int      reverse_rows (unsigned long* data, long  len, long number_along_
 }
 #endif
 
-static unsigned long calc_pow_2(unsigned long op){
+static unsigned long calc_pow_2(unsigned long op)
+{
     unsigned long a = 1;
     while(op--) a*=2;
     return a;
 }
-static int calc_bits_needed(unsigned long spread){
+
+static int calc_bits_needed(unsigned long spread)
+{
     int nbit = 0;
     if (spread == 0) return nbit;
     while (spread>0){
@@ -254,14 +257,15 @@ static int calc_bits_needed(unsigned long spread){
     }
     return nbit;
 }
-static int find_next_group(const unsigned long* vals, size_t len, unsigned long w, unsigned long l,long* nbits, long* groupsize, long* r_val){
+
+static int find_next_group(const unsigned long* vals, size_t len, unsigned long w, unsigned long l,long* nbits, long* groupsize, long* r_val)
+{
     unsigned long lmin = 0;
     unsigned long lmax = 0;
 
     size_t i = 0;
 
-
-    if  (len <=0 ) return GRIB_ARRAY_TOO_SMALL;
+    if  (len == 0) return GRIB_ARRAY_TOO_SMALL;
     lmin = vals[0];
     lmax = lmin;
 
@@ -334,8 +338,59 @@ static int spatial_difference (grib_context *c, unsigned long* vals, long  len,
 }
 #endif
 
-static int de_spatial_difference (grib_context *c, unsigned long* vals, long  len, long order, long bias){
+static int post_process(grib_context *c, long* vals, long  len, long order, long bias, unsigned long extras[2])
+{
+    unsigned long last, penultimate, j=0;
+    Assert(order > 0);
+    Assert(order <= 3);
+
+    if (order == 1) {
+        last = extras[0];
+        while (j < len) {
+            if (vals[j] == LONG_MAX) j++;
+            else {
+                vals[j++] = extras[0]; break;
+            }
+        }
+        while (j < len) {
+            if (vals[j] == LONG_MAX) j++;
+            else {
+                vals[j] += last + bias;
+                last = vals[j++];
+            }
+        }
+    }
+    else if (order == 2) {
+        penultimate = extras[0];
+        last = extras[1];
+        while (j < len) {
+            if (vals[j] == LONG_MAX) j++;
+            else {
+                vals[j++] = extras[0];
+                break;
+            }
+        }
+        while (j < len) {
+            if (vals[j] == LONG_MAX) j++;
+            else {
+                vals[j++] = extras[1];
+                break;
+            }
+        }
+        for (; j < len; j++) {
+            if (vals[j] != LONG_MAX) {
+                vals[j] = vals[j] + bias + last + last - penultimate;
+                penultimate = last;
+                last = vals[j];
+            }
+        }
+    }
+    return GRIB_SUCCESS;
+}
 
+#if 0
+static int de_spatial_difference (grib_context *c, unsigned long* vals, long  len, long order, long bias)
+{
     long j = 0;
 
     long i_origin = 0;
@@ -375,6 +430,7 @@ static int de_spatial_difference (grib_context *c, unsigned long* vals, long  le
     }
     return 0;
 }
+#endif
 
 static int unpack_double(grib_accessor* a, double* val, size_t *len)
 {
@@ -386,7 +442,7 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len)
     long     vcount = 0;
     int      err = GRIB_SUCCESS;
 
-    unsigned long*  sec_val    = NULL;
+    long* sec_val = NULL;
     grib_handle* gh = grib_handle_of_accessor(a);
 
     unsigned char*  buf = (unsigned char*)gh->buffer->data;
@@ -425,6 +481,7 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len)
     long numberOfBitsUsedForTheScaledGroupLengths;
     long orderOfSpatialDifferencing;
     long numberOfOctetsExtraDescriptors;
+    double missingValue=0;
 
     err=grib_value_count(a,&n_vals);
     if (err) return err;
@@ -448,34 +505,12 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len)
     if((err = grib_get_long_internal(gh,self->numberOfBitsUsedForTheScaledGroupLengths,&numberOfBitsUsedForTheScaledGroupLengths )) != GRIB_SUCCESS)  return err;
     if((err = grib_get_long_internal(gh,self->orderOfSpatialDifferencing,&orderOfSpatialDifferencing )) != GRIB_SUCCESS)  return err;
     if((err = grib_get_long_internal(gh,self->numberOfOctetsExtraDescriptors,&numberOfOctetsExtraDescriptors )) != GRIB_SUCCESS)  return err;
+    if((err = grib_get_double_internal(gh,"missingValue", &missingValue)) != GRIB_SUCCESS) return err;
 
     self->dirty=0;
 
-    /* I have everything now start decoding     */
-    /*
-     fprintf(stdout,"\n****************************************\n");
-     fprintf(stdout," bits_per_value = %d\n", bits_per_value);
-     fprintf(stdout," reference_value = %g\n", reference_value);
-     fprintf(stdout," binary_scale_factor = %d\n", binary_scale_factor);
-     fprintf(stdout," decimal_scale_factor = %d\n", decimal_scale_factor);
-     fprintf(stdout," typeOfOriginalFieldValues = %d\n", typeOfOriginalFieldValues);
-     fprintf(stdout," groupSplittingMethodUsed = %d\n", groupSplittingMethodUsed);
-     fprintf(stdout," missingValueManagementUsed = %d\n", missingValueManagementUsed);
-     fprintf(stdout," primaryMissingValueSubstitute = %d\n", primaryMissingValueSubstitute);
-     fprintf(stdout," secondaryMissingValueSubstitute = %d\n", secondaryMissingValueSubstitute);
-     fprintf(stdout," numberOfGroupsOfDataValues = %d\n", numberOfGroupsOfDataValues);
-     fprintf(stdout," referenceForGroupWidths = %d\n", referenceForGroupWidths);
-     fprintf(stdout," numberOfBitsUsedForTheGroupWidths = %d\n", numberOfBitsUsedForTheGroupWidths);
-     fprintf(stdout," referenceForGroupLengths = %d\n", referenceForGroupLengths);
-     fprintf(stdout," lengthIncrementForTheGroupLengths = %d\n", lengthIncrementForTheGroupLengths);
-     fprintf(stdout," trueLengthOfLastGroup = %d\n", trueLengthOfLastGroup);
-     fprintf(stdout," numberOfBitsUsedForTheScaledGroupLengths = %d\n", numberOfBitsUsedForTheScaledGroupLengths);
-     fprintf(stdout," numberOfOctetsExtraDescriptors = %d\n", numberOfOctetsExtraDescriptors);
-     fprintf(stdout," orderOfSpatialDifferencing = %d\n", orderOfSpatialDifferencing);
-     fprintf(stdout,"\n****************************************\n");
-     */
-    sec_val     =   (unsigned long*)grib_context_malloc(a->context,(n_vals)*sizeof(unsigned long));
-    if (sec_val) memset(sec_val, 0, (n_vals)*sizeof(unsigned long)); /* See SUP-718 */
+    sec_val = (long*)grib_context_malloc(a->context,(n_vals)*sizeof(long));
+    if (sec_val) memset(sec_val, 0, (n_vals)*sizeof(long)); /* See SUP-718 */
 
     buf_ref     =   buf + a->offset ;
 
@@ -483,13 +518,13 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len)
 
     if(orderOfSpatialDifferencing)  ref_p += (1+orderOfSpatialDifferencing)*(numberOfOctetsExtraDescriptors*8);
 
-    buf_width   =  buf_ref + (ref_p/8)      + (ref_p%8?1:0);
+    buf_width   =  buf_ref + (ref_p/8) + ((ref_p%8) ? 1 : 0);
 
     width_p     =  (numberOfGroupsOfDataValues*numberOfBitsUsedForTheGroupWidths);
-    buf_length  =  buf_width + (width_p/8)   + (width_p%8?1:0);
+    buf_length  =  buf_width + (width_p/8) + ((width_p%8) ? 1 : 0);
 
     length_p    =  (numberOfGroupsOfDataValues*numberOfBitsUsedForTheScaledGroupLengths);
-    buf_vals    =  buf_length + (length_p/8) + (length_p%8?1:0);
+    buf_vals    =  buf_length + (length_p/8) + ((length_p%8) ? 1 : 0);
 
     length_p = 0;
     ref_p    = orderOfSpatialDifferencing?(orderOfSpatialDifferencing+1)*(numberOfOctetsExtraDescriptors*8):0;
@@ -497,7 +532,7 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len)
     vals_p   = 0;
     vcount   = 0;
 
-    for(i=0;i < numberOfGroupsOfDataValues;i++){
+    for (i=0;i < numberOfGroupsOfDataValues;i++) {
         group_ref_val        =  grib_decode_unsigned_long(buf_ref,&ref_p, bits_per_value);
         nvals_per_group      =  grib_decode_unsigned_long(buf_length, &length_p,numberOfBitsUsedForTheScaledGroupLengths);
         nbits_per_group_val  =  grib_decode_unsigned_long(buf_width,  &width_p,   numberOfBitsUsedForTheGroupWidths);
@@ -511,31 +546,103 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len)
 
         /*grib_decode_long_array(buf_vals, &vals_p, nbits_per_group_val, nvals_per_group,
                                &sec_val[vcount]); */
-        for(j=0; j < nvals_per_group;j++){
-            sec_val[vcount+j] = group_ref_val + grib_decode_unsigned_long(buf_vals,  &vals_p, nbits_per_group_val);
-            /* sec_val[vcount+j] += group_ref_val; */
+        if (missingValueManagementUsed == 0)
+        {
+            /* No explicit missing values included within data values */
+            for(j=0; j < nvals_per_group;j++) {
+                DebugAssertAccess(sec_val, (long)(vcount+j), n_vals);
+                sec_val[vcount+j] = group_ref_val + grib_decode_unsigned_long(buf_vals,  &vals_p, nbits_per_group_val);
+                /*printf("sec_val[%ld]=%ld\n", vcount+j, sec_val[vcount+j]);*/
+            }
+        }
+        else if (missingValueManagementUsed == 1)
+        {
+            /* Primary missing values included within data values */
+            long maxn = (1 << bits_per_value) - 1;
+            for (j=0; j < nvals_per_group;j++) {
+                if (nbits_per_group_val == 0) {
+                    maxn = (1 << bits_per_value) - 1;
+                    if (group_ref_val == maxn) {
+                        sec_val[vcount+j] = LONG_MAX; /* missing value */
+                    } else {
+                        long temp = grib_decode_unsigned_long(buf_vals,  &vals_p, nbits_per_group_val);
+                        sec_val[vcount+j] = group_ref_val + temp;
+                    }
+                }
+                else {
+                    long temp = grib_decode_unsigned_long(buf_vals,  &vals_p, nbits_per_group_val);
+                    maxn = (1 << nbits_per_group_val) - 1;
+                    if (temp == maxn) {
+                        sec_val[vcount+j] = LONG_MAX; /* missing value */
+                    } else {
+                        sec_val[vcount+j] = group_ref_val + temp;
+                    }
+                }
+            }
+        }
+        else if (missingValueManagementUsed == 2)
+        {
+            /* Primary and secondary missing values included within data values */
+            long maxn = (1 << bits_per_value) - 1;
+            long maxn2 = maxn - 1;
+            for (j=0; j < nvals_per_group;j++) {
+                if (nbits_per_group_val == 0) {
+                    maxn2 = maxn - 1;
+                    if (group_ref_val == maxn || group_ref_val == maxn2) {
+                        sec_val[vcount+j] = LONG_MAX; /* missing value */
+                    } else {
+                        long temp = grib_decode_unsigned_long(buf_vals,  &vals_p, nbits_per_group_val);
+                        sec_val[vcount+j] = group_ref_val + temp;
+                    }
+                }
+                else {
+                    long temp = grib_decode_unsigned_long(buf_vals,  &vals_p, nbits_per_group_val);
+                    maxn = (1 << nbits_per_group_val) - 1;
+                    maxn2 = maxn - 1;
+                    if (temp == maxn || temp == maxn2) {
+                        sec_val[vcount+j] = LONG_MAX; /* missing value */
+                    } else {
+                        sec_val[vcount+j] = group_ref_val + temp;
+                    }
+                }
+            }
         }
 
         vcount += nvals_per_group;
     }
 
-    if(orderOfSpatialDifferencing){
+    if (orderOfSpatialDifferencing) {
         long bias = 0;
-        ref_p    = 0;
+        ref_p     = 0;
+        unsigned long extras[2] = {0,};
+
+        /* For Complex packing, order == 0 */
+        /* For Complex packing and spatial differencing, order == 1 or 2 (code table 5.6) */
+        if (orderOfSpatialDifferencing != 1 && orderOfSpatialDifferencing != 2) {
+            grib_context_log(a->context,GRIB_LOG_ERROR, "Unsupported order of spatial differencing %ld", orderOfSpatialDifferencing);
+            return GRIB_INTERNAL_ERROR;
+        }
 
-        for(i=0;i < orderOfSpatialDifferencing;i++)
-            sec_val[i]     =  grib_decode_unsigned_long(buf_ref, &ref_p, numberOfOctetsExtraDescriptors*8);
+        for(i=0;i < orderOfSpatialDifferencing;i++) {
+            extras[i] = grib_decode_unsigned_long(buf_ref, &ref_p, numberOfOctetsExtraDescriptors*8);
+        }
 
         bias  =  grib_decode_signed_longb(buf_ref, &ref_p, numberOfOctetsExtraDescriptors*8);
 
-        de_spatial_difference (a->context, sec_val, n_vals, orderOfSpatialDifferencing, bias);
+        post_process(a->context, sec_val, n_vals, orderOfSpatialDifferencing, bias, extras);
+        /*de_spatial_difference (a->context, sec_val, n_vals, orderOfSpatialDifferencing, bias);*/
     }
 
     binary_s  = grib_power(binary_scale_factor,2);
     decimal_s = grib_power(-decimal_scale_factor,10) ;
 
-    for(i=0;i < n_vals;i++)
-        val[i] = (double) ((((double)sec_val[i])*binary_s)+reference_value)*decimal_s;
+    for (i=0; i < n_vals; i++) {
+        if (sec_val[i] == LONG_MAX) {
+            val[i] = missingValue;
+        } else {
+            val[i] = (double) ((((double)sec_val[i])*binary_s)+reference_value)*decimal_s;
+        }
+    }
 
     grib_context_free(a->context,sec_val);
     return err;
@@ -622,7 +729,6 @@ static int pack_double(grib_accessor* a, const double* val, size_t *len)
     numberOfBitsUsedForTheScaledGroupLengths = 10;
 
     /*     calculation of integer array   */
-    sec_val  = NULL;
     sec_val  = (unsigned long*)grib_context_malloc(a->context,(n_vals)*sizeof(long));
     if(!sec_val) return GRIB_OUT_OF_MEMORY;
 
@@ -652,8 +758,6 @@ static int pack_double(grib_accessor* a, const double* val, size_t *len)
     for(i=0;i< n_vals;i++)
         sec_val[i] = (unsigned long)((((val[i]*d)-reference_value)*divisor)+0.5);
 
-    numberOfGroupsOfDataValues = 0;
-    nv = n_vals;
     group_val = sec_val;
 
     maxgrw = calc_pow_2(numberOfBitsUsedForTheGroupWidths);
@@ -661,7 +765,6 @@ static int pack_double(grib_accessor* a, const double* val, size_t *len)
 
     numberOfGroupsOfDataValues = 0;
     nv = n_vals;
-    group_val = sec_val;
     vals_p=0;
 
     while(find_next_group(group_val,nv,maxgrw,maxgrl,&nbits_per_group_val,&nvals_per_group,&group_ref_val)==GRIB_SUCCESS){
@@ -677,7 +780,7 @@ static int pack_double(grib_accessor* a, const double* val, size_t *len)
     buf_size  += (7+(numberOfGroupsOfDataValues*numberOfBitsUsedForTheGroupWidths))/8;
     buf_size  += (7+(numberOfGroupsOfDataValues*numberOfBitsUsedForTheScaledGroupLengths))/8;
 
-    buf_size  +=  (vals_p/8)  + (vals_p%8?1:0);
+    buf_size  +=  (vals_p/8) + ((vals_p%8) ? 1 : 0);
 
     buf = (unsigned char*)grib_context_malloc_clear(a->context,buf_size);
 
diff --git a/src/grib_accessor_class_offset_values.c b/src/grib_accessor_class_offset_values.c
index 69279c6..cb21f4b 100644
--- a/src/grib_accessor_class_offset_values.c
+++ b/src/grib_accessor_class_offset_values.c
@@ -137,60 +137,63 @@ static void init_class(grib_accessor_class* c)
 
 static void init(grib_accessor* a,const long l, grib_arguments* args)
 {
-  int n=0;
-  grib_accessor_offset_values* self= (grib_accessor_offset_values*)a;
-  self->values=grib_arguments_get_name(grib_handle_of_accessor(a),args,n++);
-  self->missingValue=grib_arguments_get_name(grib_handle_of_accessor(a),args,n++);
-  a->flags |= GRIB_ACCESSOR_FLAG_FUNCTION;
-  a->length=0;
+    int n=0;
+    grib_accessor_offset_values* self= (grib_accessor_offset_values*)a;
+    self->values=grib_arguments_get_name(grib_handle_of_accessor(a),args,n++);
+    self->missingValue=grib_arguments_get_name(grib_handle_of_accessor(a),args,n++);
+    a->flags |= GRIB_ACCESSOR_FLAG_FUNCTION;
+    a->length=0;
 }
 
 static int  unpack_double(grib_accessor* a, double* val, size_t *len)
 {
-  int ret=0;
-  *val=0;
-  *len =1;
-  return ret;
+    int ret=0;
+    *val=0;
+    *len =1;
+    return ret;
 }
 
 static int pack_double(grib_accessor* a, const double* val, size_t *len)
 {
-  double* values=NULL;
-  size_t size=0;
-  double missingValue=0;
-  int ret=0,i=0;
-  grib_accessor_offset_values* self= (grib_accessor_offset_values*)a;
-  grib_context* c=a->context;
-  grib_handle* h=grib_handle_of_accessor(a);
-
-  if (*val==0) return GRIB_SUCCESS;
-
-  if((ret = grib_get_double_internal(h,self->missingValue,&missingValue))
-       != GRIB_SUCCESS) {
+    double* values=NULL;
+    size_t size=0;
+    double missingValue=0;
+    long missingValuesPresent = 0;
+    int ret=0,i=0;
+    grib_accessor_offset_values* self= (grib_accessor_offset_values*)a;
+    grib_context* c=a->context;
+    grib_handle* h=grib_handle_of_accessor(a);
+
+    if (*val==0) return GRIB_SUCCESS;
+
+    if((ret = grib_get_double_internal(h,self->missingValue,&missingValue)) != GRIB_SUCCESS) {
         return ret;
-  }
+    }
+    if((ret=grib_get_long_internal(h,"missingValuesPresent",&missingValuesPresent)) != GRIB_SUCCESS) {
+        return ret;
+    }
 
-  if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;
+    if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;
 
-  values=(double*)grib_context_malloc(c,size*sizeof(double));
-  if (!values) return GRIB_OUT_OF_MEMORY;
+    values=(double*)grib_context_malloc(c,size*sizeof(double));
+    if (!values) return GRIB_OUT_OF_MEMORY;
 
-  if((ret = grib_get_double_array_internal(h,self->values,values,&size))
-       != GRIB_SUCCESS) {
+    if((ret = grib_get_double_array_internal(h,self->values,values,&size)) != GRIB_SUCCESS) {
         grib_context_free(c,values);
         return ret;
-  }
-
-  for (i=0;i<size;i++)
-    if (values[i]!=missingValue) values[i]+=*val;
+    }
 
+    for (i=0;i<size;i++) {
+        if (missingValuesPresent) {
+            if (values[i]!=missingValue) values[i]+=*val;
+        } else {
+            values[i]+=*val;
+        }
+    }
 
-  if((ret = grib_set_double_array_internal(h, self->values,values,size))
-      != GRIB_SUCCESS) return ret;
+    if((ret = grib_set_double_array_internal(h, self->values,values,size)) != GRIB_SUCCESS) return ret;
 
-  grib_context_free(c,values);
+    grib_context_free(c,values);
 
-  return GRIB_SUCCESS;
+    return GRIB_SUCCESS;
 }
-
-
diff --git a/src/grib_accessor_class_scale_values.c b/src/grib_accessor_class_scale_values.c
index 611e2bf..ce07233 100644
--- a/src/grib_accessor_class_scale_values.c
+++ b/src/grib_accessor_class_scale_values.c
@@ -137,59 +137,63 @@ static void init_class(grib_accessor_class* c)
 
 static void init(grib_accessor* a,const long l, grib_arguments* args)
 {
-  int n=0;
-  grib_accessor_scale_values* self= (grib_accessor_scale_values*)a;
-  self->values=grib_arguments_get_name(grib_handle_of_accessor(a),args,n++);
-  self->missingValue=grib_arguments_get_name(grib_handle_of_accessor(a),args,n++);
-  a->flags |= GRIB_ACCESSOR_FLAG_FUNCTION;
-  a->length=0;
+    int n=0;
+    grib_accessor_scale_values* self= (grib_accessor_scale_values*)a;
+    self->values=grib_arguments_get_name(grib_handle_of_accessor(a),args,n++);
+    self->missingValue=grib_arguments_get_name(grib_handle_of_accessor(a),args,n++);
+    a->flags |= GRIB_ACCESSOR_FLAG_FUNCTION;
+    a->length=0;
 }
 
-static int  unpack_double(grib_accessor* a, double* val, size_t *len)
+static int unpack_double(grib_accessor* a, double* val, size_t *len)
 {
-  int ret=0;
-  *val=1;
-  *len =1;
-  return ret;
+    int ret=0;
+    *val=1;
+    *len =1;
+    return ret;
 }
 
 static int pack_double(grib_accessor* a, const double* val, size_t *len)
 {
-  double* values=NULL;
-  double missingValue=0;
-  size_t size=0;
-  int ret=0,i=0;
-  grib_accessor_scale_values* self= (grib_accessor_scale_values*)a;
-  grib_context* c=a->context;
-  grib_handle* h=grib_handle_of_accessor(a);
-
-  if (*val==1) return GRIB_SUCCESS;
-
-  if((ret = grib_get_double_internal(h,self->missingValue,&missingValue))
-       != GRIB_SUCCESS) {
+    double* values=NULL;
+    double missingValue=0;
+    long missingValuesPresent = 0;
+    size_t size=0;
+    int ret=0,i=0;
+    grib_accessor_scale_values* self= (grib_accessor_scale_values*)a;
+    grib_context* c=a->context;
+    grib_handle* h=grib_handle_of_accessor(a);
+
+    if (*val==1) return GRIB_SUCCESS;
+
+    if((ret = grib_get_double_internal(h,self->missingValue,&missingValue)) != GRIB_SUCCESS) {
         return ret;
-  }
+    }
+    if((ret=grib_get_long_internal(h,"missingValuesPresent",&missingValuesPresent)) != GRIB_SUCCESS) {
+        return ret;
+    }
 
-  if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;
+    if ( (ret=grib_get_size(h,self->values,&size)) != GRIB_SUCCESS) return ret;
 
-  values=(double*)grib_context_malloc(c,size*sizeof(double));
-  if (!values) return GRIB_OUT_OF_MEMORY;
+    values=(double*)grib_context_malloc(c,size*sizeof(double));
+    if (!values) return GRIB_OUT_OF_MEMORY;
 
-  if((ret = grib_get_double_array_internal(h,self->values,values,&size))
-       != GRIB_SUCCESS) {
+    if((ret = grib_get_double_array_internal(h,self->values,values,&size)) != GRIB_SUCCESS) {
         grib_context_free(c,values);
         return ret;
-  }
+    }
 
-  for (i=0;i<size;i++)
-    if (values[i]!=missingValue) values[i]*=*val;
+    for (i=0;i<size;i++) {
+        if (missingValuesPresent) {
+            if (values[i]!=missingValue) values[i]*=*val;
+        } else {
+            values[i]*=*val;
+        }
+    }
 
-  if((ret = grib_set_double_array_internal(h, self->values,values,size))
-      != GRIB_SUCCESS) return ret;
+    if((ret = grib_set_double_array_internal(h, self->values,values,size)) != GRIB_SUCCESS) return ret;
 
-  grib_context_free(c,values);
+    grib_context_free(c,values);
 
-  return GRIB_SUCCESS;
+    return GRIB_SUCCESS;
 }
-
-
diff --git a/src/grib_accessor_class_statistics.c b/src/grib_accessor_class_statistics.c
index 8dd8be5..bab7ca6 100644
--- a/src/grib_accessor_class_statistics.c
+++ b/src/grib_accessor_class_statistics.c
@@ -170,6 +170,7 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len)
     size_t size=0, real_size=0;
     double max,min,avg,sd,value,skew,kurt, m2=0,m3=0,m4=0;
     double missing=0;
+    long missingValuesPresent = 0;
     size_t number_of_missing=0;
     grib_context* c=a->context;
     grib_handle* h=grib_handle_of_accessor(a);
@@ -181,32 +182,43 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len)
     grib_context_log(a->context,GRIB_LOG_DEBUG,
             "grib_accessor_statistics: computing statistics for %d values",size);
 
-    if((ret=grib_get_double(grib_handle_of_accessor(a),self->missing_value,&missing))
-            != GRIB_SUCCESS) return ret;
+    if((ret=grib_get_double(h,self->missing_value,&missing)) != GRIB_SUCCESS) return ret;
+    if((ret=grib_get_long_internal(h,"missingValuesPresent",&missingValuesPresent)) != GRIB_SUCCESS) return ret;
 
     values=(double*)grib_context_malloc_clear(c,size*sizeof(double));
     if (!values) return GRIB_OUT_OF_MEMORY;
 
-    if((ret = grib_get_double_array_internal(h,self->values,values,&size))
-            != GRIB_SUCCESS) {
+    if((ret = grib_get_double_array_internal(h,self->values,values,&size)) != GRIB_SUCCESS) {
         grib_context_free(c,values);
         return ret;
     }
 
     number_of_missing=0;
-    i=0;
-    while (i<size && values[i] == missing ) {i++;number_of_missing++;}
-    max=values[i];
-    min=values[i];
-    avg=values[i];
-    for (i=number_of_missing+1;i<size;i++) {
-        value=values[i];
-        if (value > max && value != missing) max=value;
-        if (value < min && value != missing) min=value;
-        if (value != missing) avg+=value;
-        else number_of_missing++;
+    if (missingValuesPresent) {
+        i=0;
+        while (i<size && values[i] == missing) {i++;number_of_missing++;}
+        max=values[i];
+        min=values[i];
+        avg=values[i];
+        for (i=number_of_missing+1;i<size;i++) {
+            value=values[i];
+            if (value > max && value != missing) max=value;
+            if (value < min && value != missing) min=value;
+            if (value != missing) avg+=value;
+            else number_of_missing++;
+        }
+    } else {
+        max=values[0];
+        min=values[0];
+        avg=values[0];
+        for (i=1; i<size; i++) {
+            value = values[i];
+            if (value > max) max=value;
+            if (value < min) min=value;
+            avg += value;
+        }
     }
-
+    /*printf("stats.......... number_of_missing=%ld\n", number_of_missing);*/
     /* Don't divide by zero if all values are missing! */
     if (size != number_of_missing) {
         avg/=(size-number_of_missing);
@@ -214,7 +226,11 @@ static int unpack_double(grib_accessor* a, double* val, size_t *len)
 
     sd=0; skew=0; kurt=0;
     for (i=0;i<size;i++) {
-        if (values[i] != missing) {
+        int valueNotMissing = 1;
+        if (missingValuesPresent) {
+            valueNotMissing = (values[i] != missing);
+        }
+        if (valueNotMissing) {
             double v = values[i] - avg;
             double tmp = v*v;
             m2 += tmp;
diff --git a/src/grib_api_prototypes.h b/src/grib_api_prototypes.h
index 302e02e..d457a90 100644
--- a/src/grib_api_prototypes.h
+++ b/src/grib_api_prototypes.h
@@ -1502,7 +1502,7 @@ const char *grib_get_git_sha1(void);
 
 /* grib_bits_any_endian.c */
 int grib_is_all_bits_one(long val, long nbits);
-int grib_encode_string(const unsigned char *bitStream, long *bitOffset, size_t numberOfCharacters, char *string);
+int grib_encode_string(unsigned char *bitStream, long *bitOffset, size_t numberOfCharacters, const char *string);
 char *grib_decode_string(const unsigned char *bitStream, long *bitOffset, size_t numberOfCharacters, char *string);
 unsigned long grib_decode_unsigned_long(const unsigned char *p, long *bitp, long nbits);
 int grib_encode_unsigned_long(unsigned char *p, unsigned long val, long *bitp, long nbits);
diff --git a/src/grib_api_version.c b/src/grib_api_version.c
index a8e8650..e09f15c 100644
--- a/src/grib_api_version.c
+++ b/src/grib_api_version.c
@@ -1,3 +1,3 @@
 #include "grib_api_internal.h"
 
-const char * grib_get_git_sha1() { return "526f08d3cc815e02252d58f42e1f85ff2f8cb4bc"; }
+const char * grib_get_git_sha1() { return "ef203a98d50eb6db1279312cd0f506803236cfa6"; }
diff --git a/src/grib_bits.c b/src/grib_bits.c
index d18ffee..82dc1df 100644
--- a/src/grib_bits.c
+++ b/src/grib_bits.c
@@ -101,34 +101,36 @@ int grib_encode_signed_long(unsigned char* p, long val , long o, int l)
     return GRIB_SUCCESS;
 }
 
-static void grib_set_bit_on( unsigned char* p, long* bitp){
-
+static void grib_set_bit_on( unsigned char* p, long* bitp)
+{
     p +=  *bitp/8;
     *p |=  (1u << (7-((*bitp)%8)));
     (*bitp)++;
 }
 
-void grib_set_bits_on( unsigned char* p, long* bitp,long nbits){
+void grib_set_bits_on( unsigned char* p, long* bitp,long nbits)
+{
     int i;
     for (i=0;i<nbits;i++) {
       grib_set_bit_on(p,bitp);
     }
 }
 
-static void grib_set_bit_off( unsigned char* p, long* bitp){
-
+static void grib_set_bit_off( unsigned char* p, long* bitp)
+{
     p +=  *bitp/8;
     *p &= ~(1u << (7-((*bitp)%8)));
     (*bitp)++;
 }
 
-int grib_get_bit(const unsigned char* p, long bitp){
+int grib_get_bit(const unsigned char* p, long bitp)
+{
     p += (bitp >> 3);
     return (*p&(1<<(7-(bitp%8))));
 }
 
-void grib_set_bit( unsigned char* p, long bitp, int val){
-
+void grib_set_bit( unsigned char* p, long bitp, int val)
+{
     if(val == 0) grib_set_bit_off(p,&bitp);
     else grib_set_bit_on(p,&bitp);
 }
@@ -166,18 +168,11 @@ int grib_encode_signed_longb(unsigned char* p,  long val ,long *bitp, long nb)
 }
 
 #if GRIB_IBMPOWER67_OPT
-
-#include "grib_bits_ibmpow.c"
-
-#else
-#if FAST_BIG_ENDIAN
-
-#include "grib_bits_fast_big_endian.c"
-
+ #include "grib_bits_ibmpow.c"
 #else
-
-#include "grib_bits_any_endian.c"
-
-#endif
-
+ #if FAST_BIG_ENDIAN
+  #include "grib_bits_fast_big_endian.c"
+ #else
+  #include "grib_bits_any_endian.c"
+ #endif
 #endif
diff --git a/src/grib_bits_any_endian.c b/src/grib_bits_any_endian.c
index 3166b51..bb5feeb 100644
--- a/src/grib_bits_any_endian.c
+++ b/src/grib_bits_any_endian.c
@@ -44,7 +44,7 @@ int grib_is_all_bits_one(long val, long nbits)
     return bits_all_one.v[nbits]==val;
 }
 
-int grib_encode_string(const unsigned char* bitStream, long *bitOffset, size_t numberOfCharacters,char* string)
+int grib_encode_string(unsigned char *bitStream, long *bitOffset, size_t numberOfCharacters, const char *string)
 {
     size_t i;
     int err=0;
@@ -282,15 +282,9 @@ int grib_encode_unsigned_longb(unsigned char* p, unsigned long val ,long *bitp,
 }
 
 #if OMP_PACKING
-
-#include "grib_bits_any_endian_omp.c"
-
+ #include "grib_bits_any_endian_omp.c"
 #elif VECTOR
-
-#include "grib_bits_any_endian_vector.c"
-
+ #include "grib_bits_any_endian_vector.c"
 #else
-
-#include "grib_bits_any_endian_simple.c"
-
+ #include "grib_bits_any_endian_simple.c"
 #endif
diff --git a/src/grib_bits_fast_big_endian.c b/src/grib_bits_fast_big_endian.c
index bde7dc6..f9918aa 100644
--- a/src/grib_bits_fast_big_endian.c
+++ b/src/grib_bits_fast_big_endian.c
@@ -22,138 +22,163 @@ typedef struct bits_all_one_t {
 
 static bits_all_one_t bits_all_one={0,0,{0,}};
 
-static void init_bits_all_one() {
-   int size=sizeof(long)*8;
-   long* v=0;
-   unsigned long cmask=-1;
-   bits_all_one.size=size;
-   bits_all_one.inited=1;
-   v=bits_all_one.v+size;
-   *v= cmask << size;
-   while (size>0)  *(--v)= ~(cmask << --size);
-
+static void init_bits_all_one()
+{
+    int size=sizeof(long)*8;
+    long* v=0;
+    unsigned long cmask=-1;
+    bits_all_one.size=size;
+    bits_all_one.inited=1;
+    v=bits_all_one.v+size;
+    *v= cmask << size;
+    while (size>0)  *(--v)= ~(cmask << --size);
 }
 
-int grib_is_all_bits_one(long val, long nbits) {
-
+int grib_is_all_bits_one(long val, long nbits)
+{
     if (!bits_all_one.inited) init_bits_all_one();
     return bits_all_one.v[nbits]==val;
-
 }
 
+int grib_encode_string(unsigned char *bitStream, long *bitOffset, size_t numberOfCharacters, const char *string)
+{
+    size_t i;
+    int err=0;
+    long byteOffset = *bitOffset / 8;
+    int remainder = *bitOffset % 8;
+    unsigned char* p;
+    int remainderComplement=8-remainder;
+    const char *s=string;
+
+    Assert(numberOfCharacters<512 && (numberOfCharacters == 0 || string));
+
+    /* if (remainder) byteOffset++; */
+
+    if (numberOfCharacters > 0) {
+        unsigned char *restrict p = bitStream+byteOffset;
+        if ( remainder == 0 )  {
+            memcpy(p, string, numberOfCharacters);
+        } else {
+            unsigned char mask = (unsigned char)(0xFF00 >> remainder);
+            unsigned char accum = p[0];
+            for (size_t i=0; i < numberOfCharacters; ++i) {
+                accum |= (s[i] >>remainder) & ~mask;
+                p[i] = accum;
+                accum = (s[i] << remainderComplement) & mask;
+            }
+            p[numberOfCharacters] = accum;
+        }
+    }
+    *bitOffset+=numberOfCharacters*8;
+    return err;
+}
 
 char* grib_decode_string(const unsigned char* bitStream, long *bitOffset, size_t numberOfCharacters,char* string)
 {
-  size_t i;
-  long byteOffset = *bitOffset / 8;
-  int remainder = *bitOffset % 8;
-  unsigned char c;
-  unsigned char* p;
-  char* s=string;
-  unsigned char mask[] ={ 0, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
-  int remainderComplement=8-remainder;
-
-  if (numberOfCharacters==0) return string;
-
-  p=(unsigned char*)bitStream+byteOffset;
-
-  if ( remainder == 0 )  {
-    memcpy(string,bitStream+byteOffset,numberOfCharacters);
+    size_t i;
+    long byteOffset = *bitOffset / 8;
+    int remainder = *bitOffset % 8;
+    unsigned char c;
+    unsigned char* p;
+    char* s=string;
+    unsigned char mask[] ={ 0, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
+    int remainderComplement=8-remainder;
+
+    if (numberOfCharacters==0) return string;
+
+    p=(unsigned char*)bitStream+byteOffset;
+
+    if ( remainder == 0 )  {
+        memcpy(string,bitStream+byteOffset,numberOfCharacters);
+        *bitOffset+=numberOfCharacters*8;
+        return string;
+    }
+
+    for (i=0;i<numberOfCharacters;i++) {
+        c=(*p)<<remainder;
+        p++;
+        *s = ( c | ( (*p) & mask[remainder] )>>remainderComplement );
+        s++;
+    }
     *bitOffset+=numberOfCharacters*8;
     return string;
-  }
-
-  for (i=0;i<numberOfCharacters;i++) {
-    c=(*p)<<remainder;
-    p++;
-    *s = ( c | ( (*p) & mask[remainder] )>>remainderComplement );
-    s++;
-  }
-  *bitOffset+=numberOfCharacters*8;
-  return string;
 }
 
 
 unsigned long grib_decode_unsigned_long(const unsigned char* p, long *bitp, long nbits)
 {
-  long countOfLeftmostBits=0,leftmostBits=0;
-  long startBit= *bitp ;
-  long remainingBits = nbits;
-  long *pp=(long*)p;
-  unsigned long val=0;
-
-  if (startBit >= max_nbits) {
-    pp += startBit/max_nbits;
-    startBit %= max_nbits;
-  }
-
-  countOfLeftmostBits = startBit + remainingBits;
-  if (countOfLeftmostBits > max_nbits) {
-    countOfLeftmostBits = max_nbits - startBit;
-    remainingBits -= countOfLeftmostBits;
-    leftmostBits=(VALUE(*pp,startBit,countOfLeftmostBits)) << remainingBits;
-    startBit = 0;
-    pp++;
-  } else
-    leftmostBits = 0;
-
-  val=leftmostBits+(VALUE(*pp,startBit,remainingBits));
-
-  *bitp += nbits;
-
-  return val;
+    long countOfLeftmostBits=0,leftmostBits=0;
+    long startBit= *bitp ;
+    long remainingBits = nbits;
+    long *pp=(long*)p;
+    unsigned long val=0;
+
+    if (startBit >= max_nbits) {
+        pp += startBit/max_nbits;
+        startBit %= max_nbits;
+    }
+
+    countOfLeftmostBits = startBit + remainingBits;
+    if (countOfLeftmostBits > max_nbits) {
+        countOfLeftmostBits = max_nbits - startBit;
+        remainingBits -= countOfLeftmostBits;
+        leftmostBits=(VALUE(*pp,startBit,countOfLeftmostBits)) << remainingBits;
+        startBit = 0;
+        pp++;
+    } else
+        leftmostBits = 0;
+
+    val=leftmostBits+(VALUE(*pp,startBit,remainingBits));
+
+    *bitp += nbits;
+
+    return val;
 }
 
 int grib_encode_unsigned_long(unsigned char* p, unsigned long val ,long *bitp, long nbits)
 {
-  long* destination = (long*)p;
-  long countOfLeftmostBits=0,nextWord=0,startBit=0,remainingBits=0,rightmostBits=0;
-
-  startBit = *bitp;
-  remainingBits = nbits;
-
-  if (startBit >= max_nbits) {
-    nextWord = startBit / max_nbits;
-    startBit %= max_nbits;
-  } else
-    nextWord = 0;
-
-  countOfLeftmostBits = startBit + remainingBits;
-  if (countOfLeftmostBits > max_nbits) {
-    countOfLeftmostBits = max_nbits - startBit;
-    startBit = max_nbits - remainingBits;
-    remainingBits -= countOfLeftmostBits;
+    long* destination = (long*)p;
+    long countOfLeftmostBits=0,nextWord=0,startBit=0,remainingBits=0,rightmostBits=0;
+
+    startBit = *bitp;
+    remainingBits = nbits;
+
+    if (startBit >= max_nbits) {
+        nextWord = startBit / max_nbits;
+        startBit %= max_nbits;
+    } else
+        nextWord = 0;
+
+    countOfLeftmostBits = startBit + remainingBits;
+    if (countOfLeftmostBits > max_nbits) {
+        countOfLeftmostBits = max_nbits - startBit;
+        startBit = max_nbits - remainingBits;
+        remainingBits -= countOfLeftmostBits;
+        destination[nextWord] =
+                ((destination[nextWord] >> countOfLeftmostBits) << countOfLeftmostBits)
+                + (VALUE(val,startBit,countOfLeftmostBits));
+        startBit = 0;
+        nextWord++;
+    }
+
+    rightmostBits = VALUE(val,max_nbits-remainingBits,remainingBits);
     destination[nextWord] =
-      ((destination[nextWord] >> countOfLeftmostBits) << countOfLeftmostBits)
-      + (VALUE(val,startBit,countOfLeftmostBits));
-    startBit = 0;
-    nextWord++;
-  }
-
-  rightmostBits = VALUE(val,max_nbits-remainingBits,remainingBits);
-  destination[nextWord] =
-    (destination[nextWord] & ~MASKVALUE(startBit,remainingBits))
-    + (rightmostBits << max_nbits-(remainingBits+startBit));
-
-  *bitp+=nbits;
-  return GRIB_SUCCESS;
+            (destination[nextWord] & ~MASKVALUE(startBit,remainingBits))
+            + (rightmostBits << max_nbits-(remainingBits+startBit));
+
+    *bitp+=nbits;
+    return GRIB_SUCCESS;
 }
 
 int grib_encode_unsigned_longb(unsigned char* p, unsigned long val ,long *bitp, long nbits)
 {
-  return grib_encode_unsigned_long(p,val ,bitp, nbits);
+    return grib_encode_unsigned_long(p,val ,bitp, nbits);
 }
 
 #if VECTOR
-
-#include "grib_bits_fast_big_endian_vector.c"
-
+ #include "grib_bits_fast_big_endian_vector.c"
 #elif OMP
-
-#include "grib_bits_fast_big_endian_omp.c"
-
+ #include "grib_bits_fast_big_endian_omp.c"
 #else
-
-#include "grib_bits_fast_big_endian_simple.c"
-
+ #include "grib_bits_fast_big_endian_simple.c"
 #endif
diff --git a/tests/grib_statistics.sh b/tests/grib_statistics.sh
index 6299438..4b87d15 100755
--- a/tests/grib_statistics.sh
+++ b/tests/grib_statistics.sh
@@ -35,5 +35,26 @@ ${tools_dir}/grib_filter statistics.filter ${data_dir}/$file > statistics.out
 diff statistics.out ${data_dir}/statistics.out.good
 
 done
+rm -f statistics.out statistics.filter
 
-rm -f statistics.out statistics.filter || true
+
+# GRIB with no missing values but some entries = 9999
+# See ECC-478
+# ---------------------------------------------------
+input=${data_dir}/lfpw.grib1
+temp1=temp1.statistics.grib
+temp2=temp2.statistics.grib
+stats=`${tools_dir}/grib_get -w count=50 -F%.2f -n statistics $input`
+[ "$stats" = "10098 0 1064.19 3066.07 2.57004 4.60965 0" ]
+
+# Scaling values in presence of real 9999 values
+${tools_dir}/grib_set -s scaleValuesBy=0.5                     $input $temp1
+${tools_dir}/grib_set -s missingValue=1.0E34,scaleValuesBy=0.5 $input $temp2
+${tools_dir}/grib_compare $temp1 $temp2
+
+# Offsetting values in presence of real 9999 values
+${tools_dir}/grib_set -s offsetValuesBy=0.5                     $input $temp1
+${tools_dir}/grib_set -s missingValue=1.0E34,offsetValuesBy=0.5 $input $temp2
+${tools_dir}/grib_compare $temp1 $temp2
+
+rm -f $temp1 $temp2
diff --git a/tests/grib_util_set_spec.sh b/tests/grib_util_set_spec.sh
index 3304a99..0b4d957 100755
--- a/tests/grib_util_set_spec.sh
+++ b/tests/grib_util_set_spec.sh
@@ -17,10 +17,12 @@
 infile=../data/latlon.grib
 outfile=out.grib_util_set_spec.grib
 tempOut=temp.grib_util_set_spec.grib
+grib_util_set_spec=${test_dir}/grib_util_set_spec
+
 rm -f $outfile
 
 # GRIB1 with local definition for MARS. Convert to edition2 and remove local def
-${test_dir}/grib_util_set_spec -e 2 -r $infile $outfile > /dev/null
+$grib_util_set_spec -e 2 -r $infile $outfile > /dev/null
 
 res=`${tools_dir}/grib_get -p edition,section2Used,Ni,Nj,numberOfValues,bitsPerValue $outfile`
 [ "$res" = "2 0 17 14 238 24" ]
@@ -30,22 +32,22 @@ ${tools_dir}/grib_get_data $outfile > /dev/null
 
 # Remove the local definition from input
 ${tools_dir}/grib_set -s deleteLocalDefinition=1 $infile $tempOut
-${test_dir}/grib_util_set_spec $tempOut $outfile > /dev/null
+$grib_util_set_spec $tempOut $outfile > /dev/null
 
 # Add another grib1 local definition (which is not in grib2)
 ${tools_dir}/grib_set -s setLocalDefinition=1,localDefinitionNumber=5 $infile $tempOut
 infile=$tempOut
-${test_dir}/grib_util_set_spec -r -e 2 $tempOut $outfile > /dev/null
+$grib_util_set_spec -r -e 2 $tempOut $outfile > /dev/null
 res=`${tools_dir}/grib_get -p edition,section2Used $outfile`
 [ "$res" = "2 0" ]
 
 # GRIB2 input with local definition
 infile=../data/regular_latlon_surface.grib2
-${test_dir}/grib_util_set_spec -r $infile $outfile > /dev/null
+$grib_util_set_spec -r $infile $outfile > /dev/null
 grib_check_key_equals $outfile section2Used 0
 # GRIB2 input without local definition
 infile=$ECCODES_SAMPLES_PATH/GRIB2.tmpl
-${test_dir}/grib_util_set_spec $infile $outfile > /dev/null
+$grib_util_set_spec $infile $outfile > /dev/null
 grib_check_key_equals $outfile section2Used 0
 
 # Convert to edition2 and use JPEG for packing
@@ -54,7 +56,7 @@ set +u
 if [ x"$HAVE_JPEG" != "x" ]; then
   if [ $HAVE_JPEG -eq 1 ]; then
     infile=../data/latlon.grib
-    ${test_dir}/grib_util_set_spec -e 2 -p grid_jpeg $infile $outfile > /dev/null
+    $grib_util_set_spec -e 2 -p grid_jpeg $infile $outfile > /dev/null
     res=`${tools_dir}/grib_get -p edition,section2Used,packingType $outfile`
     [ "$res" = "2 1 grid_jpeg" ]
   fi
@@ -71,7 +73,7 @@ rm -f $outfile
 stats_old=`${tools_dir}/grib_get -F%.2f -p min,max $infile`
 [ "$stats_old" = "160.25 224.45" ]
 
-${test_dir}/grib_util_set_spec -p grid_second_order $infile $outfile
+$grib_util_set_spec -p grid_second_order $infile $outfile
 
 # Check output file. Values are scaled up by 1.1
 grib_check_key_equals $outfile packingType grid_second_order
@@ -89,7 +91,7 @@ fi
 infile=$ECCODES_SAMPLES_PATH/reduced_gg_pl_32_grib2.tmpl
 rm -f $outfile
 
-${test_dir}/grib_util_set_spec $infile $outfile
+$grib_util_set_spec $infile $outfile
 grib_check_key_equals $outfile "packingType,const" "grid_simple 1"
 ${tools_dir}/grib_get_data $outfile > /dev/null
 
diff --git a/tools/grib_get_data.c b/tools/grib_get_data.c
index 720af87..c1d137f 100644
--- a/tools/grib_get_data.c
+++ b/tools/grib_get_data.c
@@ -70,10 +70,23 @@ int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* fil
     return 0;
 }
 
+/* Return 1 if the GRIB message has missing values encoded in data section and not in bitmap */
+/* e.g. grid_complex_spatial_differencing with missingValueManagementUsed enabled */
+static int hasMissingValuesButNoBitmap(grib_handle* h)
+{
+    long missingValueManagementUsed = 0;
+    int err = grib_get_long(h, "missingValueManagementUsed", &missingValueManagementUsed);
+    if (!err) {
+        /* Key exists */
+        return (missingValueManagementUsed!=0);
+    }
+    return 0;
+}
 int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h)
 {
     int err=0;
 
+    double missingValue = 9999;
     int skip_missing=1;
     char *missing_string=NULL;
     int i=0;
@@ -89,6 +102,30 @@ int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h)
     double *data_values=0,*lats=0,*lons=0;
     int n = 0;
     size_t size=0;
+    /* Cater for GRIBs which have missing values but no bitmap! */
+    /* e.g. grid_complex_spatial_differencing with 'missingValueManagementUsed' enabled */
+    const int missingValuesButNoBitmap = hasMissingValuesButNoBitmap(h);
+
+    if (grib_options_on("m:")) {
+        /* User wants to see missing values */
+        char* theEnd = NULL;
+        double mval=0;
+        char* kmiss=grib_options_get_option("m:");
+        char* p = kmiss;
+        skip_missing=0;
+        while (*p != ':' && *p != '\0') p++;
+        if (*p == ':' && *(p+1) != '\0') {
+            *p='\0';
+            missing_string=strdup(p+1);
+        } else {
+            missing_string=strdup(kmiss);
+        }
+        mval=strtod(kmiss, &theEnd);
+        if (kmiss != theEnd && *theEnd == '\0')
+            missingValue = mval;
+        grib_set_double(h,"missingValue",missingValue);
+        /*missing_string=grib_options_get_option("m:");*/
+    }
 
     if (grib_options_on("F:"))
         format=grib_options_get_option("F:");
@@ -142,13 +179,6 @@ int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h)
         GRIB_CHECK(grib_get_long_array(h,"bitmap",bitmap,&bmp_len),0);
     }
 
-    skip_missing=1;
-    if (grib_options_on("m:")) {
-        /* User wants to see missing values */
-        skip_missing=0;
-        missing_string=grib_options_get_option("m:");
-    }
-
     if (iter)
         fprintf(dump_file,"Latitude, Longitude, ");
 
@@ -166,7 +196,10 @@ int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h)
     if (skip_missing==0){
         /* Show missing values in data */
         for (i=0;i<numberOfPoints;i++) {
-            const int is_missing_val = (bitmapPresent && bitmap[i] == 0);
+            int is_missing_val = (bitmapPresent && bitmap[i] == 0);
+            if (!bitmapPresent && missingValuesButNoBitmap) {
+                is_missing_val = (data_values[i] == missingValue);
+            }
             if (iter) fprintf(dump_file,"%9.3f%9.3f ",lats[i],lons[i]);
 
             if (is_missing_val)
@@ -183,7 +216,10 @@ int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h)
     } else if ( skip_missing==1 ){
         /* Skip the missing values in data */
         for (i=0;i<numberOfPoints;i++) {
-            const int is_missing_val = (bitmapPresent && bitmap[i] == 0);
+            int is_missing_val = (bitmapPresent && bitmap[i] == 0);
+            if (!bitmapPresent && missingValuesButNoBitmap) {
+                is_missing_val = (data_values[i] == missingValue);
+            }
             if (!is_missing_val){
                 if (iter) fprintf(dump_file,"%9.3f%9.3f ",lats[i],lons[i]);
                 fprintf(dump_file,format,data_values[i]);
diff --git a/tools/grib_histogram.c b/tools/grib_histogram.c
index 64d24a7..07de754 100644
--- a/tools/grib_histogram.c
+++ b/tools/grib_histogram.c
@@ -8,148 +8,136 @@
  * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
 #include "grib_api.h"
 
 static void usage(const char *prog)
 {
-	fprintf(stderr,"%s:  in1 [in2 ... ]  out\n",prog);
-	exit(1);
+    fprintf(stderr,"%s:  in1 [in2 ... ]  out\n",prog);
+    exit(1);
 }
 
-grib_values values[10240];
-
 int main(int argc, const char *argv[])
 {
-	int i,j;
-	FILE *in;
-	int e;
-	grib_handle *h;
-	double* values = NULL;
-	size_t size;
-	size_t last_size = 0;
-	double min,max;
-	long count = 10;
-	long intervals[10];
-	const char *names[1024];
-	int name_count = 0;
-
-	if(argc < 2) usage(argv[0]);
-
-
-	for(i = 1; i < argc; i++)
-	{
-
-		if(argv[i][0] == '-') {
-			names[name_count++] = argv[i]+1;	
-			continue;
-		}
-
-		in = fopen(argv[i],"r");
-		if(!in) {
-			perror(argv[i]);
-			exit(1);
-		}
-
-		while( (h = grib_handle_new_from_file(NULL,in,&e)) != NULL )
-		{
-			long bitmap;
-			double delta;
-			GRIB_CHECK(grib_get_long(h,"bitMapIndicator",&bitmap),argv[i]);
-
-
-			GRIB_CHECK(grib_get_size(h,"values",&size),argv[i]);
-
-			if(size > last_size)
-			{
-				if(values)
-					free(values);
-				values = (double*)malloc(size*sizeof(double));
-				last_size = size;
-				assert(values);
-			}
-
-			GRIB_CHECK(grib_get_double_array(h,"values",values,&size),argv[i]);
-
-			for(j = 0; j < count; j++)
-				intervals[j] = 0;
-
-
-			if(bitmap != 255)
-			{
-
-				double missing;
-				GRIB_CHECK(grib_get_double(h,"missingValue",&missing),argv[i]);
-
-				min = max = missing;
-
-				for(j = 0; j < size ; j++)
-				{
-					if((min == missing) || ((values[j] != missing) && (min>values[j]))) min = values[j];
-					if((max == missing) || ((values[j] != missing) && (max<values[j]))) max = values[j];
-				}	
-
-				delta = max- min; if(delta == 0) delta = 1;
-
-				for(j = 0; j < size; j++)
-				{
-					if(values[j] != missing)
-					{
-						int x = (values[j] - min)/delta * count;
-					        if(x==count) x=x-1; /*handle the absolute  maximum*/
-						intervals[x]++;
-					}
-				}
-
-			}
-			else
-			{
-				min = max = values[0];
-				for(j = 1; j < size ; j++)
-				{
-					if(min>values[j]) min = values[j];
-					if(max<values[j]) max = values[j];
-				}
-
-				delta = max- min; if(delta == 0) delta = 1;
-
-				for(j = 0; j < size; j++)
-				{
-					int x = (values[j] - min)/delta * count;
-					if(x==count) x=x-1; /*handle the absolute  maximum*/
-					intervals[x]++;
-				}
-			}
-
-
-			for(j = 0; j < name_count; j++)
-			{
-				char v[1024]; size_t s = sizeof(v);
-				GRIB_CHECK(grib_get_string(h,names[j],v,&s),names[j]);
-				printf(" %s",v);
-			}
-
-			printf("\nmin=%g max=%g size=%ld\n",min,max,(long)size);
-			for(j = 0; j < count; j++)
-				printf(" %g:%g",
-						j*(max-min)/count + min
-						,
-						(j+1)*(max-min)/count + min
-					  );
-			printf("\n");
-
-			for(j = 0; j < count; j++)
-				printf(" %ld",intervals[j] );
-			printf("\n");
-
-		}
-
-		GRIB_CHECK(e,argv[i]);
-		fclose(in);
-	}
-
-	return 0;
+    int i,j;
+    FILE *in;
+    int e;
+    grib_handle *h;
+    double* values = NULL;
+    size_t size;
+    size_t last_size = 0;
+    double min,max;
+    long count = 10;
+    long intervals[10];
+    const char *names[1024];
+    int name_count = 0;
+
+    if(argc < 2) usage(argv[0]);
+
+    for(i = 1; i < argc; i++)
+    {
+        if(argv[i][0] == '-') {
+            names[name_count++] = argv[i]+1;
+            continue;
+        }
+
+        in = fopen(argv[i],"r");
+        if(!in) {
+            perror(argv[i]);
+            exit(1);
+        }
+
+        while( (h = grib_handle_new_from_file(NULL,in,&e)) != NULL )
+        {
+            long missingValuesPresent;
+            double delta;
+            GRIB_CHECK(grib_get_long(h,"missingValuesPresent",&missingValuesPresent),argv[i]);
+
+            GRIB_CHECK(grib_get_size(h,"values",&size),argv[i]);
+
+            if(size > last_size)
+            {
+                if(values) free(values);
+                values = (double*)malloc(size*sizeof(double));
+                last_size = size;
+                if (!values) {
+                    fprintf(stderr, "Failed to allocate memory for values (%ld bytes)\n", size*sizeof(double));
+                    exit(1);
+                }
+            }
+
+            GRIB_CHECK(grib_get_double_array(h,"values",values,&size),argv[i]);
+
+            for(j = 0; j < count; j++)
+                intervals[j] = 0;
+
+            if(missingValuesPresent)
+            {
+                double missing;
+                GRIB_CHECK(grib_get_double(h,"missingValue",&missing),argv[i]);
+
+                min = max = missing;
+
+                for(j = 0; j < size ; j++)
+                {
+                    if((min == missing) || ((values[j] != missing) && (min>values[j]))) min = values[j];
+                    if((max == missing) || ((values[j] != missing) && (max<values[j]))) max = values[j];
+                }
+
+                delta = max- min; if(delta == 0) delta = 1;
+
+                for(j = 0; j < size; j++)
+                {
+                    if(values[j] != missing)
+                    {
+                        int x = (values[j] - min)/delta * count;
+                        if(x==count) x=x-1; /*handle the absolute  maximum*/
+                        intervals[x]++;
+                    }
+                }
+            }
+            else
+            {
+                min = max = values[0];
+                for(j = 1; j < size ; j++)
+                {
+                    if(min>values[j]) min = values[j];
+                    if(max<values[j]) max = values[j];
+                }
+
+                delta = max- min; if(delta == 0) delta = 1;
+
+                for(j = 0; j < size; j++)
+                {
+                    int x = (values[j] - min)/delta * count;
+                    if(x==count) x=x-1; /*handle the absolute  maximum*/
+                    intervals[x]++;
+                }
+            }
+
+            for(j = 0; j < name_count; j++)
+            {
+                char v[1024]; size_t s = sizeof(v);
+                GRIB_CHECK(grib_get_string(h,names[j],v,&s),names[j]);
+                printf(" %s",v);
+            }
+
+            printf("\nmin=%g max=%g size=%ld\n",min,max,(long)size);
+            for(j = 0; j < count; j++)
+                printf(" %g:%g",
+                        j*(max-min)/count + min
+                        ,
+                        (j+1)*(max-min)/count + min
+                );
+            printf("\n");
+
+            for(j = 0; j < count; j++)
+                printf(" %ld",intervals[j] );
+            printf("\n");
+        }
+
+        GRIB_CHECK(e,argv[i]);
+        fclose(in);
+    }
+
+    return 0;
 }
diff --git a/tools/grib_to_netcdf.c b/tools/grib_to_netcdf.c
index 4af8443..964eb8b 100644
--- a/tools/grib_to_netcdf.c
+++ b/tools/grib_to_netcdf.c
@@ -1089,16 +1089,16 @@ static err to_expand_mem(field *g)
         g->values = (double*) grib_context_malloc(ctx, sizeof(double) * g->value_count);
         if((e = grib_get_double_array(g->handle, "values", g->values, &count)))
         {
-            grib_context_log(ctx, GRIB_LOG_ERROR, "ecCodes: cannot get decode values %s", grib_get_error_message(e));
+            grib_context_log(ctx, GRIB_LOG_ERROR, "ecCodes: cannot decode values %s", grib_get_error_message(e));
             return e;
         }
 
         if(count != g->value_count)
             grib_context_log(ctx, GRIB_LOG_FATAL, "ecCodes: value count mismatch %d %d", count, g->value_count);
 
-        if((e = grib_get_long(g->handle, "bitmapPresent", &bitmap)))
+        if((e = grib_get_long(g->handle, "missingValuesPresent", &bitmap)))
         {
-            grib_context_log(ctx, GRIB_LOG_ERROR, "ecCodes: cannot get bitmapPresent %s", grib_get_error_message(e));
+            grib_context_log(ctx, GRIB_LOG_ERROR, "ecCodes: cannot get missingValuesPresent %s", grib_get_error_message(e));
             return e;
         }
 
diff --git a/version.sh b/version.sh
index 207db4d..9495f0d 100644
--- a/version.sh
+++ b/version.sh
@@ -15,7 +15,7 @@ PACKAGE_NAME='eccodes'
 # Package version
 ECCODES_MAJOR_VERSION=2
 ECCODES_MINOR_VERSION=4
-ECCODES_REVISION_VERSION=0
+ECCODES_REVISION_VERSION=1
 
 ECCODES_CURRENT=1
 ECCODES_REVISION=0

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/eccodes.git



More information about the debian-science-commits mailing list