aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/libgnat
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2020-12-01 07:53:50 +0100
committerPierre-Marie de Rodat <derodat@adacore.com>2020-12-17 05:49:22 -0500
commit97919732a8ebeb343705966b2ca649d35d3197e9 (patch)
tree4fca667935c37e1a03a75228d45b48d3ef924a83 /gcc/ada/libgnat
parent5957283fa4958afc18ca718405417d742332d66c (diff)
downloadgcc-97919732a8ebeb343705966b2ca649d35d3197e9.zip
gcc-97919732a8ebeb343705966b2ca649d35d3197e9.tar.gz
gcc-97919732a8ebeb343705966b2ca649d35d3197e9.tar.bz2
[Ada] Do not use exponentiation for common bases in floating-point Value
gcc/ada/ * Makefile.rtl (GNATRTL_NONTASKING_OBJS): Likewise. * exp_imgv.adb (Expand_Value_Attribute): Use RE_Value_Long_Float in lieu of RE_Value_Long_Long_Float as fallback for fixed-point types. Also use it for Long_Long_Float if it has same size as Long_Float. * libgnat/s-imgrea.adb: Replace Powten_Table with Powen_LLF. * libgnat/s-powflt.ads: New file. * libgnat/s-powlfl.ads: Likewise. * libgnat/s-powtab.ads: Rename to... * libgnat/s-powllf.ads: ...this. * libgnat/s-valflt.ads: Add with clause for System.Powten_Flt and pass its table as actual parameter to System.Val_Real. * libgnat/s-vallfl.ads: Likewise for System.Powten_LFlt. * libgnat/s-valllf.ads: Likewise for System.Powten_LLF. * libgnat/s-valrea.ads: Add Maxpow and Powten_Address parameters. * libgnat/s-valrea.adb: Add pragma Warnings (Off). (Need_Extra): New boolean constant. (Precision_Limit): Set it according to Need_Extra. (Impl): Adjust actual parameter. (Integer_to_Rea): Add assertion on the machine radix. Take into account the extra digit only if Need_Extra is true. Reimplement the computation of the final value for bases 2, 4, 8, 10 and 16. * libgnat/s-valued.adb (Impl): Adjust actual parameter. (Scan_Decimal): Add pragma Unreferenced. (Value_Decimal): Likewise. * libgnat/s-valuef.adb (Impl): Adjust actual parameter. * libgnat/s-valuer.ads (Floating): Remove. (Round): New formal parameter. * libgnat/s-valuer.adb (Round_Extra): New procedure. (Scan_Decimal_Digits): Use it to round the extra digit if Round is set to True in the instantiation. (Scan_Integral_Digits): Likewise.
Diffstat (limited to 'gcc/ada/libgnat')
-rw-r--r--gcc/ada/libgnat/s-imgrea.adb6
-rw-r--r--gcc/ada/libgnat/s-powflt.ads85
-rw-r--r--gcc/ada/libgnat/s-powlfl.ads355
-rw-r--r--gcc/ada/libgnat/s-powllf.ads (renamed from gcc/ada/libgnat/s-powtab.ads)6
-rw-r--r--gcc/ada/libgnat/s-valflt.ads7
-rw-r--r--gcc/ada/libgnat/s-vallfl.ads7
-rw-r--r--gcc/ada/libgnat/s-valllf.ads7
-rw-r--r--gcc/ada/libgnat/s-valrea.adb116
-rw-r--r--gcc/ada/libgnat/s-valrea.ads4
-rw-r--r--gcc/ada/libgnat/s-valued.adb5
-rw-r--r--gcc/ada/libgnat/s-valuef.adb3
-rw-r--r--gcc/ada/libgnat/s-valuer.adb102
-rw-r--r--gcc/ada/libgnat/s-valuer.ads2
13 files changed, 637 insertions, 68 deletions
diff --git a/gcc/ada/libgnat/s-imgrea.adb b/gcc/ada/libgnat/s-imgrea.adb
index 03d30bd..2ec6a1a 100644
--- a/gcc/ada/libgnat/s-imgrea.adb
+++ b/gcc/ada/libgnat/s-imgrea.adb
@@ -29,9 +29,9 @@
-- --
------------------------------------------------------------------------------
-with System.Img_LLU; use System.Img_LLU;
-with System.Img_Uns; use System.Img_Uns;
-with System.Powten_Table; use System.Powten_Table;
+with System.Img_LLU; use System.Img_LLU;
+with System.Img_Uns; use System.Img_Uns;
+with System.Powten_LLF; use System.Powten_LLF;
with System.Float_Control;
package body System.Img_Real is
diff --git a/gcc/ada/libgnat/s-powflt.ads b/gcc/ada/libgnat/s-powflt.ads
new file mode 100644
index 0000000..9d58967
--- /dev/null
+++ b/gcc/ada/libgnat/s-powflt.ads
@@ -0,0 +1,85 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . P O W T E N _ F L T --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package provides a powers of ten table used for real conversions
+
+package System.Powten_Flt is
+ pragma Pure;
+
+ Maxpow : constant := 38;
+ -- Largest power of ten representable with Float
+
+ Maxpow_Exact : constant := 10;
+ -- Largest power of ten exactly representable with Float. It is equal to
+ -- floor (M * log 2 / log 5), when M is the size of the mantissa (24).
+
+ Powten : constant array (0 .. Maxpow) of Float :=
+ (00 => 1.0E+00,
+ 01 => 1.0E+01,
+ 02 => 1.0E+02,
+ 03 => 1.0E+03,
+ 04 => 1.0E+04,
+ 05 => 1.0E+05,
+ 06 => 1.0E+06,
+ 07 => 1.0E+07,
+ 08 => 1.0E+08,
+ 09 => 1.0E+09,
+ 10 => 1.0E+10,
+ 11 => 1.0E+11,
+ 12 => 1.0E+12,
+ 13 => 1.0E+13,
+ 14 => 1.0E+14,
+ 15 => 1.0E+15,
+ 16 => 1.0E+16,
+ 17 => 1.0E+17,
+ 18 => 1.0E+18,
+ 19 => 1.0E+19,
+ 20 => 1.0E+20,
+ 21 => 1.0E+21,
+ 22 => 1.0E+22,
+ 23 => 1.0E+23,
+ 24 => 1.0E+24,
+ 25 => 1.0E+25,
+ 26 => 1.0E+26,
+ 27 => 1.0E+27,
+ 28 => 1.0E+28,
+ 29 => 1.0E+29,
+ 30 => 1.0E+30,
+ 31 => 1.0E+31,
+ 32 => 1.0E+32,
+ 33 => 1.0E+33,
+ 34 => 1.0E+34,
+ 35 => 1.0E+35,
+ 36 => 1.0E+36,
+ 37 => 1.0E+37,
+ 38 => 1.0E+38);
+
+end System.Powten_Flt;
diff --git a/gcc/ada/libgnat/s-powlfl.ads b/gcc/ada/libgnat/s-powlfl.ads
new file mode 100644
index 0000000..d191eff
--- /dev/null
+++ b/gcc/ada/libgnat/s-powlfl.ads
@@ -0,0 +1,355 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- S Y S T E M . P O W T E N _ L F L T --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2020, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package provides a powers of ten table used for real conversions
+
+package System.Powten_LFlt is
+ pragma Pure;
+
+ Maxpow : constant := 308;
+ -- Largest power of ten representable with Long_Float
+
+ Maxpow_Exact : constant := 22;
+ -- Largest power of ten exactly representable with Long_Float. It is equal
+ -- to floor (M * log 2 / log 5), when M is the size of the mantissa (53).
+
+ Powten : constant array (0 .. Maxpow) of Long_Float :=
+ (00 => 1.0E+00,
+ 01 => 1.0E+01,
+ 02 => 1.0E+02,
+ 03 => 1.0E+03,
+ 04 => 1.0E+04,
+ 05 => 1.0E+05,
+ 06 => 1.0E+06,
+ 07 => 1.0E+07,
+ 08 => 1.0E+08,
+ 09 => 1.0E+09,
+ 10 => 1.0E+10,
+ 11 => 1.0E+11,
+ 12 => 1.0E+12,
+ 13 => 1.0E+13,
+ 14 => 1.0E+14,
+ 15 => 1.0E+15,
+ 16 => 1.0E+16,
+ 17 => 1.0E+17,
+ 18 => 1.0E+18,
+ 19 => 1.0E+19,
+ 20 => 1.0E+20,
+ 21 => 1.0E+21,
+ 22 => 1.0E+22,
+ 23 => 1.0E+23,
+ 24 => 1.0E+24,
+ 25 => 1.0E+25,
+ 26 => 1.0E+26,
+ 27 => 1.0E+27,
+ 28 => 1.0E+28,
+ 29 => 1.0E+29,
+ 30 => 1.0E+30,
+ 31 => 1.0E+31,
+ 32 => 1.0E+32,
+ 33 => 1.0E+33,
+ 34 => 1.0E+34,
+ 35 => 1.0E+35,
+ 36 => 1.0E+36,
+ 37 => 1.0E+37,
+ 38 => 1.0E+38,
+ 39 => 1.0E+39,
+ 40 => 1.0E+40,
+ 41 => 1.0E+41,
+ 42 => 1.0E+42,
+ 43 => 1.0E+43,
+ 44 => 1.0E+44,
+ 45 => 1.0E+45,
+ 46 => 1.0E+46,
+ 47 => 1.0E+47,
+ 48 => 1.0E+48,
+ 49 => 1.0E+49,
+ 50 => 1.0E+50,
+ 51 => 1.0E+51,
+ 52 => 1.0E+52,
+ 53 => 1.0E+53,
+ 54 => 1.0E+54,
+ 55 => 1.0E+55,
+ 56 => 1.0E+56,
+ 57 => 1.0E+57,
+ 58 => 1.0E+58,
+ 59 => 1.0E+59,
+ 60 => 1.0E+60,
+ 61 => 1.0E+61,
+ 62 => 1.0E+62,
+ 63 => 1.0E+63,
+ 64 => 1.0E+64,
+ 65 => 1.0E+65,
+ 66 => 1.0E+66,
+ 67 => 1.0E+67,
+ 68 => 1.0E+68,
+ 69 => 1.0E+69,
+ 70 => 1.0E+70,
+ 71 => 1.0E+71,
+ 72 => 1.0E+72,
+ 73 => 1.0E+73,
+ 74 => 1.0E+74,
+ 75 => 1.0E+75,
+ 76 => 1.0E+76,
+ 77 => 1.0E+77,
+ 78 => 1.0E+78,
+ 79 => 1.0E+79,
+ 80 => 1.0E+80,
+ 81 => 1.0E+81,
+ 82 => 1.0E+82,
+ 83 => 1.0E+83,
+ 84 => 1.0E+84,
+ 85 => 1.0E+85,
+ 86 => 1.0E+86,
+ 87 => 1.0E+87,
+ 88 => 1.0E+88,
+ 89 => 1.0E+89,
+ 90 => 1.0E+90,
+ 91 => 1.0E+91,
+ 92 => 1.0E+92,
+ 93 => 1.0E+93,
+ 94 => 1.0E+94,
+ 95 => 1.0E+95,
+ 96 => 1.0E+96,
+ 97 => 1.0E+97,
+ 98 => 1.0E+98,
+ 99 => 1.0E+99,
+ 100 => 1.0E+100,
+ 101 => 1.0E+101,
+ 102 => 1.0E+102,
+ 103 => 1.0E+103,
+ 104 => 1.0E+104,
+ 105 => 1.0E+105,
+ 106 => 1.0E+106,
+ 107 => 1.0E+107,
+ 108 => 1.0E+108,
+ 109 => 1.0E+109,
+ 110 => 1.0E+110,
+ 111 => 1.0E+111,
+ 112 => 1.0E+112,
+ 113 => 1.0E+113,
+ 114 => 1.0E+114,
+ 115 => 1.0E+115,
+ 116 => 1.0E+116,
+ 117 => 1.0E+117,
+ 118 => 1.0E+118,
+ 119 => 1.0E+119,
+ 120 => 1.0E+120,
+ 121 => 1.0E+121,
+ 122 => 1.0E+122,
+ 123 => 1.0E+123,
+ 124 => 1.0E+124,
+ 125 => 1.0E+125,
+ 126 => 1.0E+126,
+ 127 => 1.0E+127,
+ 128 => 1.0E+128,
+ 129 => 1.0E+129,
+ 130 => 1.0E+130,
+ 131 => 1.0E+131,
+ 132 => 1.0E+132,
+ 133 => 1.0E+133,
+ 134 => 1.0E+134,
+ 135 => 1.0E+135,
+ 136 => 1.0E+136,
+ 137 => 1.0E+137,
+ 138 => 1.0E+138,
+ 139 => 1.0E+139,
+ 140 => 1.0E+140,
+ 141 => 1.0E+141,
+ 142 => 1.0E+142,
+ 143 => 1.0E+143,
+ 144 => 1.0E+144,
+ 145 => 1.0E+145,
+ 146 => 1.0E+146,
+ 147 => 1.0E+147,
+ 148 => 1.0E+148,
+ 149 => 1.0E+149,
+ 150 => 1.0E+150,
+ 151 => 1.0E+151,
+ 152 => 1.0E+152,
+ 153 => 1.0E+153,
+ 154 => 1.0E+154,
+ 155 => 1.0E+155,
+ 156 => 1.0E+156,
+ 157 => 1.0E+157,
+ 158 => 1.0E+158,
+ 159 => 1.0E+159,
+ 160 => 1.0E+160,
+ 161 => 1.0E+161,
+ 162 => 1.0E+162,
+ 163 => 1.0E+163,
+ 164 => 1.0E+164,
+ 165 => 1.0E+165,
+ 166 => 1.0E+166,
+ 167 => 1.0E+167,
+ 168 => 1.0E+168,
+ 169 => 1.0E+169,
+ 170 => 1.0E+170,
+ 171 => 1.0E+171,
+ 172 => 1.0E+172,
+ 173 => 1.0E+173,
+ 174 => 1.0E+174,
+ 175 => 1.0E+175,
+ 176 => 1.0E+176,
+ 177 => 1.0E+177,
+ 178 => 1.0E+178,
+ 179 => 1.0E+179,
+ 180 => 1.0E+180,
+ 181 => 1.0E+181,
+ 182 => 1.0E+182,
+ 183 => 1.0E+183,
+ 184 => 1.0E+184,
+ 185 => 1.0E+185,
+ 186 => 1.0E+186,
+ 187 => 1.0E+187,
+ 188 => 1.0E+188,
+ 189 => 1.0E+189,
+ 190 => 1.0E+190,
+ 191 => 1.0E+191,
+ 192 => 1.0E+192,
+ 193 => 1.0E+193,
+ 194 => 1.0E+194,
+ 195 => 1.0E+195,
+ 196 => 1.0E+196,
+ 197 => 1.0E+197,
+ 198 => 1.0E+198,
+ 199 => 1.0E+199,
+ 200 => 1.0E+200,
+ 201 => 1.0E+201,
+ 202 => 1.0E+202,
+ 203 => 1.0E+203,
+ 204 => 1.0E+204,
+ 205 => 1.0E+205,
+ 206 => 1.0E+206,
+ 207 => 1.0E+207,
+ 208 => 1.0E+208,
+ 209 => 1.0E+209,
+ 210 => 1.0E+210,
+ 211 => 1.0E+211,
+ 212 => 1.0E+212,
+ 213 => 1.0E+213,
+ 214 => 1.0E+214,
+ 215 => 1.0E+215,
+ 216 => 1.0E+216,
+ 217 => 1.0E+217,
+ 218 => 1.0E+218,
+ 219 => 1.0E+219,
+ 220 => 1.0E+220,
+ 221 => 1.0E+221,
+ 222 => 1.0E+222,
+ 223 => 1.0E+223,
+ 224 => 1.0E+224,
+ 225 => 1.0E+225,
+ 226 => 1.0E+226,
+ 227 => 1.0E+227,
+ 228 => 1.0E+228,
+ 229 => 1.0E+229,
+ 230 => 1.0E+230,
+ 231 => 1.0E+231,
+ 232 => 1.0E+232,
+ 233 => 1.0E+233,
+ 234 => 1.0E+234,
+ 235 => 1.0E+235,
+ 236 => 1.0E+236,
+ 237 => 1.0E+237,
+ 238 => 1.0E+238,
+ 239 => 1.0E+239,
+ 240 => 1.0E+240,
+ 241 => 1.0E+241,
+ 242 => 1.0E+242,
+ 243 => 1.0E+243,
+ 244 => 1.0E+244,
+ 245 => 1.0E+245,
+ 246 => 1.0E+246,
+ 247 => 1.0E+247,
+ 248 => 1.0E+248,
+ 249 => 1.0E+249,
+ 250 => 1.0E+250,
+ 251 => 1.0E+251,
+ 252 => 1.0E+252,
+ 253 => 1.0E+253,
+ 254 => 1.0E+254,
+ 255 => 1.0E+255,
+ 256 => 1.0E+256,
+ 257 => 1.0E+257,
+ 258 => 1.0E+258,
+ 259 => 1.0E+259,
+ 260 => 1.0E+260,
+ 261 => 1.0E+261,
+ 262 => 1.0E+262,
+ 263 => 1.0E+263,
+ 264 => 1.0E+264,
+ 265 => 1.0E+265,
+ 266 => 1.0E+266,
+ 267 => 1.0E+267,
+ 268 => 1.0E+268,
+ 269 => 1.0E+269,
+ 270 => 1.0E+270,
+ 271 => 1.0E+271,
+ 272 => 1.0E+272,
+ 273 => 1.0E+273,
+ 274 => 1.0E+274,
+ 275 => 1.0E+275,
+ 276 => 1.0E+276,
+ 277 => 1.0E+277,
+ 278 => 1.0E+278,
+ 279 => 1.0E+279,
+ 280 => 1.0E+280,
+ 281 => 1.0E+281,
+ 282 => 1.0E+282,
+ 283 => 1.0E+283,
+ 284 => 1.0E+284,
+ 285 => 1.0E+285,
+ 286 => 1.0E+286,
+ 287 => 1.0E+287,
+ 288 => 1.0E+288,
+ 289 => 1.0E+289,
+ 290 => 1.0E+290,
+ 291 => 1.0E+291,
+ 292 => 1.0E+292,
+ 293 => 1.0E+293,
+ 294 => 1.0E+294,
+ 295 => 1.0E+295,
+ 296 => 1.0E+296,
+ 297 => 1.0E+297,
+ 298 => 1.0E+298,
+ 299 => 1.0E+299,
+ 300 => 1.0E+300,
+ 301 => 1.0E+301,
+ 302 => 1.0E+302,
+ 303 => 1.0E+303,
+ 304 => 1.0E+304,
+ 305 => 1.0E+305,
+ 306 => 1.0E+306,
+ 307 => 1.0E+307,
+ 308 => 1.0E+308);
+
+end System.Powten_LFlt;
diff --git a/gcc/ada/libgnat/s-powtab.ads b/gcc/ada/libgnat/s-powllf.ads
index 79982b9..c5c42a1 100644
--- a/gcc/ada/libgnat/s-powtab.ads
+++ b/gcc/ada/libgnat/s-powllf.ads
@@ -2,7 +2,7 @@
-- --
-- GNAT COMPILER COMPONENTS --
-- --
--- S Y S T E M . P O W T E N _ T A B L E --
+-- S Y S T E M . P O W T E N _ L L F --
-- --
-- S p e c --
-- --
@@ -31,7 +31,7 @@
-- This package provides a powers of ten table used for real conversions
-package System.Powten_Table is
+package System.Powten_LLF is
pragma Pure;
Maxpow : constant := 22;
@@ -67,4 +67,4 @@ package System.Powten_Table is
21 => 1.0E+21,
22 => 1.0E+22);
-end System.Powten_Table;
+end System.Powten_LLF;
diff --git a/gcc/ada/libgnat/s-valflt.ads b/gcc/ada/libgnat/s-valflt.ads
index 476a251..5806d58 100644
--- a/gcc/ada/libgnat/s-valflt.ads
+++ b/gcc/ada/libgnat/s-valflt.ads
@@ -33,12 +33,17 @@
-- type Float, for use in Text_IO.Float_IO and the Value attribute.
with Interfaces;
+with System.Powten_Flt;
with System.Val_Real;
package System.Val_Flt is
pragma Preelaborate;
- package Impl is new Val_Real (Float, Interfaces.Unsigned_32);
+ package Impl is new Val_Real
+ (Float,
+ Interfaces.Unsigned_32,
+ System.Powten_Flt.Maxpow,
+ System.Powten_Flt.Powten'Address);
function Scan_Float
(Str : String;
diff --git a/gcc/ada/libgnat/s-vallfl.ads b/gcc/ada/libgnat/s-vallfl.ads
index 5bb6da4..c612f75 100644
--- a/gcc/ada/libgnat/s-vallfl.ads
+++ b/gcc/ada/libgnat/s-vallfl.ads
@@ -33,12 +33,17 @@
-- type Long_Float, for use in Text_IO.Float_IO and the Value attribute.
with Interfaces;
+with System.Powten_LFlt;
with System.Val_Real;
package System.Val_LFlt is
pragma Preelaborate;
- package Impl is new Val_Real (Long_Float, Interfaces.Unsigned_64);
+ package Impl is new Val_Real
+ (Long_Float,
+ Interfaces.Unsigned_64,
+ System.Powten_LFlt.Maxpow,
+ System.Powten_LFlt.Powten'Address);
function Scan_Long_Float
(Str : String;
diff --git a/gcc/ada/libgnat/s-valllf.ads b/gcc/ada/libgnat/s-valllf.ads
index 715f6ac..46a311b 100644
--- a/gcc/ada/libgnat/s-valllf.ads
+++ b/gcc/ada/libgnat/s-valllf.ads
@@ -33,12 +33,17 @@
-- type Long_Long_Float, for use in Text_IO.Float_IO and the Value attribute.
with Interfaces;
+with System.Powten_LLF;
with System.Val_Real;
package System.Val_LLF is
pragma Preelaborate;
- package Impl is new Val_Real (Long_Long_Float, Interfaces.Unsigned_64);
+ package Impl is new Val_Real
+ (Long_Long_Float,
+ Interfaces.Unsigned_64,
+ System.Powten_LLF.Maxpow,
+ System.Powten_LLF.Powten'Address);
function Scan_Long_Long_Float
(Str : String;
diff --git a/gcc/ada/libgnat/s-valrea.adb b/gcc/ada/libgnat/s-valrea.adb
index 5ce3642..9614760 100644
--- a/gcc/ada/libgnat/s-valrea.adb
+++ b/gcc/ada/libgnat/s-valrea.adb
@@ -34,15 +34,26 @@ with System.Unsigned_Types; use System.Unsigned_Types;
with System.Val_Util; use System.Val_Util;
with System.Value_R;
+pragma Warnings (Off, "non-static constant in preelaborated unit");
+-- Every constant is static given our instantiation model
+
package body System.Val_Real is
pragma Assert (Num'Machine_Mantissa <= Uns'Size);
-- We need an unsigned type large enough to represent the mantissa
- Precision_Limit : constant Uns := 2**Num'Machine_Mantissa - 1;
- -- We use the precision of the floating-point type
+ Need_Extra : constant Boolean := Num'Machine_Mantissa > Uns'Size - 4;
+ -- If the mantissa of the floating-point type is almost as large as that
+ -- of the unsigned type, we do not have enough space for an extra digit
+ -- in the unsigned type so we handle the extra digit separately, at the
+ -- cost of a potential roundoff error.
+
+ Precision_Limit : constant Uns :=
+ (if Need_Extra then 2**Num'Machine_Mantissa - 1 else 2**Uns'Size - 1);
+ -- If we handle the extra digit separately, we use the precision of the
+ -- floating-point type so that the conversion is exact.
- package Impl is new Value_R (Uns, Precision_Limit, Floating => True);
+ package Impl is new Value_R (Uns, Precision_Limit, Round => Need_Extra);
subtype Base_T is Unsigned range 2 .. 16;
@@ -88,6 +99,8 @@ package body System.Val_Real is
is
pragma Assert (Base in 2 .. 16);
+ pragma Assert (Num'Machine_Radix = 2);
+
pragma Unsuppress (Range_Check);
Maxexp : constant Positive :=
@@ -112,29 +125,98 @@ package body System.Val_Real is
System.Float_Control.Reset;
end if;
- -- Take into account the extra digit
+ -- Do the conversion
R_Val := Num (Val);
- if Extra > 0 then
+
+ -- Take into account the extra digit, if need be. In this case, the
+ -- three operands are exact, so using an FMA would be ideal.
+
+ if Need_Extra and then Extra > 0 then
R_Val := R_Val * B + Num (Extra);
S := S - 1;
end if;
- -- Compute the final value. When the exponent is positive, we can do the
- -- computation directly because, if the exponentiation overflows, then
- -- the final value overflows as well. But when the exponent is negative,
- -- we may need to do it in two steps to avoid an artificial underflow.
+ -- Compute the final value
+
+ if R_Val /= 0.0 and then S /= 0 then
+ case Base is
+ -- If the base is a power of two, we use the efficient Scaling
+ -- attribute with an overflow check, if it is not 2, to catch
+ -- ludicrous exponents that would result in an infinity or zero.
+
+ when 2 =>
+ R_Val := Num'Scaling (R_Val, S);
+
+ when 4 =>
+ if Integer'First / 2 <= S and then S <= Integer'Last / 2 then
+ S := S * 2;
+ end if;
+
+ R_Val := Num'Scaling (R_Val, S);
+
+ when 8 =>
+ if Integer'First / 3 <= S and then S <= Integer'Last / 3 then
+ S := S * 3;
+ end if;
+
+ R_Val := Num'Scaling (R_Val, S);
+
+ when 16 =>
+ if Integer'First / 4 <= S and then S <= Integer'Last / 4 then
+ S := S * 4;
+ end if;
+
+ R_Val := Num'Scaling (R_Val, S);
+
+ -- If the base is 10, we use a table of powers for accuracy's sake
+
+ when 10 =>
+ declare
+ Powten : constant array (0 .. Maxpow) of Num;
+ pragma Import (Ada, Powten);
+ for Powten'Address use Powten_Address;
+
+ begin
+ if S > 0 then
+ while S > Maxpow loop
+ R_Val := R_Val * Powten (Maxpow);
+ S := S - Maxpow;
+ end loop;
+
+ R_Val := R_Val * Powten (S);
+
+ else
+ while S < -Maxpow loop
+ R_Val := R_Val / Powten (Maxpow);
+ S := S + Maxpow;
+ end loop;
+
+ R_Val := R_Val / Powten (-S);
+ end if;
+ end;
+
+ -- Implementation for other bases with exponentiation
+
+ -- When the exponent is positive, we can do the computation
+ -- directly because, if the exponentiation overflows, then
+ -- the final value overflows as well. But when the exponent
+ -- is negative, we may need to do it in two steps to avoid
+ -- an artificial underflow.
- if S > 0 then
- R_Val := R_Val * B ** S;
+ when others =>
+ if S > 0 then
+ R_Val := R_Val * B ** S;
- elsif S < 0 then
- if S < -Maxexp then
- R_Val := R_Val / B ** Maxexp;
- S := S + Maxexp;
- end if;
+ else
+ if S < -Maxexp then
+ R_Val := R_Val / B ** Maxexp;
+ S := S + Maxexp;
+ end if;
- R_Val := R_Val / B ** (-S);
+ R_Val := R_Val / B ** (-S);
+ end if;
+ end case;
end if;
-- Finally deal with initial minus sign, note that this processing is
diff --git a/gcc/ada/libgnat/s-valrea.ads b/gcc/ada/libgnat/s-valrea.ads
index 961c4803..d6ade80 100644
--- a/gcc/ada/libgnat/s-valrea.ads
+++ b/gcc/ada/libgnat/s-valrea.ads
@@ -38,6 +38,10 @@ generic
type Uns is mod <>;
+ Maxpow : Positive;
+
+ Powten_Address : System.Address;
+
package System.Val_Real is
pragma Preelaborate;
diff --git a/gcc/ada/libgnat/s-valued.adb b/gcc/ada/libgnat/s-valued.adb
index 7986ce3..8930752 100644
--- a/gcc/ada/libgnat/s-valued.adb
+++ b/gcc/ada/libgnat/s-valued.adb
@@ -38,7 +38,8 @@ package body System.Value_D is
pragma Assert (Int'Size <= Uns'Size);
-- We need an unsigned type large enough to represent the mantissa
- package Impl is new Value_R (Uns, 2**(Int'Size - 1), Floating => False);
+ package Impl is new Value_R (Uns, 2**(Int'Size - 1), Round => False);
+ -- We do not use the Extra digit for decimal fixed-point types
function Integer_to_Decimal
(Str : String;
@@ -231,6 +232,7 @@ package body System.Value_D is
Base : Unsigned;
ScaleB : Integer;
Extra : Unsigned;
+ pragma Unreferenced (Extra);
Minus : Boolean;
Val : Uns;
@@ -248,6 +250,7 @@ package body System.Value_D is
Base : Unsigned;
ScaleB : Integer;
Extra : Unsigned;
+ pragma Unreferenced (Extra);
Minus : Boolean;
Val : Uns;
diff --git a/gcc/ada/libgnat/s-valuef.adb b/gcc/ada/libgnat/s-valuef.adb
index 5a87a7f..d13111a 100644
--- a/gcc/ada/libgnat/s-valuef.adb
+++ b/gcc/ada/libgnat/s-valuef.adb
@@ -46,7 +46,8 @@ package body System.Value_F is
pragma Assert (Int'Size <= Uns'Size);
-- We need an unsigned type large enough to represent the mantissa
- package Impl is new Value_R (Uns, 2**(Int'Size - 1), Floating => False);
+ package Impl is new Value_R (Uns, 2**(Int'Size - 1), Round => True);
+ -- We use the Extra digit for ordinary fixed-point types
function Integer_To_Fixed
(Str : String;
diff --git a/gcc/ada/libgnat/s-valuer.adb b/gcc/ada/libgnat/s-valuer.adb
index 65a0d50..9e4de3e 100644
--- a/gcc/ada/libgnat/s-valuer.adb
+++ b/gcc/ada/libgnat/s-valuer.adb
@@ -42,6 +42,14 @@ package body System.Value_R is
function As_Digit (C : Character) return Char_As_Digit;
-- Given a character return the digit it represents
+ procedure Round_Extra
+ (Digit : Char_As_Digit;
+ Value : in out Uns;
+ Scale : in out Integer;
+ Extra : in out Char_As_Digit;
+ Base : Unsigned);
+ -- Round the triplet (Value, Scale, Extra) according to Digit in Base
+
procedure Scan_Decimal_Digits
(Str : String;
Index : in out Integer;
@@ -109,6 +117,45 @@ package body System.Value_R is
end case;
end As_Digit;
+ -----------------
+ -- Round_Extra --
+ -----------------
+
+ procedure Round_Extra
+ (Digit : Char_As_Digit;
+ Value : in out Uns;
+ Scale : in out Integer;
+ Extra : in out Char_As_Digit;
+ Base : Unsigned)
+ is
+ B : constant Uns := Uns (Base);
+
+ begin
+ if Digit >= Base / 2 then
+
+ -- If Extra is maximum, round Value
+
+ if Extra = Base - 1 then
+
+ -- If Value is maximum, scale it up
+
+ if Value = Precision_Limit then
+ Extra := Char_As_Digit (Value mod B);
+ Value := Value / B;
+ Scale := Scale + 1;
+ Round_Extra (Digit, Value, Scale, Extra, Base);
+
+ else
+ Extra := 0;
+ Value := Value + 1;
+ end if;
+
+ else
+ Extra := Extra + 1;
+ end if;
+ end if;
+ end Round_Extra;
+
-------------------------
-- Scan_Decimal_Digits --
-------------------------
@@ -140,8 +187,8 @@ package body System.Value_R is
-- to Precision_Limit.
Precision_Limit_Just_Reached : Boolean;
- -- Set to True if Precision_Limit_Reached was just set to True
- -- Only used when Floating = False.
+ -- Set to True if Precision_Limit_Reached was just set to True, but only
+ -- used when Round is True.
Digit : Char_As_Digit;
-- The current digit
@@ -162,7 +209,7 @@ package body System.Value_R is
Extra := 0;
end if;
- if not Floating then
+ if Round then
Precision_Limit_Just_Reached := False;
end if;
@@ -188,22 +235,12 @@ package body System.Value_R is
-- If precision limit has been reached, just ignore any remaining
-- digits for the computation of Value and Scale, but store the
- -- first in Extra and use the second to round Extra if this is for
- -- a fixed-point type (we skip the rounding for a floating-point
- -- type to preserve backward compatibility). The scanning should
- -- continue only to assess the validity of the string.
+ -- first in Extra and use the second to round Extra. The scanning
+ -- should continue only to assess the validity of the string.
if Precision_Limit_Reached then
- if not Floating and then Precision_Limit_Just_Reached then
- if Digit >= Base / 2 then
- if Extra = Base - 1 then
- Extra := 0;
- Value := Value + 1;
- else
- Extra := Extra + 1;
- end if;
- end if;
-
+ if Round and then Precision_Limit_Just_Reached then
+ Round_Extra (Digit, Value, Scale, Extra, Base);
Precision_Limit_Just_Reached := False;
end if;
@@ -252,8 +289,7 @@ package body System.Value_R is
else
Extra := Digit;
Precision_Limit_Reached := True;
-
- if not Floating then
+ if Round then
Precision_Limit_Just_Reached := True;
end if;
end if;
@@ -320,8 +356,8 @@ package body System.Value_R is
-- to Precision_Limit.
Precision_Limit_Just_Reached : Boolean;
- -- Set to True if Precision_Limit_Reached was just set to True.
- -- Only used when Floating = False.
+ -- Set to True if Precision_Limit_Reached was just set to True, but only
+ -- used when Round is True.
Digit : Char_As_Digit;
-- The current digit
@@ -336,7 +372,7 @@ package body System.Value_R is
Scale := 0;
Extra := 0;
- if not Floating then
+ if Round then
Precision_Limit_Just_Reached := False;
end if;
@@ -364,24 +400,14 @@ package body System.Value_R is
-- If precision limit has been reached, just ignore any remaining
-- digits for the computation of Value and Scale, but store the
- -- first in Extra and use the second to round Extra if this is for
- -- a fixed-point type (we skip the rounding for a floating-point
- -- type to preserve backward compatibility). The scanning should
- -- continue only to assess the validity of the string.
+ -- first in Extra and use the second to round Extra. The scanning
+ -- should continue only to assess the validity of the string.
if Precision_Limit_Reached then
Scale := Scale + 1;
- if not Floating and then Precision_Limit_Just_Reached then
- if Digit >= Base / 2 then
- if Extra = Base - 1 then
- Extra := 0;
- Value := Value + 1;
- else
- Extra := Extra + 1;
- end if;
- end if;
-
+ if Round and then Precision_Limit_Just_Reached then
+ Round_Extra (Digit, Value, Scale, Extra, Base);
Precision_Limit_Just_Reached := False;
end if;
@@ -404,11 +430,9 @@ package body System.Value_R is
else
Extra := Digit;
Precision_Limit_Reached := True;
-
- if not Floating then
+ if Round then
Precision_Limit_Just_Reached := True;
end if;
-
Scale := Scale + 1;
end if;
end if;
diff --git a/gcc/ada/libgnat/s-valuer.ads b/gcc/ada/libgnat/s-valuer.ads
index 06fbe9e..a933859 100644
--- a/gcc/ada/libgnat/s-valuer.ads
+++ b/gcc/ada/libgnat/s-valuer.ads
@@ -40,7 +40,7 @@ generic
Precision_Limit : Uns;
- Floating : Boolean;
+ Round : Boolean;
package System.Value_R is
pragma Preelaborate;