public.odin 23 KB

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