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[3]);
  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] = builtin.abs(a[i]);
  94. }
  95. } else {
  96. out = 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 x {
  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. }