1 /* Header files. */
2 /* ============= */
3 /* Interface definitions. */
4 /* ---------------------- */
5 #include "pointset.h"           /* declaration of AST__BAD etc */
6 
7 /* C header files. */
8 /* --------------- */
9 #include <float.h>
10 #include <stdio.h>
11 #include <string.h>
12 
13 /* Local Constants: */
14 #define BUFF_LEN ( 2 * DBL_DIG + 20 ) /* Buffer length */
15 #define IEEE_DIG 17                   /* Minimum number of digits required by
16                                          IEEE for conversion from binary to
17                                          string and back again to be an
18                                          identity. */
19 
20 /* Prototypes for local functions */
21 static void printdval( double );
22 static void printfval( float );
23 
24 /* Main function. */
25 /* ============== */
main(int argc,char * argv[])26 int main( int argc, char *argv[] ) {
27 /*
28 *+
29 *  Name:
30 *     astbad
31 
32 *  Purpose:
33 *     Generate a string representing an AST floating point constant.
34 
35 *  Invocation:
36 *     astbad <value>
37 
38 *  Type:
39 *     C program.
40 
41 *  Description:
42 *     This program writes a string to standard output containing
43 *     a formatted decimal representation of a specified C floating point
44 *     constant defined by AST. This is intended for use in defining these
45 *     constants for use from languages other than C.
46 *
47 *     The value written should contain sufficient decimal digits so
48 *     that a routine that uses it to generate a value in another
49 *     language will produce exactly the same value as a C program
50 *     using the same macro.
51 
52 *  Arguments:
53 *     value = LITERAL
54 *        The name of the constant to be printed: AST__BAD, AST__NAN or
55 *        AST__NANF. If not supplied, AST__BAD is printed.
56 
57 *  Copyright:
58 *     Copyright (C) 2009-2011 Science & Technology Facilities Council.
59 *     Copyright (C) 1997-2006 Council for the Central Laboratory of the
60 *     Research Councils
61 
62 *  Licence:
63 *     This program is free software: you can redistribute it and/or
64 *     modify it under the terms of the GNU Lesser General Public
65 *     License as published by the Free Software Foundation, either
66 *     version 3 of the License, or (at your option) any later
67 *     version.
68 *
69 *     This program is distributed in the hope that it will be useful,
70 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
71 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
72 *     GNU Lesser General Public License for more details.
73 *
74 *     You should have received a copy of the GNU Lesser General
75 *     License along with this program.  If not, see
76 *     <http://www.gnu.org/licenses/>.
77 
78 *  Authors:
79 *     RFWS: R.F. Warren-Smith (Starlink)
80 *     DSB: David S. Berry (Starlink)
81 *     TIMJ: Tim Jenness (JAC, Hawaii)
82 
83 *  History:
84 *     18-NOV-1997 (RFWS);
85 *        Original version.
86 *     24-OCT-2000 (DSB):
87 *        Ensure that the number of digits used is at least the minimum
88 *        required by IEEE for a conversion from binary to string and back
89 *        to binary to be an identity.
90 *     31-MAR-2009 (TIMJ):
91 *        Does not take any arguments so don't try to read arguments.
92 *     18-JAN-2011 (DSB):
93 *        Extend to print other floating point constants as well as
94 *        AST__BAD.
95 *-
96 */
97 
98 /* Local Variables; */
99    const char *name;        /* Pointer to name of constant to be printed */
100 
101 /* Get the name of the constant to be printed. */
102    if( argc > 1 ) {
103       name = argv[1];
104    } else {
105       name = "AST__BAD";
106    }
107 
108 /* Print it. */
109    if( !strcmp( name, "AST__BAD" ) ) {
110       printdval( AST__BAD );
111 
112    } else if( !strcmp( name, "AST__NAN" ) ) {
113       printdval( AST__NAN );
114 
115    } else if( !strcmp( name, "AST__NANF" ) ) {
116       printfval( AST__NANF );
117 
118 /* Issue an error message if the argument is unknown. */
119    } else {
120       (void) fprintf( stderr, "astbad: Unknown constant requested: %s\n",
121                       name );
122    }
123 
124 /* Exit. */
125    return 0;
126 }
127 
128 
129 /* Print a double precision value to standard output */
printdval(double val)130 static void printdval( double val ){
131 
132 /* Local Variables: */
133    char buff[ BUFF_LEN + 1 ];    /* Buffer for formatted string */
134    double newval;                /* Value read back from string */
135    int digits;                   /* Number of digits of precision */
136 
137 /* Vary the precision over a reasonable range to see how many decimal
138    digits are required. The initial number of digits is the larger of
139    DBL_DIG and IEEE_DIG. */
140    for ( digits = ( DBL_DIG > IEEE_DIG )?DBL_DIG:IEEE_DIG;
141          digits <= ( 2 * DBL_DIG ); digits++ ) {
142 
143 /* Format the value using this precision and then read it back. */
144       (void) sprintf( buff, "%.*G", digits, val );
145       (void) sscanf( buff, "%lg", &newval );
146 
147 /* Quit looping when the original value is read back. */
148       if ( newval == val ) break;
149    }
150 
151 /* Write the value to standard output, with one extra digit for good
152    measure. */
153    (void) printf( "%.*G\n", digits + 1, val );
154 }
155 
156 /* Print a single precision value to standard output */
printfval(float val)157 static void printfval( float val ){
158 
159 /* Local Variables: */
160    char buff[ BUFF_LEN + 1 ];    /* Buffer for formatted string */
161    float newval;                 /* Value read back from string */
162    int digits;                   /* Number of digits of precision */
163 
164 /* Vary the precision over a reasonable range to see how many decimal
165    digits are required. The initial number of digits is FLT_DIG. */
166    for ( digits = FLT_DIG; digits <= ( 2 * FLT_DIG ); digits++ ) {
167 
168 /* Format the value using this precision and then read it back. */
169       (void) sprintf( buff, "%.*G", digits, val );
170       (void) sscanf( buff, "%g", &newval );
171 
172 /* Quit looping when the original value is read back. */
173       if ( newval == val ) break;
174    }
175 
176 /* Write the value to standard output, with one extra digit for good
177    measure. */
178    (void) printf( "%.*G\n", digits + 1, val );
179 
180 }
181 
182