tpy-lang 0.3.0.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. tpy_lang-0.3.0.dev0.dist-info/METADATA +151 -0
  2. tpy_lang-0.3.0.dev0.dist-info/RECORD +333 -0
  3. tpy_lang-0.3.0.dev0.dist-info/WHEEL +4 -0
  4. tpy_lang-0.3.0.dev0.dist-info/entry_points.txt +3 -0
  5. tpyc/__init__.py +104 -0
  6. tpyc/__main__.py +6 -0
  7. tpyc/_buildinfo.py +1 -0
  8. tpyc/_data/docs/LANGUAGE_FEATURES.md +6278 -0
  9. tpyc/_data/docs/STDLIB_ROADMAP.md +1258 -0
  10. tpyc/_data/docs/TPY_FOR_AGENTS.md +556 -0
  11. tpyc/_data/lib/tpy/_bindings/__init__.py +6 -0
  12. tpyc/_data/lib/tpy/_bindings/pcre2.py +173 -0
  13. tpyc/_data/lib/tpy/_bindings/posix_socket.py +161 -0
  14. tpyc/_data/lib/tpy/_functools_macros.py +80 -0
  15. tpyc/_data/lib/tpy/_macro_helpers.py +161 -0
  16. tpyc/_data/lib/tpy/argparse.py +2062 -0
  17. tpyc/_data/lib/tpy/asyncio/__init__.py +744 -0
  18. tpyc/_data/lib/tpy/asyncio/_executor.py +515 -0
  19. tpyc/_data/lib/tpy/base64.py +410 -0
  20. tpyc/_data/lib/tpy/bisect.py +39 -0
  21. tpyc/_data/lib/tpy/builtins.py +38 -0
  22. tpyc/_data/lib/tpy/dataclasses.py +354 -0
  23. tpyc/_data/lib/tpy/enum.py +23 -0
  24. tpyc/_data/lib/tpy/functools.py +33 -0
  25. tpyc/_data/lib/tpy/hashlib.py +206 -0
  26. tpyc/_data/lib/tpy/heapq.py +118 -0
  27. tpyc/_data/lib/tpy/io.py +395 -0
  28. tpyc/_data/lib/tpy/json.py +221 -0
  29. tpyc/_data/lib/tpy/math.py +406 -0
  30. tpyc/_data/lib/tpy/random.py +597 -0
  31. tpyc/_data/lib/tpy/re.py +467 -0
  32. tpyc/_data/lib/tpy/socket.py +379 -0
  33. tpyc/_data/lib/tpy/struct.py +178 -0
  34. tpyc/_data/lib/tpy/sys.py +40 -0
  35. tpyc/_data/lib/tpy/time.py +39 -0
  36. tpyc/_data/lib/tpy/tpy/__init__.py +78 -0
  37. tpyc/_data/lib/tpy/tpy/_bootstrap/__init__.py +10 -0
  38. tpyc/_data/lib/tpy/tpy/_bootstrap/_decorators.py +37 -0
  39. tpyc/_data/lib/tpy/tpy/_bootstrap/_extern.py +64 -0
  40. tpyc/_data/lib/tpy/tpy/_builtins/__init__.py +11 -0
  41. tpyc/_data/lib/tpy/tpy/_builtins/_bytes.py +378 -0
  42. tpyc/_data/lib/tpy/tpy/_builtins/_dict.py +151 -0
  43. tpyc/_data/lib/tpy/tpy/_builtins/_exceptions.py +125 -0
  44. tpyc/_data/lib/tpy/tpy/_builtins/_funcs.py +681 -0
  45. tpyc/_data/lib/tpy/tpy/_builtins/_io.py +97 -0
  46. tpyc/_data/lib/tpy/tpy/_builtins/_list.py +127 -0
  47. tpyc/_data/lib/tpy/tpy/_builtins/_range.py +52 -0
  48. tpyc/_data/lib/tpy/tpy/_builtins/_set.py +139 -0
  49. tpyc/_data/lib/tpy/tpy/_builtins/_super.py +11 -0
  50. tpyc/_data/lib/tpy/tpy/_builtins/_types.py +661 -0
  51. tpyc/_data/lib/tpy/tpy/_core/__init__.py +23 -0
  52. tpyc/_data/lib/tpy/tpy/_core/_bytes_view.py +129 -0
  53. tpyc/_data/lib/tpy/tpy/_core/_containers.py +137 -0
  54. tpyc/_data/lib/tpy/tpy/_core/_functions.py +40 -0
  55. tpyc/_data/lib/tpy/tpy/_core/_types.py +2061 -0
  56. tpyc/_data/lib/tpy/tpy/_typing/__init__.py +77 -0
  57. tpyc/_data/lib/tpy/tpy/_version.py +29 -0
  58. tpyc/_data/lib/tpy/tpy/bits.py +28 -0
  59. tpyc/_data/lib/tpy/tpy/coro/__init__.py +127 -0
  60. tpyc/_data/lib/tpy/tpy/extern.py +8 -0
  61. tpyc/_data/lib/tpy/tpy/mem.py +49 -0
  62. tpyc/_data/lib/tpy/tpy/unsafe.py +195 -0
  63. tpyc/_data/lib/tpy/tpy/version.py +21 -0
  64. tpyc/_data/lib/tpy/typing.py +13 -0
  65. tpyc/_data/runtime/cpp/include/tpy/any.hpp +461 -0
  66. tpyc/_data/runtime/cpp/include/tpy/as_ostream.hpp +117 -0
  67. tpyc/_data/runtime/cpp/include/tpy/async.hpp +76 -0
  68. tpyc/_data/runtime/cpp/include/tpy/bigint.hpp +1343 -0
  69. tpyc/_data/runtime/cpp/include/tpy/builtins.hpp +400 -0
  70. tpyc/_data/runtime/cpp/include/tpy/bytes_ops.hpp +469 -0
  71. tpyc/_data/runtime/cpp/include/tpy/container_ops.hpp +487 -0
  72. tpyc/_data/runtime/cpp/include/tpy/copy_iter.hpp +82 -0
  73. tpyc/_data/runtime/cpp/include/tpy/core.hpp +558 -0
  74. tpyc/_data/runtime/cpp/include/tpy/dict_ops.hpp +289 -0
  75. tpyc/_data/runtime/cpp/include/tpy/dunder.hpp +750 -0
  76. tpyc/_data/runtime/cpp/include/tpy/dynamic.hpp +44 -0
  77. tpyc/_data/runtime/cpp/include/tpy/enum.hpp +40 -0
  78. tpyc/_data/runtime/cpp/include/tpy/file.hpp +245 -0
  79. tpyc/_data/runtime/cpp/include/tpy/fixed_int.hpp +317 -0
  80. tpyc/_data/runtime/cpp/include/tpy/format.hpp +954 -0
  81. tpyc/_data/runtime/cpp/include/tpy/frame_slot.hpp +120 -0
  82. tpyc/_data/runtime/cpp/include/tpy/generator.hpp +47 -0
  83. tpyc/_data/runtime/cpp/include/tpy/iterable_ops.hpp +122 -0
  84. tpyc/_data/runtime/cpp/include/tpy/itertools.hpp +749 -0
  85. tpyc/_data/runtime/cpp/include/tpy/next_iter.hpp +82 -0
  86. tpyc/_data/runtime/cpp/include/tpy/ordered_map.hpp +518 -0
  87. tpyc/_data/runtime/cpp/include/tpy/ordered_set.hpp +337 -0
  88. tpyc/_data/runtime/cpp/include/tpy/own_iter.hpp +54 -0
  89. tpyc/_data/runtime/cpp/include/tpy/pascal_graph_sdl.hpp +192 -0
  90. tpyc/_data/runtime/cpp/include/tpy/printing.hpp +302 -0
  91. tpyc/_data/runtime/cpp/include/tpy/protocols.hpp +61 -0
  92. tpyc/_data/runtime/cpp/include/tpy/range.hpp +115 -0
  93. tpyc/_data/runtime/cpp/include/tpy/ranges.hpp +212 -0
  94. tpyc/_data/runtime/cpp/include/tpy/set_ops.hpp +265 -0
  95. tpyc/_data/runtime/cpp/include/tpy/slice.hpp +47 -0
  96. tpyc/_data/runtime/cpp/include/tpy/span_iter.hpp +42 -0
  97. tpyc/_data/runtime/cpp/include/tpy/stdlib/math.hpp +41 -0
  98. tpyc/_data/runtime/cpp/include/tpy/stdlib/pcre2_h.hpp +96 -0
  99. tpyc/_data/runtime/cpp/include/tpy/stdlib/random.hpp +25 -0
  100. tpyc/_data/runtime/cpp/include/tpy/stdlib/socket_h.hpp +145 -0
  101. tpyc/_data/runtime/cpp/include/tpy/stdlib/time.hpp +62 -0
  102. tpyc/_data/runtime/cpp/include/tpy/system.hpp +121 -0
  103. tpyc/_data/runtime/cpp/include/tpy/throwable.hpp +55 -0
  104. tpyc/_data/runtime/cpp/include/tpy/tpy.hpp +156 -0
  105. tpyc/_data/runtime/cpp/include/tpy/type_name.hpp +77 -0
  106. tpyc/_data/runtime/cpp/include/tpy/type_traits.hpp +240 -0
  107. tpyc/_data/runtime/cpp/include/tpy/uninit_array_storage.hpp +250 -0
  108. tpyc/_data/runtime/cpp/include/tpy/uninit_heap_storage.hpp +277 -0
  109. tpyc/_data/runtime/cpp/include/tpy/varargs.hpp +174 -0
  110. tpyc/_data/runtime/cpp/include/tpy/variant_ref.hpp +118 -0
  111. tpyc/_data/runtime/cpp/src/stdlib/socket_impl.cpp +104 -0
  112. tpyc/_data/runtime/cpp/third_party/README.md +58 -0
  113. tpyc/_data/runtime/cpp/third_party/pcre2/AUTHORS +36 -0
  114. tpyc/_data/runtime/cpp/third_party/pcre2/CMakeLists.txt +1233 -0
  115. tpyc/_data/runtime/cpp/third_party/pcre2/COPYING +5 -0
  116. tpyc/_data/runtime/cpp/third_party/pcre2/ChangeLog +3097 -0
  117. tpyc/_data/runtime/cpp/third_party/pcre2/HACKING +853 -0
  118. tpyc/_data/runtime/cpp/third_party/pcre2/INSTALL +368 -0
  119. tpyc/_data/runtime/cpp/third_party/pcre2/LICENCE +94 -0
  120. tpyc/_data/runtime/cpp/third_party/pcre2/NEWS +492 -0
  121. tpyc/_data/runtime/cpp/third_party/pcre2/NON-AUTOTOOLS-BUILD +430 -0
  122. tpyc/_data/runtime/cpp/third_party/pcre2/README +956 -0
  123. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/COPYING-CMAKE-SCRIPTS +22 -0
  124. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindEditline.cmake +16 -0
  125. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindPackageHandleStandardArgs.cmake +58 -0
  126. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindReadline.cmake +29 -0
  127. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config-version.cmake.in +15 -0
  128. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config.cmake.in +148 -0
  129. tpyc/_data/runtime/cpp/third_party/pcre2/config-cmake.h.in +56 -0
  130. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-16.pc.in +13 -0
  131. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-32.pc.in +13 -0
  132. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-8.pc.in +13 -0
  133. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-posix.pc.in +13 -0
  134. tpyc/_data/runtime/cpp/third_party/pcre2/pcre2-config.in +121 -0
  135. tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h +483 -0
  136. tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.generic +483 -0
  137. tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.in +460 -0
  138. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h +1010 -0
  139. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.generic +1010 -0
  140. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.in +1010 -0
  141. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_auto_possess.c +1371 -0
  142. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c +196 -0
  143. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c.dist +196 -0
  144. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chkdint.c +96 -0
  145. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_compile.c +11001 -0
  146. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_config.c +252 -0
  147. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_context.c +510 -0
  148. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_convert.c +1189 -0
  149. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dfa_match.c +4119 -0
  150. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dftables.c +297 -0
  151. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_error.c +345 -0
  152. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_extuni.c +162 -0
  153. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_find_bracket.c +219 -0
  154. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_fuzzsupport.c +792 -0
  155. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_internal.h +2084 -0
  156. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_intmodedep.h +940 -0
  157. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_compile.c +14972 -0
  158. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_match.c +200 -0
  159. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_misc.c +234 -0
  160. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_neon_inc.h +354 -0
  161. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_simd_inc.h +2355 -0
  162. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_test.c +2528 -0
  163. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_maketables.c +165 -0
  164. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match.c +7777 -0
  165. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match_data.c +185 -0
  166. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_newline.c +243 -0
  167. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ord2utf.c +120 -0
  168. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_pattern_info.c +432 -0
  169. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_printint.c +886 -0
  170. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_script_run.c +344 -0
  171. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_serialize.c +286 -0
  172. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_string_utils.c +237 -0
  173. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_study.c +1915 -0
  174. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substitute.c +1009 -0
  175. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substring.c +550 -0
  176. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_tables.c +234 -0
  177. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucd.c +5460 -0
  178. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucp.h +396 -0
  179. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucptables.c +1533 -0
  180. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_valid_utf.c +398 -0
  181. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_xclass.c +308 -0
  182. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2demo.c +497 -0
  183. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2grep.c +4606 -0
  184. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.c +425 -0
  185. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.h +187 -0
  186. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix_test.c +209 -0
  187. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2test.c +9708 -0
  188. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c +137 -0
  189. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorCore.c +327 -0
  190. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorFreeBSD.c +89 -0
  191. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorPosix.c +62 -0
  192. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorWindows.c +40 -0
  193. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorNetBSD.c +72 -0
  194. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorPosix.c +172 -0
  195. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorPosix.c +141 -0
  196. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorWindows.c +102 -0
  197. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfig.h +142 -0
  198. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigCPU.h +188 -0
  199. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigInternal.h +907 -0
  200. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.c +3561 -0
  201. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.h +2466 -0
  202. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_32.c +4636 -0
  203. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_64.c +3491 -0
  204. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_T2_32.c +4302 -0
  205. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeLOONGARCH_64.c +3765 -0
  206. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_32.c +472 -0
  207. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_64.c +387 -0
  208. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_common.c +4259 -0
  209. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_32.c +485 -0
  210. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_64.c +719 -0
  211. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_common.c +3161 -0
  212. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_32.c +142 -0
  213. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_64.c +222 -0
  214. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_common.c +3121 -0
  215. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeS390X.c +4526 -0
  216. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_32.c +1685 -0
  217. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_64.c +1398 -0
  218. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_common.c +5001 -0
  219. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitSerialize.c +516 -0
  220. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitUtils.c +344 -0
  221. tpyc/_data/runtime/cpp/third_party/pcre2.sources.txt +54 -0
  222. tpyc/_data/runtime/cpp/third_party/pcre2.vendor.json +7 -0
  223. tpyc/build/__init__.py +7 -0
  224. tpyc/build/pcre2.py +122 -0
  225. tpyc/build/third_party.py +413 -0
  226. tpyc/cli.py +822 -0
  227. tpyc/codegen_cpp/__init__.py +18 -0
  228. tpyc/codegen_cpp/builtins.py +484 -0
  229. tpyc/codegen_cpp/context.py +2064 -0
  230. tpyc/codegen_cpp/expressions.py +5940 -0
  231. tpyc/codegen_cpp/functions.py +1913 -0
  232. tpyc/codegen_cpp/gen_async.py +3258 -0
  233. tpyc/codegen_cpp/gen_generators.py +657 -0
  234. tpyc/codegen_cpp/generator.py +2258 -0
  235. tpyc/codegen_cpp/match.py +1997 -0
  236. tpyc/codegen_cpp/param_const.py +172 -0
  237. tpyc/codegen_cpp/protocols.py +907 -0
  238. tpyc/codegen_cpp/records.py +1654 -0
  239. tpyc/codegen_cpp/resumable_cfg.py +1651 -0
  240. tpyc/codegen_cpp/statements.py +4963 -0
  241. tpyc/codegen_cpp/string_dispatch.py +76 -0
  242. tpyc/codegen_cpp/test_context.py +46 -0
  243. tpyc/codegen_cpp/test_param_const.py +113 -0
  244. tpyc/codegen_cpp/test_resumable_cfg.py +182 -0
  245. tpyc/codegen_cpp/type_resolution.py +53 -0
  246. tpyc/codegen_cpp/types.py +436 -0
  247. tpyc/codegen_cpp/variant_access.py +135 -0
  248. tpyc/coercions.py +749 -0
  249. tpyc/compilation_context.py +57 -0
  250. tpyc/compiler.py +3945 -0
  251. tpyc/cycle_detection.py +358 -0
  252. tpyc/diagnostics.py +135 -0
  253. tpyc/dump_types.py +353 -0
  254. tpyc/frontend_diagnostics.py +47 -0
  255. tpyc/frontend_ir/__init__.py +140 -0
  256. tpyc/frontend_ir/lower.py +1098 -0
  257. tpyc/frontend_ir/nodes.py +718 -0
  258. tpyc/frontend_ir/resolver_adapter.py +151 -0
  259. tpyc/frontend_plugin.py +209 -0
  260. tpyc/install_docs.py +81 -0
  261. tpyc/liveness.py +756 -0
  262. tpyc/macro_api.py +1724 -0
  263. tpyc/macro_loader.py +497 -0
  264. tpyc/module_names.py +64 -0
  265. tpyc/modules/__init__.py +31 -0
  266. tpyc/modules/defs.py +89 -0
  267. tpyc/modules/registry.py +36 -0
  268. tpyc/modules/resolver.py +192 -0
  269. tpyc/modules/type_resolution.py +629 -0
  270. tpyc/namespace.py +172 -0
  271. tpyc/parse/__init__.py +84 -0
  272. tpyc/parse/imports.py +490 -0
  273. tpyc/parse/nodes.py +1732 -0
  274. tpyc/parse/parser.py +4043 -0
  275. tpyc/parse/resolve_refs.py +466 -0
  276. tpyc/parse/type_resolver.py +1060 -0
  277. tpyc/prescan.py +254 -0
  278. tpyc/qnames.py +149 -0
  279. tpyc/repl.py +529 -0
  280. tpyc/repl_backends.py +848 -0
  281. tpyc/sema/__init__.py +21 -0
  282. tpyc/sema/analyzer.py +3625 -0
  283. tpyc/sema/bound_check.py +72 -0
  284. tpyc/sema/builder_trace.py +684 -0
  285. tpyc/sema/calls.py +5406 -0
  286. tpyc/sema/compatibility.py +2107 -0
  287. tpyc/sema/context.py +1243 -0
  288. tpyc/sema/expressions.py +3737 -0
  289. tpyc/sema/flow_facts.py +199 -0
  290. tpyc/sema/init_tracker.py +150 -0
  291. tpyc/sema/list_literals.py +69 -0
  292. tpyc/sema/literal_utils.py +27 -0
  293. tpyc/sema/local_deduction.py +1088 -0
  294. tpyc/sema/macros.py +179 -0
  295. tpyc/sema/match.py +1177 -0
  296. tpyc/sema/method_expansion.py +347 -0
  297. tpyc/sema/methods.py +2197 -0
  298. tpyc/sema/mutation_propagation.py +268 -0
  299. tpyc/sema/narrowing.py +857 -0
  300. tpyc/sema/numeric_lattice.py +160 -0
  301. tpyc/sema/operators.py +402 -0
  302. tpyc/sema/overloads.py +841 -0
  303. tpyc/sema/protocols.py +1209 -0
  304. tpyc/sema/reach_analysis.py +202 -0
  305. tpyc/sema/registration.py +3156 -0
  306. tpyc/sema/scope_tracker.py +193 -0
  307. tpyc/sema/statements.py +4426 -0
  308. tpyc/sema/type_ops.py +1879 -0
  309. tpyc/sema/value_range.py +181 -0
  310. tpyc/symbol_binding.py +259 -0
  311. tpyc/test_c3_mro.py +208 -0
  312. tpyc/test_cli_argv.py +52 -0
  313. tpyc/test_compiler.py +559 -0
  314. tpyc/test_contains_type_param.py +101 -0
  315. tpyc/test_cycle_detection.py +221 -0
  316. tpyc/test_dump_types.py +225 -0
  317. tpyc/test_install_docs.py +65 -0
  318. tpyc/test_local_cpp_form.py +135 -0
  319. tpyc/test_macro_loader.py +76 -0
  320. tpyc/test_method_expansion.py +254 -0
  321. tpyc/test_nominal_identity.py +182 -0
  322. tpyc/test_overloads.py +410 -0
  323. tpyc/test_parse.py +303 -0
  324. tpyc/test_parse_type_ref.py +506 -0
  325. tpyc/test_parse_version_info.py +58 -0
  326. tpyc/test_reach_analysis.py +72 -0
  327. tpyc/test_ref_type.py +216 -0
  328. tpyc/test_send_sync_substitution.py +276 -0
  329. tpyc/test_tuple_mutation_propagation.py +206 -0
  330. tpyc/test_type_def_registry.py +1729 -0
  331. tpyc/test_union_types.py +195 -0
  332. tpyc/type_def_registry.py +975 -0
  333. tpyc/typesys.py +5104 -0
