A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/python/cpython/commit/3ea7b41b5805c60a05e697211d0bfc14a62a19fb below:

Moved Rational._binary_float_to_ratio() to float.as_integer_ratio() b… · python/cpython@3ea7b41 · GitHub

@@ -1161,6 +1161,163 @@ float_float(PyObject *v)

1161 1161

return v;

1162 1162

}

1163 1163 1164 +

static PyObject *

1165 +

float_as_integer_ratio(PyObject *v)

1166 +

{

1167 +

double self;

1168 +

double float_part;

1169 +

int exponent;

1170 +

int is_negative;

1171 +

const int chunk_size = 28;

1172 +

PyObject *prev;

1173 +

PyObject *py_chunk = NULL;

1174 +

PyObject *py_exponent = NULL;

1175 +

PyObject *numerator = NULL;

1176 +

PyObject *denominator = NULL;

1177 +

PyObject *result_pair = NULL;

1178 +

PyNumberMethods *long_methods;

1179 + 1180 +

#define INPLACE_UPDATE(obj, call) \

1181 +

prev = obj; \

1182 +

obj = call; \

1183 +

Py_DECREF(prev); \

1184 + 1185 +

CONVERT_TO_DOUBLE(v, self);

1186 + 1187 +

if (Py_IS_INFINITY(self)) {

1188 +

PyErr_SetString(PyExc_OverflowError,

1189 +

"Cannot pass infinity to float.as_integer_ratio.");

1190 +

return NULL;

1191 +

}

1192 +

#ifdef Py_NAN

1193 +

if (Py_IS_NAN(self)) {

1194 +

PyErr_SetString(PyExc_ValueError,

1195 +

"Cannot pass nan to float.as_integer_ratio.");

1196 +

return NULL;

1197 +

}

1198 +

#endif

1199 + 1200 +

if (self == 0) {

1201 +

numerator = PyInt_FromLong(0);

1202 +

if (numerator == NULL) goto error;

1203 +

denominator = PyInt_FromLong(1);

1204 +

if (denominator == NULL) goto error;

1205 +

result_pair = PyTuple_Pack(2, numerator, denominator);

1206 +

/* Hand ownership over to the tuple. If the tuple

1207 +

wasn't created successfully, we want to delete the

1208 +

ints anyway. */

1209 +

Py_DECREF(numerator);

1210 +

Py_DECREF(denominator);

1211 +

return result_pair;

1212 +

}

1213 + 1214 +

/* XXX: Could perhaps handle FLT_RADIX!=2 by using ilogb and

1215 +

scalbn, but those may not be in C89. */

1216 +

PyFPE_START_PROTECT("as_integer_ratio", goto error);

1217 +

float_part = frexp(self, &exponent);

1218 +

is_negative = 0;

1219 +

if (float_part < 0) {

1220 +

float_part = -float_part;

1221 +

is_negative = 1;

1222 +

/* 0.5 <= float_part < 1.0 */

1223 +

}

1224 +

PyFPE_END_PROTECT(float_part);

1225 +

/* abs(self) == float_part * 2**exponent exactly */

1226 + 1227 +

/* Suck up chunk_size bits at a time; 28 is enough so that we

1228 +

suck up all bits in 2 iterations for all known binary

1229 +

double-precision formats, and small enough to fit in a

1230 +

long. */

1231 +

numerator = PyLong_FromLong(0);

1232 +

if (numerator == NULL) goto error;

1233 + 1234 +

long_methods = PyLong_Type.tp_as_number;

1235 + 1236 +

py_chunk = PyLong_FromLong(chunk_size);

1237 +

if (py_chunk == NULL) goto error;

1238 + 1239 +

while (float_part != 0) {

1240 +

/* invariant: abs(self) ==

1241 +

(numerator + float_part) * 2**exponent exactly */

1242 +

long digit;

1243 +

PyObject *py_digit;

1244 + 1245 +

PyFPE_START_PROTECT("as_integer_ratio", goto error);

1246 +

/* Pull chunk_size bits out of float_part, into digits. */

1247 +

float_part = ldexp(float_part, chunk_size);

1248 +

digit = (long)float_part;

1249 +

float_part -= digit;

1250 +

/* 0 <= float_part < 1 */

1251 +

exponent -= chunk_size;

1252 +

PyFPE_END_PROTECT(float_part);

1253 + 1254 +

/* Shift digits into numerator. */

1255 +

// numerator <<= chunk_size

1256 +

INPLACE_UPDATE(numerator,

1257 +

long_methods->nb_lshift(numerator, py_chunk));

1258 +

if (numerator == NULL) goto error;

1259 + 1260 +

// numerator |= digit

1261 +

py_digit = PyLong_FromLong(digit);

1262 +

if (py_digit == NULL) goto error;

1263 +

INPLACE_UPDATE(numerator,

1264 +

long_methods->nb_or(numerator, py_digit));

1265 +

Py_DECREF(py_digit);

1266 +

if (numerator == NULL) goto error;

1267 +

}

1268 + 1269 +

/* Add in the sign bit. */

1270 +

if (is_negative) {

1271 +

INPLACE_UPDATE(numerator,

1272 +

long_methods->nb_negative(numerator));

1273 +

if (numerator == NULL) goto error;

1274 +

}

1275 + 1276 +

/* now self = numerator * 2**exponent exactly; fold in 2**exponent */

1277 +

denominator = PyLong_FromLong(1);

1278 +

py_exponent = PyLong_FromLong(labs(exponent));

1279 +

if (py_exponent == NULL) goto error;

1280 +

INPLACE_UPDATE(py_exponent,

1281 +

long_methods->nb_lshift(denominator, py_exponent));

1282 +

if (py_exponent == NULL) goto error;

1283 +

if (exponent > 0) {

1284 +

INPLACE_UPDATE(numerator,

1285 +

long_methods->nb_multiply(numerator,

1286 +

py_exponent));

1287 +

if (numerator == NULL) goto error;

1288 +

}

1289 +

else {

1290 +

Py_DECREF(denominator);

1291 +

denominator = py_exponent;

1292 +

py_exponent = NULL;

1293 +

}

1294 + 1295 +

result_pair = PyTuple_Pack(2, numerator, denominator);

1296 + 1297 +

#undef INPLACE_UPDATE

1298 +

error:

1299 +

Py_XDECREF(py_exponent);

1300 +

Py_XDECREF(py_chunk);

1301 +

Py_XDECREF(denominator);

1302 +

Py_XDECREF(numerator);

1303 +

return result_pair;

1304 +

}

