Commit df44a545 authored by chris's avatar chris

added binary float

parent 90cf25e6
/*
$Id: cPickle.c,v 1.22 1997/02/26 19:34:38 chris Exp $
$Id: cPickle.c,v 1.23 1997/02/28 21:52:23 chris Exp $
Copyright
......@@ -59,6 +59,7 @@ static char cPickle_module_documentation[] =
#include "Python.h"
#include "cStringIO.h"
#include "graminit.h"
#include "mymath.h"
#include <errno.h>
......@@ -74,6 +75,9 @@ static char cPickle_module_documentation[] =
#define POP '0'
#define DUP '2'
#define FLOAT 'F'
#ifdef FORMAT_1_3
#define BINFLOAT 'G'
#endif
#define INT 'I'
#define BININT 'J'
#define BININT1 'K'
......@@ -718,13 +722,108 @@ finally:
static int
save_float(Picklerobject *self, PyObject *args) {
char c_str[250];
double x = PyFloat_AS_DOUBLE((PyFloatObject *)args);
#ifdef FORMAT_1_3
if (self->bin) {
int s, e, i = -1;
double f;
long fhi, flo;
char str[9], *p = str;
*p = BINFLOAT;
p++;
if (x < 0) {
s = 1;
x = -x;
}
else
s = 0;
f = frexp(x, &e);
/* Normalize f to be in the range [1.0, 2.0) */
if (0.5 <= f && f < 1.0) {
f *= 2.0;
e--;
}
else if (f == 0.0) {
e = 0;
}
else {
PyErr_SetString(PyExc_SystemError,
"frexp() result out of range");
return -1;
}
if (e >= 1024) {
/* XXX 1024 itself is reserved for Inf/NaN */
PyErr_SetString(PyExc_OverflowError,
"float too large to pack with d format");
return -1;
}
else if (e < -1022) {
/* Gradual underflow */
f = ldexp(f, 1022 + e);
e = 0;
}
else {
e += 1023;
f -= 1.0; /* Get rid of leading 1 */
}
/* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
f *= 268435456.0; /* 2**28 */
fhi = (long) floor(f); /* Truncate */
f -= (double)fhi;
f *= 16777216.0; /* 2**24 */
flo = (long) floor(f + 0.5); /* Round */
/* First byte */
*p = (s<<7) | (e>>4);
p++;
/* Second byte */
*p = ((e&0xF)<<4) | (fhi>>24);
p++;
/* Third byte */
*p = (fhi>>16) & 0xFF;
p++;
/* Fourth byte */
*p = (fhi>>8) & 0xFF;
p++;
/* Fifth byte */
*p = fhi & 0xFF;
p++;
/* Sixth byte */
*p = (flo>>16) & 0xFF;
p++;
/* Seventh byte */
*p = (flo>>8) & 0xFF;
p++;
/* Eighth byte */
*p = flo & 0xFF;
if ((*self->write_func)(self, str, 9) < 0)
return -1;
}
else
#endif
{
char c_str[250];
c_str[0] = FLOAT;
sprintf(c_str + 1, "%f\n", PyFloat_AS_DOUBLE((PyFloatObject *)args));
sprintf(c_str + 1, "%f\n", x);
if ((*self->write_func)(self, c_str, strlen(c_str)) < 0)
return -1;
}
return 0;
}
......@@ -1942,6 +2041,80 @@ finally:
return res;
}
#ifdef FORMAT_1_3
static int
load_binfloat(Unpicklerobject *self, PyObject *args) {
PyObject *py_float = 0;
int s, e, res = -1;
long fhi, flo;
double x;
char *p;
if ((*self->read_func)(self, &p, 8) < 0)
return -1;
/* First byte */
s = (*p>>7) & 1;
e = (*p & 0x7F) << 4;
p++;
/* Second byte */
e |= (*p>>4) & 0xF;
fhi = (*p & 0xF) << 24;
p++;
/* Third byte */
fhi |= (*p & 0xFF) << 16;
p++;
/* Fourth byte */
fhi |= (*p & 0xFF) << 8;
p++;
/* Fifth byte */
fhi |= *p & 0xFF;
p++;
/* Sixth byte */
flo = (*p & 0xFF) << 16;
p++;
/* Seventh byte */
flo |= (*p & 0xFF) << 8;
p++;
/* Eighth byte */
flo |= *p & 0xFF;
x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
x /= 268435456.0; /* 2**28 */
/* XXX This sadly ignores Inf/NaN */
if (e == 0)
e = -1022;
else {
x += 1.0;
e -= 1023;
}
x = ldexp(x, e);
if (s)
x = -x;
UNLESS(py_float = PyFloat_FromDouble(x))
goto finally;
if (PyList_Append(self->stack, py_float) < 0)
goto finally;
res = 0;
finally:
Py_XDECREF(py_float);
return res;
}
#endif
static int
load_string(Unpicklerobject *self, PyObject *args) {
......@@ -2964,6 +3137,13 @@ Unpickler_load(Unpicklerobject *self, PyObject *args) {
break;
continue;
#ifdef FORMAT_1_3
case BINFLOAT:
if (load_binfloat(self, NULL) < 0)
break;
continue;
#endif
case BINSTRING:
if (load_binstring(self, NULL) < 0)
break;
......@@ -3519,7 +3699,9 @@ init_stuff(PyObject *module, PyObject *module_dict) {
void
initcPickle() {
PyObject *m, *d;
char *rev="$Revision: 1.22 $";
char *rev="$Revision: 1.23 $";
PyObject *format_version;
PyObject *compatible_formats;
/* Create the module and add the functions */
m = Py_InitModule4("cPickle", cPickle_methods,
......@@ -3534,6 +3716,17 @@ initcPickle() {
PyDict_SetItemString(d,"__version__",
PyString_FromStringAndSize(rev+11,strlen(rev+11)-2));
#ifdef FORMAT_1_3
format_version = PyString_FromString("1.2");
compatible_formats = Py_BuildValue("[ss]", "1.0", "1.1");
#else
format_version = PyString_FromString("1.3");
compatible_formats = Py_BuildValue("[sss]", "1.0", "1.1", "1.2");
#endif
PyDict_SetItemString(d, "format_version", format_version);
PyDict_SetItemString(d, "compatible_formats", compatible_formats);
init_stuff(m, d);
CHECK_FOR_ERRORS("can't initialize module cPickle");
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment