| // clinic/float.c.h uses internal pycore_modsupport.h API | |
| #define PYTESTCAPI_NEED_INTERNAL_API | |
| #include "parts.h" | |
| #include "util.h" | |
| #include "clinic/float.c.h" | |
| /*[clinic input] | |
| module _testcapi | |
| [clinic start generated code]*/ | |
| /*[clinic end generated code: output=da39a3ee5e6b4b0d input=6361033e795369fc]*/ | |
| /*[clinic input] | |
| _testcapi.float_pack | |
| size: int | |
| d: double | |
| le: int | |
| / | |
| Test PyFloat_Pack2(), PyFloat_Pack4() and PyFloat_Pack8() | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _testcapi_float_pack_impl(PyObject *module, int size, double d, int le) | |
| /*[clinic end generated code: output=7899bd98f8b6cb04 input=52c9115121999c98]*/ | |
| { | |
| switch (size) | |
| { | |
| case 2: | |
| { | |
| char data[2]; | |
| if (PyFloat_Pack2(d, data, le) < 0) { | |
| return NULL; | |
| } | |
| return PyBytes_FromStringAndSize(data, Py_ARRAY_LENGTH(data)); | |
| } | |
| case 4: | |
| { | |
| char data[4]; | |
| if (PyFloat_Pack4(d, data, le) < 0) { | |
| return NULL; | |
| } | |
| return PyBytes_FromStringAndSize(data, Py_ARRAY_LENGTH(data)); | |
| } | |
| case 8: | |
| { | |
| char data[8]; | |
| if (PyFloat_Pack8(d, data, le) < 0) { | |
| return NULL; | |
| } | |
| return PyBytes_FromStringAndSize(data, Py_ARRAY_LENGTH(data)); | |
| } | |
| default: break; | |
| } | |
| PyErr_SetString(PyExc_ValueError, "size must 2, 4 or 8"); | |
| return NULL; | |
| } | |
| /*[clinic input] | |
| _testcapi.float_unpack | |
| data: str(accept={robuffer}, zeroes=True) | |
| le: int | |
| / | |
| Test PyFloat_Unpack2(), PyFloat_Unpack4() and PyFloat_Unpack8() | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _testcapi_float_unpack_impl(PyObject *module, const char *data, | |
| Py_ssize_t data_length, int le) | |
| /*[clinic end generated code: output=617059f889ddbfe4 input=c095e4bb75a696cd]*/ | |
| { | |
| assert(!PyErr_Occurred()); | |
| double d; | |
| switch (data_length) | |
| { | |
| case 2: | |
| d = PyFloat_Unpack2(data, le); | |
| break; | |
| case 4: | |
| d = PyFloat_Unpack4(data, le); | |
| break; | |
| case 8: | |
| d = PyFloat_Unpack8(data, le); | |
| break; | |
| default: | |
| PyErr_SetString(PyExc_ValueError, "data length must 2, 4 or 8 bytes"); | |
| return NULL; | |
| } | |
| if (d == -1.0 && PyErr_Occurred()) { | |
| return NULL; | |
| } | |
| return PyFloat_FromDouble(d); | |
| } | |
| /* Test PyOS_string_to_double. */ | |
| static PyObject * | |
| test_string_to_double(PyObject *self, PyObject *Py_UNUSED(ignored)) | |
| { | |
| double result; | |
| const char *msg; | |
| #define CHECK_STRING(STR, expected) \ | |
| do { \ | |
| result = PyOS_string_to_double(STR, NULL, NULL); \ | |
| if (result == -1.0 && PyErr_Occurred()) { \ | |
| return NULL; \ | |
| } \ | |
| if (result != (double)expected) { \ | |
| msg = "conversion of " STR " to float failed"; \ | |
| goto fail; \ | |
| } \ | |
| } while (0) | |
| #define CHECK_INVALID(STR) \ | |
| do { \ | |
| result = PyOS_string_to_double(STR, NULL, NULL); \ | |
| if (result == -1.0 && PyErr_Occurred()) { \ | |
| if (PyErr_ExceptionMatches(PyExc_ValueError)) { \ | |
| PyErr_Clear(); \ | |
| } \ | |
| else { \ | |
| return NULL; \ | |
| } \ | |
| } \ | |
| else { \ | |
| msg = "conversion of " STR " didn't raise ValueError"; \ | |
| goto fail; \ | |
| } \ | |
| } while (0) | |
| CHECK_STRING("0.1", 0.1); | |
| CHECK_STRING("1.234", 1.234); | |
| CHECK_STRING("-1.35", -1.35); | |
| CHECK_STRING(".1e01", 1.0); | |
| CHECK_STRING("2.e-2", 0.02); | |
| CHECK_INVALID(" 0.1"); | |
| CHECK_INVALID("\t\n-3"); | |
| CHECK_INVALID(".123 "); | |
| CHECK_INVALID("3\n"); | |
| CHECK_INVALID("123abc"); | |
| Py_RETURN_NONE; | |
| fail: | |
| PyErr_Format(PyExc_AssertionError, "test_string_to_double: %s", msg); | |
| return NULL; | |
| #undef CHECK_STRING | |
| #undef CHECK_INVALID | |
| } | |
| static PyMethodDef test_methods[] = { | |
| _TESTCAPI_FLOAT_PACK_METHODDEF | |
| _TESTCAPI_FLOAT_UNPACK_METHODDEF | |
| {"test_string_to_double", test_string_to_double, METH_NOARGS}, | |
| {NULL}, | |
| }; | |
| int | |
| _PyTestCapi_Init_Float(PyObject *mod) | |
| { | |
| if (PyModule_AddFunctions(mod, test_methods) < 0) { | |
| return -1; | |
| } | |
| #if (defined(__mips__) && !defined(__mips_nan2008)) || defined(__hppa__) | |
| return PyModule_Add(mod, "nan_msb_is_signaling", PyBool_FromLong(1)); | |
| #else | |
| return PyModule_Add(mod, "nan_msb_is_signaling", PyBool_FromLong(0)); | |
| #endif | |
| } |