public.odin 22 KB

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