https://gcc.gnu.org/g:5d9ea620152f7f7d2ee290ff35b665f95a4f6bf7

commit r17-4048-g5d9ea620152f7f7d2ee290ff35b665f95a4f6bf7
Author: Robert Dubner <[email protected]>
Date:   Wed Sep 9 21:22:42 2026 -0400

    cobol: Faster execution of floating-point ADD/SUBTRACT.
    
    Do GENERIC arithmetic instead of calling library routines.
    
    gcc/cobol/ChangeLog:
    
            * compare.cc (digiter): Spelling in comment.
            * genmath.cc (fast_add): Fix aliasing problem.
            (get_fbinary_value): New function for converting fixed-format to
            floating point, with rdigit scaling.
            (add_floats): Stop using library routines in favor of GENERIC.
            (add_format_3): Likewise.
            (subtract_floats): Likewise.
            (subtract_format_3): Likewise.
    
    libgcobol/ChangeLog:
    
            * gmath.cc (__gg__conditional_stash_float): New routine supporting
            faster GENERIC arithmetic.
            (__gg__add_fixed_phase1): Remove obsolete function.
            (__gg__addf1_fixed_phase2): Likewise.
            (__gg__fixed_phase2_assign_to_c): Likewise.
            (__gg__add_float_phase1): Likewise.
            (__gg__addf1_float_phase2): Likewise.
            (__gg__float_phase2_assign_to_c): Likewise.
            (__gg__addf3): Likewise.
            (__gg__subtractf1_fixed_phase2): Likewise.
            (__gg__subtractf2_fixed_phase1): Likewise.
            (__gg__subtractf1_float_phase2): Likewise.
            (__gg__subtractf2_float_phase1): Likewise.
            (__gg__subtractf3): Likewise.

Diff:
---
 gcc/cobol/compare.cc |   2 +-
 gcc/cobol/genmath.cc | 319 ++++++++++++++++----------
 libgcobol/gmath.cc   | 629 ++-------------------------------------------------
 3 files changed, 211 insertions(+), 739 deletions(-)

