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