OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [ada/] [s-imgdec.adb] - Blame information for rev 16

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT RUN-TIME COMPONENTS                         --
4
--                                                                          --
5
--                        S Y S T E M . I M G _ D E C                       --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1992-2005 Free Software Foundation, Inc.          --
10
--                                                                          --
11
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17
-- for  more details.  You should have  received  a copy of the GNU General --
18
-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
19
-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
20
-- Boston, MA 02110-1301, USA.                                              --
21
--                                                                          --
22
-- As a special exception,  if other files  instantiate  generics from this --
23
-- unit, or you link  this unit with other files  to produce an executable, --
24
-- this  unit  does not  by itself cause  the resulting  executable  to  be --
25
-- covered  by the  GNU  General  Public  License.  This exception does not --
26
-- however invalidate  any other reasons why  the executable file  might be --
27
-- covered by the  GNU Public License.                                      --
28
--                                                                          --
29
-- GNAT was originally developed  by the GNAT team at  New York University. --
30
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
31
--                                                                          --
32
------------------------------------------------------------------------------
33
 
34
with System.Img_Int; use System.Img_Int;
35
 
36
package body System.Img_Dec is
37
 
38
   -------------------
39
   -- Image_Decimal --
40
   -------------------
41
 
42
   function Image_Decimal
43
     (V     : Integer;
44
      Scale : Integer)
45
      return  String
46
   is
47
      P : Natural := 0;
48
      S : String (1 .. 64);
49
 
50
   begin