diff --git a/gcc/cobol/compare.cc b/gcc/cobol/compare.cc
index f74053825ef3..eabfe650082a 100644
--- a/gcc/cobol/compare.cc
+++ b/gcc/cobol/compare.cc
@@ -172,7 +172,7 @@ digiter(int &digits, int &rdigits, const cbl_refer_t &refer)
     if( rdigits < 0 )
       {
       // This is like 999PPPP with rdigits = -4
-      // So, digits evntually becomes 7, and rdigits becomes 0
+      // So, digits eventually becomes 7, and rdigits becomes 0
       // Our caller will have to multiply by 10^4 to get the 999 digits into
       // the right place.
       rdigits = 0;
diff --git a/gcc/cobol/genmath.cc b/gcc/cobol/genmath.cc
index cbc17dc4a578..a6766c95e8c2 100644
--- a/gcc/cobol/genmath.cc
+++ b/gcc/cobol/genmath.cc
@@ -502,21 +502,10 @@ fast_add( size_t nC, cbl_num_result_t *C,
 
         if( refer_is_clean(C[0].refer) )
           {
-          // We are accumulating into memory
-
-          if(is_working_storage(C[0].refer)
-             && C[0].refer.field->offset == 0 )
-            {
-            gg_assign(  C[0].refer.field->data_decl_node,
-                        gg_cast(TREE_TYPE(C[0].refer.field->data_decl_node),
-                        gg_add( C[0].refer.field->data_decl_node, A_value)));
-            }
-          else
-            {
-            tree dest_addr = member(C[0].refer.field->var_decl_node, "data");
-            tree dest_value = safe_load(dest_addr, dest_type);
-            safe_store(dest_addr, dest_type, gg_add(dest_value, A_value));
-            }
+          // We are accumulating into memory with no offset
+          tree dest_addr = member(C[0].refer.field->var_decl_node, "data");
+          tree dest_value = safe_load(dest_addr, dest_type);
+          safe_store(dest_addr, dest_type, gg_add(dest_value, A_value));
           }
         else
           {
@@ -918,6 +907,40 @@ fast_divide(size_t nC, cbl_num_result_t *C,
   return retval;
   }
 
+tree get_fbinary_value(const cbl_refer_t &refer)
+  {
+  tree retval = get_binary_value(refer, FLOAT128);
+  int scale = refer.field->data.rdigits;
+  if( scale )
+    {
+    if( refer.field->attr & scaled_e )
+      {
+      if( refer.field->data.rdigits < 0 )
+        {
+        // This is like 999PPPP with rdigits = -4
+        // We multiply by 10^4 to get the 999 digits into place
+        scale = -refer.field->data.rdigits;
+        FIXED_WIDE_INT(128) power_of_ten = get_power_of_ten(scale);
+        tree pot = wide_int_to_tree(INT128, power_of_ten);
+        retval = gg_multiply(retval, gg_cast(FLOAT128, pot));
+        scale = 0;
+        }
+      else
+        {
+        // This is like PPP9999.  Digits stays 3, and rdigits becomes 7
+        scale += refer.field->data.digits;
+        }
+      }
+    if( scale )
+      {
+      FIXED_WIDE_INT(128) power_of_ten = get_power_of_ten(scale);
+      tree pot = wide_int_to_tree(INT128, power_of_ten);
+      retval = gg_real_divide(retval, gg_cast(FLOAT128, pot));
+      }
+    }
+  return retval;
+  }
+
 static bool
 add_floats( size_t nC, cbl_num_result_t *C,
             size_t nA, cbl_refer_t *A,
@@ -926,6 +949,8 @@ add_floats( size_t nC, cbl_num_result_t *C,
             cbl_label_t *not_error,
             tree         compute_error )
   {
+  gcc_assert(nC > 0);
+  gcc_assert(nA > 0);
   bool handled = false;
 
   bool computation_is_float =    is_somebody_float(nA, A)
@@ -941,28 +966,29 @@ add_floats( size_t nC, cbl_num_result_t *C,
 
         set_up_arithmetic_error_handler(error,
                                         not_error);
-        // Do phase 1, which calculates the subtotal and puts it into a
-        // temporary location
-        arithmetic_operation( 0, NULL,
-                              nA, A,
-                              0, NULL,
-                              format,
-                              error,
-                              not_error,
-                              compute_error,
-                              "__gg__add_float_phase1");
+        tree initial = gg_define_variable(FLOAT128);
+        gg_assign(initial, get_fbinary_value(A[0]));
+        tree next = gg_define_variable(FLOAT128);
+        for(size_t i=1; i<nA; i++ )
+          {
+          gg_assign(next, get_fbinary_value(A[i]));
+          gg_assign(initial, gg_add(initial, next));
+          }
 
-        // Do phase 2, which accumulates the subtotal into each target 
location in turn
         for(size_t i=0; i<nC; i++)
           {
-          arithmetic_operation(1, &C[i],
-                                0, NULL,
-                                0, NULL,
-                                format,
-                                error,
-                                not_error,
-                                compute_error,
-                                "__gg__addf1_float_phase2");
+          gg_assign(next, gg_add(initial, get_fbinary_value(C[i].refer)));
+          gg_assign(gg_indirect(compute_error),
+                    gg_bitwise_or(gg_indirect(compute_error),
+                                  gg_call_expr(
+                         INT,
+                         "__gg__conditional_stash_float",
+                         gg_get_address_of(C[i].refer.field->var_decl_node),
+                         refer_offset(C[i].refer),
+                         size_t_zero_node,
+                         next,
+                         build_int_cst_type(INT, C[i].rounded),
+                         NULL_TREE)));
           }
         arithmetic_error_handler( error,
                                   not_error,
@@ -977,28 +1003,28 @@ add_floats( size_t nC, cbl_num_result_t *C,
         // Float format 2
         set_up_arithmetic_error_handler(error,
                                         not_error);
-        // Do phase 1, which calculates the subtotal and puts it into a
-        // temporary location
-        arithmetic_operation( 0, NULL,
-                              nA, A,
-                              0, NULL,
-                              format,
-                              error,
-                              not_error,
-                              compute_error,
-                              "__gg__add_float_phase1");
+        tree initial = gg_define_variable(FLOAT128);
+        gg_assign(initial, get_fbinary_value(A[0]));
+        for(size_t i=1; i<nA; i++ )
+          {
+          tree next = gg_define_variable(FLOAT128);
+          gg_assign(next, get_fbinary_value(A[i]));
+          gg_assign(initial, gg_add(initial, next));
+          }
 
-        // Do phase 2, which puts the subtotal into each target location in 
turn
         for(size_t i=0; i<nC; i++)
           {
-          arithmetic_operation(1, &C[i],
-                                0, NULL,
-                                0, NULL,
-                                format,
-                                error,
-                                not_error,
-                                compute_error,
-                                "__gg__float_phase2_assign_to_c");
+          gg_assign(gg_indirect(compute_error),
+                    gg_bitwise_or(gg_indirect(compute_error),
+                                  gg_call_expr(
+                         INT,
+                         "__gg__conditional_stash_float",
+                         gg_get_address_of(C[i].refer.field->var_decl_node),
+                         refer_offset(C[i].refer),
+                         size_t_zero_node,
+                         initial,
+                         build_int_cst_type(INT, C[i].rounded),
+                         NULL_TREE)));
           }
         arithmetic_error_handler( error,
                                   not_error,
@@ -1015,14 +1041,21 @@ add_floats( size_t nC, cbl_num_result_t *C,
 
         set_up_arithmetic_error_handler(error,
                                         not_error);
-        arithmetic_operation(nC, C,
-                              nA, A,
-                              0, NULL,
-                              format,
-                              error,
-                              not_error,
-                              compute_error,
-                              "__gg__addf3");
+        for(size_t i=0; i<nC; i++)
+          {
+          gg_assign(gg_indirect(compute_error),
+                    gg_bitwise_or(gg_indirect(compute_error),
+                                  gg_call_expr(
+                         INT,
+                         "__gg__conditional_stash_float",
+                         gg_get_address_of(C[i].refer.field->var_decl_node),
+                         refer_offset(C[i].refer),
+                         size_t_zero_node,
+                         gg_add(get_fbinary_value(C[i].refer),
+                                get_fbinary_value(A[i])),
+                         build_int_cst_type(INT, C[i].rounded),
+                         NULL_TREE)));
+          }
         arithmetic_error_handler( error,
                                   not_error,
                                   compute_error);
@@ -2129,14 +2162,28 @@ add_format_3( size_t nC, cbl_num_result_t *C,
 
     set_up_arithmetic_error_handler(error,
                                     not_error);
-    arithmetic_operation(nC, C,
-                          nA, A,
-                          0, NULL,
-                          format,
-                          error,
-                          not_error,
-                          compute_error,
-                          "__gg__addf3");
+    for(size_t i=0; i<nC; i++)
+      {
+      int digits = 0;
+      int rdigits = 0;
+      determine_excess_rdigits(1, &C[i].refer, digits, rdigits);
+      determine_excess_rdigits(1, &A[i], digits, rdigits);
+      tree cval = add_phase_1(1, &C[i].refer, rdigits);
+      tree aval = add_phase_1(1, &A[i], rdigits);
+      gg_assign(gg_indirect(compute_error),
+                gg_bitwise_or(gg_indirect(compute_error), gg_call_expr(
+                           INT,
+                           "__gg__conditional_stash",
+                           gg_get_address_of(C[i].refer.field->var_decl_node),
+                           refer_offset(C[i].refer),
+                           error || not_error
+                                    ? build_int_cst_type(INT, ON_SIZE_ERROR)
+                                    : integer_zero_node,
+                           gg_add(cval, aval),
+                           build_int_cst_type(INT, rdigits),
+                           build_int_cst_type(INT, C[i].rounded),
+                           NULL_TREE)));
+      }
     arithmetic_error_handler( error,
                               not_error,
                               compute_error);
@@ -2803,32 +2850,33 @@ subtract_floats( size_t nC, cbl_num_result_t *C,
       {
       case no_giving_e:
         {
-        // Float format 1
+        // Float SUBTRACT format 1
 
         set_up_arithmetic_error_handler(error,
                                         not_error);
-        // Do phase 1, which calculates the subtotal and puts it into a
-        // temporary location
-        arithmetic_operation( 0, NULL,
-                              nA, A,
-                              0, NULL,
-                              format,
-                              error,
-                              not_error,
-                              compute_error,
-                              "__gg__add_float_phase1");
+        tree initial = gg_define_variable(FLOAT128);
+        gg_assign(initial, get_fbinary_value(A[0]));
+        tree next = gg_define_variable(FLOAT128);
+        for(size_t i=1; i<nA; i++ )
+          {
+          gg_assign(next, get_fbinary_value(A[i]));
+          gg_assign(initial, gg_add(initial, next));
+          }
 
-        // Do phase 2, which subtracts the subtotal from each target in turn
         for(size_t i=0; i<nC; i++)
           {
-          arithmetic_operation(1, &C[i],
-                                0, NULL,
-                                0, NULL,
-                                format,
-                                error,
-                                not_error,
-                                compute_error,
-                                "__gg__subtractf1_float_phase2");
+          gg_assign(next, gg_subtract(get_fbinary_value(C[i].refer), initial));
+          gg_assign(gg_indirect(compute_error),
+                    gg_bitwise_or(gg_indirect(compute_error),
+                                  gg_call_expr(
+                         INT,
+                         "__gg__conditional_stash_float",
+                         gg_get_address_of(C[i].refer.field->var_decl_node),
+                         refer_offset(C[i].refer),
+                         size_t_zero_node,
+                         next,
+                         build_int_cst_type(INT, C[i].rounded),
+                         NULL_TREE)));
           }
         arithmetic_error_handler( error,
                                   not_error,
@@ -2846,33 +2894,33 @@ subtract_floats( size_t nC, cbl_num_result_t *C,
         gcc_assert(nB == 1);
         set_up_arithmetic_error_handler(error,
                                         not_error);
-        // Do phase 1, which calculates the subtotal and puts it into a
-        // temporary location
-        arithmetic_operation( 0, NULL,
-                              nA, A,
-                              nB, B,
-                              format,
-                              error,
-                              not_error,
-                              compute_error,
-                              "__gg__subtractf2_float_phase1");
+        tree initial = gg_define_variable(FLOAT128);
+        gg_assign(initial, get_fbinary_value(A[0]));
+        tree next = gg_define_variable(FLOAT128);
+        for(size_t i=1; i<nA; i++ )
+          {
+          gg_assign(next, get_fbinary_value(A[i]));
+          gg_assign(initial, gg_add(initial, next));
+          }
+        gg_assign(next, gg_subtract(get_fbinary_value(B[0]), initial));
 
-        // Do phase 2, which puts the subtotal into each target location in 
turn
         for(size_t i=0; i<nC; i++)
           {
-          arithmetic_operation(1, &C[i],
-                                0, NULL,
-                                0, NULL,
-                                format,
-                                error,
-                                not_error,
-                                compute_error,
-                                "__gg__float_phase2_assign_to_c");
+          gg_assign(gg_indirect(compute_error),
+                    gg_bitwise_or(gg_indirect(compute_error),
+                                  gg_call_expr(
+                         INT,
+                         "__gg__conditional_stash_float",
+                         gg_get_address_of(C[i].refer.field->var_decl_node),
+                         refer_offset(C[i].refer),
+                         size_t_zero_node,
+                         next,
+                         build_int_cst_type(INT, C[i].rounded),
+                         NULL_TREE)));
           }
         arithmetic_error_handler( error,
                                   not_error,
                                   compute_error);
-
         handled = true;
         break;
         }
@@ -2884,14 +2932,21 @@ subtract_floats( size_t nC, cbl_num_result_t *C,
 
         set_up_arithmetic_error_handler(error,
                                         not_error);
-        arithmetic_operation(nC, C,
-                              nA, A,
-                              0, NULL,
-                              format,
-                              error,
-                              not_error,
-                              compute_error,
-                              "__gg__subtractf3");
+        for(size_t i=0; i<nC; i++)
+          {
+          gg_assign(gg_indirect(compute_error),
+                    gg_bitwise_or(gg_indirect(compute_error),
+                                  gg_call_expr(
+                         INT,
+                         "__gg__conditional_stash_float",
+                         gg_get_address_of(C[i].refer.field->var_decl_node),
+                         refer_offset(C[i].refer),
+                         size_t_zero_node,
+                         gg_subtract(get_fbinary_value(C[i].refer),
+                                     get_fbinary_value(A[i])),
+                         build_int_cst_type(INT, C[i].rounded),
+                         NULL_TREE)));
+          }
         arithmetic_error_handler( error,
                                   not_error,
                                   compute_error);
@@ -3012,14 +3067,28 @@ subtract_format_3(size_t nC, cbl_num_result_t *C,
 
     set_up_arithmetic_error_handler(error,
                                     not_error);
-    arithmetic_operation(nC, C,
-                          nA, A,
-                          0, NULL,
-                          format,
-                          error,
-                          not_error,
-                          compute_error,
-                          "__gg__subtractf3");
+    for(size_t i=0; i<nC; i++)
+      {
+      int digits = 0;
+      int rdigits = 0;
+      determine_excess_rdigits(1, &C[i].refer, digits, rdigits);
+      determine_excess_rdigits(1, &A[i], digits, rdigits);
+      tree cval = add_phase_1(1, &C[i].refer, rdigits);
+      tree aval = add_phase_1(1, &A[i], rdigits);
+      gg_assign(gg_indirect(compute_error),
+                gg_bitwise_or(gg_indirect(compute_error), gg_call_expr(
+                           INT,
+                           "__gg__conditional_stash",
+                           gg_get_address_of(C[i].refer.field->var_decl_node),
+                           refer_offset(C[i].refer),
+                           error || not_error
+                                    ? build_int_cst_type(INT, ON_SIZE_ERROR)
+                                    : integer_zero_node,
+                           gg_subtract(cval, aval),
+                           build_int_cst_type(INT, rdigits),
+                           build_int_cst_type(INT, C[i].rounded),
+                           NULL_TREE)));
+      }
     arithmetic_error_handler( error,
                               not_error,
                               compute_error);
diff --git a/libgcobol/gmath.cc b/libgcobol/gmath.cc
index 70096ccea93d..baa1214bb842 100644
--- a/libgcobol/gmath.cc
+++ b/libgcobol/gmath.cc
@@ -173,6 +173,22 @@ conditional_stash(  cblc_field_t *destination,
   return retval;
   }
 
+extern "C"
+int
+__gg__conditional_stash_float(  cblc_field_t *destination,
+                                size_t        destination_o,
+                                bool          on_error_flag,
+                                GCOB_FP128    value,
+                                cbl_round_t   rounded)
+  {
+  return conditional_stash(destination,
+                           destination_o,
+                           destination->capacity,
+                           on_error_flag,
+                           value,
+                           rounded);
+  }
+
 static
 GCOB_FP128
 divide_helper_float(GCOB_FP128 a_value,
@@ -649,619 +665,6 @@ get_int256_from_qualified_field(int256 &var,
     }
   }
 
-static int256 phase1_result;
-
-static GCOB_FP128 phase1_result_float;
-
-extern "C"
-void
-__gg__add_fixed_phase1( cbl_arith_format_t ,
-                        size_t nA,
-                  const cblc_referlet_t *AA,
-                        size_t ,
-                        cblc_referlet_t *,
-                        size_t ,
-                        cblc_referlet_t *,
-                  const cbl_round_t  *,
-                        int           ,
-                        int          *compute_error
-                        )
-  {
-  // Our job is to add together the nA fixed-point values in the A[] array
-
-  // The result goes into the temporary phase1_result.
-
-  // Let us prime the pump with the first value of A[]
-  get_int256_from_qualified_field(phase1_result,
-                                  AA[0].field,
-                                  AA[0].offset,
-                                  AA[0].size);
-
-  // We now go into a loop adding each of the A[] values to phase1_result:
-
-  for( size_t i=1; i<nA; i++ )
-    {
-    int256 temp = {};
-    get_int256_from_qualified_field(temp,
-                                    AA[i].field,
-                                    AA[i].offset,
-                                    AA[i].size);
-
-    add_int256_to_int256(phase1_result, temp);
-    }
-
-  // phase1_result/phase1_result.rdigits now reflect the sum of all A[]
-
-  int overflow = squeeze_int256(phase1_result);
-  if( overflow )
-    {
-    *compute_error |= compute_error_overflow;
-    }
-  }
-
-extern "C"
-void
-__gg__addf1_fixed_phase2( cbl_arith_format_t ,
-                          size_t ,
-                          cblc_referlet_t *,
-                          size_t ,
-                          cblc_referlet_t *,
-                          size_t ,
-                    const cblc_referlet_t *C,
-                    const cbl_round_t  *rounded,
-                          int           on_error_flag,
-                          int          *compute_error
-                          )
-  {
-  // This is the assignment phase of an ADD Format 1
-
-  // We take phase1_result and accumulate it into C
-  bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR);
-
-  if( C[0].field->type == FldFloat)
-    {
-    // The target we need to accumulate into is a floating-point number, so we
-    // need to convert our fixed-point intermediate into floating point and
-    // proceed accordingly.
-
-    // Convert the intermediate
-    GCOB_FP128 value_a = (GCOB_FP128)int256_get_u128(phase1_result, 0);
-    value_a /= __gg__power_of_ten(phase1_result.rdigits);
-
-    // Pick up the target
-    GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[0].field,
-                                                             C[0].offset,
-                                                             C[0].size);
-
-    value_a += value_b;
-
-    // At this point, we assign running_sum to *C.
-    *compute_error |= conditional_stash(C[0].field,
-                                        C[0].offset,
-                                        C[0].size,
-                                        on_size_error,
-                                        value_a,
-                                        *rounded++);
-    }
-  else
-    {
-    // We have a fixed-point intermediate, and we are accumulating into a
-    // fixed point target.
-    int256 value_a   = phase1_result;
-    int256 value_b = {};
-
-    value_a.rdigits = phase1_result.rdigits;
-
-    get_int256_from_qualified_field(value_b,
-                                    C[0].field,
-                                    C[0].offset,
-                                    C[0].size);
-    add_int256_to_int256(value_a, value_b);
-
-    int overflow = squeeze_int256(value_a);
-    if( overflow )
-      {
-      *compute_error |= compute_error_overflow;
-      }
-
-      // At this point, we assign running_sum to *C.
-    *compute_error |= conditional_stash(C[0].field,
-                                        C[0].offset,
-                                        C[0].size,
-                                        on_size_error,
-                                        int256_get_u128(value_a, 0),
-                                        value_a.rdigits,
-                                        *rounded++);
-    }
-  }
-
-extern "C"
-void
-__gg__fixed_phase2_assign_to_c( cbl_arith_format_t ,
-                                size_t ,
-                                cblc_referlet_t *,
-                                size_t ,
-                                cblc_referlet_t *,
-                                size_t ,
-                          const cblc_referlet_t *CC,
-                          const cbl_round_t  *rounded,
-                                int           on_error_flag,
-                                int          *compute_error
-                                )
-  {
-  // This is the assignment phase of an ADD or SUBTRACT Format 2
-
-  // We take phase1_result and put it into C
-  bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR);
-
-  if( CC[0].field->type == FldFloat)
-    {
-    // The target we need to accumulate into is a floating-point number, so we
-    // need to convert our fixed-point intermediate into floating point and
-    // proceed accordingly.
-
-    // Convert the intermediate
-    GCOB_FP128 value_a = (GCOB_FP128)int256_get_u128(phase1_result, 0);
-    value_a /= __gg__power_of_ten(phase1_result.rdigits);
-
-    *compute_error |= conditional_stash(CC[0].field, CC[0].offset, CC[0].size,
-                                        on_size_error,
-                                        value_a,
-                                       *rounded++);
-    }
-  else
-    {
-    // We have a fixed-point intermediate, and we are accumulating intoi a
-    // fixed point target.
-    int256 value_a   = phase1_result;
-    value_a.rdigits = phase1_result.rdigits;
-
-    int overflow = squeeze_int256(value_a);
-    if( overflow )
-      {
-      *compute_error |= compute_error_overflow;
-      }
-
-    if( CC[0].field->type == FldPointer )
-      {
-      // In case somebody does pointer arithmetic that goes negative, we need
-      // to make the top 64 bits positive.  Otherwise, the conditional stash
-      // will see that FldPointer is not signable, and force the value
-      // positive with a two's complement.
-      int256_set_u128(value_a,
-                      0,
-                      int256_get_u128(value_a, 0) & 0xFFFFFFFFFFFFFFFFULL);
-      }
-
-      // At this point, we assign that value to *C.
-    *compute_error |= conditional_stash(CC[0].field, CC[0].offset, CC[0].size,
-                                        on_size_error,
-                                        int256_get_u128(value_a, 0),
-                                        value_a.rdigits,
-                                       *rounded++);
-    }
-  }
-
-extern "C"
-void
-__gg__add_float_phase1( cbl_arith_format_t ,
-                        size_t nA,
-                  const cblc_referlet_t *A,
-                        size_t ,
-                        cblc_referlet_t *,
-                        size_t ,
-                        cblc_referlet_t *,
-                  const cbl_round_t  *,
-                        int           ,
-                        int          *compute_error
-                        )
-  {
-  // Our job is to add together the nA floating-point values in the A[] array
-
-  // The result goes into the temporary phase1_result_ffloat.
-
-  // Let us prime the pump with the first value of A[]
-  phase1_result_float = __gg__float128_from_qualified_field(A[0].field,
-                                                            A[0].offset,
-                                                            A[0].size);
-
-  // We now go into a loop adding each of the A[] values to phase1_result_flt:
-
-  for( size_t i=1; i<nA; i++ )
-    {
-    GCOB_FP128 temp = __gg__float128_from_qualified_field(A[i].field,
-                                                          A[i].offset,
-                                                          A[i].size);
-    phase1_result_float = addition_helper_float(phase1_result_float,
-                                                temp,
-                                                compute_error);
-    }
-  }
-
-extern "C"
-void
-__gg__addf1_float_phase2( cbl_arith_format_t ,
-                          size_t ,
-                          cblc_referlet_t *,
-                          size_t ,
-                          cblc_referlet_t *,
-                          size_t ,
-                    const cblc_referlet_t *C,
-                    const cbl_round_t  *rounded,
-                          int           on_error_flag,
-                          int          *compute_error
-                          )
-  {
-  bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR);
-  // This is the assignment phase of an ADD Format 2
-  // We take phase1_result and accumulate it into C
-
-  GCOB_FP128 temp = __gg__float128_from_qualified_field(C[0].field,
-                                                        C[0].offset,
-                                                        C[0].size);
-  temp = addition_helper_float(temp, phase1_result_float, compute_error);
-  *compute_error |= conditional_stash(C[0].field, C[0].offset, C[0].size,
-                                      on_size_error,
-                                      temp,
-                                     *rounded++);
-  }
-
-extern "C"
-void
-__gg__float_phase2_assign_to_c( cbl_arith_format_t ,
-                          size_t ,
-                          cblc_referlet_t *,
-                          size_t ,
-                          cblc_referlet_t *,
-                          size_t ,
-                    const cblc_referlet_t *C,
-                    const cbl_round_t  *rounded,
-                          int           on_error_flag,
-                          int          *compute_error
-                          )
-  {
-  bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR);
-  // This is the assignment phase of an ADD Format 2
-    // We take phase1_result and put it into C
-
-  *compute_error |= conditional_stash(C[0].field, C[0].offset, C[0].size,
-                                      on_size_error,
-                                      phase1_result_float,
-                                     *rounded++);
-  }
-
-extern "C"
-void
-__gg__addf3(cbl_arith_format_t ,
-            size_t nA,
-       const cblc_referlet_t *A,
-            size_t ,
-            cblc_referlet_t *,
-            size_t ,
-       const cblc_referlet_t *C,
-      const cbl_round_t  *rounded,
-            int           on_error_flag,
-            int          *compute_error
-            )
-  {
-  // This is an ADD Format 3.  Each A[i] gets accumulated into each C[i].  When
-  // both are fixed, we do fixed arithmetic.  When either is a FldFloat, we
-  // do floating-point arithmetic.
-  bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR);
-
-  for(size_t i=0; i<nA; i++)
-    {
-    if( A[i].field->type == FldFloat || C[i].field->type == FldFloat )
-      {
-      GCOB_FP128 value_a = __gg__float128_from_qualified_field(A[i].field,
-                                                               A[i].offset,
-                                                               A[i].size);
-      GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[i].field,
-                                                               C[i].offset,
-                                                               C[i].size);
-
-      value_a = addition_helper_float(value_a, value_b, compute_error);
-
-        // At this point, we assign the sum to *C.
-      *compute_error |= conditional_stash(C[i].field, C[i].offset, C[i].size,
-                                          on_size_error,
-                                          value_a,
-                                          *rounded++);
-      }
-    else
-      {
-      // We have are doing fixed-point arithmetic.
-      int256 value_a;
-      int256 value_b;
-
-      get_int256_from_qualified_field(value_a,
-                                      A[i].field,
-                                      A[i].offset,
-                                      A[i].size);
-      get_int256_from_qualified_field(value_b,
-                                      C[i].field,
-                                      C[i].offset,
-                                      C[i].size);
-      add_int256_to_int256(value_a, value_b);
-
-      int overflow = squeeze_int256(value_a);
-      if( overflow )
-        {
-        *compute_error |= compute_error_overflow;
-        }
-
-        // At this point, we assign the sum to *C.
-      *compute_error |= conditional_stash(C[i].field, C[i].offset, C[i].size,
-                                          on_size_error,
-                                          int256_get_u128(value_a, 0),
-                                          value_a.rdigits,
-                                          *rounded++);
-      }
-    }
-  }
-
-extern "C"
-void
-__gg__subtractf1_fixed_phase2(cbl_arith_format_t ,
-                              size_t ,
-                              cblc_referlet_t *,
-                              size_t ,
-                              cblc_referlet_t *,
-                              size_t ,
-                        const cblc_referlet_t *C,
-                        const cbl_round_t  *rounded,
-                              int           on_error_flag,
-                              int          *compute_error
-                              )
-  {
-  // This is the assignment phase of an ADD Format 1
-
-  // We take phase1_result and subtrace it from C
-  bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR);
-
-  if( C[0].field->type == FldFloat)
-    {
-    // The target we need to accumulate into is a floating-point number, so we
-    // need to convert our fixed-point intermediate into floating point and
-    // proceed accordingly.
-
-    // Convert the intermediate
-    GCOB_FP128 value_a = (GCOB_FP128)int256_get_u128(phase1_result, 0);
-    value_a /= __gg__power_of_ten(phase1_result.rdigits);
-
-    // Pick up the target
-    GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[0].field,
-                                                             C[0].offset,
-                                                             C[0].size);
-
-    value_b -= value_a;
-
-    // At this point, we assign the difference to *C.
-    *compute_error |= conditional_stash(C[0].field, C[0].offset, C[0].size,
-                                        on_size_error,
-                                        value_b,
-                                        *rounded++);
-    }
-  else
-    {
-    // We have a fixed-point intermediate, and we are accumulating intoi a
-    // fixed point target.
-    int256 value_a   = phase1_result;
-    value_a.rdigits = phase1_result.rdigits;
-
-    int256 value_b = {};
-
-    get_int256_from_qualified_field(value_b,
-                                    C[0].field,
-                                    C[0].offset,
-                                    C[0].size);
-
-    subtract_int256_from_int256(value_b, value_a);
-
-    int overflow = squeeze_int256(value_b);
-    if( overflow )
-      {
-      *compute_error |= compute_error_overflow;
-      }
-
-      // At this point, we assign running_sum to *C.
-    *compute_error |= conditional_stash(C[0].field, C[0].offset, C[0].size,
-                                        on_size_error,
-                                        int256_get_u128(value_b, 0),
-                                        value_b.rdigits,
-                                        *rounded++);
-    }
-  }
-
-extern "C"
-void
-__gg__subtractf2_fixed_phase1(cbl_arith_format_t ,
-                              size_t nA,
-                        const cblc_referlet_t *AA,
-                              size_t ,
-                        const cblc_referlet_t *BB,
-                              size_t ,
-                              cblc_referlet_t *,
-                        const cbl_round_t  *rounded,
-                              int           on_error_flag,
-                              int          *compute_error
-                              )
-  {
-  // This is the calculation phase of a fixed-point SUBTRACT Format 2
-
-  // Add up all the A values
-  __gg__add_fixed_phase1( not_expected_e ,
-                          nA,
-                          AA,
-                          0,
-                          NULL,
-                          0,
-                          NULL,
-                          rounded,
-                          on_error_flag,
-                          compute_error);
-
-  // Subtract the phase1_result from the B value:
-
-  int256 value_a   = phase1_result;
-  value_a.rdigits = phase1_result.rdigits;
-
-  int256 value_b = {};
-
-  get_int256_from_qualified_field(value_b,
-                                  BB[0].field,
-                                  BB[0].offset,
-                                  BB[0].size);
-
-  subtract_int256_from_int256(value_b, value_a);
-
-  int overflow = squeeze_int256(value_b);
-  if( overflow )
-    {
-    *compute_error |= compute_error_overflow;
-    }
-  phase1_result  = value_b;
-  phase1_result.rdigits = value_b.rdigits;
-  }
-
-extern "C"
-void
-__gg__subtractf1_float_phase2(cbl_arith_format_t ,
-                              size_t ,
-                              cblc_referlet_t *,
-                              size_t ,
-                              cblc_referlet_t *,
-                              size_t ,
-                        const cblc_referlet_t *C,
-                        const cbl_round_t  *rounded,
-                              int           on_error_flag,
-                              int          *compute_error
-                              )
-  {
-  bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR);
-  // This is the assignment phase of an SUBTRACT Format 2
-  // We take phase1_result and subtract it from C
-
-  GCOB_FP128 temp = __gg__float128_from_qualified_field(C[0].field,
-                                                        C[0].offset,
-                                                        C[0].size);
-  temp = subtraction_helper_float(temp, phase1_result_float, compute_error);
-  *compute_error |= conditional_stash(C[0].field, C[0].offset, C[0].size,
-                                      on_size_error,
-                                      temp,
-                                     *rounded++);
-  }
-
-extern "C"
-void
-__gg__subtractf2_float_phase1(cbl_arith_format_t ,
-                              size_t nA,
-                        const cblc_referlet_t *A,
-                              size_t ,
-                        const cblc_referlet_t *B,
-                              size_t ,
-                              cblc_referlet_t *,
-                        const cbl_round_t  *rounded,
-                              int           on_error_flag,
-                              int          *compute_error
-                              )
-  {
-  // This is the calculation phase of a fixed-point SUBTRACT Format 2
-
-  // Add up all the A values
-  __gg__add_float_phase1( not_expected_e ,
-                          nA,
-                          A,
-                          0,
-                          NULL,
-                          0,
-                          NULL,
-                          rounded,
-                          on_error_flag,
-                          compute_error
-                          );
-
-  // Subtract that subtotal from the B value:
-  GCOB_FP128 value_b = __gg__float128_from_qualified_field(B[0].field,
-                                                           B[0].offset,
-                                                           B[0].size);
-  phase1_result_float = subtraction_helper_float(value_b,
-                                                 phase1_result_float,
-                                                 compute_error);
-  }
-
-extern "C"
-void
-__gg__subtractf3( cbl_arith_format_t ,
-                  size_t nA,
-            const cblc_referlet_t *A,
-                  size_t ,
-                  cblc_referlet_t *,
-                  size_t ,
-            const cblc_referlet_t *C,
-            const cbl_round_t  *rounded,
-                  int           on_error_flag,
-                  int          *compute_error
-                  )
-  {
-  // This is an ADD Format 3.  Each A[i] gets accumulated into each C[i].  Each
-  // SUBTRACTION is treated separately.
-
-  bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR);
-
-  for(size_t i=0; i<nA; i++)
-    {
-    if( A[i].field->type == FldFloat || C[i].field->type == FldFloat)
-      {
-      GCOB_FP128 value_a = __gg__float128_from_qualified_field(A[i].field,
-                                                               A[i].offset,
-                                                               A[i].size);
-      GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[i].field,
-                                                               C[i].offset,
-                                                               C[i].size);
-
-      value_b = subtraction_helper_float(value_b, value_a, compute_error);
-
-        // At this point, we assign the sum to *C.
-      *compute_error |= conditional_stash(C[i].field, C[i].offset, C[i].size,
-                                          on_size_error,
-                                          value_b,
-                                          *rounded++);
-      }
-    else
-      {
-      // We are doing fixed-point subtraction.
-      int256 value_a;
-      int256 value_b;
-
-      get_int256_from_qualified_field(value_a,
-                                      A[i].field,
-                                      A[i].offset,
-                                      A[i].size);
-      get_int256_from_qualified_field(value_b,
-                                      C[i].field,
-                                      C[i].offset,
-                                      C[i].size);
-
-      subtract_int256_from_int256(value_b, value_a);
-
-      int overflow = squeeze_int256(value_b);
-
-      if( overflow )
-        {
-        *compute_error |= compute_error_overflow;
-        }
-
-        // At this point, we assign the sum to *C.
-      *compute_error |= conditional_stash(C[i].field, C[i].offset, C[i].size,
-                                          on_size_error,
-                                          int256_get_u128(value_b, 0),
-                                          value_b.rdigits,
-                                          *rounded++);
-      }
-    }
-  }
-
 static bool multiply_intermediate_is_float;
 static GCOB_FP128 multiply_intermediate_float;
 static int128 multiply_intermediate_int128;

Reply via email to