/
_sfputd.c
91 lines (77 loc) · 2.94 KB
/
_sfputd.c
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
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.eclipse.org/org/documents/epl-v10.html *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <glenn.s.fowler@gmail.com> *
* David Korn <dgkorn@gmail.com> *
* Phong Vo <phongvo@gmail.com> *
* *
***********************************************************************/
#include "config_ast.h" // IWYU pragma: keep
#include <math.h>
#include <sys/types.h>
#include "sfhdr.h"
/* Write out a floating point value in a portable format
**
** Written by Kiem-Phong Vo.
*/
int _sfputd(Sfio_t *f, Sfdouble_t v) {
#define N_ARRAY (16 * sizeof(Sfdouble_t))
ssize_t n, w;
uchar *s, *ends;
int exp;
uchar c[N_ARRAY];
Sfdouble_t x;
SFMTXDECL(f)
SFMTXENTER(f, -1)
if (f->mode != SF_WRITE && _sfmode(f, SF_WRITE, 0) < 0) SFMTXRETURN(f, -1)
SFLOCK(f, 0)
/* get the sign of v */
if (v < 0.) {
v = -v;
n = 1;
} else
n = 0;
/* make the magnitude of v < 1 */
if (v != 0.)
v = frexpl(v, &exp);
else
exp = 0;
/* code the sign of v and exp */
if ((w = exp) < 0) {
n |= 02;
w = -w;
}
/* write out the signs and the exp */
SFOPEN(f)
if (sfputc(f, n) < 0 || (w = sfputu(f, w)) < 0) SFMTXRETURN(f, -1)
SFLOCK(f, 0)
w += 1;
s = (ends = &c[0]) + sizeof(c);
while (s > ends) { /* get 2^SF_PRECIS precision at a time */
n = (int)(x = ldexpl(v, SF_PRECIS));
*--s = n | SF_MORE;
v = x - n;
if (v <= 0.) break;
}
/* last byte is not SF_MORE */
ends = &c[0] + sizeof(c) - 1;
*ends &= ~SF_MORE;
/* write out coded bytes */
n = ends - s + 1;
w = SFWRITE(f, (void *)s, n) == n ? w + n : -1;
SFOPEN(f)
SFMTXRETURN(f, w)
}