From 0633fead25903def466c31d0ccfab9dc68cdfc9d Mon Sep 17 00:00:00 2001
From: q66 <daniel@octaforge.org>
Date: Tue, 25 Jun 2019 01:32:18 +0200
Subject: [PATCH] apl: patch build on platforms with not enough ldbl range

Not every system has 80-bit or better extended range/precision
long doubles, particularly ppc(64) uses either 128-bit long doubles
implemented as a double pair (which has extended precision but not
range) or just plain 64-bit that is the same as double (with musl
which does not implement the 128-bit precision). On those systems,
this patch pretty much reverts to the old code which was not using
precomputed tables.
---
 srcpkgs/apl/patches/ppc.patch | 97 +++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)
 create mode 100644 srcpkgs/apl/patches/ppc.patch

diff --git a/srcpkgs/apl/patches/ppc.patch b/srcpkgs/apl/patches/ppc.patch
new file mode 100644
index 00000000000..de877a7be00
--- /dev/null
+++ b/srcpkgs/apl/patches/ppc.patch
@@ -0,0 +1,97 @@
+See comment below. This pretty much just restores older code on platforms
+where gcc now fails with this error:
+
+Tokenizer.cc:769:4: error: floating constant exceeds range of 'long double' [-Werror=overflow]
+    exp_0_9(1E30)
+    ^~~~~~~
+
+--- src/Tokenizer.cc
++++ src/Tokenizer.cc
+@@ -19,6 +19,7 @@
+ */
+ 
+ #include <string.h>
++#include <limits.h>
+ 
+ #include "Bif_F12_FORMAT.hh"
+ #include "Bif_F12_SORT.hh"
+@@ -755,6 +756,15 @@ enum { MAX_TOKENIZE_DIGITS_1 = 20,                       // incl. rounding digit
+        MAX_TOKENIZE_DIGITS = MAX_TOKENIZE_DIGITS_1 - 1   // excl. rounding digit
+      };
+ 
++/* particularly ppc uses either 128-bit double-double format (which has
++ * a range that is the same as the range of a normal 64-bit double) or
++ * just plain 64-bit (on musl), either way not enough range
++ */
++#if LDBL_MAX_EXP > DBL_MAX_EXP
++#define USE_EXPO_TAB 1
++#endif
++
++#ifdef USE_EXPO_TAB
+ #define exp_0_9(x) x ## 0L, x ## 1L, x ## 2L, x ## 3L, x ## 4L,  \
+                            x ## 5L, x ## 6L, x ## 7L, x ## 8L, x ## 9L, 
+ 
+@@ -779,6 +789,7 @@ static const long double nexpo_tab[310] =
+    exp_0_9(1E-25) exp_0_9(1E-26) exp_0_9(1E-27) exp_0_9(1E-28) exp_0_9(1E-29)
+    exp_0_9(1E-30)
+ };
++#endif
+ 
+ bool
+ Tokenizer::tokenize_real(Unicode_source & src, bool & need_float,
+@@ -958,21 +969,55 @@ UTF8_string digits = int_digits;
+             --expo;
+           }
+ 
++#ifndef USE_EXPO_TAB
++        // perfom the scaling in higher precision to avoid rounding errors
++        //
++        long double dval = v;
++#endif
+         if (expo > 0)
+            {
++#ifdef USE_EXPO_TAB
+              if (negative)   flt_val = - v * expo_tab[expo];
+              else            flt_val =   v * expo_tab[expo];
+              return true;   // OK
++#else
++             if (expo >= 256)   { expo -= 256;   dval *= 1E256; }
++             if (expo >= 128)   { expo -= 128;   dval *= 1E128; }
++             if (expo >=  64)   { expo -=  64;   dval *= 1E64;  }
++             if (expo >=  32)   { expo -=  32;   dval *= 1E32;  }
++             if (expo >=  16)   { expo -=  16;   dval *= 1E16;  }
++             if (expo >=   8)   { expo -=   8;   dval *= 1E8;   }
++             if (expo >=   4)   { expo -=   4;   dval *= 1E4;   }
++             if (expo >=   2)   { expo -=   2;   dval *= 1E2;   }
++             if (expo >=   1)   { expo -=   1;   dval *= 1E1;   }
++#endif
+            }
+         else if (expo < 0)
+            {
++#ifdef USE_EXPO_TAB
+              if (negative)   flt_val = - v * nexpo_tab[-expo];
+              else            flt_val =   v * nexpo_tab[-expo];
+              return true;   // OK
++#else
++             if (expo <= -256)   { expo += 256;   dval /= 1E256; }
++             if (expo <= -128)   { expo += 128;   dval /= 1E128; }
++             if (expo <=  -64)   { expo +=  64;   dval /= 1E64;  }
++             if (expo <=  -32)   { expo +=  32;   dval /= 1E32;  }
++             if (expo <=  -16)   { expo +=  16;   dval /= 1E16;  }
++             if (expo <=   -8)   { expo +=   8;   dval /= 1E8;   }
++             if (expo <=   -4)   { expo +=   4;   dval /= 1E4;   }
++             if (expo <=   -2)   { expo +=   2;   dval /= 1E2;   }
++             if (expo <=   -1)   { expo +=   1;   dval /= 1E1;   }
++#endif
+            }
+ 
++#ifdef USE_EXPO_TAB
+         if (negative)   flt_val = - v;
+         else            flt_val =   v;
++#else
++        if (negative)   dval = - dval;
++        flt_val = dval;
++#endif
+         return true;   // OK
+       }
+    else
