1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <ctype.h>
include <printf.h>
# DTOC -- Format and output a floating point number, in any of the formats
# F,E,G,H, or M (H and M are hours-minutes-seconds and minutes-seconds formats,
# respectively).
int procedure dtoc (dval, outstr, maxch, decpl, a_fmt, width)
double dval # number to be output
char outstr[ARB] # output string
int maxch # size of the output string
int decpl # number of decimal places or precision
int a_fmt, fmt # format type (feghm)
int width # field width
bool neg
double val
int op, round, h, m, s, f, v, i
int dtoc3(), ltoc()
define output {outstr[op]=$1;op=op+1;if(op>maxch)goto retry_}
define retry_ 91
begin
# If HMS format is not desired, simply call DTOC3. Control also
# returns to this point in the event of overflow.
fmt = a_fmt
if (IS_UPPER (fmt))
fmt = TO_LOWER (fmt)
if (fmt == FMT_FIXED || fmt == FMT_EXPON || fmt == FMT_GENERAL ||
IS_INDEFD(dval)) {
retry_
return (dtoc3 (dval, outstr, maxch, decpl, fmt, width))
}
# HMS format is implemented using calls to DTOC3, LTOC. Use zero
# fill to get two chars for the second and third fields, if necessary.
# The second field is omitted for "m" format. No whitespace is
# permitted in an HMS (or other) number. If the format is %H or %M
# (instead of the usual %h or %m) scale the number by 15 before output
# (converting degrees to hours).
if (IS_UPPER (a_fmt))
val = dval / 15.0
else
val = dval
# Working with a positive number simplifies things.
neg = (val < 0.0)
if (neg)
val = -val
# Decompose number into HMS or MS.
h = 0
if (fmt == FMT_HMS) {
h = int(val); val = (val - h) * 60.0
}
m = int(val); val = (val - m) * 60.0
s = int(val); val = (val - s)
# Round the fractional seconds field and carry if the rounded value
# is greater than 60. This has to be done explicitly due to the
# "base 60" sexagesimal arithmetic.
round = (10.0 ** decpl)
f = int (val * round + 0.5)
while (f >= round) {
f = f - round
s = s + 1
}
while (s >= 60) {
s = s - 60
m = m + 1
}
while (m >= 60) {
m = m - 60
h = h + 1
}
# Format the output string.
op = 1
if (neg)
output ('-')
# Output the first field, which is the hours field for HMS format,
# or the minutes field for MS format.
if (fmt == FMT_HMS)
v = h
else
v = h * 60 + m
op = op + ltoc (v, outstr[op], maxch-op+1)
output (':')
# Output the minutes field in HMS format.
if (fmt == FMT_HMS) {
output (TO_DIGIT (m / 10))
output (TO_DIGIT (mod (m, 10)))
output (':')
}
# Output the seconds field.
output (TO_DIGIT (s / 10))
output (TO_DIGIT (mod (s, 10)))
# Output the fraction, if any.
if (decpl > 0) {
output ('.')
do i = 1, decpl {
round = round / 10
output (TO_DIGIT (f / round))
f = mod (f, round)
}
}
# If the HMS format does not fit, go try a more compact format.
if (op-1 > abs(width) || op > maxch) {
fmt = FMT_GENERAL
goto retry_
}
outstr[op] = EOS
return (op-1)
end
|