From 8ffd7b73ecbb2d5f7952d1a84c6d5c023d19968c Mon Sep 17 00:00:00 2001
From: Mamoru TASAKA <mtasaka@fedoraproject.org>
Date: Tue, 21 Dec 2021 20:07:43 +0900
Subject: [PATCH] g1second_order_general_extended_packing: preserve significant
 bits for signedness on 32bit

In g1second_order_general_extended_packing, firstOrderValues or so are restored
with grib_get_long_array(), and the restored values are stored in "long" type array.
So on 32 bit system, when "bits_per_value" is set to 32 and 32 bit unsigned values
are saved with grib_set_long_array(), restored values by grib_get_long_array()
are recognized as negative value, which results in wrong result
(in grib_second_order.sh).

For now, on linux 32 bit system, save 1 significant bit for signedness and
restrict bits_per_value to 31, and relax allowed error due to this change.
---
 ...lass_data_g1second_order_general_extended_packing.c | 10 +++++++++-
 tests/grib_second_order.sh                             |  7 ++++++-
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/grib_accessor_class_data_g1second_order_general_extended_packing.c b/src/grib_accessor_class_data_g1second_order_general_extended_packing.c
index 7293d26b..986b1528 100644
--- a/src/grib_accessor_class_data_g1second_order_general_extended_packing.c
+++ b/src/grib_accessor_class_data_g1second_order_general_extended_packing.c
@@ -1248,7 +1248,15 @@ static int get_bits_per_value(grib_handle* h, const char* bits_per_value_str, lo
          * because it has already been changed to second order!
          * We have to take precision=1 for IEEE which is 32bits
          */
-        *bits_per_value = 32;
+        /* But on 32bit, the most significant bit is for signnedness, so we have to drop one bit
+         * because it has already been changed to second order!
+         * We have to take precision=1 for IEEE which is 32bits
+         */
+        if (sizeof(long) == 4) {
+            *bits_per_value = 31;
+        } else {
+            *bits_per_value = 32;
+        }
     }
     return err;
 }
diff --git a/tests/grib_second_order.sh b/tests/grib_second_order.sh
index be2e2184..ae01c20a 100755
--- a/tests/grib_second_order.sh
+++ b/tests/grib_second_order.sh
@@ -143,11 +143,16 @@ grib_check_key_equals $temp3 packingType grid_second_order
 
 # ECC-1219: packingType conversion from grid_ieee to grid_second_order
 # ---------------------------------------------------------------------
+if [ $ECCODES_ON_LINUX_32BIT -eq 1 ] ; then
+    ALLOWED_ERROR=7e-06
+else
+    ALLOWED_ERROR=3e-06
+fi
 if [ $ECCODES_ON_WINDOWS -eq 0 ]; then
     infile=grid_ieee.grib
     ${tools_dir}/grib_set -r -s packingType=grid_second_order $infile $temp1
     grib_check_key_equals $temp1 packingType grid_second_order
-    ${tools_dir}/grib_compare -cdata:n -R all=3e-06 $infile $temp1
+    ${tools_dir}/grib_compare -cdata:n -R all=$ALLOWED_ERROR $infile $temp1
 fi
 
 # Second order doesn't have a proper representation for constant fields
-- 
2.33.1