1305 + 1306 +

PyDoc_STRVAR(float_as_integer_ratio_doc,

1307 +

"float.as_integer_ratio() -> (int, int)\n"

1308 +

"\n"

1309 +

"Returns a pair of integers, not necessarily in lowest terms, whose\n"

1310 +

"ratio is exactly equal to the original float. This method raises an\n"

1311 +

"OverflowError on infinities and a ValueError on nans. The resulting\n"

1312 +

"denominator will be positive.\n"

1313 +

"\n"

1314 +

">>> (10.0).as_integer_ratio()\n"

1315 +

"(167772160L, 16777216L)\n"

1316 +

">>> (0.0).as_integer_ratio()\n"

1317 +

"(0, 1)\n"

1318 +

">>> (-.25).as_integer_ratio()\n"

1319 +

"(-134217728L, 536870912L)");

1320 + 1164 1321 1165 1322

static PyObject *

1166 1323

float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);

@@ -1349,6 +1506,8 @@ static PyMethodDef float_methods[] = {

1349 1506

"Returns self, the complex conjugate of any float."},

1350 1507

{"__trunc__", (PyCFunction)float_trunc, METH_NOARGS,

1351 1508

"Returns the Integral closest to x between 0 and x."},

1509 +

{"as_integer_ratio", (PyCFunction)float_as_integer_ratio, METH_NOARGS,

1510 +

float_as_integer_ratio_doc},

1352 1511

{"__getnewargs__", (PyCFunction)float_getnewargs, METH_NOARGS},

1353 1512

{"__getformat__", (PyCFunction)float_getformat,

1354 1513

METH_O|METH_CLASS, float_getformat_doc},


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4