f -= (double)fhi; f *= 16777216.0; /* 2**24 */ flo = (unsigned int)(f + 0.5); /* Round */ assert(flo <= 16777216); if (flo >> 24) { /* The carry propagated out of a string of 24 1 bits. */ flo = 0; ++fhi; if (fhi >> 28) { /* And it also progagated out of the next 28 bits. */ fhi = 0; ++e; if (e >= 2047) goto Overflow; } } /* First byte */ *p = (sign << 7) | (e >> 4); p += incr; /* Second byte */ *p = (unsigned char) (((e & 0xF) << 4) | (fhi >> 24)); p += incr; /* Third byte */ *p = (fhi >> 16) & 0xFF; p += incr; /* Fourth byte */ *p = (fhi >> 8) & 0xFF; p += incr; /* Fifth byte */ *p = fhi & 0xFF; p += incr; /* Sixth byte */ *p = (flo >> 16) & 0xFF; p += incr; /* Seventh byte */ *p = (flo >> 8) & 0xFF; p += incr; /* Eighth byte */ *p = flo & 0xFF; p += incr; /* Done */ return 0; Overflow: PyErr_SetString(PyExc_OverflowError, "float too large to pack with d format"); return -1; } else { const char *s = (char*)&x; int i, incr = 1; if ((double_format == ieee_little_endian_format && !le) || (double_format == ieee_big_endian_format && le)) { p += 7; incr = -1; } for (i = 0; i < 8; i++) { *p = *s++; p += incr; } return 0; }} double_PyFloat_Unpack4(const unsigned char *p, int le){ if (float_format == unknown_format) { unsigned char sign; int e; unsigned int f; double x; int incr = 1; if (le) { p += 3; incr = -1; } /* First byte */ sign = (*p >> 7) & 1; e = (*p & 0x7F) << 1; p += incr; /* Second byte */ e |= (*p >> 7) & 1; f = (*p & 0x7F) << 16; p += incr; if (e == 255) { PyErr_SetString( PyExc_ValueError, "can't unpack IEEE 754 special value " "on non-IEEE platform"); return -1; } /* Third byte */ f |= *p << 8; p += incr; /* Fourth byte */ f |= *p; x = (double)f / 8388608.0; /* XXX This sadly ignores Inf/NaN issues */ if (e == 0) e = -126; else { x += 1.0; e -= 127; } x = ldexp(x, e); if (sign) x = -x; return x; } else { float x; if ((float_format == ieee_little_endian_format && !le) || (float_format == ieee_big_endian_format && le)) { char buf[4]; char *d = &buf[3]; int i; for (i = 0; i < 4; i++) { *d-- = *p++; } memcpy(&x, buf, 4); } else { memcpy(&x, p, 4); } return x; } } double_PyFloat_Unpack8(const unsigned char *p, int le){ if (double_format == unknown_format) { unsigned char sign; int e; unsigned int fhi, flo; double x; int incr = 1; if (le) { p += 7; incr = -1; } /* First byte */ sign = (*p >> 7) & 1; e = (*p & 0x7F) << 4; p += incr; /* Second byte */ e |= (*p >> 4) & 0xF; fhi = (*p & 0xF) << 24; p += incr; if (e == 2047) { PyErr_SetString( PyExc_ValueError, "can't unpack IEEE 754 special value " "on non-IEEE platform"); return -1.0; } /* Third byte */ fhi |= *p << 16; p += incr; /* Fourth byte */ fhi |= *p << 8; p += incr; /* Fifth byte */ fhi |= *p; p += incr; /* Sixth byte */ flo = *p << 16; p += incr; /* Seventh byte */ flo |= *p << 8; p += incr; /* Eighth byte */ flo |= *p; x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */ x /= 268435456.0; /* 2**28 */ if (e == 0) e = -1022; else { x += 1.0; e -= 1023; } x = ldexp(x, e); if (sign) x = -x; return x; } else { double x; if ((double_format == ieee_little_endian_format && !le) || (double_format == ieee_big_endian_format && le)) { char buf[8]; char *d = &buf[7]; int i; for (i = 0; i < 8; i++) { *d-- = *p++; } memcpy(&x, buf, 8); } else { memcpy(&x, p, 8); } return x; }}Lines 1501–1748 of 1748. Previous lines
f -= (double)fhi; f *= 16777216.0; /* 2**24 */ flo = (unsigned int)(f + 0.5); /* Round */ assert(flo <= 16777216); if (flo >> 24) { /* The carry propagated out of a string of 24 1 bits. */ flo = 0; ++fhi; if (fhi >> 28) { /* And it also progagated out of the next 28 bits. */ fhi = 0; ++e; if (e >= 2047) goto Overflow; } } /* First byte */ *p = (sign << 7) | (e >> 4); p += incr; /* Second byte */ *p = (unsigned char) (((e & 0xF) << 4) | (fhi >> 24)); p += incr; /* Third byte */ *p = (fhi >> 16) & 0xFF; p += incr; /* Fourth byte */ *p = (fhi >> 8) & 0xFF; p += incr; /* Fifth byte */ *p = fhi & 0xFF; p += incr; /* Sixth byte */ *p = (flo >> 16) & 0xFF; p += incr; /* Seventh byte */ *p = (flo >> 8) & 0xFF; p += incr; /* Eighth byte */ *p = flo & 0xFF; p += incr; /* Done */ return 0; Overflow: PyErr_SetString(PyExc_OverflowError, "float too large to pack with d format"); return -1; } else { const char *s = (char*)&x; int i, incr = 1; if ((double_format == ieee_little_endian_format && !le) || (double_format == ieee_big_endian_format && le)) { p += 7; incr = -1; } for (i = 0; i < 8; i++) { *p = *s++; p += incr; } return 0; } } double _PyFloat_Unpack4(const unsigned char *p, int le) { if (float_format == unknown_format) { unsigned char sign; int e; unsigned int f; double x; int incr = 1; if (le) { p += 3; incr = -1; } /* First byte */ sign = (*p >> 7) & 1; e = (*p & 0x7F) << 1; p += incr; /* Second byte */ e |= (*p >> 7) & 1; f = (*p & 0x7F) << 16; p += incr; if (e == 255) { PyErr_SetString( PyExc_ValueError, "can't unpack IEEE 754 special value " "on non-IEEE platform"); return -1; } /* Third byte */ f |= *p << 8; p += incr; /* Fourth byte */ f |= *p; x = (double)f / 8388608.0; /* XXX This sadly ignores Inf/NaN issues */ if (e == 0) e = -126; else { x += 1.0; e -= 127; } x = ldexp(x, e); if (sign) x = -x; return x; } else { float x; if ((float_format == ieee_little_endian_format && !le) || (float_format == ieee_big_endian_format && le)) { char buf[4]; char *d = &buf[3]; int i; for (i = 0; i < 4; i++) { *d-- = *p++; } memcpy(&x, buf, 4); } else { memcpy(&x, p, 4); } return x; } } double _PyFloat_Unpack8(const unsigned char *p, int le) { if (double_format == unknown_format) { unsigned char sign; int e; unsigned int fhi, flo; double x; int incr = 1; if (le) { p += 7; incr = -1; } /* First byte */ sign = (*p >> 7) & 1; e = (*p & 0x7F) << 4; p += incr; /* Second byte */ e |= (*p >> 4) & 0xF; fhi = (*p & 0xF) << 24; p += incr; if (e == 2047) { PyErr_SetString( PyExc_ValueError, "can't unpack IEEE 754 special value " "on non-IEEE platform"); return -1.0; } /* Third byte */ fhi |= *p << 16; p += incr; /* Fourth byte */ fhi |= *p << 8; p += incr; /* Fifth byte */ fhi |= *p; p += incr; /* Sixth byte */ flo = *p << 16; p += incr; /* Seventh byte */ flo |= *p << 8; p += incr; /* Eighth byte */ flo |= *p; x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */ x /= 268435456.0; /* 2**28 */ if (e == 0) e = -1022; else { x += 1.0; e -= 1023; } x = ldexp(x, e); if (sign) x = -x; return x; } else { double x; if ((double_format == ieee_little_endian_format && !le) || (double_format == ieee_big_endian_format && le)) { char buf[8]; char *d = &buf[7]; int i; for (i = 0; i < 8; i++) { *d-- = *p++; } memcpy(&x, buf, 8); } else { memcpy(&x, p, 8); } return x; } }