rat.odin 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. package math_big
  2. import "base:builtin"
  3. import "base:intrinsics"
  4. import "core:math"
  5. Rat :: struct {
  6. a, b: Int,
  7. }
  8. rat_set_f64 :: proc(dst: ^Rat, f: f64, allocator := context.allocator) -> (err: Error) {
  9. assert_if_nil(dst)
  10. context.allocator = allocator
  11. EXP_MASK :: 1<<11 - 1
  12. bits := transmute(u64)f
  13. mantissa := bits & (1<<52 - 1)
  14. exp := int((bits>>52) & EXP_MASK)
  15. int_set_from_integer(&dst.b, 1) or_return
  16. switch exp {
  17. case EXP_MASK:
  18. dst.a.flags += {.Inf}
  19. return
  20. case 0:
  21. exp -= 1022
  22. case:
  23. mantissa |= 1<<52
  24. exp -= 1023
  25. }
  26. shift := 52 - exp
  27. for mantissa&1 == 0 && shift > 0 {
  28. mantissa >>= 1
  29. shift -= 1
  30. }
  31. int_set_from_integer(&dst.a, mantissa) or_return
  32. dst.a.sign = .Negative if f < 0 else .Zero_or_Positive
  33. if shift > 0 {
  34. internal_int_shl(&dst.b, &dst.b, shift) or_return
  35. } else {
  36. internal_int_shl(&dst.a, &dst.a, -shift) or_return
  37. }
  38. return internal_rat_norm(dst)
  39. }
  40. rat_set_f32 :: proc(dst: ^Rat, f: f32, allocator := context.allocator) -> (err: Error) {
  41. return rat_set_f64(dst, f64(f), allocator)
  42. }
  43. rat_set_f16 :: proc(dst: ^Rat, f: f16, allocator := context.allocator) -> (err: Error) {
  44. return rat_set_f64(dst, f64(f), allocator)
  45. }
  46. rat_set_frac :: proc{rat_set_frac_digit, rat_set_frac_int}
  47. rat_set_frac_digit :: proc(dst: ^Rat, a, b: DIGIT, allocator := context.allocator) -> (err: Error) {
  48. assert_if_nil(dst)
  49. if b == 0 {
  50. return .Division_by_Zero
  51. }
  52. context.allocator = allocator
  53. internal_set(&dst.a, a) or_return
  54. internal_set(&dst.b, b) or_return
  55. return internal_rat_norm(dst)
  56. }
  57. rat_set_frac_int :: proc(dst: ^Rat, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
  58. assert_if_nil(dst)
  59. assert_if_nil(a, b)
  60. if internal_is_zero(b) {
  61. return .Division_by_Zero
  62. }
  63. context.allocator = allocator
  64. internal_set(&dst.a, a) or_return
  65. internal_set(&dst.b, b) or_return
  66. return internal_rat_norm(dst)
  67. }
  68. rat_set_int :: proc(dst: ^Rat, a: ^Int, allocator := context.allocator) -> (err: Error) {
  69. assert_if_nil(dst)
  70. assert_if_nil(a)
  71. context.allocator = allocator
  72. internal_set(&dst.a, a) or_return
  73. internal_set(&dst.b, 1) or_return
  74. return
  75. }
  76. rat_set_digit :: proc(dst: ^Rat, a: DIGIT, allocator := context.allocator) -> (err: Error) {
  77. assert_if_nil(dst)
  78. context.allocator = allocator
  79. internal_set(&dst.a, a) or_return
  80. internal_set(&dst.b, 1) or_return
  81. return
  82. }
  83. rat_set_rat :: proc(dst, x: ^Rat, allocator := context.allocator) -> (err: Error) {
  84. assert_if_nil(dst, x)
  85. context.allocator = allocator
  86. internal_set(&dst.a, &x.a) or_return
  87. internal_set(&dst.b, &x.b) or_return
  88. return
  89. }
  90. rat_set_u64 :: proc(dst: ^Rat, x: u64, allocator := context.allocator) -> (err: Error) {
  91. assert_if_nil(dst)
  92. context.allocator = allocator
  93. internal_set(&dst.a, x) or_return
  94. internal_set(&dst.b, 1) or_return
  95. return
  96. }
  97. rat_set_i64 :: proc(dst: ^Rat, x: i64, allocator := context.allocator) -> (err: Error) {
  98. assert_if_nil(dst)
  99. context.allocator = allocator
  100. internal_set(&dst.a, x) or_return
  101. internal_set(&dst.b, 1) or_return
  102. return
  103. }
  104. rat_copy :: proc(dst, src: ^Rat, minimize := false, allocator := context.allocator) -> (err: Error) {
  105. if (dst == src) { return nil }
  106. assert_if_nil(dst, src)
  107. context.allocator = allocator
  108. int_copy(&dst.a, &src.a, minimize, allocator) or_return
  109. int_copy(&dst.b, &src.b, minimize, allocator) or_return
  110. internal_rat_norm(dst) or_return
  111. return nil
  112. }
  113. internal_rat_destroy :: proc(rationals: ..^Rat) {
  114. rationals := rationals
  115. for &z in rationals {
  116. internal_int_destroy(&z.a, &z.b)
  117. }
  118. }
  119. internal_rat_norm :: proc(z: ^Rat, allocator := context.allocator) -> (err: Error) {
  120. assert_if_nil(z)
  121. context.allocator = allocator
  122. switch {
  123. case internal_is_zero(&z.a):
  124. z.a.sign = .Zero_or_Positive
  125. fallthrough
  126. case internal_is_zero(&z.b):
  127. int_set_from_integer(&z.b, 1) or_return
  128. case:
  129. sign := z.a.sign
  130. z.a.sign = .Zero_or_Positive
  131. z.b.sign = .Zero_or_Positive
  132. f := &Int{}
  133. defer internal_int_destroy(f)
  134. internal_int_gcd(f, &z.a, &z.b) or_return
  135. if !internal_int_equals_digit(f, 1) {
  136. f.sign = .Zero_or_Positive
  137. internal_int_div(&z.a, &z.a, f) or_return
  138. internal_int_div(&z.b, &z.b, f) or_return
  139. }
  140. z.a.sign = sign
  141. }
  142. return
  143. }
  144. rat_swap :: proc(a, b: ^Rat) {
  145. assert_if_nil(a, b)
  146. #force_inline internal_swap(a, b)
  147. }
  148. internal_rat_swap :: #force_inline proc(a, b: ^Rat) {
  149. internal_int_swap(&a.a, &b.a)
  150. internal_int_swap(&a.b, &b.b)
  151. }
  152. rat_sign :: proc(z: ^Rat) -> Sign {
  153. if z == nil {
  154. return .Zero_or_Positive
  155. }
  156. return z.a.sign
  157. }
  158. rat_is_int :: proc(z: ^Rat) -> bool {
  159. assert_if_nil(z)
  160. return internal_is_zero(&z.a) || internal_int_equals_digit(&z.b, 1)
  161. }
  162. rat_is_zero :: proc(z: ^Rat) -> bool {
  163. return internal_rat_is_zero(z)
  164. }
  165. internal_rat_is_zero :: #force_inline proc(z: ^Rat) -> bool {
  166. assert_if_nil(z)
  167. return internal_is_zero(&z.a)
  168. }
  169. internal_int_mul_denom :: proc(dst, x, y: ^Int, allocator := context.allocator) -> (err: Error) {
  170. assert_if_nil(dst, x, y)
  171. context.allocator = allocator
  172. switch {
  173. case internal_is_zero(x) && internal_is_zero(y):
  174. return internal_set(dst, 1)
  175. case internal_is_zero(x):
  176. return internal_set(dst, y)
  177. case internal_is_zero(y):
  178. return internal_set(dst, x)
  179. }
  180. return int_mul(dst, x, y)
  181. }
  182. internal_int_scale_denom :: proc(dst, x, y: ^Int, allocator := context.allocator) -> (err: Error) {
  183. assert_if_nil(dst, x, y)
  184. if internal_is_zero(y) {
  185. return internal_set(dst, x)
  186. }
  187. int_mul(dst, x, y) or_return
  188. dst.sign = x.sign
  189. return
  190. }
  191. rat_add_rat :: proc(dst, x, y: ^Rat, allocator := context.allocator) -> (err: Error) {
  192. assert_if_nil(dst, x, y)
  193. context.allocator = allocator
  194. a1, a2: Int
  195. defer internal_destroy(&a1, &a2)
  196. internal_int_scale_denom(&a1, &x.a, &y.b) or_return
  197. internal_int_scale_denom(&a2, &y.a, &x.b) or_return
  198. int_add(&dst.a, &a1, &a2) or_return
  199. internal_int_mul_denom(&dst.b, &x.b, &y.b) or_return
  200. return internal_rat_norm(dst)
  201. }
  202. rat_sub_rat :: proc(dst, x, y: ^Rat, allocator := context.allocator) -> (err: Error) {
  203. assert_if_nil(dst, x, y)
  204. context.allocator = allocator
  205. a1, a2 := &Int{}, &Int{}
  206. defer internal_destroy(a1, a2)
  207. internal_int_scale_denom(a1, &x.a, &y.b) or_return
  208. internal_int_scale_denom(a2, &y.a, &x.b) or_return
  209. int_sub(&dst.a, a1, a2) or_return
  210. internal_int_mul_denom(&dst.b, &x.b, &y.b) or_return
  211. return internal_rat_norm(dst)
  212. }
  213. rat_mul_rat :: proc(dst, x, y: ^Rat, allocator := context.allocator) -> (err: Error) {
  214. assert_if_nil(dst, x, y)
  215. context.allocator = allocator
  216. if x == y {
  217. internal_sqr(&dst.a, &x.a) or_return
  218. if internal_is_zero(&x.b) {
  219. internal_set(&dst.b, 1) or_return
  220. } else {
  221. internal_sqr(&dst.a, &x.b) or_return
  222. }
  223. return
  224. }
  225. int_mul(&dst.a, &x.a, &y.a) or_return
  226. internal_int_mul_denom(&dst.b, &x.b, &y.b) or_return
  227. return internal_rat_norm(dst)
  228. }
  229. rat_div_rat :: proc(dst, x, y: ^Rat, allocator := context.allocator) -> (err: Error) {
  230. if internal_rat_is_zero(y) {
  231. return .Division_by_Zero
  232. }
  233. context.allocator = allocator
  234. a, b := &Int{}, &Int{}
  235. defer internal_destroy(a, b)
  236. internal_int_scale_denom(a, &x.a, &y.b) or_return
  237. internal_int_scale_denom(b, &y.a, &x.b) or_return
  238. internal_set(&dst.a, a) or_return
  239. internal_set(&dst.b, b) or_return
  240. internal_int_abs(&dst.a, &dst.a)
  241. internal_int_abs(&dst.b, &dst.b)
  242. dst.a.sign = .Negative if a.sign != b.sign else .Zero_or_Positive
  243. return internal_rat_norm(dst)
  244. }
  245. rat_abs :: proc(dst, x: ^Rat, allocator := context.allocator) -> (err: Error) {
  246. rat_set_rat(dst, x, allocator) or_return
  247. internal_abs(&dst.a, &dst.a, allocator) or_return
  248. return
  249. }
  250. rat_neg :: proc(dst, x: ^Rat, allocator := context.allocator) -> (err: Error) {
  251. rat_set_rat(dst, x, allocator) or_return
  252. internal_neg(&dst.a, &dst.a, allocator) or_return
  253. return
  254. }
  255. rat_is_positive :: proc(z: ^Rat, allocator := context.allocator) -> (ok: bool, err: Error) {
  256. assert_if_nil(z)
  257. a := int_is_positive(&z.a, allocator) or_return
  258. b := int_is_positive(&z.b, allocator) or_return
  259. return !(a ~ b), nil
  260. }
  261. rat_is_negative :: proc(z: ^Rat, allocator := context.allocator) -> (ok: bool, err: Error) {
  262. assert_if_nil(z)
  263. a := int_is_positive(&z.a, allocator) or_return
  264. b := int_is_positive(&z.b, allocator) or_return
  265. return (a ~ b), nil
  266. }
  267. rat_is_even :: proc(z: ^Rat, allocator := context.allocator) -> (ok: bool, err: Error) {
  268. assert_if_nil(z)
  269. if rat_is_int(z) {
  270. return int_is_even(&z.a, allocator)
  271. }
  272. return false, nil
  273. }
  274. rat_is_odd :: proc(z: ^Rat, allocator := context.allocator) -> (ok: bool, err: Error) {
  275. assert_if_nil(z)
  276. if rat_is_int(z) {
  277. return int_is_odd(&z.a, allocator)
  278. }
  279. return false, nil
  280. }
  281. rat_to_f16 :: proc(z: ^Rat, allocator := context.allocator) -> (f: f16, exact: bool, err: Error) {
  282. assert_if_nil(z)
  283. return internal_rat_to_float(f16, z, allocator)
  284. }
  285. rat_to_f32 :: proc(z: ^Rat, allocator := context.allocator) -> (f: f32, exact: bool, err: Error) {
  286. assert_if_nil(z)
  287. return internal_rat_to_float(f32, z, allocator)
  288. }
  289. rat_to_f64 :: proc(z: ^Rat, allocator := context.allocator) -> (f: f64, exact: bool, err: Error) {
  290. assert_if_nil(z)
  291. return internal_rat_to_float(f64, z, allocator)
  292. }
  293. internal_rat_to_float :: proc($T: typeid, z: ^Rat, allocator := context.allocator) -> (f: T, exact: bool, err: Error) where intrinsics.type_is_float(T) {
  294. FSIZE :: 8*size_of(T)
  295. when FSIZE == 16 {
  296. MSIZE :: 10
  297. } else when FSIZE == 32 {
  298. MSIZE :: 23
  299. } else when FSIZE == 64 {
  300. MSIZE :: 52
  301. } else {
  302. #panic("unsupported float type")
  303. }
  304. MSIZE1 :: MSIZE+1
  305. MSIZE2 :: MSIZE+2
  306. ESIZE :: FSIZE - MSIZE1
  307. EBIAS :: 1<<(ESIZE-1) - 1
  308. EMIN :: 1 - EBIAS
  309. EMAX :: EBIAS
  310. assert_if_nil(z)
  311. a, b := &z.a, &z.b
  312. context.allocator = allocator
  313. alen := internal_count_bits(a)
  314. if alen == 0 {
  315. return 0, true, nil
  316. }
  317. blen := internal_count_bits(b)
  318. if blen == 0 {
  319. return T(math.nan_f64()), false, .Division_by_Zero
  320. }
  321. has_sign := a.sign != b.sign
  322. exp := alen - blen
  323. a2, b2 := &Int{}, &Int{}
  324. defer internal_destroy(a2, b2)
  325. internal_int_abs(a2, a) or_return
  326. internal_int_abs(b2, b) or_return
  327. if shift := MSIZE2 - exp; shift > 0 {
  328. internal_int_shl(a2, a2, shift) or_return
  329. } else if shift < 0 {
  330. internal_int_shl(b2, b2, -shift) or_return
  331. }
  332. q, r := &Int{}, &Int{}
  333. defer internal_destroy(q, r)
  334. internal_int_divmod(q, r, a2, b2) or_return
  335. has_rem := !internal_is_zero(r)
  336. mantissa := internal_int_get_u64(q) or_return
  337. if mantissa>>MSIZE2 == 1 {
  338. if mantissa&1 == 1 {
  339. has_rem = true
  340. }
  341. mantissa >>= 1
  342. exp += 1
  343. }
  344. assert(mantissa>>MSIZE1 == 1, "invalid bit result")
  345. if EMIN-MSIZE <= exp && exp <= EMIN {
  346. shift := uint(EMIN - (exp - 1))
  347. lost_bits := mantissa & (1<<shift - 1)
  348. has_rem ||= lost_bits != 0
  349. mantissa >>= shift
  350. exp = 2 - EBIAS // exp + shift
  351. }
  352. exact = !has_rem
  353. if mantissa&1 != 0 {
  354. exact = false
  355. if has_rem || mantissa&2 != 0 {
  356. mantissa += 1
  357. if mantissa >= 1<<MSIZE2 {
  358. mantissa >>= 1
  359. exp += 1
  360. }
  361. }
  362. }
  363. mantissa >>= 1
  364. f = T(math.ldexp(f64(mantissa), exp-MSIZE1))
  365. if math.is_inf(f, 0) {
  366. exact = false
  367. }
  368. if has_sign {
  369. f = -builtin.abs(f)
  370. }
  371. return
  372. }
  373. rat_compare :: proc(x, y: ^Rat, allocator := context.allocator) -> (comparison: int, error: Error) {
  374. assert_if_nil(x, y)
  375. context.allocator = allocator
  376. a, b: Int
  377. internal_init_multi(&a, &b) or_return
  378. defer internal_destroy(&a, &b)
  379. internal_int_scale_denom(&a, &x.a, &y.b) or_return
  380. internal_int_scale_denom(&b, &y.a, &x.b) or_return
  381. return int_compare(&a, &b)
  382. }
  383. rat_add_int :: proc(dst, x: ^Rat, y: ^Int, allocator := context.allocator) -> (err: Error) {
  384. assert_if_nil(dst, x)
  385. assert_if_nil(y)
  386. z: Rat
  387. rat_set_int(&z, y, allocator) or_return
  388. defer internal_destroy(&z)
  389. return rat_add_rat(dst, x, &z, allocator)
  390. }
  391. rat_sub_int :: proc(dst, x: ^Rat, y: ^Int, allocator := context.allocator) -> (err: Error) {
  392. assert_if_nil(dst, x)
  393. assert_if_nil(y)
  394. z: Rat
  395. rat_set_int(&z, y, allocator) or_return
  396. defer internal_destroy(&z)
  397. return rat_sub_rat(dst, x, &z, allocator)
  398. }
  399. rat_mul_int :: proc(dst, x: ^Rat, y: ^Int, allocator := context.allocator) -> (err: Error) {
  400. assert_if_nil(dst, x)
  401. assert_if_nil(y)
  402. z: Rat
  403. rat_set_int(&z, y, allocator) or_return
  404. defer internal_destroy(&z)
  405. return rat_mul_rat(dst, x, &z, allocator)
  406. }
  407. rat_div_int :: proc(dst, x: ^Rat, y: ^Int, allocator := context.allocator) -> (err: Error) {
  408. if internal_is_zero(y) {
  409. return .Division_by_Zero
  410. }
  411. z: Rat
  412. rat_set_int(&z, y, allocator) or_return
  413. defer internal_destroy(&z)
  414. return rat_div_rat(dst, x, &z, allocator)
  415. }
  416. int_add_rat :: proc(dst: ^Rat, x: ^Int, y: ^Rat, allocator := context.allocator) -> (err: Error) {
  417. assert_if_nil(x)
  418. assert_if_nil(dst, y)
  419. w: Rat
  420. rat_set_int(&w, x, allocator) or_return
  421. defer internal_destroy(&w)
  422. return rat_add_rat(dst, &w, y, allocator)
  423. }
  424. int_sub_rat :: proc(dst: ^Rat, x: ^Int, y: ^Rat, allocator := context.allocator) -> (err: Error) {
  425. assert_if_nil(x)
  426. assert_if_nil(dst, y)
  427. w: Rat
  428. rat_set_int(&w, x, allocator) or_return
  429. defer internal_destroy(&w)
  430. return rat_sub_rat(dst, &w, y, allocator)
  431. }
  432. int_mul_rat :: proc(dst: ^Rat, x: ^Int, y: ^Rat, allocator := context.allocator) -> (err: Error) {
  433. assert_if_nil(x)
  434. assert_if_nil(dst, y)
  435. w: Rat
  436. rat_set_int(&w, x, allocator) or_return
  437. defer internal_destroy(&w)
  438. return rat_mul_rat(dst, &w, y, allocator)
  439. }
  440. int_div_rat :: proc(dst: ^Rat, x: ^Int, y: ^Rat, allocator := context.allocator) -> (err: Error) {
  441. if internal_is_zero(y) {
  442. return .Division_by_Zero
  443. }
  444. w: Rat
  445. rat_set_int(&w, x, allocator) or_return
  446. defer internal_destroy(&w)
  447. return rat_div_rat(dst, &w, y, allocator)
  448. }