51
      Set_Image_Decimal (V, S, P, Scale, 1, Integer'Max (1, Scale), 0);
52
 
53
      --  Mess around to make sure we have the objectionable space at the
54
      --  start for positive numbers in accordance with the annoying rules!
55
 
56
      if S (1) /= ' ' and then S (1) /= '-' then
57
         S (2 .. P + 1) := S (1 .. P);
58
         S (1) := ' ';
59
         return S (1 .. P + 1);
60
      else
61
         return S (1 .. P);
62
      end if;
63
   end Image_Decimal;
64
 
65
   ------------------------
66
   -- Set_Decimal_Digits --
67
   ------------------------
68
 
69
   procedure Set_Decimal_Digits
70
     (Digs  : in out String;
71
      NDigs : Natural;
72
      S     : out String;
73
      P     : in out Natural;
74
      Scale : Integer;
75
      Fore  : Natural;
76
      Aft   : Natural;
77
      Exp   : Natural)
78
   is
79
      Minus : constant Boolean := (Digs (1) = '-');
80
      --  Set True if input is negative
81
 
82
      Zero : Boolean := (Digs (2) = '0');
83
      --  Set True if input is exactly zero (only case when a leading zero
84
      --  is permitted in the input string given to this procedure). This
85
      --  flag can get set later if rounding causes the value to become zero.
86
 
87
      FD : Natural := 2;
88
      --  First digit position of digits remaining to be processed
89
 
90
      LD : Natural := NDigs;
91
      --  Last digit position of digits remaining to be processed
92
 
93
      ND : Natural := NDigs - 1;
94
      --  Number of digits remaining to be processed (LD - FD + 1)
95
 
96
      Digits_Before_Point : Integer := ND - Scale;
97
      --  Number of digits before decimal point in the input value. This
98
      --  value can be negative if the input value is less than 0.1, so
99
      --  it is an indication of the current exponent. Digits_Before_Point
100
      --  is adjusted if the rounding step generates an extra digit.
101
 
102
      Digits_After_Point : constant Natural := Integer'Max (1, Aft);
103
      --  Digit positions after decimal point in result string
104
 
105
      Expon : Integer;
106
      --  Integer value of exponent
107
 
108
      procedure Round (N : Natural);
109
      --  Round the number in Digs. N is the position of the last digit to be
110
      --  retained in the rounded position (rounding is based on Digs (N + 1)
111
      --  FD, LD, ND are reset as necessary if required. Note that if the
112
      --  result value rounds up (e.g. 9.99 => 10.0), an extra digit can be
113
      --  placed in the sign position as a result of the rounding, this is
114
      --  the case in which FD is adjusted.
115
 
116
      procedure Set (C : Character);
117
      pragma Inline (Set);
118
      --  Sets character C in output buffer
119
 
120
      procedure Set_Blanks_And_Sign (N : Integer);
121
      --  Sets leading blanks and minus sign if needed. N is the number of
122
      --  positions to be filled (a minus sign is output even if N is zero
123
      --  or negative, For a positive value, if N is non-positive, then
124
      --  a leading blank is filled.
125
 
126
      procedure Set_Digits (S, E : Natural);
127
      pragma Inline (Set_Digits);
128
      --  Set digits S through E from Digs, no effect if S > E
129
 
130
      procedure Set_Zeroes (N : Integer);
131
      pragma Inline (Set_Zeroes);
132
      --  Set N zeroes, no effect if N is negative
133
 
134
      procedure Round (N : Natural) is
135
         D : Character;
136
 
137
      begin
138
         --  Nothing to do if rounding at or past last digit
139
 
140
         if N >= LD then
141
            return;
142
 
143
         --  Cases of rounding before the initial digit
144
 
145
         elsif N < FD then
146
 
147
            --  The result is zero, unless we are rounding just before
148
            --  the first digit, and the first digit is five or more.
149
 
150
            if N = 1 and then Digs (2) >= '5' then
151
               Digs (1) := '1';
152
            else
153
               Digs (1) := '0';
154
               Zero := True;
155
            end if;
156
 
157
            Digits_Before_Point := Digits_Before_Point + 1;
158
            FD := 1;
159
            LD := 1;
160
            ND := 1;
161
 
162
         --  Normal case of rounding an existing digit
163
 
164
         else
165
            LD := N;
166
            ND := LD - 1;
167
 
168
            if Digs (N + 1) >= '5' then
169
               for J in reverse 2 .. N loop
170
                  D := Character'Succ (Digs (J));
171
 
172
                  if D <= '9' then
173
                     Digs (J) := D;
174
                     return;
175
                  else
176
                     Digs (J) := '0';
177
                  end if;
178
               end loop;
179
 
180
               --  Here the rounding overflows into the sign position. That's
181
               --  OK, because we already captured the value of the sign and
182
               --  we are in any case destroying the value in the Digs buffer
183
 
184
               Digs (1) := '1';
185
               FD := 1;
186
               ND := ND + 1;
187
               Digits_Before_Point := Digits_Before_Point + 1;
188
            end if;
189
         end if;
190
      end Round;
191
 
192
      procedure Set (C : Character) is
193
      begin
194
         P := P + 1;
195
         S (P) := C;
196
      end Set;
197
 
198
      procedure Set_Blanks_And_Sign (N : Integer) is
199
         W : Integer := N;
200
 
201
      begin
202
         if Minus then
203
            W := W - 1;
204
 
205
            for J in 1 .. W loop
206
               Set (' ');
207
            end loop;
208
 
209
            Set ('-');
210
 
211
         else
212
            for J in 1 .. W loop
213
               Set (' ');
214
            end loop;
215
         end if;
216
      end Set_Blanks_And_Sign;
217
 
218
      procedure Set_Digits (S, E : Natural) is
219
      begin
220
         for J in S .. E loop
221
            Set (Digs (J));
222
         end loop;
223
      end Set_Digits;
224
 
225
      procedure Set_Zeroes (N : Integer) is
226
      begin
227
         for J in 1 .. N loop
228
            Set ('0');
229
         end loop;
230
      end Set_Zeroes;
231
 
232
   --  Start of processing for Set_Decimal_Digits
233
 
234
   begin
235
      --  Case of exponent given
236
 
237
      if Exp > 0 then
238
         Set_Blanks_And_Sign (Fore - 1);
239
         Round (Aft + 2);
240
         Set (Digs (FD));
241
         FD := FD + 1;
242
         ND := ND - 1;
243
         Set ('.');
244
 
245
         if ND >= Digits_After_Point then
246
            Set_Digits (FD, FD + Digits_After_Point - 1);
247
 
248
         else
249
            Set_Digits (FD, LD);
250
            Set_Zeroes (Digits_After_Point - ND);
251
         end if;
252
 
253
         --  Calculate exponent. The number of digits before the decimal point
254
         --  in the input is Digits_Before_Point, and the number of digits
255
         --  before the decimal point in the output is 1, so we can get the
256
         --  exponent as the difference between these two values. The one
257
         --  exception is for the value zero, which by convention has an
258
         --  exponent of +0.
259
 
260
         if Zero then
261
            Expon := 0;
262
         else
263
            Expon := Digits_Before_Point - 1;
264
         end if;
265
 
266
         Set ('E');
267
         ND := 0;
268
 
269
         if Expon >= 0 then
270
            Set ('+');
271
            Set_Image_Integer (Expon, Digs, ND);
272
         else
273
            Set ('-');
274
            Set_Image_Integer (-Expon, Digs, ND);
275
         end if;
276
 
277
         Set_Zeroes (Exp - ND - 1);
278
         Set_Digits (1, ND);
279
         return;
280
 
281
      --  Case of no exponent given. To make these cases clear, we use
282
      --  examples. For all the examples, we assume Fore = 2, Aft = 3.
283
      --  A P in the example input string is an implied zero position,
284
      --  not included in the input string.
285
 
286
      else
287
         --  Round at correct position
288
         --    Input: 4PP      => unchanged
289
         --    Input: 400.03   => unchanged
290
         --    Input  3.4567   => 3.457
291
         --    Input: 9.9999   => 10.000
292
         --    Input: 0.PPP5   => 0.001
293
         --    Input: 0.PPP4   => 0
294
         --    Input: 0.00003  => 0
295
 
296
         Round (LD - (Scale - Digits_After_Point));
297
 
298
         --  No digits before point in input
299
         --    Input: .123   Output: 0.123
300
         --    Input: .PP3   Output: 0.003
301
 
302
         if Digits_Before_Point <= 0 then
303
            Set_Blanks_And_Sign (Fore - 1);
304
            Set ('0');
305
            Set ('.');
306
 
307
            Set_Zeroes (Digits_After_Point - ND);
308
            Set_Digits (FD, LD);
309
 
310
         --  At least one digit before point in input
311
 
312
         else
313
            Set_Blanks_And_Sign (Fore - Digits_Before_Point);
314
 
315
            --  Less digits in input than are needed before point
316
            --    Input: 1PP  Output: 100.000
317
 
318
            if ND < Digits_Before_Point then
319
               Set_Digits (FD, LD);
320
               Set_Zeroes (Digits_Before_Point - ND);
321
               Set ('.');
322
               Set_Zeroes (Digits_After_Point);
323
 
324
            --  Input has full amount of digits before decimal point
325
 
326
            else
327
               Set_Digits (FD, FD + Digits_Before_Point - 1);
328
               Set ('.');
329
               Set_Digits (FD + Digits_Before_Point, LD);
330
               Set_Zeroes (Digits_After_Point - (ND - Digits_Before_Point));
331
            end if;
332
         end if;
333
      end if;
334
 
335
   end Set_Decimal_Digits;
336
 
337
   -----------------------
338
   -- Set_Image_Decimal --
339
   -----------------------
340
 
341
   procedure Set_Image_Decimal
342
     (V     : Integer;
343
      S     : out String;
344
      P     : in out Natural;
345
      Scale : Integer;
346
      Fore  : Natural;
347
      Aft   : Natural;
348
      Exp   : Natural)
349
   is
350
      Digs : String := Image_Integer (V);
351
      --  Sign and digits of decimal value
352
 
353
   begin
354
      Set_Decimal_Digits (Digs, Digs'Length, S, P, Scale, Fore, Aft, Exp);
355
   end Set_Image_Decimal;
356
 
357
end System.Img_Dec;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.