public.odin 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. // Arbitrary precision integers and rationals.
  2. package math_big
  3. /*
  4. Copyright 2021 Jeroen van Rijn <[email protected]>.
  5. Made available under Odin's BSD-3 license.
  6. An arbitrary precision mathematics implementation in Odin.
  7. For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
  8. The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
  9. This file contains basic arithmetic operations like `add`, `sub`, `mul`, `div`, ...
  10. */
  11. import "base:intrinsics"
  12. /*
  13. ===========================
  14. User-level routines
  15. ===========================
  16. */
  17. /*
  18. High-level addition. Handles sign.
  19. */
  20. int_add :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
  21. assert_if_nil(dest, a, b)
  22. context.allocator = allocator
  23. internal_clear_if_uninitialized(dest, a, b) or_return
  24. /*
  25. All parameters have been initialized.
  26. */
  27. return #force_inline internal_int_add_signed(dest, a, b)
  28. }
  29. /*
  30. Adds the unsigned `DIGIT` immediate to an `Int`,
  31. such that the `DIGIT` doesn't have to be turned into an `Int` first.
  32. dest = a + digit;
  33. */
  34. int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) {
  35. assert_if_nil(dest, a)
  36. context.allocator = allocator
  37. internal_clear_if_uninitialized(a) or_return
  38. /*
  39. Grow destination as required.
  40. */
  41. grow(dest, a.used + 1) or_return
  42. /*
  43. All parameters have been initialized.
  44. */
  45. return #force_inline internal_int_add_digit(dest, a, digit)
  46. }
  47. /*
  48. High-level subtraction, dest = number - decrease. Handles signs.
  49. */
  50. int_sub :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> (err: Error) {
  51. assert_if_nil(dest, number, decrease)
  52. context.allocator = allocator
  53. internal_clear_if_uninitialized(dest, number, decrease) or_return
  54. /*
  55. All parameters have been initialized.
  56. */
  57. return #force_inline internal_int_sub_signed(dest, number, decrease)
  58. }
  59. /*
  60. Adds the unsigned `DIGIT` immediate to an `Int`,
  61. such that the `DIGIT` doesn't have to be turned into an `Int` first.
  62. dest = a - digit;
  63. */
  64. int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) {
  65. assert_if_nil(dest, a)
  66. context.allocator = allocator
  67. internal_clear_if_uninitialized(a) or_return
  68. /*
  69. Grow destination as required.
  70. */
  71. grow(dest, a.used + 1) or_return
  72. /*
  73. All parameters have been initialized.
  74. */
  75. return #force_inline internal_int_sub_digit(dest, a, digit)
  76. }
  77. /*
  78. dest = src / 2
  79. dest = src >> 1
  80. */
  81. int_halve :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
  82. assert_if_nil(dest, src)
  83. context.allocator = allocator
  84. internal_clear_if_uninitialized(dest, src) or_return
  85. /*
  86. Grow destination as required.
  87. */
  88. if dest != src { grow(dest, src.used + 1) or_return }
  89. return #force_inline internal_int_shr1(dest, src)
  90. }
  91. halve :: proc { int_halve, }
  92. shr1 :: halve
  93. /*
  94. dest = src * 2
  95. dest = src << 1
  96. */
  97. int_double :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
  98. assert_if_nil(dest, src)
  99. context.allocator = allocator
  100. internal_clear_if_uninitialized(dest, src) or_return
  101. /*
  102. Grow destination as required.
  103. */
  104. if dest != src { grow(dest, src.used + 1) or_return }
  105. return #force_inline internal_int_shl1(dest, src)
  106. }
  107. double :: proc { int_double, }
  108. shl1 :: double
  109. /*
  110. Multiply by a DIGIT.
  111. */
  112. int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT, allocator := context.allocator) -> (err: Error) {
  113. assert_if_nil(dest, src)
  114. context.allocator = allocator
  115. internal_clear_if_uninitialized(src, dest) or_return
  116. return #force_inline internal_int_mul_digit(dest, src, multiplier)
  117. }
  118. /*
  119. High level multiplication (handles sign).
  120. */
  121. int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.allocator) -> (err: Error) {
  122. assert_if_nil(dest, src, multiplier)
  123. context.allocator = allocator
  124. internal_clear_if_uninitialized(dest, src, multiplier) or_return
  125. return #force_inline internal_int_mul(dest, src, multiplier)
  126. }
  127. mul :: proc {
  128. int_mul,
  129. int_mul_digit,
  130. rat_mul_rat,
  131. rat_mul_int,
  132. int_mul_rat,
  133. }
  134. int_sqr :: proc(dest, src: ^Int) -> (err: Error) { return mul(dest, src, src) }
  135. rat_sqr :: proc(dest, src: ^Rat) -> (err: Error) { return mul(dest, src, src) }
  136. sqr :: proc { int_sqr, rat_sqr }
  137. /*
  138. divmod.
  139. Both the quotient and remainder are optional and may be passed a nil.
  140. */
  141. int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
  142. context.allocator = allocator
  143. /*
  144. Early out if neither of the results is wanted.
  145. */
  146. if quotient == nil && remainder == nil { return nil }
  147. internal_clear_if_uninitialized(numerator, denominator) or_return
  148. return #force_inline internal_divmod(quotient, remainder, numerator, denominator)
  149. }
  150. int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) {
  151. assert_if_nil(quotient, numerator)
  152. context.allocator = allocator
  153. internal_clear_if_uninitialized(numerator) or_return
  154. return #force_inline internal_divmod(quotient, numerator, denominator)
  155. }
  156. divmod :: proc{ int_divmod, int_divmod_digit, }
  157. int_div :: proc(quotient, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
  158. assert_if_nil(quotient, numerator, denominator)
  159. context.allocator = allocator
  160. internal_clear_if_uninitialized(numerator, denominator) or_return
  161. return #force_inline internal_divmod(quotient, nil, numerator, denominator)
  162. }
  163. int_div_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (err: Error) {
  164. assert_if_nil(quotient, numerator)
  165. context.allocator = allocator
  166. internal_clear_if_uninitialized(numerator) or_return
  167. _ = #force_inline internal_divmod(quotient, numerator, denominator) or_return
  168. return
  169. }
  170. div :: proc {
  171. int_div,
  172. int_div_digit,
  173. rat_div_rat,
  174. rat_div_int,
  175. int_div_rat,
  176. }
  177. /*
  178. remainder = numerator % denominator.
  179. 0 <= remainder < denominator if denominator > 0
  180. denominator < remainder <= 0 if denominator < 0
  181. */
  182. int_mod :: proc(remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
  183. assert_if_nil(remainder, numerator, denominator)
  184. context.allocator = allocator
  185. internal_clear_if_uninitialized(numerator, denominator) or_return
  186. return #force_inline internal_int_mod(remainder, numerator, denominator)
  187. }
  188. int_mod_digit :: proc(numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) {
  189. return #force_inline internal_divmod(nil, numerator, denominator, allocator)
  190. }
  191. mod :: proc { int_mod, int_mod_digit, }
  192. /*
  193. remainder = (number + addend) % modulus.
  194. */
  195. int_addmod :: proc(remainder, number, addend, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
  196. assert_if_nil(remainder, number, addend)
  197. context.allocator = allocator
  198. internal_clear_if_uninitialized(number, addend, modulus) or_return
  199. return #force_inline internal_addmod(remainder, number, addend, modulus)
  200. }
  201. addmod :: proc { int_addmod, }
  202. /*
  203. remainder = (number - decrease) % modulus.
  204. */
  205. int_submod :: proc(remainder, number, decrease, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
  206. assert_if_nil(remainder, number, decrease)
  207. context.allocator = allocator
  208. internal_clear_if_uninitialized(number, decrease, modulus) or_return
  209. return #force_inline internal_submod(remainder, number, decrease, modulus)
  210. }
  211. submod :: proc { int_submod, }
  212. /*
  213. remainder = (number * multiplicand) % modulus.
  214. */
  215. int_mulmod :: proc(remainder, number, multiplicand, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
  216. assert_if_nil(remainder, number, multiplicand)
  217. context.allocator = allocator
  218. internal_clear_if_uninitialized(number, multiplicand, modulus) or_return
  219. return #force_inline internal_mulmod(remainder, number, multiplicand, modulus)
  220. }
  221. mulmod :: proc { int_mulmod, }
  222. /*
  223. remainder = (number * number) % modulus.
  224. */
  225. int_sqrmod :: proc(remainder, number, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
  226. assert_if_nil(remainder, number, modulus)
  227. context.allocator = allocator
  228. internal_clear_if_uninitialized(number, modulus) or_return
  229. return #force_inline internal_sqrmod(remainder, number, modulus)
  230. }
  231. sqrmod :: proc { int_sqrmod, }
  232. int_factorial :: proc(res: ^Int, n: int, allocator := context.allocator) -> (err: Error) {
  233. if n < 0 || n > FACTORIAL_MAX_N { return .Invalid_Argument }
  234. assert_if_nil(res)
  235. return #force_inline internal_int_factorial(res, n, allocator)
  236. }
  237. factorial :: proc { int_factorial, }
  238. /*
  239. Number of ways to choose `k` items from `n` items.
  240. Also known as the binomial coefficient.
  241. TODO: Speed up.
  242. Could be done faster by reusing code from factorial and reusing the common "prefix" results for n!, k! and n-k!
  243. We know that n >= k, otherwise we early out with res = 0.
  244. So:
  245. n-k, keep result
  246. n, start from previous result
  247. k, start from previous result
  248. */
  249. int_choose_digit :: proc(res: ^Int, n, k: int, allocator := context.allocator) -> (err: Error) {
  250. assert_if_nil(res)
  251. context.allocator = allocator
  252. if n < 0 || n > FACTORIAL_MAX_N { return .Invalid_Argument }
  253. if k > n { return internal_zero(res) }
  254. /*
  255. res = n! / (k! * (n - k)!)
  256. */
  257. n_fac, k_fac, n_minus_k_fac := &Int{}, &Int{}, &Int{}
  258. defer internal_destroy(n_fac, k_fac, n_minus_k_fac)
  259. #force_inline internal_int_factorial(n_minus_k_fac, n - k) or_return
  260. #force_inline internal_int_factorial(k_fac, k) or_return
  261. #force_inline internal_mul(k_fac, k_fac, n_minus_k_fac) or_return
  262. #force_inline internal_int_factorial(n_fac, n) or_return
  263. #force_inline internal_div(res, n_fac, k_fac) or_return
  264. return
  265. }
  266. choose :: proc { int_choose_digit, }
  267. /*
  268. Function computing both GCD and (if target isn't `nil`) also LCM.
  269. */
  270. int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
  271. if res_gcd == nil && res_lcm == nil { return nil }
  272. assert_if_nil(a, b)
  273. context.allocator = allocator
  274. internal_clear_if_uninitialized(a, b) or_return
  275. return #force_inline internal_int_gcd_lcm(res_gcd, res_lcm, a, b)
  276. }
  277. gcd_lcm :: proc { int_gcd_lcm, }
  278. /*
  279. Greatest Common Divisor.
  280. */
  281. int_gcd :: proc(res, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
  282. return #force_inline int_gcd_lcm(res, nil, a, b, allocator)
  283. }
  284. gcd :: proc { int_gcd, }
  285. /*
  286. Least Common Multiple.
  287. */
  288. int_lcm :: proc(res, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
  289. return #force_inline int_gcd_lcm(nil, res, a, b, allocator)
  290. }
  291. lcm :: proc { int_lcm, }
  292. /*
  293. remainder = numerator % (1 << bits)
  294. */
  295. int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
  296. assert_if_nil(remainder, numerator)
  297. context.allocator = allocator
  298. internal_clear_if_uninitialized(remainder, numerator) or_return
  299. if bits < 0 { return .Invalid_Argument }
  300. return #force_inline internal_int_mod_bits(remainder, numerator, bits)
  301. }
  302. mod_bits :: proc { int_mod_bits, }
  303. /*
  304. Logs and roots and such.
  305. */
  306. int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) -> (res: int, err: Error) {
  307. assert_if_nil(a)
  308. context.allocator = allocator
  309. internal_clear_if_uninitialized(a) or_return
  310. return #force_inline internal_int_log(a, base)
  311. }
  312. digit_log :: proc(a: DIGIT, base: DIGIT) -> (log: int, err: Error) {
  313. return #force_inline internal_digit_log(a, base)
  314. }
  315. log :: proc { int_log, digit_log, }
  316. ilog2 :: proc(value: $T) -> (log2: T) {
  317. return (size_of(T) * 8) - intrinsics.count_leading_zeros(value)
  318. }
  319. /*
  320. Calculate `dest = base^power` using a square-multiply algorithm.
  321. */
  322. int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allocator) -> (err: Error) {
  323. assert_if_nil(dest, base)
  324. context.allocator = allocator
  325. internal_clear_if_uninitialized(dest, base) or_return
  326. return #force_inline internal_int_pow(dest, base, power)
  327. }
  328. /*
  329. Calculate `dest = base^power` using a square-multiply algorithm.
  330. */
  331. int_pow_int :: proc(dest: ^Int, base, power: int, allocator := context.allocator) -> (err: Error) {
  332. assert_if_nil(dest)
  333. return #force_inline internal_pow(dest, base, power, allocator)
  334. }
  335. pow :: proc { int_pow, int_pow_int, small_pow, }
  336. exp :: pow
  337. small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) {
  338. return #force_inline internal_small_pow(base, exponent)
  339. }
  340. /*
  341. This function is less generic than `root_n`, simpler and faster.
  342. */
  343. int_sqrt :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
  344. assert_if_nil(dest, src)
  345. context.allocator = allocator
  346. internal_clear_if_uninitialized(dest, src) or_return
  347. return #force_inline internal_int_sqrt(dest, src)
  348. }
  349. sqrt :: proc { int_sqrt, }
  350. /*
  351. Find the nth root of an Integer.
  352. Result found such that `(dest)**n <= src` and `(dest+1)**n > src`
  353. This algorithm uses Newton's approximation `x[i+1] = x[i] - f(x[i])/f'(x[i])`,
  354. which will find the root in `log(n)` time where each step involves a fair bit.
  355. */
  356. int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.allocator) -> (err: Error) {
  357. context.allocator = allocator
  358. /*
  359. Fast path for n == 2.
  360. */
  361. if n == 2 { return sqrt(dest, src) }
  362. assert_if_nil(dest, src)
  363. /*
  364. Initialize dest + src if needed.
  365. */
  366. internal_clear_if_uninitialized(dest, src) or_return
  367. return #force_inline internal_int_root_n(dest, src, n)
  368. }
  369. root_n :: proc { int_root_n, }
  370. /*
  371. Comparison routines.
  372. */
  373. int_is_initialized :: proc(a: ^Int) -> bool {
  374. if a == nil { return false }
  375. return #force_inline internal_int_is_initialized(a)
  376. }
  377. int_is_zero :: proc(a: ^Int, allocator := context.allocator) -> (zero: bool, err: Error) {
  378. assert_if_nil(a)
  379. context.allocator = allocator
  380. internal_clear_if_uninitialized(a) or_return
  381. return #force_inline internal_is_zero(a), nil
  382. }
  383. int_is_positive :: proc(a: ^Int, allocator := context.allocator) -> (positive: bool, err: Error) {
  384. assert_if_nil(a)
  385. context.allocator = allocator
  386. internal_clear_if_uninitialized(a) or_return
  387. return #force_inline internal_is_positive(a), nil
  388. }
  389. int_is_negative :: proc(a: ^Int, allocator := context.allocator) -> (negative: bool, err: Error) {
  390. assert_if_nil(a)
  391. context.allocator = allocator
  392. internal_clear_if_uninitialized(a) or_return
  393. return #force_inline internal_is_negative(a), nil
  394. }
  395. int_is_even :: proc(a: ^Int, allocator := context.allocator) -> (even: bool, err: Error) {
  396. assert_if_nil(a)
  397. context.allocator = allocator
  398. internal_clear_if_uninitialized(a) or_return
  399. return #force_inline internal_is_even(a), nil
  400. }
  401. int_is_odd :: proc(a: ^Int, allocator := context.allocator) -> (odd: bool, err: Error) {
  402. assert_if_nil(a)
  403. context.allocator = allocator
  404. internal_clear_if_uninitialized(a) or_return
  405. return #force_inline internal_is_odd(a), nil
  406. }
  407. platform_int_is_power_of_two :: #force_inline proc(a: int) -> bool {
  408. return ((a) != 0) && (((a) & ((a) - 1)) == 0)
  409. }
  410. int_is_power_of_two :: proc(a: ^Int, allocator := context.allocator) -> (res: bool, err: Error) {
  411. assert_if_nil(a)
  412. context.allocator = allocator
  413. internal_clear_if_uninitialized(a) or_return
  414. return #force_inline internal_is_power_of_two(a), nil
  415. }
  416. /*
  417. Compare two `Int`s, signed.
  418. */
  419. int_compare :: proc(a, b: ^Int, allocator := context.allocator) -> (comparison: int, err: Error) {
  420. assert_if_nil(a, b)
  421. context.allocator = allocator
  422. internal_clear_if_uninitialized(a, b) or_return
  423. return #force_inline internal_cmp(a, b), nil
  424. }
  425. int_cmp :: int_compare
  426. /*
  427. Compare an `Int` to an unsigned number upto the size of the backing type.
  428. */
  429. int_compare_digit :: proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (comparison: int, err: Error) {
  430. assert_if_nil(a)
  431. context.allocator = allocator
  432. internal_clear_if_uninitialized(a) or_return
  433. return #force_inline internal_cmp_digit(a, b), nil
  434. }
  435. int_cmp_digit :: int_compare_digit
  436. /*
  437. Compare the magnitude of two `Int`s, unsigned.
  438. */
  439. int_compare_magnitude :: proc(a, b: ^Int, allocator := context.allocator) -> (res: int, err: Error) {
  440. assert_if_nil(a, b)
  441. context.allocator = allocator
  442. internal_clear_if_uninitialized(a, b) or_return
  443. return #force_inline internal_cmp_mag(a, b), nil
  444. }
  445. int_cmp_mag :: int_compare_magnitude
  446. /*
  447. bool := a < b
  448. */
  449. int_less_than :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (less_than: bool, err: Error) {
  450. assert_if_nil(a, b)
  451. context.allocator = allocator
  452. internal_clear_if_uninitialized(a, b) or_return
  453. c: int
  454. c, err = cmp(a, b)
  455. return c == -1, err
  456. }
  457. /*
  458. bool := a < b
  459. */
  460. int_less_than_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (less_than: bool, err: Error) {
  461. assert_if_nil(a)
  462. context.allocator = allocator
  463. internal_clear_if_uninitialized(a) or_return
  464. c: int
  465. c, err = cmp(a, b)
  466. return c == -1, err
  467. }
  468. /*
  469. bool := |a| < |b|
  470. Compares the magnitudes only, ignores the sign.
  471. */
  472. int_less_than_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (less_than: bool, err: Error) {
  473. assert_if_nil(a, b)
  474. context.allocator = allocator
  475. internal_clear_if_uninitialized(a, b) or_return
  476. c: int
  477. c, err = cmp_mag(a, b)
  478. return c == -1, err
  479. }
  480. less_than :: proc {
  481. int_less_than,
  482. int_less_than_digit,
  483. }
  484. lt :: less_than
  485. less_than_abs :: proc {
  486. int_less_than_abs,
  487. }
  488. lt_abs :: less_than_abs
  489. /*
  490. bool := a <= b
  491. */
  492. int_less_than_or_equal :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (less_than_or_equal: bool, err: Error) {
  493. assert_if_nil(a, b)
  494. context.allocator = allocator
  495. internal_clear_if_uninitialized(a, b) or_return
  496. c: int
  497. c, err = cmp(a, b)
  498. return c <= 0, err
  499. }
  500. /*
  501. bool := a <= b
  502. */
  503. int_less_than_or_equal_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (less_than_or_equal: bool, err: Error) {
  504. assert_if_nil(a)
  505. context.allocator = allocator
  506. internal_clear_if_uninitialized(a) or_return
  507. c: int
  508. c, err = cmp(a, b)
  509. return c <= 0, err
  510. }
  511. /*
  512. bool := |a| <= |b|
  513. Compares the magnitudes only, ignores the sign.
  514. */
  515. int_less_than_or_equal_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (less_than_or_equal: bool, err: Error) {
  516. assert_if_nil(a, b)
  517. context.allocator = allocator
  518. internal_clear_if_uninitialized(a, b) or_return
  519. c: int
  520. c, err = cmp_mag(a, b)
  521. return c <= 0, err
  522. }
  523. less_than_or_equal :: proc {
  524. int_less_than_or_equal,
  525. int_less_than_or_equal_digit,
  526. }
  527. lteq :: less_than_or_equal
  528. less_than_or_equal_abs :: proc {
  529. int_less_than_or_equal_abs,
  530. }
  531. lteq_abs :: less_than_or_equal_abs
  532. /*
  533. bool := a == b
  534. */
  535. int_equals :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (equals: bool, err: Error) {
  536. assert_if_nil(a, b)
  537. context.allocator = allocator
  538. internal_clear_if_uninitialized(a, b) or_return
  539. c: int
  540. c, err = cmp(a, b)
  541. return c == 0, err
  542. }
  543. /*
  544. bool := a == b
  545. */
  546. int_equals_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (equals: bool, err: Error) {
  547. assert_if_nil(a)
  548. context.allocator = allocator
  549. internal_clear_if_uninitialized(a) or_return
  550. c: int
  551. c, err = cmp(a, b)
  552. return c == 0, err
  553. }
  554. /*
  555. bool := |a| == |b|
  556. Compares the magnitudes only, ignores the sign.
  557. */
  558. int_equals_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (equals: bool, err: Error) {
  559. assert_if_nil(a, b)
  560. context.allocator = allocator
  561. internal_clear_if_uninitialized(a, b) or_return
  562. c: int
  563. c, err = cmp_mag(a, b)
  564. return c == 0, err
  565. }
  566. equals :: proc {
  567. int_equals,
  568. int_equals_digit,
  569. }
  570. eq :: equals
  571. equals_abs :: proc {
  572. int_equals_abs,
  573. }
  574. eq_abs :: equals_abs
  575. /*
  576. bool := a >= b
  577. */
  578. int_greater_than_or_equal :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (greater_than_or_equal: bool, err: Error) {
  579. assert_if_nil(a, b)
  580. context.allocator = allocator
  581. internal_clear_if_uninitialized(a, b) or_return
  582. c: int
  583. c, err = cmp(a, b)
  584. return c >= 0, err
  585. }
  586. /*
  587. bool := a >= b
  588. */
  589. int_greater_than_or_equal_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (greater_than_or_equal: bool, err: Error) {
  590. assert_if_nil(a)
  591. context.allocator = allocator
  592. internal_clear_if_uninitialized(a) or_return
  593. c: int
  594. c, err = cmp(a, b)
  595. return c >= 0, err
  596. }
  597. /*
  598. bool := |a| >= |b|
  599. Compares the magnitudes only, ignores the sign.
  600. */
  601. int_greater_than_or_equal_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (greater_than_or_equal: bool, err: Error) {
  602. assert_if_nil(a, b)
  603. context.allocator = allocator
  604. internal_clear_if_uninitialized(a, b) or_return
  605. c: int
  606. c, err = cmp_mag(a, b)
  607. return c >= 0, err
  608. }
  609. greater_than_or_equal :: proc {
  610. int_greater_than_or_equal,
  611. int_greater_than_or_equal_digit,
  612. }
  613. gteq :: greater_than_or_equal
  614. greater_than_or_equal_abs :: proc {
  615. int_greater_than_or_equal_abs,
  616. }
  617. gteq_abs :: greater_than_or_equal_abs
  618. /*
  619. bool := a > b
  620. */
  621. int_greater_than :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (greater_than: bool, err: Error) {
  622. assert_if_nil(a, b)
  623. context.allocator = allocator
  624. internal_clear_if_uninitialized(a, b) or_return
  625. c: int
  626. c, err = cmp(a, b)
  627. return c > 0, err
  628. }
  629. /*
  630. bool := a > b
  631. */
  632. int_greater_than_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (greater_than: bool, err: Error) {
  633. assert_if_nil(a)
  634. context.allocator = allocator
  635. internal_clear_if_uninitialized(a) or_return
  636. c: int
  637. c, err = cmp(a, b)
  638. return c > 0, err
  639. }
  640. /*
  641. bool := |a| > |b|
  642. Compares the magnitudes only, ignores the sign.
  643. */
  644. int_greater_than_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (greater_than: bool, err: Error) {
  645. assert_if_nil(a, b)
  646. context.allocator = allocator
  647. internal_clear_if_uninitialized(a, b) or_return
  648. c: int
  649. c, err = cmp_mag(a, b)
  650. return c > 0, err
  651. }
  652. greater_than :: proc {
  653. int_greater_than,
  654. int_greater_than_digit,
  655. }
  656. gt :: greater_than
  657. greater_than_abs :: proc {
  658. int_greater_than_abs,
  659. }
  660. gt_abs :: greater_than_abs
  661. /*
  662. Check if remainders are possible squares - fast exclude non-squares.
  663. Returns `true` if `a` is a square, `false` if not.
  664. Assumes `a` not to be `nil` and to have been initialized.
  665. */
  666. int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (square: bool, err: Error) {
  667. assert_if_nil(a)
  668. context.allocator = allocator
  669. internal_clear_if_uninitialized(a) or_return
  670. return #force_inline internal_int_is_square(a)
  671. }