extended.odin 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. package linalg
  2. import "core:builtin"
  3. import "core:math"
  4. radians :: proc(degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
  5. when IS_ARRAY(T) {
  6. for i in 0..<len(T) {
  7. out[i] = degrees * RAD_PER_DEG
  8. }
  9. } else {
  10. out = degrees * RAD_PER_DEG
  11. }
  12. return
  13. }
  14. degrees :: proc(radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
  15. when IS_ARRAY(T) {
  16. for i in 0..<len(T) {
  17. out[i] = radians * DEG_PER_RAD
  18. }
  19. } else {
  20. out = radians * DEG_PER_RAD
  21. }
  22. return
  23. }
  24. min_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
  25. when IS_ARRAY(T) {
  26. for i in 0..<len(T) {
  27. out[i] = builtin.min(a[i], b[i])
  28. }
  29. } else {
  30. out = builtin.min(a, b)
  31. }
  32. return
  33. }
  34. min_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) {
  35. when IS_ARRAY(T) {
  36. N :: len(T)
  37. when N == 1 {
  38. out = a[0]
  39. } else when N == 2 {
  40. out = builtin.min(a[0], a[1])
  41. } else {
  42. out = builtin.min(a[0], a[1])
  43. for i in 2..<N {
  44. out = builtin.min(out, a[i])
  45. }
  46. }
  47. } else {
  48. out = a
  49. }
  50. return
  51. }
  52. min_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) {
  53. return min_double(a, min_double(b, c))
  54. }
  55. min :: proc{min_single, min_double, min_triple}
  56. max_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
  57. when IS_ARRAY(T) {
  58. for i in 0..<len(T) {
  59. out[i] = builtin.max(a[i], b[i])
  60. }
  61. } else {
  62. out = builtin.max(a, b)
  63. }
  64. return
  65. }
  66. max_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) {
  67. when IS_ARRAY(T) {
  68. N :: len(T)
  69. when N == 1 {
  70. out = a[0]
  71. } else when N == 2 {
  72. out = builtin.max(a[0], a[1])
  73. } else when N == 3 {
  74. out = builtin.max(a[0], a[1], a[2])
  75. }else {
  76. out = builtin.max(a[0], a[1])
  77. for i in 2..<N {
  78. out = builtin.max(out, a[i])
  79. }
  80. }
  81. } else {
  82. out = a
  83. }
  84. return
  85. }
  86. max_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) {
  87. return max_double(a, max_double(b, c))
  88. }
  89. max :: proc{max_single, max_double, max_triple}
  90. abs :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
  91. when IS_ARRAY(T) {
  92. for i in 0..<len(T) {
  93. out[i] = auto_cast builtin.abs(a[i])
  94. }
  95. } else {
  96. out = auto_cast builtin.abs(a)
  97. }
  98. return
  99. }
  100. sign :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
  101. when IS_ARRAY(T) {
  102. for i in 0..<len(T) {
  103. out[i] = #force_inline math.sign(a[i])
  104. }
  105. } else {
  106. out = #force_inline math.sign(a)
  107. }
  108. return
  109. }
  110. clamp :: proc(x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
  111. when IS_ARRAY(T) {
  112. for i in 0..<len(T) {
  113. out[i] = builtin.clamp(x[i], a[i], b[i])
  114. }
  115. } else {
  116. out = builtin.clamp(x, a, b)
  117. }
  118. return
  119. }
  120. saturate :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
  121. return clamp(x, 0.0, 1.0)
  122. }
  123. lerp :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  124. when IS_ARRAY(T) {
  125. for i in 0..<len(T) {
  126. out[i] = a[i]*(1-t[i]) + b[i]*t[i]
  127. }
  128. } else {
  129. out = a * (1.0 - t) + b * t
  130. }
  131. return
  132. }
  133. mix :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  134. when IS_ARRAY(T) {
  135. for i in 0..<len(T) {
  136. out[i] = a[i]*(1-t[i]) + b[i]*t[i]
  137. }
  138. } else {
  139. out = a * (1.0 - t) + b * t
  140. }
  141. return
  142. }
  143. unlerp :: proc(a, b, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
  144. return (x - a) / (b - a)
  145. }
  146. step :: proc(e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  147. when IS_ARRAY(T) {
  148. for i in 0..<len(T) {
  149. out[i] = x[i] < e[i] ? 0.0 : 1.0
  150. }
  151. } else {
  152. out = x < e ? 0.0 : 1.0
  153. }
  154. return
  155. }
  156. smoothstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
  157. t := saturate(unlerp(e0, e1, x))
  158. return t * t * (3.0 - 2.0 * t)
  159. }
  160. smootherstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
  161. t := saturate(unlerp(e0, e1, x))
  162. return t * t * t * (t * (6*t - 15) + 10)
  163. }
  164. sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  165. when IS_ARRAY(T) {
  166. for i in 0..<len(T) {
  167. out[i] = math.sqrt(x[i])
  168. }
  169. } else {
  170. out = math.sqrt(x)
  171. }
  172. return
  173. }
  174. inverse_sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  175. when IS_ARRAY(T) {
  176. for i in 0..<len(T) {
  177. out[i] = 1.0/math.sqrt(x[i])
  178. }
  179. } else {
  180. out = 1.0/math.sqrt(x)
  181. }
  182. return
  183. }
  184. cos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  185. when IS_ARRAY(T) {
  186. for i in 0..<len(T) {
  187. out[i] = math.cos(x[i])
  188. }
  189. } else {
  190. out = math.cos(x)
  191. }
  192. return
  193. }
  194. sin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  195. when IS_ARRAY(T) {
  196. for i in 0..<len(T) {
  197. out[i] = math.sin(x[i])
  198. }
  199. } else {
  200. out = math.sin(x)
  201. }
  202. return
  203. }
  204. tan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  205. when IS_ARRAY(T) {
  206. for i in 0..<len(T) {
  207. out[i] = math.tan(x[i])
  208. }
  209. } else {
  210. out = math.tan(x)
  211. }
  212. return
  213. }
  214. acos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  215. when IS_ARRAY(T) {
  216. for i in 0..<len(T) {
  217. out[i] = math.acos(x[i])
  218. }
  219. } else {
  220. out = math.acos(x)
  221. }
  222. return
  223. }
  224. asin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  225. when IS_ARRAY(T) {
  226. for i in 0..<len(T) {
  227. out[i] = math.asin(x[i])
  228. }
  229. } else {
  230. out = math.asin(x)
  231. }
  232. return
  233. }
  234. atan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  235. when IS_ARRAY(T) {
  236. for i in 0..<len(T) {
  237. out[i] = math.atan(x[i])
  238. }
  239. } else {
  240. out = math.atan(x)
  241. }
  242. return
  243. }
  244. atan2 :: proc(y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  245. when IS_ARRAY(T) {
  246. for i in 0..<len(T) {
  247. out[i] = math.atan2(y[i], x[i])
  248. }
  249. } else {
  250. out = math.atan2(y, x)
  251. }
  252. return
  253. }
  254. ln :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  255. when IS_ARRAY(T) {
  256. for i in 0..<len(T) {
  257. out[i] = math.ln(x[i])
  258. }
  259. } else {
  260. out = math.ln(x)
  261. }
  262. return
  263. }
  264. log2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  265. when IS_ARRAY(T) {
  266. for i in 0..<len(T) {
  267. out[i] = INVLN2 * math.ln(x[i])
  268. }
  269. } else {
  270. out = INVLN2 * math.ln(x)
  271. }
  272. return
  273. }
  274. log10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  275. when IS_ARRAY(T) {
  276. for i in 0..<len(T) {
  277. out[i] = INVLN10 * math.ln(x[i])
  278. }
  279. } else {
  280. out = INVLN10 * math.ln(x)
  281. }
  282. return
  283. }
  284. log :: proc(x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  285. when IS_ARRAY(T) {
  286. for i in 0..<len(T) {
  287. out[i] = math.ln(x[i]) / math.ln(cast(ELEM_TYPE(T))b[i])
  288. }
  289. } else {
  290. out = INVLN10 * math.ln(x) / math.ln(cast(ELEM_TYPE(T))b)
  291. }
  292. return
  293. }
  294. exp :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  295. when IS_ARRAY(T) {
  296. for i in 0..<len(T) {
  297. out[i] = math.exp(x[i])
  298. }
  299. } else {
  300. out = math.exp(x)
  301. }
  302. return
  303. }
  304. exp2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  305. when IS_ARRAY(T) {
  306. for i in 0..<len(T) {
  307. out[i] = math.exp(LN2 * x[i])
  308. }
  309. } else {
  310. out = math.exp(LN2 * x)
  311. }
  312. return
  313. }
  314. exp10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  315. when IS_ARRAY(T) {
  316. for i in 0..<len(T) {
  317. out[i] = math.exp(LN10 * x[i])
  318. }
  319. } else {
  320. out = math.exp(LN10 * x)
  321. }
  322. return
  323. }
  324. pow :: proc(x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  325. when IS_ARRAY(T) {
  326. for i in 0..<len(T) {
  327. out[i] = math.pow(x[i], e[i])
  328. }
  329. } else {
  330. out = math.pow(x, e)
  331. }
  332. return
  333. }
  334. ceil :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  335. when IS_ARRAY(T) {
  336. for i in 0..<len(T) {
  337. out[i] = #force_inline math.ceil(x[i])
  338. }
  339. } else {
  340. out = #force_inline math.ceil(x)
  341. }
  342. return
  343. }
  344. floor :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  345. when IS_ARRAY(T) {
  346. for i in 0..<len(T) {
  347. out[i] = #force_inline math.floor(x[i])
  348. }
  349. } else {
  350. out = #force_inline math.floor(x)
  351. }
  352. return
  353. }
  354. round :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
  355. when IS_ARRAY(T) {
  356. for i in 0..<len(T) {
  357. out[i] = #force_inline math.round(x[i])
  358. }
  359. } else {
  360. out = #force_inline math.round(x)
  361. }
  362. return
  363. }
  364. fract :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
  365. f := #force_inline floor(x)
  366. return x - f
  367. }
  368. mod :: proc(x, m: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
  369. f := #force_inline floor(x / m)
  370. return x - f * m
  371. }
  372. face_forward :: proc(N, I, N_ref: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
  373. return dot(N_ref, I) < 0 ? N : -N
  374. }
  375. distance :: proc(p0, p1: $V/[$N]$E) -> E where IS_NUMERIC(E) {
  376. return length(p1 - p0)
  377. }
  378. reflect :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
  379. b := N * (2 * dot(N, I))
  380. return I - b
  381. }
  382. refract :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
  383. dv := dot(N, I)
  384. k := 1 - eta*eta - (1 - dv*dv)
  385. a := I * eta
  386. b := N * eta*dv*math.sqrt(k)
  387. return (a - b) * E(int(k >= 0))
  388. }
  389. is_nan_single :: proc(x: $T) -> bool where IS_FLOAT(T) {
  390. return #force_inline math.is_nan(x)
  391. }
  392. is_nan_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
  393. for i in 0..<N {
  394. out[i] = #force_inline is_nan(x[i])
  395. }
  396. return
  397. }
  398. is_inf_single :: proc(x: $T) -> bool where IS_FLOAT(T) {
  399. return #force_inline math.is_inf(x)
  400. }
  401. is_inf_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
  402. for i in 0..<N {
  403. out[i] = #force_inline is_inf(x[i])
  404. }
  405. return
  406. }
  407. classify_single :: proc(x: $T) -> math.Float_Class where IS_FLOAT(T) {
  408. return #force_inline math.classify(x)
  409. }
  410. classify_array :: proc(x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) {
  411. for i in 0..<N {
  412. out[i] = #force_inline classify_single(x[i])
  413. }
  414. return
  415. }
  416. is_nan :: proc{is_nan_single, is_nan_array}
  417. is_inf :: proc{is_inf_single, is_inf_array}
  418. classify :: proc{classify_single, classify_array}
  419. less_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x < y }
  420. less_than_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x <= y }
  421. greater_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x > y }
  422. greater_than_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x >= y }
  423. equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x == y }
  424. not_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x != y }
  425. less_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
  426. for i in 0..<N {
  427. out[i] = x[i] < y[i]
  428. }
  429. return
  430. }
  431. less_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
  432. for i in 0..<N {
  433. out[i] = x[i] <= y[i]
  434. }
  435. return
  436. }
  437. greater_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
  438. for i in 0..<N {
  439. out[i] = x[i] > y[i]
  440. }
  441. return
  442. }
  443. greater_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
  444. for i in 0..<N {
  445. out[i] = x[i] >= y[i]
  446. }
  447. return
  448. }
  449. equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
  450. for i in 0..<N {
  451. out[i] = x[i] == y[i]
  452. }
  453. return
  454. }
  455. not_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
  456. for i in 0..<N {
  457. out[i] = x[i] != y[i]
  458. }
  459. return
  460. }
  461. less_than :: proc{less_than_single, less_than_array}
  462. less_than_equal :: proc{less_than_equal_single, less_than_equal_array}
  463. greater_than :: proc{greater_than_single, greater_than_array}
  464. greater_than_equal :: proc{greater_than_equal_single, greater_than_equal_array}
  465. equal :: proc{equal_single, equal_array}
  466. not_equal :: proc{not_equal_single, not_equal_array}
  467. any :: proc(x: $A/[$N]bool) -> (out: bool) {
  468. for e in x {
  469. if e {
  470. return true
  471. }
  472. }
  473. return false
  474. }
  475. all :: proc(x: $A/[$N]bool) -> (out: bool) {
  476. for e in x {
  477. if !e {
  478. return false
  479. }
  480. }
  481. return true
  482. }
  483. not :: proc(x: $A/[$N]bool) -> (out: A) {
  484. for e, i in x {
  485. out[i] = !e
  486. }
  487. return
  488. }