internal.odin 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. package runtime
  2. import "core:intrinsics"
  3. @(private)
  4. byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte #no_bounds_check {
  5. return ([^]byte)(data)[:max(len, 0)]
  6. }
  7. bswap_16 :: proc "contextless" (x: u16) -> u16 {
  8. return x>>8 | x<<8
  9. }
  10. bswap_32 :: proc "contextless" (x: u32) -> u32 {
  11. return x>>24 | (x>>8)&0xff00 | (x<<8)&0xff0000 | x<<24
  12. }
  13. bswap_64 :: proc "contextless" (x: u64) -> u64 {
  14. z := x
  15. z = (z & 0x00000000ffffffff) << 32 | (z & 0xffffffff00000000) >> 32
  16. z = (z & 0x0000ffff0000ffff) << 16 | (z & 0xffff0000ffff0000) >> 16
  17. z = (z & 0x00ff00ff00ff00ff) << 8 | (z & 0xff00ff00ff00ff00) >> 8
  18. return z
  19. }
  20. bswap_128 :: proc "contextless" (x: u128) -> u128 {
  21. z := transmute([4]u32)x
  22. z[0] = bswap_32(z[3])
  23. z[1] = bswap_32(z[2])
  24. z[2] = bswap_32(z[1])
  25. z[3] = bswap_32(z[0])
  26. return transmute(u128)z
  27. }
  28. bswap_f16 :: proc "contextless" (f: f16) -> f16 {
  29. x := transmute(u16)f
  30. z := bswap_16(x)
  31. return transmute(f16)z
  32. }
  33. bswap_f32 :: proc "contextless" (f: f32) -> f32 {
  34. x := transmute(u32)f
  35. z := bswap_32(x)
  36. return transmute(f32)z
  37. }
  38. bswap_f64 :: proc "contextless" (f: f64) -> f64 {
  39. x := transmute(u64)f
  40. z := bswap_64(x)
  41. return transmute(f64)z
  42. }
  43. is_power_of_two_int :: #force_inline proc(x: int) -> bool {
  44. if x <= 0 {
  45. return false
  46. }
  47. return (x & (x-1)) == 0
  48. }
  49. align_forward_int :: #force_inline proc(ptr, align: int) -> int {
  50. assert(is_power_of_two_int(align))
  51. p := ptr
  52. modulo := p & (align-1)
  53. if modulo != 0 {
  54. p += align - modulo
  55. }
  56. return p
  57. }
  58. is_power_of_two_uintptr :: #force_inline proc(x: uintptr) -> bool {
  59. if x <= 0 {
  60. return false
  61. }
  62. return (x & (x-1)) == 0
  63. }
  64. align_forward_uintptr :: #force_inline proc(ptr, align: uintptr) -> uintptr {
  65. assert(is_power_of_two_uintptr(align))
  66. p := ptr
  67. modulo := p & (align-1)
  68. if modulo != 0 {
  69. p += align - modulo
  70. }
  71. return p
  72. }
  73. mem_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
  74. if data == nil {
  75. return nil
  76. }
  77. if len < 0 {
  78. return data
  79. }
  80. intrinsics.mem_zero(data, len)
  81. return data
  82. }
  83. mem_copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
  84. if src == nil {
  85. return dst
  86. }
  87. // NOTE(bill): This _must_ be implemented like C's memmove
  88. intrinsics.mem_copy(dst, src, len)
  89. return dst
  90. }
  91. mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
  92. if src == nil {
  93. return dst
  94. }
  95. // NOTE(bill): This _must_ be implemented like C's memcpy
  96. intrinsics.mem_copy_non_overlapping(dst, src, len)
  97. return dst
  98. }
  99. DEFAULT_ALIGNMENT :: 2*align_of(rawptr)
  100. mem_alloc_bytes :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
  101. if size == 0 {
  102. return nil, nil
  103. }
  104. if allocator.procedure == nil {
  105. return nil, nil
  106. }
  107. return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc)
  108. }
  109. mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (rawptr, Allocator_Error) {
  110. if size == 0 {
  111. return nil, nil
  112. }
  113. if allocator.procedure == nil {
  114. return nil, nil
  115. }
  116. data, err := allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc)
  117. return raw_data(data), err
  118. }
  119. mem_free :: #force_inline proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
  120. if ptr == nil {
  121. return .None
  122. }
  123. if allocator.procedure == nil {
  124. return .None
  125. }
  126. _, err := allocator.procedure(allocator.data, .Free, 0, 0, ptr, 0, loc)
  127. return err
  128. }
  129. mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #caller_location) -> (err: Allocator_Error) {
  130. if allocator.procedure != nil {
  131. _, err = allocator.procedure(allocator.data, .Free_All, 0, 0, nil, 0, loc)
  132. }
  133. return
  134. }
  135. mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (new_ptr: rawptr, err: Allocator_Error) {
  136. new_data: []byte
  137. switch {
  138. case allocator.procedure == nil:
  139. return
  140. case new_size == 0:
  141. new_data, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, 0, loc)
  142. case ptr == nil:
  143. new_data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
  144. case:
  145. new_data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc)
  146. }
  147. new_ptr = raw_data(new_data)
  148. return
  149. }
  150. memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
  151. switch {
  152. case n == 0: return true
  153. case x == y: return true
  154. }
  155. a, b := ([^]byte)(x), ([^]byte)(y)
  156. length := uint(n)
  157. when size_of(uint) == 8 {
  158. if word_length := length >> 3; word_length != 0 {
  159. for i in 0..<word_length {
  160. if intrinsics.unaligned_load((^u64)(a)) != intrinsics.unaligned_load((^u64)(b)) {
  161. return false
  162. }
  163. a = a[size_of(u64):]
  164. b = b[size_of(u64):]
  165. }
  166. }
  167. if length & 4 != 0 {
  168. if intrinsics.unaligned_load((^u32)(a)) != intrinsics.unaligned_load((^u32)(b)) {
  169. return false
  170. }
  171. a = a[size_of(u32):]
  172. b = b[size_of(u32):]
  173. }
  174. if length & 2 != 0 {
  175. if intrinsics.unaligned_load((^u16)(a)) != intrinsics.unaligned_load((^u16)(b)) {
  176. return false
  177. }
  178. a = a[size_of(u16):]
  179. b = b[size_of(u16):]
  180. }
  181. if length & 1 != 0 && a[0] != b[0] {
  182. return false
  183. }
  184. return true
  185. } else {
  186. if word_length := length >> 2; word_length != 0 {
  187. for i in 0..<word_length {
  188. if intrinsics.unaligned_load((^u32)(a)) != intrinsics.unaligned_load((^u32)(b)) {
  189. return false
  190. }
  191. a = a[size_of(u32):]
  192. b = b[size_of(u32):]
  193. }
  194. }
  195. length &= 3
  196. if length != 0 {
  197. for i in 0..<length {
  198. if a[i] != b[i] {
  199. return false
  200. }
  201. }
  202. }
  203. return true
  204. }
  205. }
  206. memory_compare :: proc "contextless" (a, b: rawptr, n: int) -> int #no_bounds_check {
  207. switch {
  208. case a == b: return 0
  209. case a == nil: return -1
  210. case b == nil: return +1
  211. }
  212. x := uintptr(a)
  213. y := uintptr(b)
  214. n := uintptr(n)
  215. SU :: size_of(uintptr)
  216. fast := n/SU + 1
  217. offset := (fast-1)*SU
  218. curr_block := uintptr(0)
  219. if n < SU {
  220. fast = 0
  221. }
  222. for /**/; curr_block < fast; curr_block += 1 {
  223. va := (^uintptr)(x + curr_block * size_of(uintptr))^
  224. vb := (^uintptr)(y + curr_block * size_of(uintptr))^
  225. if va ~ vb != 0 {
  226. for pos := curr_block*SU; pos < n; pos += 1 {
  227. a := (^byte)(x+pos)^
  228. b := (^byte)(y+pos)^
  229. if a ~ b != 0 {
  230. return -1 if (int(a) - int(b)) < 0 else +1
  231. }
  232. }
  233. }
  234. }
  235. for /**/; offset < n; offset += 1 {
  236. a := (^byte)(x+offset)^
  237. b := (^byte)(y+offset)^
  238. if a ~ b != 0 {
  239. return -1 if (int(a) - int(b)) < 0 else +1
  240. }
  241. }
  242. return 0
  243. }
  244. memory_compare_zero :: proc "contextless" (a: rawptr, n: int) -> int #no_bounds_check {
  245. x := uintptr(a)
  246. n := uintptr(n)
  247. SU :: size_of(uintptr)
  248. fast := n/SU + 1
  249. offset := (fast-1)*SU
  250. curr_block := uintptr(0)
  251. if n < SU {
  252. fast = 0
  253. }
  254. for /**/; curr_block < fast; curr_block += 1 {
  255. va := (^uintptr)(x + curr_block * size_of(uintptr))^
  256. if va ~ 0 != 0 {
  257. for pos := curr_block*SU; pos < n; pos += 1 {
  258. a := (^byte)(x+pos)^
  259. if a ~ 0 != 0 {
  260. return -1 if int(a) < 0 else +1
  261. }
  262. }
  263. }
  264. }
  265. for /**/; offset < n; offset += 1 {
  266. a := (^byte)(x+offset)^
  267. if a ~ 0 != 0 {
  268. return -1 if int(a) < 0 else +1
  269. }
  270. }
  271. return 0
  272. }
  273. string_eq :: proc "contextless" (lhs, rhs: string) -> bool {
  274. x := transmute(Raw_String)lhs
  275. y := transmute(Raw_String)rhs
  276. if x.len != y.len {
  277. return false
  278. }
  279. return #force_inline memory_equal(x.data, y.data, x.len)
  280. }
  281. string_cmp :: proc "contextless" (a, b: string) -> int {
  282. x := transmute(Raw_String)a
  283. y := transmute(Raw_String)b
  284. return memory_compare(x.data, y.data, min(x.len, y.len))
  285. }
  286. string_ne :: #force_inline proc "contextless" (a, b: string) -> bool { return !string_eq(a, b) }
  287. string_lt :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) < 0 }
  288. string_gt :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) > 0 }
  289. string_le :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) <= 0 }
  290. string_ge :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) >= 0 }
  291. cstring_len :: proc "contextless" (s: cstring) -> int {
  292. p0 := uintptr((^byte)(s))
  293. p := p0
  294. for p != 0 && (^byte)(p)^ != 0 {
  295. p += 1
  296. }
  297. return int(p - p0)
  298. }
  299. cstring_to_string :: proc "contextless" (s: cstring) -> string {
  300. if s == nil {
  301. return ""
  302. }
  303. ptr := (^byte)(s)
  304. n := cstring_len(s)
  305. return transmute(string)Raw_String{ptr, n}
  306. }
  307. complex32_eq :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) == real(b) && imag(a) == imag(b) }
  308. complex32_ne :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) != real(b) || imag(a) != imag(b) }
  309. complex64_eq :: #force_inline proc "contextless" (a, b: complex64) -> bool { return real(a) == real(b) && imag(a) == imag(b) }
  310. complex64_ne :: #force_inline proc "contextless" (a, b: complex64) -> bool { return real(a) != real(b) || imag(a) != imag(b) }
  311. complex128_eq :: #force_inline proc "contextless" (a, b: complex128) -> bool { return real(a) == real(b) && imag(a) == imag(b) }
  312. complex128_ne :: #force_inline proc "contextless" (a, b: complex128) -> bool { return real(a) != real(b) || imag(a) != imag(b) }
  313. quaternion64_eq :: #force_inline proc "contextless" (a, b: quaternion64) -> bool { return real(a) == real(b) && imag(a) == imag(b) && jmag(a) == jmag(b) && kmag(a) == kmag(b) }
  314. quaternion64_ne :: #force_inline proc "contextless" (a, b: quaternion64) -> bool { return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b) }
  315. quaternion128_eq :: #force_inline proc "contextless" (a, b: quaternion128) -> bool { return real(a) == real(b) && imag(a) == imag(b) && jmag(a) == jmag(b) && kmag(a) == kmag(b) }
  316. quaternion128_ne :: #force_inline proc "contextless" (a, b: quaternion128) -> bool { return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b) }
  317. quaternion256_eq :: #force_inline proc "contextless" (a, b: quaternion256) -> bool { return real(a) == real(b) && imag(a) == imag(b) && jmag(a) == jmag(b) && kmag(a) == kmag(b) }
  318. quaternion256_ne :: #force_inline proc "contextless" (a, b: quaternion256) -> bool { return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b) }
  319. string_decode_rune :: #force_inline proc "contextless" (s: string) -> (rune, int) {
  320. // NOTE(bill): Duplicated here to remove dependency on package unicode/utf8
  321. @static accept_sizes := [256]u8{
  322. 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x00-0x0f
  323. 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x10-0x1f
  324. 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x20-0x2f
  325. 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x30-0x3f
  326. 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x40-0x4f
  327. 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x50-0x5f
  328. 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x60-0x6f
  329. 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x70-0x7f
  330. 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0x80-0x8f
  331. 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0x90-0x9f
  332. 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xa0-0xaf
  333. 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xb0-0xbf
  334. 0xf1, 0xf1, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xc0-0xcf
  335. 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xd0-0xdf
  336. 0x13, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x23, 0x03, 0x03, // 0xe0-0xef
  337. 0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff
  338. }
  339. Accept_Range :: struct {lo, hi: u8}
  340. @static accept_ranges := [5]Accept_Range{
  341. {0x80, 0xbf},
  342. {0xa0, 0xbf},
  343. {0x80, 0x9f},
  344. {0x90, 0xbf},
  345. {0x80, 0x8f},
  346. }
  347. MASKX :: 0b0011_1111
  348. MASK2 :: 0b0001_1111
  349. MASK3 :: 0b0000_1111
  350. MASK4 :: 0b0000_0111
  351. LOCB :: 0b1000_0000
  352. HICB :: 0b1011_1111
  353. RUNE_ERROR :: '\ufffd'
  354. n := len(s)
  355. if n < 1 {
  356. return RUNE_ERROR, 0
  357. }
  358. s0 := s[0]
  359. x := accept_sizes[s0]
  360. if x >= 0xF0 {
  361. mask := rune(x) << 31 >> 31 // NOTE(bill): Create 0x0000 or 0xffff.
  362. return rune(s[0])&~mask | RUNE_ERROR&mask, 1
  363. }
  364. sz := x & 7
  365. accept := accept_ranges[x>>4]
  366. if n < int(sz) {
  367. return RUNE_ERROR, 1
  368. }
  369. b1 := s[1]
  370. if b1 < accept.lo || accept.hi < b1 {
  371. return RUNE_ERROR, 1
  372. }
  373. if sz == 2 {
  374. return rune(s0&MASK2)<<6 | rune(b1&MASKX), 2
  375. }
  376. b2 := s[2]
  377. if b2 < LOCB || HICB < b2 {
  378. return RUNE_ERROR, 1
  379. }
  380. if sz == 3 {
  381. return rune(s0&MASK3)<<12 | rune(b1&MASKX)<<6 | rune(b2&MASKX), 3
  382. }
  383. b3 := s[3]
  384. if b3 < LOCB || HICB < b3 {
  385. return RUNE_ERROR, 1
  386. }
  387. return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4
  388. }
  389. abs_f16 :: #force_inline proc "contextless" (x: f16) -> f16 {
  390. return -x if x < 0 else x
  391. }
  392. abs_f32 :: #force_inline proc "contextless" (x: f32) -> f32 {
  393. return -x if x < 0 else x
  394. }
  395. abs_f64 :: #force_inline proc "contextless" (x: f64) -> f64 {
  396. return -x if x < 0 else x
  397. }
  398. min_f16 :: #force_inline proc "contextless" (a, b: f16) -> f16 {
  399. return a if a < b else b
  400. }
  401. min_f32 :: #force_inline proc "contextless" (a, b: f32) -> f32 {
  402. return a if a < b else b
  403. }
  404. min_f64 :: #force_inline proc "contextless" (a, b: f64) -> f64 {
  405. return a if a < b else b
  406. }
  407. max_f16 :: #force_inline proc "contextless" (a, b: f16) -> f16 {
  408. return a if a > b else b
  409. }
  410. max_f32 :: #force_inline proc "contextless" (a, b: f32) -> f32 {
  411. return a if a > b else b
  412. }
  413. max_f64 :: #force_inline proc "contextless" (a, b: f64) -> f64 {
  414. return a if a > b else b
  415. }
  416. abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 {
  417. r, i := real(x), imag(x)
  418. return f16(intrinsics.sqrt(f32(r*r + i*i)))
  419. }
  420. abs_complex64 :: #force_inline proc "contextless" (x: complex64) -> f32 {
  421. r, i := real(x), imag(x)
  422. return intrinsics.sqrt(r*r + i*i)
  423. }
  424. abs_complex128 :: #force_inline proc "contextless" (x: complex128) -> f64 {
  425. r, i := real(x), imag(x)
  426. return intrinsics.sqrt(r*r + i*i)
  427. }
  428. abs_quaternion64 :: #force_inline proc "contextless" (x: quaternion64) -> f16 {
  429. r, i, j, k := real(x), imag(x), jmag(x), kmag(x)
  430. return f16(intrinsics.sqrt(f32(r*r + i*i + j*j + k*k)))
  431. }
  432. abs_quaternion128 :: #force_inline proc "contextless" (x: quaternion128) -> f32 {
  433. r, i, j, k := real(x), imag(x), jmag(x), kmag(x)
  434. return intrinsics.sqrt(r*r + i*i + j*j + k*k)
  435. }
  436. abs_quaternion256 :: #force_inline proc "contextless" (x: quaternion256) -> f64 {
  437. r, i, j, k := real(x), imag(x), jmag(x), kmag(x)
  438. return intrinsics.sqrt(r*r + i*i + j*j + k*k)
  439. }
  440. quo_complex32 :: proc "contextless" (n, m: complex32) -> complex32 {
  441. e, f: f16
  442. if abs(real(m)) >= abs(imag(m)) {
  443. ratio := imag(m) / real(m)
  444. denom := real(m) + ratio*imag(m)
  445. e = (real(n) + imag(n)*ratio) / denom
  446. f = (imag(n) - real(n)*ratio) / denom
  447. } else {
  448. ratio := real(m) / imag(m)
  449. denom := imag(m) + ratio*real(m)
  450. e = (real(n)*ratio + imag(n)) / denom
  451. f = (imag(n)*ratio - real(n)) / denom
  452. }
  453. return complex(e, f)
  454. }
  455. quo_complex64 :: proc "contextless" (n, m: complex64) -> complex64 {
  456. e, f: f32
  457. if abs(real(m)) >= abs(imag(m)) {
  458. ratio := imag(m) / real(m)
  459. denom := real(m) + ratio*imag(m)
  460. e = (real(n) + imag(n)*ratio) / denom
  461. f = (imag(n) - real(n)*ratio) / denom
  462. } else {
  463. ratio := real(m) / imag(m)
  464. denom := imag(m) + ratio*real(m)
  465. e = (real(n)*ratio + imag(n)) / denom
  466. f = (imag(n)*ratio - real(n)) / denom
  467. }
  468. return complex(e, f)
  469. }
  470. quo_complex128 :: proc "contextless" (n, m: complex128) -> complex128 {
  471. e, f: f64
  472. if abs(real(m)) >= abs(imag(m)) {
  473. ratio := imag(m) / real(m)
  474. denom := real(m) + ratio*imag(m)
  475. e = (real(n) + imag(n)*ratio) / denom
  476. f = (imag(n) - real(n)*ratio) / denom
  477. } else {
  478. ratio := real(m) / imag(m)
  479. denom := imag(m) + ratio*real(m)
  480. e = (real(n)*ratio + imag(n)) / denom
  481. f = (imag(n)*ratio - real(n)) / denom
  482. }
  483. return complex(e, f)
  484. }
  485. mul_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
  486. q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q)
  487. r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r)
  488. t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3
  489. t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2
  490. t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1
  491. t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0
  492. return quaternion(t0, t1, t2, t3)
  493. }
  494. mul_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
  495. q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q)
  496. r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r)
  497. t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3
  498. t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2
  499. t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1
  500. t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0
  501. return quaternion(t0, t1, t2, t3)
  502. }
  503. mul_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
  504. q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q)
  505. r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r)
  506. t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3
  507. t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2
  508. t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1
  509. t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0
  510. return quaternion(t0, t1, t2, t3)
  511. }
  512. quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
  513. q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q)
  514. r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r)
  515. invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3)
  516. t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2
  517. t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2
  518. t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2
  519. t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2
  520. return quaternion(t0, t1, t2, t3)
  521. }
  522. quo_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
  523. q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q)
  524. r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r)
  525. invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3)
  526. t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2
  527. t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2
  528. t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2
  529. t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2
  530. return quaternion(t0, t1, t2, t3)
  531. }
  532. quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
  533. q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q)
  534. r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r)
  535. invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3)
  536. t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2
  537. t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2
  538. t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2
  539. t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2
  540. return quaternion(t0, t1, t2, t3)
  541. }
  542. @(link_name="__truncsfhf2")
  543. truncsfhf2 :: proc "c" (value: f32) -> u16 {
  544. v: struct #raw_union { i: u32, f: f32 }
  545. i, s, e, m: i32
  546. v.f = value
  547. i = i32(v.i)
  548. s = (i >> 16) & 0x00008000
  549. e = ((i >> 23) & 0x000000ff) - (127 - 15)
  550. m = i & 0x007fffff
  551. if e <= 0 {
  552. if e < -10 {
  553. return u16(s)
  554. }
  555. m = (m | 0x00800000) >> u32(1 - e)
  556. if m & 0x00001000 != 0 {
  557. m += 0x00002000
  558. }
  559. return u16(s | (m >> 13))
  560. } else if e == 0xff - (127 - 15) {
  561. if m == 0 {
  562. return u16(s | 0x7c00) /* NOTE(bill): infinity */
  563. } else {
  564. /* NOTE(bill): NAN */
  565. m >>= 13
  566. return u16(s | 0x7c00 | m | i32(m == 0))
  567. }
  568. } else {
  569. if m & 0x00001000 != 0 {
  570. m += 0x00002000
  571. if (m & 0x00800000) != 0 {
  572. m = 0
  573. e += 1
  574. }
  575. }
  576. if e > 30 {
  577. f := i64(1e12)
  578. for j := 0; j < 10; j += 1 {
  579. /* NOTE(bill): Cause overflow */
  580. g := intrinsics.volatile_load(&f)
  581. g *= g
  582. intrinsics.volatile_store(&f, g)
  583. }
  584. return u16(s | 0x7c00)
  585. }
  586. return u16(s | (e << 10) | (m >> 13))
  587. }
  588. }
  589. @(link_name="__truncdfhf2")
  590. truncdfhf2 :: proc "c" (value: f64) -> u16 {
  591. return truncsfhf2(f32(value))
  592. }
  593. @(link_name="__gnu_h2f_ieee")
  594. gnu_h2f_ieee :: proc "c" (value: u16) -> f32 {
  595. fp32 :: struct #raw_union { u: u32, f: f32 }
  596. v: fp32
  597. magic, inf_or_nan: fp32
  598. magic.u = u32((254 - 15) << 23)
  599. inf_or_nan.u = u32((127 + 16) << 23)
  600. v.u = u32(value & 0x7fff) << 13
  601. v.f *= magic.f
  602. if v.f >= inf_or_nan.f {
  603. v.u |= 255 << 23
  604. }
  605. v.u |= u32(value & 0x8000) << 16
  606. return v.f
  607. }
  608. @(link_name="__gnu_f2h_ieee")
  609. gnu_f2h_ieee :: proc "c" (value: f32) -> u16 {
  610. return truncsfhf2(value)
  611. }
  612. @(link_name="__extendhfsf2")
  613. extendhfsf2 :: proc "c" (value: u16) -> f32 {
  614. return gnu_h2f_ieee(value)
  615. }
  616. @(link_name="__floattidf")
  617. floattidf :: proc "c" (a: i128) -> f64 {
  618. DBL_MANT_DIG :: 53
  619. if a == 0 {
  620. return 0.0
  621. }
  622. a := a
  623. N :: size_of(i128) * 8
  624. s := a >> (N-1)
  625. a = (a ~ s) - s
  626. sd: = N - intrinsics.count_leading_zeros(a) // number of significant digits
  627. e := i32(sd - 1) // exponent
  628. if sd > DBL_MANT_DIG {
  629. switch sd {
  630. case DBL_MANT_DIG + 1:
  631. a <<= 1
  632. case DBL_MANT_DIG + 2:
  633. // okay
  634. case:
  635. a = i128(u128(a) >> u128(sd - (DBL_MANT_DIG+2))) |
  636. i128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0)
  637. }
  638. a |= i128((a & 4) != 0)
  639. a += 1
  640. a >>= 2
  641. if a & (i128(1) << DBL_MANT_DIG) != 0 {
  642. a >>= 1
  643. e += 1
  644. }
  645. } else {
  646. a <<= u128(DBL_MANT_DIG - sd) & 127
  647. }
  648. fb: [2]u32
  649. fb[1] = (u32(s) & 0x80000000) | // sign
  650. (u32(e + 1023) << 20) | // exponent
  651. u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high
  652. fb[0] = u32(a) // mantissa-low
  653. return transmute(f64)fb
  654. }
  655. @(link_name="__floattidf_unsigned")
  656. floattidf_unsigned :: proc "c" (a: u128) -> f64 {
  657. DBL_MANT_DIG :: 53
  658. if a == 0 {
  659. return 0.0
  660. }
  661. a := a
  662. N :: size_of(u128) * 8
  663. sd: = N - intrinsics.count_leading_zeros(a) // number of significant digits
  664. e := i32(sd - 1) // exponent
  665. if sd > DBL_MANT_DIG {
  666. switch sd {
  667. case DBL_MANT_DIG + 1:
  668. a <<= 1
  669. case DBL_MANT_DIG + 2:
  670. // okay
  671. case:
  672. a = u128(u128(a) >> u128(sd - (DBL_MANT_DIG+2))) |
  673. u128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0)
  674. }
  675. a |= u128((a & 4) != 0)
  676. a += 1
  677. a >>= 2
  678. if a & (1 << DBL_MANT_DIG) != 0 {
  679. a >>= 1
  680. e += 1
  681. }
  682. } else {
  683. a <<= u128(DBL_MANT_DIG - sd)
  684. }
  685. fb: [2]u32
  686. fb[1] = (0) | // sign
  687. u32((e + 1023) << 20) | // exponent
  688. u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high
  689. fb[0] = u32(a) // mantissa-low
  690. return transmute(f64)fb
  691. }
  692. @(link_name="__fixunsdfti")
  693. fixunsdfti :: #force_no_inline proc "c" (a: f64) -> u128 {
  694. // TODO(bill): implement `fixunsdfti` correctly
  695. x := u64(a)
  696. return u128(x)
  697. }
  698. @(link_name="__fixunsdfdi")
  699. fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 {
  700. // TODO(bill): implement `fixunsdfdi` correctly
  701. x := i64(a)
  702. return i128(x)
  703. }
  704. @(link_name="__umodti3")
  705. umodti3 :: proc "c" (a, b: u128) -> u128 {
  706. r: u128 = ---
  707. _ = udivmod128(a, b, &r)
  708. return r
  709. }
  710. @(link_name="__udivmodti4")
  711. udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
  712. return udivmod128(a, b, rem)
  713. }
  714. @(link_name="__udivti3")
  715. udivti3 :: proc "c" (a, b: u128) -> u128 {
  716. return udivmodti4(a, b, nil)
  717. }
  718. @(link_name="__modti3")
  719. modti3 :: proc "c" (a, b: i128) -> i128 {
  720. s_a := a >> (128 - 1)
  721. s_b := b >> (128 - 1)
  722. an := (a ~ s_a) - s_a
  723. bn := (b ~ s_b) - s_b
  724. r: u128 = ---
  725. _ = udivmod128(transmute(u128)an, transmute(u128)bn, &r)
  726. return (transmute(i128)r ~ s_a) - s_a
  727. }
  728. @(link_name="__divmodti4")
  729. divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 {
  730. u := udivmod128(transmute(u128)a, transmute(u128)b, cast(^u128)rem)
  731. return transmute(i128)u
  732. }
  733. @(link_name="__divti3")
  734. divti3 :: proc "c" (a, b: i128) -> i128 {
  735. u := udivmodti4(transmute(u128)a, transmute(u128)b, nil)
  736. return transmute(i128)u
  737. }
  738. @(link_name="__fixdfti")
  739. fixdfti :: proc(a: u64) -> i128 {
  740. significandBits :: 52
  741. typeWidth :: (size_of(u64)*8)
  742. exponentBits :: (typeWidth - significandBits - 1)
  743. maxExponent :: ((1 << exponentBits) - 1)
  744. exponentBias :: (maxExponent >> 1)
  745. implicitBit :: (u64(1) << significandBits)
  746. significandMask :: (implicitBit - 1)
  747. signBit :: (u64(1) << (significandBits + exponentBits))
  748. absMask :: (signBit - 1)
  749. exponentMask :: (absMask ~ significandMask)
  750. // Break a into sign, exponent, significand
  751. aRep := a
  752. aAbs := aRep & absMask
  753. sign := i128(-1 if aRep & signBit != 0 else 1)
  754. exponent := u64((aAbs >> significandBits) - exponentBias)
  755. significand := u64((aAbs & significandMask) | implicitBit)
  756. // If exponent is negative, the result is zero.
  757. if exponent < 0 {
  758. return 0
  759. }
  760. // If the value is too large for the integer type, saturate.
  761. if exponent >= size_of(i128) * 8 {
  762. return max(i128) if sign == 1 else min(i128)
  763. }
  764. // If 0 <= exponent < significandBits, right shift to get the result.
  765. // Otherwise, shift left.
  766. if exponent < significandBits {
  767. return sign * i128(significand >> (significandBits - exponent))
  768. } else {
  769. return sign * (i128(significand) << (exponent - significandBits))
  770. }
  771. }