int_ops.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. // Int primitive operations (tagged arbitrary-precision integers)
  2. //
  3. // These are registered in mypyc.primitives.int_ops.
  4. #include <Python.h>
  5. #include "CPy.h"
  6. #ifndef _WIN32
  7. // On 64-bit Linux and macOS, ssize_t and long are both 64 bits, and
  8. // PyLong_FromLong is faster than PyLong_FromSsize_t, so use the faster one
  9. #define CPyLong_FromSsize_t PyLong_FromLong
  10. #else
  11. // On 64-bit Windows, ssize_t is 64 bits but long is 32 bits, so we
  12. // can't use the above trick
  13. #define CPyLong_FromSsize_t PyLong_FromSsize_t
  14. #endif
  15. CPyTagged CPyTagged_FromSsize_t(Py_ssize_t value) {
  16. // We use a Python object if the value shifted left by 1 is too
  17. // large for Py_ssize_t
  18. if (unlikely(CPyTagged_TooBig(value))) {
  19. PyObject *object = PyLong_FromSsize_t(value);
  20. return ((CPyTagged)object) | CPY_INT_TAG;
  21. } else {
  22. return value << 1;
  23. }
  24. }
  25. CPyTagged CPyTagged_FromVoidPtr(void *ptr) {
  26. if ((uintptr_t)ptr > PY_SSIZE_T_MAX) {
  27. PyObject *object = PyLong_FromVoidPtr(ptr);
  28. return ((CPyTagged)object) | CPY_INT_TAG;
  29. } else {
  30. return CPyTagged_FromSsize_t((Py_ssize_t)ptr);
  31. }
  32. }
  33. CPyTagged CPyTagged_FromInt64(int64_t value) {
  34. if (unlikely(CPyTagged_TooBigInt64(value))) {
  35. PyObject *object = PyLong_FromLongLong(value);
  36. return ((CPyTagged)object) | CPY_INT_TAG;
  37. } else {
  38. return value << 1;
  39. }
  40. }
  41. CPyTagged CPyTagged_FromObject(PyObject *object) {
  42. int overflow;
  43. // The overflow check knows about CPyTagged's width
  44. Py_ssize_t value = CPyLong_AsSsize_tAndOverflow(object, &overflow);
  45. if (unlikely(overflow != 0)) {
  46. Py_INCREF(object);
  47. return ((CPyTagged)object) | CPY_INT_TAG;
  48. } else {
  49. return value << 1;
  50. }
  51. }
  52. CPyTagged CPyTagged_StealFromObject(PyObject *object) {
  53. int overflow;
  54. // The overflow check knows about CPyTagged's width
  55. Py_ssize_t value = CPyLong_AsSsize_tAndOverflow(object, &overflow);
  56. if (unlikely(overflow != 0)) {
  57. return ((CPyTagged)object) | CPY_INT_TAG;
  58. } else {
  59. Py_DECREF(object);
  60. return value << 1;
  61. }
  62. }
  63. CPyTagged CPyTagged_BorrowFromObject(PyObject *object) {
  64. int overflow;
  65. // The overflow check knows about CPyTagged's width
  66. Py_ssize_t value = CPyLong_AsSsize_tAndOverflow(object, &overflow);
  67. if (unlikely(overflow != 0)) {
  68. return ((CPyTagged)object) | CPY_INT_TAG;
  69. } else {
  70. return value << 1;
  71. }
  72. }
  73. PyObject *CPyTagged_AsObject(CPyTagged x) {
  74. PyObject *value;
  75. if (unlikely(CPyTagged_CheckLong(x))) {
  76. value = CPyTagged_LongAsObject(x);
  77. Py_INCREF(value);
  78. } else {
  79. value = CPyLong_FromSsize_t(CPyTagged_ShortAsSsize_t(x));
  80. if (value == NULL) {
  81. CPyError_OutOfMemory();
  82. }
  83. }
  84. return value;
  85. }
  86. PyObject *CPyTagged_StealAsObject(CPyTagged x) {
  87. PyObject *value;
  88. if (unlikely(CPyTagged_CheckLong(x))) {
  89. value = CPyTagged_LongAsObject(x);
  90. } else {
  91. value = CPyLong_FromSsize_t(CPyTagged_ShortAsSsize_t(x));
  92. if (value == NULL) {
  93. CPyError_OutOfMemory();
  94. }
  95. }
  96. return value;
  97. }
  98. Py_ssize_t CPyTagged_AsSsize_t(CPyTagged x) {
  99. if (likely(CPyTagged_CheckShort(x))) {
  100. return CPyTagged_ShortAsSsize_t(x);
  101. } else {
  102. return PyLong_AsSsize_t(CPyTagged_LongAsObject(x));
  103. }
  104. }
  105. CPy_NOINLINE
  106. void CPyTagged_IncRef(CPyTagged x) {
  107. if (unlikely(CPyTagged_CheckLong(x))) {
  108. Py_INCREF(CPyTagged_LongAsObject(x));
  109. }
  110. }
  111. CPy_NOINLINE
  112. void CPyTagged_DecRef(CPyTagged x) {
  113. if (unlikely(CPyTagged_CheckLong(x))) {
  114. Py_DECREF(CPyTagged_LongAsObject(x));
  115. }
  116. }
  117. CPy_NOINLINE
  118. void CPyTagged_XDecRef(CPyTagged x) {
  119. if (unlikely(CPyTagged_CheckLong(x))) {
  120. Py_XDECREF(CPyTagged_LongAsObject(x));
  121. }
  122. }
  123. CPyTagged CPyTagged_Negate(CPyTagged num) {
  124. if (CPyTagged_CheckShort(num)
  125. && num != (CPyTagged) ((Py_ssize_t)1 << (CPY_INT_BITS - 1))) {
  126. // The only possibility of an overflow error happening when negating a short is if we
  127. // attempt to negate the most negative number.
  128. return -num;
  129. }
  130. PyObject *num_obj = CPyTagged_AsObject(num);
  131. PyObject *result = PyNumber_Negative(num_obj);
  132. if (result == NULL) {
  133. CPyError_OutOfMemory();
  134. }
  135. Py_DECREF(num_obj);
  136. return CPyTagged_StealFromObject(result);
  137. }
  138. CPyTagged CPyTagged_Add(CPyTagged left, CPyTagged right) {
  139. // TODO: Use clang/gcc extension __builtin_saddll_overflow instead.
  140. if (likely(CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right))) {
  141. CPyTagged sum = left + right;
  142. if (likely(!CPyTagged_IsAddOverflow(sum, left, right))) {
  143. return sum;
  144. }
  145. }
  146. PyObject *left_obj = CPyTagged_AsObject(left);
  147. PyObject *right_obj = CPyTagged_AsObject(right);
  148. PyObject *result = PyNumber_Add(left_obj, right_obj);
  149. if (result == NULL) {
  150. CPyError_OutOfMemory();
  151. }
  152. Py_DECREF(left_obj);
  153. Py_DECREF(right_obj);
  154. return CPyTagged_StealFromObject(result);
  155. }
  156. CPyTagged CPyTagged_Subtract(CPyTagged left, CPyTagged right) {
  157. // TODO: Use clang/gcc extension __builtin_saddll_overflow instead.
  158. if (likely(CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right))) {
  159. CPyTagged diff = left - right;
  160. if (likely(!CPyTagged_IsSubtractOverflow(diff, left, right))) {
  161. return diff;
  162. }
  163. }
  164. PyObject *left_obj = CPyTagged_AsObject(left);
  165. PyObject *right_obj = CPyTagged_AsObject(right);
  166. PyObject *result = PyNumber_Subtract(left_obj, right_obj);
  167. if (result == NULL) {
  168. CPyError_OutOfMemory();
  169. }
  170. Py_DECREF(left_obj);
  171. Py_DECREF(right_obj);
  172. return CPyTagged_StealFromObject(result);
  173. }
  174. CPyTagged CPyTagged_Multiply(CPyTagged left, CPyTagged right) {
  175. // TODO: Consider using some clang/gcc extension
  176. if (CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right)) {
  177. if (!CPyTagged_IsMultiplyOverflow(left, right)) {
  178. return left * CPyTagged_ShortAsSsize_t(right);
  179. }
  180. }
  181. PyObject *left_obj = CPyTagged_AsObject(left);
  182. PyObject *right_obj = CPyTagged_AsObject(right);
  183. PyObject *result = PyNumber_Multiply(left_obj, right_obj);
  184. if (result == NULL) {
  185. CPyError_OutOfMemory();
  186. }
  187. Py_DECREF(left_obj);
  188. Py_DECREF(right_obj);
  189. return CPyTagged_StealFromObject(result);
  190. }
  191. CPyTagged CPyTagged_FloorDivide(CPyTagged left, CPyTagged right) {
  192. if (CPyTagged_CheckShort(left)
  193. && CPyTagged_CheckShort(right)
  194. && !CPyTagged_MaybeFloorDivideFault(left, right)) {
  195. Py_ssize_t result = CPyTagged_ShortAsSsize_t(left) / CPyTagged_ShortAsSsize_t(right);
  196. if (((Py_ssize_t)left < 0) != (((Py_ssize_t)right) < 0)) {
  197. if (result * right != left) {
  198. // Round down
  199. result--;
  200. }
  201. }
  202. return result << 1;
  203. }
  204. PyObject *left_obj = CPyTagged_AsObject(left);
  205. PyObject *right_obj = CPyTagged_AsObject(right);
  206. PyObject *result = PyNumber_FloorDivide(left_obj, right_obj);
  207. Py_DECREF(left_obj);
  208. Py_DECREF(right_obj);
  209. // Handle exceptions honestly because it could be ZeroDivisionError
  210. if (result == NULL) {
  211. return CPY_INT_TAG;
  212. } else {
  213. return CPyTagged_StealFromObject(result);
  214. }
  215. }
  216. CPyTagged CPyTagged_Remainder(CPyTagged left, CPyTagged right) {
  217. if (CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right)
  218. && !CPyTagged_MaybeRemainderFault(left, right)) {
  219. Py_ssize_t result = (Py_ssize_t)left % (Py_ssize_t)right;
  220. if (((Py_ssize_t)right < 0) != ((Py_ssize_t)left < 0) && result != 0) {
  221. result += right;
  222. }
  223. return result;
  224. }
  225. PyObject *left_obj = CPyTagged_AsObject(left);
  226. PyObject *right_obj = CPyTagged_AsObject(right);
  227. PyObject *result = PyNumber_Remainder(left_obj, right_obj);
  228. Py_DECREF(left_obj);
  229. Py_DECREF(right_obj);
  230. // Handle exceptions honestly because it could be ZeroDivisionError
  231. if (result == NULL) {
  232. return CPY_INT_TAG;
  233. } else {
  234. return CPyTagged_StealFromObject(result);
  235. }
  236. }
  237. bool CPyTagged_IsEq_(CPyTagged left, CPyTagged right) {
  238. if (CPyTagged_CheckShort(right)) {
  239. return false;
  240. } else {
  241. PyObject *left_obj = CPyTagged_AsObject(left);
  242. PyObject *right_obj = CPyTagged_AsObject(right);
  243. int result = PyObject_RichCompareBool(left_obj, right_obj, Py_EQ);
  244. Py_DECREF(left_obj);
  245. Py_DECREF(right_obj);
  246. if (result == -1) {
  247. CPyError_OutOfMemory();
  248. }
  249. return result;
  250. }
  251. }
  252. bool CPyTagged_IsLt_(CPyTagged left, CPyTagged right) {
  253. PyObject *left_obj = CPyTagged_AsObject(left);
  254. PyObject *right_obj = CPyTagged_AsObject(right);
  255. int result = PyObject_RichCompareBool(left_obj, right_obj, Py_LT);
  256. Py_DECREF(left_obj);
  257. Py_DECREF(right_obj);
  258. if (result == -1) {
  259. CPyError_OutOfMemory();
  260. }
  261. return result;
  262. }
  263. PyObject *CPyLong_FromStrWithBase(PyObject *o, CPyTagged base) {
  264. Py_ssize_t base_size_t = CPyTagged_AsSsize_t(base);
  265. return PyLong_FromUnicodeObject(o, base_size_t);
  266. }
  267. PyObject *CPyLong_FromStr(PyObject *o) {
  268. CPyTagged base = CPyTagged_FromSsize_t(10);
  269. return CPyLong_FromStrWithBase(o, base);
  270. }
  271. CPyTagged CPyTagged_FromFloat(double f) {
  272. if (f < ((double)CPY_TAGGED_MAX + 1.0) && f > (CPY_TAGGED_MIN - 1.0)) {
  273. return (Py_ssize_t)f << 1;
  274. }
  275. PyObject *o = PyLong_FromDouble(f);
  276. if (o == NULL)
  277. return CPY_INT_TAG;
  278. return CPyTagged_StealFromObject(o);
  279. }
  280. PyObject *CPyBool_Str(bool b) {
  281. return PyObject_Str(b ? Py_True : Py_False);
  282. }
  283. static void CPyLong_NormalizeUnsigned(PyLongObject *v) {
  284. Py_ssize_t i = CPY_LONG_SIZE_UNSIGNED(v);
  285. while (i > 0 && CPY_LONG_DIGIT(v, i - 1) == 0)
  286. i--;
  287. CPyLong_SetUnsignedSize(v, i);
  288. }
  289. // Bitwise op '&', '|' or '^' using the generic (slow) API
  290. static CPyTagged GenericBitwiseOp(CPyTagged a, CPyTagged b, char op) {
  291. PyObject *aobj = CPyTagged_AsObject(a);
  292. PyObject *bobj = CPyTagged_AsObject(b);
  293. PyObject *r;
  294. if (op == '&') {
  295. r = PyNumber_And(aobj, bobj);
  296. } else if (op == '|') {
  297. r = PyNumber_Or(aobj, bobj);
  298. } else {
  299. r = PyNumber_Xor(aobj, bobj);
  300. }
  301. if (unlikely(r == NULL)) {
  302. CPyError_OutOfMemory();
  303. }
  304. Py_DECREF(aobj);
  305. Py_DECREF(bobj);
  306. return CPyTagged_StealFromObject(r);
  307. }
  308. // Return pointer to digits of a PyLong object. If it's a short
  309. // integer, place digits in the buffer buf instead to avoid memory
  310. // allocation (it's assumed to be big enough). Return the number of
  311. // digits in *size. *size is negative if the integer is negative.
  312. static digit *GetIntDigits(CPyTagged n, Py_ssize_t *size, digit *buf) {
  313. if (CPyTagged_CheckShort(n)) {
  314. Py_ssize_t val = CPyTagged_ShortAsSsize_t(n);
  315. bool neg = val < 0;
  316. int len = 1;
  317. if (neg) {
  318. val = -val;
  319. }
  320. buf[0] = val & PyLong_MASK;
  321. if (val > (Py_ssize_t)PyLong_MASK) {
  322. val >>= PyLong_SHIFT;
  323. buf[1] = val & PyLong_MASK;
  324. if (val > (Py_ssize_t)PyLong_MASK) {
  325. buf[2] = val >> PyLong_SHIFT;
  326. len = 3;
  327. } else {
  328. len = 2;
  329. }
  330. }
  331. *size = neg ? -len : len;
  332. return buf;
  333. } else {
  334. PyLongObject *obj = (PyLongObject *)CPyTagged_LongAsObject(n);
  335. *size = CPY_LONG_SIZE_SIGNED(obj);
  336. return &CPY_LONG_DIGIT(obj, 0);
  337. }
  338. }
  339. // Shared implementation of bitwise '&', '|' and '^' (specified by op) for at least
  340. // one long operand. This is somewhat optimized for performance.
  341. static CPyTagged BitwiseLongOp(CPyTagged a, CPyTagged b, char op) {
  342. // Directly access the digits, as there is no fast C API function for this.
  343. digit abuf[3];
  344. digit bbuf[3];
  345. Py_ssize_t asize;
  346. Py_ssize_t bsize;
  347. digit *adigits = GetIntDigits(a, &asize, abuf);
  348. digit *bdigits = GetIntDigits(b, &bsize, bbuf);
  349. PyLongObject *r;
  350. if (unlikely(asize < 0 || bsize < 0)) {
  351. // Negative operand. This is slower, but bitwise ops on them are pretty rare.
  352. return GenericBitwiseOp(a, b, op);
  353. }
  354. // Optimized implementation for two non-negative integers.
  355. // Swap a and b as needed to ensure a is no longer than b.
  356. if (asize > bsize) {
  357. digit *tmp = adigits;
  358. adigits = bdigits;
  359. bdigits = tmp;
  360. Py_ssize_t tmp_size = asize;
  361. asize = bsize;
  362. bsize = tmp_size;
  363. }
  364. r = _PyLong_New(op == '&' ? asize : bsize);
  365. if (unlikely(r == NULL)) {
  366. CPyError_OutOfMemory();
  367. }
  368. Py_ssize_t i;
  369. if (op == '&') {
  370. for (i = 0; i < asize; i++) {
  371. CPY_LONG_DIGIT(r, i) = adigits[i] & bdigits[i];
  372. }
  373. } else {
  374. if (op == '|') {
  375. for (i = 0; i < asize; i++) {
  376. CPY_LONG_DIGIT(r, i) = adigits[i] | bdigits[i];
  377. }
  378. } else {
  379. for (i = 0; i < asize; i++) {
  380. CPY_LONG_DIGIT(r, i) = adigits[i] ^ bdigits[i];
  381. }
  382. }
  383. for (; i < bsize; i++) {
  384. CPY_LONG_DIGIT(r, i) = bdigits[i];
  385. }
  386. }
  387. CPyLong_NormalizeUnsigned(r);
  388. return CPyTagged_StealFromObject((PyObject *)r);
  389. }
  390. // Bitwise '&'
  391. CPyTagged CPyTagged_And(CPyTagged left, CPyTagged right) {
  392. if (likely(CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right))) {
  393. return left & right;
  394. }
  395. return BitwiseLongOp(left, right, '&');
  396. }
  397. // Bitwise '|'
  398. CPyTagged CPyTagged_Or(CPyTagged left, CPyTagged right) {
  399. if (likely(CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right))) {
  400. return left | right;
  401. }
  402. return BitwiseLongOp(left, right, '|');
  403. }
  404. // Bitwise '^'
  405. CPyTagged CPyTagged_Xor(CPyTagged left, CPyTagged right) {
  406. if (likely(CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right))) {
  407. return left ^ right;
  408. }
  409. return BitwiseLongOp(left, right, '^');
  410. }
  411. // Bitwise '~'
  412. CPyTagged CPyTagged_Invert(CPyTagged num) {
  413. if (likely(CPyTagged_CheckShort(num) && num != CPY_TAGGED_ABS_MIN)) {
  414. return ~num & ~CPY_INT_TAG;
  415. } else {
  416. PyObject *obj = CPyTagged_AsObject(num);
  417. PyObject *result = PyNumber_Invert(obj);
  418. if (unlikely(result == NULL)) {
  419. CPyError_OutOfMemory();
  420. }
  421. Py_DECREF(obj);
  422. return CPyTagged_StealFromObject(result);
  423. }
  424. }
  425. // Bitwise '>>'
  426. CPyTagged CPyTagged_Rshift(CPyTagged left, CPyTagged right) {
  427. if (likely(CPyTagged_CheckShort(left)
  428. && CPyTagged_CheckShort(right)
  429. && (Py_ssize_t)right >= 0)) {
  430. CPyTagged count = CPyTagged_ShortAsSsize_t(right);
  431. if (unlikely(count >= CPY_INT_BITS)) {
  432. if ((Py_ssize_t)left >= 0) {
  433. return 0;
  434. } else {
  435. return CPyTagged_ShortFromInt(-1);
  436. }
  437. }
  438. return ((Py_ssize_t)left >> count) & ~CPY_INT_TAG;
  439. } else {
  440. // Long integer or negative shift -- use generic op
  441. PyObject *lobj = CPyTagged_AsObject(left);
  442. PyObject *robj = CPyTagged_AsObject(right);
  443. PyObject *result = PyNumber_Rshift(lobj, robj);
  444. Py_DECREF(lobj);
  445. Py_DECREF(robj);
  446. if (result == NULL) {
  447. // Propagate error (could be negative shift count)
  448. return CPY_INT_TAG;
  449. }
  450. return CPyTagged_StealFromObject(result);
  451. }
  452. }
  453. static inline bool IsShortLshiftOverflow(Py_ssize_t short_int, Py_ssize_t shift) {
  454. return ((Py_ssize_t)(short_int << shift) >> shift) != short_int;
  455. }
  456. // Bitwise '<<'
  457. CPyTagged CPyTagged_Lshift(CPyTagged left, CPyTagged right) {
  458. if (likely(CPyTagged_CheckShort(left)
  459. && CPyTagged_CheckShort(right)
  460. && (Py_ssize_t)right >= 0
  461. && right < CPY_INT_BITS * 2)) {
  462. CPyTagged shift = CPyTagged_ShortAsSsize_t(right);
  463. if (!IsShortLshiftOverflow(left, shift))
  464. // Short integers, no overflow
  465. return left << shift;
  466. }
  467. // Long integer or out of range shift -- use generic op
  468. PyObject *lobj = CPyTagged_AsObject(left);
  469. PyObject *robj = CPyTagged_AsObject(right);
  470. PyObject *result = PyNumber_Lshift(lobj, robj);
  471. Py_DECREF(lobj);
  472. Py_DECREF(robj);
  473. if (result == NULL) {
  474. // Propagate error (could be negative shift count)
  475. return CPY_INT_TAG;
  476. }
  477. return CPyTagged_StealFromObject(result);
  478. }
  479. int64_t CPyLong_AsInt64(PyObject *o) {
  480. if (likely(PyLong_Check(o))) {
  481. PyLongObject *lobj = (PyLongObject *)o;
  482. Py_ssize_t size = Py_SIZE(lobj);
  483. if (likely(size == 1)) {
  484. // Fast path
  485. return CPY_LONG_DIGIT(lobj, 0);
  486. } else if (likely(size == 0)) {
  487. return 0;
  488. }
  489. }
  490. // Slow path
  491. int overflow;
  492. int64_t result = PyLong_AsLongLongAndOverflow(o, &overflow);
  493. if (result == -1) {
  494. if (PyErr_Occurred()) {
  495. return CPY_LL_INT_ERROR;
  496. } else if (overflow) {
  497. PyErr_SetString(PyExc_OverflowError, "int too large to convert to i64");
  498. return CPY_LL_INT_ERROR;
  499. }
  500. }
  501. return result;
  502. }
  503. int64_t CPyInt64_Divide(int64_t x, int64_t y) {
  504. if (y == 0) {
  505. PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero");
  506. return CPY_LL_INT_ERROR;
  507. }
  508. if (y == -1 && x == INT64_MIN) {
  509. PyErr_SetString(PyExc_OverflowError, "integer division overflow");
  510. return CPY_LL_INT_ERROR;
  511. }
  512. int64_t d = x / y;
  513. // Adjust for Python semantics
  514. if (((x < 0) != (y < 0)) && d * y != x) {
  515. d--;
  516. }
  517. return d;
  518. }
  519. int64_t CPyInt64_Remainder(int64_t x, int64_t y) {
  520. if (y == 0) {
  521. PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero");
  522. return CPY_LL_INT_ERROR;
  523. }
  524. // Edge case: avoid core dump
  525. if (y == -1 && x == INT64_MIN) {
  526. return 0;
  527. }
  528. int64_t d = x % y;
  529. // Adjust for Python semantics
  530. if (((x < 0) != (y < 0)) && d != 0) {
  531. d += y;
  532. }
  533. return d;
  534. }
  535. int32_t CPyLong_AsInt32(PyObject *o) {
  536. if (likely(PyLong_Check(o))) {
  537. #if CPY_3_12_FEATURES
  538. PyLongObject *lobj = (PyLongObject *)o;
  539. size_t tag = CPY_LONG_TAG(lobj);
  540. if (likely(tag == (1 << CPY_NON_SIZE_BITS))) {
  541. // Fast path
  542. return CPY_LONG_DIGIT(lobj, 0);
  543. } else if (likely(tag == CPY_SIGN_ZERO)) {
  544. return 0;
  545. }
  546. #else
  547. PyLongObject *lobj = (PyLongObject *)o;
  548. Py_ssize_t size = lobj->ob_base.ob_size;
  549. if (likely(size == 1)) {
  550. // Fast path
  551. return CPY_LONG_DIGIT(lobj, 0);
  552. } else if (likely(size == 0)) {
  553. return 0;
  554. }
  555. #endif
  556. }
  557. // Slow path
  558. int overflow;
  559. long result = PyLong_AsLongAndOverflow(o, &overflow);
  560. if (result > 0x7fffffffLL || result < -0x80000000LL) {
  561. overflow = 1;
  562. result = -1;
  563. }
  564. if (result == -1) {
  565. if (PyErr_Occurred()) {
  566. return CPY_LL_INT_ERROR;
  567. } else if (overflow) {
  568. PyErr_SetString(PyExc_OverflowError, "int too large to convert to i32");
  569. return CPY_LL_INT_ERROR;
  570. }
  571. }
  572. return result;
  573. }
  574. int32_t CPyInt32_Divide(int32_t x, int32_t y) {
  575. if (y == 0) {
  576. PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero");
  577. return CPY_LL_INT_ERROR;
  578. }
  579. if (y == -1 && x == INT32_MIN) {
  580. PyErr_SetString(PyExc_OverflowError, "integer division overflow");
  581. return CPY_LL_INT_ERROR;
  582. }
  583. int32_t d = x / y;
  584. // Adjust for Python semantics
  585. if (((x < 0) != (y < 0)) && d * y != x) {
  586. d--;
  587. }
  588. return d;
  589. }
  590. int32_t CPyInt32_Remainder(int32_t x, int32_t y) {
  591. if (y == 0) {
  592. PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero");
  593. return CPY_LL_INT_ERROR;
  594. }
  595. // Edge case: avoid core dump
  596. if (y == -1 && x == INT32_MIN) {
  597. return 0;
  598. }
  599. int32_t d = x % y;
  600. // Adjust for Python semantics
  601. if (((x < 0) != (y < 0)) && d != 0) {
  602. d += y;
  603. }
  604. return d;
  605. }
  606. void CPyInt32_Overflow() {
  607. PyErr_SetString(PyExc_OverflowError, "int too large to convert to i32");
  608. }
  609. int16_t CPyLong_AsInt16(PyObject *o) {
  610. if (likely(PyLong_Check(o))) {
  611. #if CPY_3_12_FEATURES
  612. PyLongObject *lobj = (PyLongObject *)o;
  613. size_t tag = CPY_LONG_TAG(lobj);
  614. if (likely(tag == (1 << CPY_NON_SIZE_BITS))) {
  615. // Fast path
  616. digit x = CPY_LONG_DIGIT(lobj, 0);
  617. if (x < 0x8000)
  618. return x;
  619. } else if (likely(tag == CPY_SIGN_ZERO)) {
  620. return 0;
  621. }
  622. #else
  623. PyLongObject *lobj = (PyLongObject *)o;
  624. Py_ssize_t size = lobj->ob_base.ob_size;
  625. if (likely(size == 1)) {
  626. // Fast path
  627. digit x = lobj->ob_digit[0];
  628. if (x < 0x8000)
  629. return x;
  630. } else if (likely(size == 0)) {
  631. return 0;
  632. }
  633. #endif
  634. }
  635. // Slow path
  636. int overflow;
  637. long result = PyLong_AsLongAndOverflow(o, &overflow);
  638. if (result > 0x7fff || result < -0x8000) {
  639. overflow = 1;
  640. result = -1;
  641. }
  642. if (result == -1) {
  643. if (PyErr_Occurred()) {
  644. return CPY_LL_INT_ERROR;
  645. } else if (overflow) {
  646. PyErr_SetString(PyExc_OverflowError, "int too large to convert to i16");
  647. return CPY_LL_INT_ERROR;
  648. }
  649. }
  650. return result;
  651. }
  652. int16_t CPyInt16_Divide(int16_t x, int16_t y) {
  653. if (y == 0) {
  654. PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero");
  655. return CPY_LL_INT_ERROR;
  656. }
  657. if (y == -1 && x == INT16_MIN) {
  658. PyErr_SetString(PyExc_OverflowError, "integer division overflow");
  659. return CPY_LL_INT_ERROR;
  660. }
  661. int16_t d = x / y;
  662. // Adjust for Python semantics
  663. if (((x < 0) != (y < 0)) && d * y != x) {
  664. d--;
  665. }
  666. return d;
  667. }
  668. int16_t CPyInt16_Remainder(int16_t x, int16_t y) {
  669. if (y == 0) {
  670. PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero");
  671. return CPY_LL_INT_ERROR;
  672. }
  673. // Edge case: avoid core dump
  674. if (y == -1 && x == INT16_MIN) {
  675. return 0;
  676. }
  677. int16_t d = x % y;
  678. // Adjust for Python semantics
  679. if (((x < 0) != (y < 0)) && d != 0) {
  680. d += y;
  681. }
  682. return d;
  683. }
  684. void CPyInt16_Overflow() {
  685. PyErr_SetString(PyExc_OverflowError, "int too large to convert to i16");
  686. }
  687. uint8_t CPyLong_AsUInt8(PyObject *o) {
  688. if (likely(PyLong_Check(o))) {
  689. #if CPY_3_12_FEATURES
  690. PyLongObject *lobj = (PyLongObject *)o;
  691. size_t tag = CPY_LONG_TAG(lobj);
  692. if (likely(tag == (1 << CPY_NON_SIZE_BITS))) {
  693. // Fast path
  694. digit x = CPY_LONG_DIGIT(lobj, 0);
  695. if (x < 256)
  696. return x;
  697. } else if (likely(tag == CPY_SIGN_ZERO)) {
  698. return 0;
  699. }
  700. #else
  701. PyLongObject *lobj = (PyLongObject *)o;
  702. Py_ssize_t size = lobj->ob_base.ob_size;
  703. if (likely(size == 1)) {
  704. // Fast path
  705. digit x = lobj->ob_digit[0];
  706. if (x < 256)
  707. return x;
  708. } else if (likely(size == 0)) {
  709. return 0;
  710. }
  711. #endif
  712. }
  713. // Slow path
  714. int overflow;
  715. long result = PyLong_AsLongAndOverflow(o, &overflow);
  716. if (result < 0 || result >= 256) {
  717. overflow = 1;
  718. result = -1;
  719. }
  720. if (result == -1) {
  721. if (PyErr_Occurred()) {
  722. return CPY_LL_UINT_ERROR;
  723. } else if (overflow) {
  724. PyErr_SetString(PyExc_OverflowError, "int too large or small to convert to u8");
  725. return CPY_LL_UINT_ERROR;
  726. }
  727. }
  728. return result;
  729. }
  730. void CPyUInt8_Overflow() {
  731. PyErr_SetString(PyExc_OverflowError, "int too large or small to convert to u8");
  732. }
  733. double CPyTagged_TrueDivide(CPyTagged x, CPyTagged y) {
  734. if (unlikely(y == 0)) {
  735. PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
  736. return CPY_FLOAT_ERROR;
  737. }
  738. if (likely(!CPyTagged_CheckLong(x) && !CPyTagged_CheckLong(y))) {
  739. return (double)((Py_ssize_t)x >> 1) / (double)((Py_ssize_t)y >> 1);
  740. } else {
  741. PyObject *xo = CPyTagged_AsObject(x);
  742. PyObject *yo = CPyTagged_AsObject(y);
  743. PyObject *result = PyNumber_TrueDivide(xo, yo);
  744. if (result == NULL) {
  745. return CPY_FLOAT_ERROR;
  746. }
  747. return PyFloat_AsDouble(result);
  748. }
  749. return 1.0;
  750. }