@@ -0,0 +1,1343 @@
1
+ /**
2
+ * TurboPython Runtime - BigInt
3
+ *
4
+ * Arbitrary precision integer with small-int optimization.
5
+ * Uses pointer tagging to store small integers inline.
6
+ *
7
+ * TODO(perf):
8
+ * - Reduce big-path temporary allocations by adding in-place limb operations
9
+ * and reusable scratch buffers for add/sub/mul/div flows.
10
+ * - Replace shift/subtract long division with a faster normalized long division
11
+ * algorithm (and optional Burnikel-Ziegler for very large operands).
12
+ * - Avoid full two's-complement materialization for bitwise ops when possible.
13
+ * - Replace to_double() decimal-string roundtrip with direct binary conversion.
14
+ * - Add architecture-specific kernels (e.g. BMI2/ADX intrinsics) behind a
15
+ * clean abstraction; keep scalar path as baseline.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <bit>
21
+ #include <cctype>
22
+ #include <charconv>
23
+ #include <cmath>
24
+ #include <cstddef>
25
+ #include <cstdint>
26
+ #include <cstdlib>
27
+ #include <functional>
28
+ #include <iomanip>
29
+ #include <limits>
30
+ #include <ostream>
31
+ #include <string>
32
+ #include <string_view>
33
+ #include <tuple>
34
+ #include <type_traits>
35
+ #include <utility>
36
+ #include <vector>
37
+
38
+ #include "core.hpp"
39
+ #include "fixed_int.hpp"
40
+ #include "type_traits.hpp"
41
+
42
+ namespace tpy {
43
+
44
+ /**
45
+ * BigInt - Arbitrary precision integer with small-int optimization.
46
+ *
47
+ * raw_ layout:
48
+ * - raw_ & 1 == 0: small value (int63) stored as (value << 1)
49
+ * - raw_ & 1 == 1: tagged pointer to HeapBig
50
+ *
51
+ * Python semantics for division and modulo (floor division).
52
+ */
53
+ class BigInt {
54
+ public:
55
+ BigInt() noexcept : raw_(0) {}
56
+
57
+ BigInt(int32_t v) noexcept : BigInt(static_cast<int64_t>(v)) {}
58
+
59
+ BigInt(int64_t v) noexcept {
60
+ if (fits_small(v)) {
61
+ raw_ = encode_small(v);
62
+ return;
63
+ }
64
+ auto* p = alloc_heap(1);
65
+ p->len = 1;
66
+ p->sign = (v < 0) ? -1 : 1;
67
+ p->limbs[0] = abs_u64(v);
68
+ raw_ = encode_big(p);
69
+ }
70
+
71
+ BigInt(uint64_t v) noexcept {
72
+ if (v <= static_cast<uint64_t>(SMALL_MAX)) {
73
+ raw_ = encode_small(static_cast<int64_t>(v));
74
+ return;
75
+ }
76
+ auto* p = alloc_heap(1);
77
+ p->len = 1;
78
+ p->sign = 1;
79
+ p->limbs[0] = v;
80
+ raw_ = encode_big(p);
81
+ }
82
+
83
+ BigInt(const BigInt& other) noexcept {
84
+ if (other.is_small()) {
85
+ raw_ = other.raw_;
86
+ return;
87
+ }
88
+ raw_ = encode_big(clone_heap(other.heap_ptr()));
89
+ }
90
+
91
+ BigInt(BigInt&& other) noexcept : raw_(other.raw_) {
92
+ other.raw_ = 0;
93
+ }
94
+
95
+ ~BigInt() {
96
+ if (!is_small()) {
97
+ free_heap(heap_ptr());
98
+ }
99
+ }
100
+
101
+ BigInt& operator=(const BigInt& other) noexcept {
102
+ if (this == &other) {
103
+ return *this;
104
+ }
105
+ if (!is_small()) {
106
+ free_heap(heap_ptr());
107
+ }
108
+ if (other.is_small()) {
109
+ raw_ = other.raw_;
110
+ } else {
111
+ raw_ = encode_big(clone_heap(other.heap_ptr()));
112
+ }
113
+ return *this;
114
+ }
115
+
116
+ BigInt& operator=(BigInt&& other) noexcept {
117
+ if (this == &other) {
118
+ return *this;
119
+ }
120
+ if (!is_small()) {
121
+ free_heap(heap_ptr());
122
+ }
123
+ raw_ = other.raw_;
124
+ other.raw_ = 0;
125
+ return *this;
126
+ }
127
+
128
+ bool is_small() const noexcept { return (raw_ & TAG_MASK) == 0; }
129
+
130
+ int64_t small_value() const noexcept {
131
+ return static_cast<int64_t>(raw_) >> 1;
132
+ }
133
+
134
+ // Arithmetic operators
135
+ BigInt operator+(const BigInt& rhs) const {
136
+ if (is_small() && rhs.is_small()) {
137
+ int64_t a = small_value();
138
+ int64_t b = rhs.small_value();
139
+ int64_t result;
140
+ if (!__builtin_add_overflow(a, b, &result) && fits_small(result)) {
141
+ return make_small(result);
142
+ }
143
+ }
144
+
145
+ const int a_sign = signum();
146
+ const int b_sign = rhs.signum();
147
+ if (a_sign == 0) return rhs;
148
+ if (b_sign == 0) return *this;
149
+
150
+ std::vector<uint64_t> a = abs_limbs();
151
+ std::vector<uint64_t> b = rhs.abs_limbs();
152
+
153
+ if (a_sign == b_sign) {
154
+ return from_sign_mag(a_sign, add_mag(a, b));
155
+ }
156
+
157
+ int cmp = cmp_mag(a, b);
158
+ if (cmp == 0) {
159
+ return BigInt(0);
160
+ }
161
+ if (cmp > 0) {
162
+ return from_sign_mag(a_sign, sub_mag(a, b));
163
+ }
164
+ return from_sign_mag(b_sign, sub_mag(b, a));
165
+ }
166
+
167
+ BigInt operator-(const BigInt& rhs) const {
168
+ if (is_small() && rhs.is_small()) {
169
+ int64_t a = small_value();
170
+ int64_t b = rhs.small_value();
171
+ int64_t result;
172
+ if (!__builtin_sub_overflow(a, b, &result) && fits_small(result)) {
173
+ return make_small(result);
174
+ }
175
+ }
176
+ return *this + (-rhs);
177
+ }
178
+
179
+ BigInt operator*(const BigInt& rhs) const {
180
+ if (is_small() && rhs.is_small()) {
181
+ int64_t a = small_value();
182
+ int64_t b = rhs.small_value();
183
+ int64_t result;
184
+ if (!__builtin_mul_overflow(a, b, &result) && fits_small(result)) {
185
+ return make_small(result);
186
+ }
187
+ }
188
+
189
+ const int a_sign = signum();
190
+ const int b_sign = rhs.signum();
191
+ if (a_sign == 0 || b_sign == 0) return BigInt(0);
192
+
193
+ std::vector<uint64_t> a = abs_limbs();
194
+ std::vector<uint64_t> b = rhs.abs_limbs();
195
+ std::vector<uint64_t> prod = mul_mag(a, b);
196
+ return from_sign_mag(a_sign == b_sign ? 1 : -1, std::move(prod));
197
+ }
198
+
199
+ BigInt operator/(const BigInt& rhs) const {
200
+ return floor_div(rhs);
201
+ }
202
+
203
+ BigInt operator%(const BigInt& rhs) const {
204
+ return floor_mod(rhs);
205
+ }
206
+
207
+ BigInt operator-() const {
208
+ if (is_small()) {
209
+ int64_t v = small_value();
210
+ if (v != INT64_MIN && fits_small(-v)) {
211
+ return make_small(-v);
212
+ }
213
+ }
214
+ const int s = signum();
215
+ if (s == 0) {
216
+ return BigInt(0);
217
+ }
218
+ return from_sign_mag(-s, abs_limbs());
219
+ }
220
+
221
+ // Compound assignment operators
222
+ BigInt& operator+=(const BigInt& rhs) { *this = *this + rhs; return *this; }
223
+ BigInt& operator-=(const BigInt& rhs) { *this = *this - rhs; return *this; }
224
+ BigInt& operator*=(const BigInt& rhs) { *this = *this * rhs; return *this; }
225
+ BigInt& operator/=(const BigInt& rhs) { *this = *this / rhs; return *this; }
226
+ BigInt& operator%=(const BigInt& rhs) { *this = *this % rhs; return *this; }
227
+
228
+ // Increment/decrement operators
229
+ BigInt& operator++() { *this += BigInt(1); return *this; }
230
+ BigInt operator++(int) { BigInt tmp = *this; ++(*this); return tmp; }
231
+ BigInt& operator--() { *this -= BigInt(1); return *this; }
232
+ BigInt operator--(int) { BigInt tmp = *this; --(*this); return tmp; }
233
+
234
+ // Shift operators (Python semantics: arbitrary precision)
235
+ BigInt operator<<(int32_t shift) const {
236
+ if (shift < 0) {
237
+ raise_value_error("negative shift count");
238
+ }
239
+ if (shift == 0 || signum() == 0) {
240
+ return *this;
241
+ }
242
+ std::vector<uint64_t> mag = abs_limbs();
243
+ return from_sign_mag(signum(), lshift_mag(mag, static_cast<size_t>(shift)));
244
+ }
245
+
246
+ BigInt operator>>(int32_t shift) const {
247
+ if (shift < 0) {
248
+ raise_value_error("negative shift count");
249
+ }
250
+ if (shift == 0 || signum() == 0) {
251
+ return *this;
252
+ }
253
+ BigInt divisor = BigInt(1) << shift;
254
+ return floor_div(divisor);
255
+ }
256
+
257
+ BigInt& operator<<=(int32_t shift) { *this = *this << shift; return *this; }
258
+ BigInt& operator>>=(int32_t shift) { *this = *this >> shift; return *this; }
259
+
260
+ // BigInt overloads for shift (convert to int32)
261
+ BigInt operator<<(const BigInt& shift) const { return *this << shift.to_fixed_check<int32_t>(); }
262
+ BigInt operator>>(const BigInt& shift) const { return *this >> shift.to_fixed_check<int32_t>(); }
263
+
264
+ // Bitwise operators
265
+ BigInt operator&(const BigInt& rhs) const {
266
+ return bitwise_binary(rhs, '&');
267
+ }
268
+
269
+ BigInt operator|(const BigInt& rhs) const {
270
+ return bitwise_binary(rhs, '|');
271
+ }
272
+
273
+ BigInt operator^(const BigInt& rhs) const {
274
+ return bitwise_binary(rhs, '^');
275
+ }
276
+
277
+ BigInt operator~() const {
278
+ // Python: ~x = -(x+1)
279
+ return -(*this + BigInt(1));
280
+ }
281
+
282
+ BigInt& operator&=(const BigInt& rhs) { *this = *this & rhs; return *this; }
283
+ BigInt& operator|=(const BigInt& rhs) { *this = *this | rhs; return *this; }
284
+ BigInt& operator^=(const BigInt& rhs) { *this = *this ^ rhs; return *this; }
285
+
286
+ // Power operator (Python semantics: negative exponent not supported)
287
+ BigInt pow(const BigInt& exp) const {
288
+ if (exp.signum() < 0) {
289
+ // TPy-specific limitation: int**neg returns float in CPython, but
290
+ // our return type is BigInt. Stays panic -- a sema/codegen fix
291
+ // would dispatch to a float-pow helper instead of routing the
292
+ // panic through any catchable type.
293
+ tpy_panic("Negative exponent not supported (would require float)");
294
+ }
295
+
296
+ uint64_t e = 0;
297
+ if (!exp.to_uint64_checked(e)) {
298
+ raise_overflow_error("exponent too large");
299
+ }
300
+
301
+ BigInt base = *this;
302
+ BigInt result(1);
303
+ while (e != 0) {
304
+ if ((e & 1U) != 0) {
305
+ result *= base;
306
+ }
307
+ e >>= 1U;
308
+ if (e != 0) {
309
+ base *= base;
310
+ }
311
+ }
312
+ return result;
313
+ }
314
+
315
+ // Comparison operators
316
+ bool operator==(const BigInt& rhs) const {
317
+ if (is_small() && rhs.is_small()) {
318
+ return raw_ == rhs.raw_;
319
+ }
320
+ return compare(rhs) == 0;
321
+ }
322
+
323
+ bool operator!=(const BigInt& rhs) const { return !(*this == rhs); }
324
+
325
+ bool operator<(const BigInt& rhs) const { return compare(rhs) < 0; }
326
+ bool operator<=(const BigInt& rhs) const { return compare(rhs) <= 0; }
327
+ bool operator>(const BigInt& rhs) const { return compare(rhs) > 0; }
328
+ bool operator>=(const BigInt& rhs) const { return compare(rhs) >= 0; }
329
+
330
+ // Generic conversion to any fixed-width integer type
331
+ template<typename T>
332
+ T to_fixed_check() const {
333
+ static_assert(std::is_integral_v<T>, "T must be an integer type");
334
+
335
+ if (is_small()) {
336
+ int64_t v = small_value();
337
+ if constexpr (std::is_signed_v<T>) {
338
+ if (v >= static_cast<int64_t>(std::numeric_limits<T>::min()) &&
339
+ v <= static_cast<int64_t>(std::numeric_limits<T>::max())) {
340
+ return static_cast<T>(v);
341
+ }
342
+ } else {
343
+ if (v >= 0 && static_cast<uint64_t>(v) <= static_cast<uint64_t>(std::numeric_limits<T>::max())) {
344
+ return static_cast<T>(v);
345
+ }
346
+ }
347
+ raise_fixedint_overflow("{} overflow: value out of range",
348
+ tpy::fixed_int_name<T>());
349
+ }
350
+
351
+ const HeapBig* p = heap_ptr();
352
+ if (p->len > 1) {
353
+ raise_fixedint_overflow("{} overflow: value out of range",
354
+ tpy::fixed_int_name<T>());
355
+ }
356
+
357
+ uint64_t mag = (p->len == 0) ? 0 : p->limbs[0];
358
+ if constexpr (std::is_signed_v<T>) {
359
+ __int128 value = (p->sign < 0)
360
+ ? -static_cast<__int128>(mag)
361
+ : static_cast<__int128>(mag);
362
+ __int128 min_v = static_cast<__int128>(std::numeric_limits<T>::min());
363
+ __int128 max_v = static_cast<__int128>(std::numeric_limits<T>::max());
364
+ if (value >= min_v && value <= max_v) {
365
+ return static_cast<T>(value);
366
+ }
367
+ } else {
368
+ if (p->sign >= 0 && mag <= static_cast<uint64_t>(std::numeric_limits<T>::max())) {
369
+ return static_cast<T>(mag);
370
+ }
371
+ }
372
+
373
+ raise_fixedint_overflow("{} overflow: value out of range",
374
+ tpy::fixed_int_name<T>());
375
+ }
376
+
377
+ // Truncating conversion to any fixed-width integer type (modular reduction, never panics)
378
+ template<typename T>
379
+ T to_fixed_trunc() const {
380
+ static_assert(std::is_integral_v<T>, "T must be an integer type");
381
+ constexpr int bits = static_cast<int>(sizeof(T) * 8);
382
+
383
+ uint64_t low = 0;
384
+ if (is_small()) {
385
+ low = static_cast<uint64_t>(small_value());
386
+ return static_cast<T>(low);
387
+ }
388
+
389
+ const HeapBig* p = heap_ptr();
390
+ uint64_t mag_mod = 0;
391
+ if (p->len != 0) {
392
+ mag_mod = p->limbs[0];
393
+ }
394
+
395
+ if constexpr (bits < 64) {
396
+ uint64_t mask = (uint64_t(1) << bits) - 1;
397
+ mag_mod &= mask;
398
+ if (p->sign < 0) {
399
+ low = (uint64_t(0) - mag_mod) & mask;
400
+ } else {
401
+ low = mag_mod;
402
+ }
403
+ } else {
404
+ if (p->sign < 0) {
405
+ low = uint64_t(0) - mag_mod;
406
+ } else {
407
+ low = mag_mod;
408
+ }
409
+ }
410
+
411
+ return static_cast<T>(low);
412
+ }
413
+
414
+ // Conversion to double (for float operations)
415
+ double to_double() const {
416
+ if (is_small()) {
417
+ return static_cast<double>(small_value());
418
+ }
419
+ std::string s = to_string();
420
+ return std::strtod(s.c_str(), nullptr);
421
+ }
422
+
423
+ // Explicit conversion operator for static_cast<double>
424
+ explicit operator double() const {
425
+ return to_double();
426
+ }
427
+
428
+ // String conversion for printing
429
+ std::string to_string() const {
430
+ if (is_small()) {
431
+ return std::to_string(small_value());
432
+ }
433
+
434
+ const HeapBig* p = heap_ptr();
435
+ if (p->len == 0) {
436
+ return "0";
437
+ }
438
+
439
+ std::vector<uint64_t> tmp(p->limbs, p->limbs + p->len);
440
+ std::vector<uint32_t> chunks;
441
+ chunks.reserve((p->len * 64) / 29 + 2);
442
+
443
+ while (!tmp.empty()) {
444
+ uint32_t rem = div_small_inplace(tmp, 1000000000U);
445
+ chunks.push_back(rem);
446
+ }
447
+
448
+ std::string out;
449
+ if (p->sign < 0) {
450
+ out.push_back('-');
451
+ }
452
+
453
+ out += std::to_string(chunks.back());
454
+ for (size_t i = chunks.size(); i > 1; --i) {
455
+ size_t idx = i - 2;
456
+ out += pad9(chunks[idx]);
457
+ }
458
+ return out;
459
+ }
460
+
461
+ // Binary string (e.g. "0b101", "-0b11")
462
+ std::string to_bin_string() const {
463
+ int s = signum();
464
+ if (s == 0) return "0b0";
465
+ std::vector<uint64_t> limbs = abs_limbs();
466
+ std::string digits;
467
+ // Extract bits from least significant to most significant
468
+ for (size_t i = 0; i < limbs.size(); ++i) {
469
+ uint64_t w = limbs[i];
470
+ for (int b = 0; b < 64; ++b) {
471
+ digits.push_back('0' + static_cast<char>(w & 1));
472
+ w >>= 1;
473
+ }
474
+ }
475
+ // Trim trailing zeros (they're leading zeros in reversed form)
476
+ while (!digits.empty() && digits.back() == '0') digits.pop_back();
477
+ std::string result;
478
+ if (s < 0) result += '-';
479
+ result += "0b";
480
+ for (auto it = digits.rbegin(); it != digits.rend(); ++it) result += *it;
481
+ return result;
482
+ }
483
+
484
+ // Hex string (e.g. "0xff", "-0x1a")
485
+ std::string to_hex_string() const {
486
+ int s = signum();
487
+ if (s == 0) return "0x0";
488
+ std::vector<uint64_t> limbs = abs_limbs();
489
+ std::string result;
490
+ if (s < 0) result += '-';
491
+ result += "0x";
492
+ char buf[16];
493
+ // Most significant limb without leading zeros
494
+ auto [p1, e1] = std::to_chars(buf, buf + sizeof(buf), limbs.back(), 16);
495
+ result.append(buf, p1);
496
+ // Remaining limbs zero-padded to 16 hex digits
497
+ for (size_t i = limbs.size() - 1; i > 0; --i) {
498
+ auto [p, e] = std::to_chars(buf, buf + sizeof(buf), limbs[i - 1], 16);
499
+ size_t len = static_cast<size_t>(p - buf);
500
+ result.append(16 - len, '0');
501
+ result.append(buf, p);
502
+ }
503
+ return result;
504
+ }
505
+
506
+ // Octal string (e.g. "0o17", "-0o77")
507
+ std::string to_oct_string() const {
508
+ int s = signum();
509
+ if (s == 0) return "0o0";
510
+ std::vector<uint64_t> limbs = abs_limbs();
511
+ size_t total_bits = (limbs.size() - 1) * 64 +
512
+ (64 - static_cast<size_t>(std::countl_zero(limbs.back())));
513
+ std::string digits;
514
+ // Extract 3-bit groups across limb boundaries
515
+ for (size_t bit = 0; bit < total_bits; bit += 3) {
516
+ unsigned val = 0;
517
+ for (int k = 0; k < 3; ++k) {
518
+ size_t pos = bit + static_cast<size_t>(k);
519
+ if (pos < total_bits) {
520
+ size_t limb_idx = pos / 64;
521
+ int bit_idx = static_cast<int>(pos % 64);
522
+ if ((limbs[limb_idx] >> bit_idx) & 1) {
523
+ val |= (1u << k);
524
+ }
525
+ }
526
+ }
527
+ digits.push_back('0' + static_cast<char>(val));
528
+ }
529
+ // Trim trailing zeros
530
+ while (!digits.empty() && digits.back() == '0') digits.pop_back();
531
+ std::string result;
532
+ if (s < 0) result += '-';
533
+ result += "0o";
534
+ for (auto it = digits.rbegin(); it != digits.rend(); ++it) result += *it;
535
+ return result;
536
+ }
537
+
538
+ // Absolute value (static method)
539
+ static BigInt abs(const BigInt& x) {
540
+ return x < BigInt(0) ? -x : x;
541
+ }
542
+
543
+ // Check if value is zero (useful for conditionals)
544
+ explicit operator bool() const {
545
+ return signum() != 0;
546
+ }
547
+
548
+ uint64_t hash() const noexcept {
549
+ if (is_small()) {
550
+ return std::hash<int64_t>{}(small_value());
551
+ }
552
+ const HeapBig* p = heap_ptr();
553
+ uint64_t h = 0;
554
+ h ^= std::hash<int8_t>{}(p->sign) + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2);
555
+ for (uint32_t i = 0; i < p->len; ++i) {
556
+ h ^= std::hash<uint64_t>{}(p->limbs[i]) + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2);
557
+ }
558
+ return h;
559
+ }
560
+
561
+ // Static factory methods for conversions
562
+ static BigInt from_float(double v) {
563
+ if (std::isnan(v)) {
564
+ raise_value_error("cannot convert float NaN to integer");
565
+ }
566
+ if (std::isinf(v)) {
567
+ raise_overflow_error("cannot convert float infinity to integer");
568
+ }
569
+ if (v == 0.0) {
570
+ return BigInt(0);
571
+ }
572
+
573
+ bool negative = v < 0.0;
574
+ double av = negative ? -v : v;
575
+
576
+ uint64_t bits = std::bit_cast<uint64_t>(av);
577
+ uint64_t exp_bits = (bits >> 52) & 0x7FFU;
578
+ uint64_t frac = bits & ((uint64_t(1) << 52) - 1);
579
+
580
+ // Subnormal (and |v| < 1) truncates to 0.
581
+ if (exp_bits == 0) {
582
+ return BigInt(0);
583
+ }
584
+
585
+ int exp = static_cast<int>(exp_bits) - 1023;
586
+ if (exp < 0) {
587
+ return BigInt(0);
588
+ }
589
+
590
+ uint64_t mantissa = frac | (uint64_t(1) << 52);
591
+ std::vector<uint64_t> mag;
592
+
593
+ if (exp >= 52) {
594
+ mag.push_back(mantissa);
595
+ mag = lshift_mag(mag, static_cast<size_t>(exp - 52));
596
+ } else {
597
+ uint64_t truncated = mantissa >> static_cast<unsigned>(52 - exp);
598
+ if (truncated != 0) {
599
+ mag.push_back(truncated);
600
+ }
601
+ }
602
+
603
+ return from_sign_mag(negative ? -1 : 1, std::move(mag));
604
+ }
605
+
606
+ static BigInt from_floor(double v) { return from_float(std::floor(v)); }
607
+ static BigInt from_ceil(double v) { return from_float(std::ceil(v)); }
608
+
609
+ static BigInt from_str(std::string_view s) {
610
+ // Skip leading whitespace.
611
+ size_t start = 0;
612
+ while (start < s.size() && std::isspace(static_cast<unsigned char>(s[start]))) {
613
+ ++start;
614
+ }
615
+ // Skip trailing whitespace.
616
+ size_t end = s.size();
617
+ while (end > start && std::isspace(static_cast<unsigned char>(s[end - 1]))) {
618
+ --end;
619
+ }
620
+ if (start >= end) {
621
+ raise_value_error("invalid literal for int() with base 10: '{}'", s);
622
+ }
623
+
624
+ std::string_view trimmed = s.substr(start, end - start);
625
+
626
+ bool negative = false;
627
+ size_t idx = 0;
628
+ if (trimmed[0] == '-') {
629
+ negative = true;
630
+ ++idx;
631
+ } else if (trimmed[0] == '+') {
632
+ ++idx;
633
+ }
634
+
635
+ if (idx >= trimmed.size()) {
636
+ raise_value_error("invalid literal for int() with base 10: '{}'", s);
637
+ }
638
+
639
+ std::vector<uint64_t> mag;
640
+ for (size_t i = idx; i < trimmed.size(); ++i) {
641
+ unsigned char ch = static_cast<unsigned char>(trimmed[i]);
642
+ if (!std::isdigit(ch)) {
643
+ raise_value_error("invalid literal for int() with base 10: '{}'", s);
644
+ }
645
+ mul_small_inplace(mag, 10);
646
+ add_small_inplace(mag, static_cast<uint32_t>(ch - '0'));
647
+ }
648
+
649
+ return from_sign_mag(negative ? -1 : 1, std::move(mag));
650
+ }
651
+
652
+ std::tuple<BigInt, BigInt> floor_divmod(const BigInt& rhs) const {
653
+ if (rhs.signum() == 0) {
654
+ raise_zero_division_error("integer division or modulo by zero");
655
+ }
656
+ if (signum() == 0) {
657
+ return {BigInt(0), BigInt(0)};
658
+ }
659
+
660
+ int a_sign = signum();
661
+ int b_sign = rhs.signum();
662
+ std::vector<uint64_t> a = abs_limbs();
663
+ std::vector<uint64_t> b = rhs.abs_limbs();
664
+
665
+ std::vector<uint64_t> q_abs;
666
+ std::vector<uint64_t> r_abs;
667
+ divmod_mag(a, b, q_abs, r_abs);
668
+
669
+ if (r_abs.empty()) {
670
+ int q_sign = (a_sign == b_sign) ? 1 : -1;
671
+ return {from_sign_mag(q_sign, std::move(q_abs)), BigInt(0)};
672
+ }
673
+
674
+ if (a_sign == b_sign) {
675
+ return {from_sign_mag(1, std::move(q_abs)),
676
+ from_sign_mag(b_sign, std::move(r_abs))};
677
+ }
678
+
679
+ // Different signs: q = -(|q|+1), r = |b| - |r|
680
+ add_small_inplace(q_abs, 1);
681
+ std::vector<uint64_t> adjusted = sub_mag(b, r_abs);
682
+ return {from_sign_mag(-1, std::move(q_abs)),
683
+ from_sign_mag(b_sign, std::move(adjusted))};
684
+ }
685
+
686
+ // Try to convert to size_t for container pre-allocation.
687
+ // Returns false for negative values or values exceeding uint64_t range.
688
+ bool to_size_checked(size_t& out) const {
689
+ if (is_small()) {
690
+ int64_t v = small_value();
691
+ if (v < 0) return false;
692
+ out = static_cast<size_t>(v);
693
+ return true;
694
+ }
695
+ const HeapBig* p = heap_ptr();
696
+ if (p->sign < 0 || p->len > 1) return false;
697
+ out = (p->len == 0) ? 0 : static_cast<size_t>(p->limbs[0]);
698
+ return true;
699
+ }
700
+
701
+ // Public Python-API name; abs_bit_length() is the size_t internal
702
+ // form used elsewhere in the runtime. The int32_t return is fixed
703
+ // (independent of --default-int) and sufficient for any BigInt
704
+ // that fits in addressable memory; the cast is silent on overflow.
705
+ int32_t bit_length() const {
706
+ return static_cast<int32_t>(abs_bit_length());
707
+ }
708
+
709
+ private:
710
+ struct HeapBig {
711
+ uint32_t len; // Number of used limbs.
712
+ uint32_t cap; // Allocated limb capacity.
713
+ int8_t sign; // -1, 0, +1
714
+ uint8_t _pad[7];
715
+ uint64_t limbs[1]; // Trailing storage.
716
+ };
717
+
718
+ uintptr_t raw_; // small: encoded int63; big: tagged HeapBig* (LSB=1)
719
+
720
+ static_assert(sizeof(uintptr_t) == 8, "BigInt requires 64-bit pointers");
721
+ static_assert(alignof(HeapBig) >= 2, "BigInt pointer tagging requires aligned HeapBig");
722
+
723
+ static constexpr uintptr_t TAG_MASK = uintptr_t(1);
724
+ static constexpr int64_t SMALL_MAX = (INT64_MAX >> 1);
725
+ static constexpr int64_t SMALL_MIN = (INT64_MIN >> 1);
726
+ static constexpr uint64_t SMALL_MIN_MAG = (uint64_t(1) << 62);
727
+
728
+ static bool fits_small(int64_t v) noexcept {
729
+ return v >= SMALL_MIN && v <= SMALL_MAX;
730
+ }
731
+
732
+ static uintptr_t encode_small(int64_t v) noexcept {
733
+ return static_cast<uintptr_t>(static_cast<uint64_t>(v) << 1);
734
+ }
735
+
736
+ static uintptr_t encode_big(HeapBig* p) noexcept {
737
+ return reinterpret_cast<uintptr_t>(p) | TAG_MASK;
738
+ }
739
+
740
+ static BigInt make_small(int64_t v) noexcept {
741
+ BigInt out;
742
+ out.raw_ = encode_small(v);
743
+ return out;
744
+ }
745
+
746
+ static uint64_t abs_u64(int64_t v) noexcept {
747
+ uint64_t u = static_cast<uint64_t>(v);
748
+ return (v < 0) ? (~u + 1U) : u;
749
+ }
750
+
751
+ HeapBig* heap_ptr() noexcept {
752
+ return reinterpret_cast<HeapBig*>(raw_ & ~TAG_MASK);
753
+ }
754
+
755
+ const HeapBig* heap_ptr() const noexcept {
756
+ return reinterpret_cast<const HeapBig*>(raw_ & ~TAG_MASK);
757
+ }
758
+
759
+ static size_t heap_alloc_size(uint32_t cap) noexcept {
760
+ size_t base = offsetof(HeapBig, limbs);
761
+ return base + static_cast<size_t>(cap) * sizeof(uint64_t);
762
+ }
763
+
764
+ static HeapBig* alloc_heap(uint32_t cap) {
765
+ if (cap == 0) {
766
+ cap = 1;
767
+ }
768
+ void* mem = std::malloc(heap_alloc_size(cap));
769
+ if (mem == nullptr) {
770
+ tpy_panic("out of memory");
771
+ }
772
+ auto* p = static_cast<HeapBig*>(mem);
773
+ p->len = 0;
774
+ p->cap = cap;
775
+ p->sign = 0;
776
+ for (uint32_t i = 0; i < cap; ++i) {
777
+ p->limbs[i] = 0;
778
+ }
779
+ return p;
780
+ }
781
+
782
+ static HeapBig* clone_heap(const HeapBig* src) {
783
+ HeapBig* dst = alloc_heap(src->len == 0 ? 1 : src->len);
784
+ dst->len = src->len;
785
+ dst->cap = src->len == 0 ? 1 : src->len;
786
+ dst->sign = src->sign;
787
+ for (uint32_t i = 0; i < src->len; ++i) {
788
+ dst->limbs[i] = src->limbs[i];
789
+ }
790
+ return dst;
791
+ }
792
+
793
+ static void free_heap(HeapBig* p) noexcept {
794
+ std::free(p);
795
+ }
796
+
797
+ int signum() const noexcept {
798
+ if (is_small()) {
799
+ int64_t v = small_value();
800
+ return (v > 0) - (v < 0);
801
+ }
802
+ return heap_ptr()->sign;
803
+ }
804
+
805
+ static void trim_mag(std::vector<uint64_t>& limbs) {
806
+ while (!limbs.empty() && limbs.back() == 0) {
807
+ limbs.pop_back();
808
+ }
809
+ }
810
+
811
+ std::vector<uint64_t> abs_limbs() const {
812
+ if (is_small()) {
813
+ int64_t v = small_value();
814
+ if (v == 0) {
815
+ return {};
816
+ }
817
+ return {abs_u64(v)};
818
+ }
819
+ const HeapBig* p = heap_ptr();
820
+ return std::vector<uint64_t>(p->limbs, p->limbs + p->len);
821
+ }
822
+
823
+ static BigInt from_sign_mag(int sign, std::vector<uint64_t> limbs) {
824
+ trim_mag(limbs);
825
+ if (limbs.empty() || sign == 0) {
826
+ return BigInt(0);
827
+ }
828
+
829
+ sign = (sign < 0) ? -1 : 1;
830
+
831
+ if (limbs.size() == 1) {
832
+ uint64_t v = limbs[0];
833
+ if (sign > 0) {
834
+ if (v <= static_cast<uint64_t>(SMALL_MAX)) {
835
+ return make_small(static_cast<int64_t>(v));
836
+ }
837
+ } else {
838
+ if (v <= SMALL_MIN_MAG) {
839
+ if (v == SMALL_MIN_MAG) {
840
+ return make_small(SMALL_MIN);
841
+ }
842
+ return make_small(-static_cast<int64_t>(v));
843
+ }
844
+ }
845
+ }
846
+
847
+ HeapBig* p = alloc_heap(static_cast<uint32_t>(limbs.size()));
848
+ p->len = static_cast<uint32_t>(limbs.size());
849
+ p->sign = static_cast<int8_t>(sign);
850
+ for (size_t i = 0; i < limbs.size(); ++i) {
851
+ p->limbs[i] = limbs[i];
852
+ }
853
+
854
+ BigInt out;
855
+ out.raw_ = encode_big(p);
856
+ return out;
857
+ }
858
+
859
+ static int cmp_mag(const std::vector<uint64_t>& a, const std::vector<uint64_t>& b) {
860
+ if (a.size() != b.size()) {
861
+ return (a.size() > b.size()) ? 1 : -1;
862
+ }
863
+ for (size_t i = a.size(); i > 0; --i) {
864
+ size_t idx = i - 1;
865
+ if (a[idx] != b[idx]) {
866
+ return (a[idx] > b[idx]) ? 1 : -1;
867
+ }
868
+ }
869
+ return 0;
870
+ }
871
+
872
+ static std::vector<uint64_t> add_mag(const std::vector<uint64_t>& a, const std::vector<uint64_t>& b) {
873
+ size_t n = (a.size() > b.size()) ? a.size() : b.size();
874
+ std::vector<uint64_t> out(n, 0);
875
+ unsigned __int128 carry = 0;
876
+ for (size_t i = 0; i < n; ++i) {
877
+ unsigned __int128 av = (i < a.size()) ? a[i] : 0;
878
+ unsigned __int128 bv = (i < b.size()) ? b[i] : 0;
879
+ unsigned __int128 sum = av + bv + carry;
880
+ out[i] = static_cast<uint64_t>(sum);
881
+ carry = sum >> 64;
882
+ }
883
+ if (carry != 0) {
884
+ out.push_back(static_cast<uint64_t>(carry));
885
+ }
886
+ trim_mag(out);
887
+ return out;
888
+ }
889
+
890
+ static std::vector<uint64_t> sub_mag(const std::vector<uint64_t>& a, const std::vector<uint64_t>& b) {
891
+ // Precondition: a >= b
892
+ std::vector<uint64_t> out(a.size(), 0);
893
+ uint64_t borrow = 0;
894
+ for (size_t i = 0; i < a.size(); ++i) {
895
+ unsigned __int128 av = a[i];
896
+ unsigned __int128 bv = (i < b.size()) ? b[i] : 0;
897
+ unsigned __int128 sub = bv + borrow;
898
+ if (av >= sub) {
899
+ out[i] = static_cast<uint64_t>(av - sub);
900
+ borrow = 0;
901
+ } else {
902
+ out[i] = static_cast<uint64_t>((static_cast<unsigned __int128>(uint64_t(1)) << 64) + av - sub);
903
+ borrow = 1;
904
+ }
905
+ }
906
+ trim_mag(out);
907
+ return out;
908
+ }
909
+
910
+ static std::vector<uint64_t> mul_mag(const std::vector<uint64_t>& a, const std::vector<uint64_t>& b) {
911
+ if (a.empty() || b.empty()) {
912
+ return {};
913
+ }
914
+ std::vector<uint64_t> out(a.size() + b.size() + 1, 0);
915
+ for (size_t i = 0; i < a.size(); ++i) {
916
+ unsigned __int128 carry = 0;
917
+ for (size_t j = 0; j < b.size(); ++j) {
918
+ size_t idx = i + j;
919
+ unsigned __int128 cur =
920
+ static_cast<unsigned __int128>(a[i]) * b[j] +
921
+ out[idx] + carry;
922
+ out[idx] = static_cast<uint64_t>(cur);
923
+ carry = cur >> 64;
924
+ }
925
+ size_t k = i + b.size();
926
+ while (carry != 0) {
927
+ unsigned __int128 cur = static_cast<unsigned __int128>(out[k]) + carry;
928
+ out[k] = static_cast<uint64_t>(cur);
929
+ carry = cur >> 64;
930
+ ++k;
931
+ }
932
+ }
933
+ trim_mag(out);
934
+ return out;
935
+ }
936
+
937
+ static void add_small_inplace(std::vector<uint64_t>& a, uint32_t v) {
938
+ if (v == 0) {
939
+ return;
940
+ }
941
+ unsigned __int128 carry = v;
942
+ size_t i = 0;
943
+ while (carry != 0) {
944
+ if (i >= a.size()) {
945
+ a.push_back(0);
946
+ }
947
+ unsigned __int128 sum = static_cast<unsigned __int128>(a[i]) + carry;
948
+ a[i] = static_cast<uint64_t>(sum);
949
+ carry = sum >> 64;
950
+ ++i;
951
+ }
952
+ }
953
+
954
+ static void mul_small_inplace(std::vector<uint64_t>& a, uint32_t m) {
955
+ if (a.empty() || m == 1) {
956
+ return;
957
+ }
958
+ if (m == 0) {
959
+ a.clear();
960
+ return;
961
+ }
962
+ unsigned __int128 carry = 0;
963
+ for (size_t i = 0; i < a.size(); ++i) {
964
+ unsigned __int128 prod = static_cast<unsigned __int128>(a[i]) * m + carry;
965
+ a[i] = static_cast<uint64_t>(prod);
966
+ carry = prod >> 64;
967
+ }
968
+ if (carry != 0) {
969
+ a.push_back(static_cast<uint64_t>(carry));
970
+ }
971
+ }
972
+
973
+ static std::vector<uint64_t> lshift_mag(const std::vector<uint64_t>& a, size_t bits) {
974
+ if (a.empty() || bits == 0) {
975
+ return a;
976
+ }
977
+ size_t word_shift = bits / 64;
978
+ size_t bit_shift = bits % 64;
979
+
980
+ std::vector<uint64_t> out;
981
+ out.reserve(a.size() + word_shift + 1);
982
+ for (size_t i = 0; i < word_shift; ++i) {
983
+ out.push_back(0);
984
+ }
985
+
986
+ if (bit_shift == 0) {
987
+ out.insert(out.end(), a.begin(), a.end());
988
+ trim_mag(out);
989
+ return out;
990
+ }
991
+
992
+ uint64_t carry = 0;
993
+ for (uint64_t limb : a) {
994
+ uint64_t lower = (limb << bit_shift) | carry;
995
+ out.push_back(lower);
996
+ carry = limb >> (64 - bit_shift);
997
+ }
998
+ if (carry != 0) {
999
+ out.push_back(carry);
1000
+ }
1001
+ trim_mag(out);
1002
+ return out;
1003
+ }
1004
+
1005
+ static std::vector<uint64_t> rshift_mag(const std::vector<uint64_t>& a, size_t bits) {
1006
+ if (a.empty() || bits == 0) {
1007
+ return a;
1008
+ }
1009
+ size_t word_shift = bits / 64;
1010
+ size_t bit_shift = bits % 64;
1011
+ if (word_shift >= a.size()) {
1012
+ return {};
1013
+ }
1014
+
1015
+ std::vector<uint64_t> out(a.size() - word_shift, 0);
1016
+ if (bit_shift == 0) {
1017
+ for (size_t i = word_shift; i < a.size(); ++i) {
1018
+ out[i - word_shift] = a[i];
1019
+ }
1020
+ trim_mag(out);
1021
+ return out;
1022
+ }
1023
+
1024
+ for (size_t i = word_shift; i < a.size(); ++i) {
1025
+ uint64_t low = a[i] >> bit_shift;
1026
+ uint64_t high = 0;
1027
+ if (i + 1 < a.size()) {
1028
+ high = a[i + 1] << (64 - bit_shift);
1029
+ }
1030
+ out[i - word_shift] = low | high;
1031
+ }
1032
+ trim_mag(out);
1033
+ return out;
1034
+ }
1035
+
1036
+ static void rshift1_inplace(std::vector<uint64_t>& a) {
1037
+ uint64_t carry = 0;
1038
+ for (size_t i = a.size(); i > 0; --i) {
1039
+ size_t idx = i - 1;
1040
+ uint64_t new_carry = a[idx] << 63;
1041
+ a[idx] = (a[idx] >> 1) | carry;
1042
+ carry = new_carry;
1043
+ }
1044
+ trim_mag(a);
1045
+ }
1046
+
1047
+ static size_t bit_length_mag(const std::vector<uint64_t>& a) {
1048
+ if (a.empty()) {
1049
+ return 0;
1050
+ }
1051
+ uint64_t ms = a.back();
1052
+ return (a.size() - 1) * 64 + (64 - static_cast<size_t>(__builtin_clzll(ms)));
1053
+ }
1054
+
1055
+ static void set_bit(std::vector<uint64_t>& a, size_t bit_idx) {
1056
+ size_t limb_idx = bit_idx / 64;
1057
+ size_t off = bit_idx % 64;
1058
+ if (limb_idx >= a.size()) {
1059
+ a.resize(limb_idx + 1, 0);
1060
+ }
1061
+ a[limb_idx] |= (uint64_t(1) << off);
1062
+ }
1063
+
1064
+ static uint32_t div_small_inplace(std::vector<uint64_t>& a, uint32_t divisor) {
1065
+ uint64_t rem = 0;
1066
+ for (size_t i = a.size(); i > 0; --i) {
1067
+ size_t idx = i - 1;
1068
+ unsigned __int128 cur = (static_cast<unsigned __int128>(rem) << 64) | a[idx];
1069
+ a[idx] = static_cast<uint64_t>(cur / divisor);
1070
+ rem = static_cast<uint64_t>(cur % divisor);
1071
+ }
1072
+ trim_mag(a);
1073
+ return static_cast<uint32_t>(rem);
1074
+ }
1075
+
1076
+ static void divmod_mag(
1077
+ const std::vector<uint64_t>& num,
1078
+ const std::vector<uint64_t>& den,
1079
+ std::vector<uint64_t>& q,
1080
+ std::vector<uint64_t>& r
1081
+ ) {
1082
+ // Internal invariant: public callers (floor_div / floor_mod /
1083
+ // floor_divmod) throw ZeroDivisionError before reaching this helper.
1084
+ if (den.empty()) {
1085
+ tpy_panic("BigInt::divmod_mag called with empty divisor");
1086
+ }
1087
+ if (num.empty()) {
1088
+ q.clear();
1089
+ r.clear();
1090
+ return;
1091
+ }
1092
+
1093
+ int cmp = cmp_mag(num, den);
1094
+ if (cmp < 0) {
1095
+ q.clear();
1096
+ r = num;
1097
+ return;
1098
+ }
1099
+ if (cmp == 0) {
1100
+ q = {1};
1101
+ r.clear();
1102
+ return;
1103
+ }
1104
+
1105
+ if (den.size() == 1) {
1106
+ uint64_t d = den[0];
1107
+ q.assign(num.size(), 0);
1108
+ uint64_t rem = 0;
1109
+ for (size_t i = num.size(); i > 0; --i) {
1110
+ size_t idx = i - 1;
1111
+ unsigned __int128 cur = (static_cast<unsigned __int128>(rem) << 64) | num[idx];
1112
+ q[idx] = static_cast<uint64_t>(cur / d);
1113
+ rem = static_cast<uint64_t>(cur % d);
1114
+ }
1115
+ trim_mag(q);
1116
+ r.clear();
1117
+ if (rem != 0) {
1118
+ r.push_back(rem);
1119
+ }
1120
+ return;
1121
+ }
1122
+
1123
+ size_t nbits = bit_length_mag(num);
1124
+ size_t dbits = bit_length_mag(den);
1125
+ size_t shift = nbits - dbits;
1126
+
1127
+ std::vector<uint64_t> d = lshift_mag(den, shift);
1128
+ r = num;
1129
+ q.clear();
1130
+
1131
+ for (size_t i = shift + 1; i > 0; --i) {
1132
+ size_t bit = i - 1;
1133
+ if (cmp_mag(r, d) >= 0) {
1134
+ r = sub_mag(r, d);
1135
+ set_bit(q, bit);
1136
+ }
1137
+ rshift1_inplace(d);
1138
+ }
1139
+
1140
+ trim_mag(q);
1141
+ trim_mag(r);
1142
+ }
1143
+
1144
+ bool to_uint64_checked(uint64_t& out) const {
1145
+ if (is_small()) {
1146
+ int64_t v = small_value();
1147
+ if (v < 0) {
1148
+ return false;
1149
+ }
1150
+ out = static_cast<uint64_t>(v);
1151
+ return true;
1152
+ }
1153
+ const HeapBig* p = heap_ptr();
1154
+ if (p->sign < 0 || p->len > 1) {
1155
+ return false;
1156
+ }
1157
+ out = (p->len == 0) ? 0 : p->limbs[0];
1158
+ return true;
1159
+ }
1160
+
1161
+ size_t abs_bit_length() const {
1162
+ if (is_small()) {
1163
+ uint64_t mag = abs_u64(small_value());
1164
+ if (mag == 0) return 0;
1165
+ return 64 - static_cast<size_t>(__builtin_clzll(mag));
1166
+ }
1167
+ const HeapBig* p = heap_ptr();
1168
+ if (p->len == 0) return 0;
1169
+ uint64_t ms = p->limbs[p->len - 1];
1170
+ return (static_cast<size_t>(p->len) - 1) * 64 +
1171
+ (64 - static_cast<size_t>(__builtin_clzll(ms)));
1172
+ }
1173
+
1174
+ static std::vector<uint64_t> to_twos_complement(const BigInt& x, size_t limbs_n) {
1175
+ std::vector<uint64_t> out(limbs_n, 0);
1176
+ std::vector<uint64_t> mag = x.abs_limbs();
1177
+ for (size_t i = 0; i < mag.size() && i < limbs_n; ++i) {
1178
+ out[i] = mag[i];
1179
+ }
1180
+
1181
+ if (x.signum() < 0) {
1182
+ for (size_t i = 0; i < out.size(); ++i) {
1183
+ out[i] = ~out[i];
1184
+ }
1185
+ uint64_t carry = 1;
1186
+ for (size_t i = 0; i < out.size() && carry != 0; ++i) {
1187
+ unsigned __int128 sum = static_cast<unsigned __int128>(out[i]) + carry;
1188
+ out[i] = static_cast<uint64_t>(sum);
1189
+ carry = static_cast<uint64_t>(sum >> 64);
1190
+ }
1191
+ }
1192
+ return out;
1193
+ }
1194
+
1195
+ static BigInt from_twos_complement(std::vector<uint64_t> tc) {
1196
+ if (tc.empty()) {
1197
+ return BigInt(0);
1198
+ }
1199
+ bool negative = ((tc.back() >> 63) != 0);
1200
+ if (!negative) {
1201
+ trim_mag(tc);
1202
+ return from_sign_mag(1, std::move(tc));
1203
+ }
1204
+
1205
+ for (size_t i = 0; i < tc.size(); ++i) {
1206
+ tc[i] = ~tc[i];
1207
+ }
1208
+ uint64_t carry = 1;
1209
+ for (size_t i = 0; i < tc.size() && carry != 0; ++i) {
1210
+ unsigned __int128 sum = static_cast<unsigned __int128>(tc[i]) + carry;
1211
+ tc[i] = static_cast<uint64_t>(sum);
1212
+ carry = static_cast<uint64_t>(sum >> 64);
1213
+ }
1214
+ trim_mag(tc);
1215
+ return from_sign_mag(-1, std::move(tc));
1216
+ }
1217
+
1218
+ BigInt bitwise_binary(const BigInt& rhs, char op) const {
1219
+ size_t a_limbs = (abs_bit_length() + 63) / 64;
1220
+ size_t b_limbs = (rhs.abs_bit_length() + 63) / 64;
1221
+ size_t n = (a_limbs > b_limbs ? a_limbs : b_limbs) + 2;
1222
+ if (n == 0) n = 2;
1223
+
1224
+ std::vector<uint64_t> a = to_twos_complement(*this, n);
1225
+ std::vector<uint64_t> b = to_twos_complement(rhs, n);
1226
+ std::vector<uint64_t> out(n, 0);
1227
+
1228
+ for (size_t i = 0; i < n; ++i) {
1229
+ if (op == '&') {
1230
+ out[i] = a[i] & b[i];
1231
+ } else if (op == '|') {
1232
+ out[i] = a[i] | b[i];
1233
+ } else {
1234
+ out[i] = a[i] ^ b[i];
1235
+ }
1236
+ }
1237
+ return from_twos_complement(std::move(out));
1238
+ }
1239
+
1240
+ int compare(const BigInt& rhs) const {
1241
+ int a_sign = signum();
1242
+ int b_sign = rhs.signum();
1243
+ if (a_sign != b_sign) {
1244
+ return (a_sign > b_sign) ? 1 : -1;
1245
+ }
1246
+ if (a_sign == 0) {
1247
+ return 0;
1248
+ }
1249
+
1250
+ std::vector<uint64_t> a = abs_limbs();
1251
+ std::vector<uint64_t> b = rhs.abs_limbs();
1252
+ int cmp = cmp_mag(a, b);
1253
+ return (a_sign > 0) ? cmp : -cmp;
1254
+ }
1255
+
1256
+ BigInt floor_div(const BigInt& rhs) const {
1257
+ if (rhs.signum() == 0) {
1258
+ raise_zero_division_error("integer division or modulo by zero");
1259
+ }
1260
+ if (signum() == 0) {
1261
+ return BigInt(0);
1262
+ }
1263
+
1264
+ int a_sign = signum();
1265
+ int b_sign = rhs.signum();
1266
+ std::vector<uint64_t> a = abs_limbs();
1267
+ std::vector<uint64_t> b = rhs.abs_limbs();
1268
+
1269
+ std::vector<uint64_t> q_abs;
1270
+ std::vector<uint64_t> r_abs;
1271
+ divmod_mag(a, b, q_abs, r_abs);
1272
+
1273
+ bool rem_zero = r_abs.empty();
1274
+ if (a_sign == b_sign) {
1275
+ return from_sign_mag(1, std::move(q_abs));
1276
+ }
1277
+
1278
+ if (rem_zero) {
1279
+ return from_sign_mag(-1, std::move(q_abs));
1280
+ }
1281
+
1282
+ add_small_inplace(q_abs, 1);
1283
+ return from_sign_mag(-1, std::move(q_abs));
1284
+ }
1285
+
1286
+ BigInt floor_mod(const BigInt& rhs) const {
1287
+ if (rhs.signum() == 0) {
1288
+ raise_zero_division_error("integer modulo by zero");
1289
+ }
1290
+ if (signum() == 0) {
1291
+ return BigInt(0);
1292
+ }
1293
+
1294
+ int a_sign = signum();
1295
+ int b_sign = rhs.signum();
1296
+ std::vector<uint64_t> a = abs_limbs();
1297
+ std::vector<uint64_t> b = rhs.abs_limbs();
1298
+
1299
+ std::vector<uint64_t> q_abs;
1300
+ std::vector<uint64_t> r_abs;
1301
+ divmod_mag(a, b, q_abs, r_abs);
1302
+
1303
+ if (r_abs.empty()) {
1304
+ return BigInt(0);
1305
+ }
1306
+
1307
+ if (a_sign == b_sign) {
1308
+ return from_sign_mag(b_sign, std::move(r_abs));
1309
+ }
1310
+
1311
+ std::vector<uint64_t> adjusted = sub_mag(b, r_abs); // |b| - r
1312
+ return from_sign_mag(b_sign, std::move(adjusted));
1313
+ }
1314
+
1315
+ static std::string pad9(uint32_t v) {
1316
+ std::string s = std::to_string(v);
1317
+ if (s.size() >= 9) {
1318
+ return s;
1319
+ }
1320
+ return std::string(9 - s.size(), '0') + s;
1321
+ }
1322
+ };
1323
+
1324
+ static_assert(sizeof(BigInt) == sizeof(uintptr_t), "BigInt must stay 8 bytes");
1325
+
1326
+ // Stream output operator for BigInt
1327
+ inline std::ostream& operator<<(std::ostream& os, const BigInt& val) {
1328
+ return os << val.to_string();
1329
+ }
1330
+
1331
+ inline uint64_t __hash__(const BigInt& val) {
1332
+ return val.hash();
1333
+ }
1334
+
1335
+
1336
+ } // namespace tpy
1337
+
1338
+ template<>
1339
+ struct std::hash<tpy::BigInt> {
1340
+ size_t operator()(const tpy::BigInt& val) const noexcept {
1341
+ return static_cast<size_t>(val.hash());
1342
+ }
1343
+ };