Compare commits

...

431 Commits

Author SHA1 Message Date
gingerBill 9453b2387b Merge pull request #2669 from laytan/check-disabled-when-generating-parapoly
Fix #2666 by checking for disabled when generating parapoly procs
2023-08-01 14:45:36 +01:00
gingerBill a4de59c8ee Merge pull request #2686 from ryuukk/patch-8
Assign element to Slice not Array when alloc a Type_Slice
2023-08-01 14:45:19 +01:00
gingerBill fab40080e4 Merge pull request #2693 from hasanyasin/master
Add -show-system-calls flag info to cli usage help
2023-08-01 14:45:03 +01:00
Hasan Yasin Ozturk fb30bda7d7 Add -show-system-calls flag info to cli usage help 2023-08-01 15:51:22 +03:00
gingerBill 65206fe33e Go through loads of TODOs 2023-08-01 11:39:04 +01:00
gingerBill 2f094134a3 Remove -strict-style-init-only 2023-08-01 11:14:52 +01:00
gingerBill 69e1f42aed Replace a lot of warnings with errors; remove deprecated stuff 2023-08-01 11:11:15 +01:00
gingerBill c35c58b023 Add -vet-style and -vet-semicolon 2023-08-01 11:03:15 +01:00
gingerBill 4b57aec1c6 Fix typo 2023-07-31 17:30:03 +01:00
gingerBill 2038bd0c15 Merge branch 'master' of https://github.com/odin-lang/Odin 2023-07-31 17:27:39 +01:00
gingerBill 19b24fcce2 Add require_results for proc groups 2023-07-31 17:27:23 +01:00
Jeroen van Rijn ed3354b433 Merge pull request #2692 from hasanyasin/master
Fix dropped "dev-" prefix from version tag
2023-07-31 16:55:37 +02:00
Hasan Yasin Ozturk 963eeee361 Fix dropped "dev-" prefix from version tag
In commit c3a31666, "dev-" prefix was dropped unintentionally. This commit fixes
that.
2023-07-31 17:46:45 +03:00
Jeroen van Rijn c3a316664a Merge pull request #2691 from hasanyasin/master
Set version date to commit date instead of build date
2023-07-31 16:39:32 +02:00
Hasan Yasin Ozturk 3d16880d95 Set version date to commit date instead of build date
Fixes #2688

This commit updates `build_odin.sh` and `build.bat` so that date of the commit
is used for the version tag, instead of the build time.
2023-07-31 17:29:56 +03:00
gingerBill be6f355665 Keep -vet happy by removing using 2023-07-31 12:32:30 +01:00
gingerBill 5dba08fb3b Keep -vet happy 2023-07-31 12:19:25 +01:00
gingerBill f17077c05c Remove debug code 2023-07-31 12:11:31 +01:00
gingerBill 8aa36072fc Remove using where easily possible 2023-07-31 12:11:17 +01:00
gingerBill 44ea82f845 Clean up usage of using throughout core and vendor 2023-07-31 11:46:40 +01:00
gingerBill 0de7df9eab Improve //+vet; remove using in many places; add //+vet !using-stmt where necessary 2023-07-31 11:37:14 +01:00
gingerBill 60e509b1e0 Add separate -vet flags; -vet-using-* flags; //+vet file flags 2023-07-31 11:09:19 +01:00
Jeroen van Rijn 551c379f1b Merge pull request #2687 from Kelimion/xml-value-fix
Fix #2684
2023-07-28 16:01:01 +02:00
Jeroen van Rijn 683ee75703 Fix #2684 2023-07-28 15:53:39 +02:00
ryuukk a99da47b0d Assign element to Slice not Array when alloc a Type_Slice 2023-07-27 22:13:55 +02:00
Jeroen van Rijn 5ac7fe453f Merge pull request #2676 from jasonKercher/fix-2667
coalesce tombstones in map insert
2023-07-22 10:29:15 +02:00
jason f9c083073e coalesce tombstones in map insert 2023-07-21 15:44:39 -04:00
Laytan Laats 74338733ba Fix #2666 by checking for disabled when generating parapoly procs 2023-07-19 20:27:34 +02:00
gingerBill 1b3657122c Uncomment procedures in procedure group 2023-07-17 16:02:18 +01:00
gingerBill 0f28857c59 Improve type inference for procedure group stuff 2023-07-17 13:03:58 +01:00
gingerBill 88485d5467 Improve scoring for polymorphic procedures 2023-07-17 12:57:33 +01:00
gingerBill 921530dd01 Fix to allow procedure groups on objective-c types 2023-07-17 12:43:56 +01:00
gingerBill dcf3023d93 Fix bug caused by incorrect assert 2023-07-17 12:06:48 +01:00
Jeroen van Rijn b12c46b28a Merge pull request #2659 from Pingar5/master
Fixed typo in GGPO bindings
2023-07-17 01:11:32 +02:00
Brennen Shaughnessy 635d671ee7 Fixed typo in GGPO bindings 2023-07-15 15:59:58 -04:00
Jeroen van Rijn 204c0fa4d8 Merge pull request #2650 from hchac/remove-core-odin-from-gitignore
Don't gitignore folders named odin.
2023-07-11 22:58:56 +02:00
gingerBill 3a0b66d5df Merge pull request #2625 from laytan/exit-code-1-on-test-failure
exit with code 1 on `odin test` failure
2023-07-11 21:50:18 +01:00
gingerBill 07d3122c14 Merge pull request #2651 from erjohnson/arena-static-bootstrap-doc-fix
Fix small doc mistakes in arena.odin
2023-07-11 21:49:06 +01:00
Eric Johnson c6957e4e31 Fix small doc mistakes in arena.odin 2023-07-11 13:41:12 -07:00
hchac 8068a3899d Don't gitignore folders named odin. 2023-07-11 16:23:54 -04:00
Laytan Laats 3cce972125 fix indentation 2023-07-11 19:34:59 +02:00
Laytan Laats 52700d6a84 use lb_emit_select instead of lb_emit_if for exit check 2023-07-11 19:30:44 +02:00
Jeroen van Rijn 0c80a4b836 Merge pull request #2640 from z64/z64/mutex
Improve Mutex struct documentation
2023-07-11 14:01:02 +02:00
Zac Nowicki 46f408cc9f Fixup link format 2023-07-11 07:43:36 -04:00
Jeroen van Rijn 5c068a9062 Merge pull request #2647 from ryuukk/patch-6
core:sys/windows: Deprecate htons, htonl, ntohl, ntohs in favor of endian specific integers
2023-07-11 08:11:50 +02:00
ryuukk e1fae5b902 Fix attribute 2023-07-11 03:51:28 +02:00
ryuukk 20e5e95ff8 Deprecate htons, htonl, ntohl, ntohs 2023-07-11 03:45:08 +02:00
Jeroen van Rijn a238f78855 Merge pull request #2645 from Pix-xiP/fix-raylib-gesture
GetGestureDetected proc returns a Gesture not a Gestures bit_set
2023-07-10 17:25:02 +02:00
Jeroen van Rijn 5b96712ed0 Merge pull request #2642 from ryuukk/patch-4
core:sys/windows: Add definitions for network byte order conversion procs
2023-07-10 17:04:09 +02:00
Pix f141078073 GetGestureDetecetd should return a Gestures bit_set not a Gesture. 2023-07-10 22:24:16 +08:00
Jeroen van Rijn d47fed16a9 Merge pull request #2643 from ryuukk/patch-5
core:sys/windows: Add CopyFileW proc
2023-07-10 11:21:37 +02:00
ryuukk bc43a8d38d Add CopyFileW 2023-07-10 06:02:38 +02:00
ryuukk ccd5685cee Fix doc links 2023-07-10 05:57:12 +02:00
ryuukk f0f8177a19 Add definitions for network byte order conversion procs 2023-07-10 05:56:26 +02:00
Zac Nowicki 363b701925 Improve Mutex struct documentation 2023-07-09 08:30:16 -04:00
Jeroen van Rijn 0a897e2fae Merge pull request #2638 from ramn/handle_nils_in_expect_value
Fix #2637
2023-07-09 00:28:02 +02:00
ramn 5f53d815d1 fix: make -vet not complain 2023-07-09 00:15:01 +02:00
ramn 7b89f25818 Fix #2637
where testing.expect_value can't compare nils
2023-07-08 23:46:51 +02:00
gingerBill 3072479c3c Generalize name mangling rule to have a singular definition for a name separator 2023-07-07 23:52:56 +01:00
gingerBill 62031c24a2 Add extra mutex guards around module value access 2023-07-07 23:35:16 +01:00
gingerBill aa38889704 Fix issue with pointer casting internal llvm intrinsics 2023-07-07 23:23:47 +01:00
gingerBill 17562e476f Remove math usage of raw LLVM intrinsic prototypes 2023-07-07 23:13:37 +01:00
gingerBill 6495f2cf98 Fix #2593 2023-07-07 23:09:46 +01:00
gingerBill ea20b644cc Fix #2624 2023-07-07 23:07:41 +01:00
gingerBill bf848637aa Fix #2629 2023-07-07 23:06:15 +01:00
gingerBill 759f846b2b Fix [2]union{T} comparison against nil 2023-07-07 23:03:46 +01:00
gingerBill 3758be55f5 Fix #2630 2023-07-07 22:56:20 +01:00
gingerBill 8f4c59b080 Add core:math/cmpl to all_main.odin 2023-07-07 22:29:53 +01:00
gingerBill 1ff6212ffa Always call lb_run_remove_dead_instruction_pass to fix -debug issues 2023-07-07 22:28:31 +01:00
Jeroen van Rijn b60d29ae9a Merge pull request #2627 from laytan/add-address-family-type-definition
add `ADDRESS_FAMILY` to darwin (currently only available in linux)
2023-07-03 22:45:28 +02:00
Laytan Laats 38d71e668d add ADDRESS_FAMILY to darwin (currently only available in linux) 2023-07-03 19:56:56 +02:00
Laytan Laats 7cdf37eaf6 exit with code 1 on odin test failure 2023-07-03 01:22:36 +02:00
Jeroen van Rijn 8d9adfd548 Merge pull request #2623 from laytan/fix-2615-cant-iterate-untyped-string
Fix #2615: can't iterate untyped string
2023-07-02 23:06:35 +02:00
Laytan Laats a3e2d90f4c add test 2023-07-02 23:00:37 +02:00
Laytan Laats fc81008ab5 Fix #2615: can't iterate untyped string 2023-07-02 22:18:25 +02:00
Jeroen van Rijn a1eae6304f Merge pull request #2622 from laytan/detect-unix-colors-support
detect unix color support
2023-07-02 21:34:34 +02:00
Laytan Laats 49058620f0 fix spacing 2023-07-02 21:25:48 +02:00
Laytan Laats f68a3639b4 use more common detection method and add FORCE_COLOR and NO_COLOR support 2023-07-02 21:11:19 +02:00
Laytan Laats f4e87c9720 ignore stderr in tput call 2023-07-02 20:20:10 +02:00
Laytan Laats 23bf7973fa detect unix color support 2023-07-02 19:56:46 +02:00
Jeroen van Rijn 67e0751124 Merge pull request #2621 from DanielGavin/vulkan-flags2
Add support for vulkan FlagBits2
2023-07-02 19:34:20 +02:00
DanielGavin f76559daf6 Remove whitespaces 2023-07-02 18:28:37 +02:00
DanielGavin 5e99ff6769 Add support FlagBits2 2023-07-02 18:24:37 +02:00
gingerBill 1ecb4aa9aa Begin work on core:math/cmplx
`complex*` types only at the moment, `quaternion*` types coming later
2023-06-28 13:20:23 +01:00
gingerBill a2b3c72647 Improve accuracy of abs or complex* types 2023-06-28 13:18:36 +01:00
gingerBill 0180a4fcd4 Add math.sincos 2023-06-28 12:57:09 +01:00
gingerBill abca3ceac8 Keep -vet happy 2023-06-28 12:20:12 +01:00
gingerBill 866a9fdf19 Actually add math.hypot 2023-06-28 12:19:45 +01:00
gingerBill 20e954a864 Add math.hypot 2023-06-28 12:16:49 +01:00
gingerBill 03e40b333a Merge branch 'master' of https://github.com/odin-lang/Odin 2023-06-28 11:57:43 +01:00
gingerBill ebed66d4ce General code style clean up for vendor:nanovg 2023-06-28 11:57:37 +01:00
gingerBill 9e9f3c485b General code style clean up for vendor:fontstash 2023-06-28 11:36:27 +01:00
gingerBill d50a844720 Replace mem with runtime in core:slice 2023-06-28 11:04:51 +01:00
Jeroen van Rijn 89e559296e Merge pull request #2612 from laytan/master
only run nightly upload if workflow is ran on main repo
2023-06-28 07:53:40 +02:00
Laytan Laats d352e2fa31 only run nightly upload if workflow is ran on main repo 2023-06-27 23:33:18 +02:00
Jeroen van Rijn 71bc452764 Merge pull request #2611 from GoNZooo/gonz.add-unix-setenv
fix(os): use `setenv` instead of `putenv`
2023-06-27 20:54:49 +02:00
Rickard Andersson f048ad13b5 fix(set_env): use clone_to_cstring instead of unsafe_to_cstring 2023-06-27 21:48:53 +03:00
Rickard Andersson d03d5d8f03 style: use tabs
:[
2023-06-27 21:46:00 +03:00
Rickard Andersson 6ff0ce15e7 cleanup: remove leftover line 2023-06-27 21:42:20 +03:00
Rickard Andersson 330b393e16 fix(os): use setenv instead of putenv
`setenv` doesn't copy the value that is put, which means that the
previous code had a bug where we free'd the temporary memory and the
environment was accidentally cleared right after the function finished.
2023-06-27 21:37:10 +03:00
gingerBill a820246f64 Keep -vet happy 2023-06-26 23:00:39 +01:00
gingerBill 1bf4c8c9ba Merge pull request #2268 from Skytrias/skytrias-vendor-additions
fontstash / nanovg vendor additions
2023-06-26 22:59:11 +01:00
skytrias ca1d437435 add build flags restrictions 2023-06-26 21:28:54 +02:00
gingerBill 8b8310711e Fix #2594 zero sized union code generation 2023-06-26 17:36:27 +01:00
gingerBill cdcb64b0d0 Add missing -strict-style check 2023-06-26 17:06:42 +01:00
gingerBill 3c0f1caa41 Fix #2606 2023-06-26 17:03:40 +01:00
gingerBill 8182ba4ee0 Improve internal names for parapoly records 2023-06-26 16:48:43 +01:00
gingerBill 3d9328fd79 Default to panic allocator for wasm targets 2023-06-26 15:55:52 +01:00
gingerBill 6c6f9f7d25 Fix fmt implementation for js 2023-06-26 15:55:35 +01:00
gingerBill c8f475174e Fix tests for -strict-style 2023-06-26 15:51:08 +01:00
gingerBill 3dec55f009 Replace x in &y Use &v in y syntax through core & vendor for switch/for statements 2023-06-26 15:42:57 +01:00
gingerBill 00d60e28c2 Allow switch &v in ... work to be consistent with for &e in ... 2023-06-26 15:41:53 +01:00
gingerBill ea00619c3b for &e, i in array and for k, &v in map (alternative to passing the iterable by pointer) 2023-06-26 15:20:40 +01:00
skytrias bbe50bdaf1 -strict-style fix 2023-06-23 16:21:52 +02:00
skytrias 6b59aee336 cleanup with -vet and add to all_vendor 2023-06-23 16:18:40 +02:00
gingerBill 26a5614572 Merge branch 'master' into skytrias-vendor-additions 2023-06-23 14:33:01 +01:00
gingerBill 19ea090633 Merge pull request #2584 from odin-lang/new-io
New and Improved `io.Stream` interface
2023-06-23 12:12:17 +01:00
gingerBill 9841b11a54 Merge pull request #2597 from odin-lang/ordered-named-arguments
Allowing for Positional and Named Arguments in Procedure Calls
2023-06-23 12:11:46 +01:00
gingerBill 5a6d5374d7 Update WebGL procedures to contextless calling convention 2023-06-22 14:30:02 +01:00
gingerBill 9099bc0b6e Merge pull request #2599 from RehkitzDev/master
fixed dynlib wasm stub
2023-06-22 12:56:23 +01:00
Rehkitzdev e3b43b6e1c fixed dynlib wasm stub 2023-06-22 13:35:22 +02:00
gingerBill b0d801f629 Merge pull request #2582 from ftphikari/master
[core:thread] Added self_cleanup flag to properly auto-clean threads
2023-06-21 18:21:48 +01:00
gingerBill c48057081e Fix nullptr entity case 2023-06-21 14:39:23 +01:00
gingerBill ea76e09ea7 Fix empty varargs 2023-06-21 14:30:39 +01:00
gingerBill c9fb078c0f Handle #c_vararg 2023-06-21 14:07:14 +01:00
gingerBill 1800030356 Correct deferred procedures 2023-06-21 14:01:46 +01:00
gingerBill 43ba2c6226 Fix constant parameter passing 2023-06-21 12:10:07 +01:00
gingerBill 735181dc0e Remove unnecessary indent 2023-06-21 01:33:37 +01:00
gingerBill 8a890fd3d3 Remove new_and_improved in the name 2023-06-21 01:32:35 +01:00
gingerBill 15e31e47fa Remove in order requirement for named parameters 2023-06-21 01:24:57 +01:00
gingerBill 9b54b99bf6 Use positional and named arguments within the core library 2023-06-21 01:17:05 +01:00
gingerBill 67ca9166d3 Allow named arguments variadic expansion .. 2023-06-21 01:03:21 +01:00
gingerBill b2ced834ba Minor code reshuffle 2023-06-21 00:43:51 +01:00
gingerBill 18746c1444 Refactor call argument checking to a single procedure 2023-06-21 00:40:02 +01:00
gingerBill 09f366bec7 Correct purely named argument handling 2023-06-21 00:03:56 +01:00
gingerBill 3998d0c81e Make error checks diverging where possible 2023-06-20 22:55:47 +01:00
gingerBill 2a002c3882 Fix scoring for untyped ternary expressions 2023-06-20 22:55:33 +01:00
gingerBill fb756e3463 Correct procedure group handling 2023-06-20 21:02:57 +01:00
gingerBill 3c5661b51b Allow for positional and named arguments in procedure calls 2023-06-20 20:29:40 +01:00
gingerBill 26e06ba6a6 Correct check_call_arguments_new_and_improved logic 2023-06-20 16:08:26 +01:00
gingerBill 7c57dde255 Start work on parapoly args for new and improved 2023-06-20 13:47:10 +01:00
gingerBill 9ec927b9e9 Try to get make everything work with parapoly 2023-06-20 00:30:29 +01:00
gingerBill 15a0d9f900 Begin to handle split arguments correctly 2023-06-19 23:46:06 +01:00
gingerBill f26e3c6509 Improve proc group selection with named arguments 2023-06-19 22:26:43 +01:00
gingerBill 6568625dea Fix line error printing for error messages 2023-06-19 22:12:47 +01:00
gingerBill 427f212170 Begin work in procedure calls 2023-06-19 13:56:00 +01:00
Jeroen van Rijn c1fb8eaf1a Merge pull request #2591 from GoNZooo/g.add-poll-for-unix
feat(os_linux): add `poll` & `ppoll`
2023-06-17 08:27:42 +02:00
Rickard Andersson 37469dc9c2 fix(poll): make interface more odinary
We take `fds` as a normal slice and get the length from it instead of
bothering with a second parameter.
2023-06-15 16:10:00 +03:00
Rickard Andersson dce57627c9 fix: remove redefinition of timespec
They are in the same package, so it's accessible anyway.
2023-06-15 08:54:42 +03:00
gingerBill 2992ca5df1 Basic support for new procedure code (non-polymorphic, non-proc-group) 2023-06-15 01:37:55 +01:00
Rickard Andersson a5ed5883c7 cleanup: more tabs 2023-06-14 23:59:09 +03:00
Rickard Andersson 0036509f74 cleanup(os_linux/poll): use tabs everywhere
:(
2023-06-14 23:51:33 +03:00
Rickard Andersson 003c470a4d fix(os_linux): make when for arm64 check correct order
Also remove `sys_select` since we aren't using it anyway
2023-06-14 23:38:00 +03:00
Rickard Andersson d6540d9077 fix(os_linux): call ppoll instead on arm64 2023-06-14 23:26:43 +03:00
Rickard Andersson 091c515fea cleanup(os_linux): remove select 2023-06-14 22:34:57 +03:00
Rickard Andersson 4f2b9835f5 feat(unix): add poll 2023-06-14 22:13:36 +03:00
gingerBill 242d3b3c4d Begin work allowing mixture of named and unnamed 2023-06-14 15:40:52 +01:00
gingerBill c66ac9725e Separate out logic for checking mixture of named and unnamed parameters 2023-06-14 14:56:33 +01:00
gingerBill feacc5cd11 Basic enforcement of ordered named arguments/parameters for procedures 2023-06-14 14:03:08 +01:00
gingerBill 3a761395be Add basic optimization for comparisons against the empty string "" 2023-06-14 12:49:33 +01:00
gingerBill a78d6fe0b3 Use i64 instead of int for internal procedures 2023-06-14 12:31:57 +01:00
gingerBill 08e466938f Merge branch 'master' into new-io 2023-06-14 12:07:04 +01:00
gingerBill e036155bdb Merge pull request #2586 from thetarnav/patch-1
Replace `0` with `os.ERROR_NONE` in `demo.odin`
2023-06-14 12:05:52 +01:00
gingerBill 2149afabe1 Merge pull request #2590 from inbelic/inbelic/fix-no_nil-variants-err
[check-type] fix faulty #no_nil variants error
2023-06-14 12:05:34 +01:00
finn ec32967daa [check-type] fix faulty #no_nil variants error
- when checking the variants of a union type we will skip adding
  the variants if we have an unspecialized polymorphic, hence our
  union_type variants will be empty and have a count of 0

- so when checking if we violate the #no_nil error, if we are in the
  unspecialized polymorphic case and there exists at least one variant
  in the original variants then we should not raise this error

- test checks that we do not raise the error anymore, and that we still
  detect the #no_nil error in the described circumstances
2023-06-13 22:07:01 +02:00
gingerBill fc4a5e61c2 Add ODIN_IGNORE_MSVC_CHECK check to build.bat 2023-06-13 13:21:15 +01:00
gingerBill e9608c9d05 Merge branch 'master' of https://github.com/odin-lang/Odin 2023-06-13 13:15:05 +01:00
gingerBill 581eebb197 Fix a race condition when produced anonymous procedure literals with -use-separate-modules 2023-06-13 13:14:59 +01:00
Jeroen van Rijn 10fa67fdaa Merge pull request #2589 from jlreymendez/master
fix: read file from windows was not returning platform error correctly
2023-06-13 09:48:50 +02:00
José Rey Méndez 10f2136675 fix: read file from windows was not returning platform error correctly 2023-06-12 19:28:41 -03:00
Jeroen van Rijn d97dd99d91 Merge pull request #2588 from laytan/fix-darwin-fcntl
fix fcntl binding on darwin
2023-06-12 16:16:49 +02:00
gingerBill 296674e18b Rename ODIN_DISALLOW_RTTI to ODIN_NO_RTTI; Remove dead command line flags 2023-06-12 14:53:05 +01:00
gingerBill 52a926dd90 Deprecate -disallow-rtti in favour of -no-rtti 2023-06-12 14:49:00 +01:00
Laytan Laats d38ea63c78 fix fcntl binding on darwin 2023-06-12 15:37:39 +02:00
gingerBill 2022a7615a Make all id suffixes use atomics where possible 2023-06-12 14:10:18 +01:00
gingerBill dca0fae781 Improve lb_generate_anonymous_proc_lit (again) 2023-06-12 13:42:51 +01:00
gingerBill e16c6c1b6b Replace procedure strings.concatenate 2023-06-12 12:58:47 +01:00
gingerBill ede9881458 Keep compilers happy 2023-06-12 12:54:36 +01:00
gingerBill a7f8c78358 Change how "$anon" mangling works to use an atomic value instead 2023-06-12 12:52:17 +01:00
Jeroen van Rijn 3a90b40425 Merge pull request #2587 from GoNZooo/g.fix-early-exit-on-no-hosts
fix(dns): don't exit early on no hosts in hosts file
2023-06-12 12:51:37 +02:00
Rickard Andersson 454709559b fix(dns): don't exit early on no hosts in hosts file
If we don't have any hosts specified we'll still not generate any
overrides which is fine, but we'll continue onto actually trying to
resolve the hostname we came into the function for initially.
2023-06-12 13:38:12 +03:00
Damian Tarnawski c3933cead4 Replace 0 with os.ERROR_NONE in demo.odin 2023-06-11 23:41:26 +02:00
gingerBill 420f93ce78 Ignore BSD's for stream.odin 2023-06-08 22:38:15 +01:00
gingerBill 2a212a7556 Put stream into the impl 2023-06-08 17:00:38 +01:00
gingerBill 145a7a24e8 Use io.Stream as the internal interface for os2.File 2023-06-08 16:55:01 +01:00
gingerBill 6c040497ef Update os2 to new io.Stream 2023-06-08 16:45:13 +01:00
gingerBill 9ee4b76cd9 Just make the io.Reader etc aliases 2023-06-08 16:38:57 +01:00
gingerBill 3f6775e29b Update to new io interface 2023-06-08 16:35:24 +01:00
gingerBill 4c17e2e97e Merge pull request #2552 from jcmoyer/fix-2466
Use compound literal storage for ValueDecl lvals
2023-06-08 12:34:40 +01:00
Jeroen van Rijn eac53fed59 Merge pull request #2583 from JamesDSource/master
Correct Timeval struct to use microseconds on darwin and linux (Issue #2489)
2023-06-08 09:39:25 +02:00
James Duran fed0c2ea26 Fix Timeval for darwin and linux 2023-06-07 21:55:08 -07:00
gingerBill 21c1618d94 Add botan libraries to all/all_vendor.odin 2023-06-08 00:28:35 +01:00
gingerBill d37699f51a Add bsd to mem/virtual 2023-06-07 23:07:31 +01:00
gingerBill d82bfa98a7 Remove redundant comments 2023-06-07 23:01:08 +01:00
gingerBill 9b15bda055 Add missing packages to examples/all 2023-06-07 22:48:39 +01:00
gingerBill 635842b322 Add more text packages to examples/all 2023-06-07 22:40:46 +01:00
hikari 3b8515beb0 [core:thread] Seeing if this fixes network tests 2023-06-07 20:52:41 +03:00
hikari 7b62b81ebd [core:thread] Fix compilation 2023-06-07 20:03:19 +03:00
hikari dcf4e51787 [core:thread] Added self_cleanup flag to properly auto-clean threads 2023-06-07 19:11:16 +03:00
gingerBill 7dc09ed450 Add ODIN_COMPILE_TIMESTAMP (unix timestamp in nanoseconds) 2023-06-07 15:49:12 +01:00
gingerBill 349641e95f Fix #2572 2023-06-07 13:08:15 +01:00
gingerBill 9941ec85d8 Fix #2578 (check for fallthrough) 2023-06-07 12:18:21 +01:00
gingerBill ef944b903b "Fix" #2580 2023-06-07 12:13:20 +01:00
gingerBill 0c477f2c6b Merge pull request #2289 from Lperlind/staging/fix_os_args
Fix out of range error with _alloc_command_line_arguments in darwin
2023-06-07 12:06:43 +01:00
gingerBill 151396507e Merge pull request #1309 from Yawning/fix/freebsd-syscall
src: "Fix" the system call intrinsic for FreeBSD
2023-06-07 12:04:57 +01:00
gingerBill 8441c0c51e Merge pull request #2577 from Tetralux/refactor-init-context
[thread] Refactor handling of 'init_context' + add doc comments for it
2023-06-07 11:51:30 +01:00
gingerBill ae7bf468d1 Merge pull request #2573 from inbelic/inbelic/fmt-zero-padding
[fmt] fix zero-padding behaviour of numbers
2023-06-07 11:44:53 +01:00
gingerBill 907ef82d4b Merge pull request #2470 from odin-lang/separate-int-word-sizes
Separate int size from word/pointer size
2023-06-07 02:20:06 +01:00
gingerBill 7a1ab62987 Fix endianness for wasm64p32 2023-06-07 01:19:40 +01:00
gingerBill 295cfc905c Fix typo in wasm64p32 abi 2023-06-07 00:53:31 +01:00
gingerBill 204924927a Ignore non-variable parameters 2023-06-07 00:35:11 +01:00
gingerBill f622a8393c Change ABI for wasm64p32 on slices and structs 2023-06-07 00:30:14 +01:00
gingerBill d75df7fd8a Rename procs 2023-06-07 00:12:54 +01:00
gingerBill 2bc5e0ebd7 Fix non-constant compound literals of slices 2023-06-07 00:10:39 +01:00
gingerBill ca6cef9a7d Fix wasm intrinsics; fix len for strings and slices 2023-06-06 23:11:42 +01:00
gingerBill 1c2a30d7e9 Fix constant slice initialization for wasm64p32 2023-06-06 22:51:51 +01:00
gingerBill 4a75a1e839 Merge branch 'master' into separate-int-word-sizes 2023-06-06 22:42:04 +01:00
gingerBill 6a2ff3a371 Merge pull request #2571 from jakubtomsu/builtin-soa-procs-improvements
Update SOA dynamic array procs to match non-SOA
2023-06-06 22:40:27 +01:00
gingerBill 7ce1386d1a Merge pull request #2575 from RehkitzDev/master
added webgl bindFramebuffer
2023-06-06 22:39:17 +01:00
gingerBill d6f45e4d76 Fix fmt for js 2023-06-06 22:38:43 +01:00
gingerBill 356f66784f Fix @(default_calling_convention) check on wasm 2023-06-06 22:36:36 +01:00
Jeroen van Rijn 166ab7b600 Merge pull request #2579 from apahl/patch-1
Documentation: Tracking_Allocator example is leaking memory
2023-06-06 15:20:38 +02:00
Axel Pahl 1cdb0abf80 Update core/mem/doc.odin 2023-06-06 15:17:18 +02:00
gingerBill 0defd1d141 Correct printing in fmt for ODIN_ERROR_POS_STYLE 2023-06-06 11:17:34 +01:00
gingerBill 24ed07b6d5 Add error requiring an explicit calling convention for foreign procedures 2023-06-06 11:12:14 +01:00
gingerBill ecad730945 Fix map_get typo 2023-06-06 11:08:09 +01:00
gingerBill efb7fd919b Minor fix to internal using logic with LLVM causing a compiler bug 2023-06-06 10:58:36 +01:00
Tetralux 5d6b923244 [thread] Refactor handling of 'init_context' + add doc comments for it 2023-06-03 08:08:18 +00:00
Rehkitzdev d8752da7d5 added webgl bindFramebuffer 2023-06-02 22:19:32 +02:00
finn 6952124988 [fmt] fix zero-padding behaviour of numbers
- when formatting a negative number with left zero-padding we expect the
  padding to be placed between the minus (-) sign and the number
- currently the padding is placed before the sign
2023-06-01 16:04:07 +02:00
jakubtomsu a6c93e2c41 Update SOA dynamic array procs to match non-SOA 2023-06-01 13:42:26 +02:00
gingerBill 788f3c22bf Merge branch 'master' of https://github.com/odin-lang/Odin 2023-05-31 22:23:53 +01:00
gingerBill c194dfbdf7 Remove thread.init_context = context 2023-05-31 22:23:47 +01:00
gingerBill 5e996a1c02 Merge pull request #2568 from RehkitzDev/master
fixed webgl BindFramebuffer parameter
2023-05-31 20:48:00 +01:00
Rehkitzdev b52bf11ea5 fixed webgl BindFramebuffer parameter 2023-05-31 21:44:30 +02:00
gingerBill 7915dde43c Merge pull request #2504 from jon-lipstate/attr_error
helpful error on custom-attrs
2023-05-31 14:08:33 +01:00
gingerBill 7675b9c28f Merge pull request #2564 from Lperlind/rand-docs
Document core:math/rand and add 'possible output'
2023-05-31 14:08:21 +01:00
Lucas Perlind ebe5636307 Document core:math/rand and add 'possible output'
Possible output allows us to just type check a test
and have some sort of output field in the docs but
not actually verify it matches stdout
2023-05-31 09:49:12 +10:00
gingerBill 6fe2df1d7d Add more documentation to numerous @builtin procedures in package runtime 2023-05-30 23:42:21 +01:00
gingerBill 5376d32772 Parse leading comment above attribute for value declarations 2023-05-30 23:06:04 +01:00
gingerBill 2924e478ee Improve check_decl_attributes logic for is_runtime 2023-05-30 20:36:43 +01:00
gingerBill 297700ad11 Merge branch 'master' of https://github.com/odin-lang/Odin 2023-05-30 20:26:27 +01:00
gingerBill 9d29914304 Don't strip builtin attribute form AST 2023-05-30 20:26:22 +01:00
jon lipstate b223bc0302 Merge branch 'odin-lang:master' into attr_error 2023-05-30 08:23:28 -07:00
gingerBill 3562a38f8c Merge pull request #2558 from laytan/implement-set-blocking-darwin
implement non blocking sockets for darwin
2023-05-30 02:15:20 +01:00
gingerBill 201544ef8b Merge pull request #2559 from wiremoons/patch-1
Update build_odin.sh to better support optimisation on Arm CPUs
2023-05-30 02:13:46 +01:00
gingerBill 837ba6c33b Minor change to #reverse for logic; add comments explaining it 2023-05-30 00:21:40 +01:00
gingerBill 3ab01dbc00 Fix type switch debug information on -o:none 2023-05-30 00:05:52 +01:00
gingerBill c241edaa30 Add missing procedure for #reverse on strings 2023-05-30 00:05:24 +01:00
gingerBill e0530df98a Support #reverse for strings 2023-05-29 23:45:21 +01:00
gingerBill 6cbce9fdff Merge pull request #2563 from charles-l/master
WASM: Use BasicC ABI convention for arguments that have `proc "c"`
2023-05-29 23:33:58 +01:00
gingerBill c1eb536726 Change to "contextless" from "c"` 2023-05-29 23:30:48 +01:00
gingerBill b848ae7abb Improve error message for #reverse on an interval 2023-05-29 23:27:42 +01:00
gingerBill f07453d0ae Support #reverse on #soa arrays 2023-05-29 23:24:03 +01:00
charles 052051244f WASM: Use BasicC ABI convention for arguments that have a proc "c" annotation 2023-05-29 18:20:25 -04:00
gingerBill 97490c6445 Basic support for #reverse for in on normal arrays 2023-05-29 23:17:06 +01:00
gingerBill 1247d36a12 Fix #2562 caused by inlining of procedure call 2023-05-29 22:57:42 +01:00
gingerBill f3a463000d Fix #2561 - ARM64 ABI bug for homogenous structs with more than 4 elements 2023-05-29 22:50:28 +01:00
gingerBill c38842ecb2 Merge pull request #2535 from jasonKercher/fix2515
Fix #2515 - Implement backward shift on `map` on insert and reseed hashes on resize
2023-05-29 22:41:46 +01:00
gingerBill 8b825b23b1 Add missing comma 2023-05-29 15:18:38 +01:00
gingerBill d2f62730bc Fix #2560 2023-05-29 14:55:27 +01:00
Simon Rowe d167d18bb3 Update build_odin.sh to better support optimisation on Arm CPUs
The `build_odin` flags include the option `release-native`.

The current `EXTRAFLAGS` set however don't work for Arm CPUs as they dont support `-march=native`.

Added code to detect CPU and either set the preferred flag for Arm CPUs (ie `-mcpu=native`) or keep the current default.

Information on preferred Arm CPU optimisation flag taken from here: https://community.arm.com/arm-community-blogs/b/tools-software-ides-blog/posts/compiler-flags-across-architectures-march-mtune-and-mcpu

Changes tested on an Apple Silicon M1 CPU (arm64) using HomeBrew installed llvm as follows:

```
Homebrew clang version 14.0.6                                                                                                                    
Target: arm64-apple-darwin22.5.0                                                                                                                 
Thread model: posix                                                                                                                              
InstalledDir: /opt/homebrew/opt/llvm@14/bin
```
2023-05-28 15:08:14 +01:00
Jeroen van Rijn 508d7c3336 Merge pull request #2557 from laytan/fix-weird-errno-on-darwin
fix weird errno returned on darwin
2023-05-27 23:26:45 +02:00
Laytan Laats 2b31d85cd4 implement non blocking sockets for darwin 2023-05-27 22:40:05 +02:00
Laytan Laats e350c37e6f fix weird errno returned on darwin 2023-05-27 21:49:39 +02:00
gingerBill 319a465429 Correct queue usage of runtime.Allocator_Error 2023-05-27 15:26:27 +01:00
gingerBill 9371325246 Fix typo 2023-05-25 12:19:41 +01:00
gingerBill 2fda3cf988 Remove os dependency in primitives_openbsd.odin 2023-05-25 12:17:39 +01:00
gingerBill 03b7194c97 Remove os dependency for futex_openbsd.odin 2023-05-25 12:05:58 +01:00
gingerBill 39bff40a75 Make many core:unicode/utf8 procedures "contextless" 2023-05-25 11:58:42 +01:00
gingerBill 3dc6edfd2d Merge branch 'master' of https://github.com/odin-lang/Odin 2023-05-25 11:58:09 +01:00
gingerBill 762747273e Add mutex to mem.Tracking_Allocator 2023-05-25 11:58:02 +01:00
gingerBill 0f392a95ae Merge pull request #2549 from NoahR02/update-vulkan
Update Vulkan
2023-05-24 23:17:06 +01:00
gingerBill 29786b0024 Merge pull request #2555 from ryhor-spivak/fix_windowplacement
Remove rcDevice field from WINDOWPLACEMENT
2023-05-24 23:14:42 +01:00
gingerBill 32ca50a097 Fix special printing for certain named types with fmt.printf related procedures 2023-05-24 20:54:30 +01:00
Ryhor Spivak 8012e6fa43 Remove rcDevice field from WINDOWPLACEMENT. Add WaitMessage and SetWindowPlacement.
rcDevice is under #ifdef _MAC in WinUser.h and _MAC is defined only for PowerPC Mac builds.
2023-05-24 15:14:30 +03:00
gingerBill 54b7cefb09 Fix lua.MAXSTACK 2023-05-24 10:21:53 +01:00
gingerBill 3a61350f4b Add debug messages to docs_writer.cpp 2023-05-22 21:48:32 +01:00
gingerBill bdbbaf6c88 Disable stable_type_cache for the time being 2023-05-22 21:34:20 +01:00
gingerBill 24a1a8a626 Keep -vet happy 2023-05-22 20:48:49 +01:00
gingerBill 38b64dc5df Improve doc_writer.cpp performance 2023-05-22 20:48:13 +01:00
gingerBill e3360a0e5d Merge branch 'master' of https://github.com/odin-lang/Odin 2023-05-22 20:44:07 +01:00
gingerBill 4181444734 Add vendor:darwin/MetalKit to examples/all 2023-05-22 20:44:01 +01:00
gingerBill 7958708641 Add missing class method to NS.Number 2023-05-22 20:43:41 +01:00
gingerBill 40a8ed535a Add @(require_results) to core:math/ease 2023-05-22 20:43:19 +01:00
Jeroen van Rijn c7d571f0b5 Merge pull request #2553 from laytan/fix-2550-json-unicode-issue
fix #2550 json encoding should use surrogate pairs per RFC7159
2023-05-22 18:28:59 +02:00
Laytan Laats 5d54b710e7 fix #2550 json encoding should use surrogate pairs per RFC7159 2023-05-22 17:22:33 +02:00
gingerBill 248f14a1ef Correct entity flag generation 2023-05-22 15:29:01 +01:00
gingerBill b76fc58543 Inline are_types_identical_unique_tuples to improve odin_doc_type performance 2023-05-22 15:23:24 +01:00
gingerBill 9fc9981a9e Update calling convention to the most appropriate
- "odin" if the `context` is needed for `assert`
- "contextless" if multiple return values are needed (better for optimizations)
- "c" otherwise
2023-05-22 15:04:33 +01:00
gingerBill 8f563df7c5 Use proc "c" calling convention in NS Foundation package 2023-05-22 14:59:24 +01:00
gingerBill 730192adc4 Add procedure groups for Device_newBuffer and Texture_newTextureView 2023-05-22 14:51:46 +01:00
gingerBill 8bf32ac697 Minor change to handling of propagation of errors with --- as a value 2023-05-22 12:53:29 +01:00
gingerBill 540f724b1f Fix --- on variable declarations 2023-05-22 12:42:02 +01:00
gingerBill d5a8f2298e Restrict --- to variable declarations only 2023-05-22 12:37:26 +01:00
gingerBill 18c5a53685 Add @(require_results) and contextless to procedures in core:math/bits 2023-05-22 12:13:44 +01:00
gingerBill a1172d31f4 Add @(require_results) to core:math/fixed 2023-05-22 12:11:53 +01:00
gingerBill 396debb9cb Add @(require_results) to core:math/linalg's glsl and hlsl packages 2023-05-22 12:11:18 +01:00
gingerBill c4cb2f2378 Add "contextless" to core:math/linalg procedures 2023-05-22 12:07:37 +01:00
gingerBill 74ce99e0d7 Add @(require_results) core:math/linalg procedures 2023-05-22 12:05:56 +01:00
gingerBill 89a233ccd2 Add @(require_results) to core:math/noise 2023-05-22 12:00:17 +01:00
gingerBill 2df6cabee0 Add @(require_results) to core:math/rand 2023-05-22 11:59:44 +01:00
gingerBill 82023cd629 Add @(require_results) to core:math procedures 2023-05-22 11:58:01 +01:00
gingerBill 1e17f44991 Improve error handling for resize and reserve procedures 2023-05-22 11:47:36 +01:00
gingerBill 600c97cc0f Add missing Allocator_Error and @(require_results) to many procedures 2023-05-22 11:34:38 +01:00
gingerBill 7298054974 Add require_results to make builtin procedures 2023-05-22 11:19:13 +01:00
J.C. Moyer 4d5a442d1f Use compound literal storage for ValueDecl lvals
Prior to this commit, if a variable was initialized using a compound
literal, its associated storage would not be set. This commit makes the
variable always take on the storage of the compound literal.

Fixes #2466
2023-05-21 16:43:34 -04:00
J.C. Moyer 249f42f054 Add test for #2466 2023-05-21 16:42:48 -04:00
NoahR02 87788142bf Generate the new vulkan files 2023-05-20 19:15:32 -04:00
NoahR02 f0b08a6c67 Add required metal types 2023-05-20 19:14:19 -04:00
NoahR02 a144a49a9a Parse vulkan video constants in seperate section and
add MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT to the base constants
2023-05-20 19:07:34 -04:00
NoahR02 2167f1b567 Make sure the 's' is after Flags and not the ext name 2023-05-20 18:58:40 -04:00
NoahR02 c5c723b80c Parse C bit fields in parse_structs 2023-05-20 18:42:49 -04:00
NoahR02 66461c9dbc Parse Vulkan Video headers 2023-05-20 18:28:39 -04:00
NoahR02 d77103e53e Add MicromapUsageEXT** to convert_type
We should probably parse this in parse_structs.
2023-05-20 18:18:50 -04:00
Jeroen van Rijn 963908e508 Merge pull request #2548 from ntn9995/fix_stb_truetype
add missing fields to fontinfo
2023-05-20 15:33:11 +02:00
ikarus 9e5677ab02 add missing fields to fontinfo 2023-05-20 20:07:41 +07:00
gingerBill 46bb9bc5c7 Enforce an icmp when casting to i1 to correct behaviour for booleans which are not 0 or 1 2023-05-20 12:41:30 +01:00
Jeroen van Rijn 118ab60588 Merge pull request #2521 from elusivePorpoise/main
remove misleading defer if example
2023-05-19 22:01:13 +02:00
Elusive Porpoise 223ae61c89 added error printing 2023-05-19 11:36:53 -07:00
Jeroen van Rijn 1f4baba06e Merge pull request #2479 from Naught00/master
Change default executable extension for non-Windows platforms
2023-05-19 20:09:39 +02:00
Mark Naughton fa1ce7d5d1 Fix accidental check in 2023-05-19 18:56:35 +01:00
Mark Naughton 775a488a36 Fix windows write_directory() 2023-05-19 18:53:43 +01:00
Mark Naughton 018904f0ec Add write permissions check on output folder 2023-05-19 18:37:55 +01:00
Jeroen van Rijn b358641e7d Merge pull request #2547 from laytan/parse-address-can-return-nil
fix parse_address can return nil
2023-05-19 19:28:24 +02:00
Laytan Laats ff745e0ad8 fix parse_address can return nil 2023-05-19 19:14:25 +02:00
gingerBill 4201834b18 Make intrinsics.type_merge form a union of the types; ignoring duplicates 2023-05-19 12:11:18 +01:00
gingerBill 2631e07bea Add intrinsics.type_merge 2023-05-19 11:18:20 +01:00
Jeroen van Rijn 76a1851cb8 Merge pull request #2546 from kstreets/master
Fix #2545 - Typo in vec4 lerping procedures
2023-05-18 22:40:44 +02:00
KyleRhoads45 87a1792677 Fix #2545 - Typo in vec4 lerping procedures 2023-05-18 13:19:22 -07:00
Mark Naughton 413077a5d9 Fix single-file package case 2023-05-18 13:23:17 +01:00
gingerBill d56fdd2937 Add fmt:"s,0" tags to UTF-16 strings in dxgi.odin 2023-05-18 12:00:23 +01:00
gingerBill 6639b7d017 Merge pull request #2500 from Ahsan-Sarbaz/master
Fixed a bug in DXGI
2023-05-18 11:57:55 +01:00
gingerBill 7702a488e5 Merge pull request #2474 from cshenton/patch-1
Add Dynamic Resource Root Signature flags
2023-05-18 11:56:35 +01:00
gingerBill 3108752a0c Fix #2518 2023-05-18 11:55:37 +01:00
gingerBill 56c0d32ea0 Fix #2526 2023-05-18 11:52:16 +01:00
gingerBill c0e84b0592 Fix #2536 2023-05-18 11:39:18 +01:00
gingerBill f2e590be7a Fix #2544 2023-05-18 11:35:47 +01:00
gingerBill 60ec3594ab Remove unused variable 2023-05-18 11:29:27 +01:00
gingerBill 49d1f6aca0 Merge branch 'master' into separate-int-word-sizes 2023-05-18 11:26:57 +01:00
gingerBill 49cd9648b0 Merge pull request #2512 from jasonKercher/master
update os2 to match core changes
2023-05-18 11:26:16 +01:00
gingerBill 1692dcf8d5 Merge pull request #2514 from ryuukk/patch-2
Missing cast
2023-05-18 11:26:02 +01:00
gingerBill 5ec4719124 Merge pull request #2523 from jcmoyer/fix-2056
Zero non-diagonal elements when converting to matrix
2023-05-18 11:25:44 +01:00
gingerBill 911c98e235 Merge pull request #2525 from laytan/fix-buffer-init-cap-0-wrong-allocator
fix bytes.buffer_init_allocator not using given allocator if len/cap is 0
2023-05-18 11:24:27 +01:00
gingerBill 535c64c318 Merge pull request #2534 from Tetralux/fix-append-nothing-loc
[runtime] Pass along #caller_location in append_nothing()
2023-05-18 11:23:46 +01:00
gingerBill 171f38b9b5 Allow implicit conversion between boolean types within or_return
This is to improve the experience using third-party code, especially foreign C-like code which may use a distinct boolean or a different sized one
2023-05-18 11:06:02 +01:00
jason b2645b3201 add rehash to map_shrink_dynamic 2023-05-17 00:06:31 -04:00
jason a9936d1570 implement random map seed 2023-05-16 23:49:55 -04:00
jason 3032a4274d implement backward shift during map insertion 2023-05-16 16:56:32 -04:00
Jeroen van Rijn 31c21a054b Merge pull request #2543 from Yawning/fix/cpuid-test
core/sys/info: Fix the CPUID check
2023-05-16 17:04:42 +02:00
Yawning Angel def4fdc3f3 core/sys/info: Fix the CPUID check
This needs to test that the n-th bit is set.
2023-05-16 23:52:15 +09:00
Jeroen van Rijn 3fed1af7df Merge pull request #2542 from Yawning/bug/cpuid-osxsave
core/sys/info: Workaround extremely rare XGETBV issues
2023-05-16 16:07:43 +02:00
Yawning Angel adb4692ce8 core/sys/info: Workaround extremely rare XGETBV issues
Someone ran into this on Discord, so adopt the same workaround that
chrome did, by checking both OSXSAVE and XSAVE before calling XGETBV.

The old way of detecting AVX is correct per Intel, but such is life.
2023-05-16 22:56:16 +09:00
gingerBill bb4ff84a4a Add extra mutex for error block stuff 2023-05-16 11:52:02 +01:00
Jeroen van Rijn 5d2c1b175e Merge pull request #2541 from laytan/add-hex-and-expand-percent-decoding
fix hex.encode and add tests for the package
2023-05-15 22:32:27 +02:00
Laytan Laats 2ab6de8ee4 fix hex.encode and add tests for the package 2023-05-15 20:52:07 +02:00
Jeroen van Rijn 1896ae5d15 Merge pull request #2533 from laytan/add-hex-and-expand-percent-decoding
add encoding/hex and use it to expand the percent decoding chars
2023-05-15 19:25:31 +02:00
Laytan Laats 6e4fab19a2 fix indentation and simplify hex.decode_sequence 2023-05-15 18:40:36 +02:00
gingerBill 103dcfe897 Merge pull request #2539 from powerc9000/patch-6
lua MAXSTACK should be 1000000 on 32 bits OR greater
2023-05-14 22:05:28 +01:00
Clay Murray 8caadbacf7 lua MAXSTACK should be 1000000 on 32 bits OR greater
Code only checks if 4 bytes for `rawptr` size. However lua defines the macro (that I assume the odin code is based on) as:

```
/*
@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits.
*/
#define LUAI_IS32INT	((UINT_MAX >> 30) >= 3)
```

This error broke `upvalues` because it would be looking for the wrong index for lua to find them at.
2023-05-14 14:00:38 -06:00
Jeroen van Rijn 870d776875 Merge pull request #2537 from CORDEA/feature/join-url-queries
Join URL queries with &
2023-05-14 09:03:10 +02:00
Yoshihiro Tanaka 59e66ffe49 Add test for net.split_url 2023-05-14 12:15:20 +09:00
Yoshihiro Tanaka 418a0132d0 Join URL queries with & 2023-05-14 12:15:20 +09:00
Laytan Laats a381846034 add encoding/hex and use it to expand the percent decoding chars 2023-05-14 03:23:24 +02:00
Tetralux 1c5ce75d9f [runtime] Pass along #caller_location in append_nothing() 2023-05-12 23:05:28 +00:00
gingerBill 8693a045bb Revert "Change intrinsics.read_cycle_counter on ARM64"
This reverts commit b567679eb6.
2023-05-12 11:50:49 +01:00
gingerBill b567679eb6 Change intrinsics.read_cycle_counter on ARM64 2023-05-12 11:34:01 +01:00
Jeroen van Rijn e6c8d3d1db Merge pull request #2532 from j0-1/j0-1-patch-1
Fixed incorrect header and typo
2023-05-11 22:28:37 +02:00
j0-1 12c4afd824 Fixed incorrect header and typo 2023-05-11 11:26:16 -07:00
Jeroen van Rijn 968a07ed7a Merge pull request #2531 from jasonKercher/fix2530
add nil check to heap_alloc calls (issue 2530)
2023-05-11 20:20:03 +02:00
jason f9c600a760 add nil check to heap_alloc calls (issue 2530) 2023-05-11 14:04:09 -04:00
Jeroen van Rijn 82561cfbac Merge pull request #2528 from matias-eduardo/patch-1
Patch "no_copy" typo in parser.cpp
2023-05-10 09:11:46 +02:00
matias 277ae4e2b0 Patch "no_copy" typo in parser.cpp 2023-05-10 02:58:17 -04:00
Jeroen van Rijn 0f9e747583 Merge pull request #2520 from matias-eduardo/master
Allow for custom sleep duration in tsc frequency fallback
2023-05-09 23:03:47 +02:00
Matias Fernandez 4e146a75b6 Allow user to pass in scale directly in spall.context_create 2023-05-09 16:43:26 -04:00
Jeroen van Rijn 33d0e2037b Merge pull request #2524 from laytan/fix-url-parse-leak
fix leak in url_parse
2023-05-09 21:46:51 +02:00
Laytan Laats 7a04b7262e fix bytes.buffer_init_allocator not using given allocator if len/cap is 0 2023-05-09 21:25:15 +02:00
Laytan Laats f2d5e4b995 fix leak in url_parse 2023-05-09 21:05:16 +02:00
J.C. Moyer ada42aa184 Add test for issue #2056 2023-05-09 12:37:12 -04:00
J.C. Moyer ed580b3060 Zero non-diagonal elements when converting to matrix
Fixes #2056
2023-05-09 12:00:38 -04:00
Jeroen van Rijn 29e4762011 Merge pull request #2519 from colrdavidson/revert-2462-master
Revert "Fix: header directories in Unix build script"
2023-05-09 08:27:47 +02:00
Elusive Porpoise eff4833840 remove misleading example 2023-05-08 23:13:27 -07:00
Matias Fernandez 9867037aa2 Revert "Add the waits that support I/O completion routines in kernel32.odin"
This reverts commit 46da53ba15.
2023-05-09 00:16:17 -04:00
Matias Fernandez 57c14f6a9b Allow custom sleep on tsc fallback.
This gives the user more control over the spectrum of precision vs. load time on Windows. Spall's output with much lower sleep times is still useful in my experience.

NOTE: A better API might be to allow the user to pass the freq as a param to "create_context" in case they already paid for it beforehand, but this seems fine for now.
2023-05-09 00:03:58 -04:00
Matias Fernandez 1ed105205c Merge branch 'master' of https://github.com/matias-eduardo/Odin 2023-05-08 23:52:21 -04:00
Colin Davidson 8233f49beb Revert "Fix: header directories in Unix build script" 2023-05-08 20:13:33 -07:00
Jeroen van Rijn 2c01a4613c Merge pull request #2516 from colrdavidson/read_at_fix
Make read_at and write_at more consistent between platforms
2023-05-07 08:52:37 +02:00
Colin Davidson b0eda47b26 prevent infinite-loop on EOF 2023-05-06 17:52:08 -07:00
Colin Davidson 291111e626 oops. define e 2023-05-06 17:23:44 -07:00
Colin Davidson 47693da4aa Make read_at and write_at more consistent between platforms 2023-05-06 17:14:11 -07:00
Jeroen van Rijn 9f39209712 Merge pull request #2513 from laytan/add-time-weekday
add time.weekday proc
2023-05-06 20:20:13 +02:00
Laytan Laats c47dcbbe2f fix spacing 2023-05-06 19:39:39 +02:00
ryuukk f313538ea5 Missing cast 2023-05-06 18:00:33 +02:00
Laytan Laats 956ffdf654 add time.weekday proc 2023-05-05 20:55:59 +02:00
jason ef4a527c36 default to O_NOCTTY in open 2023-05-04 11:46:39 -04:00
jason 3fe0680ad5 update os2 for recent core changes 2023-05-04 10:00:06 -04:00
gingerBill 182b269e46 Merge pull request #2511 from zhibog/botan3
Add Botan3 libraries and use VS 2022 for Windows builds
2023-05-03 22:14:17 +01:00
zhibog 05856ac93e Change nightly to VS 2022 too 2023-05-03 21:51:40 +02:00
zhibog 60c29e195a Windows requires the botan-3 naming due to the new release 2023-05-03 21:35:06 +02:00
zhibog 6b23662ce6 Fix typo 2023-05-03 21:15:50 +02:00
zhibog 77d6364405 Try Windows 2022, since the windows tests failed. Likely because I compiled them on a newer version of VS. Also added another when statement to make sure Linux still uses botan-2, because they haven't updated 2023-05-03 21:12:27 +02:00
zhibog 077a611a5e Add Botan 3.0, comment some tests, due to removed algorithms 2023-05-03 20:55:11 +02:00
gingerBill e82146bf17 Merge branch 'master' into separate-int-word-sizes 2023-05-03 17:06:37 +01:00
Jon Lipstate f5dcbf517b helpful errors custom-attrs 2023-04-30 18:36:00 -07:00
Ahsan-Sarbaz 808e7ed4ae Fixed Bug in DXGI 2023-05-01 00:16:20 +05:00
Mark Naughton 4b4481ea27 Simplify extension addition logic 2023-04-26 16:39:47 +01:00
Mark Naughton e84802468b Use buildpath instead of init_filename 2023-04-26 15:48:59 +01:00
Mark Naughton 1a5ed4eb7f Fix .bin not being applied for relative directory 2023-04-26 14:10:22 +01:00
Mark Naughton 5151403aaa Fix Windows version of get_current_directory 2023-04-25 12:08:15 +01:00
Mark Naughton 67b6a8ee89 Add Windows equivalent of get_current_directory 2023-04-24 14:26:53 +01:00
Mark Naughton 780375d865 Add .bin extension in extra case 2023-04-24 12:57:59 +01:00
Mark Naughton cbcf94669e Add get_current_directory() 2023-04-24 12:57:34 +01:00
Matias Fernandez 46da53ba15 Add the waits that support I/O completion routines in kernel32.odin 2023-04-23 22:08:12 -04:00
Mark Naughton 06e8d03fba Use last element for directory collision check 2023-04-23 21:15:08 +01:00
Mark Naughton a6b9341593 Add .bin extension the case of a collision
The directory name is used to determine the executable name. In the case
that the directory and output executable are in conflict, a .bin
extension is added.
2023-04-23 18:53:00 +01:00
Mark Naughton 47610725ea Change default executable extension
Putting a program into your path on a UNIX system with a
file extension means that you have to type the extension out for every
invocation of the program. A better default is to have no extension at
all since most people will end up removing it anyway.

This change does not affect Windows since the .exe extension is set
after the default extension if compiling on Windows.
2023-04-23 17:02:56 +01:00
Charlie Shenton c7d4af5c79 Add Dynamic Resource Root Signature flags
Add flag values associated with dynamics resources (ResourceDescriptorHeap and SamplerDescriptorHeap) see https://microsoft.github.io/DirectX-Specs/d3d/HLSL_SM_6_6_DynamicResources.html for details
2023-04-22 16:39:01 +10:00
gingerBill 685f7d0fea Rename word_size to ptr_size internally to make it clearer 2023-04-20 12:18:13 +01:00
gingerBill f5d9ca64f9 Begin work on new pseudo-architecture: wasm64p32 2023-04-20 12:02:32 +01:00
gingerBill cde442fa2c Add internal padding to types where ptr size != int size 2023-04-20 11:55:18 +01:00
gingerBill 84f966cb8f Begin work on separating int and word sizes (i.e. size_of(int) might not equal size_of(uintptr)) 2023-04-20 11:46:41 +01:00
Skytrias f36e19e86f fix GL2 2022-12-24 11:47:57 +01:00
Skytrias 86fada718e optional constants, starting GL2 fixes 2022-12-24 11:30:15 +01:00
Skytrias 2a94b66f4d test 2022-12-24 11:19:12 +01:00
Michael Kutowski 4ee413aa32 Merge branch 'odin-lang:master' into skytrias-vendor-additions 2022-12-24 10:39:01 +01:00
Lucas Perlind 2d824e4809 Fix out or range error with _alloc_command_line_arguments in darwin 2022-12-23 09:37:30 +11:00
skytrias 9474c99795 add freeLoadedData flag in case you dont want to remove font memory (e.g. #load) 2022-12-21 01:36:00 +01:00
Michael Kutowski 84a7f222ff mention fontstash and nanovg in reamde 2022-12-20 12:27:23 +01:00
skytrias d29423c24e add fontstash and nanovg port from heimdall 2022-12-20 12:17:23 +01:00
gingerBill 02a8bba02e Merge branch 'master' into fix/freebsd-syscall 2022-07-24 22:27:45 +01:00
Yawning Angel 6ea68869c9 src: "Fix" the system call intrinsic for FreeBSD
FreeBSD's systemcall handler clears out R8, R9, and R10 prior to
`sysretq`, and additionally returns positive errno (with CF) set on
error.  This modifies the syscall intrinsic such that LLVM knows
about the additional clobbered registers.

Note that propagating CF back to the caller of the syscall intrinsic
is left for a future PR.  As far as I can tell, Darwin does not use
the syscall intrinsic at all, and FreeBSD only uses it for SYS_GETTID,
so this should be "ok" for now.

See: sys/amd64/amd64/exception.S in the FreeBSD src for more details.
2021-11-13 20:40:27 +00:00
333 changed files with 33583 additions and 16504 deletions
+19 -14
View File
@@ -56,9 +56,9 @@ jobs:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: Download LLVM and setup PATH - name: Download LLVM, botan and setup PATH
run: | run: |
brew install llvm@11 brew install llvm@11 botan
echo "/usr/local/opt/llvm@11/bin" >> $GITHUB_PATH echo "/usr/local/opt/llvm@11/bin" >> $GITHUB_PATH
TMP_PATH=$(xcrun --show-sdk-path)/user/include TMP_PATH=$(xcrun --show-sdk-path)/user/include
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
@@ -87,6 +87,11 @@ jobs:
cd tests/core cd tests/core
make make
timeout-minutes: 10 timeout-minutes: 10
- name: Vendor library tests
run: |
cd tests/vendor
make
timeout-minutes: 10
- name: Odin internals tests - name: Odin internals tests
run: | run: |
cd tests/internal cd tests/internal
@@ -99,13 +104,13 @@ jobs:
run: ./odin check examples/all -vet -strict-style -target:linux_arm64 run: ./odin check examples/all -vet -strict-style -target:linux_arm64
timeout-minutes: 10 timeout-minutes: 10
build_windows: build_windows:
runs-on: windows-2019 runs-on: windows-2022
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: build Odin - name: build Odin
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
./build.bat 1 ./build.bat 1
- name: Odin version - name: Odin version
run: ./odin version run: ./odin version
@@ -116,65 +121,65 @@ jobs:
- name: Odin check - name: Odin check
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/demo -vet odin check examples/demo -vet
timeout-minutes: 10 timeout-minutes: 10
- name: Odin run - name: Odin run
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo odin run examples/demo
timeout-minutes: 10 timeout-minutes: 10
- name: Odin run -debug - name: Odin run -debug
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo -debug odin run examples/demo -debug
timeout-minutes: 10 timeout-minutes: 10
- name: Odin check examples/all - name: Odin check examples/all
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style odin check examples/all -strict-style
timeout-minutes: 10 timeout-minutes: 10
- name: Core library tests - name: Core library tests
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\core cd tests\core
call build.bat call build.bat
timeout-minutes: 10 timeout-minutes: 10
- name: Vendor library tests - name: Vendor library tests
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\vendor cd tests\vendor
call build.bat call build.bat
timeout-minutes: 10 timeout-minutes: 10
- name: Odin internals tests - name: Odin internals tests
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\internal cd tests\internal
call build.bat call build.bat
timeout-minutes: 10 timeout-minutes: 10
- name: Odin documentation tests - name: Odin documentation tests
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\documentation cd tests\documentation
call build.bat call build.bat
timeout-minutes: 10 timeout-minutes: 10
- name: core:math/big tests - name: core:math/big tests
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\core\math\big cd tests\core\math\big
call build.bat call build.bat
timeout-minutes: 10 timeout-minutes: 10
- name: Odin check examples/all for Windows 32bits - name: Odin check examples/all for Windows 32bits
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style -target:windows_i386 odin check examples/all -strict-style -target:windows_i386
timeout-minutes: 10 timeout-minutes: 10
+6 -3
View File
@@ -7,18 +7,19 @@ on:
jobs: jobs:
build_windows: build_windows:
runs-on: windows-2019 if: github.repository == 'odin-lang/Odin'
runs-on: windows-2022
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: build Odin - name: build Odin
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
./build.bat 1 1 ./build.bat 1 1
- name: Odin run - name: Odin run
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo odin run examples/demo
- name: Copy artifacts - name: Copy artifacts
run: | run: |
@@ -37,6 +38,7 @@ jobs:
name: windows_artifacts name: windows_artifacts
path: dist path: dist
build_ubuntu: build_ubuntu:
if: github.repository == 'odin-lang/Odin'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
@@ -61,6 +63,7 @@ jobs:
name: ubuntu_artifacts name: ubuntu_artifacts
path: dist path: dist
build_macos: build_macos:
if: github.repository == 'odin-lang/Odin'
runs-on: macOS-latest runs-on: macOS-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
+2 -1
View File
@@ -270,6 +270,7 @@ bin/
# - Linux/MacOS # - Linux/MacOS
odin odin
!odin/
odin.dSYM odin.dSYM
*.bin *.bin
demo.bin demo.bin
@@ -286,4 +287,4 @@ shared/
*.sublime-workspace *.sublime-workspace
examples/bug/ examples/bug/
build.sh build.sh
!core/debug/ !core/debug/
+15 -10
View File
@@ -3,18 +3,20 @@
setlocal EnableDelayedExpansion setlocal EnableDelayedExpansion
where /Q cl.exe || ( where /Q cl.exe || (
set __VSCMD_ARG_NO_LOGO=1 set __VSCMD_ARG_NO_LOGO=1
for /f "tokens=*" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop -property installationPath') do set VS=%%i for /f "tokens=*" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop -property installationPath') do set VS=%%i
if "!VS!" equ "" ( if "!VS!" equ "" (
echo ERROR: Visual Studio installation not found echo ERROR: Visual Studio installation not found
exit /b 1 exit /b 1
) )
call "!VS!\VC\Auxiliary\Build\vcvarsall.bat" amd64 || exit /b 1 call "!VS!\VC\Auxiliary\Build\vcvarsall.bat" amd64 || exit /b 1
) )
if "%VSCMD_ARG_TGT_ARCH%" neq "x64" ( if "%VSCMD_ARG_TGT_ARCH%" neq "x64" (
echo ERROR: please run this from MSVC x64 native tools command prompt, 32-bit target is not supported! if "%ODIN_IGNORE_MSVC_CHECK%" == "" (
exit /b 1 echo ERROR: please run this from MSVC x64 native tools command prompt, 32-bit target is not supported!
exit /b 1
)
) )
for /f "usebackq tokens=1,2 delims=,=- " %%i in (`wmic os get LocalDateTime /value`) do @if %%i==LocalDateTime ( for /f "usebackq tokens=1,2 delims=,=- " %%i in (`wmic os get LocalDateTime /value`) do @if %%i==LocalDateTime (
@@ -49,7 +51,10 @@ set compiler_flags= -nologo -Oi -TP -fp:precise -Gm- -MP -FC -EHsc- -GR- -GF
set compiler_defines= -DODIN_VERSION_RAW=\"%odin_version_raw%\" set compiler_defines= -DODIN_VERSION_RAW=\"%odin_version_raw%\"
if not exist .git\ goto skip_git_hash if not exist .git\ goto skip_git_hash
for /f %%i in ('git rev-parse --short HEAD') do set GIT_SHA=%%i for /f "tokens=1,2" %%i IN ('git show "--pretty=%%cd %%h" "--date=format:%%Y-%%m" --no-patch --no-notes HEAD') do (
set odin_version_raw=dev-%%i
set GIT_SHA=%%j
)
if %ERRORLEVEL% equ 0 set compiler_defines=%compiler_defines% -DGIT_SHA=\"%GIT_SHA%\" if %ERRORLEVEL% equ 0 set compiler_defines=%compiler_defines% -DGIT_SHA=\"%GIT_SHA%\"
:skip_git_hash :skip_git_hash
+16 -8
View File
@@ -4,23 +4,24 @@ set -eu
: ${CXX=clang++} : ${CXX=clang++}
: ${CPPFLAGS=} : ${CPPFLAGS=}
: ${CXXFLAGS=} : ${CXXFLAGS=}
: ${INCLUDE_DIRECTORIES=}
: ${LDFLAGS=} : ${LDFLAGS=}
: ${ODIN_VERSION=dev-$(date +"%Y-%m")} : ${ODIN_VERSION=dev-$(date +"%Y-%m")}
: ${GIT_SHA=} : ${GIT_SHA=}
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"$ODIN_VERSION\""
CXXFLAGS="$CXXFLAGS -std=c++14" CXXFLAGS="$CXXFLAGS -std=c++14"
INCLUDE_DIRECTORIES="$INCLUDE_DIRECTORIES -Isrc/"
LDFLAGS="$LDFLAGS -pthread -lm -lstdc++" LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
if [ -d ".git" ]; then if [ -d ".git" ] && [ $(which git) ]; then
GIT_SHA=$(git rev-parse --short HEAD || :) versionTag=( $(git show --pretty='%cd %h' --date=format:%Y-%m --no-patch --no-notes HEAD) )
if [ "$GIT_SHA" ]; then if [ $? -eq 0 ]; then
ODIN_VERSION="dev-${versionTag[0]}"
GIT_SHA="${versionTag[1]}"
CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\"" CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\""
fi fi
fi fi
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"$ODIN_VERSION\""
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value" DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
OS=$(uname) OS=$(uname)
@@ -137,7 +138,14 @@ build_odin() {
EXTRAFLAGS="-O3" EXTRAFLAGS="-O3"
;; ;;
release-native) release-native)
EXTRAFLAGS="-O3 -march=native" local ARCH=$(uname -m)
if [ "${ARCH}" == "arm64" ]; then
# Use preferred flag for Arm (ie arm64 / aarch64 / etc)
EXTRAFLAGS="-O3 -mcpu=native"
else
# Use preferred flag for x86 / amd64
EXTRAFLAGS="-O3 -march=native"
fi
;; ;;
nightly) nightly)
EXTRAFLAGS="-DNIGHTLY -O3" EXTRAFLAGS="-DNIGHTLY -O3"
@@ -148,7 +156,7 @@ build_odin() {
esac esac
set -x set -x
$CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $INCLUDE_DIRECTORIES $EXTRAFLAGS $LDFLAGS -o odin $CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $EXTRAFLAGS $LDFLAGS -o odin
set +x set +x
} }
+22 -44
View File
@@ -14,51 +14,29 @@ read_writer_init :: proc(rw: ^Read_Writer, r: ^Reader, w: ^Writer) {
} }
read_writer_to_stream :: proc(rw: ^Read_Writer) -> (s: io.Stream) { read_writer_to_stream :: proc(rw: ^Read_Writer) -> (s: io.Stream) {
s.stream_data = rw s.procedure = _read_writer_procedure
s.stream_vtable = &_read_writer_vtable s.data = rw
return return
} }
@(private) @(private)
_read_writer_vtable := io.Stream_VTable{ _read_writer_procedure := proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { rw := (^Read_Writer)(stream_data)
b := (^Read_Writer)(s.stream_data).r n_int: int
return reader_read(b, p) #partial switch mode {
}, case .Flush:
impl_unread_byte = proc(s: io.Stream) -> io.Error { err = writer_flush(rw.w)
b := (^Read_Writer)(s.stream_data).r return
return reader_unread_byte(b) case .Read:
}, n_int, err = reader_read(rw.r, p)
impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) { n = i64(n_int)
b := (^Read_Writer)(s.stream_data).r return
return reader_read_rune(b) case .Write:
}, n_int, err = writer_write(rw.w, p)
impl_unread_rune = proc(s: io.Stream) -> io.Error { n = i64(n_int)
b := (^Read_Writer)(s.stream_data).r return
return reader_unread_rune(b) case .Query:
}, return io.query_utility({.Flush, .Read, .Write, .Query})
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) { }
b := (^Read_Writer)(s.stream_data).r return 0, .Empty
return reader_write_to(b, w) }
},
impl_flush = proc(s: io.Stream) -> io.Error {
b := (^Read_Writer)(s.stream_data).w
return writer_flush(b)
},
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
b := (^Read_Writer)(s.stream_data).w
return writer_write(b, p)
},
impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
b := (^Read_Writer)(s.stream_data).w
return writer_write_byte(b, c)
},
impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
b := (^Read_Writer)(s.stream_data).w
return writer_write_rune(b, r)
},
impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
b := (^Read_Writer)(s.stream_data).w
return writer_read_from(b, r)
},
}
+13 -45
View File
@@ -311,18 +311,6 @@ reader_write_to :: proc(b: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
} }
m: i64 m: i64
if nr, ok := io.to_writer_to(b.rd); ok {
m, err = io.write_to(nr, w)
n += m
return n, err
}
if nw, ok := io.to_reader_from(w); ok {
m, err = io.read_from(nw, b.rd)
n += m
return n, err
}
if b.w-b.r < len(b.buf) { if b.w-b.r < len(b.buf) {
if err = _reader_read_new_chunk(b); err != nil { if err = _reader_read_new_chunk(b); err != nil {
return return
@@ -352,48 +340,28 @@ reader_write_to :: proc(b: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
// reader_to_stream converts a Reader into an io.Stream // reader_to_stream converts a Reader into an io.Stream
reader_to_stream :: proc(b: ^Reader) -> (s: io.Stream) { reader_to_stream :: proc(b: ^Reader) -> (s: io.Stream) {
s.stream_data = b s.data = b
s.stream_vtable = &_reader_vtable s.procedure = _reader_proc
return return
} }
@(private) @(private)
_reader_vtable := io.Stream_VTable{ _reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
impl_destroy = proc(s: io.Stream) -> io.Error { b := (^Reader)(stream_data)
b := (^Reader)(s.stream_data) #partial switch mode {
case .Read:
return io._i64_err(reader_read(b, p))
case .Destroy:
reader_destroy(b) reader_destroy(b)
return nil return
}, case .Query:
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { return io.query_utility({.Read, .Destroy, .Query})
b := (^Reader)(s.stream_data) }
return reader_read(b, p) return 0, .Empty
},
impl_read_byte = proc(s: io.Stream) -> (c: byte, err: io.Error) {
b := (^Reader)(s.stream_data)
return reader_read_byte(b)
},
impl_unread_byte = proc(s: io.Stream) -> io.Error {
b := (^Reader)(s.stream_data)
return reader_unread_byte(b)
},
impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
b := (^Reader)(s.stream_data)
return reader_read_rune(b)
},
impl_unread_rune = proc(s: io.Stream) -> io.Error {
b := (^Reader)(s.stream_data)
return reader_unread_rune(b)
},
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
b := (^Reader)(s.stream_data)
return reader_write_to(b, w)
},
} }
// //
// Utility procedures // Utility procedures
// //
+20 -39
View File
@@ -173,14 +173,6 @@ writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) {
if b.err != nil { if b.err != nil {
return 0, b.err return 0, b.err
} }
if writer_buffered(b) == 0 {
if w, ok := io.to_reader_from(b.wr); !ok {
n, err = io.read_from(w, r)
b.err = err
return
}
}
for { for {
if writer_available(b) == 0 { if writer_available(b) == 0 {
writer_flush(b) or_return writer_flush(b) or_return
@@ -222,46 +214,35 @@ writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) {
// writer_to_stream converts a Writer into an io.Stream // writer_to_stream converts a Writer into an io.Stream
writer_to_stream :: proc(b: ^Writer) -> (s: io.Stream) { writer_to_stream :: proc(b: ^Writer) -> (s: io.Stream) {
s.stream_data = b s.data = b
s.stream_vtable = &_writer_vtable s.procedure = _writer_proc
return return
} }
// writer_to_stream converts a Writer into an io.Stream // writer_to_stream converts a Writer into an io.Stream
writer_to_writer :: proc(b: ^Writer) -> (s: io.Writer) { writer_to_writer :: proc(b: ^Writer) -> (s: io.Writer) {
s.stream_data = b return writer_to_stream(b)
s.stream_vtable = &_writer_vtable
return
} }
@(private) @(private)
_writer_vtable := io.Stream_VTable{ _writer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
impl_destroy = proc(s: io.Stream) -> io.Error { b := (^Writer)(stream_data)
b := (^Writer)(s.stream_data) #partial switch mode {
case .Flush:
err = writer_flush(b)
return
case .Write:
n_int: int
n_int, err = writer_write(b, p)
n = i64(n_int)
return
case .Destroy:
writer_destroy(b) writer_destroy(b)
return nil return
}, case .Query:
impl_flush = proc(s: io.Stream) -> io.Error { return io.query_utility({.Flush, .Write, .Destroy, .Query})
b := (^Writer)(s.stream_data) }
return writer_flush(b) return 0, .Empty
},
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
b := (^Writer)(s.stream_data)
return writer_write(b, p)
},
impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
b := (^Writer)(s.stream_data)
return writer_write_byte(b, c)
},
impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
b := (^Writer)(s.stream_data)
return writer_write_rune(b, r)
},
impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
b := (^Writer)(s.stream_data)
return writer_read_from(b, r)
},
} }
+27 -60
View File
@@ -38,6 +38,11 @@ buffer_init_string :: proc(b: ^Buffer, s: string) {
} }
buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) { buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) {
if b.buf == nil {
b.buf = make([dynamic]byte, len, cap, allocator)
return
}
b.buf.allocator = allocator b.buf.allocator = allocator
reserve(&b.buf, cap) reserve(&b.buf, cap)
resize(&b.buf, len) resize(&b.buf, len)
@@ -370,69 +375,31 @@ buffer_read_from :: proc(b: ^Buffer, r: io.Reader) -> (n: i64, err: io.Error) #n
buffer_to_stream :: proc(b: ^Buffer) -> (s: io.Stream) { buffer_to_stream :: proc(b: ^Buffer) -> (s: io.Stream) {
s.stream_data = b s.data = b
s.stream_vtable = &_buffer_vtable s.procedure = _buffer_proc
return return
} }
@(private) @(private)
_buffer_vtable := io.Stream_VTable{ _buffer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
impl_size = proc(s: io.Stream) -> i64 { b := (^Buffer)(stream_data)
b := (^Buffer)(s.stream_data) #partial switch mode {
return i64(buffer_capacity(b)) case .Read:
}, return io._i64_err(buffer_read(b, p))
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { case .Read_At:
b := (^Buffer)(s.stream_data) return io._i64_err(buffer_read_at(b, p, int(offset)))
return buffer_read(b, p) case .Write:
}, return io._i64_err(buffer_write(b, p))
impl_read_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) { case .Write_At:
b := (^Buffer)(s.stream_data) return io._i64_err(buffer_write_at(b, p, int(offset)))
return buffer_read_at(b, p, int(offset)) case .Size:
}, n = i64(buffer_capacity(b))
impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) { return
b := (^Buffer)(s.stream_data) case .Destroy:
return buffer_read_byte(b)
},
impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
b := (^Buffer)(s.stream_data)
return buffer_read_rune(b)
},
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
b := (^Buffer)(s.stream_data)
return buffer_write(b, p)
},
impl_write_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
b := (^Buffer)(s.stream_data)
return buffer_write_at(b, p, int(offset))
},
impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
b := (^Buffer)(s.stream_data)
return buffer_write_byte(b, c)
},
impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
b := (^Buffer)(s.stream_data)
return buffer_write_rune(b, r)
},
impl_unread_byte = proc(s: io.Stream) -> io.Error {
b := (^Buffer)(s.stream_data)
return buffer_unread_byte(b)
},
impl_unread_rune = proc(s: io.Stream) -> io.Error {
b := (^Buffer)(s.stream_data)
return buffer_unread_rune(b)
},
impl_destroy = proc(s: io.Stream) -> io.Error {
b := (^Buffer)(s.stream_data)
buffer_destroy(b) buffer_destroy(b)
return nil return
}, case .Query:
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) { return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Size, .Destroy})
b := (^Buffer)(s.stream_data) }
return buffer_write_to(b, w) return 0, .Empty
},
impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
b := (^Buffer)(s.stream_data)
return buffer_read_from(b, r)
},
} }
+20 -39
View File
@@ -16,8 +16,8 @@ reader_init :: proc(r: ^Reader, s: []byte) {
} }
reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) { reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
s.stream_data = r s.data = r
s.stream_vtable = &_reader_vtable s.procedure = _reader_proc
return return
} }
@@ -137,41 +137,22 @@ reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
@(private) @(private)
_reader_vtable := io.Stream_VTable{ _reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
impl_size = proc(s: io.Stream) -> i64 { r := (^Reader)(stream_data)
r := (^Reader)(s.stream_data) #partial switch mode {
return reader_size(r) case .Read:
}, return io._i64_err(reader_read(r, p))
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { case .Read_At:
r := (^Reader)(s.stream_data) return io._i64_err(reader_read_at(r, p, offset))
return reader_read(r, p) case .Seek:
}, n, err = reader_seek(r, offset, whence)
impl_read_at = proc(s: io.Stream, p: []byte, off: i64) -> (n: int, err: io.Error) { return
r := (^Reader)(s.stream_data) case .Size:
return reader_read_at(r, p, off) n = reader_size(r)
}, return
impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) { case .Query:
r := (^Reader)(s.stream_data) return io.query_utility({.Read, .Read_At, .Seek, .Size, .Query})
return reader_read_byte(r) }
}, return 0, .Empty
impl_unread_byte = proc(s: io.Stream) -> io.Error {
r := (^Reader)(s.stream_data)
return reader_unread_byte(r)
},
impl_read_rune = proc(s: io.Stream) -> (ch: rune, size: int, err: io.Error) {
r := (^Reader)(s.stream_data)
return reader_read_rune(r)
},
impl_unread_rune = proc(s: io.Stream) -> io.Error {
r := (^Reader)(s.stream_data)
return reader_unread_rune(r)
},
impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
r := (^Reader)(s.stream_data)
return reader_seek(r, offset, whence)
},
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
r := (^Reader)(s.stream_data)
return reader_write_to(r, w)
},
} }
+2 -2
View File
@@ -1118,7 +1118,7 @@ expand_macro :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) -> bool {
search_include_next :: proc(cpp: ^Preprocessor, filename: string) -> (path: string, ok: bool) { search_include_next :: proc(cpp: ^Preprocessor, filename: string) -> (path: string, ok: bool) {
for ; cpp.include_next_index < len(cpp.include_paths); cpp.include_next_index += 1 { for ; cpp.include_next_index < len(cpp.include_paths); cpp.include_next_index += 1 {
tpath := filepath.join(elems={cpp.include_paths[cpp.include_next_index], filename}, allocator=context.temp_allocator) tpath := filepath.join({cpp.include_paths[cpp.include_next_index], filename}, allocator=context.temp_allocator)
if os.exists(tpath) { if os.exists(tpath) {
return strings.clone(tpath), true return strings.clone(tpath), true
} }
@@ -1136,7 +1136,7 @@ search_include_paths :: proc(cpp: ^Preprocessor, filename: string) -> (path: str
} }
for include_path in cpp.include_paths { for include_path in cpp.include_paths {
tpath := filepath.join(elems={include_path, filename}, allocator=context.temp_allocator) tpath := filepath.join({include_path, filename}, allocator=context.temp_allocator)
if os.exists(tpath) { if os.exists(tpath) {
path, ok = strings.clone(tpath), true path, ok = strings.clone(tpath), true
cpp.filepath_cache[filename] = path cpp.filepath_cache[filename] = path
+3 -2
View File
@@ -188,7 +188,8 @@ input_size_from_memory :: proc(z: ^Context_Memory_Input) -> (res: i64, err: Erro
} }
input_size_from_stream :: proc(z: ^Context_Stream_Input) -> (res: i64, err: Error) { input_size_from_stream :: proc(z: ^Context_Stream_Input) -> (res: i64, err: Error) {
return io.size(z.input), nil res, _ = io.size(z.input)
return
} }
input_size :: proc{input_size_from_memory, input_size_from_stream} input_size :: proc{input_size_from_memory, input_size_from_stream}
@@ -215,7 +216,7 @@ read_slice_from_stream :: #force_inline proc(z: ^Context_Stream_Input, size: int
// TODO: REMOVE ALL USE OF context.temp_allocator here // TODO: REMOVE ALL USE OF context.temp_allocator here
// the is literally no need for it // the is literally no need for it
b := make([]u8, size, context.temp_allocator) b := make([]u8, size, context.temp_allocator)
_, e := z.input->impl_read(b[:]) _, e := io.read(z.input, b[:])
if e == .None { if e == .None {
return b, .None return b, .None
} }
+1 -1
View File
@@ -335,7 +335,7 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp
// fmt.printf("GZIP: Expected Payload Size: %v\n", expected_output_size); // fmt.printf("GZIP: Expected Payload Size: %v\n", expected_output_size);
zlib_error := zlib.inflate_raw(z=z, expected_output_size=expected_output_size) zlib_error := zlib.inflate_raw(z, expected_output_size=expected_output_size)
if zlib_error != nil { if zlib_error != nil {
return zlib_error return zlib_error
} }
+4 -8
View File
@@ -177,12 +177,10 @@ decompress_slice_to_string :: proc(input: []u8, model := DEFAULT_MODEL, allocato
max_output_size := decompress_bound(len(input), model) max_output_size := decompress_bound(len(input), model)
buf: [dynamic]u8 buf: [dynamic]u8
if !resize(&buf, max_output_size) { resize(&buf, max_output_size) or_return
return "", .Out_Of_Memory
}
length, result := decompress_slice_to_output_buffer(input, buf[:]) length, result := decompress_slice_to_output_buffer(input, buf[:])
resize(&buf, length) resize(&buf, length) or_return
return string(buf[:]), result return string(buf[:]), result
} }
decompress :: proc{decompress_slice_to_output_buffer, decompress_slice_to_string} decompress :: proc{decompress_slice_to_output_buffer, decompress_slice_to_string}
@@ -307,12 +305,10 @@ compress_string :: proc(input: string, model := DEFAULT_MODEL, allocator := cont
max_output_size := compress_bound(len(input)) max_output_size := compress_bound(len(input))
buf: [dynamic]u8 buf: [dynamic]u8
if !resize(&buf, max_output_size) { resize(&buf, max_output_size) or_return
return {}, .Out_Of_Memory
}
length, result := compress_string_to_buffer(input, buf[:]) length, result := compress_string_to_buffer(input, buf[:])
resize(&buf, length) resize(&buf, length) or_return
return buf[:length], result return buf[:length], result
} }
compress :: proc{compress_string_to_buffer, compress_string} compress :: proc{compress_string_to_buffer, compress_string}
+4 -3
View File
@@ -1,3 +1,4 @@
//+vet !using-param
package zlib package zlib
/* /*
@@ -471,7 +472,7 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
} }
// Parse ZLIB stream without header. // Parse ZLIB stream without header.
inflate_raw(z=ctx, expected_output_size=expected_output_size) or_return inflate_raw(ctx, expected_output_size=expected_output_size) or_return
if !raw { if !raw {
compress.discard_to_next_byte_lsb(ctx) compress.discard_to_next_byte_lsb(ctx)
@@ -665,7 +666,7 @@ inflate_from_byte_array :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, e
ctx.input_data = input ctx.input_data = input
ctx.output = buf ctx.output = buf
return inflate_from_context(ctx=&ctx, raw=raw, expected_output_size=expected_output_size) return inflate_from_context(&ctx, raw=raw, expected_output_size=expected_output_size)
} }
inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) { inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) {
@@ -674,7 +675,7 @@ inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := fals
ctx.input_data = input ctx.input_data = input
ctx.output = buf ctx.output = buf
return inflate_raw(z=&ctx, expected_output_size=expected_output_size) return inflate_raw(&ctx, expected_output_size=expected_output_size)
} }
inflate :: proc{inflate_from_context, inflate_from_byte_array} inflate :: proc{inflate_from_context, inflate_from_byte_array}
+11 -11
View File
@@ -14,7 +14,7 @@ Queue :: struct($T: typeid) {
DEFAULT_CAPACITY :: 16 DEFAULT_CAPACITY :: 16
// Procedure to initialize a queue // Procedure to initialize a queue
init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator) -> bool { init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator) -> runtime.Allocator_Error {
if q.data.allocator.procedure == nil { if q.data.allocator.procedure == nil {
q.data.allocator = allocator q.data.allocator = allocator
} }
@@ -55,11 +55,11 @@ space :: proc(q: $Q/Queue($T)) -> int {
} }
// Reserve enough space for at least the specified capacity // Reserve enough space for at least the specified capacity
reserve :: proc(q: ^$Q/Queue($T), capacity: int) -> bool { reserve :: proc(q: ^$Q/Queue($T), capacity: int) -> runtime.Allocator_Error {
if uint(capacity) > q.len { if uint(capacity) > q.len {
return _grow(q, uint(capacity)) return _grow(q, uint(capacity))
} }
return true return nil
} }
@@ -112,25 +112,25 @@ peek_back :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> ^T {
} }
// Push an element to the back of the queue // Push an element to the back of the queue
push_back :: proc(q: ^$Q/Queue($T), elem: T) -> bool { push_back :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) {
if space(q^) == 0 { if space(q^) == 0 {
_grow(q) or_return _grow(q) or_return
} }
idx := (q.offset+uint(q.len))%builtin.len(q.data) idx := (q.offset+uint(q.len))%builtin.len(q.data)
q.data[idx] = elem q.data[idx] = elem
q.len += 1 q.len += 1
return true return true, nil
} }
// Push an element to the front of the queue // Push an element to the front of the queue
push_front :: proc(q: ^$Q/Queue($T), elem: T) -> bool { push_front :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) {
if space(q^) == 0 { if space(q^) == 0 {
_grow(q) or_return _grow(q) or_return
} }
q.offset = uint(q.offset - 1 + builtin.len(q.data)) % builtin.len(q.data) q.offset = uint(q.offset - 1 + builtin.len(q.data)) % builtin.len(q.data)
q.len += 1 q.len += 1
q.data[q.offset] = elem q.data[q.offset] = elem
return true return true, nil
} }
@@ -173,7 +173,7 @@ pop_front_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) {
} }
// Push multiple elements to the front of the queue // Push multiple elements to the front of the queue
push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> bool { push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> (ok: bool, err: runtime.Allocator_Error) {
n := uint(builtin.len(elems)) n := uint(builtin.len(elems))
if space(q^) < int(n) { if space(q^) < int(n) {
_grow(q, q.len + n) or_return _grow(q, q.len + n) or_return
@@ -188,7 +188,7 @@ push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> bool {
copy(q.data[insert_from:], elems[:insert_to]) copy(q.data[insert_from:], elems[:insert_to])
copy(q.data[:insert_from], elems[insert_to:]) copy(q.data[:insert_from], elems[insert_to:])
q.len += n q.len += n
return true return true, nil
} }
// Consume `n` elements from the front of the queue // Consume `n` elements from the front of the queue
@@ -225,7 +225,7 @@ clear :: proc(q: ^$Q/Queue($T)) {
// Internal growinh procedure // Internal growinh procedure
_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> bool { _grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> runtime.Allocator_Error {
new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2) new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2)
n := uint(builtin.len(q.data)) n := uint(builtin.len(q.data))
builtin.resize(&q.data, int(new_capacity)) or_return builtin.resize(&q.data, int(new_capacity)) or_return
@@ -234,5 +234,5 @@ _grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> bool {
copy(q.data[new_capacity-diff:], q.data[q.offset:][:diff]) copy(q.data[new_capacity-diff:], q.data[q.offset:][:diff])
q.offset += new_capacity - n q.offset += new_capacity - n
} }
return true return nil
} }
@@ -32,7 +32,7 @@ init :: proc(sorter: ^$S/Sorter($K)) {
} }
destroy :: proc(sorter: ^$S/Sorter($K)) { destroy :: proc(sorter: ^$S/Sorter($K)) {
for _, v in &sorter.relations { for _, v in sorter.relations {
delete(v.dependents) delete(v.dependents)
} }
delete(sorter.relations) delete(sorter.relations)
@@ -80,7 +80,7 @@ sort :: proc(sorter: ^$S/Sorter($K)) -> (sorted, cycled: [dynamic]K) {
} }
} }
for root in &sorted do for k, _ in relations[root].dependents { for root in sorted do for k, _ in relations[root].dependents {
relation := &relations[k] relation := &relations[k]
relation.dependencies -= 1 relation.dependencies -= 1
if relation.dependencies == 0 { if relation.dependencies == 0 {
+4 -4
View File
@@ -70,7 +70,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -149,7 +149,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -228,7 +228,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -307,7 +307,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+1 -1
View File
@@ -77,7 +77,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_blake2.update(&ctx, buf[:read]) _blake2.update(&ctx, buf[:read])
} }
+1 -1
View File
@@ -77,7 +77,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_blake2.update(&ctx, buf[:read]) _blake2.update(&ctx, buf[:read])
} }
+1 -1
View File
@@ -65,7 +65,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+4 -4
View File
@@ -70,7 +70,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -149,7 +149,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -228,7 +228,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -307,7 +307,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+15 -15
View File
@@ -79,7 +79,7 @@ hash_stream_128_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -164,7 +164,7 @@ hash_stream_128_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -249,7 +249,7 @@ hash_stream_128_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -334,7 +334,7 @@ hash_stream_160_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -419,7 +419,7 @@ hash_stream_160_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -504,7 +504,7 @@ hash_stream_160_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -589,7 +589,7 @@ hash_stream_192_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -674,7 +674,7 @@ hash_stream_192_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -759,7 +759,7 @@ hash_stream_192_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -844,7 +844,7 @@ hash_stream_224_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -929,7 +929,7 @@ hash_stream_224_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -1014,7 +1014,7 @@ hash_stream_224_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -1099,7 +1099,7 @@ hash_stream_256_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -1184,7 +1184,7 @@ hash_stream_256_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
@@ -1270,7 +1270,7 @@ hash_stream_256_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
ctx.str_len = u32(len(buf[:read])) ctx.str_len = u32(len(buf[:read]))
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
+4 -4
View File
@@ -70,7 +70,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -149,7 +149,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -228,7 +228,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -307,7 +307,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+4 -4
View File
@@ -77,7 +77,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_sha3.update(&ctx, buf[:read]) _sha3.update(&ctx, buf[:read])
} }
@@ -159,7 +159,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_sha3.update(&ctx, buf[:read]) _sha3.update(&ctx, buf[:read])
} }
@@ -241,7 +241,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_sha3.update(&ctx, buf[:read]) _sha3.update(&ctx, buf[:read])
} }
@@ -323,7 +323,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_sha3.update(&ctx, buf[:read]) _sha3.update(&ctx, buf[:read])
} }
+1 -1
View File
@@ -64,7 +64,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+1 -1
View File
@@ -68,7 +68,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+1 -1
View File
@@ -67,7 +67,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+4 -4
View File
@@ -69,7 +69,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -145,7 +145,7 @@ hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -221,7 +221,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -297,7 +297,7 @@ hash_stream_320 :: proc(s: io.Stream) -> ([DIGEST_SIZE_320]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+1 -1
View File
@@ -67,7 +67,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+4 -4
View File
@@ -74,7 +74,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -153,7 +153,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -232,7 +232,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -311,7 +311,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+4 -4
View File
@@ -73,7 +73,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_sha3.update(&ctx, buf[:read]) _sha3.update(&ctx, buf[:read])
} }
@@ -152,7 +152,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_sha3.update(&ctx, buf[:read]) _sha3.update(&ctx, buf[:read])
} }
@@ -231,7 +231,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_sha3.update(&ctx, buf[:read]) _sha3.update(&ctx, buf[:read])
} }
@@ -310,7 +310,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_sha3.update(&ctx, buf[:read]) _sha3.update(&ctx, buf[:read])
} }
+2 -2
View File
@@ -73,7 +73,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_sha3.update(&ctx, buf[:read]) _sha3.update(&ctx, buf[:read])
} }
@@ -155,7 +155,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_sha3.update(&ctx, buf[:read]) _sha3.update(&ctx, buf[:read])
} }
+1 -1
View File
@@ -66,7 +66,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+2 -2
View File
@@ -70,7 +70,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
@@ -146,7 +146,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
+3 -3
View File
@@ -71,7 +71,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_tiger.update(&ctx, buf[:read]) _tiger.update(&ctx, buf[:read])
} }
@@ -150,7 +150,7 @@ hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_tiger.update(&ctx, buf[:read]) _tiger.update(&ctx, buf[:read])
} }
@@ -229,7 +229,7 @@ hash_stream_192 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_tiger.update(&ctx, buf[:read]) _tiger.update(&ctx, buf[:read])
} }
+3 -3
View File
@@ -71,7 +71,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_tiger.update(&ctx, buf[:read]) _tiger.update(&ctx, buf[:read])
} }
@@ -150,7 +150,7 @@ hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_tiger.update(&ctx, buf[:read]) _tiger.update(&ctx, buf[:read])
} }
@@ -229,7 +229,7 @@ hash_stream_192 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
_tiger.update(&ctx, buf[:read]) _tiger.update(&ctx, buf[:read])
} }
+1 -1
View File
@@ -66,7 +66,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
defer delete(buf) defer delete(buf)
read := 1 read := 1
for read > 0 { for read > 0 {
read, _ = s->impl_read(buf) read, _ = io.read(s, buf)
if read > 0 { if read > 0 {
update(&ctx, buf[:read]) update(&ctx, buf[:read])
} }
-3
View File
@@ -1,8 +1,5 @@
package debug_pe package debug_pe
import "core:runtime"
import "core:io"
Section_Header32 :: struct { Section_Header32 :: struct {
name: [8]u8, name: [8]u8,
virtual_size: u32le, virtual_size: u32le,
+3 -3
View File
@@ -3,13 +3,13 @@
package dynlib package dynlib
_load_library :: proc(path: string, global_symbols := false) -> (Library, bool) { _load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
return return nil, false
} }
_unload_library :: proc(library: Library) -> bool { _unload_library :: proc(library: Library) -> bool {
return return false
} }
_symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) { _symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
return return nil, false
} }
+17 -20
View File
@@ -184,28 +184,26 @@ decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator :=
advance :: proc(t: ^Tokenizer) -> (err: Error) { advance :: proc(t: ^Tokenizer) -> (err: Error) {
if t == nil { return .Tokenizer_Is_Nil } if t == nil { return .Tokenizer_Is_Nil }
using t
#no_bounds_check { #no_bounds_check {
if read_offset < len(src) { if t.read_offset < len(t.src) {
offset = read_offset t.offset = t.read_offset
r, w = rune(src[read_offset]), 1 t.r, t.w = rune(t.src[t.read_offset]), 1
switch { switch {
case r == 0: case t.r == 0:
return .Illegal_NUL_Character return .Illegal_NUL_Character
case r >= utf8.RUNE_SELF: case t.r >= utf8.RUNE_SELF:
r, w = utf8.decode_rune_in_string(src[read_offset:]) t.r, t.w = utf8.decode_rune_in_string(t.src[t.read_offset:])
if r == utf8.RUNE_ERROR && w == 1 { if t.r == utf8.RUNE_ERROR && t.w == 1 {
return .Illegal_UTF_Encoding return .Illegal_UTF_Encoding
} else if r == utf8.RUNE_BOM && offset > 0 { } else if t.r == utf8.RUNE_BOM && t.offset > 0 {
return .Illegal_BOM return .Illegal_BOM
} }
} }
read_offset += w t.read_offset += t.w
return .None return .None
} else { } else {
offset = len(src) t.offset = len(t.src)
r = -1 t.r = -1
return return
} }
} }
@@ -273,26 +271,25 @@ _extract_xml_entity :: proc(t: ^Tokenizer) -> (entity: string, err: Error) {
All of these would be in the ASCII range. All of these would be in the ASCII range.
Even if one is not, it doesn't matter. All characters we need to compare to extract are. Even if one is not, it doesn't matter. All characters we need to compare to extract are.
*/ */
using t
length := len(t.src) length := len(t.src)
found := false found := false
#no_bounds_check { #no_bounds_check {
for read_offset < length { for t.read_offset < length {
if src[read_offset] == ';' { if t.src[t.read_offset] == ';' {
t.read_offset += 1
found = true found = true
read_offset += 1
break break
} }
read_offset += 1 t.read_offset += 1
} }
} }
if found { if found {
return string(src[offset + 1 : read_offset - 1]), .None return string(t.src[t.offset + 1 : t.read_offset - 1]), .None
} }
return string(src[offset : read_offset]), .Invalid_Entity_Encoding return string(t.src[t.offset : t.read_offset]), .Invalid_Entity_Encoding
} }
/* /*
+73
View File
@@ -0,0 +1,73 @@
package hex
import "core:strings"
encode :: proc(src: []byte, allocator := context.allocator) -> []byte #no_bounds_check {
dst := make([]byte, len(src) * 2, allocator)
for i, j := 0, 0; i < len(src); i += 1 {
v := src[i]
dst[j] = HEXTABLE[v>>4]
dst[j+1] = HEXTABLE[v&0x0f]
j += 2
}
return dst
}
decode :: proc(src: []byte, allocator := context.allocator) -> (dst: []byte, ok: bool) #no_bounds_check {
if len(src) % 2 == 1 {
return
}
dst = make([]byte, len(src) / 2, allocator)
for i, j := 0, 1; j < len(src); j += 2 {
p := src[j-1]
q := src[j]
a := hex_digit(p) or_return
b := hex_digit(q) or_return
dst[i] = (a << 4) | b
i += 1
}
return dst, true
}
// Decodes the given sequence into one byte.
// Should be called with one byte worth of the source, eg: 0x23 -> '#'.
decode_sequence :: proc(str: string) -> (res: byte, ok: bool) {
str := str
if strings.has_prefix(str, "0x") || strings.has_prefix(str, "0X") {
str = str[2:]
}
if len(str) != 2 {
return 0, false
}
upper := hex_digit(str[0]) or_return
lower := hex_digit(str[1]) or_return
return upper << 4 | lower, true
}
@(private)
HEXTABLE := [16]byte {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f',
}
@(private)
hex_digit :: proc(char: byte) -> (u8, bool) {
switch char {
case '0' ..= '9': return char - '0', true
case 'a' ..= 'f': return char - 'a' + 10, true
case 'A' ..= 'F': return char - 'A' + 10, true
case: return 0, false
}
}
+2 -2
View File
@@ -83,7 +83,7 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
meta_data = make([]Meta, int(capacity)) meta_data = make([]Meta, int(capacity))
count := 0 count := 0
defer meta_data = meta_data[:count] defer meta_data = meta_data[:count]
for m in &meta_data { for &m in meta_data {
m.name = read_name(r) or_return m.name = read_name(r) or_return
type := read_value(r, Meta_Value_Type) or_return type := read_value(r, Meta_Value_Type) or_return
@@ -116,7 +116,7 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
layer_count := 0 layer_count := 0
layers = make(Layer_Stack, stack_count) layers = make(Layer_Stack, stack_count)
defer layers = layers[:layer_count] defer layers = layers[:layer_count]
for layer in &layers { for &layer in layers {
layer.name = read_name(r) or_return layer.name = read_name(r) or_return
layer.components = read_value(r, u8) or_return layer.components = read_value(r, u8) or_return
type := read_value(r, Layer_Data_Type) or_return type := read_value(r, Layer_Data_Type) or_return
+3 -3
View File
@@ -153,7 +153,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
case complex128: r, i = f64(real(z)), f64(imag(z)) case complex128: r, i = f64(real(z)), f64(imag(z))
case: return .Unsupported_Type case: return .Unsupported_Type
} }
io.write_byte(w, '[') or_return io.write_byte(w, '[') or_return
io.write_f64(w, r) or_return io.write_f64(w, r) or_return
io.write_string(w, ", ") or_return io.write_string(w, ", ") or_return
@@ -165,8 +165,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
case runtime.Type_Info_String: case runtime.Type_Info_String:
switch s in a { switch s in a {
case string: io.write_quoted_string(w, s) or_return case string: io.write_quoted_string(w, s, '"', nil, true) or_return
case cstring: io.write_quoted_string(w, string(s)) or_return case cstring: io.write_quoted_string(w, string(s), '"', nil, true) or_return
} }
case runtime.Type_Info_Boolean: case runtime.Type_Info_Boolean:
+10 -1
View File
@@ -2,6 +2,7 @@ package json
import "core:mem" import "core:mem"
import "core:unicode/utf8" import "core:unicode/utf8"
import "core:unicode/utf16"
import "core:strconv" import "core:strconv"
Parser :: struct { Parser :: struct {
@@ -403,11 +404,19 @@ unquote_string :: proc(token: Token, spec: Specification, allocator := context.a
} }
i += 6 i += 6
// If this is a surrogate pair, decode as such by taking the next rune too.
if r >= utf8.SURROGATE_MIN && r <= utf8.SURROGATE_HIGH_MAX && len(s) > i + 2 && s[i:i+2] == "\\u" {
r2 := get_u4_rune(s[i:])
if r2 >= utf8.SURROGATE_LOW_MIN && r2 <= utf8.SURROGATE_MAX {
i += 6
r = utf16.decode_surrogate_pair(r, r2)
}
}
buf, buf_width := utf8.encode_rune(r) buf, buf_width := utf8.encode_rune(r)
copy(b[w:], buf[:buf_width]) copy(b[w:], buf[:buf_width])
w += buf_width w += buf_width
case '0': case '0':
if spec != .JSON { if spec != .JSON {
b[w] = '\x00' b[w] = '\x00'
+5 -5
View File
@@ -72,7 +72,7 @@ unmarshal_string :: proc(data: string, ptr: ^$T, spec := DEFAULT_SPECIFICATION,
@(private) @(private)
assign_bool :: proc(val: any, b: bool) -> bool { assign_bool :: proc(val: any, b: bool) -> bool {
v := reflect.any_core(val) v := reflect.any_core(val)
switch dst in &v { switch &dst in v {
case bool: dst = bool(b) case bool: dst = bool(b)
case b8: dst = b8 (b) case b8: dst = b8 (b)
case b16: dst = b16 (b) case b16: dst = b16 (b)
@@ -85,7 +85,7 @@ assign_bool :: proc(val: any, b: bool) -> bool {
@(private) @(private)
assign_int :: proc(val: any, i: $T) -> bool { assign_int :: proc(val: any, i: $T) -> bool {
v := reflect.any_core(val) v := reflect.any_core(val)
switch dst in &v { switch &dst in v {
case i8: dst = i8 (i) case i8: dst = i8 (i)
case i16: dst = i16 (i) case i16: dst = i16 (i)
case i16le: dst = i16le (i) case i16le: dst = i16le (i)
@@ -122,7 +122,7 @@ assign_int :: proc(val: any, i: $T) -> bool {
@(private) @(private)
assign_float :: proc(val: any, f: $T) -> bool { assign_float :: proc(val: any, f: $T) -> bool {
v := reflect.any_core(val) v := reflect.any_core(val)
switch dst in &v { switch &dst in v {
case f16: dst = f16 (f) case f16: dst = f16 (f)
case f16le: dst = f16le(f) case f16le: dst = f16le(f)
case f16be: dst = f16be(f) case f16be: dst = f16be(f)
@@ -150,7 +150,7 @@ assign_float :: proc(val: any, f: $T) -> bool {
@(private) @(private)
unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.Type_Info) -> bool { unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.Type_Info) -> bool {
val := val val := val
switch dst in &val { switch &dst in val {
case string: case string:
dst = str dst = str
return true return true
@@ -215,7 +215,7 @@ unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
} }
} }
switch dst in &v { switch &dst in v {
// Handle json.Value as an unknown type // Handle json.Value as an unknown type
case Value: case Value:
dst = parse_value(p) or_return dst = parse_value(p) or_return
+21 -23
View File
@@ -19,43 +19,39 @@ import "core:fmt"
*/ */
print :: proc(writer: io.Writer, doc: ^Document) -> (written: int, err: io.Error) { print :: proc(writer: io.Writer, doc: ^Document) -> (written: int, err: io.Error) {
if doc == nil { return } if doc == nil { return }
using fmt written += fmt.wprintf(writer, "[XML Prolog]\n")
written += wprintf(writer, "[XML Prolog]\n")
for attr in doc.prologue { for attr in doc.prologue {
written += wprintf(writer, "\t%v: %v\n", attr.key, attr.val) written += fmt.wprintf(writer, "\t%v: %v\n", attr.key, attr.val)
} }
written += wprintf(writer, "[Encoding] %v\n", doc.encoding) written += fmt.wprintf(writer, "[Encoding] %v\n", doc.encoding)
if len(doc.doctype.ident) > 0 { if len(doc.doctype.ident) > 0 {
written += wprintf(writer, "[DOCTYPE] %v\n", doc.doctype.ident) written += fmt.wprintf(writer, "[DOCTYPE] %v\n", doc.doctype.ident)
if len(doc.doctype.rest) > 0 { if len(doc.doctype.rest) > 0 {
wprintf(writer, "\t%v\n", doc.doctype.rest) fmt.wprintf(writer, "\t%v\n", doc.doctype.rest)
} }
} }
for comment in doc.comments { for comment in doc.comments {
written += wprintf(writer, "[Pre-root comment] %v\n", comment) written += fmt.wprintf(writer, "[Pre-root comment] %v\n", comment)
} }
if len(doc.elements) > 0 { if len(doc.elements) > 0 {
wprintln(writer, " --- ") fmt.wprintln(writer, " --- ")
print_element(writer, doc, 0) print_element(writer, doc, 0)
wprintln(writer, " --- ") fmt.wprintln(writer, " --- ")
} }
return written, .None return written, .None
} }
print_element :: proc(writer: io.Writer, doc: ^Document, element_id: Element_ID, indent := 0) -> (written: int, err: io.Error) { print_element :: proc(writer: io.Writer, doc: ^Document, element_id: Element_ID, indent := 0) -> (written: int, err: io.Error) {
using fmt
tab :: proc(writer: io.Writer, indent: int) { tab :: proc(writer: io.Writer, indent: int) {
for _ in 0..=indent { for _ in 0..=indent {
wprintf(writer, "\t") fmt.wprintf(writer, "\t")
} }
} }
@@ -64,22 +60,24 @@ print_element :: proc(writer: io.Writer, doc: ^Document, element_id: Element_ID,
element := doc.elements[element_id] element := doc.elements[element_id]
if element.kind == .Element { if element.kind == .Element {
wprintf(writer, "<%v>\n", element.ident) fmt.wprintf(writer, "<%v>\n", element.ident)
if len(element.value) > 0 {
tab(writer, indent + 1) for value in element.value {
wprintf(writer, "[Value] %v\n", element.value) switch v in value {
case string:
tab(writer, indent + 1)
fmt.wprintf(writer, "[Value] %v\n", v)
case Element_ID:
print_element(writer, doc, v, indent + 1)
}
} }
for attr in element.attribs { for attr in element.attribs {
tab(writer, indent + 1) tab(writer, indent + 1)
wprintf(writer, "[Attr] %v: %v\n", attr.key, attr.val) fmt.wprintf(writer, "[Attr] %v: %v\n", attr.key, attr.val)
}
for child in element.children {
print_element(writer, doc, child, indent + 1)
} }
} else if element.kind == .Comment { } else if element.kind == .Comment {
wprintf(writer, "[COMMENT] %v\n", element.value) fmt.wprintf(writer, "[COMMENT] %v\n", element.value)
} }
return written, .None return written, .None
+3 -3
View File
@@ -72,10 +72,10 @@ example :: proc() {
return return
} }
printf("Found `<charlist>` with %v children, %v elements total\n", len(docs[0].elements[charlist].children), docs[0].element_count) printf("Found `<charlist>` with %v children, %v elements total\n", len(docs[0].elements[charlist].value), docs[0].element_count)
crc32 := doc_hash(docs[0]) crc32 := doc_hash(docs[0], false)
printf("[%v] CRC32: 0x%08x\n", "🎉" if crc32 == 0xcaa042b9 else "🤬", crc32) printf("[%v] CRC32: 0x%08x\n", "🎉" if crc32 == 0x420dbac5 else "🤬", crc32)
for round in 0..<N { for round in 0..<N {
defer xml.destroy(docs[round]) defer xml.destroy(docs[round])
+17 -12
View File
@@ -13,20 +13,25 @@ find_child_by_ident :: proc(doc: ^Document, parent_id: Element_ID, ident: string
tag := doc.elements[parent_id] tag := doc.elements[parent_id]
count := 0 count := 0
for child_id in tag.children { for v in tag.value {
child := doc.elements[child_id] switch child_id in v {
/* case string: continue
Skip commments. They have no name. case Element_ID:
*/ child := doc.elements[child_id]
if child.kind != .Element { continue } /*
Skip commments. They have no name.
*/
if child.kind != .Element { continue }
/* /*
If the ident matches and it's the nth such child, return it. If the ident matches and it's the nth such child, return it.
*/ */
if child.ident == ident { if child.ident == ident {
if count == nth { return child_id, true } if count == nth { return child_id, true }
count += 1 count += 1
}
} }
} }
return 0, false return 0, false
} }
+16 -16
View File
@@ -125,38 +125,38 @@ error :: proc(t: ^Tokenizer, offset: int, msg: string, args: ..any) {
} }
@(optimization_mode="speed") @(optimization_mode="speed")
advance_rune :: proc(using t: ^Tokenizer) { advance_rune :: proc(t: ^Tokenizer) {
#no_bounds_check { #no_bounds_check {
/* /*
Already bounds-checked here. Already bounds-checked here.
*/ */
if read_offset < len(src) { if t.read_offset < len(t.src) {
offset = read_offset t.offset = t.read_offset
if ch == '\n' { if t.ch == '\n' {
line_offset = offset t.line_offset = t.offset
line_count += 1 t.line_count += 1
} }
r, w := rune(src[read_offset]), 1 r, w := rune(t.src[t.read_offset]), 1
switch { switch {
case r == 0: case r == 0:
error(t, t.offset, "illegal character NUL") error(t, t.offset, "illegal character NUL")
case r >= utf8.RUNE_SELF: case r >= utf8.RUNE_SELF:
r, w = #force_inline utf8.decode_rune_in_string(src[read_offset:]) r, w = #force_inline utf8.decode_rune_in_string(t.src[t.read_offset:])
if r == utf8.RUNE_ERROR && w == 1 { if r == utf8.RUNE_ERROR && w == 1 {
error(t, t.offset, "illegal UTF-8 encoding") error(t, t.offset, "illegal UTF-8 encoding")
} else if r == utf8.RUNE_BOM && offset > 0 { } else if r == utf8.RUNE_BOM && t.offset > 0 {
error(t, t.offset, "illegal byte order mark") error(t, t.offset, "illegal byte order mark")
} }
} }
read_offset += w t.read_offset += w
ch = r t.ch = r
} else { } else {
offset = len(src) t.offset = len(t.src)
if ch == '\n' { if t.ch == '\n' {
line_offset = offset t.line_offset = t.offset
line_count += 1 t.line_count += 1
} }
ch = -1 t.ch = -1
} }
} }
} }
+15 -27
View File
@@ -125,16 +125,19 @@ Document :: struct {
Element :: struct { Element :: struct {
ident: string, ident: string,
value: string, value: [dynamic]Value,
attribs: Attributes, attribs: Attributes,
kind: enum { kind: enum {
Element = 0, Element = 0,
Comment, Comment,
}, },
parent: Element_ID, parent: Element_ID,
children: [dynamic]Element_ID, }
Value :: union {
string,
Element_ID,
} }
Attribute :: struct { Attribute :: struct {
@@ -247,9 +250,6 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
err = .Unexpected_Token err = .Unexpected_Token
element, parent: Element_ID element, parent: Element_ID
tag_is_open := false
first_element := true
open: Token open: Token
/* /*
@@ -275,16 +275,10 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
e.g. <odin - Start of new element. e.g. <odin - Start of new element.
*/ */
element = new_element(doc) element = new_element(doc)
tag_is_open = true if element == 0 { // First Element
parent = element
if first_element {
/*
First element.
*/
parent = element
first_element = false
} else { } else {
append(&doc.elements[parent].children, element) append(&doc.elements[parent].value, element)
} }
doc.elements[element].parent = parent doc.elements[element].parent = parent
@@ -324,7 +318,6 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
expect(t, .Gt) or_return expect(t, .Gt) or_return
parent = doc.elements[element].parent parent = doc.elements[element].parent
element = parent element = parent
tag_is_open = false
case: case:
error(t, t.offset, "Expected close tag, got: %#v\n", end_token) error(t, t.offset, "Expected close tag, got: %#v\n", end_token)
@@ -344,7 +337,6 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
} }
parent = doc.elements[element].parent parent = doc.elements[element].parent
element = parent element = parent
tag_is_open = false
} else if open.kind == .Exclaim { } else if open.kind == .Exclaim {
/* /*
@@ -392,8 +384,8 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
el := new_element(doc) el := new_element(doc)
doc.elements[el].parent = element doc.elements[el].parent = element
doc.elements[el].kind = .Comment doc.elements[el].kind = .Comment
doc.elements[el].value = comment append(&doc.elements[el].value, comment)
append(&doc.elements[element].children, el) append(&doc.elements[element].value, el)
} }
} }
@@ -436,9 +428,6 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
/* /*
End of file. End of file.
*/ */
if tag_is_open {
return doc, .Premature_EOF
}
break loop break loop
case: case:
@@ -450,7 +439,7 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
needs_processing |= .Decode_SGML_Entities in opts.flags needs_processing |= .Decode_SGML_Entities in opts.flags
if !needs_processing { if !needs_processing {
doc.elements[element].value = body_text append(&doc.elements[element].value, body_text)
continue continue
} }
@@ -472,10 +461,10 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
decoded, decode_err := entity.decode_xml(body_text, decode_opts) decoded, decode_err := entity.decode_xml(body_text, decode_opts)
if decode_err == .None { if decode_err == .None {
doc.elements[element].value = decoded append(&doc.elements[element].value, decoded)
append(&doc.strings_to_free, decoded) append(&doc.strings_to_free, decoded)
} else { } else {
doc.elements[element].value = body_text append(&doc.elements[element].value, body_text)
} }
} }
} }
@@ -518,7 +507,7 @@ destroy :: proc(doc: ^Document) {
for el in doc.elements { for el in doc.elements {
delete(el.attribs) delete(el.attribs)
delete(el.children) delete(el.value)
} }
delete(doc.elements) delete(doc.elements)
@@ -710,6 +699,5 @@ new_element :: proc(doc: ^Document) -> (id: Element_ID) {
cur := doc.element_count cur := doc.element_count
doc.element_count += 1 doc.element_count += 1
return cur return cur
} }
+45 -37
View File
@@ -123,7 +123,7 @@ register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Regist
aprint :: proc(args: ..any, sep := " ") -> string { aprint :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder str: strings.Builder
strings.builder_init(&str) strings.builder_init(&str)
sbprint(buf=&str, args=args, sep=sep) sbprint(&str, ..args, sep=sep)
return strings.to_string(str) return strings.to_string(str)
} }
// Creates a formatted string with a newline character at the end // Creates a formatted string with a newline character at the end
@@ -139,7 +139,7 @@ aprint :: proc(args: ..any, sep := " ") -> string {
aprintln :: proc(args: ..any, sep := " ") -> string { aprintln :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder str: strings.Builder
strings.builder_init(&str) strings.builder_init(&str)
sbprintln(buf=&str, args=args, sep=sep) sbprintln(&str, ..args, sep=sep)
return strings.to_string(str) return strings.to_string(str)
} }
// Creates a formatted string using a format string and arguments // Creates a formatted string using a format string and arguments
@@ -171,7 +171,7 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
tprint :: proc(args: ..any, sep := " ") -> string { tprint :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder str: strings.Builder
strings.builder_init(&str, context.temp_allocator) strings.builder_init(&str, context.temp_allocator)
sbprint(buf=&str, args=args, sep=sep) sbprint(&str, ..args, sep=sep)
return strings.to_string(str) return strings.to_string(str)
} }
// Creates a formatted string with a newline character at the end // Creates a formatted string with a newline character at the end
@@ -187,7 +187,7 @@ tprint :: proc(args: ..any, sep := " ") -> string {
tprintln :: proc(args: ..any, sep := " ") -> string { tprintln :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder str: strings.Builder
strings.builder_init(&str, context.temp_allocator) strings.builder_init(&str, context.temp_allocator)
sbprintln(buf=&str, args=args, sep=sep) sbprintln(&str, ..args, sep=sep)
return strings.to_string(str) return strings.to_string(str)
} }
// Creates a formatted string using a format string and arguments // Creates a formatted string using a format string and arguments
@@ -217,7 +217,7 @@ tprintf :: proc(fmt: string, args: ..any) -> string {
// //
bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string { bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string {
sb := strings.builder_from_bytes(buf[0:len(buf)]) sb := strings.builder_from_bytes(buf[0:len(buf)])
return sbprint(buf=&sb, args=args, sep=sep) return sbprint(&sb, ..args, sep=sep)
} }
// Creates a formatted string using a supplied buffer as the backing array, appends newline. Writes into the buffer. // Creates a formatted string using a supplied buffer as the backing array, appends newline. Writes into the buffer.
// //
@@ -230,7 +230,7 @@ bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string {
// //
bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string { bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string {
sb := strings.builder_from_bytes(buf[0:len(buf)]) sb := strings.builder_from_bytes(buf[0:len(buf)])
return sbprintln(buf=&sb, args=args, sep=sep) return sbprintln(&sb, ..args, sep=sep)
} }
// Creates a formatted string using a supplied buffer as the backing array. Writes into the buffer. // Creates a formatted string using a supplied buffer as the backing array. Writes into the buffer.
// //
@@ -327,7 +327,7 @@ ctprintf :: proc(format: string, args: ..any) -> cstring {
// Returns: A formatted string // Returns: A formatted string
// //
sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string { sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
wprint(w=strings.to_writer(buf), args=args, sep=sep) wprint(strings.to_writer(buf), ..args, sep=sep)
return strings.to_string(buf^) return strings.to_string(buf^)
} }
// Formats and writes to a strings.Builder buffer using the default print settings // Formats and writes to a strings.Builder buffer using the default print settings
@@ -340,7 +340,7 @@ sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
// Returns: The resulting formatted string // Returns: The resulting formatted string
// //
sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string { sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
wprintln(w=strings.to_writer(buf), args=args, sep=sep) wprintln(strings.to_writer(buf), ..args, sep=sep)
return strings.to_string(buf^) return strings.to_string(buf^)
} }
// Formats and writes to a strings.Builder buffer according to the specified format string // Formats and writes to a strings.Builder buffer according to the specified format string
@@ -353,7 +353,7 @@ sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
// Returns: The resulting formatted string // Returns: The resulting formatted string
// //
sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string { sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string {
wprintf(w=strings.to_writer(buf), fmt=fmt, args=args) wprintf(strings.to_writer(buf), fmt, ..args)
return strings.to_string(buf^) return strings.to_string(buf^)
} }
// Formats and writes to an io.Writer using the default print settings // Formats and writes to an io.Writer using the default print settings
@@ -835,22 +835,22 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
// - fi: A pointer to an Info structure // - fi: A pointer to an Info structure
// - verb: The invalid format verb // - verb: The invalid format verb
// //
fmt_bad_verb :: proc(using fi: ^Info, verb: rune) { fmt_bad_verb :: proc(fi: ^Info, verb: rune) {
prev_in_bad := fi.in_bad prev_in_bad := fi.in_bad
defer fi.in_bad = prev_in_bad defer fi.in_bad = prev_in_bad
fi.in_bad = true fi.in_bad = true
io.write_string(writer, "%!", &fi.n) io.write_string(fi.writer, "%!", &fi.n)
io.write_rune(writer, verb, &fi.n) io.write_rune(fi.writer, verb, &fi.n)
io.write_byte(writer, '(', &fi.n) io.write_byte(fi.writer, '(', &fi.n)
if arg.id != nil { if fi.arg.id != nil {
reflect.write_typeid(writer, arg.id, &fi.n) reflect.write_typeid(fi.writer, fi.arg.id, &fi.n)
io.write_byte(writer, '=', &fi.n) io.write_byte(fi.writer, '=', &fi.n)
fmt_value(fi, arg, 'v') fmt_value(fi, fi.arg, 'v')
} else { } else {
io.write_string(writer, "<nil>", &fi.n) io.write_string(fi.writer, "<nil>", &fi.n)
} }
io.write_byte(writer, ')', &fi.n) io.write_byte(fi.writer, ')', &fi.n)
} }
// Formats a boolean value according to the specified format verb // Formats a boolean value according to the specified format verb
// //
@@ -859,7 +859,7 @@ fmt_bad_verb :: proc(using fi: ^Info, verb: rune) {
// - b: The boolean value to format // - b: The boolean value to format
// - verb: The format verb // - verb: The format verb
// //
fmt_bool :: proc(using fi: ^Info, b: bool, verb: rune) { fmt_bool :: proc(fi: ^Info, b: bool, verb: rune) {
switch verb { switch verb {
case 't', 'v': case 't', 'v':
fmt_string(fi, b ? "true" : "false", 's') fmt_string(fi, b ? "true" : "false", 's')
@@ -1142,6 +1142,11 @@ _pad :: proc(fi: ^Info, s: string) {
if fi.minus { // right pad if fi.minus { // right pad
io.write_string(fi.writer, s, &fi.n) io.write_string(fi.writer, s, &fi.n)
fmt_write_padding(fi, width) fmt_write_padding(fi, width)
} else if !fi.space && s != "" && s[0] == '-' {
// left pad accounting for zero pad of negative number
io.write_byte(fi.writer, '-', &fi.n)
fmt_write_padding(fi, width)
io.write_string(fi.writer, s[1:], &fi.n)
} else { // left pad } else { // left pad
fmt_write_padding(fi, width) fmt_write_padding(fi, width)
io.write_string(fi.writer, s, &fi.n) io.write_string(fi.writer, s, &fi.n)
@@ -1961,11 +1966,22 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named)
switch a in v { switch a in v {
case runtime.Source_Code_Location: case runtime.Source_Code_Location:
io.write_string(fi.writer, a.file_path, &fi.n) io.write_string(fi.writer, a.file_path, &fi.n)
io.write_byte(fi.writer, '(', &fi.n)
io.write_int(fi.writer, int(a.line), 10, &fi.n) when ODIN_ERROR_POS_STYLE == .Default {
io.write_byte(fi.writer, ':', &fi.n) io.write_byte(fi.writer, '(', &fi.n)
io.write_int(fi.writer, int(a.column), 10, &fi.n) io.write_int(fi.writer, int(a.line), 10, &fi.n)
io.write_byte(fi.writer, ')', &fi.n) io.write_byte(fi.writer, ':', &fi.n)
io.write_int(fi.writer, int(a.column), 10, &fi.n)
io.write_byte(fi.writer, ')', &fi.n)
} else when ODIN_ERROR_POS_STYLE == .Unix {
io.write_byte(fi.writer, ':', &fi.n)
io.write_int(fi.writer, int(a.line), 10, &fi.n)
io.write_byte(fi.writer, ':', &fi.n)
io.write_int(fi.writer, int(a.column), 10, &fi.n)
io.write_byte(fi.writer, ':', &fi.n)
} else {
#panic("Unhandled ODIN_ERROR_POS_STYLE")
}
return return
case time.Duration: case time.Duration:
@@ -2647,18 +2663,10 @@ fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) {
} }
} }
arg_info := type_info_of(arg.id)
custom_types: switch a in arg { if info, ok := arg_info.variant.(runtime.Type_Info_Named); ok {
case runtime.Source_Code_Location: fmt_named(fi, arg, verb, info)
if fi.hash && verb == 'v' { return
io.write_string(fi.writer, a.file_path, &fi.n)
io.write_byte(fi.writer, '(', &fi.n)
io.write_i64(fi.writer, i64(a.line), 10, &fi.n)
io.write_byte(fi.writer, ':', &fi.n)
io.write_i64(fi.writer, i64(a.column), 10, &fi.n)
io.write_byte(fi.writer, ')', &fi.n)
return
}
} }
base_arg := arg base_arg := arg
+11 -14
View File
@@ -7,31 +7,28 @@ foreign import "odin_env"
@(private="file") @(private="file")
foreign odin_env { foreign odin_env {
write :: proc "c" (fd: u32, p: []byte) --- write :: proc "contextless" (fd: u32, p: []byte) ---
} }
@(private="file") @(private="file")
write_vtable := io.Stream_VTable{ write_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) { if mode == .Write {
fd := u32(uintptr(s.stream_data)) fd := u32(uintptr(stream_data))
write(fd, p) write(fd, p)
return len(p), nil return i64(len(p)), nil
}, }
return 0, .Empty
} }
@(private="file") @(private="file")
stdout := io.Writer{ stdout := io.Writer{
stream = { procedure = write_stream_proc,
stream_vtable = &write_vtable, data = rawptr(uintptr(1)),
stream_data = rawptr(uintptr(1)),
},
} }
@(private="file") @(private="file")
stderr := io.Writer{ stderr := io.Writer{
stream = { procedure = write_stream_proc,
stream_vtable = &write_vtable, data = rawptr(uintptr(2)),
stream_data = rawptr(uintptr(2)),
},
} }
// print formats using the default print settings and writes to stdout // print formats using the default print settings and writes to stdout
+11 -11
View File
@@ -12,9 +12,9 @@ fprint :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
b: bufio.Writer b: bufio.Writer
defer bufio.writer_flush(&b) defer bufio.writer_flush(&b)
bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:]) bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b) w := bufio.writer_to_writer(&b)
return wprint(w=w, args=args, sep=sep) return wprint(w, ..args, sep=sep)
} }
// fprintln formats using the default print settings and writes to fd // fprintln formats using the default print settings and writes to fd
@@ -23,10 +23,10 @@ fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
b: bufio.Writer b: bufio.Writer
defer bufio.writer_flush(&b) defer bufio.writer_flush(&b)
bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:]) bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b) w := bufio.writer_to_writer(&b)
return wprintln(w=w, args=args, sep=sep) return wprintln(w, ..args, sep=sep)
} }
// fprintf formats according to the specified format string and writes to fd // fprintf formats according to the specified format string and writes to fd
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int { fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
@@ -34,7 +34,7 @@ fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
b: bufio.Writer b: bufio.Writer
defer bufio.writer_flush(&b) defer bufio.writer_flush(&b)
bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:]) bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b) w := bufio.writer_to_writer(&b)
return wprintf(w, fmt, ..args) return wprintf(w, fmt, ..args)
@@ -44,7 +44,7 @@ fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info) -> (n: int, err: io
b: bufio.Writer b: bufio.Writer
defer bufio.writer_flush(&b) defer bufio.writer_flush(&b)
bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:]) bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b) w := bufio.writer_to_writer(&b)
return wprint_type(w, info) return wprint_type(w, info)
@@ -54,22 +54,22 @@ fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) {
b: bufio.Writer b: bufio.Writer
defer bufio.writer_flush(&b) defer bufio.writer_flush(&b)
bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:]) bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
w := bufio.writer_to_writer(&b) w := bufio.writer_to_writer(&b)
return wprint_typeid(w, id) return wprint_typeid(w, id)
} }
// print formats using the default print settings and writes to os.stdout // print formats using the default print settings and writes to os.stdout
print :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stdout, args=args, sep=sep) } print :: proc(args: ..any, sep := " ") -> int { return fprint(os.stdout, ..args, sep=sep) }
// println formats using the default print settings and writes to os.stdout // println formats using the default print settings and writes to os.stdout
println :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stdout, args=args, sep=sep) } println :: proc(args: ..any, sep := " ") -> int { return fprintln(os.stdout, ..args, sep=sep) }
// printf formats according to the specified format string and writes to os.stdout // printf formats according to the specified format string and writes to os.stdout
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) } printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) }
// eprint formats using the default print settings and writes to os.stderr // eprint formats using the default print settings and writes to os.stderr
eprint :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stderr, args=args, sep=sep) } eprint :: proc(args: ..any, sep := " ") -> int { return fprint(os.stderr, ..args, sep=sep) }
// eprintln formats using the default print settings and writes to os.stderr // eprintln formats using the default print settings and writes to os.stderr
eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stderr, args=args, sep=sep) } eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(os.stderr, ..args, sep=sep) }
// eprintf formats according to the specified format string and writes to os.stderr // eprintf formats according to the specified format string and writes to os.stderr
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) } eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
+5 -5
View File
@@ -634,7 +634,7 @@ alpha_add_if_missing :: proc(img: ^Image, alpha_key := Alpha_Key{}, allocator :=
buf := bytes.Buffer{} buf := bytes.Buffer{}
// Can we allocate the return buffer? // Can we allocate the return buffer?
if !resize(&buf.buf, bytes_wanted) { if resize(&buf.buf, bytes_wanted) != nil {
delete(buf.buf) delete(buf.buf)
return false return false
} }
@@ -826,7 +826,7 @@ alpha_drop_if_present :: proc(img: ^Image, options := Options{}, alpha_key := Al
buf := bytes.Buffer{} buf := bytes.Buffer{}
// Can we allocate the return buffer? // Can we allocate the return buffer?
if !resize(&buf.buf, bytes_wanted) { if resize(&buf.buf, bytes_wanted) != nil {
delete(buf.buf) delete(buf.buf)
return false return false
} }
@@ -1075,7 +1075,7 @@ apply_palette_rgb :: proc(img: ^Image, palette: [256]RGB_Pixel, allocator := con
// Can we allocate the return buffer? // Can we allocate the return buffer?
buf := bytes.Buffer{} buf := bytes.Buffer{}
bytes_wanted := compute_buffer_size(img.width, img.height, 3, 8) bytes_wanted := compute_buffer_size(img.width, img.height, 3, 8)
if !resize(&buf.buf, bytes_wanted) { if resize(&buf.buf, bytes_wanted) != nil {
delete(buf.buf) delete(buf.buf)
return false return false
} }
@@ -1112,7 +1112,7 @@ apply_palette_rgba :: proc(img: ^Image, palette: [256]RGBA_Pixel, allocator := c
// Can we allocate the return buffer? // Can we allocate the return buffer?
buf := bytes.Buffer{} buf := bytes.Buffer{}
bytes_wanted := compute_buffer_size(img.width, img.height, 4, 8) bytes_wanted := compute_buffer_size(img.width, img.height, 4, 8)
if !resize(&buf.buf, bytes_wanted) { if resize(&buf.buf, bytes_wanted) != nil {
delete(buf.buf) delete(buf.buf)
return false return false
} }
@@ -1147,7 +1147,7 @@ expand_grayscale :: proc(img: ^Image, allocator := context.allocator) -> (ok: bo
// Can we allocate the return buffer? // Can we allocate the return buffer?
buf := bytes.Buffer{} buf := bytes.Buffer{}
bytes_wanted := compute_buffer_size(img.width, img.height, img.channels + 2, img.depth) bytes_wanted := compute_buffer_size(img.width, img.height, img.channels + 2, img.depth)
if !resize(&buf.buf, bytes_wanted) { if resize(&buf.buf, bytes_wanted) != nil {
delete(buf.buf) delete(buf.buf)
return false return false
} }
+8 -7
View File
@@ -4,13 +4,14 @@ import "core:bytes"
import "core:image" import "core:image"
destroy :: proc(img: ^image.Image) -> bool { destroy :: proc(img: ^image.Image) -> bool {
if img == nil do return false if img == nil {
return false
}
defer free(img) defer free(img)
bytes.buffer_destroy(&img.pixels) bytes.buffer_destroy(&img.pixels)
info, ok := img.metadata.(^image.Netpbm_Info) info := img.metadata.(^image.Netpbm_Info) or_return
if !ok do return false
header_destroy(&info.header) header_destroy(&info.header)
free(info) free(info)
@@ -19,9 +20,9 @@ destroy :: proc(img: ^image.Image) -> bool {
return true return true
} }
header_destroy :: proc(using header: ^Header) { header_destroy :: proc(header: ^Header) {
if format == .P7 && tupltype != "" { if header.format == .P7 && header.tupltype != "" {
delete(tupltype) delete(header.tupltype)
tupltype = "" header.tupltype = ""
} }
} }
+7 -6
View File
@@ -1,3 +1,4 @@
//+vet !using-stmt
package netpbm package netpbm
import "core:bytes" import "core:bytes"
@@ -161,18 +162,18 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context
// convert from native endianness // convert from native endianness
if img.depth == 16 { if img.depth == 16 {
pixels := mem.slice_data_cast([]u16be, data.buf[len(header_buf):]) pixels := mem.slice_data_cast([]u16be, data.buf[len(header_buf):])
for p in &pixels { for &p in pixels {
p = u16be(transmute(u16) p) p = u16be(transmute(u16) p)
} }
} else if header.format in PFM { } else if header.format in PFM {
if header.little_endian { if header.little_endian {
pixels := mem.slice_data_cast([]f32le, data.buf[len(header_buf):]) pixels := mem.slice_data_cast([]f32le, data.buf[len(header_buf):])
for p in &pixels { for &p in pixels {
p = f32le(transmute(f32) p) p = f32le(transmute(f32) p)
} }
} else { } else {
pixels := mem.slice_data_cast([]f32be, data.buf[len(header_buf):]) pixels := mem.slice_data_cast([]f32be, data.buf[len(header_buf):])
for p in &pixels { for &p in pixels {
p = f32be(transmute(f32) p) p = f32be(transmute(f32) p)
} }
} }
@@ -578,18 +579,18 @@ decode_image :: proc(img: ^Image, header: Header, data: []byte, allocator := con
if header.format in PFM { if header.format in PFM {
pixels := mem.slice_data_cast([]f32, img.pixels.buf[:]) pixels := mem.slice_data_cast([]f32, img.pixels.buf[:])
if header.little_endian { if header.little_endian {
for p in &pixels { for &p in pixels {
p = f32(transmute(f32le) p) p = f32(transmute(f32le) p)
} }
} else { } else {
for p in &pixels { for &p in pixels {
p = f32(transmute(f32be) p) p = f32(transmute(f32be) p)
} }
} }
} else { } else {
if img.depth == 16 { if img.depth == 16 {
pixels := mem.slice_data_cast([]u16, img.pixels.buf[:]) pixels := mem.slice_data_cast([]u16, img.pixels.buf[:])
for p in &pixels { for &p in pixels {
p = u16(transmute(u16be) p) p = u16(transmute(u16be) p)
} }
} }
+8 -9
View File
@@ -36,7 +36,7 @@ destroy :: proc(img: ^Image) {
bytes.buffer_destroy(&img.pixels) bytes.buffer_destroy(&img.pixels)
if v, ok := img.metadata.(^image.PNG_Info); ok { if v, ok := img.metadata.(^image.PNG_Info); ok {
for chunk in &v.chunks { for chunk in v.chunks {
delete(chunk.data) delete(chunk.data)
} }
delete(v.chunks) delete(v.chunks)
@@ -80,11 +80,10 @@ time :: proc(c: image.PNG_Chunk) -> (res: tIME, ok: bool) {
} }
core_time :: proc(c: image.PNG_Chunk) -> (t: coretime.Time, ok: bool) { core_time :: proc(c: image.PNG_Chunk) -> (t: coretime.Time, ok: bool) {
if png_time, png_ok := time(c); png_ok { if t, png_ok := time(c); png_ok {
using png_time
return coretime.datetime_to_time( return coretime.datetime_to_time(
int(year), int(month), int(day), int(t.year), int(t.month), int(t.day),
int(hour), int(minute), int(second), int(t.hour), int(t.minute), int(t.second),
) )
} else { } else {
return {}, false return {}, false
@@ -99,7 +98,7 @@ text :: proc(c: image.PNG_Chunk) -> (res: Text, ok: bool) {
case .tEXt: case .tEXt:
ok = true ok = true
fields := bytes.split(s=c.data, sep=[]u8{0}, allocator=context.temp_allocator) fields := bytes.split(c.data, sep=[]u8{0}, allocator=context.temp_allocator)
if len(fields) == 2 { if len(fields) == 2 {
res.keyword = strings.clone(string(fields[0])) res.keyword = strings.clone(string(fields[0]))
res.text = strings.clone(string(fields[1])) res.text = strings.clone(string(fields[1]))
@@ -110,7 +109,7 @@ text :: proc(c: image.PNG_Chunk) -> (res: Text, ok: bool) {
case .zTXt: case .zTXt:
ok = true ok = true
fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator) fields := bytes.split_n(c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
if len(fields) != 3 || len(fields[1]) != 0 { if len(fields) != 3 || len(fields[1]) != 0 {
// Compression method must be 0=Deflate, which thanks to the split above turns // Compression method must be 0=Deflate, which thanks to the split above turns
// into an empty slice // into an empty slice
@@ -199,7 +198,7 @@ text_destroy :: proc(text: Text) {
iccp :: proc(c: image.PNG_Chunk) -> (res: iCCP, ok: bool) { iccp :: proc(c: image.PNG_Chunk) -> (res: iCCP, ok: bool) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator) fields := bytes.split_n(c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
if len(fields[0]) < 1 || len(fields[0]) > 79 { if len(fields[0]) < 1 || len(fields[0]) > 79 {
// Invalid profile name // Invalid profile name
@@ -263,7 +262,7 @@ splt :: proc(c: image.PNG_Chunk) -> (res: sPLT, ok: bool) {
} }
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=2, allocator=context.temp_allocator) fields := bytes.split_n(c.data, sep=[]u8{0}, n=2, allocator=context.temp_allocator)
if len(fields) != 2 { if len(fields) != 2 {
return return
} }
+13 -13
View File
@@ -11,6 +11,7 @@
// package png implements a PNG image reader // package png implements a PNG image reader
// //
// The PNG specification is at https://www.w3.org/TR/PNG/. // The PNG specification is at https://www.w3.org/TR/PNG/.
//+vet !using-stmt
package png package png
import "core:compress" import "core:compress"
@@ -444,15 +445,14 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
img.width = int(header.width) img.width = int(header.width)
img.height = int(header.height) img.height = int(header.height)
using header
h := image.PNG_IHDR{ h := image.PNG_IHDR{
width = width, width = header.width,
height = height, height = header.height,
bit_depth = bit_depth, bit_depth = header.bit_depth,
color_type = color_type, color_type = header.color_type,
compression_method = compression_method, compression_method = header.compression_method,
filter_method = filter_method, filter_method = header.filter_method,
interlace_method = interlace_method, interlace_method = header.interlace_method,
} }
info.header = h info.header = h
@@ -731,7 +731,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
// We need to create a new image buffer // We need to create a new image buffer
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8) dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8)
t := bytes.Buffer{} t := bytes.Buffer{}
if !resize(&t.buf, dest_raw_size) { if resize(&t.buf, dest_raw_size) != nil {
return {}, .Unable_To_Allocate_Or_Resize return {}, .Unable_To_Allocate_Or_Resize
} }
@@ -812,7 +812,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
// We need to create a new image buffer // We need to create a new image buffer
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 16) dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 16)
t := bytes.Buffer{} t := bytes.Buffer{}
if !resize(&t.buf, dest_raw_size) { if resize(&t.buf, dest_raw_size) != nil {
return {}, .Unable_To_Allocate_Or_Resize return {}, .Unable_To_Allocate_Or_Resize
} }
@@ -1011,7 +1011,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
// We need to create a new image buffer // We need to create a new image buffer
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8) dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8)
t := bytes.Buffer{} t := bytes.Buffer{}
if !resize(&t.buf, dest_raw_size) { if resize(&t.buf, dest_raw_size) != nil {
return {}, .Unable_To_Allocate_Or_Resize return {}, .Unable_To_Allocate_Or_Resize
} }
@@ -1522,7 +1522,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
bytes_per_channel := depth == 16 ? 2 : 1 bytes_per_channel := depth == 16 ? 2 : 1
num_bytes := compute_buffer_size(width, height, channels, depth == 16 ? 16 : 8) num_bytes := compute_buffer_size(width, height, channels, depth == 16 ? 16 : 8)
if !resize(&img.pixels.buf, num_bytes) { if resize(&img.pixels.buf, num_bytes) != nil {
return .Unable_To_Allocate_Or_Resize return .Unable_To_Allocate_Or_Resize
} }
@@ -1564,7 +1564,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
if x > 0 && y > 0 { if x > 0 && y > 0 {
temp: bytes.Buffer temp: bytes.Buffer
temp_len := compute_buffer_size(x, y, channels, depth == 16 ? 16 : 8) temp_len := compute_buffer_size(x, y, channels, depth == 16 ? 16 : 8)
if !resize(&temp.buf, temp_len) { if resize(&temp.buf, temp_len) != nil {
return .Unable_To_Allocate_Or_Resize return .Unable_To_Allocate_Or_Resize
} }
+2 -2
View File
@@ -53,7 +53,7 @@ save_to_buffer :: proc(output: ^bytes.Buffer, img: ^Image, options := Options{}
// Calculate and allocate maximum size. We'll reclaim space to actually written output at the end. // Calculate and allocate maximum size. We'll reclaim space to actually written output at the end.
max_size := pixels * (img.channels + 1) + size_of(image.QOI_Header) + size_of(u64be) max_size := pixels * (img.channels + 1) + size_of(image.QOI_Header) + size_of(u64be)
if !resize(&output.buf, max_size) { if resize(&output.buf, max_size) != nil {
return .Unable_To_Allocate_Or_Resize return .Unable_To_Allocate_Or_Resize
} }
@@ -233,7 +233,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
bytes_needed := image.compute_buffer_size(int(header.width), int(header.height), img.channels, 8) bytes_needed := image.compute_buffer_size(int(header.width), int(header.height), img.channels, 8)
if !resize(&img.pixels.buf, bytes_needed) { if resize(&img.pixels.buf, bytes_needed) != nil {
return img, .Unable_To_Allocate_Or_Resize return img, .Unable_To_Allocate_Or_Resize
} }
+2 -2
View File
@@ -57,7 +57,7 @@ save_to_buffer :: proc(output: ^bytes.Buffer, img: ^Image, options := Options{}
// Calculate and allocate necessary space. // Calculate and allocate necessary space.
necessary := pixels * img.channels + size_of(image.TGA_Header) necessary := pixels * img.channels + size_of(image.TGA_Header)
if !resize(&output.buf, necessary) { if resize(&output.buf, necessary) != nil {
return .Unable_To_Allocate_Or_Resize return .Unable_To_Allocate_Or_Resize
} }
@@ -292,7 +292,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
return img, nil return img, nil
} }
if !resize(&img.pixels.buf, dest_channels * img.width * img.height) { if resize(&img.pixels.buf, dest_channels * img.width * img.height) != nil {
return img, .Unable_To_Allocate_Or_Resize return img, .Unable_To_Allocate_Or_Resize
} }
+1
View File
@@ -192,6 +192,7 @@ type_map_info :: proc($T: typeid/map[$K]$V) -> ^runtime.Map_Info ---
type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info --- type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) --- type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
constant_utf16_cstring :: proc($literal: string) -> [^]u16 --- constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
+30 -74
View File
@@ -1,124 +1,80 @@
package io package io
to_reader :: proc(s: Stream) -> (r: Reader, ok: bool = true) #optional_ok { to_reader :: proc(s: Stream) -> (r: Reader, ok: bool = true) #optional_ok {
r.stream = s r = s
if s.stream_vtable == nil || s.impl_read == nil { ok = .Read in query(s)
ok = false
}
return return
} }
to_writer :: proc(s: Stream) -> (w: Writer, ok: bool = true) #optional_ok { to_writer :: proc(s: Stream) -> (w: Writer, ok: bool = true) #optional_ok {
w.stream = s w = s
if s.stream_vtable == nil || s.impl_write == nil { ok = .Write in query(s)
ok = false
}
return return
} }
to_closer :: proc(s: Stream) -> (c: Closer, ok: bool = true) #optional_ok { to_closer :: proc(s: Stream) -> (c: Closer, ok: bool = true) #optional_ok {
c.stream = s c = s
if s.stream_vtable == nil || s.impl_close == nil { ok = .Close in query(s)
ok = false
}
return return
} }
to_flusher :: proc(s: Stream) -> (f: Flusher, ok: bool = true) #optional_ok { to_flusher :: proc(s: Stream) -> (f: Flusher, ok: bool = true) #optional_ok {
f.stream = s f = s
if s.stream_vtable == nil || s.impl_flush == nil { ok = .Flush in query(s)
ok = false
}
return return
} }
to_seeker :: proc(s: Stream) -> (seeker: Seeker, ok: bool = true) #optional_ok { to_seeker :: proc(s: Stream) -> (seeker: Seeker, ok: bool = true) #optional_ok {
seeker.stream = s seeker = s
if s.stream_vtable == nil || s.impl_seek == nil { ok = .Seek in query(s)
ok = false
}
return return
} }
to_read_writer :: proc(s: Stream) -> (r: Read_Writer, ok: bool = true) #optional_ok { to_read_writer :: proc(s: Stream) -> (r: Read_Writer, ok: bool = true) #optional_ok {
r.stream = s r = s
if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil { ok = query(s) >= {.Read, .Write}
ok = false
}
return return
} }
to_read_closer :: proc(s: Stream) -> (r: Read_Closer, ok: bool = true) #optional_ok { to_read_closer :: proc(s: Stream) -> (r: Read_Closer, ok: bool = true) #optional_ok {
r.stream = s r = s
if s.stream_vtable == nil || s.impl_read == nil || s.impl_close == nil { ok = query(s) >= {.Read, .Close}
ok = false
}
return return
} }
to_read_write_closer :: proc(s: Stream) -> (r: Read_Write_Closer, ok: bool = true) #optional_ok { to_read_write_closer :: proc(s: Stream) -> (r: Read_Write_Closer, ok: bool = true) #optional_ok {
r.stream = s r = s
if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil || s.impl_close == nil { ok = query(s) >= {.Read, .Write, .Close}
ok = false
}
return return
} }
to_read_write_seeker :: proc(s: Stream) -> (r: Read_Write_Seeker, ok: bool = true) #optional_ok { to_read_write_seeker :: proc(s: Stream) -> (r: Read_Write_Seeker, ok: bool = true) #optional_ok {
r.stream = s r = s
if s.stream_vtable == nil || s.impl_read == nil || s.impl_write == nil || s.impl_seek == nil { ok = query(s) >= {.Read, .Write, .Seek}
ok = false
}
return return
} }
to_write_flusher :: proc(s: Stream) -> (w: Write_Flusher, ok: bool = true) #optional_ok { to_write_flusher :: proc(s: Stream) -> (w: Write_Flusher, ok: bool = true) #optional_ok {
w.stream = s w = s
if s.stream_vtable == nil || s.impl_write == nil || s.impl_flush == nil { ok = query(s) >= {.Write, .Flush}
ok = false
}
return return
} }
to_write_flush_closer :: proc(s: Stream) -> (w: Write_Flush_Closer, ok: bool = true) #optional_ok { to_write_flush_closer :: proc(s: Stream) -> (w: Write_Flush_Closer, ok: bool = true) #optional_ok {
w.stream = s w = s
if s.stream_vtable == nil || s.impl_write == nil || s.impl_flush == nil || s.impl_close == nil { ok = query(s) >= {.Write, .Flush, .Close}
ok = false
}
return return
} }
to_reader_at :: proc(s: Stream) -> (r: Reader_At, ok: bool = true) #optional_ok { to_reader_at :: proc(s: Stream) -> (r: Reader_At, ok: bool = true) #optional_ok {
r.stream = s r = s
if s.stream_vtable == nil || s.impl_read_at == nil { ok = query(s) >= {.Read_At}
ok = false
}
return return
} }
to_writer_at :: proc(s: Stream) -> (w: Writer_At, ok: bool = true) #optional_ok { to_writer_at :: proc(s: Stream) -> (w: Writer_At, ok: bool = true) #optional_ok {
w.stream = s w = s
if s.stream_vtable == nil || s.impl_write_at == nil { ok = query(s) >= {.Write_At}
ok = false
}
return
}
to_reader_from :: proc(s: Stream) -> (r: Reader_From, ok: bool = true) #optional_ok {
r.stream = s
if s.stream_vtable == nil || s.impl_read_from == nil {
ok = false
}
return
}
to_writer_to :: proc(s: Stream) -> (w: Writer_To, ok: bool = true) #optional_ok {
w.stream = s
if s.stream_vtable == nil || s.impl_write_to == nil {
ok = false
}
return return
} }
to_write_closer :: proc(s: Stream) -> (w: Write_Closer, ok: bool = true) #optional_ok { to_write_closer :: proc(s: Stream) -> (w: Write_Closer, ok: bool = true) #optional_ok {
w.stream = s w = s
if s.stream_vtable == nil || s.impl_write == nil || s.impl_close == nil { ok = query(s) >= {.Write, .Close}
ok = false
}
return return
} }
to_write_seeker :: proc(s: Stream) -> (w: Write_Seeker, ok: bool = true) #optional_ok { to_write_seeker :: proc(s: Stream) -> (w: Write_Seeker, ok: bool = true) #optional_ok {
w.stream = s w = s
if s.stream_vtable == nil || s.impl_write == nil || s.impl_seek == nil { ok = query(s) >= {.Write, .Seek}
ok = false
}
return return
} }
+146 -298
View File
@@ -53,137 +53,106 @@ Error :: enum i32 {
Empty = -1, Empty = -1,
} }
Close_Proc :: proc(using s: Stream) -> Error Stream_Mode :: enum {
Flush_Proc :: proc(using s: Stream) -> Error Close,
Seek_Proc :: proc(using s: Stream, offset: i64, whence: Seek_From) -> (n: i64, err: Error) Flush,
Size_Proc :: proc(using s: Stream) -> i64 Read,
Read_Proc :: proc(using s: Stream, p: []byte) -> (n: int, err: Error) Read_At,
Read_At_Proc :: proc(using s: Stream, p: []byte, off: i64) -> (n: int, err: Error) Write,
Read_From_Proc :: proc(using s: Stream, r: Reader) -> (n: i64, err: Error) Write_At,
Read_Byte_Proc :: proc(using s: Stream) -> (byte, Error) Seek,
Read_Rune_Proc :: proc(using s: Stream) -> (ch: rune, size: int, err: Error) Size,
Unread_Byte_Proc :: proc(using s: Stream) -> Error Destroy,
Unread_Rune_Proc :: proc(using s: Stream) -> Error Query, // query what modes are available
Write_Proc :: proc(using s: Stream, p: []byte) -> (n: int, err: Error) }
Write_At_Proc :: proc(using s: Stream, p: []byte, off: i64) -> (n: int, err: Error)
Write_To_Proc :: proc(using s: Stream, w: Writer) -> (n: i64, err: Error)
Write_Byte_Proc :: proc(using s: Stream, c: byte) -> Error
Write_Rune_Proc :: proc(using s: Stream, r: rune) -> (size: int, err: Error)
Destroy_Proc :: proc(using s: Stream) -> Error
Stream_Mode_Set :: distinct bit_set[Stream_Mode; i64]
Stream_Proc :: #type proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error)
Stream :: struct { Stream :: struct {
using stream_vtable: ^Stream_VTable, procedure: Stream_Proc,
stream_data: rawptr, data: rawptr,
}
Stream_VTable :: struct {
impl_close: Close_Proc,
impl_flush: Flush_Proc,
impl_seek: Seek_Proc,
impl_size: Size_Proc,
impl_read: Read_Proc,
impl_read_at: Read_At_Proc,
impl_read_byte: Read_Byte_Proc,
impl_read_rune: Read_Rune_Proc,
impl_write_to: Write_To_Proc,
impl_write: Write_Proc,
impl_write_at: Write_At_Proc,
impl_write_byte: Write_Byte_Proc,
impl_write_rune: Write_Rune_Proc,
impl_read_from: Read_From_Proc,
impl_unread_byte: Unread_Byte_Proc,
impl_unread_rune: Unread_Rune_Proc,
impl_destroy: Destroy_Proc,
} }
Reader :: Stream
Writer :: Stream
Closer :: Stream
Flusher :: Stream
Seeker :: Stream
Reader :: struct {using stream: Stream} Read_Writer :: Stream
Writer :: struct {using stream: Stream} Read_Closer :: Stream
Closer :: struct {using stream: Stream} Read_Write_Closer :: Stream
Flusher :: struct {using stream: Stream} Read_Write_Seeker :: Stream
Seeker :: struct {using stream: Stream}
Read_Writer :: struct {using stream: Stream} Write_Closer :: Stream
Read_Closer :: struct {using stream: Stream} Write_Seeker :: Stream
Read_Write_Closer :: struct {using stream: Stream} Write_Flusher :: Stream
Read_Write_Seeker :: struct {using stream: Stream} Write_Flush_Closer :: Stream
Write_Closer :: struct {using stream: Stream} Reader_At :: Stream
Write_Seeker :: struct {using stream: Stream} Writer_At :: Stream
Write_Flusher :: struct {using stream: Stream}
Write_Flush_Closer :: struct {using stream: Stream}
Reader_At :: struct {using stream: Stream}
Writer_At :: struct {using stream: Stream}
Reader_From :: struct {using stream: Stream}
Writer_To :: struct {using stream: Stream}
destroy :: proc(s: Stream) -> Error { destroy :: proc(s: Stream) -> (err: Error) {
close_err := close({s}) _ = flush(s)
if s.stream_vtable != nil && s.impl_destroy != nil { _ = close(s)
return s->impl_destroy() if s.procedure != nil {
_, err = s.procedure(s.data, .Destroy, nil, 0, nil)
} else {
err = .Empty
} }
if close_err != .None { return
return close_err
}
return .Empty
} }
query :: proc(s: Stream) -> (set: Stream_Mode_Set) {
if s.procedure != nil {
n, _ := s.procedure(s.data, .Query, nil, 0, nil)
set = transmute(Stream_Mode_Set)n
if set != nil {
set += {.Query}
}
}
return
}
query_utility :: #force_inline proc "contextless" (set: Stream_Mode_Set) -> (n: i64, err: Error) {
return transmute(i64)set, nil
}
_i64_err :: #force_inline proc "contextless" (n: int, err: Error) -> (i64, Error) {
return i64(n), err
}
// read reads up to len(p) bytes into s. It returns the number of bytes read and any error if occurred. // read reads up to len(p) bytes into s. It returns the number of bytes read and any error if occurred.
// //
// When read encounters an .EOF or error after successfully reading n > 0 bytes, it returns the number of // When read encounters an .EOF or error after successfully reading n > 0 bytes, it returns the number of
// bytes read along with the error. // bytes read along with the error.
read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) { read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
if s.stream_vtable != nil { if s.procedure != nil {
if s.impl_read != nil { n64: i64
n, err = s->impl_read(p) n64, err = s.procedure(s.data, .Read, p, 0, nil)
if n_read != nil { n = int(n64)
n_read^ += n if n_read != nil { n_read^ += n }
} } else {
return err = .Empty
} else if s.impl_read_byte != nil {
bytes_read := 0
defer if n_read != nil {
n_read^ += bytes_read
}
for _, i in p {
p[i] = s->impl_read_byte() or_return
bytes_read += 1
}
return
}
} }
return 0, .Empty return
} }
// write writes up to len(p) bytes into s. It returns the number of bytes written and any error if occurred. // write writes up to len(p) bytes into s. It returns the number of bytes written and any error if occurred.
write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Error) { write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Error) {
if s.stream_vtable != nil { if s.procedure != nil {
if s.impl_write != nil { n64: i64
n, err = s->impl_write(p) n64, err = s.procedure(s.data, .Write, p, 0, nil)
if n_written != nil { n = int(n64)
n_written^ += n if n_written != nil { n_written^ += n }
} } else {
return err = .Empty
} else if s.impl_write_byte != nil {
bytes_written := 0
defer if n_written != nil {
n_written^ += bytes_written
}
for c in p {
s->impl_write_byte(c) or_return
bytes_written += 1
}
return
}
} }
return 0, .Empty return
} }
// seek sets the offset of the next read or write to offset. // seek sets the offset of the next read or write to offset.
@@ -194,57 +163,45 @@ write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Erro
// //
// seek returns the new offset to the start of the file/stream, and any error if occurred. // seek returns the new offset to the start of the file/stream, and any error if occurred.
seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error) { seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
if s.stream_vtable != nil && s.impl_seek != nil { if s.procedure != nil {
return s->impl_seek(offset, whence) n, err = s.procedure(s.data, .Seek, nil, offset, whence)
} else {
err = .Empty
} }
return 0, .Empty return
} }
// The behaviour of close after the first call is stream implementation defined. // The behaviour of close after the first call is stream implementation defined.
// Different streams may document their own behaviour. // Different streams may document their own behaviour.
close :: proc(s: Closer) -> Error { close :: proc(s: Closer) -> (err: Error) {
if s.stream_vtable != nil && s.impl_close != nil { if s.procedure != nil {
return s->impl_close() _, err = s.procedure(s.data, .Close, nil, 0, nil)
} }
// Instead of .Empty, .None is fine in this case return
return .None
} }
flush :: proc(s: Flusher) -> Error { flush :: proc(s: Flusher) -> (err: Error) {
if s.stream_vtable != nil && s.impl_flush != nil { if s.procedure != nil {
return s->impl_flush() _, err = s.procedure(s.data, .Flush, nil, 0, nil)
} }
// Instead of .Empty, .None is fine in this case return
return .None
} }
// size returns the size of the stream. If the stream does not support querying its size, 0 will be returned. // size returns the size of the stream. If the stream does not support querying its size, 0 will be returned.
size :: proc(s: Stream) -> i64 { size :: proc(s: Stream) -> (n: i64, err: Error) {
if s.stream_vtable == nil { if s.procedure != nil {
return 0 n, err = s.procedure(s.data, .Size, nil, 0, nil)
if err == .Empty {
n = 0
curr := seek(s, 0, .Current) or_return
end := seek(s, 0, .End) or_return
seek(s, curr, .Start) or_return
n = end
}
} else {
err = .Empty
} }
if s.impl_size != nil { return
return s->impl_size()
}
if s.impl_seek == nil {
return 0
}
curr, end: i64
err: Error
if curr, err = s->impl_seek(0, .Current); err != nil {
return 0
}
if end, err = s->impl_seek(0, .End); err != nil {
return 0
}
if _, err = s->impl_seek(curr, .Start); err != nil {
return 0
}
return end
} }
@@ -256,29 +213,24 @@ size :: proc(s: Stream) -> i64 {
// //
// If n == len(p), err may be either nil or .EOF // If n == len(p), err may be either nil or .EOF
read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n: int, err: Error) { read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n: int, err: Error) {
defer if n_read != nil { if r.procedure != nil {
n_read^ += n n64: i64
} n64, err = r.procedure(r.data, .Read_At, p, offset, nil)
if err != .Empty {
if r.stream_vtable == nil { n = int(n64)
return 0, .Empty } else {
} curr := seek(r, offset, .Current) or_return
if r.impl_read_at != nil { n, err = read(r, p)
return r->impl_read_at(p, offset) _, err1 := seek(r, curr, .Start)
} if err1 != nil && err == nil {
if r.impl_seek == nil || r.impl_read == nil { err = err1
return 0, .Empty }
} }
if n_read != nil { n_read^ += n }
curr_offset := r->impl_seek(offset, .Current) or_return } else {
err = .Empty
n, err = r->impl_read(p)
_, err1 := r->impl_seek(curr_offset, .Start)
if err1 != nil && err == nil {
err = err1
} }
return return
} }
// write_at writes len(p) bytes into p starting with the provided offset in the underlying Writer_At stream w. // write_at writes len(p) bytes into p starting with the provided offset in the underlying Writer_At stream w.
@@ -287,97 +239,39 @@ read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n:
// If write_at is writing to a Writer_At which has a seek offset, then write_at should not affect the underlying // If write_at is writing to a Writer_At which has a seek offset, then write_at should not affect the underlying
// seek offset. // seek offset.
write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) { write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) {
defer if n_written != nil { if w.procedure != nil {
n_written^ += n n64: i64
} n64, err = w.procedure(w.data, .Write_At, p, offset, nil)
if err != .Empty {
if w.stream_vtable == nil { n = int(n64)
return 0, .Empty } else {
} curr := seek(w, offset, .Current) or_return
if w.impl_write_at != nil { n, err = write(w, p)
return w->impl_write_at(p, offset) _, err1 := seek(w, curr, .Start)
} if err1 != nil && err == nil {
if w.impl_seek == nil || w.impl_write == nil { err = err1
return 0, .Empty }
} }
if n_written != nil { n_written^ += n }
curr_offset: i64 } else {
curr_offset, err = w->impl_seek(offset, .Current) err = .Empty
if err != nil {
return 0, err
}
n, err = w->impl_write(p)
_, err1 := w->impl_seek(curr_offset, .Start)
if err1 != nil && err == nil {
err = err1
} }
return return
} }
write_to :: proc(r: Writer_To, w: Writer) -> (n: i64, err: Error) {
if r.stream_vtable == nil || w.stream_vtable == nil {
return 0, .Empty
}
if r.impl_write_to != nil {
return r->impl_write_to(w)
}
return 0, .Empty
}
read_from :: proc(w: Reader_From, r: Reader) -> (n: i64, err: Error) {
if r.stream_vtable == nil || w.stream_vtable == nil {
return 0, .Empty
}
if r.impl_read_from != nil {
return w->impl_read_from(r)
}
return 0, .Empty
}
// read_byte reads and returns the next byte from r. // read_byte reads and returns the next byte from r.
read_byte :: proc(r: Reader, n_read: ^int = nil) -> (b: byte, err: Error) { read_byte :: proc(r: Reader, n_read: ^int = nil) -> (b: byte, err: Error) {
defer if err == nil && n_read != nil {
n_read^ += 1
}
if r.stream_vtable == nil {
return 0, .Empty
}
if r.impl_read_byte != nil {
return r->impl_read_byte()
}
if r.impl_read == nil {
return 0, .Empty
}
buf: [1]byte buf: [1]byte
_, err = r->impl_read(buf[:]) _, err = read(r, buf[:], n_read)
return buf[0], err b = buf[0]
return
} }
write_byte :: proc(w: Writer, c: byte, n_written: ^int = nil) -> Error { write_byte :: proc(w: Writer, c: byte, n_written: ^int = nil) -> Error {
return _write_byte(auto_cast w, c, n_written) buf: [1]byte
} buf[0] = c
write(w, buf[:], n_written) or_return
@(private) return nil
_write_byte :: proc(w: Writer, c: byte, n_written: ^int = nil) -> (err: Error) {
defer if err == nil && n_written != nil {
n_written^ += 1
}
if w.stream_vtable == nil {
return .Empty
}
if w.impl_write_byte != nil {
return w->impl_write_byte(c)
}
if w.impl_write == nil {
return .Empty
}
b := [1]byte{c}
_, err = w->impl_write(b[:])
return err
} }
// read_rune reads a single UTF-8 encoded Unicode codepoint and returns the rune and its size in bytes. // read_rune reads a single UTF-8 encoded Unicode codepoint and returns the rune and its size in bytes.
@@ -385,19 +279,9 @@ read_rune :: proc(br: Reader, n_read: ^int = nil) -> (ch: rune, size: int, err:
defer if err == nil && n_read != nil { defer if err == nil && n_read != nil {
n_read^ += size n_read^ += size
} }
if br.stream_vtable == nil {
return 0, 0, .Empty
}
if br.impl_read_rune != nil {
return br->impl_read_rune()
}
if br.impl_read == nil {
return 0, 0, .Empty
}
b: [utf8.UTF_MAX]byte b: [utf8.UTF_MAX]byte
_, err = br->impl_read(b[:1]) _, err = read(br, b[:1])
s0 := b[0] s0 := b[0]
ch = rune(s0) ch = rune(s0)
@@ -415,7 +299,7 @@ read_rune :: proc(br: Reader, n_read: ^int = nil) -> (ch: rune, size: int, err:
return return
} }
sz := int(x&7) sz := int(x&7)
size, err = br->impl_read(b[1:sz]) size, err = read(br, b[1:sz])
if err != nil || size+1 < sz { if err != nil || size+1 < sz {
ch = utf8.RUNE_ERROR ch = utf8.RUNE_ERROR
return return
@@ -425,28 +309,6 @@ read_rune :: proc(br: Reader, n_read: ^int = nil) -> (ch: rune, size: int, err:
return return
} }
unread_byte :: proc(s: Stream) -> Error {
if s.stream_vtable == nil {
return .Empty
}
if s.impl_unread_byte != nil {
return s->impl_unread_byte()
}
if s.impl_seek != nil {
_, err := s->impl_seek(-1, .Current)
return err
}
return .Empty
}
unread_rune :: proc(s: Writer) -> Error {
if s.stream_vtable != nil && s.impl_unread_rune != nil {
return s->impl_unread_rune()
}
return .Empty
}
// write_string writes the contents of the string s to w. // write_string writes the contents of the string s to w.
write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, err: Error) { write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, err: Error) {
return write(s, transmute([]byte)str, n_written) return write(s, transmute([]byte)str, n_written)
@@ -457,14 +319,6 @@ write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err
defer if err == nil && n_written != nil { defer if err == nil && n_written != nil {
n_written^ += size n_written^ += size
} }
if s.stream_vtable == nil {
return 0, .Empty
}
if s.impl_write_rune != nil {
return s->impl_write_rune(r)
}
if r < utf8.RUNE_SELF { if r < utf8.RUNE_SELF {
err = write_byte(s, byte(r)) err = write_byte(s, byte(r))
if err == nil { if err == nil {
@@ -542,21 +396,15 @@ copy_n :: proc(dst: Writer, src: Reader, n: i64) -> (written: i64, err: Error) {
@(private) @(private)
_copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err: Error) { _copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err: Error) {
if dst.stream_vtable == nil || src.stream_vtable == nil { if dst.procedure == nil || src.procedure == nil {
return 0, .Empty return 0, .Empty
} }
if src.impl_write_to != nil {
return src->impl_write_to(dst)
}
if src.impl_read_from != nil {
return dst->impl_read_from(src)
}
buf := buf buf := buf
if buf == nil { if buf == nil {
DEFAULT_SIZE :: 4 * 1024 DEFAULT_SIZE :: 4 * 1024
size := DEFAULT_SIZE size := DEFAULT_SIZE
if src.stream_vtable == _limited_reader_vtable { if src.procedure == _limited_reader_proc {
l := (^Limited_Reader)(src.stream_data) l := (^Limited_Reader)(src.data)
if i64(size) > l.n { if i64(size) > l.n {
if l.n < 1 { if l.n < 1 {
size = 1 size = 1
+48 -40
View File
@@ -5,33 +5,37 @@ Multi_Reader :: struct {
} }
@(private) @(private)
_multi_reader_vtable := &Stream_VTable{ _multi_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) { if mode == .Query {
mr := (^Multi_Reader)(s.stream_data) return query_utility({.Read, .Query})
for len(mr.readers) > 0 { } else if mode != .Read {
r := mr.readers[0] return 0, .Empty
n, err = read(r, p) }
if err == .EOF { mr := (^Multi_Reader)(stream_data)
ordered_remove(&mr.readers, 0) for len(mr.readers) > 0 {
} r := mr.readers[0]
if n > 0 || err != .EOF { n, err = _i64_err(read(r, p))
if err == .EOF && len(mr.readers) > 0 { if err == .EOF {
// Don't return EOF yet, more readers remain ordered_remove(&mr.readers, 0)
err = nil
}
return
}
} }
return 0, .EOF if n > 0 || err != .EOF {
}, if err == .EOF && len(mr.readers) > 0 {
// Don't return EOF yet, more readers remain
err = nil
}
return
}
}
return 0, .EOF
} }
multi_reader_init :: proc(mr: ^Multi_Reader, readers: ..Reader, allocator := context.allocator) -> (r: Reader) { multi_reader_init :: proc(mr: ^Multi_Reader, readers: ..Reader, allocator := context.allocator) -> (r: Reader) {
all_readers := make([dynamic]Reader, 0, len(readers), allocator) all_readers := make([dynamic]Reader, 0, len(readers), allocator)
for w in readers { for w in readers {
if w.stream_vtable == _multi_reader_vtable { if w.procedure == _multi_reader_proc {
other := (^Multi_Reader)(w.stream_data) other := (^Multi_Reader)(w.data)
append(&all_readers, ..other.readers[:]) append(&all_readers, ..other.readers[:])
} else { } else {
append(&all_readers, w) append(&all_readers, w)
@@ -40,8 +44,8 @@ multi_reader_init :: proc(mr: ^Multi_Reader, readers: ..Reader, allocator := con
mr.readers = all_readers mr.readers = all_readers
r.stream_vtable = _multi_reader_vtable r.procedure = _multi_reader_proc
r.stream_data = mr r.data = mr
return return
} }
@@ -55,38 +59,42 @@ Multi_Writer :: struct {
} }
@(private) @(private)
_multi_writer_vtable := &Stream_VTable{ _multi_writer_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
impl_write = proc(s: Stream, p: []byte) -> (n: int, err: Error) { if mode == .Query {
mw := (^Multi_Writer)(s.stream_data) return query_utility({.Write, .Query})
for w in mw.writers { } else if mode != .Write {
n, err = write(w, p) return 0, .Empty
if err != nil { }
return mw := (^Multi_Writer)(stream_data)
} for w in mw.writers {
if n != len(p) { n, err = _i64_err(write(w, p))
err = .Short_Write if err != nil {
return return
}
} }
if n != i64(len(p)) {
err = .Short_Write
return
}
}
return len(p), nil return i64(len(p)), nil
},
} }
multi_writer_init :: proc(mw: ^Multi_Writer, writers: ..Writer, allocator := context.allocator) -> (out: Writer) { multi_writer_init :: proc(mw: ^Multi_Writer, writers: ..Writer, allocator := context.allocator) -> (out: Writer) {
mw.writers = make([dynamic]Writer, 0, len(writers), allocator) mw.writers = make([dynamic]Writer, 0, len(writers), allocator)
for w in writers { for w in writers {
if w.stream_vtable == _multi_writer_vtable { if w.procedure == _multi_writer_proc {
other := (^Multi_Writer)(w.stream_data) other := (^Multi_Writer)(w.data)
append(&mw.writers, ..other.writers[:]) append(&mw.writers, ..other.writers[:])
} else { } else {
append(&mw.writers, w) append(&mw.writers, w)
} }
} }
out.stream_vtable = _multi_writer_vtable out.procedure = _multi_writer_proc
out.stream_data = mw out.data = mw
return return
} }
+64 -44
View File
@@ -2,6 +2,7 @@ package io
import "core:strconv" import "core:strconv"
import "core:unicode/utf8" import "core:unicode/utf8"
import "core:unicode/utf16"
read_ptr :: proc(r: Reader, p: rawptr, byte_size: int, n_read: ^int = nil) -> (n: int, err: Error) { read_ptr :: proc(r: Reader, p: rawptr, byte_size: int, n_read: ^int = nil) -> (n: int, err: Error) {
return read(r, ([^]byte)(p)[:byte_size], n_read) return read(r, ([^]byte)(p)[:byte_size], n_read)
@@ -146,7 +147,7 @@ write_encoded_rune :: proc(w: Writer, r: rune, write_quote := true, n_written: ^
return return
} }
write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false, n_written: ^int = nil) -> (n: int, err: Error) { write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false, n_written: ^int = nil, for_json := false) -> (n: int, err: Error) {
is_printable :: proc(r: rune) -> bool { is_printable :: proc(r: rune) -> bool {
if r <= 0xff { if r <= 0xff {
switch r { switch r {
@@ -163,7 +164,7 @@ write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false,
defer if n_written != nil { defer if n_written != nil {
n_written^ += n n_written^ += n
} }
if html_safe { if html_safe {
switch r { switch r {
case '<', '>', '&': case '<', '>', '&':
@@ -211,17 +212,29 @@ write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false,
write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
} }
case: case:
write_byte(w, '\\', &n) or_return if for_json {
write_byte(w, 'U', &n) or_return buf: [2]u16
for s := 28; s >= 0; s -= 4 { utf16.encode(buf[:], []rune{c})
write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return for bc in buf {
write_byte(w, '\\', &n) or_return
write_byte(w, 'u', &n) or_return
for s := 12; s >= 0; s -= 4 {
write_byte(w, DIGITS_LOWER[bc>>uint(s) & 0xf], &n) or_return
}
}
} else {
write_byte(w, '\\', &n) or_return
write_byte(w, 'U', &n) or_return
for s := 24; s >= 0; s -= 4 {
write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
}
} }
} }
} }
return return
} }
write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written: ^int = nil) -> (n: int, err: Error) { write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written: ^int = nil, for_json := false) -> (n: int, err: Error) {
defer if n_written != nil { defer if n_written != nil {
n_written^ += n n_written^ += n
} }
@@ -240,7 +253,7 @@ write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written
continue continue
} }
n_wrapper(write_escaped_rune(w, r, quote), &n) or_return n_wrapper(write_escaped_rune(w, r, quote, false, nil, for_json), &n) or_return
} }
write_byte(w, quote, &n) or_return write_byte(w, quote, &n) or_return
@@ -279,17 +292,21 @@ Tee_Reader :: struct {
} }
@(private) @(private)
_tee_reader_vtable := &Stream_VTable{ _tee_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) { t := (^Tee_Reader)(stream_data)
t := (^Tee_Reader)(s.stream_data) #partial switch mode {
n, err = read(t.r, p) case .Read:
n, err = _i64_err(read(t.r, p))
if n > 0 { if n > 0 {
if wn, werr := write(t.w, p[:n]); werr != nil { if wn, werr := write(t.w, p[:n]); werr != nil {
return wn, werr return i64(wn), werr
} }
} }
return return
}, case .Query:
return query_utility({.Read, .Query})
}
return 0, .Empty
} }
// tee_reader_init returns a Reader that writes to 'w' what it reads from 'r' // tee_reader_init returns a Reader that writes to 'w' what it reads from 'r'
@@ -304,8 +321,8 @@ tee_reader_init :: proc(t: ^Tee_Reader, r: Reader, w: Writer, allocator := conte
} }
tee_reader_to_reader :: proc(t: ^Tee_Reader) -> (r: Reader) { tee_reader_to_reader :: proc(t: ^Tee_Reader) -> (r: Reader) {
r.stream_data = t r.data = t
r.stream_vtable = _tee_reader_vtable r.procedure = _tee_reader_proc
return return
} }
@@ -319,9 +336,10 @@ Limited_Reader :: struct {
} }
@(private) @(private)
_limited_reader_vtable := &Stream_VTable{ _limited_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
impl_read = proc(s: Stream, p: []byte) -> (n: int, err: Error) { l := (^Limited_Reader)(stream_data)
l := (^Limited_Reader)(s.stream_data) #partial switch mode {
case .Read:
if l.n <= 0 { if l.n <= 0 {
return 0, .EOF return 0, .EOF
} }
@@ -329,10 +347,13 @@ _limited_reader_vtable := &Stream_VTable{
if i64(len(p)) > l.n { if i64(len(p)) > l.n {
p = p[0:l.n] p = p[0:l.n]
} }
n, err = read(l.r, p) n, err = _i64_err(read(l.r, p))
l.n -= i64(n) l.n -= i64(n)
return return
}, case .Query:
return query_utility({.Read, .Query})
}
return 0, .Empty
} }
limited_reader_init :: proc(l: ^Limited_Reader, r: Reader, n: i64) -> Reader { limited_reader_init :: proc(l: ^Limited_Reader, r: Reader, n: i64) -> Reader {
@@ -342,8 +363,8 @@ limited_reader_init :: proc(l: ^Limited_Reader, r: Reader, n: i64) -> Reader {
} }
limited_reader_to_reader :: proc(l: ^Limited_Reader) -> (r: Reader) { limited_reader_to_reader :: proc(l: ^Limited_Reader) -> (r: Reader) {
r.stream_vtable = _limited_reader_vtable r.procedure = _limited_reader_proc
r.stream_data = l r.data = l
return return
} }
@@ -362,15 +383,16 @@ section_reader_init :: proc(s: ^Section_Reader, r: Reader_At, off: i64, n: i64)
return return
} }
section_reader_to_stream :: proc(s: ^Section_Reader) -> (out: Stream) { section_reader_to_stream :: proc(s: ^Section_Reader) -> (out: Stream) {
out.stream_data = s out.data = s
out.stream_vtable = _section_reader_vtable out.procedure = _section_reader_proc
return return
} }
@(private) @(private)
_section_reader_vtable := &Stream_VTable{ _section_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
impl_read = proc(stream: Stream, p: []byte) -> (n: int, err: Error) { s := (^Section_Reader)(stream_data)
s := (^Section_Reader)(stream.stream_data) #partial switch mode {
case .Read:
if s.off >= s.limit { if s.off >= s.limit {
return 0, .EOF return 0, .EOF
} }
@@ -378,13 +400,11 @@ _section_reader_vtable := &Stream_VTable{
if max := s.limit - s.off; i64(len(p)) > max { if max := s.limit - s.off; i64(len(p)) > max {
p = p[0:max] p = p[0:max]
} }
n, err = read_at(s.r, p, s.off) n, err = _i64_err(read_at(s.r, p, s.off))
s.off += i64(n) s.off += i64(n)
return return
}, case .Read_At:
impl_read_at = proc(stream: Stream, p: []byte, off: i64) -> (n: int, err: Error) { p, off := p, offset
s := (^Section_Reader)(stream.stream_data)
p, off := p, off
if off < 0 || off >= s.limit - s.base { if off < 0 || off >= s.limit - s.base {
return 0, .EOF return 0, .EOF
@@ -392,17 +412,15 @@ _section_reader_vtable := &Stream_VTable{
off += s.base off += s.base
if max := s.limit - off; i64(len(p)) > max { if max := s.limit - off; i64(len(p)) > max {
p = p[0:max] p = p[0:max]
n, err = read_at(s.r, p, off) n, err = _i64_err(read_at(s.r, p, off))
if err == nil { if err == nil {
err = .EOF err = .EOF
} }
return return
} }
return read_at(s.r, p, off) return _i64_err(read_at(s.r, p, off))
},
impl_seek = proc(stream: Stream, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
s := (^Section_Reader)(stream.stream_data)
case .Seek:
offset := offset offset := offset
switch whence { switch whence {
case: case:
@@ -420,10 +438,12 @@ _section_reader_vtable := &Stream_VTable{
s.off = offset s.off = offset
n = offset - s.base n = offset - s.base
return return
}, case .Size:
impl_size = proc(stream: Stream) -> i64 { n = s.limit - s.base
s := (^Section_Reader)(stream.stream_data) return
return s.limit - s.base case .Query:
}, return query_utility({.Read, .Read_At, .Seek, .Size, .Query})
} }
return 0, nil
}
+13 -13
View File
@@ -76,43 +76,43 @@ nil_logger :: proc() -> Logger {
} }
debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) { debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
logf(level=.Debug, fmt_str=fmt_str, args=args, location=location) logf(.Debug, fmt_str, ..args, location=location)
} }
infof :: proc(fmt_str: string, args: ..any, location := #caller_location) { infof :: proc(fmt_str: string, args: ..any, location := #caller_location) {
logf(level=.Info, fmt_str=fmt_str, args=args, location=location) logf(.Info, fmt_str, ..args, location=location)
} }
warnf :: proc(fmt_str: string, args: ..any, location := #caller_location) { warnf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
logf(level=.Warning, fmt_str=fmt_str, args=args, location=location) logf(.Warning, fmt_str, ..args, location=location)
} }
errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) { errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
logf(level=.Error, fmt_str=fmt_str, args=args, location=location) logf(.Error, fmt_str, ..args, location=location)
} }
fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) { fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location) logf(.Fatal, fmt_str, ..args, location=location)
} }
debug :: proc(args: ..any, sep := " ", location := #caller_location) { debug :: proc(args: ..any, sep := " ", location := #caller_location) {
log(level=.Debug, args=args, sep=sep, location=location) log(.Debug, ..args, sep=sep, location=location)
} }
info :: proc(args: ..any, sep := " ", location := #caller_location) { info :: proc(args: ..any, sep := " ", location := #caller_location) {
log(level=.Info, args=args, sep=sep, location=location) log(.Info, ..args, sep=sep, location=location)
} }
warn :: proc(args: ..any, sep := " ", location := #caller_location) { warn :: proc(args: ..any, sep := " ", location := #caller_location) {
log(level=.Warning, args=args, sep=sep, location=location) log(.Warning, ..args, sep=sep, location=location)
} }
error :: proc(args: ..any, sep := " ", location := #caller_location) { error :: proc(args: ..any, sep := " ", location := #caller_location) {
log(level=.Error, args=args, sep=sep, location=location) log(.Error, ..args, sep=sep, location=location)
} }
fatal :: proc(args: ..any, sep := " ", location := #caller_location) { fatal :: proc(args: ..any, sep := " ", location := #caller_location) {
log(level=.Fatal, args=args, sep=sep, location=location) log(.Fatal, ..args, sep=sep, location=location)
} }
panic :: proc(args: ..any, location := #caller_location) -> ! { panic :: proc(args: ..any, location := #caller_location) -> ! {
log(level=.Fatal, args=args, location=location) log(.Fatal, ..args, location=location)
runtime.panic("log.panic", location) runtime.panic("log.panic", location)
} }
panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! { panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! {
logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location) logf(.Fatal, fmt_str, ..args, location=location)
runtime.panic("log.panicf", location) runtime.panic("log.panicf", location)
} }
@@ -127,7 +127,7 @@ log :: proc(level: Level, args: ..any, sep := " ", location := #caller_location)
if level < logger.lowest_level { if level < logger.lowest_level {
return return
} }
str := fmt.tprint(args=args, sep=sep) //NOTE(Hoej): While tprint isn't thread-safe, no logging is. str := fmt.tprint(..args, sep=sep) //NOTE(Hoej): While tprint isn't thread-safe, no logging is.
logger.procedure(logger.data, level, str, logger.options, location) logger.procedure(logger.data, level, str, logger.options, location)
} }
+27 -27
View File
@@ -38,60 +38,60 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode,
switch mode { switch mode {
case .Alloc: case .Alloc:
logf( logf(
level=la.level, la.level,
fmt_str = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)", "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)",
args = {la.prefix, padding, size, alignment}, la.prefix, padding, size, alignment,
location = location, location = location,
) )
case .Alloc_Non_Zeroed: case .Alloc_Non_Zeroed:
logf( logf(
level=la.level, la.level,
fmt_str = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)", "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)",
args = {la.prefix, padding, size, alignment}, la.prefix, padding, size, alignment,
location = location, location = location,
) )
case .Free: case .Free:
if old_size != 0 { if old_size != 0 {
logf( logf(
level=la.level, la.level,
fmt_str = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)", "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)",
args = {la.prefix, padding, old_memory, old_size}, la.prefix, padding, old_memory, old_size,
location = location, location = location,
) )
} else { } else {
logf( logf(
level=la.level, la.level,
fmt_str = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)", "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)",
args = {la.prefix, padding, old_memory}, la.prefix, padding, old_memory,
location = location, location = location,
) )
} }
case .Free_All: case .Free_All:
logf( logf(
level=la.level, la.level,
fmt_str = "%s%s<<< ALLOCATOR(mode=.Free_All)", "%s%s<<< ALLOCATOR(mode=.Free_All)",
args = {la.prefix, padding}, la.prefix, padding,
location = location, location = location,
) )
case .Resize: case .Resize:
logf( logf(
level=la.level, la.level,
fmt_str = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)", "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)",
args = {la.prefix, padding, old_memory, old_size, size, alignment}, la.prefix, padding, old_memory, old_size, size, alignment,
location = location, location = location,
) )
case .Query_Features: case .Query_Features:
logf( logf(
level=la.level, la.level,
fmt_str = "%s%ALLOCATOR(mode=.Query_Features)", "%s%ALLOCATOR(mode=.Query_Features)",
args = {la.prefix, padding}, la.prefix, padding,
location = location, location = location,
) )
case .Query_Info: case .Query_Info:
logf( logf(
level=la.level, la.level,
fmt_str = "%s%ALLOCATOR(mode=.Query_Info)", "%s%ALLOCATOR(mode=.Query_Info)",
args = {la.prefix, padding}, la.prefix, padding,
location = location, location = location,
) )
} }
@@ -103,9 +103,9 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode,
defer la.locked = false defer la.locked = false
if err != nil { if err != nil {
logf( logf(
level=la.level, la.level,
fmt_str = "%s%ALLOCATOR ERROR=%v", "%s%ALLOCATOR ERROR=%v",
args = {la.prefix, padding, error}, la.prefix, padding, error,
location = location, location = location,
) )
} }
+3 -3
View File
@@ -19,7 +19,7 @@ import rnd "core:math/rand"
int_destroy :: proc(integers: ..^Int) { int_destroy :: proc(integers: ..^Int) {
integers := integers integers := integers
for a in &integers { for a in integers {
assert_if_nil(a) assert_if_nil(a)
} }
#force_inline internal_int_destroy(..integers) #force_inline internal_int_destroy(..integers)
@@ -408,7 +408,7 @@ clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context.allocato
args := args args := args
assert_if_nil(..args) assert_if_nil(..args)
for i in &args { for i in args {
#force_inline internal_clear_if_uninitialized_single(i, allocator) or_return #force_inline internal_clear_if_uninitialized_single(i, allocator) or_return
} }
return err return err
@@ -435,7 +435,7 @@ int_init_multi :: proc(integers: ..^Int, allocator := context.allocator) -> (err
assert_if_nil(..integers) assert_if_nil(..integers)
integers := integers integers := integers
for a in &integers { for a in integers {
#force_inline internal_clear(a, true, allocator) or_return #force_inline internal_clear(a, true, allocator) or_return
} }
return nil return nil
+2 -2
View File
@@ -1857,7 +1857,7 @@ internal_root_n :: proc { internal_int_root_n, }
internal_int_destroy :: proc(integers: ..^Int) { internal_int_destroy :: proc(integers: ..^Int) {
integers := integers integers := integers
for a in &integers { for &a in integers {
if internal_int_allocated_cap(a) > 0 { if internal_int_allocated_cap(a) > 0 {
mem.zero_slice(a.digit[:]) mem.zero_slice(a.digit[:])
free(&a.digit[0]) free(&a.digit[0])
@@ -2909,7 +2909,7 @@ internal_int_init_multi :: proc(integers: ..^Int, allocator := context.allocator
context.allocator = allocator context.allocator = allocator
integers := integers integers := integers
for a in &integers { for a in integers {
internal_clear(a) or_return internal_clear(a) or_return
} }
return nil return nil
+1 -1
View File
@@ -429,7 +429,7 @@ internal_int_write_to_ascii_file :: proc(a: ^Int, filename: string, radix := i8(
len = l, len = l,
} }
ok := os.write_entire_file(name=filename, data=data, truncate=true) ok := os.write_entire_file(filename, data, truncate=true)
return nil if ok else .Cannot_Write_File return nil if ok else .Cannot_Write_File
} }
+1 -1
View File
@@ -137,7 +137,7 @@ rat_copy :: proc(dst, src: ^Rat, minimize := false, allocator := context.allocat
internal_rat_destroy :: proc(rationals: ..^Rat) { internal_rat_destroy :: proc(rationals: ..^Rat) {
rationals := rationals rationals := rationals
for z in &rationals { for &z in rationals {
internal_int_destroy(&z.a, &z.b) internal_int_destroy(&z.a, &z.b)
} }
} }
+154 -77
View File
@@ -37,68 +37,96 @@ overflowing_sub :: intrinsics.overflow_sub
overflowing_mul :: intrinsics.overflow_mul overflowing_mul :: intrinsics.overflow_mul
log2 :: proc(x: $T) -> T where intrinsics.type_is_integer(T), intrinsics.type_is_unsigned(T) { @(require_results)
log2 :: proc "contextless" (x: $T) -> T where intrinsics.type_is_integer(T), intrinsics.type_is_unsigned(T) {
return (8*size_of(T)-1) - count_leading_zeros(x) return (8*size_of(T)-1) - count_leading_zeros(x)
} }
rotate_left8 :: proc(x: u8, k: int) -> u8 { @(require_results)
rotate_left8 :: proc "contextless" (x: u8, k: int) -> u8 {
n :: 8 n :: 8
s := uint(k) & (n-1) s := uint(k) & (n-1)
return x <<s | x>>(n-s) return x <<s | x>>(n-s)
} }
rotate_left16 :: proc(x: u16, k: int) -> u16 { @(require_results)
rotate_left16 :: proc "contextless" (x: u16, k: int) -> u16 {
n :: 16 n :: 16
s := uint(k) & (n-1) s := uint(k) & (n-1)
return x <<s | x>>(n-s) return x <<s | x>>(n-s)
} }
rotate_left32 :: proc(x: u32, k: int) -> u32 { @(require_results)
rotate_left32 :: proc "contextless" (x: u32, k: int) -> u32 {
n :: 32 n :: 32
s := uint(k) & (n-1) s := uint(k) & (n-1)
return x <<s | x>>(n-s) return x <<s | x>>(n-s)
} }
rotate_left64 :: proc(x: u64, k: int) -> u64 { @(require_results)
rotate_left64 :: proc "contextless" (x: u64, k: int) -> u64 {
n :: 64 n :: 64
s := uint(k) & (n-1) s := uint(k) & (n-1)
return x <<s | x>>(n-s) return x <<s | x>>(n-s)
} }
rotate_left :: proc(x: uint, k: int) -> uint { @(require_results)
rotate_left :: proc "contextless" (x: uint, k: int) -> uint {
n :: 8*size_of(uint) n :: 8*size_of(uint)
s := uint(k) & (n-1) s := uint(k) & (n-1)
return x <<s | x>>(n-s) return x <<s | x>>(n-s)
} }
from_be_u8 :: proc(i: u8) -> u8 { return i } @(require_results)
from_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } from_be_u8 :: proc "contextless" (i: u8) -> u8 { return i }
from_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } @(require_results)
from_be_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } from_be_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
from_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } @(require_results)
from_be_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
from_be_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
from_be_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
from_le_u8 :: proc(i: u8) -> u8 { return i } @(require_results)
from_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } from_le_u8 :: proc "contextless" (i: u8) -> u8 { return i }
from_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } @(require_results)
from_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } from_le_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
from_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } @(require_results)
from_le_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
from_le_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
from_le_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
to_be_u8 :: proc(i: u8) -> u8 { return i } @(require_results)
to_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } to_be_u8 :: proc "contextless" (i: u8) -> u8 { return i }
to_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } @(require_results)
to_be_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } to_be_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
to_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } @(require_results)
to_be_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
to_be_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
to_be_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
to_le_u8 :: proc(i: u8) -> u8 { return i } @(require_results)
to_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } to_le_u8 :: proc "contextless" (i: u8) -> u8 { return i }
to_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } @(require_results)
to_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } to_le_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
to_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } @(require_results)
to_le_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
to_le_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
to_le_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
len_u8 :: proc(x: u8) -> int { @(require_results)
len_u8 :: proc "contextless" (x: u8) -> int {
return int(len_u8_table[x]) return int(len_u8_table[x])
} }
len_u16 :: proc(x: u16) -> (n: int) { @(require_results)
len_u16 :: proc "contextless" (x: u16) -> (n: int) {
x := x x := x
if x >= 1<<8 { if x >= 1<<8 {
x >>= 8 x >>= 8
@@ -106,7 +134,8 @@ len_u16 :: proc(x: u16) -> (n: int) {
} }
return n + int(len_u8_table[x]) return n + int(len_u8_table[x])
} }
len_u32 :: proc(x: u32) -> (n: int) { @(require_results)
len_u32 :: proc "contextless" (x: u32) -> (n: int) {
x := x x := x
if x >= 1<<16 { if x >= 1<<16 {
x >>= 16 x >>= 16
@@ -118,7 +147,8 @@ len_u32 :: proc(x: u32) -> (n: int) {
} }
return n + int(len_u8_table[x]) return n + int(len_u8_table[x])
} }
len_u64 :: proc(x: u64) -> (n: int) { @(require_results)
len_u64 :: proc "contextless" (x: u64) -> (n: int) {
x := x x := x
if x >= 1<<32 { if x >= 1<<32 {
x >>= 32 x >>= 32
@@ -134,7 +164,8 @@ len_u64 :: proc(x: u64) -> (n: int) {
} }
return n + int(len_u8_table[x]) return n + int(len_u8_table[x])
} }
len_uint :: proc(x: uint) -> (n: int) { @(require_results)
len_uint :: proc "contextless" (x: uint) -> (n: int) {
when size_of(uint) == size_of(u64) { when size_of(uint) == size_of(u64) {
return len_u64(u64(x)) return len_u64(u64(x))
} else { } else {
@@ -146,21 +177,24 @@ len_uint :: proc(x: uint) -> (n: int) {
len :: proc{len_u8, len_u16, len_u32, len_u64, len_uint} len :: proc{len_u8, len_u16, len_u32, len_u64, len_uint}
add_u32 :: proc(x, y, carry: u32) -> (sum, carry_out: u32) { @(require_results)
add_u32 :: proc "contextless" (x, y, carry: u32) -> (sum, carry_out: u32) {
tmp_carry, tmp_carry2: bool tmp_carry, tmp_carry2: bool
sum, tmp_carry = intrinsics.overflow_add(x, y) sum, tmp_carry = intrinsics.overflow_add(x, y)
sum, tmp_carry2 = intrinsics.overflow_add(sum, carry) sum, tmp_carry2 = intrinsics.overflow_add(sum, carry)
carry_out = u32(tmp_carry | tmp_carry2) carry_out = u32(tmp_carry | tmp_carry2)
return return
} }
add_u64 :: proc(x, y, carry: u64) -> (sum, carry_out: u64) { @(require_results)
add_u64 :: proc "contextless" (x, y, carry: u64) -> (sum, carry_out: u64) {
tmp_carry, tmp_carry2: bool tmp_carry, tmp_carry2: bool
sum, tmp_carry = intrinsics.overflow_add(x, y) sum, tmp_carry = intrinsics.overflow_add(x, y)
sum, tmp_carry2 = intrinsics.overflow_add(sum, carry) sum, tmp_carry2 = intrinsics.overflow_add(sum, carry)
carry_out = u64(tmp_carry | tmp_carry2) carry_out = u64(tmp_carry | tmp_carry2)
return return
} }
add_uint :: proc(x, y, carry: uint) -> (sum, carry_out: uint) { @(require_results)
add_uint :: proc "contextless" (x, y, carry: uint) -> (sum, carry_out: uint) {
when size_of(uint) == size_of(u64) { when size_of(uint) == size_of(u64) {
a, b := add_u64(u64(x), u64(y), u64(carry)) a, b := add_u64(u64(x), u64(y), u64(carry))
} else { } else {
@@ -172,21 +206,24 @@ add_uint :: proc(x, y, carry: uint) -> (sum, carry_out: uint) {
add :: proc{add_u32, add_u64, add_uint} add :: proc{add_u32, add_u64, add_uint}
sub_u32 :: proc(x, y, borrow: u32) -> (diff, borrow_out: u32) { @(require_results)
sub_u32 :: proc "contextless" (x, y, borrow: u32) -> (diff, borrow_out: u32) {
tmp_borrow, tmp_borrow2: bool tmp_borrow, tmp_borrow2: bool
diff, tmp_borrow = intrinsics.overflow_sub(x, y) diff, tmp_borrow = intrinsics.overflow_sub(x, y)
diff, tmp_borrow2 = intrinsics.overflow_sub(diff, borrow) diff, tmp_borrow2 = intrinsics.overflow_sub(diff, borrow)
borrow_out = u32(tmp_borrow | tmp_borrow2) borrow_out = u32(tmp_borrow | tmp_borrow2)
return return
} }
sub_u64 :: proc(x, y, borrow: u64) -> (diff, borrow_out: u64) { @(require_results)
sub_u64 :: proc "contextless" (x, y, borrow: u64) -> (diff, borrow_out: u64) {
tmp_borrow, tmp_borrow2: bool tmp_borrow, tmp_borrow2: bool
diff, tmp_borrow = intrinsics.overflow_sub(x, y) diff, tmp_borrow = intrinsics.overflow_sub(x, y)
diff, tmp_borrow2 = intrinsics.overflow_sub(diff, borrow) diff, tmp_borrow2 = intrinsics.overflow_sub(diff, borrow)
borrow_out = u64(tmp_borrow | tmp_borrow2) borrow_out = u64(tmp_borrow | tmp_borrow2)
return return
} }
sub_uint :: proc(x, y, borrow: uint) -> (diff, borrow_out: uint) { @(require_results)
sub_uint :: proc "contextless" (x, y, borrow: uint) -> (diff, borrow_out: uint) {
when size_of(uint) == size_of(u64) { when size_of(uint) == size_of(u64) {
a, b := sub_u64(u64(x), u64(y), u64(borrow)) a, b := sub_u64(u64(x), u64(y), u64(borrow))
} else { } else {
@@ -198,18 +235,21 @@ sub_uint :: proc(x, y, borrow: uint) -> (diff, borrow_out: uint) {
sub :: proc{sub_u32, sub_u64, sub_uint} sub :: proc{sub_u32, sub_u64, sub_uint}
mul_u32 :: proc(x, y: u32) -> (hi, lo: u32) { @(require_results)
mul_u32 :: proc "contextless" (x, y: u32) -> (hi, lo: u32) {
z := u64(x) * u64(y) z := u64(x) * u64(y)
hi, lo = u32(z>>32), u32(z) hi, lo = u32(z>>32), u32(z)
return return
} }
mul_u64 :: proc(x, y: u64) -> (hi, lo: u64) { @(require_results)
mul_u64 :: proc "contextless" (x, y: u64) -> (hi, lo: u64) {
prod_wide := u128(x) * u128(y) prod_wide := u128(x) * u128(y)
hi, lo = u64(prod_wide>>64), u64(prod_wide) hi, lo = u64(prod_wide>>64), u64(prod_wide)
return return
} }
mul_uint :: proc(x, y: uint) -> (hi, lo: uint) { @(require_results)
mul_uint :: proc "contextless" (x, y: uint) -> (hi, lo: uint) {
when size_of(uint) == size_of(u32) { when size_of(uint) == size_of(u32) {
a, b := mul_u32(u32(x), u32(y)) a, b := mul_u32(u32(x), u32(y))
} else { } else {
@@ -222,13 +262,15 @@ mul_uint :: proc(x, y: uint) -> (hi, lo: uint) {
mul :: proc{mul_u32, mul_u64, mul_uint} mul :: proc{mul_u32, mul_u64, mul_uint}
div_u32 :: proc(hi, lo, y: u32) -> (quo, rem: u32) { @(require_results)
div_u32 :: proc "odin" (hi, lo, y: u32) -> (quo, rem: u32) {
assert(y != 0 && y <= hi) assert(y != 0 && y <= hi)
z := u64(hi)<<32 | u64(lo) z := u64(hi)<<32 | u64(lo)
quo, rem = u32(z/u64(y)), u32(z%u64(y)) quo, rem = u32(z/u64(y)), u32(z%u64(y))
return return
} }
div_u64 :: proc(hi, lo, y: u64) -> (quo, rem: u64) { @(require_results)
div_u64 :: proc "odin" (hi, lo, y: u64) -> (quo, rem: u64) {
y := y y := y
two32 :: 1 << 32 two32 :: 1 << 32
mask32 :: two32 - 1 mask32 :: two32 - 1
@@ -273,7 +315,8 @@ div_u64 :: proc(hi, lo, y: u64) -> (quo, rem: u64) {
return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s
} }
div_uint :: proc(hi, lo, y: uint) -> (quo, rem: uint) { @(require_results)
div_uint :: proc "odin" (hi, lo, y: uint) -> (quo, rem: uint) {
when size_of(uint) == size_of(u32) { when size_of(uint) == size_of(u32) {
a, b := div_u32(u32(hi), u32(lo), u32(y)) a, b := div_u32(u32(hi), u32(lo), u32(y))
} else { } else {
@@ -286,16 +329,26 @@ div :: proc{div_u32, div_u64, div_uint}
is_power_of_two_u8 :: proc(i: u8) -> bool { return i > 0 && (i & (i-1)) == 0 } @(require_results)
is_power_of_two_i8 :: proc(i: i8) -> bool { return i > 0 && (i & (i-1)) == 0 } is_power_of_two_u8 :: proc "contextless" (i: u8) -> bool { return i > 0 && (i & (i-1)) == 0 }
is_power_of_two_u16 :: proc(i: u16) -> bool { return i > 0 && (i & (i-1)) == 0 } @(require_results)
is_power_of_two_i16 :: proc(i: i16) -> bool { return i > 0 && (i & (i-1)) == 0 } is_power_of_two_i8 :: proc "contextless" (i: i8) -> bool { return i > 0 && (i & (i-1)) == 0 }
is_power_of_two_u32 :: proc(i: u32) -> bool { return i > 0 && (i & (i-1)) == 0 } @(require_results)
is_power_of_two_i32 :: proc(i: i32) -> bool { return i > 0 && (i & (i-1)) == 0 } is_power_of_two_u16 :: proc "contextless" (i: u16) -> bool { return i > 0 && (i & (i-1)) == 0 }
is_power_of_two_u64 :: proc(i: u64) -> bool { return i > 0 && (i & (i-1)) == 0 } @(require_results)
is_power_of_two_i64 :: proc(i: i64) -> bool { return i > 0 && (i & (i-1)) == 0 } is_power_of_two_i16 :: proc "contextless" (i: i16) -> bool { return i > 0 && (i & (i-1)) == 0 }
is_power_of_two_uint :: proc(i: uint) -> bool { return i > 0 && (i & (i-1)) == 0 } @(require_results)
is_power_of_two_int :: proc(i: int) -> bool { return i > 0 && (i & (i-1)) == 0 } is_power_of_two_u32 :: proc "contextless" (i: u32) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_i32 :: proc "contextless" (i: i32) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_u64 :: proc "contextless" (i: u64) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_i64 :: proc "contextless" (i: i64) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_uint :: proc "contextless" (i: uint) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_int :: proc "contextless" (i: int) -> bool { return i > 0 && (i & (i-1)) == 0 }
is_power_of_two :: proc{ is_power_of_two :: proc{
is_power_of_two_u8, is_power_of_two_i8, is_power_of_two_u8, is_power_of_two_i8,
@@ -320,44 +373,56 @@ len_u8_table := [256]u8{
} }
bitfield_extract_u8 :: proc(value: u8, offset, bits: uint) -> u8 { return (value >> offset) & u8(1<<bits - 1) } @(require_results)
bitfield_extract_u16 :: proc(value: u16, offset, bits: uint) -> u16 { return (value >> offset) & u16(1<<bits - 1) } bitfield_extract_u8 :: proc "contextless" (value: u8, offset, bits: uint) -> u8 { return (value >> offset) & u8(1<<bits - 1) }
bitfield_extract_u32 :: proc(value: u32, offset, bits: uint) -> u32 { return (value >> offset) & u32(1<<bits - 1) } @(require_results)
bitfield_extract_u64 :: proc(value: u64, offset, bits: uint) -> u64 { return (value >> offset) & u64(1<<bits - 1) } bitfield_extract_u16 :: proc "contextless" (value: u16, offset, bits: uint) -> u16 { return (value >> offset) & u16(1<<bits - 1) }
bitfield_extract_u128 :: proc(value: u128, offset, bits: uint) -> u128 { return (value >> offset) & u128(1<<bits - 1) } @(require_results)
bitfield_extract_uint :: proc(value: uint, offset, bits: uint) -> uint { return (value >> offset) & uint(1<<bits - 1) } bitfield_extract_u32 :: proc "contextless" (value: u32, offset, bits: uint) -> u32 { return (value >> offset) & u32(1<<bits - 1) }
@(require_results)
bitfield_extract_u64 :: proc "contextless" (value: u64, offset, bits: uint) -> u64 { return (value >> offset) & u64(1<<bits - 1) }
@(require_results)
bitfield_extract_u128 :: proc "contextless" (value: u128, offset, bits: uint) -> u128 { return (value >> offset) & u128(1<<bits - 1) }
@(require_results)
bitfield_extract_uint :: proc "contextless" (value: uint, offset, bits: uint) -> uint { return (value >> offset) & uint(1<<bits - 1) }
bitfield_extract_i8 :: proc(value: i8, offset, bits: uint) -> i8 { @(require_results)
bitfield_extract_i8 :: proc "contextless" (value: i8, offset, bits: uint) -> i8 {
v := (u8(value) >> offset) & u8(1<<bits - 1) v := (u8(value) >> offset) & u8(1<<bits - 1)
m := u8(1<<(bits-1)) m := u8(1<<(bits-1))
r := (v~m) - m r := (v~m) - m
return i8(r) return i8(r)
} }
bitfield_extract_i16 :: proc(value: i16, offset, bits: uint) -> i16 { @(require_results)
bitfield_extract_i16 :: proc "contextless" (value: i16, offset, bits: uint) -> i16 {
v := (u16(value) >> offset) & u16(1<<bits - 1) v := (u16(value) >> offset) & u16(1<<bits - 1)
m := u16(1<<(bits-1)) m := u16(1<<(bits-1))
r := (v~m) - m r := (v~m) - m
return i16(r) return i16(r)
} }
bitfield_extract_i32 :: proc(value: i32, offset, bits: uint) -> i32 { @(require_results)
bitfield_extract_i32 :: proc "contextless" (value: i32, offset, bits: uint) -> i32 {
v := (u32(value) >> offset) & u32(1<<bits - 1) v := (u32(value) >> offset) & u32(1<<bits - 1)
m := u32(1<<(bits-1)) m := u32(1<<(bits-1))
r := (v~m) - m r := (v~m) - m
return i32(r) return i32(r)
} }
bitfield_extract_i64 :: proc(value: i64, offset, bits: uint) -> i64 { @(require_results)
bitfield_extract_i64 :: proc "contextless" (value: i64, offset, bits: uint) -> i64 {
v := (u64(value) >> offset) & u64(1<<bits - 1) v := (u64(value) >> offset) & u64(1<<bits - 1)
m := u64(1<<(bits-1)) m := u64(1<<(bits-1))
r := (v~m) - m r := (v~m) - m
return i64(r) return i64(r)
} }
bitfield_extract_i128 :: proc(value: i128, offset, bits: uint) -> i128 { @(require_results)
bitfield_extract_i128 :: proc "contextless" (value: i128, offset, bits: uint) -> i128 {
v := (u128(value) >> offset) & u128(1<<bits - 1) v := (u128(value) >> offset) & u128(1<<bits - 1)
m := u128(1<<(bits-1)) m := u128(1<<(bits-1))
r := (v~m) - m r := (v~m) - m
return i128(r) return i128(r)
} }
bitfield_extract_int :: proc(value: int, offset, bits: uint) -> int { @(require_results)
bitfield_extract_int :: proc "contextless" (value: int, offset, bits: uint) -> int {
v := (uint(value) >> offset) & uint(1<<bits - 1) v := (uint(value) >> offset) & uint(1<<bits - 1)
m := uint(1<<(bits-1)) m := uint(1<<(bits-1))
r := (v~m) - m r := (v~m) - m
@@ -381,52 +446,64 @@ bitfield_extract :: proc{
} }
bitfield_insert_u8 :: proc(base, insert: u8, offset, bits: uint) -> u8 { @(require_results)
bitfield_insert_u8 :: proc "contextless" (base, insert: u8, offset, bits: uint) -> u8 {
mask := u8(1<<bits - 1) mask := u8(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_u16 :: proc(base, insert: u16, offset, bits: uint) -> u16 { @(require_results)
bitfield_insert_u16 :: proc "contextless" (base, insert: u16, offset, bits: uint) -> u16 {
mask := u16(1<<bits - 1) mask := u16(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_u32 :: proc(base, insert: u32, offset, bits: uint) -> u32 { @(require_results)
bitfield_insert_u32 :: proc "contextless" (base, insert: u32, offset, bits: uint) -> u32 {
mask := u32(1<<bits - 1) mask := u32(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_u64 :: proc(base, insert: u64, offset, bits: uint) -> u64 { @(require_results)
bitfield_insert_u64 :: proc "contextless" (base, insert: u64, offset, bits: uint) -> u64 {
mask := u64(1<<bits - 1) mask := u64(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_u128 :: proc(base, insert: u128, offset, bits: uint) -> u128 { @(require_results)
bitfield_insert_u128 :: proc "contextless" (base, insert: u128, offset, bits: uint) -> u128 {
mask := u128(1<<bits - 1) mask := u128(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_uint :: proc(base, insert: uint, offset, bits: uint) -> uint { @(require_results)
bitfield_insert_uint :: proc "contextless" (base, insert: uint, offset, bits: uint) -> uint {
mask := uint(1<<bits - 1) mask := uint(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_i8 :: proc(base, insert: i8, offset, bits: uint) -> i8 { @(require_results)
bitfield_insert_i8 :: proc "contextless" (base, insert: i8, offset, bits: uint) -> i8 {
mask := i8(1<<bits - 1) mask := i8(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_i16 :: proc(base, insert: i16, offset, bits: uint) -> i16 { @(require_results)
bitfield_insert_i16 :: proc "contextless" (base, insert: i16, offset, bits: uint) -> i16 {
mask := i16(1<<bits - 1) mask := i16(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_i32 :: proc(base, insert: i32, offset, bits: uint) -> i32 { @(require_results)
bitfield_insert_i32 :: proc "contextless" (base, insert: i32, offset, bits: uint) -> i32 {
mask := i32(1<<bits - 1) mask := i32(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_i64 :: proc(base, insert: i64, offset, bits: uint) -> i64 { @(require_results)
bitfield_insert_i64 :: proc "contextless" (base, insert: i64, offset, bits: uint) -> i64 {
mask := i64(1<<bits - 1) mask := i64(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_i128 :: proc(base, insert: i128, offset, bits: uint) -> i128 { @(require_results)
bitfield_insert_i128 :: proc "contextless" (base, insert: i128, offset, bits: uint) -> i128 {
mask := i128(1<<bits - 1) mask := i128(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
bitfield_insert_int :: proc(base, insert: int, offset, bits: uint) -> int { @(require_results)
bitfield_insert_int :: proc "contextless" (base, insert: int, offset, bits: uint) -> int {
mask := int(1<<bits - 1) mask := int(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset) return (base &~ (mask<<offset)) | ((insert&mask) << offset)
} }
+513
View File
@@ -0,0 +1,513 @@
package math_cmplx
import "core:builtin"
import "core:math"
// The original C code, the long comment, and the constants
// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
// The go code is a simplified version of the original C.
//
// Cephes Math Library Release 2.8: June, 2000
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
//
// The readme file at http://netlib.sandia.gov/cephes/ says:
// Some software in this archive may be from the book _Methods and
// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
// International, 1989) or from the Cephes Mathematical Library, a
// commercial product. In either event, it is copyrighted by the author.
// What you see here may be used freely but it comes with no support or
// guarantee.
//
// The two known misprints in the book are repaired here in the
// source listings for the gamma function and the incomplete beta
// integral.
//
// Stephen L. Moshier
// moshier@na-net.ornl.gov
abs :: builtin.abs
conj :: builtin.conj
real :: builtin.real
imag :: builtin.imag
jmag :: builtin.jmag
kmag :: builtin.kmag
sin :: proc{
sin_complex128,
}
cos :: proc{
cos_complex128,
}
tan :: proc{
tan_complex128,
}
cot :: proc{
cot_complex128,
}
sinh :: proc{
sinh_complex128,
}
cosh :: proc{
cosh_complex128,
}
tanh :: proc{
tanh_complex128,
}
// sqrt returns the square root of x.
// The result r is chosen so that real(r) 0 and imag(r) has the same sign as imag(x).
sqrt :: proc{
sqrt_complex32,
sqrt_complex64,
sqrt_complex128,
}
ln :: proc{
ln_complex32,
ln_complex64,
ln_complex128,
}
log10 :: proc{
log10_complex32,
log10_complex64,
log10_complex128,
}
exp :: proc{
exp_complex32,
exp_complex64,
exp_complex128,
}
pow :: proc{
pow_complex32,
pow_complex64,
pow_complex128,
}
phase :: proc{
phase_complex32,
phase_complex64,
phase_complex128,
}
polar :: proc{
polar_complex32,
polar_complex64,
polar_complex128,
}
is_inf :: proc{
is_inf_complex32,
is_inf_complex64,
is_inf_complex128,
}
is_nan :: proc{
is_nan_complex32,
is_nan_complex64,
is_nan_complex128,
}
// sqrt_complex32 returns the square root of x.
// The result r is chosen so that real(r) 0 and imag(r) has the same sign as imag(x).
sqrt_complex32 :: proc "contextless" (x: complex32) -> complex32 {
return complex32(sqrt_complex128(complex128(x)))
}
// sqrt_complex64 returns the square root of x.
// The result r is chosen so that real(r) 0 and imag(r) has the same sign as imag(x).
sqrt_complex64 :: proc "contextless" (x: complex64) -> complex64 {
return complex64(sqrt_complex128(complex128(x)))
}
// sqrt_complex128 returns the square root of x.
// The result r is chosen so that real(r) 0 and imag(r) has the same sign as imag(x).
sqrt_complex128 :: proc "contextless" (x: complex128) -> complex128 {
// The original C code, the long comment, and the constants
// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
// The go code is a simplified version of the original C.
//
// Cephes Math Library Release 2.8: June, 2000
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
//
// The readme file at http://netlib.sandia.gov/cephes/ says:
// Some software in this archive may be from the book _Methods and
// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
// International, 1989) or from the Cephes Mathematical Library, a
// commercial product. In either event, it is copyrighted by the author.
// What you see here may be used freely but it comes with no support or
// guarantee.
//
// The two known misprints in the book are repaired here in the
// source listings for the gamma function and the incomplete beta
// integral.
//
// Stephen L. Moshier
// moshier@na-net.ornl.gov
// Complex square root
//
// DESCRIPTION:
//
// If z = x + iy, r = |z|, then
//
// 1/2
// Re w = [ (r + x)/2 ] ,
//
// 1/2
// Im w = [ (r - x)/2 ] .
//
// Cancellation error in r-x or r+x is avoided by using the
// identity 2 Re w Im w = y.
//
// Note that -w is also a square root of z. The root chosen
// is always in the right half plane and Im w has the same sign as y.
//
// ACCURACY:
//
// Relative error:
// arithmetic domain # trials peak rms
// DEC -10,+10 25000 3.2e-17 9.6e-18
// IEEE -10,+10 1,000,000 2.9e-16 6.1e-17
if imag(x) == 0 {
// Ensure that imag(r) has the same sign as imag(x) for imag(x) == signed zero.
if real(x) == 0 {
return complex(0, imag(x))
}
if real(x) < 0 {
return complex(0, math.copy_sign(math.sqrt(-real(x)), imag(x)))
}
return complex(math.sqrt(real(x)), imag(x))
} else if math.is_inf(imag(x), 0) {
return complex(math.inf_f64(1.0), imag(x))
}
if real(x) == 0 {
if imag(x) < 0 {
r := math.sqrt(-0.5 * imag(x))
return complex(r, -r)
}
r := math.sqrt(0.5 * imag(x))
return complex(r, r)
}
a := real(x)
b := imag(x)
scale: f64
// Rescale to avoid internal overflow or underflow.
if abs(a) > 4 || abs(b) > 4 {
a *= 0.25
b *= 0.25
scale = 2
} else {
a *= 1.8014398509481984e16 // 2**54
b *= 1.8014398509481984e16
scale = 7.450580596923828125e-9 // 2**-27
}
r := math.hypot(a, b)
t: f64
if a > 0 {
t = math.sqrt(0.5*r + 0.5*a)
r = scale * abs((0.5*b)/t)
t *= scale
} else {
r = math.sqrt(0.5*r - 0.5*a)
t = scale * abs((0.5*b)/r)
r *= scale
}
if b < 0 {
return complex(t, -r)
}
return complex(t, r)
}
ln_complex32 :: proc "contextless" (x: complex32) -> complex32 {
return complex(math.ln(abs(x)), phase(x))
}
ln_complex64 :: proc "contextless" (x: complex64) -> complex64 {
return complex(math.ln(abs(x)), phase(x))
}
ln_complex128 :: proc "contextless" (x: complex128) -> complex128 {
return complex(math.ln(abs(x)), phase(x))
}
exp_complex32 :: proc "contextless" (x: complex32) -> complex32 {
switch re, im := real(x), imag(x); {
case math.is_inf(re, 0):
switch {
case re > 0 && im == 0:
return x
case math.is_inf(im, 0) || math.is_nan(im):
if re < 0 {
return complex(0, math.copy_sign(0, im))
} else {
return complex(math.inf_f64(1.0), math.nan_f64())
}
}
case math.is_nan(re):
if im == 0 {
return complex(math.nan_f16(), im)
}
}
r := math.exp(real(x))
s, c := math.sincos(imag(x))
return complex(r*c, r*s)
}
exp_complex64 :: proc "contextless" (x: complex64) -> complex64 {
switch re, im := real(x), imag(x); {
case math.is_inf(re, 0):
switch {
case re > 0 && im == 0:
return x
case math.is_inf(im, 0) || math.is_nan(im):
if re < 0 {
return complex(0, math.copy_sign(0, im))
} else {
return complex(math.inf_f64(1.0), math.nan_f64())
}
}
case math.is_nan(re):
if im == 0 {
return complex(math.nan_f32(), im)
}
}
r := math.exp(real(x))
s, c := math.sincos(imag(x))
return complex(r*c, r*s)
}
exp_complex128 :: proc "contextless" (x: complex128) -> complex128 {
switch re, im := real(x), imag(x); {
case math.is_inf(re, 0):
switch {
case re > 0 && im == 0:
return x
case math.is_inf(im, 0) || math.is_nan(im):
if re < 0 {
return complex(0, math.copy_sign(0, im))
} else {
return complex(math.inf_f64(1.0), math.nan_f64())
}
}
case math.is_nan(re):
if im == 0 {
return complex(math.nan_f64(), im)
}
}
r := math.exp(real(x))
s, c := math.sincos(imag(x))
return complex(r*c, r*s)
}
pow_complex32 :: proc "contextless" (x, y: complex32) -> complex32 {
if x == 0 { // Guaranteed also true for x == -0.
if is_nan(y) {
return nan_complex32()
}
r, i := real(y), imag(y)
switch {
case r == 0:
return 1
case r < 0:
if i == 0 {
return complex(math.inf_f16(1), 0)
}
return inf_complex32()
case r > 0:
return 0
}
unreachable()
}
modulus := abs(x)
if modulus == 0 {
return complex(0, 0)
}
r := math.pow(modulus, real(y))
arg := phase(x)
theta := real(y) * arg
if imag(y) != 0 {
r *= math.exp(-imag(y) * arg)
theta += imag(y) * math.ln(modulus)
}
s, c := math.sincos(theta)
return complex(r*c, r*s)
}
pow_complex64 :: proc "contextless" (x, y: complex64) -> complex64 {
if x == 0 { // Guaranteed also true for x == -0.
if is_nan(y) {
return nan_complex64()
}
r, i := real(y), imag(y)
switch {
case r == 0:
return 1
case r < 0:
if i == 0 {
return complex(math.inf_f32(1), 0)
}
return inf_complex64()
case r > 0:
return 0
}
unreachable()
}
modulus := abs(x)
if modulus == 0 {
return complex(0, 0)
}
r := math.pow(modulus, real(y))
arg := phase(x)
theta := real(y) * arg
if imag(y) != 0 {
r *= math.exp(-imag(y) * arg)
theta += imag(y) * math.ln(modulus)
}
s, c := math.sincos(theta)
return complex(r*c, r*s)
}
pow_complex128 :: proc "contextless" (x, y: complex128) -> complex128 {
if x == 0 { // Guaranteed also true for x == -0.
if is_nan(y) {
return nan_complex128()
}
r, i := real(y), imag(y)
switch {
case r == 0:
return 1
case r < 0:
if i == 0 {
return complex(math.inf_f64(1), 0)
}
return inf_complex128()
case r > 0:
return 0
}
unreachable()
}
modulus := abs(x)
if modulus == 0 {
return complex(0, 0)
}
r := math.pow(modulus, real(y))
arg := phase(x)
theta := real(y) * arg
if imag(y) != 0 {
r *= math.exp(-imag(y) * arg)
theta += imag(y) * math.ln(modulus)
}
s, c := math.sincos(theta)
return complex(r*c, r*s)
}
log10_complex32 :: proc "contextless" (x: complex32) -> complex32 {
return math.LN10*ln(x)
}
log10_complex64 :: proc "contextless" (x: complex64) -> complex64 {
return math.LN10*ln(x)
}
log10_complex128 :: proc "contextless" (x: complex128) -> complex128 {
return math.LN10*ln(x)
}
phase_complex32 :: proc "contextless" (x: complex32) -> f16 {
return math.atan2(imag(x), real(x))
}
phase_complex64 :: proc "contextless" (x: complex64) -> f32 {
return math.atan2(imag(x), real(x))
}
phase_complex128 :: proc "contextless" (x: complex128) -> f64 {
return math.atan2(imag(x), real(x))
}
rect_complex32 :: proc "contextless" (r, θ: f16) -> complex32 {
s, c := math.sincos(θ)
return complex(r*c, r*s)
}
rect_complex64 :: proc "contextless" (r, θ: f32) -> complex64 {
s, c := math.sincos(θ)
return complex(r*c, r*s)
}
rect_complex128 :: proc "contextless" (r, θ: f64) -> complex128 {
s, c := math.sincos(θ)
return complex(r*c, r*s)
}
polar_complex32 :: proc "contextless" (x: complex32) -> (r, θ: f16) {
return abs(x), phase(x)
}
polar_complex64 :: proc "contextless" (x: complex64) -> (r, θ: f32) {
return abs(x), phase(x)
}
polar_complex128 :: proc "contextless" (x: complex128) -> (r, θ: f64) {
return abs(x), phase(x)
}
nan_complex32 :: proc "contextless" () -> complex32 {
return complex(math.nan_f16(), math.nan_f16())
}
nan_complex64 :: proc "contextless" () -> complex64 {
return complex(math.nan_f32(), math.nan_f32())
}
nan_complex128 :: proc "contextless" () -> complex128 {
return complex(math.nan_f64(), math.nan_f64())
}
inf_complex32 :: proc "contextless" () -> complex32 {
inf := math.inf_f16(1)
return complex(inf, inf)
}
inf_complex64 :: proc "contextless" () -> complex64 {
inf := math.inf_f32(1)
return complex(inf, inf)
}
inf_complex128 :: proc "contextless" () -> complex128 {
inf := math.inf_f64(1)
return complex(inf, inf)
}
is_inf_complex32 :: proc "contextless" (x: complex32) -> bool {
return math.is_inf(real(x), 0) || math.is_inf(imag(x), 0)
}
is_inf_complex64 :: proc "contextless" (x: complex64) -> bool {
return math.is_inf(real(x), 0) || math.is_inf(imag(x), 0)
}
is_inf_complex128 :: proc "contextless" (x: complex128) -> bool {
return math.is_inf(real(x), 0) || math.is_inf(imag(x), 0)
}
is_nan_complex32 :: proc "contextless" (x: complex32) -> bool {
if math.is_inf(real(x), 0) || math.is_inf(imag(x), 0) {
return false
}
return math.is_nan(real(x)) || math.is_nan(imag(x))
}
is_nan_complex64 :: proc "contextless" (x: complex64) -> bool {
if math.is_inf(real(x), 0) || math.is_inf(imag(x), 0) {
return false
}
return math.is_nan(real(x)) || math.is_nan(imag(x))
}
is_nan_complex128 :: proc "contextless" (x: complex128) -> bool {
if math.is_inf(real(x), 0) || math.is_inf(imag(x), 0) {
return false
}
return math.is_nan(real(x)) || math.is_nan(imag(x))
}
+273
View File
@@ -0,0 +1,273 @@
package math_cmplx
import "core:builtin"
import "core:math"
// The original C code, the long comment, and the constants
// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
// The go code is a simplified version of the original C.
//
// Cephes Math Library Release 2.8: June, 2000
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
//
// The readme file at http://netlib.sandia.gov/cephes/ says:
// Some software in this archive may be from the book _Methods and
// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
// International, 1989) or from the Cephes Mathematical Library, a
// commercial product. In either event, it is copyrighted by the author.
// What you see here may be used freely but it comes with no support or
// guarantee.
//
// The two known misprints in the book are repaired here in the
// source listings for the gamma function and the incomplete beta
// integral.
//
// Stephen L. Moshier
// moshier@na-net.ornl.gov
acos :: proc{
acos_complex32,
acos_complex64,
acos_complex128,
}
acosh :: proc{
acosh_complex32,
acosh_complex64,
acosh_complex128,
}
asin :: proc{
asin_complex32,
asin_complex64,
asin_complex128,
}
asinh :: proc{
asinh_complex32,
asinh_complex64,
asinh_complex128,
}
atan :: proc{
atan_complex32,
atan_complex64,
atan_complex128,
}
atanh :: proc{
atanh_complex32,
atanh_complex64,
atanh_complex128,
}
acos_complex32 :: proc "contextless" (x: complex32) -> complex32 {
w := asin(x)
return complex(math.PI/2 - real(w), -imag(w))
}
acos_complex64 :: proc "contextless" (x: complex64) -> complex64 {
w := asin(x)
return complex(math.PI/2 - real(w), -imag(w))
}
acos_complex128 :: proc "contextless" (x: complex128) -> complex128 {
w := asin(x)
return complex(math.PI/2 - real(w), -imag(w))
}
acosh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
if x == 0 {
return complex(0, math.copy_sign(math.PI/2, imag(x)))
}
w := acos(x)
if imag(w) <= 0 {
return complex(-imag(w), real(w))
}
return complex(imag(w), -real(w))
}
acosh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
if x == 0 {
return complex(0, math.copy_sign(math.PI/2, imag(x)))
}
w := acos(x)
if imag(w) <= 0 {
return complex(-imag(w), real(w))
}
return complex(imag(w), -real(w))
}
acosh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
if x == 0 {
return complex(0, math.copy_sign(math.PI/2, imag(x)))
}
w := acos(x)
if imag(w) <= 0 {
return complex(-imag(w), real(w))
}
return complex(imag(w), -real(w))
}
asin_complex32 :: proc "contextless" (x: complex32) -> complex32 {
return complex32(asin_complex128(complex128(x)))
}
asin_complex64 :: proc "contextless" (x: complex64) -> complex64 {
return complex64(asin_complex128(complex128(x)))
}
asin_complex128 :: proc "contextless" (x: complex128) -> complex128 {
switch re, im := real(x), imag(x); {
case im == 0 && abs(re) <= 1:
return complex(math.asin(re), im)
case re == 0 && abs(im) <= 1:
return complex(re, math.asinh(im))
case math.is_nan(im):
switch {
case re == 0:
return complex(re, math.nan_f64())
case math.is_inf(re, 0):
return complex(math.nan_f64(), re)
case:
return nan_complex128()
}
case math.is_inf(im, 0):
switch {
case math.is_nan(re):
return x
case math.is_inf(re, 0):
return complex(math.copy_sign(math.PI/4, re), im)
case:
return complex(math.copy_sign(0, re), im)
}
case math.is_inf(re, 0):
return complex(math.copy_sign(math.PI/2, re), math.copy_sign(re, im))
}
ct := complex(-imag(x), real(x)) // i * x
xx := x * x
x1 := complex(1-real(xx), -imag(xx)) // 1 - x*x
x2 := sqrt(x1) // x2 = sqrt(1 - x*x)
w := ln(ct + x2)
return complex(imag(w), -real(w)) // -i * w
}
asinh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
return complex32(asinh_complex128(complex128(x)))
}
asinh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
return complex64(asinh_complex128(complex128(x)))
}
asinh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
switch re, im := real(x), imag(x); {
case im == 0 && abs(re) <= 1:
return complex(math.asinh(re), im)
case re == 0 && abs(im) <= 1:
return complex(re, math.asin(im))
case math.is_inf(re, 0):
switch {
case math.is_inf(im, 0):
return complex(re, math.copy_sign(math.PI/4, im))
case math.is_nan(im):
return x
case:
return complex(re, math.copy_sign(0.0, im))
}
case math.is_nan(re):
switch {
case im == 0:
return x
case math.is_inf(im, 0):
return complex(im, re)
case:
return nan_complex128()
}
case math.is_inf(im, 0):
return complex(math.copy_sign(im, re), math.copy_sign(math.PI/2, im))
}
xx := x * x
x1 := complex(1+real(xx), imag(xx)) // 1 + x*x
return ln(x + sqrt(x1)) // log(x + sqrt(1 + x*x))
}
atan_complex32 :: proc "contextless" (x: complex32) -> complex32 {
return complex32(atan_complex128(complex128(x)))
}
atan_complex64 :: proc "contextless" (x: complex64) -> complex64 {
return complex64(atan_complex128(complex128(x)))
}
atan_complex128 :: proc "contextless" (x: complex128) -> complex128 {
// Complex circular arc tangent
//
// DESCRIPTION:
//
// If
// z = x + iy,
//
// then
// 1 ( 2x )
// Re w = - arctan(-----------) + k PI
// 2 ( 2 2)
// (1 - x - y )
//
// ( 2 2)
// 1 (x + (y+1) )
// Im w = - log(------------)
// 4 ( 2 2)
// (x + (y-1) )
//
// Where k is an arbitrary integer.
//
// catan(z) = -i catanh(iz).
//
// ACCURACY:
//
// Relative error:
// arithmetic domain # trials peak rms
// DEC -10,+10 5900 1.3e-16 7.8e-18
// IEEE -10,+10 30000 2.3e-15 8.5e-17
// The check catan( ctan(z) ) = z, with |x| and |y| < PI/2,
// had peak relative error 1.5e-16, rms relative error
// 2.9e-17. See also clog().
switch re, im := real(x), imag(x); {
case im == 0:
return complex(math.atan(re), im)
case re == 0 && abs(im) <= 1:
return complex(re, math.atanh(im))
case math.is_inf(im, 0) || math.is_inf(re, 0):
if math.is_nan(re) {
return complex(math.nan_f64(), math.copy_sign(0, im))
}
return complex(math.copy_sign(math.PI/2, re), math.copy_sign(0, im))
case math.is_nan(re) || math.is_nan(im):
return nan_complex128()
}
x2 := real(x) * real(x)
a := 1 - x2 - imag(x)*imag(x)
if a == 0 {
return nan_complex128()
}
t := 0.5 * math.atan2(2*real(x), a)
w := _reduce_pi_f64(t)
t = imag(x) - 1
b := x2 + t*t
if b == 0 {
return nan_complex128()
}
t = imag(x) + 1
c := (x2 + t*t) / b
return complex(w, 0.25*math.ln(c))
}
atanh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
z := complex(-imag(x), real(x)) // z = i * x
z = atan(z)
return complex(imag(z), -real(z)) // z = -i * z
}
atanh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
z := complex(-imag(x), real(x)) // z = i * x
z = atan(z)
return complex(imag(z), -real(z)) // z = -i * z
}
atanh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
z := complex(-imag(x), real(x)) // z = i * x
z = atan(z)
return complex(imag(z), -real(z)) // z = -i * z
}
+409
View File
@@ -0,0 +1,409 @@
package math_cmplx
import "core:math"
import "core:math/bits"
// The original C code, the long comment, and the constants
// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
// The go code is a simplified version of the original C.
//
// Cephes Math Library Release 2.8: June, 2000
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
//
// The readme file at http://netlib.sandia.gov/cephes/ says:
// Some software in this archive may be from the book _Methods and
// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
// International, 1989) or from the Cephes Mathematical Library, a
// commercial product. In either event, it is copyrighted by the author.
// What you see here may be used freely but it comes with no support or
// guarantee.
//
// The two known misprints in the book are repaired here in the
// source listings for the gamma function and the incomplete beta
// integral.
//
// Stephen L. Moshier
// moshier@na-net.ornl.gov
sin_complex128 :: proc "contextless" (x: complex128) -> complex128 {
// Complex circular sine
//
// DESCRIPTION:
//
// If
// z = x + iy,
//
// then
//
// w = sin x cosh y + i cos x sinh y.
//
// csin(z) = -i csinh(iz).
//
// ACCURACY:
//
// Relative error:
// arithmetic domain # trials peak rms
// DEC -10,+10 8400 5.3e-17 1.3e-17
// IEEE -10,+10 30000 3.8e-16 1.0e-16
// Also tested by csin(casin(z)) = z.
switch re, im := real(x), imag(x); {
case im == 0 && (math.is_inf(re, 0) || math.is_nan(re)):
return complex(math.nan_f64(), im)
case math.is_inf(im, 0):
switch {
case re == 0:
return x
case math.is_inf(re, 0) || math.is_nan(re):
return complex(math.nan_f64(), im)
}
case re == 0 && math.is_nan(im):
return x
}
s, c := math.sincos(real(x))
sh, ch := _sinhcosh_f64(imag(x))
return complex(s*ch, c*sh)
}
cos_complex128 :: proc "contextless" (x: complex128) -> complex128 {
// Complex circular cosine
//
// DESCRIPTION:
//
// If
// z = x + iy,
//
// then
//
// w = cos x cosh y - i sin x sinh y.
//
// ACCURACY:
//
// Relative error:
// arithmetic domain # trials peak rms
// DEC -10,+10 8400 4.5e-17 1.3e-17
// IEEE -10,+10 30000 3.8e-16 1.0e-16
switch re, im := real(x), imag(x); {
case im == 0 && (math.is_inf(re, 0) || math.is_nan(re)):
return complex(math.nan_f64(), -im*math.copy_sign(0, re))
case math.is_inf(im, 0):
switch {
case re == 0:
return complex(math.inf_f64(1), -re*math.copy_sign(0, im))
case math.is_inf(re, 0) || math.is_nan(re):
return complex(math.inf_f64(1), math.nan_f64())
}
case re == 0 && math.is_nan(im):
return complex(math.nan_f64(), 0)
}
s, c := math.sincos(real(x))
sh, ch := _sinhcosh_f64(imag(x))
return complex(c*ch, -s*sh)
}
sinh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
// Complex hyperbolic sine
//
// DESCRIPTION:
//
// csinh z = (cexp(z) - cexp(-z))/2
// = sinh x * cos y + i cosh x * sin y .
//
// ACCURACY:
//
// Relative error:
// arithmetic domain # trials peak rms
// IEEE -10,+10 30000 3.1e-16 8.2e-17
switch re, im := real(x), imag(x); {
case re == 0 && (math.is_inf(im, 0) || math.is_nan(im)):
return complex(re, math.nan_f64())
case math.is_inf(re, 0):
switch {
case im == 0:
return complex(re, im)
case math.is_inf(im, 0) || math.is_nan(im):
return complex(re, math.nan_f64())
}
case im == 0 && math.is_nan(re):
return complex(math.nan_f64(), im)
}
s, c := math.sincos(imag(x))
sh, ch := _sinhcosh_f64(real(x))
return complex(c*sh, s*ch)
}
cosh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
// Complex hyperbolic cosine
//
// DESCRIPTION:
//
// ccosh(z) = cosh x cos y + i sinh x sin y .
//
// ACCURACY:
//
// Relative error:
// arithmetic domain # trials peak rms
// IEEE -10,+10 30000 2.9e-16 8.1e-17
switch re, im := real(x), imag(x); {
case re == 0 && (math.is_inf(im, 0) || math.is_nan(im)):
return complex(math.nan_f64(), re*math.copy_sign(0, im))
case math.is_inf(re, 0):
switch {
case im == 0:
return complex(math.inf_f64(1), im*math.copy_sign(0, re))
case math.is_inf(im, 0) || math.is_nan(im):
return complex(math.inf_f64(1), math.nan_f64())
}
case im == 0 && math.is_nan(re):
return complex(math.nan_f64(), im)
}
s, c := math.sincos(imag(x))
sh, ch := _sinhcosh_f64(real(x))
return complex(c*ch, s*sh)
}
tan_complex128 :: proc "contextless" (x: complex128) -> complex128 {
// Complex circular tangent
//
// DESCRIPTION:
//
// If
// z = x + iy,
//
// then
//
// sin 2x + i sinh 2y
// w = --------------------.
// cos 2x + cosh 2y
//
// On the real axis the denominator is zero at odd multiples
// of PI/2. The denominator is evaluated by its Taylor
// series near these points.
//
// ctan(z) = -i ctanh(iz).
//
// ACCURACY:
//
// Relative error:
// arithmetic domain # trials peak rms
// DEC -10,+10 5200 7.1e-17 1.6e-17
// IEEE -10,+10 30000 7.2e-16 1.2e-16
// Also tested by ctan * ccot = 1 and catan(ctan(z)) = z.
switch re, im := real(x), imag(x); {
case math.is_inf(im, 0):
switch {
case math.is_inf(re, 0) || math.is_nan(re):
return complex(math.copy_sign(0, re), math.copy_sign(1, im))
}
return complex(math.copy_sign(0, math.sin(2*re)), math.copy_sign(1, im))
case re == 0 && math.is_nan(im):
return x
}
d := math.cos(2*real(x)) + math.cosh(2*imag(x))
if abs(d) < 0.25 {
d = _tan_series_f64(x)
}
if d == 0 {
return inf_complex128()
}
return complex(math.sin(2*real(x))/d, math.sinh(2*imag(x))/d)
}
tanh_complex128 :: proc "contextless" (x: complex128) -> complex128 {
switch re, im := real(x), imag(x); {
case math.is_inf(re, 0):
switch {
case math.is_inf(im, 0) || math.is_nan(im):
return complex(math.copy_sign(1, re), math.copy_sign(0, im))
}
return complex(math.copy_sign(1, re), math.copy_sign(0, math.sin(2*im)))
case im == 0 && math.is_nan(re):
return x
}
d := math.cosh(2*real(x)) + math.cos(2*imag(x))
if d == 0 {
return inf_complex128()
}
return complex(math.sinh(2*real(x))/d, math.sin(2*imag(x))/d)
}
cot_complex128 :: proc "contextless" (x: complex128) -> complex128 {
d := math.cosh(2*imag(x)) - math.cos(2*real(x))
if abs(d) < 0.25 {
d = _tan_series_f64(x)
}
if d == 0 {
return inf_complex128()
}
return complex(math.sin(2*real(x))/d, -math.sinh(2*imag(x))/d)
}
@(private="file")
_sinhcosh_f64 :: proc "contextless" (x: f64) -> (sh, ch: f64) {
if abs(x) <= 0.5 {
return math.sinh(x), math.cosh(x)
}
e := math.exp(x)
ei := 0.5 / e
e *= 0.5
return e - ei, e + ei
}
// taylor series of cosh(2y) - cos(2x)
@(private)
_tan_series_f64 :: proc "contextless" (z: complex128) -> f64 {
MACH_EPSILON :: 1.0 / (1 << 53)
x := abs(2 * real(z))
y := abs(2 * imag(z))
x = _reduce_pi_f64(x)
x, y = x * x, y * y
x2, y2 := 1.0, 1.0
f, rn, d := 1.0, 0.0, 0.0
for {
rn += 1
f *= rn
rn += 1
f *= rn
x2 *= x
y2 *= y
t := y2 + x2
t /= f
d += t
rn += 1
f *= rn
rn += 1
f *= rn
x2 *= x
y2 *= y
t = y2 - x2
t /= f
d += t
if !(abs(t/d) > MACH_EPSILON) { // don't use <=, because of floating point nonsense and NaN
break
}
}
return d
}
// _reduce_pi_f64 reduces the input argument x to the range (-PI/2, PI/2].
// x must be greater than or equal to 0. For small arguments it
// uses Cody-Waite reduction in 3 f64 parts based on:
// "Elementary Function Evaluation: Algorithms and Implementation"
// Jean-Michel Muller, 1997.
// For very large arguments it uses Payne-Hanek range reduction based on:
// "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit"
@(private)
_reduce_pi_f64 :: proc "contextless" (x: f64) -> f64 #no_bounds_check {
x := x
// REDUCE_THRESHOLD is the maximum value of x where the reduction using
// Cody-Waite reduction still gives accurate results. This threshold
// is set by t*PIn being representable as a f64 without error
// where t is given by t = floor(x * (1 / PI)) and PIn are the leading partial
// terms of PI. Since the leading terms, PI1 and PI2 below, have 30 and 32
// trailing zero bits respectively, t should have less than 30 significant bits.
// t < 1<<30 -> floor(x*(1/PI)+0.5) < 1<<30 -> x < (1<<30-1) * PI - 0.5
// So, conservatively we can take x < 1<<30.
REDUCE_THRESHOLD :: f64(1 << 30)
if abs(x) < REDUCE_THRESHOLD {
// Use Cody-Waite reduction in three parts.
// PI1, PI2 and PI3 comprise an extended precision value of PI
// such that PI ~= PI1 + PI2 + PI3. The parts are chosen so
// that PI1 and PI2 have an approximately equal number of trailing
// zero bits. This ensures that t*PI1 and t*PI2 are exact for
// large integer values of t. The full precision PI3 ensures the
// approximation of PI is accurate to 102 bits to handle cancellation
// during subtraction.
PI1 :: 0h400921fb40000000 // 3.141592502593994
PI2 :: 0h3e84442d00000000 // 1.5099578831723193e-07
PI3 :: 0h3d08469898cc5170 // 1.0780605716316238e-14
t := x / math.PI
t += 0.5
t = f64(i64(t)) // i64(t) = the multiple
return ((x - t*PI1) - t*PI2) - t*PI3
}
// Must apply Payne-Hanek range reduction
MASK :: 0x7FF
SHIFT :: 64 - 11 - 1
BIAS :: 1023
FRAC_MASK :: 1<<SHIFT - 1
// Extract out the integer and exponent such that,
// x = ix * 2 ** exp.
ix := transmute(u64)(x)
exp := int(ix>>SHIFT&MASK) - BIAS - SHIFT
ix &= FRAC_MASK
ix |= 1 << SHIFT
// bdpi is the binary digits of 1/PI as a u64 array,
// that is, 1/PI = SUM bdpi[i]*2^(-64*i).
// 19 64-bit digits give 1216 bits of precision
// to handle the largest possible f64 exponent.
@static bdpi := [?]u64{
0x0000000000000000,
0x517cc1b727220a94,
0xfe13abe8fa9a6ee0,
0x6db14acc9e21c820,
0xff28b1d5ef5de2b0,
0xdb92371d2126e970,
0x0324977504e8c90e,
0x7f0ef58e5894d39f,
0x74411afa975da242,
0x74ce38135a2fbf20,
0x9cc8eb1cc1a99cfa,
0x4e422fc5defc941d,
0x8ffc4bffef02cc07,
0xf79788c5ad05368f,
0xb69b3f6793e584db,
0xa7a31fb34f2ff516,
0xba93dd63f5f2f8bd,
0x9e839cfbc5294975,
0x35fdafd88fc6ae84,
0x2b0198237e3db5d5,
}
// Use the exponent to extract the 3 appropriate u64 digits from bdpi,
// B ~ (z0, z1, z2), such that the product leading digit has the exponent -64.
// Note, exp >= 50 since x >= REDUCE_THRESHOLD and exp < 971 for maximum f64.
digit, bitshift := uint(exp+64)/64, uint(exp+64)%64
z0 := (bdpi[digit] << bitshift) | (bdpi[digit+1] >> (64 - bitshift))
z1 := (bdpi[digit+1] << bitshift) | (bdpi[digit+2] >> (64 - bitshift))
z2 := (bdpi[digit+2] << bitshift) | (bdpi[digit+3] >> (64 - bitshift))
// Multiply mantissa by the digits and extract the upper two digits (hi, lo).
z2hi, _ := bits.mul(z2, ix)
z1hi, z1lo := bits.mul(z1, ix)
z0lo := z0 * ix
lo, c := bits.add(z1lo, z2hi, 0)
hi, _ := bits.add(z0lo, z1hi, c)
// Find the magnitude of the fraction.
lz := uint(bits.leading_zeros(hi))
e := u64(BIAS - (lz + 1))
// Clear implicit mantissa bit and shift into place.
hi = (hi << (lz + 1)) | (lo >> (64 - (lz + 1)))
hi >>= 64 - SHIFT
// Include the exponent and convert to a float.
hi |= e << SHIFT
x = transmute(f64)(hi)
// map to (-PI/2, PI/2]
if x > 0.5 {
x -= 1
}
return math.PI * x
}
+68 -33
View File
@@ -11,11 +11,13 @@ import "core:time"
// with additional enum based call // with additional enum based call
// Modeled after the parabola y = x^2 // Modeled after the parabola y = x^2
@(require_results)
quadratic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { quadratic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p return p * p
} }
// Modeled after the parabola y = -x^2 + 2x // Modeled after the parabola y = -x^2 + 2x
@(require_results)
quadratic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { quadratic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return -(p * (p - 2)) return -(p * (p - 2))
} }
@@ -23,6 +25,7 @@ quadratic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(
// Modeled after the piecewise quadratic // Modeled after the piecewise quadratic
// y = (1/2)((2x)^2) ; [0, 0.5) // y = (1/2)((2x)^2) ; [0, 0.5)
// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1] // y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1]
@(require_results)
quadratic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { quadratic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 { if p < 0.5 {
return 2 * p * p return 2 * p * p
@@ -32,11 +35,13 @@ quadratic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_flo
} }
// Modeled after the cubic y = x^3 // Modeled after the cubic y = x^3
@(require_results)
cubic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { cubic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p return p * p * p
} }
// Modeled after the cubic y = (x - 1)^3 + 1 // Modeled after the cubic y = (x - 1)^3 + 1
@(require_results)
cubic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { cubic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := p - 1 f := p - 1
return f * f * f + 1 return f * f * f + 1
@@ -45,6 +50,7 @@ cubic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
// Modeled after the piecewise cubic // Modeled after the piecewise cubic
// y = (1/2)((2x)^3) ; [0, 0.5) // y = (1/2)((2x)^3) ; [0, 0.5)
// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1] // y = (1/2)((2x-2)^3 + 2) ; [0.5, 1]
@(require_results)
cubic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { cubic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 { if p < 0.5 {
return 4 * p * p * p return 4 * p * p * p
@@ -55,11 +61,13 @@ cubic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T
} }
// Modeled after the quartic x^4 // Modeled after the quartic x^4
@(require_results)
quartic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { quartic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p * p return p * p * p * p
} }
// Modeled after the quartic y = 1 - (x - 1)^4 // Modeled after the quartic y = 1 - (x - 1)^4
@(require_results)
quartic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { quartic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := p - 1 f := p - 1
return f * f * f * (1 - p) + 1 return f * f * f * (1 - p) + 1
@@ -68,6 +76,7 @@ quartic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T)
// Modeled after the piecewise quartic // Modeled after the piecewise quartic
// y = (1/2)((2x)^4) ; [0, 0.5) // y = (1/2)((2x)^4) ; [0, 0.5)
// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1] // y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1]
@(require_results)
quartic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { quartic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 { if p < 0.5 {
return 8 * p * p * p * p return 8 * p * p * p * p
@@ -78,11 +87,13 @@ quartic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float
} }
// Modeled after the quintic y = x^5 // Modeled after the quintic y = x^5
@(require_results)
quintic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { quintic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p * p * p return p * p * p * p * p
} }
// Modeled after the quintic y = (x - 1)^5 + 1 // Modeled after the quintic y = (x - 1)^5 + 1
@(require_results)
quintic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { quintic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := p - 1 f := p - 1
return f * f * f * f * f + 1 return f * f * f * f * f + 1
@@ -91,6 +102,7 @@ quintic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T)
// Modeled after the piecewise quintic // Modeled after the piecewise quintic
// y = (1/2)((2x)^5) ; [0, 0.5) // y = (1/2)((2x)^5) ; [0, 0.5)
// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1] // y = (1/2)((2x-2)^5 + 2) ; [0.5, 1]
@(require_results)
quintic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { quintic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 { if p < 0.5 {
return 16 * p * p * p * p * p return 16 * p * p * p * p * p
@@ -101,26 +113,31 @@ quintic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float
} }
// Modeled after quarter-cycle of sine wave // Modeled after quarter-cycle of sine wave
@(require_results)
sine_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { sine_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin((p - 1) * PI_2) + 1 return math.sin((p - 1) * PI_2) + 1
} }
// Modeled after quarter-cycle of sine wave (different phase) // Modeled after quarter-cycle of sine wave (different phase)
@(require_results)
sine_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { sine_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin(p * PI_2) return math.sin(p * PI_2)
} }
// Modeled after half sine wave // Modeled after half sine wave
@(require_results)
sine_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { sine_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return 0.5 * (1 - math.cos(p * math.PI)) return 0.5 * (1 - math.cos(p * math.PI))
} }
// Modeled after shifted quadrant IV of unit circle // Modeled after shifted quadrant IV of unit circle
@(require_results)
circular_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { circular_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return 1 - math.sqrt(1 - (p * p)) return 1 - math.sqrt(1 - (p * p))
} }
// Modeled after shifted quadrant II of unit circle // Modeled after shifted quadrant II of unit circle
@(require_results)
circular_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { circular_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sqrt((2 - p) * p) return math.sqrt((2 - p) * p)
} }
@@ -128,6 +145,7 @@ circular_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T
// Modeled after the piecewise circular function // Modeled after the piecewise circular function
// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5) // y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5)
// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1] // y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1]
@(require_results)
circular_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { circular_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 { if p < 0.5 {
return 0.5 * (1 - math.sqrt(1 - 4 * (p * p))) return 0.5 * (1 - math.sqrt(1 - 4 * (p * p)))
@@ -137,11 +155,13 @@ circular_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_floa
} }
// Modeled after the exponential function y = 2^(10(x - 1)) // Modeled after the exponential function y = 2^(10(x - 1))
@(require_results)
exponential_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { exponential_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p == 0.0 ? p : math.pow(2, 10 * (p - 1)) return p == 0.0 ? p : math.pow(2, 10 * (p - 1))
} }
// Modeled after the exponential function y = -2^(-10x) + 1 // Modeled after the exponential function y = -2^(-10x) + 1
@(require_results)
exponential_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { exponential_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p == 1.0 ? p : 1 - math.pow(2, -10 * p) return p == 1.0 ? p : 1 - math.pow(2, -10 * p)
} }
@@ -149,6 +169,7 @@ exponential_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_floa
// Modeled after the piecewise exponential // Modeled after the piecewise exponential
// y = (1/2)2^(10(2x - 1)) ; [0,0.5) // y = (1/2)2^(10(2x - 1)) ; [0,0.5)
// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1] // y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1]
@(require_results)
exponential_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { exponential_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p == 0.0 || p == 1.0 { if p == 0.0 || p == 1.0 {
return p return p
@@ -162,11 +183,13 @@ exponential_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_f
} }
// Modeled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1)) // Modeled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1))
@(require_results)
elastic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { elastic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin(13 * PI_2 * p) * math.pow(2, 10 * (p - 1)) return math.sin(13 * PI_2 * p) * math.pow(2, 10 * (p - 1))
} }
// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) + 1 // Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) + 1
@(require_results)
elastic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { elastic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin(-13 * PI_2 * (p + 1)) * math.pow(2, -10 * p) + 1 return math.sin(-13 * PI_2 * (p + 1)) * math.pow(2, -10 * p) + 1
} }
@@ -174,6 +197,7 @@ elastic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T)
// Modeled after the piecewise exponentially-damped sine wave: // Modeled after the piecewise exponentially-damped sine wave:
// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5) // y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5)
// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1] // y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1]
@(require_results)
elastic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { elastic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 { if p < 0.5 {
return 0.5 * math.sin(13 * PI_2 * (2 * p)) * math.pow(2, 10 * ((2 * p) - 1)) return 0.5 * math.sin(13 * PI_2 * (2 * p)) * math.pow(2, 10 * ((2 * p) - 1))
@@ -183,11 +207,13 @@ elastic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float
} }
// Modeled after the overshooting cubic y = x^3-x*sin(x*pi) // Modeled after the overshooting cubic y = x^3-x*sin(x*pi)
@(require_results)
back_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { back_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p - p * math.sin(p * math.PI) return p * p * p - p * math.sin(p * math.PI)
} }
// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi)) // Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi))
@(require_results)
back_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { back_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := 1 - p f := 1 - p
return 1 - (f * f * f - f * math.sin(f * math.PI)) return 1 - (f * f * f - f * math.sin(f * math.PI))
@@ -196,6 +222,7 @@ back_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
// Modeled after the piecewise overshooting cubic function: // Modeled after the piecewise overshooting cubic function:
// y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5) // y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5)
// y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1] // y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1]
@(require_results)
back_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { back_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 { if p < 0.5 {
f := 2 * p f := 2 * p
@@ -206,10 +233,12 @@ back_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T)
} }
} }
@(require_results)
bounce_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { bounce_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return 1 - bounce_out(1 - p) return 1 - bounce_out(1 - p)
} }
@(require_results)
bounce_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { bounce_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 4/11.0 { if p < 4/11.0 {
return (121 * p * p)/16.0 return (121 * p * p)/16.0
@@ -222,6 +251,7 @@ bounce_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T)
} }
} }
@(require_results)
bounce_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { bounce_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 { if p < 0.5 {
return 0.5 * bounce_in(p*2) return 0.5 * bounce_in(p*2)
@@ -276,50 +306,51 @@ Ease :: enum {
Bounce_In_Out, Bounce_In_Out,
} }
@(require_results)
ease :: proc "contextless" (type: Ease, p: $T) -> T ease :: proc "contextless" (type: Ease, p: $T) -> T
where intrinsics.type_is_float(T) { where intrinsics.type_is_float(T) {
switch type { switch type {
case .Linear: return p case .Linear: return p
case .Quadratic_In: return quadratic_in(p)
case .Quadratic_Out: return quadratic_out(p)
case .Quadratic_In_Out: return quadratic_in_out(p)
case .Cubic_In: return cubic_in(p) case .Quadratic_In: return quadratic_in(p)
case .Cubic_Out: return cubic_out(p) case .Quadratic_Out: return quadratic_out(p)
case .Cubic_In_Out: return cubic_in_out(p) case .Quadratic_In_Out: return quadratic_in_out(p)
case .Quartic_In: return quartic_in(p) case .Cubic_In: return cubic_in(p)
case .Quartic_Out: return quartic_out(p) case .Cubic_Out: return cubic_out(p)
case .Quartic_In_Out: return quartic_in_out(p) case .Cubic_In_Out: return cubic_in_out(p)
case .Quintic_In: return quintic_in(p) case .Quartic_In: return quartic_in(p)
case .Quintic_Out: return quintic_out(p) case .Quartic_Out: return quartic_out(p)
case .Quintic_In_Out: return quintic_in_out(p) case .Quartic_In_Out: return quartic_in_out(p)
case .Sine_In: return sine_in(p) case .Quintic_In: return quintic_in(p)
case .Sine_Out: return sine_out(p) case .Quintic_Out: return quintic_out(p)
case .Sine_In_Out: return sine_in_out(p) case .Quintic_In_Out: return quintic_in_out(p)
case .Circular_In: return circular_in(p) case .Sine_In: return sine_in(p)
case .Circular_Out: return circular_out(p) case .Sine_Out: return sine_out(p)
case .Circular_In_Out: return circular_in_out(p) case .Sine_In_Out: return sine_in_out(p)
case .Exponential_In: return exponential_in(p) case .Circular_In: return circular_in(p)
case .Exponential_Out: return exponential_out(p) case .Circular_Out: return circular_out(p)
case .Exponential_In_Out: return exponential_in_out(p) case .Circular_In_Out: return circular_in_out(p)
case .Elastic_In: return elastic_in(p) case .Exponential_In: return exponential_in(p)
case .Elastic_Out: return elastic_out(p) case .Exponential_Out: return exponential_out(p)
case .Elastic_In_Out: return elastic_in_out(p) case .Exponential_In_Out: return exponential_in_out(p)
case .Back_In: return back_in(p) case .Elastic_In: return elastic_in(p)
case .Back_Out: return back_out(p) case .Elastic_Out: return elastic_out(p)
case .Back_In_Out: return back_in_out(p) case .Elastic_In_Out: return elastic_in_out(p)
case .Bounce_In: return bounce_in(p) case .Back_In: return back_in(p)
case .Bounce_Out: return bounce_out(p) case .Back_Out: return back_out(p)
case .Bounce_In_Out: return bounce_in_out(p) case .Back_In_Out: return back_in_out(p)
case .Bounce_In: return bounce_in(p)
case .Bounce_Out: return bounce_out(p)
case .Bounce_In_Out: return bounce_in_out(p)
} }
// in case type was invalid // in case type was invalid
@@ -353,6 +384,7 @@ Flux_Tween :: struct($T: typeid) {
} }
// init flux map to a float type and a wanted cap // init flux map to a float type and a wanted cap
@(require_results)
flux_init :: proc($T: typeid, value_capacity := 8) -> Flux_Map(T) where intrinsics.type_is_float(T) { flux_init :: proc($T: typeid, value_capacity := 8) -> Flux_Map(T) where intrinsics.type_is_float(T) {
return { return {
values = make(map[^T]Flux_Tween(T), value_capacity), values = make(map[^T]Flux_Tween(T), value_capacity),
@@ -374,6 +406,7 @@ flux_clear :: proc(flux: ^Flux_Map($T)) where intrinsics.type_is_float(T) {
// append / overwrite existing tween value to parameters // append / overwrite existing tween value to parameters
// rest is initialized in flux_tween_init, inside update // rest is initialized in flux_tween_init, inside update
// return value can be used to set callbacks // return value can be used to set callbacks
@(require_results)
flux_to :: proc( flux_to :: proc(
flux: ^Flux_Map($T), flux: ^Flux_Map($T),
value: ^T, value: ^T,
@@ -417,7 +450,7 @@ flux_tween_init :: proc(tween: ^Flux_Tween($T), duration: time.Duration) where i
flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float(T) { flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float(T) {
clear(&flux.keys_to_be_deleted) clear(&flux.keys_to_be_deleted)
for key, tween in &flux.values { for key, &tween in flux.values {
delay_remainder := f64(0) delay_remainder := f64(0)
// Update delay if necessary. // Update delay if necessary.
@@ -475,6 +508,7 @@ flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float
// stop a specific key inside the map // stop a specific key inside the map
// returns true when it successfully removed the key // returns true when it successfully removed the key
@(require_results)
flux_stop :: proc(flux: ^Flux_Map($T), key: ^T) -> bool where intrinsics.type_is_float(T) { flux_stop :: proc(flux: ^Flux_Map($T), key: ^T) -> bool where intrinsics.type_is_float(T) {
if key in flux.values { if key in flux.values {
delete_key(&flux.values, key) delete_key(&flux.values, key)
@@ -486,6 +520,7 @@ flux_stop :: proc(flux: ^Flux_Map($T), key: ^T) -> bool where intrinsics.type_is
// returns the amount of time left for the tween animation, if the key exists in the map // returns the amount of time left for the tween animation, if the key exists in the map
// returns 0 if the tween doesnt exist on the map // returns 0 if the tween doesnt exist on the map
@(require_results)
flux_tween_time_left :: proc(flux: Flux_Map($T), key: ^T) -> f64 { flux_tween_time_left :: proc(flux: Flux_Map($T), key: ^T) -> f64 {
if tween, ok := flux.values[key]; ok { if tween, ok := flux.values[key]; ok {
return ((1 - tween.progress) * tween.rate) + tween.delay return ((1 - tween.progress) * tween.rate) + tween.delay
+11
View File
@@ -50,39 +50,48 @@ to_f64 :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> f64 {
} }
@(require_results)
add :: proc(x, y: $T/Fixed) -> T { add :: proc(x, y: $T/Fixed) -> T {
return {x.i + y.i} return {x.i + y.i}
} }
@(require_results)
sub :: proc(x, y: $T/Fixed) -> T { sub :: proc(x, y: $T/Fixed) -> T {
return {x.i - y.i} return {x.i - y.i}
} }
@(require_results)
mul :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { mul :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_mul(x.i, y.i, Fraction_Width) z.i = intrinsics.fixed_point_mul(x.i, y.i, Fraction_Width)
return return
} }
@(require_results)
mul_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { mul_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_mul_sat(x.i, y.i, Fraction_Width) z.i = intrinsics.fixed_point_mul_sat(x.i, y.i, Fraction_Width)
return return
} }
@(require_results)
div :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { div :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_div(x.i, y.i, Fraction_Width) z.i = intrinsics.fixed_point_div(x.i, y.i, Fraction_Width)
return return
} }
@(require_results)
div_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { div_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_div_sat(x.i, y.i, Fraction_Width) z.i = intrinsics.fixed_point_div_sat(x.i, y.i, Fraction_Width)
return return
} }
@(require_results)
floor :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { floor :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
return x.i >> Fraction_Width return x.i >> Fraction_Width
} }
@(require_results)
ceil :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { ceil :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
Integer :: 8*size_of(Backing) - Fraction_Width Integer :: 8*size_of(Backing) - Fraction_Width
return (x.i + (1 << Integer-1)) >> Fraction_Width return (x.i + (1 << Integer-1)) >> Fraction_Width
} }
@(require_results)
round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
Integer :: 8*size_of(Backing) - Fraction_Width Integer :: 8*size_of(Backing) - Fraction_Width
return (x.i + (1 << (Integer - 1))) >> Fraction_Width return (x.i + (1 << (Integer - 1))) >> Fraction_Width
@@ -90,6 +99,7 @@ round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
@(require_results)
append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string { append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string {
x := x x := x
buf: [48]byte buf: [48]byte
@@ -123,6 +133,7 @@ append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string {
} }
@(require_results)
to_string :: proc(x: $T/Fixed($Backing, $Fraction_Width), allocator := context.allocator) -> string { to_string :: proc(x: $T/Fixed($Backing, $Fraction_Width), allocator := context.allocator) -> string {
buf: [48]byte buf: [48]byte
s := append(buf[:], x) s := append(buf[:], x)
+124 -65
View File
@@ -3,7 +3,8 @@ package linalg
import "core:builtin" import "core:builtin"
import "core:math" import "core:math"
to_radians :: proc(degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
to_radians :: proc "contextless" (degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = degrees[i] * RAD_PER_DEG out[i] = degrees[i] * RAD_PER_DEG
@@ -14,7 +15,8 @@ to_radians :: proc(degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return return
} }
to_degrees :: proc(radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
to_degrees :: proc "contextless" (radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = radians[i] * DEG_PER_RAD out[i] = radians[i] * DEG_PER_RAD
@@ -25,7 +27,8 @@ to_degrees :: proc(radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return return
} }
min_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
min_double :: proc "contextless" (a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = builtin.min(a[i], b[i]) out[i] = builtin.min(a[i], b[i])
@@ -36,7 +39,8 @@ min_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return return
} }
min_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
min_single :: proc "contextless" (a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
N :: len(T) N :: len(T)
@@ -56,13 +60,15 @@ min_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T))
return return
} }
min_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
min_triple :: proc "contextless" (a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) {
return min_double(a, min_double(b, c)) return min_double(a, min_double(b, c))
} }
min :: proc{min_single, min_double, min_triple} min :: proc{min_single, min_double, min_triple}
max_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
max_double :: proc "contextless" (a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = builtin.max(a[i], b[i]) out[i] = builtin.max(a[i], b[i])
@@ -73,7 +79,8 @@ max_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return return
} }
max_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
max_single :: proc "contextless" (a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
N :: len(T) N :: len(T)
@@ -95,13 +102,15 @@ max_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T))
return return
} }
max_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
max_triple :: proc "contextless" (a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) {
return max_double(a, max_double(b, c)) return max_double(a, max_double(b, c))
} }
max :: proc{max_single, max_double, max_triple} max :: proc{max_single, max_double, max_triple}
abs :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
abs :: proc "contextless" (a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = auto_cast builtin.abs(a[i]) out[i] = auto_cast builtin.abs(a[i])
@@ -112,7 +121,8 @@ abs :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return return
} }
sign :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
sign :: proc "contextless" (a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = #force_inline math.sign(a[i]) out[i] = #force_inline math.sign(a[i])
@@ -123,7 +133,8 @@ sign :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return return
} }
clamp :: proc(x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results)
clamp :: proc "contextless" (x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = builtin.clamp(x[i], a[i], b[i]) out[i] = builtin.clamp(x[i], a[i], b[i])
@@ -135,11 +146,13 @@ clamp :: proc(x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
} }
saturate :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
saturate :: proc "contextless" (x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
return clamp(x, 0.0, 1.0) return clamp(x, 0.0, 1.0)
} }
lerp :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
lerp :: proc "contextless" (a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = a[i]*(1-t[i]) + b[i]*t[i] out[i] = a[i]*(1-t[i]) + b[i]*t[i]
@@ -149,7 +162,8 @@ lerp :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
} }
return return
} }
mix :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
mix :: proc "contextless" (a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = a[i]*(1-t[i]) + b[i]*t[i] out[i] = a[i]*(1-t[i]) + b[i]*t[i]
@@ -160,11 +174,13 @@ mix :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
unlerp :: proc(a, b, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
unlerp :: proc "contextless" (a, b, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
return (x - a) / (b - a) return (x - a) / (b - a)
} }
step :: proc(e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
step :: proc "contextless" (e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = x[i] < e[i] ? 0.0 : 1.0 out[i] = x[i] < e[i] ? 0.0 : 1.0
@@ -175,18 +191,21 @@ step :: proc(e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
smoothstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
smoothstep :: proc "contextless" (e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
t := saturate(unlerp(e0, e1, x)) t := saturate(unlerp(e0, e1, x))
return t * t * (3.0 - 2.0 * t) return t * t * (3.0 - 2.0 * t)
} }
smootherstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
smootherstep :: proc "contextless" (e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
t := saturate(unlerp(e0, e1, x)) t := saturate(unlerp(e0, e1, x))
return t * t * t * (t * (6*t - 15) + 10) return t * t * t * (t * (6*t - 15) + 10)
} }
sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
sqrt :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.sqrt(x[i]) out[i] = math.sqrt(x[i])
@@ -197,7 +216,8 @@ sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
inverse_sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
inverse_sqrt :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = 1.0/math.sqrt(x[i]) out[i] = 1.0/math.sqrt(x[i])
@@ -208,7 +228,8 @@ inverse_sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
cos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
cos :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.cos(x[i]) out[i] = math.cos(x[i])
@@ -219,7 +240,8 @@ cos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
sin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
sin :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.sin(x[i]) out[i] = math.sin(x[i])
@@ -230,7 +252,8 @@ sin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
tan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
tan :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.tan(x[i]) out[i] = math.tan(x[i])
@@ -241,7 +264,8 @@ tan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
acos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
acos :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.acos(x[i]) out[i] = math.acos(x[i])
@@ -252,7 +276,8 @@ acos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
asin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
asin :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.asin(x[i]) out[i] = math.asin(x[i])
@@ -263,7 +288,8 @@ asin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
atan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
atan :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.atan(x[i]) out[i] = math.atan(x[i])
@@ -273,7 +299,8 @@ atan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
} }
return return
} }
atan2 :: proc(y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
atan2 :: proc "contextless" (y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.atan2(y[i], x[i]) out[i] = math.atan2(y[i], x[i])
@@ -285,7 +312,8 @@ atan2 :: proc(y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
} }
ln :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
ln :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.ln(x[i]) out[i] = math.ln(x[i])
@@ -296,7 +324,8 @@ ln :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
log2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
log2 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = INVLN2 * math.ln(x[i]) out[i] = INVLN2 * math.ln(x[i])
@@ -307,7 +336,8 @@ log2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
log10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
log10 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = INVLN10 * math.ln(x[i]) out[i] = INVLN10 * math.ln(x[i])
@@ -318,7 +348,8 @@ log10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
log :: proc(x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
log :: proc "contextless" (x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.ln(x[i]) / math.ln(cast(ELEM_TYPE(T))b[i]) out[i] = math.ln(x[i]) / math.ln(cast(ELEM_TYPE(T))b[i])
@@ -329,7 +360,8 @@ log :: proc(x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
exp :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
exp :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.exp(x[i]) out[i] = math.exp(x[i])
@@ -340,7 +372,8 @@ exp :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
exp2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
exp2 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.exp(LN2 * x[i]) out[i] = math.exp(LN2 * x[i])
@@ -351,7 +384,8 @@ exp2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
exp10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
exp10 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.exp(LN10 * x[i]) out[i] = math.exp(LN10 * x[i])
@@ -362,7 +396,8 @@ exp10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
pow :: proc(x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
pow :: proc "contextless" (x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = math.pow(x[i], e[i]) out[i] = math.pow(x[i], e[i])
@@ -374,7 +409,8 @@ pow :: proc(x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
} }
ceil :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
ceil :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = #force_inline math.ceil(x[i]) out[i] = #force_inline math.ceil(x[i])
@@ -385,7 +421,8 @@ ceil :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
floor :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
floor :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = #force_inline math.floor(x[i]) out[i] = #force_inline math.floor(x[i])
@@ -396,7 +433,8 @@ floor :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
round :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
round :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) { when IS_ARRAY(T) {
for i in 0..<len(T) { for i in 0..<len(T) {
out[i] = #force_inline math.round(x[i]) out[i] = #force_inline math.round(x[i])
@@ -407,30 +445,36 @@ round :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return return
} }
fract :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
fract :: proc "contextless" (x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
f := #force_inline floor(x) f := #force_inline floor(x)
return x - f return x - f
} }
mod :: proc(x, m: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
mod :: proc "contextless" (x, m: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
f := #force_inline floor(x / m) f := #force_inline floor(x / m)
return x - f * m return x - f * m
} }
face_forward :: proc(N, I, N_ref: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
face_forward :: proc "contextless" (N, I, N_ref: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
return dot(N_ref, I) < 0 ? N : -N return dot(N_ref, I) < 0 ? N : -N
} }
distance :: proc(p0, p1: $V/[$N]$E) -> E where IS_NUMERIC(E) { @(require_results)
distance :: proc "contextless" (p0, p1: $V/[$N]$E) -> E where IS_NUMERIC(E) {
return length(p1 - p0) return length(p1 - p0)
} }
reflect :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { @(require_results)
reflect :: proc "contextless" (I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
b := N * (2 * dot(N, I)) b := N * (2 * dot(N, I))
return I - b return I - b
} }
refract :: proc(I, Normal: $V/[$N]$E, eta: E) -> (out: V) where IS_ARRAY(V), IS_FLOAT(ELEM_TYPE(V)) { @(require_results)
refract :: proc "contextless" (I, Normal: $V/[$N]$E, eta: E) -> (out: V) where IS_ARRAY(V), IS_FLOAT(ELEM_TYPE(V)) {
dv := dot(Normal, I) dv := dot(Normal, I)
k := 1 - eta*eta * (1 - dv*dv) k := 1 - eta*eta * (1 - dv*dv)
a := I * eta a := I * eta
@@ -441,33 +485,39 @@ refract :: proc(I, Normal: $V/[$N]$E, eta: E) -> (out: V) where IS_ARRAY(V), IS_
is_nan_single :: proc(x: $T) -> bool where IS_FLOAT(T) { @(require_results)
is_nan_single :: proc "contextless" (x: $T) -> bool where IS_FLOAT(T) {
return #force_inline math.is_nan(x) return #force_inline math.is_nan(x)
} }
is_nan_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) { @(require_results)
is_nan_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
for i in 0..<N { for i in 0..<N {
out[i] = #force_inline is_nan(x[i]) out[i] = #force_inline is_nan(x[i])
} }
return return
} }
is_inf_single :: proc(x: $T) -> bool where IS_FLOAT(T) { @(require_results)
is_inf_single :: proc "contextless" (x: $T) -> bool where IS_FLOAT(T) {
return #force_inline math.is_inf(x) return #force_inline math.is_inf(x)
} }
is_inf_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) { @(require_results)
is_inf_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
for i in 0..<N { for i in 0..<N {
out[i] = #force_inline is_inf(x[i]) out[i] = #force_inline is_inf(x[i])
} }
return return
} }
classify_single :: proc(x: $T) -> math.Float_Class where IS_FLOAT(T) { @(require_results)
classify_single :: proc "contextless" (x: $T) -> math.Float_Class where IS_FLOAT(T) {
return #force_inline math.classify(x) return #force_inline math.classify(x)
} }
classify_array :: proc(x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) { @(require_results)
classify_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) {
for i in 0..<N { for i in 0..<N {
out[i] = #force_inline classify_single(x[i]) out[i] = #force_inline classify_single(x[i])
} }
@@ -479,44 +529,50 @@ is_inf :: proc{is_inf_single, is_inf_array}
classify :: proc{classify_single, classify_array} classify :: proc{classify_single, classify_array}
less_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x < y } @(require_results) less_than_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x < y }
less_than_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x <= y } @(require_results) less_than_equal_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x <= y }
greater_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x > y } @(require_results) greater_than_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x > y }
greater_than_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x >= y } @(require_results) greater_than_equal_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x >= y }
equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x == y } @(require_results) equal_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x == y }
not_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x != y } @(require_results) not_equal_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x != y }
less_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { @(require_results)
less_than_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N { for i in 0..<N {
out[i] = x[i] < y[i] out[i] = x[i] < y[i]
} }
return return
} }
less_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { @(require_results)
less_than_equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N { for i in 0..<N {
out[i] = x[i] <= y[i] out[i] = x[i] <= y[i]
} }
return return
} }
greater_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { @(require_results)
greater_than_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N { for i in 0..<N {
out[i] = x[i] > y[i] out[i] = x[i] > y[i]
} }
return return
} }
greater_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { @(require_results)
greater_than_equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N { for i in 0..<N {
out[i] = x[i] >= y[i] out[i] = x[i] >= y[i]
} }
return return
} }
equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { @(require_results)
equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N { for i in 0..<N {
out[i] = x[i] == y[i] out[i] = x[i] == y[i]
} }
return return
} }
not_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { @(require_results)
not_equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N { for i in 0..<N {
out[i] = x[i] != y[i] out[i] = x[i] != y[i]
} }
@@ -530,7 +586,8 @@ greater_than_equal :: proc{greater_than_equal_single, greater_than_equal_array}
equal :: proc{equal_single, equal_array} equal :: proc{equal_single, equal_array}
not_equal :: proc{not_equal_single, not_equal_array} not_equal :: proc{not_equal_single, not_equal_array}
any :: proc(x: $A/[$N]bool) -> (out: bool) { @(require_results)
any :: proc "contextless" (x: $A/[$N]bool) -> (out: bool) {
for e in x { for e in x {
if e { if e {
return true return true
@@ -538,7 +595,8 @@ any :: proc(x: $A/[$N]bool) -> (out: bool) {
} }
return false return false
} }
all :: proc(x: $A/[$N]bool) -> (out: bool) { @(require_results)
all :: proc "contextless" (x: $A/[$N]bool) -> (out: bool) {
for e in x { for e in x {
if !e { if !e {
return false return false
@@ -546,7 +604,8 @@ all :: proc(x: $A/[$N]bool) -> (out: bool) {
} }
return true return true
} }
not :: proc(x: $A/[$N]bool) -> (out: A) { @(require_results)
not :: proc "contextless" (x: $A/[$N]bool) -> (out: A) {
for e, i in x { for e, i in x {
out[i] = !e out[i] = !e
} }
+94 -56
View File
@@ -38,23 +38,28 @@ DEG_PER_RAD :: 360.0/TAU
@private ELEM_TYPE :: intrinsics.type_elem_type @private ELEM_TYPE :: intrinsics.type_elem_type
scalar_dot :: proc(a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) { @(require_results)
scalar_dot :: proc "contextless" (a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) {
return a * b return a * b
} }
vector_dot :: proc(a, b: $T/[$N]$E) -> (c: E) where IS_NUMERIC(E) #no_bounds_check { @(require_results)
vector_dot :: proc "contextless" (a, b: $T/[$N]$E) -> (c: E) where IS_NUMERIC(E) #no_bounds_check {
for i in 0..<N { for i in 0..<N {
c += a[i] * b[i] c += a[i] * b[i]
} }
return return
} }
quaternion64_dot :: proc(a, b: $T/quaternion64) -> (c: f16) { @(require_results)
quaternion64_dot :: proc "contextless" (a, b: $T/quaternion64) -> (c: f16) {
return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z
} }
quaternion128_dot :: proc(a, b: $T/quaternion128) -> (c: f32) { @(require_results)
quaternion128_dot :: proc "contextless" (a, b: $T/quaternion128) -> (c: f32) {
return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z
} }
quaternion256_dot :: proc(a, b: $T/quaternion256) -> (c: f64) { @(require_results)
quaternion256_dot :: proc "contextless" (a, b: $T/quaternion256) -> (c: f64) {
return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z
} }
@@ -63,27 +68,32 @@ dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quatern
inner_product :: dot inner_product :: dot
outer_product :: builtin.outer_product outer_product :: builtin.outer_product
quaternion_inverse :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { @(require_results)
quaternion_inverse :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0) return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0)
} }
scalar_cross :: proc(a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) { @(require_results)
scalar_cross :: proc "contextless" (a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) {
return a * b return a * b
} }
vector_cross2 :: proc(a, b: $T/[2]$E) -> E where IS_NUMERIC(E) { @(require_results)
vector_cross2 :: proc "contextless" (a, b: $T/[2]$E) -> E where IS_NUMERIC(E) {
return a[0]*b[1] - b[0]*a[1] return a[0]*b[1] - b[0]*a[1]
} }
vector_cross3 :: proc(a, b: $T/[3]$E) -> (c: T) where IS_NUMERIC(E) { @(require_results)
vector_cross3 :: proc "contextless" (a, b: $T/[3]$E) -> (c: T) where IS_NUMERIC(E) {
c[0] = a[1]*b[2] - b[1]*a[2] c[0] = a[1]*b[2] - b[1]*a[2]
c[1] = a[2]*b[0] - b[2]*a[0] c[1] = a[2]*b[0] - b[2]*a[0]
c[2] = a[0]*b[1] - b[0]*a[1] c[2] = a[0]*b[1] - b[0]*a[1]
return return
} }
quaternion_cross :: proc(q1, q2: $Q) -> (q3: Q) where IS_QUATERNION(Q) { @(require_results)
quaternion_cross :: proc "contextless" (q1, q2: $Q) -> (q3: Q) where IS_QUATERNION(Q) {
q3.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y q3.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y
q3.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z q3.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z
q3.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x q3.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x
@@ -94,49 +104,59 @@ quaternion_cross :: proc(q1, q2: $Q) -> (q3: Q) where IS_QUATERNION(Q) {
vector_cross :: proc{scalar_cross, vector_cross2, vector_cross3} vector_cross :: proc{scalar_cross, vector_cross2, vector_cross3}
cross :: proc{scalar_cross, vector_cross2, vector_cross3, quaternion_cross} cross :: proc{scalar_cross, vector_cross2, vector_cross3, quaternion_cross}
vector_normalize :: proc(v: $T/[$N]$E) -> T where IS_FLOAT(E) { @(require_results)
vector_normalize :: proc "contextless" (v: $T/[$N]$E) -> T where IS_FLOAT(E) {
return v / length(v) return v / length(v)
} }
quaternion_normalize :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { @(require_results)
quaternion_normalize :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
return q/abs(q) return q/abs(q)
} }
normalize :: proc{vector_normalize, quaternion_normalize} normalize :: proc{vector_normalize, quaternion_normalize}
vector_normalize0 :: proc(v: $T/[$N]$E) -> T where IS_FLOAT(E) { @(require_results)
vector_normalize0 :: proc "contextless" (v: $T/[$N]$E) -> T where IS_FLOAT(E) {
m := length(v) m := length(v)
return 0 if m == 0 else v/m return 0 if m == 0 else v/m
} }
quaternion_normalize0 :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { @(require_results)
quaternion_normalize0 :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
m := abs(q) m := abs(q)
return 0 if m == 0 else q/m return 0 if m == 0 else q/m
} }
normalize0 :: proc{vector_normalize0, quaternion_normalize0} normalize0 :: proc{vector_normalize0, quaternion_normalize0}
vector_length :: proc(v: $T/[$N]$E) -> E where IS_FLOAT(E) { @(require_results)
vector_length :: proc "contextless" (v: $T/[$N]$E) -> E where IS_FLOAT(E) {
return math.sqrt(dot(v, v)) return math.sqrt(dot(v, v))
} }
vector_length2 :: proc(v: $T/[$N]$E) -> E where IS_NUMERIC(E) { @(require_results)
vector_length2 :: proc "contextless" (v: $T/[$N]$E) -> E where IS_NUMERIC(E) {
return dot(v, v) return dot(v, v)
} }
quaternion_length :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { @(require_results)
quaternion_length :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
return abs(q) return abs(q)
} }
quaternion_length2 :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { @(require_results)
quaternion_length2 :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
return dot(q, q) return dot(q, q)
} }
scalar_triple_product :: proc(a, b, c: $T/[$N]$E) -> E where IS_NUMERIC(E) { @(require_results)
scalar_triple_product :: proc "contextless" (a, b, c: $T/[$N]$E) -> E where IS_NUMERIC(E) {
// a . (b x c) // a . (b x c)
// b . (c x a) // b . (c x a)
// c . (a x b) // c . (a x b)
return dot(a, cross(b, c)) return dot(a, cross(b, c))
} }
vector_triple_product :: proc(a, b, c: $T/[$N]$E) -> T where IS_NUMERIC(E) { @(require_results)
vector_triple_product :: proc "contextless" (a, b, c: $T/[$N]$E) -> T where IS_NUMERIC(E) {
// a x (b x c) // a x (b x c)
// (a . c)b - (a . b)c // (a . c)b - (a . b)c
return cross(a, cross(b, c)) return cross(a, cross(b, c))
@@ -146,11 +166,13 @@ vector_triple_product :: proc(a, b, c: $T/[$N]$E) -> T where IS_NUMERIC(E) {
length :: proc{vector_length, quaternion_length} length :: proc{vector_length, quaternion_length}
length2 :: proc{vector_length2, quaternion_length2} length2 :: proc{vector_length2, quaternion_length2}
projection :: proc(x, normal: $T/[$N]$E) -> T where IS_NUMERIC(E) { @(require_results)
projection :: proc "contextless" (x, normal: $T/[$N]$E) -> T where IS_NUMERIC(E) {
return dot(x, normal) / dot(normal, normal) * normal return dot(x, normal) / dot(normal, normal) * normal
} }
identity :: proc($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check { @(require_results)
identity :: proc "contextless" ($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check {
for i in 0..<N { for i in 0..<N {
m[i][i] = E(1) m[i][i] = E(1)
} }
@@ -160,32 +182,38 @@ identity :: proc($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check {
trace :: builtin.matrix_trace trace :: builtin.matrix_trace
transpose :: builtin.transpose transpose :: builtin.transpose
matrix_mul :: proc(a, b: $M/matrix[$N, N]$E) -> (c: M) @(require_results)
matrix_mul :: proc "contextless" (a, b: $M/matrix[$N, N]$E) -> (c: M)
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check { where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
return a * b return a * b
} }
matrix_comp_mul :: proc(a, b: $M/matrix[$I, $J]$E) -> (c: M) @(require_results)
matrix_comp_mul :: proc "contextless" (a, b: $M/matrix[$I, $J]$E) -> (c: M)
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check { where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
return hadamard_product(a, b) return hadamard_product(a, b)
} }
matrix_mul_differ :: proc(a: $A/matrix[$I, $J]$E, b: $B/matrix[J, $K]E) -> (c: matrix[I, K]E) @(require_results)
matrix_mul_differ :: proc "contextless" (a: $A/matrix[$I, $J]$E, b: $B/matrix[J, $K]E) -> (c: matrix[I, K]E)
where !IS_ARRAY(E), IS_NUMERIC(E), I != K #no_bounds_check { where !IS_ARRAY(E), IS_NUMERIC(E), I != K #no_bounds_check {
return a * b return a * b
} }
matrix_mul_vector :: proc(a: $A/matrix[$I, $J]$E, b: $B/[J]E) -> (c: B) @(require_results)
matrix_mul_vector :: proc "contextless" (a: $A/matrix[$I, $J]$E, b: $B/[J]E) -> (c: B)
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check { where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
return a * b return a * b
} }
quaternion_mul_quaternion :: proc(q1, q2: $Q) -> Q where IS_QUATERNION(Q) { @(require_results)
quaternion_mul_quaternion :: proc "contextless" (q1, q2: $Q) -> Q where IS_QUATERNION(Q) {
return q1 * q2 return q1 * q2
} }
quaternion64_mul_vector3 :: proc(q: $Q/quaternion64, v: $V/[3]$F/f16) -> V { @(require_results)
quaternion64_mul_vector3 :: proc "contextless" (q: $Q/quaternion64, v: $V/[3]$F/f16) -> V {
Raw_Quaternion :: struct {xyz: [3]f16, r: f16} Raw_Quaternion :: struct {xyz: [3]f16, r: f16}
q := transmute(Raw_Quaternion)q q := transmute(Raw_Quaternion)q
@@ -194,7 +222,8 @@ quaternion64_mul_vector3 :: proc(q: $Q/quaternion64, v: $V/[3]$F/f16) -> V {
t := cross(2*q.xyz, v) t := cross(2*q.xyz, v)
return V(v + q.r*t + cross(q.xyz, t)) return V(v + q.r*t + cross(q.xyz, t))
} }
quaternion128_mul_vector3 :: proc(q: $Q/quaternion128, v: $V/[3]$F/f32) -> V { @(require_results)
quaternion128_mul_vector3 :: proc "contextless" (q: $Q/quaternion128, v: $V/[3]$F/f32) -> V {
Raw_Quaternion :: struct {xyz: [3]f32, r: f32} Raw_Quaternion :: struct {xyz: [3]f32, r: f32}
q := transmute(Raw_Quaternion)q q := transmute(Raw_Quaternion)q
@@ -203,7 +232,8 @@ quaternion128_mul_vector3 :: proc(q: $Q/quaternion128, v: $V/[3]$F/f32) -> V {
t := cross(2*q.xyz, v) t := cross(2*q.xyz, v)
return V(v + q.r*t + cross(q.xyz, t)) return V(v + q.r*t + cross(q.xyz, t))
} }
quaternion256_mul_vector3 :: proc(q: $Q/quaternion256, v: $V/[3]$F/f64) -> V { @(require_results)
quaternion256_mul_vector3 :: proc "contextless" (q: $Q/quaternion256, v: $V/[3]$F/f64) -> V {
Raw_Quaternion :: struct {xyz: [3]f64, r: f64} Raw_Quaternion :: struct {xyz: [3]f64, r: f64}
q := transmute(Raw_Quaternion)q q := transmute(Raw_Quaternion)q
@@ -224,10 +254,12 @@ mul :: proc{
quaternion_mul_quaternion, quaternion_mul_quaternion,
} }
vector_to_ptr :: proc(v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check { @(require_results)
vector_to_ptr :: proc "contextless" (v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check {
return &v[0] return &v[0]
} }
matrix_to_ptr :: proc(m: ^$A/matrix[$I, $J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check { @(require_results)
matrix_to_ptr :: proc "contextless" (m: ^$A/matrix[$I, $J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check {
return &m[0, 0] return &m[0, 0]
} }
@@ -239,7 +271,8 @@ to_ptr :: proc{vector_to_ptr, matrix_to_ptr}
// Splines // Splines
vector_slerp :: proc(x, y: $T/[$N]$E, a: E) -> T { @(require_results)
vector_slerp :: proc "contextless" (x, y: $T/[$N]$E, a: E) -> T {
cos_alpha := dot(x, y) cos_alpha := dot(x, y)
alpha := math.acos(cos_alpha) alpha := math.acos(cos_alpha)
sin_alpha := math.sin(alpha) sin_alpha := math.sin(alpha)
@@ -250,7 +283,8 @@ vector_slerp :: proc(x, y: $T/[$N]$E, a: E) -> T {
return x * t1 + y * t2 return x * t1 + y * t2
} }
catmull_rom :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T { @(require_results)
catmull_rom :: proc "contextless" (v1, v2, v3, v4: $T/[$N]$E, s: E) -> T {
s2 := s*s s2 := s*s
s3 := s2*s s3 := s2*s
@@ -262,7 +296,8 @@ catmull_rom :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T {
return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) * 0.5 return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) * 0.5
} }
hermite :: proc(v1, t1, v2, t2: $T/[$N]$E, s: E) -> T { @(require_results)
hermite :: proc "contextless" (v1, t1, v2, t2: $T/[$N]$E, s: E) -> T {
s2 := s*s s2 := s*s
s3 := s2*s s3 := s2*s
@@ -274,20 +309,23 @@ hermite :: proc(v1, t1, v2, t2: $T/[$N]$E, s: E) -> T {
return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2 return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2
} }
cubic :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T { @(require_results)
cubic :: proc "contextless" (v1, v2, v3, v4: $T/[$N]$E, s: E) -> T {
return ((v1 * s + v2) * s + v3) * s + v4 return ((v1 * s + v2) * s + v3) * s + v4
} }
array_cast :: proc(v: $A/[$N]$T, $Elem_Type: typeid) -> (w: [N]Elem_Type) #no_bounds_check { @(require_results)
array_cast :: proc "contextless" (v: $A/[$N]$T, $Elem_Type: typeid) -> (w: [N]Elem_Type) #no_bounds_check {
for i in 0..<N { for i in 0..<N {
w[i] = Elem_Type(v[i]) w[i] = Elem_Type(v[i])
} }
return return
} }
matrix_cast :: proc(v: $A/matrix[$M, $N]$T, $Elem_Type: typeid) -> (w: matrix[M, N]Elem_Type) #no_bounds_check { @(require_results)
matrix_cast :: proc "contextless" (v: $A/matrix[$M, $N]$T, $Elem_Type: typeid) -> (w: matrix[M, N]Elem_Type) #no_bounds_check {
for j in 0..<N { for j in 0..<N {
for i in 0..<M { for i in 0..<M {
w[i, j] = Elem_Type(v[i, j]) w[i, j] = Elem_Type(v[i, j])
@@ -296,24 +334,24 @@ matrix_cast :: proc(v: $A/matrix[$M, $N]$T, $Elem_Type: typeid) -> (w: matrix[M,
return return
} }
to_f32 :: #force_inline proc(v: $A/[$N]$T) -> [N]f32 { return array_cast(v, f32) } @(require_results) to_f32 :: #force_inline proc(v: $A/[$N]$T) -> [N]f32 { return array_cast(v, f32) }
to_f64 :: #force_inline proc(v: $A/[$N]$T) -> [N]f64 { return array_cast(v, f64) } @(require_results) to_f64 :: #force_inline proc(v: $A/[$N]$T) -> [N]f64 { return array_cast(v, f64) }
to_i8 :: #force_inline proc(v: $A/[$N]$T) -> [N]i8 { return array_cast(v, i8) } @(require_results) to_i8 :: #force_inline proc(v: $A/[$N]$T) -> [N]i8 { return array_cast(v, i8) }
to_i16 :: #force_inline proc(v: $A/[$N]$T) -> [N]i16 { return array_cast(v, i16) } @(require_results) to_i16 :: #force_inline proc(v: $A/[$N]$T) -> [N]i16 { return array_cast(v, i16) }
to_i32 :: #force_inline proc(v: $A/[$N]$T) -> [N]i32 { return array_cast(v, i32) } @(require_results) to_i32 :: #force_inline proc(v: $A/[$N]$T) -> [N]i32 { return array_cast(v, i32) }
to_i64 :: #force_inline proc(v: $A/[$N]$T) -> [N]i64 { return array_cast(v, i64) } @(require_results) to_i64 :: #force_inline proc(v: $A/[$N]$T) -> [N]i64 { return array_cast(v, i64) }
to_int :: #force_inline proc(v: $A/[$N]$T) -> [N]int { return array_cast(v, int) } @(require_results) to_int :: #force_inline proc(v: $A/[$N]$T) -> [N]int { return array_cast(v, int) }
to_u8 :: #force_inline proc(v: $A/[$N]$T) -> [N]u8 { return array_cast(v, u8) } @(require_results) to_u8 :: #force_inline proc(v: $A/[$N]$T) -> [N]u8 { return array_cast(v, u8) }
to_u16 :: #force_inline proc(v: $A/[$N]$T) -> [N]u16 { return array_cast(v, u16) } @(require_results) to_u16 :: #force_inline proc(v: $A/[$N]$T) -> [N]u16 { return array_cast(v, u16) }
to_u32 :: #force_inline proc(v: $A/[$N]$T) -> [N]u32 { return array_cast(v, u32) } @(require_results) to_u32 :: #force_inline proc(v: $A/[$N]$T) -> [N]u32 { return array_cast(v, u32) }
to_u64 :: #force_inline proc(v: $A/[$N]$T) -> [N]u64 { return array_cast(v, u64) } @(require_results) to_u64 :: #force_inline proc(v: $A/[$N]$T) -> [N]u64 { return array_cast(v, u64) }
to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return array_cast(v, uint) } @(require_results) to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return array_cast(v, uint) }
to_complex32 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex32 { return array_cast(v, complex32) } @(require_results) to_complex32 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex32 { return array_cast(v, complex32) }
to_complex64 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64 { return array_cast(v, complex64) } @(require_results) to_complex64 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64 { return array_cast(v, complex64) }
to_complex128 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128 { return array_cast(v, complex128) } @(require_results) to_complex128 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128 { return array_cast(v, complex128) }
to_quaternion64 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return array_cast(v, quaternion64) } @(require_results) to_quaternion64 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return array_cast(v, quaternion64) }
to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128) } @(require_results) to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128) }
to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256) } @(require_results) to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256) }
File diff suppressed because it is too large Load Diff
+50 -48
View File
@@ -2,30 +2,31 @@ package math_linalg_glsl
import "core:math" import "core:math"
cos_f32 :: proc "c" (x: f32) -> f32 { return math.cos(x) } @(require_results) cos_f32 :: proc "c" (x: f32) -> f32 { return math.cos(x) }
sin_f32 :: proc "c" (x: f32) -> f32 { return math.sin(x) } @(require_results) sin_f32 :: proc "c" (x: f32) -> f32 { return math.sin(x) }
tan_f32 :: proc "c" (x: f32) -> f32 { return math.tan(x) } @(require_results) tan_f32 :: proc "c" (x: f32) -> f32 { return math.tan(x) }
acos_f32 :: proc "c" (x: f32) -> f32 { return math.acos(x) } @(require_results) acos_f32 :: proc "c" (x: f32) -> f32 { return math.acos(x) }
asin_f32 :: proc "c" (x: f32) -> f32 { return math.asin(x) } @(require_results) asin_f32 :: proc "c" (x: f32) -> f32 { return math.asin(x) }
atan_f32 :: proc "c" (x: f32) -> f32 { return math.atan(x) } @(require_results) atan_f32 :: proc "c" (x: f32) -> f32 { return math.atan(x) }
atan2_f32 :: proc "c" (y, x: f32) -> f32 { return math.atan2(y, x) } @(require_results) atan2_f32 :: proc "c" (y, x: f32) -> f32 { return math.atan2(y, x) }
cosh_f32 :: proc "c" (x: f32) -> f32 { return math.cosh(x) } @(require_results) cosh_f32 :: proc "c" (x: f32) -> f32 { return math.cosh(x) }
sinh_f32 :: proc "c" (x: f32) -> f32 { return math.sinh(x) } @(require_results) sinh_f32 :: proc "c" (x: f32) -> f32 { return math.sinh(x) }
tanh_f32 :: proc "c" (x: f32) -> f32 { return math.tanh(x) } @(require_results) tanh_f32 :: proc "c" (x: f32) -> f32 { return math.tanh(x) }
acosh_f32 :: proc "c" (x: f32) -> f32 { return math.acosh(x) } @(require_results) acosh_f32 :: proc "c" (x: f32) -> f32 { return math.acosh(x) }
asinh_f32 :: proc "c" (x: f32) -> f32 { return math.asinh(x) } @(require_results) asinh_f32 :: proc "c" (x: f32) -> f32 { return math.asinh(x) }
atanh_f32 :: proc "c" (x: f32) -> f32 { return math.atanh(x) } @(require_results) atanh_f32 :: proc "c" (x: f32) -> f32 { return math.atanh(x) }
sqrt_f32 :: proc "c" (x: f32) -> f32 { return math.sqrt(x) } @(require_results) sqrt_f32 :: proc "c" (x: f32) -> f32 { return math.sqrt(x) }
inversesqrt_f32 :: proc "c" (x: f32) -> f32 { return 1.0/math.sqrt(x) } @(require_results) inversesqrt_f32 :: proc "c" (x: f32) -> f32 { return 1.0/math.sqrt(x) }
pow_f32 :: proc "c" (x, y: f32) -> f32 { return math.pow(x, y) } @(require_results) pow_f32 :: proc "c" (x, y: f32) -> f32 { return math.pow(x, y) }
exp_f32 :: proc "c" (x: f32) -> f32 { return math.exp(x) } @(require_results) exp_f32 :: proc "c" (x: f32) -> f32 { return math.exp(x) }
log_f32 :: proc "c" (x: f32) -> f32 { return math.ln(x) } @(require_results) log_f32 :: proc "c" (x: f32) -> f32 { return math.ln(x) }
exp2_f32 :: proc "c" (x: f32) -> f32 { return math.pow(f32(2), x) } @(require_results) exp2_f32 :: proc "c" (x: f32) -> f32 { return math.pow(f32(2), x) }
sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) } @(require_results) sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) }
floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) } @(require_results) floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) }
round_f32 :: proc "c" (x: f32) -> f32 { return math.round(x) } @(require_results) round_f32 :: proc "c" (x: f32) -> f32 { return math.round(x) }
ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) } @(require_results) ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) }
mod_f32 :: proc "c" (x, y: f32) -> f32 { return math.mod(x, y) } @(require_results) mod_f32 :: proc "c" (x, y: f32) -> f32 { return math.mod(x, y) }
@(require_results)
fract_f32 :: proc "c" (x: f32) -> f32 { fract_f32 :: proc "c" (x: f32) -> f32 {
if x >= 0 { if x >= 0 {
return x - math.trunc(x) return x - math.trunc(x)
@@ -33,30 +34,31 @@ fract_f32 :: proc "c" (x: f32) -> f32 {
return math.trunc(-x) + x return math.trunc(-x) + x
} }
cos_f64 :: proc "c" (x: f64) -> f64 { return math.cos(x) } @(require_results) cos_f64 :: proc "c" (x: f64) -> f64 { return math.cos(x) }
sin_f64 :: proc "c" (x: f64) -> f64 { return math.sin(x) } @(require_results) sin_f64 :: proc "c" (x: f64) -> f64 { return math.sin(x) }
tan_f64 :: proc "c" (x: f64) -> f64 { return math.tan(x) } @(require_results) tan_f64 :: proc "c" (x: f64) -> f64 { return math.tan(x) }
acos_f64 :: proc "c" (x: f64) -> f64 { return math.acos(x) } @(require_results) acos_f64 :: proc "c" (x: f64) -> f64 { return math.acos(x) }
asin_f64 :: proc "c" (x: f64) -> f64 { return math.asin(x) } @(require_results) asin_f64 :: proc "c" (x: f64) -> f64 { return math.asin(x) }
atan_f64 :: proc "c" (x: f64) -> f64 { return math.atan(x) } @(require_results) atan_f64 :: proc "c" (x: f64) -> f64 { return math.atan(x) }
atan2_f64 :: proc "c" (y, x: f64) -> f64 { return math.atan2(y, x) } @(require_results) atan2_f64 :: proc "c" (y, x: f64) -> f64 { return math.atan2(y, x) }
cosh_f64 :: proc "c" (x: f64) -> f64 { return math.cosh(x) } @(require_results) cosh_f64 :: proc "c" (x: f64) -> f64 { return math.cosh(x) }
sinh_f64 :: proc "c" (x: f64) -> f64 { return math.sinh(x) } @(require_results) sinh_f64 :: proc "c" (x: f64) -> f64 { return math.sinh(x) }
tanh_f64 :: proc "c" (x: f64) -> f64 { return math.tanh(x) } @(require_results) tanh_f64 :: proc "c" (x: f64) -> f64 { return math.tanh(x) }
acosh_f64 :: proc "c" (x: f64) -> f64 { return math.acosh(x) } @(require_results) acosh_f64 :: proc "c" (x: f64) -> f64 { return math.acosh(x) }
asinh_f64 :: proc "c" (x: f64) -> f64 { return math.asinh(x) } @(require_results) asinh_f64 :: proc "c" (x: f64) -> f64 { return math.asinh(x) }
atanh_f64 :: proc "c" (x: f64) -> f64 { return math.atanh(x) } @(require_results) atanh_f64 :: proc "c" (x: f64) -> f64 { return math.atanh(x) }
sqrt_f64 :: proc "c" (x: f64) -> f64 { return math.sqrt(x) } @(require_results) sqrt_f64 :: proc "c" (x: f64) -> f64 { return math.sqrt(x) }
inversesqrt_f64 :: proc "c" (x: f64) -> f64 { return 1.0/math.sqrt(x) } @(require_results) inversesqrt_f64 :: proc "c" (x: f64) -> f64 { return 1.0/math.sqrt(x) }
pow_f64 :: proc "c" (x, y: f64) -> f64 { return math.pow(x, y) } @(require_results) pow_f64 :: proc "c" (x, y: f64) -> f64 { return math.pow(x, y) }
exp_f64 :: proc "c" (x: f64) -> f64 { return math.exp(x) } @(require_results) exp_f64 :: proc "c" (x: f64) -> f64 { return math.exp(x) }
log_f64 :: proc "c" (x: f64) -> f64 { return math.ln(x) } @(require_results) log_f64 :: proc "c" (x: f64) -> f64 { return math.ln(x) }
exp2_f64 :: proc "c" (x: f64) -> f64 { return math.pow(f64(2), x) } @(require_results) exp2_f64 :: proc "c" (x: f64) -> f64 { return math.pow(f64(2), x) }
sign_f64 :: proc "c" (x: f64) -> f64 { return math.sign(x) } @(require_results) sign_f64 :: proc "c" (x: f64) -> f64 { return math.sign(x) }
floor_f64 :: proc "c" (x: f64) -> f64 { return math.floor(x) } @(require_results) floor_f64 :: proc "c" (x: f64) -> f64 { return math.floor(x) }
round_f64 :: proc "c" (x: f64) -> f64 { return math.round(x) } @(require_results) round_f64 :: proc "c" (x: f64) -> f64 { return math.round(x) }
ceil_f64 :: proc "c" (x: f64) -> f64 { return math.ceil(x) } @(require_results) ceil_f64 :: proc "c" (x: f64) -> f64 { return math.ceil(x) }
mod_f64 :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) } @(require_results) mod_f64 :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) }
@(require_results)
fract_f64 :: proc "c" (x: f64) -> f64 { fract_f64 :: proc "c" (x: f64) -> f64 {
if x >= 0 { if x >= 0 {
return x - math.trunc(x) return x - math.trunc(x)
File diff suppressed because it is too large Load Diff
+58 -56
View File
@@ -2,34 +2,35 @@ package math_linalg_hlsl
import "core:math" import "core:math"
cos_float :: proc "c" (x: float) -> float { return math.cos(x) } @(require_results) cos_float :: proc "c" (x: float) -> float { return math.cos(x) }
sin_float :: proc "c" (x: float) -> float { return math.sin(x) } @(require_results) sin_float :: proc "c" (x: float) -> float { return math.sin(x) }
tan_float :: proc "c" (x: float) -> float { return math.tan(x) } @(require_results) tan_float :: proc "c" (x: float) -> float { return math.tan(x) }
acos_float :: proc "c" (x: float) -> float { return math.acos(x) } @(require_results) acos_float :: proc "c" (x: float) -> float { return math.acos(x) }
asin_float :: proc "c" (x: float) -> float { return math.asin(x) } @(require_results) asin_float :: proc "c" (x: float) -> float { return math.asin(x) }
atan_float :: proc "c" (x: float) -> float { return math.atan(x) } @(require_results) atan_float :: proc "c" (x: float) -> float { return math.atan(x) }
atan2_float :: proc "c" (y, x: float) -> float { return math.atan2(y, x) } @(require_results) atan2_float :: proc "c" (y, x: float) -> float { return math.atan2(y, x) }
cosh_float :: proc "c" (x: float) -> float { return math.cosh(x) } @(require_results) cosh_float :: proc "c" (x: float) -> float { return math.cosh(x) }
sinh_float :: proc "c" (x: float) -> float { return math.sinh(x) } @(require_results) sinh_float :: proc "c" (x: float) -> float { return math.sinh(x) }
tanh_float :: proc "c" (x: float) -> float { return math.tanh(x) } @(require_results) tanh_float :: proc "c" (x: float) -> float { return math.tanh(x) }
acosh_float :: proc "c" (x: float) -> float { return math.acosh(x) } @(require_results) acosh_float :: proc "c" (x: float) -> float { return math.acosh(x) }
asinh_float :: proc "c" (x: float) -> float { return math.asinh(x) } @(require_results) asinh_float :: proc "c" (x: float) -> float { return math.asinh(x) }
atanh_float :: proc "c" (x: float) -> float { return math.atanh(x) } @(require_results) atanh_float :: proc "c" (x: float) -> float { return math.atanh(x) }
sqrt_float :: proc "c" (x: float) -> float { return math.sqrt(x) } @(require_results) sqrt_float :: proc "c" (x: float) -> float { return math.sqrt(x) }
rsqrt_float :: proc "c" (x: float) -> float { return 1.0/math.sqrt(x) } @(require_results) rsqrt_float :: proc "c" (x: float) -> float { return 1.0/math.sqrt(x) }
rcp_float :: proc "c" (x: float) -> float { return 1.0/x } @(require_results) rcp_float :: proc "c" (x: float) -> float { return 1.0/x }
pow_float :: proc "c" (x, y: float) -> float { return math.pow(x, y) } @(require_results) pow_float :: proc "c" (x, y: float) -> float { return math.pow(x, y) }
exp_float :: proc "c" (x: float) -> float { return math.exp(x) } @(require_results) exp_float :: proc "c" (x: float) -> float { return math.exp(x) }
log_float :: proc "c" (x: float) -> float { return math.ln(x) } @(require_results) log_float :: proc "c" (x: float) -> float { return math.ln(x) }
log2_float :: proc "c" (x: float) -> float { return math.log(x, 2) } @(require_results) log2_float :: proc "c" (x: float) -> float { return math.log(x, 2) }
log10_float :: proc "c" (x: float) -> float { return math.log(x, 10) } @(require_results) log10_float :: proc "c" (x: float) -> float { return math.log(x, 10) }
exp2_float :: proc "c" (x: float) -> float { return math.pow(float(2), x) } @(require_results) exp2_float :: proc "c" (x: float) -> float { return math.pow(float(2), x) }
sign_float :: proc "c" (x: float) -> float { return math.sign(x) } @(require_results) sign_float :: proc "c" (x: float) -> float { return math.sign(x) }
floor_float :: proc "c" (x: float) -> float { return math.floor(x) } @(require_results) floor_float :: proc "c" (x: float) -> float { return math.floor(x) }
round_float :: proc "c" (x: float) -> float { return math.round(x) } @(require_results) round_float :: proc "c" (x: float) -> float { return math.round(x) }
ceil_float :: proc "c" (x: float) -> float { return math.ceil(x) } @(require_results) ceil_float :: proc "c" (x: float) -> float { return math.ceil(x) }
isnan_float :: proc "c" (x: float) -> bool { return math.classify(x) == .NaN} @(require_results) isnan_float :: proc "c" (x: float) -> bool { return math.classify(x) == .NaN}
fmod_float :: proc "c" (x, y: float) -> float { return math.mod(x, y) } @(require_results) fmod_float :: proc "c" (x, y: float) -> float { return math.mod(x, y) }
@(require_results)
frac_float :: proc "c" (x: float) -> float { frac_float :: proc "c" (x: float) -> float {
if x >= 0 { if x >= 0 {
return x - math.trunc(x) return x - math.trunc(x)
@@ -38,34 +39,35 @@ frac_float :: proc "c" (x: float) -> float {
} }
cos_double :: proc "c" (x: double) -> double { return math.cos(x) } @(require_results) cos_double :: proc "c" (x: double) -> double { return math.cos(x) }
sin_double :: proc "c" (x: double) -> double { return math.sin(x) } @(require_results) sin_double :: proc "c" (x: double) -> double { return math.sin(x) }
tan_double :: proc "c" (x: double) -> double { return math.tan(x) } @(require_results) tan_double :: proc "c" (x: double) -> double { return math.tan(x) }
acos_double :: proc "c" (x: double) -> double { return math.acos(x) } @(require_results) acos_double :: proc "c" (x: double) -> double { return math.acos(x) }
asin_double :: proc "c" (x: double) -> double { return math.asin(x) } @(require_results) asin_double :: proc "c" (x: double) -> double { return math.asin(x) }
atan_double :: proc "c" (x: double) -> double { return math.atan(x) } @(require_results) atan_double :: proc "c" (x: double) -> double { return math.atan(x) }
atan2_double :: proc "c" (y, x: double) -> double { return math.atan2(y, x) } @(require_results) atan2_double :: proc "c" (y, x: double) -> double { return math.atan2(y, x) }
cosh_double :: proc "c" (x: double) -> double { return math.cosh(x) } @(require_results) cosh_double :: proc "c" (x: double) -> double { return math.cosh(x) }
sinh_double :: proc "c" (x: double) -> double { return math.sinh(x) } @(require_results) sinh_double :: proc "c" (x: double) -> double { return math.sinh(x) }
tanh_double :: proc "c" (x: double) -> double { return math.tanh(x) } @(require_results) tanh_double :: proc "c" (x: double) -> double { return math.tanh(x) }
acosh_double :: proc "c" (x: double) -> double { return math.acosh(x) } @(require_results) acosh_double :: proc "c" (x: double) -> double { return math.acosh(x) }
asinh_double :: proc "c" (x: double) -> double { return math.asinh(x) } @(require_results) asinh_double :: proc "c" (x: double) -> double { return math.asinh(x) }
atanh_double :: proc "c" (x: double) -> double { return math.atanh(x) } @(require_results) atanh_double :: proc "c" (x: double) -> double { return math.atanh(x) }
sqrt_double :: proc "c" (x: double) -> double { return math.sqrt(x) } @(require_results) sqrt_double :: proc "c" (x: double) -> double { return math.sqrt(x) }
rsqrt_double :: proc "c" (x: double) -> double { return 1.0/math.sqrt(x) } @(require_results) rsqrt_double :: proc "c" (x: double) -> double { return 1.0/math.sqrt(x) }
rcp_double :: proc "c" (x: double) -> double { return 1.0/x } @(require_results) rcp_double :: proc "c" (x: double) -> double { return 1.0/x }
pow_double :: proc "c" (x, y: double) -> double { return math.pow(x, y) } @(require_results) pow_double :: proc "c" (x, y: double) -> double { return math.pow(x, y) }
exp_double :: proc "c" (x: double) -> double { return math.exp(x) } @(require_results) exp_double :: proc "c" (x: double) -> double { return math.exp(x) }
log_double :: proc "c" (x: double) -> double { return math.ln(x) } @(require_results) log_double :: proc "c" (x: double) -> double { return math.ln(x) }
log2_double :: proc "c" (x: double) -> double { return math.log(x, 2) } @(require_results) log2_double :: proc "c" (x: double) -> double { return math.log(x, 2) }
log10_double :: proc "c" (x: double) -> double { return math.log(x, 10) } @(require_results) log10_double :: proc "c" (x: double) -> double { return math.log(x, 10) }
exp2_double :: proc "c" (x: double) -> double { return math.pow(double(2), x) } @(require_results) exp2_double :: proc "c" (x: double) -> double { return math.pow(double(2), x) }
sign_double :: proc "c" (x: double) -> double { return math.sign(x) } @(require_results) sign_double :: proc "c" (x: double) -> double { return math.sign(x) }
floor_double :: proc "c" (x: double) -> double { return math.floor(x) } @(require_results) floor_double :: proc "c" (x: double) -> double { return math.floor(x) }
round_double :: proc "c" (x: double) -> double { return math.round(x) } @(require_results) round_double :: proc "c" (x: double) -> double { return math.round(x) }
ceil_double :: proc "c" (x: double) -> double { return math.ceil(x) } @(require_results) ceil_double :: proc "c" (x: double) -> double { return math.ceil(x) }
isnan_double :: proc "c" (x: double) -> bool { return math.classify(x) == .NaN} @(require_results) isnan_double :: proc "c" (x: double) -> bool { return math.classify(x) == .NaN}
fmod_double :: proc "c" (x, y: double) -> double { return math.mod(x, y) } @(require_results) fmod_double :: proc "c" (x, y: double) -> double { return math.mod(x, y) }
@(require_results)
frac_double :: proc "c" (x: double) -> double { frac_double :: proc "c" (x: double) -> double {
if x >= 0 { if x >= 0 {
return x - math.trunc(x) return x - math.trunc(x)
File diff suppressed because it is too large Load Diff
+200 -100
View File
@@ -2,7 +2,8 @@ package linalg
import "core:math" import "core:math"
euler_angles_from_matrix3_f16 :: proc(m: Matrix3f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
switch order { switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m) case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m) case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m)
@@ -19,7 +20,8 @@ euler_angles_from_matrix3_f16 :: proc(m: Matrix3f16, order: Euler_Angle_Order) -
} }
return return
} }
euler_angles_from_matrix4_f16 :: proc(m: Matrix4f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
switch order { switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m) case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m) case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m)
@@ -36,7 +38,8 @@ euler_angles_from_matrix4_f16 :: proc(m: Matrix4f16, order: Euler_Angle_Order) -
} }
return return
} }
euler_angles_from_quaternion_f16 :: proc(m: Quaternionf16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_from_quaternion_f16 :: proc "contextless" (m: Quaternionf16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
switch order { switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m) case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m) case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m)
@@ -54,7 +57,8 @@ euler_angles_from_quaternion_f16 :: proc(m: Quaternionf16, order: Euler_Angle_Or
return return
} }
matrix3_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_f16 :: proc "contextless" (t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix3f16) {
switch order { switch order {
case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -71,7 +75,8 @@ matrix3_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order)
} }
return return
} }
matrix4_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_f16 :: proc "contextless" (t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix4f16) {
switch order { switch order {
case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -89,7 +94,8 @@ matrix4_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order)
return return
} }
quaternion_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> Quaternionf16 { @(require_results)
quaternion_from_euler_angles_f16 :: proc "contextless" (t1, t2, t3: f16, order: Euler_Angle_Order) -> Quaternionf16 {
X :: quaternion_from_euler_angle_x X :: quaternion_from_euler_angle_x
Y :: quaternion_from_euler_angle_y Y :: quaternion_from_euler_angle_y
Z :: quaternion_from_euler_angle_z Z :: quaternion_from_euler_angle_z
@@ -117,17 +123,21 @@ quaternion_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Ord
// Quaternionf16s // Quaternionf16s
quaternion_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (q: Quaternionf16) { @(require_results)
quaternion_from_euler_angle_x_f16 :: proc "contextless" (angle_x: f16) -> (q: Quaternionf16) {
return quaternion_angle_axis_f16(angle_x, {1, 0, 0}) return quaternion_angle_axis_f16(angle_x, {1, 0, 0})
} }
quaternion_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (q: Quaternionf16) { @(require_results)
quaternion_from_euler_angle_y_f16 :: proc "contextless" (angle_y: f16) -> (q: Quaternionf16) {
return quaternion_angle_axis_f16(angle_y, {0, 1, 0}) return quaternion_angle_axis_f16(angle_y, {0, 1, 0})
} }
quaternion_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (q: Quaternionf16) { @(require_results)
quaternion_from_euler_angle_z_f16 :: proc "contextless" (angle_z: f16) -> (q: Quaternionf16) {
return quaternion_angle_axis_f16(angle_z, {0, 0, 1}) return quaternion_angle_axis_f16(angle_z, {0, 0, 1})
} }
quaternion_from_pitch_yaw_roll_f16 :: proc(pitch, yaw, roll: f16) -> Quaternionf16 { @(require_results)
quaternion_from_pitch_yaw_roll_f16 :: proc "contextless" (pitch, yaw, roll: f16) -> Quaternionf16 {
a, b, c := pitch, yaw, roll a, b, c := pitch, yaw, roll
ca, sa := math.cos(a*0.5), math.sin(a*0.5) ca, sa := math.cos(a*0.5), math.sin(a*0.5)
@@ -142,11 +152,13 @@ quaternion_from_pitch_yaw_roll_f16 :: proc(pitch, yaw, roll: f16) -> Quaternionf
return q return q
} }
roll_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { @(require_results)
roll_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 {
return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z) return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z)
} }
pitch_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { @(require_results)
pitch_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 {
y := 2 * (q.y*q.z + q.w*q.w) y := 2 * (q.y*q.z + q.w*q.w)
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
@@ -157,52 +169,66 @@ pitch_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
return math.atan2(y, x) return math.atan2(y, x)
} }
yaw_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { @(require_results)
yaw_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 {
return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)) return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1))
} }
pitch_yaw_roll_from_quaternion_f16 :: proc(q: Quaternionf16) -> (pitch, yaw, roll: f16) { @(require_results)
pitch_yaw_roll_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (pitch, yaw, roll: f16) {
pitch = pitch_from_quaternion(q) pitch = pitch_from_quaternion(q)
yaw = yaw_from_quaternion(q) yaw = yaw_from_quaternion(q)
roll = roll_from_quaternion(q) roll = roll_from_quaternion(q)
return return
} }
euler_angles_xyz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xyz_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yxz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yxz_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_xzx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xzx_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_xyx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xyx_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yxy_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yzy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yzy_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zyz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zyz_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zxz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zxz_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_xzy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xzy_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yzx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yzx_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zyx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zyx_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zxy_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q))
} }
@@ -210,7 +236,8 @@ euler_angles_zxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f
// Matrix3 // Matrix3
matrix3_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angle_x_f16 :: proc "contextless" (angle_x: f16) -> (m: Matrix3f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1 m[0, 0] = 1
m[1, 1] = +cos_x m[1, 1] = +cos_x
@@ -219,7 +246,8 @@ matrix3_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix3f16) {
m[2, 2] = +cos_x m[2, 2] = +cos_x
return return
} }
matrix3_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angle_y_f16 :: proc "contextless" (angle_y: f16) -> (m: Matrix3f16) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y m[0, 0] = +cos_y
m[0, 2] = -sin_y m[0, 2] = -sin_y
@@ -228,7 +256,8 @@ matrix3_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix3f16) {
m[2, 2] = +cos_y m[2, 2] = +cos_y
return return
} }
matrix3_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angle_z_f16 :: proc "contextless" (angle_z: f16) -> (m: Matrix3f16) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z m[0, 0] = +cos_z
m[0, 1] = +sin_z m[0, 1] = +sin_z
@@ -239,7 +268,8 @@ matrix3_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix3f16) {
} }
matrix3_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_derived_euler_angle_x_f16 :: proc "contextless" (angle_x: f16, angular_velocity_x: f16) -> (m: Matrix3f16) {
cos_x := math.cos(angle_x) * angular_velocity_x cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1 m[0, 0] = 1
@@ -249,7 +279,8 @@ matrix3_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x:
m[2, 2] = +cos_x m[2, 2] = +cos_x
return return
} }
matrix3_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_derived_euler_angle_y_f16 :: proc "contextless" (angle_y: f16, angular_velocity_y: f16) -> (m: Matrix3f16) {
cos_y := math.cos(angle_y) * angular_velocity_y cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y m[0, 0] = +cos_y
@@ -259,7 +290,8 @@ matrix3_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y:
m[2, 2] = +cos_y m[2, 2] = +cos_y
return return
} }
matrix3_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_derived_euler_angle_z_f16 :: proc "contextless" (angle_z: f16, angular_velocity_z: f16) -> (m: Matrix3f16) {
cos_z := math.cos(angle_z) * angular_velocity_z cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z m[0, 0] = +cos_z
@@ -271,7 +303,8 @@ matrix3_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z:
} }
matrix3_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_xy_f16 :: proc "contextless" (angle_x, angle_y: f16) -> (m: Matrix3f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -286,7 +319,8 @@ matrix3_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix3f1
} }
matrix3_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_yx_f16 :: proc "contextless" (angle_y, angle_x: f16) -> (m: Matrix3f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -300,21 +334,26 @@ matrix3_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix3f1
return return
} }
matrix3_from_euler_angles_xz_f16 :: proc(angle_x, angle_z: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_xz_f16 :: proc "contextless" (angle_x, angle_z: f16) -> (m: Matrix3f16) {
return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)) return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z))
} }
matrix3_from_euler_angles_zx_f16 :: proc(angle_z, angle_x: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_zx_f16 :: proc "contextless" (angle_z, angle_x: f16) -> (m: Matrix3f16) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)) return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x))
} }
matrix3_from_euler_angles_yz_f16 :: proc(angle_y, angle_z: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_yz_f16 :: proc "contextless" (angle_y, angle_z: f16) -> (m: Matrix3f16) {
return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)) return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z))
} }
matrix3_from_euler_angles_zy_f16 :: proc(angle_z, angle_y: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_zy_f16 :: proc "contextless" (angle_z, angle_y: f16) -> (m: Matrix3f16) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)) return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y))
} }
matrix3_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_xyz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(-t1) c1 := math.cos(-t1)
c2 := math.cos(-t2) c2 := math.cos(-t2)
c3 := math.cos(-t3) c3 := math.cos(-t3)
@@ -334,7 +373,8 @@ matrix3_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return return
} }
matrix3_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_yxz_f16 :: proc "contextless" (yaw, pitch, roll: f16) -> (m: Matrix3f16) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -354,7 +394,8 @@ matrix3_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f
return return
} }
matrix3_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_xzx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -374,7 +415,8 @@ matrix3_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return return
} }
matrix3_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_xyx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -394,7 +436,8 @@ matrix3_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return return
} }
matrix3_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_yxy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -414,7 +457,8 @@ matrix3_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return return
} }
matrix3_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_yzy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -434,7 +478,8 @@ matrix3_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return return
} }
matrix3_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_zyz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -454,7 +499,8 @@ matrix3_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return return
} }
matrix3_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_zxz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -475,7 +521,8 @@ matrix3_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
} }
matrix3_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_xzy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -495,7 +542,8 @@ matrix3_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return return
} }
matrix3_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_yzx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -515,7 +563,8 @@ matrix3_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return return
} }
matrix3_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_zyx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -535,7 +584,8 @@ matrix3_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return return
} }
matrix3_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_euler_angles_zxy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -556,7 +606,8 @@ matrix3_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
} }
matrix3_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16) { @(require_results)
matrix3_from_yaw_pitch_roll_f16 :: proc "contextless" (yaw, pitch, roll: f16) -> (m: Matrix3f16) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -576,7 +627,8 @@ matrix3_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16
return m return m
} }
euler_angles_xyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xyz_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 2], m[2, 2]) T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2) T2 := math.atan2(-m[0, 2], C2)
@@ -589,7 +641,8 @@ euler_angles_xyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_yxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yxz_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 2], m[2, 2]) T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1]) C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2) T2 := math.atan2(-m[1, 2], C2)
@@ -602,7 +655,8 @@ euler_angles_yxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_xzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xzx_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 0], m[1, 0]) T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -615,7 +669,8 @@ euler_angles_xzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_xyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xyx_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 0], -m[2, 0]) T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -628,7 +683,8 @@ euler_angles_xyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_yxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yxy_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 1], m[2, 1]) T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -641,7 +697,8 @@ euler_angles_yxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_yzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yzy_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 1], -m[0, 1]) T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -653,7 +710,8 @@ euler_angles_yzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
t3 = T3 t3 = T3
return return
} }
euler_angles_zyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zyz_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 2], m[0, 2]) T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -666,7 +724,8 @@ euler_angles_zyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_zxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zxz_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 2], -m[1, 2]) T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -679,7 +738,8 @@ euler_angles_zxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_xzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xzy_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 1], m[1, 1]) T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2) T2 := math.atan2(-m[0, 1], C2)
@@ -692,7 +752,8 @@ euler_angles_xzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_yzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yzx_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(-m[2, 0], m[0, 0]) T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2]) C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2) T2 := math.atan2(m[1, 0], C2)
@@ -705,7 +766,8 @@ euler_angles_yzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_zyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zyx_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 0], m[0, 0]) T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2) T2 := math.atan2(-m[2, 0], C2)
@@ -718,7 +780,8 @@ euler_angles_zyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_zxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zxy_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(-m[0, 1], m[1, 1]) T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2) T2 := math.atan2(m[2, 1], C2)
@@ -735,7 +798,8 @@ euler_angles_zxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
// Matrix4 // Matrix4
matrix4_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angle_x_f16 :: proc "contextless" (angle_x: f16) -> (m: Matrix4f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1 m[0, 0] = 1
m[1, 1] = +cos_x m[1, 1] = +cos_x
@@ -745,7 +809,8 @@ matrix4_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix4f16) {
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angle_y_f16 :: proc "contextless" (angle_y: f16) -> (m: Matrix4f16) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y m[0, 0] = +cos_y
m[0, 2] = -sin_y m[0, 2] = -sin_y
@@ -755,7 +820,8 @@ matrix4_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix4f16) {
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angle_z_f16 :: proc "contextless" (angle_z: f16) -> (m: Matrix4f16) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z m[0, 0] = +cos_z
m[0, 1] = +sin_z m[0, 1] = +sin_z
@@ -767,7 +833,8 @@ matrix4_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix4f16) {
} }
matrix4_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_derived_euler_angle_x_f16 :: proc "contextless" (angle_x: f16, angular_velocity_x: f16) -> (m: Matrix4f16) {
cos_x := math.cos(angle_x) * angular_velocity_x cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1 m[0, 0] = 1
@@ -778,7 +845,8 @@ matrix4_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x:
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_derived_euler_angle_y_f16 :: proc "contextless" (angle_y: f16, angular_velocity_y: f16) -> (m: Matrix4f16) {
cos_y := math.cos(angle_y) * angular_velocity_y cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y m[0, 0] = +cos_y
@@ -789,7 +857,8 @@ matrix4_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y:
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_derived_euler_angle_z_f16 :: proc "contextless" (angle_z: f16, angular_velocity_z: f16) -> (m: Matrix4f16) {
cos_z := math.cos(angle_z) * angular_velocity_z cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z m[0, 0] = +cos_z
@@ -802,7 +871,8 @@ matrix4_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z:
} }
matrix4_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_xy_f16 :: proc "contextless" (angle_x, angle_y: f16) -> (m: Matrix4f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -818,7 +888,8 @@ matrix4_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix4f1
} }
matrix4_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_yx_f16 :: proc "contextless" (angle_y, angle_x: f16) -> (m: Matrix4f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -833,21 +904,26 @@ matrix4_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix4f1
return return
} }
matrix4_from_euler_angles_xz_f16 :: proc(angle_x, angle_z: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_xz_f16 :: proc "contextless" (angle_x, angle_z: f16) -> (m: Matrix4f16) {
return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)) return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z))
} }
matrix4_from_euler_angles_zx_f16 :: proc(angle_z, angle_x: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_zx_f16 :: proc "contextless" (angle_z, angle_x: f16) -> (m: Matrix4f16) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)) return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x))
} }
matrix4_from_euler_angles_yz_f16 :: proc(angle_y, angle_z: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_yz_f16 :: proc "contextless" (angle_y, angle_z: f16) -> (m: Matrix4f16) {
return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)) return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z))
} }
matrix4_from_euler_angles_zy_f16 :: proc(angle_z, angle_y: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_zy_f16 :: proc "contextless" (angle_z, angle_y: f16) -> (m: Matrix4f16) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)) return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y))
} }
matrix4_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_xyz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(-t1) c1 := math.cos(-t1)
c2 := math.cos(-t2) c2 := math.cos(-t2)
c3 := math.cos(-t3) c3 := math.cos(-t3)
@@ -874,7 +950,8 @@ matrix4_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return return
} }
matrix4_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_yxz_f16 :: proc "contextless" (yaw, pitch, roll: f16) -> (m: Matrix4f16) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -901,7 +978,8 @@ matrix4_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f
return return
} }
matrix4_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_xzx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -928,7 +1006,8 @@ matrix4_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return return
} }
matrix4_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_xyx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -955,7 +1034,8 @@ matrix4_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return return
} }
matrix4_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_yxy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -982,7 +1062,8 @@ matrix4_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return return
} }
matrix4_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_yzy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1009,7 +1090,8 @@ matrix4_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return return
} }
matrix4_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_zyz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1036,7 +1118,8 @@ matrix4_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return return
} }
matrix4_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_zxz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1064,7 +1147,8 @@ matrix4_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
} }
matrix4_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_xzy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1091,7 +1175,8 @@ matrix4_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return return
} }
matrix4_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_yzx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1118,7 +1203,8 @@ matrix4_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return return
} }
matrix4_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_zyx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1145,7 +1231,8 @@ matrix4_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return return
} }
matrix4_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_euler_angles_zxy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1173,7 +1260,8 @@ matrix4_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
} }
matrix4_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16) { @(require_results)
matrix4_from_yaw_pitch_roll_f16 :: proc "contextless" (yaw, pitch, roll: f16) -> (m: Matrix4f16) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -1200,7 +1288,8 @@ matrix4_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16
return m return m
} }
euler_angles_xyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xyz_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 2], m[2, 2]) T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2) T2 := math.atan2(-m[0, 2], C2)
@@ -1213,7 +1302,8 @@ euler_angles_xyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_yxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yxz_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 2], m[2, 2]) T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1]) C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2) T2 := math.atan2(-m[1, 2], C2)
@@ -1226,7 +1316,8 @@ euler_angles_yxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_xzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xzx_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 0], m[1, 0]) T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -1239,7 +1330,8 @@ euler_angles_xzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_xyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xyx_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 0], -m[2, 0]) T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -1252,7 +1344,8 @@ euler_angles_xyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_yxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yxy_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 1], m[2, 1]) T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -1265,7 +1358,8 @@ euler_angles_yxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_yzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yzy_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 1], -m[0, 1]) T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -1277,7 +1371,8 @@ euler_angles_yzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
t3 = T3 t3 = T3
return return
} }
euler_angles_zyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zyz_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 2], m[0, 2]) T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -1290,7 +1385,8 @@ euler_angles_zyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_zxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zxz_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 2], -m[1, 2]) T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -1303,7 +1399,8 @@ euler_angles_zxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_xzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_xzy_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 1], m[1, 1]) T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2) T2 := math.atan2(-m[0, 1], C2)
@@ -1316,7 +1413,8 @@ euler_angles_xzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_yzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_yzx_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(-m[2, 0], m[0, 0]) T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2]) C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2) T2 := math.atan2(m[1, 0], C2)
@@ -1329,7 +1427,8 @@ euler_angles_yzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_zyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zyx_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 0], m[0, 0]) T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2) T2 := math.atan2(-m[2, 0], C2)
@@ -1342,7 +1441,8 @@ euler_angles_zyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return return
} }
euler_angles_zxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { @(require_results)
euler_angles_zxy_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(-m[0, 1], m[1, 1]) T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2) T2 := math.atan2(m[2, 1], C2)
+200 -100
View File
@@ -2,7 +2,8 @@ package linalg
import "core:math" import "core:math"
euler_angles_from_matrix3_f32 :: proc(m: Matrix3f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) {
switch order { switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m) case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m) case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m)
@@ -19,7 +20,8 @@ euler_angles_from_matrix3_f32 :: proc(m: Matrix3f32, order: Euler_Angle_Order) -
} }
return return
} }
euler_angles_from_matrix4_f32 :: proc(m: Matrix4f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) {
switch order { switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m) case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m) case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m)
@@ -36,7 +38,8 @@ euler_angles_from_matrix4_f32 :: proc(m: Matrix4f32, order: Euler_Angle_Order) -
} }
return return
} }
euler_angles_from_quaternion_f32 :: proc(m: Quaternionf32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_from_quaternion_f32 :: proc "contextless" (m: Quaternionf32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) {
switch order { switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m) case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m) case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m)
@@ -54,7 +57,8 @@ euler_angles_from_quaternion_f32 :: proc(m: Quaternionf32, order: Euler_Angle_Or
return return
} }
matrix3_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_f32 :: proc "contextless" (t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix3f32) {
switch order { switch order {
case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -71,7 +75,8 @@ matrix3_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order)
} }
return return
} }
matrix4_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_f32 :: proc "contextless" (t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix4f32) {
switch order { switch order {
case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -89,7 +94,8 @@ matrix4_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order)
return return
} }
quaternion_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> Quaternionf32 { @(require_results)
quaternion_from_euler_angles_f32 :: proc "contextless" (t1, t2, t3: f32, order: Euler_Angle_Order) -> Quaternionf32 {
X :: quaternion_from_euler_angle_x X :: quaternion_from_euler_angle_x
Y :: quaternion_from_euler_angle_y Y :: quaternion_from_euler_angle_y
Z :: quaternion_from_euler_angle_z Z :: quaternion_from_euler_angle_z
@@ -117,17 +123,21 @@ quaternion_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Ord
// Quaternionf32s // Quaternionf32s
quaternion_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (q: Quaternionf32) { @(require_results)
quaternion_from_euler_angle_x_f32 :: proc "contextless" (angle_x: f32) -> (q: Quaternionf32) {
return quaternion_angle_axis_f32(angle_x, {1, 0, 0}) return quaternion_angle_axis_f32(angle_x, {1, 0, 0})
} }
quaternion_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (q: Quaternionf32) { @(require_results)
quaternion_from_euler_angle_y_f32 :: proc "contextless" (angle_y: f32) -> (q: Quaternionf32) {
return quaternion_angle_axis_f32(angle_y, {0, 1, 0}) return quaternion_angle_axis_f32(angle_y, {0, 1, 0})
} }
quaternion_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (q: Quaternionf32) { @(require_results)
quaternion_from_euler_angle_z_f32 :: proc "contextless" (angle_z: f32) -> (q: Quaternionf32) {
return quaternion_angle_axis_f32(angle_z, {0, 0, 1}) return quaternion_angle_axis_f32(angle_z, {0, 0, 1})
} }
quaternion_from_pitch_yaw_roll_f32 :: proc(pitch, yaw, roll: f32) -> Quaternionf32 { @(require_results)
quaternion_from_pitch_yaw_roll_f32 :: proc "contextless" (pitch, yaw, roll: f32) -> Quaternionf32 {
a, b, c := pitch, yaw, roll a, b, c := pitch, yaw, roll
ca, sa := math.cos(a*0.5), math.sin(a*0.5) ca, sa := math.cos(a*0.5), math.sin(a*0.5)
@@ -142,11 +152,13 @@ quaternion_from_pitch_yaw_roll_f32 :: proc(pitch, yaw, roll: f32) -> Quaternionf
return q return q
} }
roll_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { @(require_results)
roll_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 {
return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z) return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z)
} }
pitch_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { @(require_results)
pitch_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 {
y := 2 * (q.y*q.z + q.w*q.w) y := 2 * (q.y*q.z + q.w*q.w)
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
@@ -157,52 +169,66 @@ pitch_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 {
return math.atan2(y, x) return math.atan2(y, x)
} }
yaw_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { @(require_results)
yaw_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 {
return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)) return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1))
} }
pitch_yaw_roll_from_quaternion_f32 :: proc(q: Quaternionf32) -> (pitch, yaw, roll: f32) { @(require_results)
pitch_yaw_roll_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (pitch, yaw, roll: f32) {
pitch = pitch_from_quaternion(q) pitch = pitch_from_quaternion(q)
yaw = yaw_from_quaternion(q) yaw = yaw_from_quaternion(q)
roll = roll_from_quaternion(q) roll = roll_from_quaternion(q)
return return
} }
euler_angles_xyz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xyz_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yxz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yxz_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_xzx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xzx_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_xyx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xyx_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yxy_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yzy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yzy_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zyz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zyz_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zxz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zxz_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_xzy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xzy_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yzx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yzx_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zyx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zyx_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zxy_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q))
} }
@@ -210,7 +236,8 @@ euler_angles_zxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f
// Matrix3 // Matrix3
matrix3_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angle_x_f32 :: proc "contextless" (angle_x: f32) -> (m: Matrix3f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1 m[0, 0] = 1
m[1, 1] = +cos_x m[1, 1] = +cos_x
@@ -219,7 +246,8 @@ matrix3_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix3f32) {
m[2, 2] = +cos_x m[2, 2] = +cos_x
return return
} }
matrix3_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angle_y_f32 :: proc "contextless" (angle_y: f32) -> (m: Matrix3f32) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y m[0, 0] = +cos_y
m[0, 2] = -sin_y m[0, 2] = -sin_y
@@ -228,7 +256,8 @@ matrix3_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix3f32) {
m[2, 2] = +cos_y m[2, 2] = +cos_y
return return
} }
matrix3_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angle_z_f32 :: proc "contextless" (angle_z: f32) -> (m: Matrix3f32) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z m[0, 0] = +cos_z
m[0, 1] = +sin_z m[0, 1] = +sin_z
@@ -239,7 +268,8 @@ matrix3_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix3f32) {
} }
matrix3_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_derived_euler_angle_x_f32 :: proc "contextless" (angle_x: f32, angular_velocity_x: f32) -> (m: Matrix3f32) {
cos_x := math.cos(angle_x) * angular_velocity_x cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1 m[0, 0] = 1
@@ -249,7 +279,8 @@ matrix3_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x:
m[2, 2] = +cos_x m[2, 2] = +cos_x
return return
} }
matrix3_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_derived_euler_angle_y_f32 :: proc "contextless" (angle_y: f32, angular_velocity_y: f32) -> (m: Matrix3f32) {
cos_y := math.cos(angle_y) * angular_velocity_y cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y m[0, 0] = +cos_y
@@ -259,7 +290,8 @@ matrix3_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y:
m[2, 2] = +cos_y m[2, 2] = +cos_y
return return
} }
matrix3_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_derived_euler_angle_z_f32 :: proc "contextless" (angle_z: f32, angular_velocity_z: f32) -> (m: Matrix3f32) {
cos_z := math.cos(angle_z) * angular_velocity_z cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z m[0, 0] = +cos_z
@@ -271,7 +303,8 @@ matrix3_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z:
} }
matrix3_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_xy_f32 :: proc "contextless" (angle_x, angle_y: f32) -> (m: Matrix3f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -286,7 +319,8 @@ matrix3_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix3f3
} }
matrix3_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_yx_f32 :: proc "contextless" (angle_y, angle_x: f32) -> (m: Matrix3f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -300,21 +334,26 @@ matrix3_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix3f3
return return
} }
matrix3_from_euler_angles_xz_f32 :: proc(angle_x, angle_z: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_xz_f32 :: proc "contextless" (angle_x, angle_z: f32) -> (m: Matrix3f32) {
return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)) return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z))
} }
matrix3_from_euler_angles_zx_f32 :: proc(angle_z, angle_x: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_zx_f32 :: proc "contextless" (angle_z, angle_x: f32) -> (m: Matrix3f32) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)) return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x))
} }
matrix3_from_euler_angles_yz_f32 :: proc(angle_y, angle_z: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_yz_f32 :: proc "contextless" (angle_y, angle_z: f32) -> (m: Matrix3f32) {
return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)) return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z))
} }
matrix3_from_euler_angles_zy_f32 :: proc(angle_z, angle_y: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_zy_f32 :: proc "contextless" (angle_z, angle_y: f32) -> (m: Matrix3f32) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)) return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y))
} }
matrix3_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_xyz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(-t1) c1 := math.cos(-t1)
c2 := math.cos(-t2) c2 := math.cos(-t2)
c3 := math.cos(-t3) c3 := math.cos(-t3)
@@ -334,7 +373,8 @@ matrix3_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return return
} }
matrix3_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_yxz_f32 :: proc "contextless" (yaw, pitch, roll: f32) -> (m: Matrix3f32) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -354,7 +394,8 @@ matrix3_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f
return return
} }
matrix3_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_xzx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -374,7 +415,8 @@ matrix3_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return return
} }
matrix3_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_xyx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -394,7 +436,8 @@ matrix3_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return return
} }
matrix3_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_yxy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -414,7 +457,8 @@ matrix3_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return return
} }
matrix3_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_yzy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -434,7 +478,8 @@ matrix3_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return return
} }
matrix3_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_zyz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -454,7 +499,8 @@ matrix3_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return return
} }
matrix3_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_zxz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -475,7 +521,8 @@ matrix3_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
} }
matrix3_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_xzy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -495,7 +542,8 @@ matrix3_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return return
} }
matrix3_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_yzx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -515,7 +563,8 @@ matrix3_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return return
} }
matrix3_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_zyx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -535,7 +584,8 @@ matrix3_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return return
} }
matrix3_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_euler_angles_zxy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -556,7 +606,8 @@ matrix3_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
} }
matrix3_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f32) { @(require_results)
matrix3_from_yaw_pitch_roll_f32 :: proc "contextless" (yaw, pitch, roll: f32) -> (m: Matrix3f32) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -576,7 +627,8 @@ matrix3_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f32
return m return m
} }
euler_angles_xyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xyz_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 2], m[2, 2]) T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2) T2 := math.atan2(-m[0, 2], C2)
@@ -589,7 +641,8 @@ euler_angles_xyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_yxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yxz_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 2], m[2, 2]) T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1]) C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2) T2 := math.atan2(-m[1, 2], C2)
@@ -602,7 +655,8 @@ euler_angles_yxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_xzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xzx_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 0], m[1, 0]) T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -615,7 +669,8 @@ euler_angles_xzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_xyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xyx_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 0], -m[2, 0]) T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -628,7 +683,8 @@ euler_angles_xyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_yxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yxy_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 1], m[2, 1]) T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -641,7 +697,8 @@ euler_angles_yxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_yzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yzy_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 1], -m[0, 1]) T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -653,7 +710,8 @@ euler_angles_yzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
t3 = T3 t3 = T3
return return
} }
euler_angles_zyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zyz_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 2], m[0, 2]) T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -666,7 +724,8 @@ euler_angles_zyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_zxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zxz_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 2], -m[1, 2]) T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -679,7 +738,8 @@ euler_angles_zxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_xzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xzy_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 1], m[1, 1]) T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2) T2 := math.atan2(-m[0, 1], C2)
@@ -692,7 +752,8 @@ euler_angles_xzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_yzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yzx_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(-m[2, 0], m[0, 0]) T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2]) C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2) T2 := math.atan2(m[1, 0], C2)
@@ -705,7 +766,8 @@ euler_angles_yzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_zyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zyx_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 0], m[0, 0]) T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2) T2 := math.atan2(-m[2, 0], C2)
@@ -718,7 +780,8 @@ euler_angles_zyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_zxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zxy_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(-m[0, 1], m[1, 1]) T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2) T2 := math.atan2(m[2, 1], C2)
@@ -735,7 +798,8 @@ euler_angles_zxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
// Matrix4 // Matrix4
matrix4_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angle_x_f32 :: proc "contextless" (angle_x: f32) -> (m: Matrix4f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1 m[0, 0] = 1
m[1, 1] = +cos_x m[1, 1] = +cos_x
@@ -745,7 +809,8 @@ matrix4_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix4f32) {
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angle_y_f32 :: proc "contextless" (angle_y: f32) -> (m: Matrix4f32) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y m[0, 0] = +cos_y
m[0, 2] = -sin_y m[0, 2] = -sin_y
@@ -755,7 +820,8 @@ matrix4_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix4f32) {
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angle_z_f32 :: proc "contextless" (angle_z: f32) -> (m: Matrix4f32) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z m[0, 0] = +cos_z
m[0, 1] = +sin_z m[0, 1] = +sin_z
@@ -767,7 +833,8 @@ matrix4_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix4f32) {
} }
matrix4_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_derived_euler_angle_x_f32 :: proc "contextless" (angle_x: f32, angular_velocity_x: f32) -> (m: Matrix4f32) {
cos_x := math.cos(angle_x) * angular_velocity_x cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1 m[0, 0] = 1
@@ -778,7 +845,8 @@ matrix4_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x:
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_derived_euler_angle_y_f32 :: proc "contextless" (angle_y: f32, angular_velocity_y: f32) -> (m: Matrix4f32) {
cos_y := math.cos(angle_y) * angular_velocity_y cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y m[0, 0] = +cos_y
@@ -789,7 +857,8 @@ matrix4_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y:
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_derived_euler_angle_z_f32 :: proc "contextless" (angle_z: f32, angular_velocity_z: f32) -> (m: Matrix4f32) {
cos_z := math.cos(angle_z) * angular_velocity_z cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z m[0, 0] = +cos_z
@@ -802,7 +871,8 @@ matrix4_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z:
} }
matrix4_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_xy_f32 :: proc "contextless" (angle_x, angle_y: f32) -> (m: Matrix4f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -818,7 +888,8 @@ matrix4_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix4f3
} }
matrix4_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_yx_f32 :: proc "contextless" (angle_y, angle_x: f32) -> (m: Matrix4f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -833,21 +904,26 @@ matrix4_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix4f3
return return
} }
matrix4_from_euler_angles_xz_f32 :: proc(angle_x, angle_z: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_xz_f32 :: proc "contextless" (angle_x, angle_z: f32) -> (m: Matrix4f32) {
return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)) return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z))
} }
matrix4_from_euler_angles_zx_f32 :: proc(angle_z, angle_x: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_zx_f32 :: proc "contextless" (angle_z, angle_x: f32) -> (m: Matrix4f32) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)) return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x))
} }
matrix4_from_euler_angles_yz_f32 :: proc(angle_y, angle_z: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_yz_f32 :: proc "contextless" (angle_y, angle_z: f32) -> (m: Matrix4f32) {
return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)) return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z))
} }
matrix4_from_euler_angles_zy_f32 :: proc(angle_z, angle_y: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_zy_f32 :: proc "contextless" (angle_z, angle_y: f32) -> (m: Matrix4f32) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)) return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y))
} }
matrix4_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_xyz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(-t1) c1 := math.cos(-t1)
c2 := math.cos(-t2) c2 := math.cos(-t2)
c3 := math.cos(-t3) c3 := math.cos(-t3)
@@ -874,7 +950,8 @@ matrix4_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return return
} }
matrix4_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_yxz_f32 :: proc "contextless" (yaw, pitch, roll: f32) -> (m: Matrix4f32) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -901,7 +978,8 @@ matrix4_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f
return return
} }
matrix4_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_xzx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -928,7 +1006,8 @@ matrix4_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return return
} }
matrix4_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_xyx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -955,7 +1034,8 @@ matrix4_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return return
} }
matrix4_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_yxy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -982,7 +1062,8 @@ matrix4_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return return
} }
matrix4_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_yzy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1009,7 +1090,8 @@ matrix4_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return return
} }
matrix4_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_zyz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1036,7 +1118,8 @@ matrix4_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return return
} }
matrix4_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_zxz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1064,7 +1147,8 @@ matrix4_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
} }
matrix4_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_xzy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1091,7 +1175,8 @@ matrix4_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return return
} }
matrix4_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_yzx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1118,7 +1203,8 @@ matrix4_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return return
} }
matrix4_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_zyx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1145,7 +1231,8 @@ matrix4_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return return
} }
matrix4_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_euler_angles_zxy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1173,7 +1260,8 @@ matrix4_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
} }
matrix4_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f32) { @(require_results)
matrix4_from_yaw_pitch_roll_f32 :: proc "contextless" (yaw, pitch, roll: f32) -> (m: Matrix4f32) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -1200,7 +1288,8 @@ matrix4_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f32
return m return m
} }
euler_angles_xyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xyz_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 2], m[2, 2]) T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2) T2 := math.atan2(-m[0, 2], C2)
@@ -1213,7 +1302,8 @@ euler_angles_xyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_yxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yxz_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 2], m[2, 2]) T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1]) C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2) T2 := math.atan2(-m[1, 2], C2)
@@ -1226,7 +1316,8 @@ euler_angles_yxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_xzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xzx_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 0], m[1, 0]) T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -1239,7 +1330,8 @@ euler_angles_xzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_xyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xyx_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 0], -m[2, 0]) T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -1252,7 +1344,8 @@ euler_angles_xyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_yxy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yxy_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 1], m[2, 1]) T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -1265,7 +1358,8 @@ euler_angles_yxy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_yzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yzy_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 1], -m[0, 1]) T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -1277,7 +1371,8 @@ euler_angles_yzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
t3 = T3 t3 = T3
return return
} }
euler_angles_zyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zyz_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 2], m[0, 2]) T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -1290,7 +1385,8 @@ euler_angles_zyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_zxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zxz_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 2], -m[1, 2]) T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -1303,7 +1399,8 @@ euler_angles_zxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_xzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_xzy_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 1], m[1, 1]) T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2) T2 := math.atan2(-m[0, 1], C2)
@@ -1316,7 +1413,8 @@ euler_angles_xzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_yzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_yzx_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(-m[2, 0], m[0, 0]) T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2]) C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2) T2 := math.atan2(m[1, 0], C2)
@@ -1329,7 +1427,8 @@ euler_angles_yzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_zyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zyx_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 0], m[0, 0]) T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2) T2 := math.atan2(-m[2, 0], C2)
@@ -1342,7 +1441,8 @@ euler_angles_zyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return return
} }
euler_angles_zxy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { @(require_results)
euler_angles_zxy_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(-m[0, 1], m[1, 1]) T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2) T2 := math.atan2(m[2, 1], C2)
+200 -100
View File
@@ -2,7 +2,8 @@ package linalg
import "core:math" import "core:math"
euler_angles_from_matrix3_f64 :: proc(m: Matrix3f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) {
switch order { switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m) case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m) case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m)
@@ -19,7 +20,8 @@ euler_angles_from_matrix3_f64 :: proc(m: Matrix3f64, order: Euler_Angle_Order) -
} }
return return
} }
euler_angles_from_matrix4_f64 :: proc(m: Matrix4f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) {
switch order { switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m) case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m) case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m)
@@ -36,7 +38,8 @@ euler_angles_from_matrix4_f64 :: proc(m: Matrix4f64, order: Euler_Angle_Order) -
} }
return return
} }
euler_angles_from_quaternion_f64 :: proc(m: Quaternionf64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_from_quaternion_f64 :: proc "contextless" (m: Quaternionf64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) {
switch order { switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m) case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m) case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m)
@@ -54,7 +57,8 @@ euler_angles_from_quaternion_f64 :: proc(m: Quaternionf64, order: Euler_Angle_Or
return return
} }
matrix3_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_f64 :: proc "contextless" (t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix3f64) {
switch order { switch order {
case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -71,7 +75,8 @@ matrix3_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order)
} }
return return
} }
matrix4_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_f64 :: proc "contextless" (t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix4f64) {
switch order { switch order {
case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -89,7 +94,8 @@ matrix4_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order)
return return
} }
quaternion_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> Quaternionf64 { @(require_results)
quaternion_from_euler_angles_f64 :: proc "contextless" (t1, t2, t3: f64, order: Euler_Angle_Order) -> Quaternionf64 {
X :: quaternion_from_euler_angle_x X :: quaternion_from_euler_angle_x
Y :: quaternion_from_euler_angle_y Y :: quaternion_from_euler_angle_y
Z :: quaternion_from_euler_angle_z Z :: quaternion_from_euler_angle_z
@@ -117,17 +123,21 @@ quaternion_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Ord
// Quaternionf64s // Quaternionf64s
quaternion_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (q: Quaternionf64) { @(require_results)
quaternion_from_euler_angle_x_f64 :: proc "contextless" (angle_x: f64) -> (q: Quaternionf64) {
return quaternion_angle_axis_f64(angle_x, {1, 0, 0}) return quaternion_angle_axis_f64(angle_x, {1, 0, 0})
} }
quaternion_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (q: Quaternionf64) { @(require_results)
quaternion_from_euler_angle_y_f64 :: proc "contextless" (angle_y: f64) -> (q: Quaternionf64) {
return quaternion_angle_axis_f64(angle_y, {0, 1, 0}) return quaternion_angle_axis_f64(angle_y, {0, 1, 0})
} }
quaternion_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (q: Quaternionf64) { @(require_results)
quaternion_from_euler_angle_z_f64 :: proc "contextless" (angle_z: f64) -> (q: Quaternionf64) {
return quaternion_angle_axis_f64(angle_z, {0, 0, 1}) return quaternion_angle_axis_f64(angle_z, {0, 0, 1})
} }
quaternion_from_pitch_yaw_roll_f64 :: proc(pitch, yaw, roll: f64) -> Quaternionf64 { @(require_results)
quaternion_from_pitch_yaw_roll_f64 :: proc "contextless" (pitch, yaw, roll: f64) -> Quaternionf64 {
a, b, c := pitch, yaw, roll a, b, c := pitch, yaw, roll
ca, sa := math.cos(a*0.5), math.sin(a*0.5) ca, sa := math.cos(a*0.5), math.sin(a*0.5)
@@ -142,11 +152,13 @@ quaternion_from_pitch_yaw_roll_f64 :: proc(pitch, yaw, roll: f64) -> Quaternionf
return q return q
} }
roll_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { @(require_results)
roll_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> f64 {
return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z) return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z)
} }
pitch_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { @(require_results)
pitch_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> f64 {
y := 2 * (q.y*q.z + q.w*q.w) y := 2 * (q.y*q.z + q.w*q.w)
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
@@ -157,52 +169,66 @@ pitch_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 {
return math.atan2(y, x) return math.atan2(y, x)
} }
yaw_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { @(require_results)
yaw_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> f64 {
return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)) return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1))
} }
pitch_yaw_roll_from_quaternion_f64 :: proc(q: Quaternionf64) -> (pitch, yaw, roll: f64) { @(require_results)
pitch_yaw_roll_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (pitch, yaw, roll: f64) {
pitch = pitch_from_quaternion(q) pitch = pitch_from_quaternion(q)
yaw = yaw_from_quaternion(q) yaw = yaw_from_quaternion(q)
roll = roll_from_quaternion(q) roll = roll_from_quaternion(q)
return return
} }
euler_angles_xyz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xyz_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yxz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yxz_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_xzx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xzx_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_xyx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xyx_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yxy_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yzy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yzy_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zyz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zyz_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zxz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zxz_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_xzy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xzy_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_yzx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yzx_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zyx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zyx_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q))
} }
euler_angles_zxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zxy_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)) return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q))
} }
@@ -210,7 +236,8 @@ euler_angles_zxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f
// Matrix3 // Matrix3
matrix3_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angle_x_f64 :: proc "contextless" (angle_x: f64) -> (m: Matrix3f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1 m[0, 0] = 1
m[1, 1] = +cos_x m[1, 1] = +cos_x
@@ -219,7 +246,8 @@ matrix3_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix3f64) {
m[2, 2] = +cos_x m[2, 2] = +cos_x
return return
} }
matrix3_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angle_y_f64 :: proc "contextless" (angle_y: f64) -> (m: Matrix3f64) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y m[0, 0] = +cos_y
m[0, 2] = -sin_y m[0, 2] = -sin_y
@@ -228,7 +256,8 @@ matrix3_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix3f64) {
m[2, 2] = +cos_y m[2, 2] = +cos_y
return return
} }
matrix3_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angle_z_f64 :: proc "contextless" (angle_z: f64) -> (m: Matrix3f64) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z m[0, 0] = +cos_z
m[0, 1] = +sin_z m[0, 1] = +sin_z
@@ -239,7 +268,8 @@ matrix3_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix3f64) {
} }
matrix3_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_derived_euler_angle_x_f64 :: proc "contextless" (angle_x: f64, angular_velocity_x: f64) -> (m: Matrix3f64) {
cos_x := math.cos(angle_x) * angular_velocity_x cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1 m[0, 0] = 1
@@ -249,7 +279,8 @@ matrix3_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x:
m[2, 2] = +cos_x m[2, 2] = +cos_x
return return
} }
matrix3_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_derived_euler_angle_y_f64 :: proc "contextless" (angle_y: f64, angular_velocity_y: f64) -> (m: Matrix3f64) {
cos_y := math.cos(angle_y) * angular_velocity_y cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y m[0, 0] = +cos_y
@@ -259,7 +290,8 @@ matrix3_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y:
m[2, 2] = +cos_y m[2, 2] = +cos_y
return return
} }
matrix3_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_derived_euler_angle_z_f64 :: proc "contextless" (angle_z: f64, angular_velocity_z: f64) -> (m: Matrix3f64) {
cos_z := math.cos(angle_z) * angular_velocity_z cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z m[0, 0] = +cos_z
@@ -271,7 +303,8 @@ matrix3_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z:
} }
matrix3_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_xy_f64 :: proc "contextless" (angle_x, angle_y: f64) -> (m: Matrix3f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -286,7 +319,8 @@ matrix3_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix3f6
} }
matrix3_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_yx_f64 :: proc "contextless" (angle_y, angle_x: f64) -> (m: Matrix3f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -300,21 +334,26 @@ matrix3_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix3f6
return return
} }
matrix3_from_euler_angles_xz_f64 :: proc(angle_x, angle_z: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_xz_f64 :: proc "contextless" (angle_x, angle_z: f64) -> (m: Matrix3f64) {
return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)) return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z))
} }
matrix3_from_euler_angles_zx_f64 :: proc(angle_z, angle_x: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_zx_f64 :: proc "contextless" (angle_z, angle_x: f64) -> (m: Matrix3f64) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)) return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x))
} }
matrix3_from_euler_angles_yz_f64 :: proc(angle_y, angle_z: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_yz_f64 :: proc "contextless" (angle_y, angle_z: f64) -> (m: Matrix3f64) {
return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)) return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z))
} }
matrix3_from_euler_angles_zy_f64 :: proc(angle_z, angle_y: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_zy_f64 :: proc "contextless" (angle_z, angle_y: f64) -> (m: Matrix3f64) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)) return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y))
} }
matrix3_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_xyz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(-t1) c1 := math.cos(-t1)
c2 := math.cos(-t2) c2 := math.cos(-t2)
c3 := math.cos(-t3) c3 := math.cos(-t3)
@@ -334,7 +373,8 @@ matrix3_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return return
} }
matrix3_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_yxz_f64 :: proc "contextless" (yaw, pitch, roll: f64) -> (m: Matrix3f64) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -354,7 +394,8 @@ matrix3_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f
return return
} }
matrix3_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_xzx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -374,7 +415,8 @@ matrix3_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return return
} }
matrix3_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_xyx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -394,7 +436,8 @@ matrix3_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return return
} }
matrix3_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_yxy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -414,7 +457,8 @@ matrix3_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return return
} }
matrix3_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_yzy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -434,7 +478,8 @@ matrix3_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return return
} }
matrix3_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_zyz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -454,7 +499,8 @@ matrix3_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return return
} }
matrix3_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_zxz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -475,7 +521,8 @@ matrix3_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
} }
matrix3_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_xzy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -495,7 +542,8 @@ matrix3_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return return
} }
matrix3_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_yzx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -515,7 +563,8 @@ matrix3_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return return
} }
matrix3_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_zyx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -535,7 +584,8 @@ matrix3_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return return
} }
matrix3_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_euler_angles_zxy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -556,7 +606,8 @@ matrix3_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
} }
matrix3_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f64) { @(require_results)
matrix3_from_yaw_pitch_roll_f64 :: proc "contextless" (yaw, pitch, roll: f64) -> (m: Matrix3f64) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -576,7 +627,8 @@ matrix3_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f64
return m return m
} }
euler_angles_xyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xyz_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 2], m[2, 2]) T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2) T2 := math.atan2(-m[0, 2], C2)
@@ -589,7 +641,8 @@ euler_angles_xyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_yxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yxz_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 2], m[2, 2]) T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1]) C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2) T2 := math.atan2(-m[1, 2], C2)
@@ -602,7 +655,8 @@ euler_angles_yxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_xzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xzx_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 0], m[1, 0]) T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -615,7 +669,8 @@ euler_angles_xzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_xyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xyx_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 0], -m[2, 0]) T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -628,7 +683,8 @@ euler_angles_xyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_yxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yxy_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 1], m[2, 1]) T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -641,7 +697,8 @@ euler_angles_yxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_yzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yzy_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 1], -m[0, 1]) T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -653,7 +710,8 @@ euler_angles_yzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
t3 = T3 t3 = T3
return return
} }
euler_angles_zyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zyz_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 2], m[0, 2]) T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -666,7 +724,8 @@ euler_angles_zyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_zxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zxz_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 2], -m[1, 2]) T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -679,7 +738,8 @@ euler_angles_zxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_xzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xzy_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 1], m[1, 1]) T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2) T2 := math.atan2(-m[0, 1], C2)
@@ -692,7 +752,8 @@ euler_angles_xzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_yzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yzx_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(-m[2, 0], m[0, 0]) T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2]) C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2) T2 := math.atan2(m[1, 0], C2)
@@ -705,7 +766,8 @@ euler_angles_yzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_zyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zyx_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 0], m[0, 0]) T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2) T2 := math.atan2(-m[2, 0], C2)
@@ -718,7 +780,8 @@ euler_angles_zyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_zxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zxy_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(-m[0, 1], m[1, 1]) T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2) T2 := math.atan2(m[2, 1], C2)
@@ -735,7 +798,8 @@ euler_angles_zxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
// Matrix4 // Matrix4
matrix4_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angle_x_f64 :: proc "contextless" (angle_x: f64) -> (m: Matrix4f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1 m[0, 0] = 1
m[1, 1] = +cos_x m[1, 1] = +cos_x
@@ -745,7 +809,8 @@ matrix4_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix4f64) {
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angle_y_f64 :: proc "contextless" (angle_y: f64) -> (m: Matrix4f64) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y m[0, 0] = +cos_y
m[0, 2] = -sin_y m[0, 2] = -sin_y
@@ -755,7 +820,8 @@ matrix4_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix4f64) {
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angle_z_f64 :: proc "contextless" (angle_z: f64) -> (m: Matrix4f64) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z m[0, 0] = +cos_z
m[0, 1] = +sin_z m[0, 1] = +sin_z
@@ -767,7 +833,8 @@ matrix4_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix4f64) {
} }
matrix4_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_derived_euler_angle_x_f64 :: proc "contextless" (angle_x: f64, angular_velocity_x: f64) -> (m: Matrix4f64) {
cos_x := math.cos(angle_x) * angular_velocity_x cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1 m[0, 0] = 1
@@ -778,7 +845,8 @@ matrix4_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x:
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_derived_euler_angle_y_f64 :: proc "contextless" (angle_y: f64, angular_velocity_y: f64) -> (m: Matrix4f64) {
cos_y := math.cos(angle_y) * angular_velocity_y cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y m[0, 0] = +cos_y
@@ -789,7 +857,8 @@ matrix4_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y:
m[3, 3] = 1 m[3, 3] = 1
return return
} }
matrix4_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_derived_euler_angle_z_f64 :: proc "contextless" (angle_z: f64, angular_velocity_z: f64) -> (m: Matrix4f64) {
cos_z := math.cos(angle_z) * angular_velocity_z cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z m[0, 0] = +cos_z
@@ -802,7 +871,8 @@ matrix4_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z:
} }
matrix4_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_xy_f64 :: proc "contextless" (angle_x, angle_y: f64) -> (m: Matrix4f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -818,7 +888,8 @@ matrix4_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix4f6
} }
matrix4_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_yx_f64 :: proc "contextless" (angle_y, angle_x: f64) -> (m: Matrix4f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y m[0, 0] = cos_y
@@ -833,21 +904,26 @@ matrix4_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix4f6
return return
} }
matrix4_from_euler_angles_xz_f64 :: proc(angle_x, angle_z: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_xz_f64 :: proc "contextless" (angle_x, angle_z: f64) -> (m: Matrix4f64) {
return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)) return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z))
} }
matrix4_from_euler_angles_zx_f64 :: proc(angle_z, angle_x: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_zx_f64 :: proc "contextless" (angle_z, angle_x: f64) -> (m: Matrix4f64) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)) return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x))
} }
matrix4_from_euler_angles_yz_f64 :: proc(angle_y, angle_z: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_yz_f64 :: proc "contextless" (angle_y, angle_z: f64) -> (m: Matrix4f64) {
return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)) return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z))
} }
matrix4_from_euler_angles_zy_f64 :: proc(angle_z, angle_y: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_zy_f64 :: proc "contextless" (angle_z, angle_y: f64) -> (m: Matrix4f64) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)) return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y))
} }
matrix4_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_xyz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(-t1) c1 := math.cos(-t1)
c2 := math.cos(-t2) c2 := math.cos(-t2)
c3 := math.cos(-t3) c3 := math.cos(-t3)
@@ -874,7 +950,8 @@ matrix4_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return return
} }
matrix4_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_yxz_f64 :: proc "contextless" (yaw, pitch, roll: f64) -> (m: Matrix4f64) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -901,7 +978,8 @@ matrix4_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f
return return
} }
matrix4_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_xzx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -928,7 +1006,8 @@ matrix4_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return return
} }
matrix4_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_xyx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -955,7 +1034,8 @@ matrix4_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return return
} }
matrix4_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_yxy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -982,7 +1062,8 @@ matrix4_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return return
} }
matrix4_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_yzy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1009,7 +1090,8 @@ matrix4_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return return
} }
matrix4_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_zyz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1036,7 +1118,8 @@ matrix4_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return return
} }
matrix4_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_zxz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1064,7 +1147,8 @@ matrix4_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
} }
matrix4_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_xzy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1091,7 +1175,8 @@ matrix4_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return return
} }
matrix4_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_yzx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1118,7 +1203,8 @@ matrix4_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return return
} }
matrix4_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_zyx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1145,7 +1231,8 @@ matrix4_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return return
} }
matrix4_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_euler_angles_zxy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1) c1 := math.cos(t1)
s1 := math.sin(t1) s1 := math.sin(t1)
c2 := math.cos(t2) c2 := math.cos(t2)
@@ -1173,7 +1260,8 @@ matrix4_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
} }
matrix4_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f64) { @(require_results)
matrix4_from_yaw_pitch_roll_f64 :: proc "contextless" (yaw, pitch, roll: f64) -> (m: Matrix4f64) {
ch := math.cos(yaw) ch := math.cos(yaw)
sh := math.sin(yaw) sh := math.sin(yaw)
cp := math.cos(pitch) cp := math.cos(pitch)
@@ -1200,7 +1288,8 @@ matrix4_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f64
return m return m
} }
euler_angles_xyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xyz_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 2], m[2, 2]) T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2) T2 := math.atan2(-m[0, 2], C2)
@@ -1213,7 +1302,8 @@ euler_angles_xyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_yxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yxz_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 2], m[2, 2]) T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1]) C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2) T2 := math.atan2(-m[1, 2], C2)
@@ -1226,7 +1316,8 @@ euler_angles_yxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_xzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xzx_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 0], m[1, 0]) T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -1239,7 +1330,8 @@ euler_angles_xzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_xyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xyx_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 0], -m[2, 0]) T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2]) S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0]) T2 := math.atan2(S2, m[0, 0])
@@ -1252,7 +1344,8 @@ euler_angles_xyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_yxy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yxy_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 1], m[2, 1]) T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -1265,7 +1358,8 @@ euler_angles_yxy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_yzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yzy_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 1], -m[0, 1]) T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2]) S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1]) T2 := math.atan2(S2, m[1, 1])
@@ -1277,7 +1371,8 @@ euler_angles_yzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
t3 = T3 t3 = T3
return return
} }
euler_angles_zyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zyz_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 2], m[0, 2]) T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -1290,7 +1385,8 @@ euler_angles_zyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_zxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zxz_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 2], -m[1, 2]) T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1]) S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2]) T2 := math.atan2(S2, m[2, 2])
@@ -1303,7 +1399,8 @@ euler_angles_zxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_xzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_xzy_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 1], m[1, 1]) T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2]) C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2) T2 := math.atan2(-m[0, 1], C2)
@@ -1316,7 +1413,8 @@ euler_angles_xzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_yzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_yzx_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(-m[2, 0], m[0, 0]) T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2]) C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2) T2 := math.atan2(m[1, 0], C2)
@@ -1329,7 +1427,8 @@ euler_angles_yzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_zyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zyx_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 0], m[0, 0]) T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2) T2 := math.atan2(-m[2, 0], C2)
@@ -1342,7 +1441,8 @@ euler_angles_zyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return return
} }
euler_angles_zxy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { @(require_results)
euler_angles_zxy_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(-m[0, 1], m[1, 1]) T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2]) C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2) T2 := math.atan2(m[2, 1], C2)
+64 -32
View File
@@ -37,110 +37,142 @@ Vector4_Components :: enum u8 {
a = 3, a = 3,
} }
scalar_f32_swizzle1 :: proc(f: f32, c0: Scalar_Components) -> f32 { @(require_results)
scalar_f32_swizzle1 :: proc "contextless" (f: f32, c0: Scalar_Components) -> f32 {
return f return f
} }
scalar_f32_swizzle2 :: proc(f: f32, c0, c1: Scalar_Components) -> Vector2f32 { @(require_results)
scalar_f32_swizzle2 :: proc "contextless" (f: f32, c0, c1: Scalar_Components) -> Vector2f32 {
return {f, f} return {f, f}
} }
scalar_f32_swizzle3 :: proc(f: f32, c0, c1, c2: Scalar_Components) -> Vector3f32 { @(require_results)
scalar_f32_swizzle3 :: proc "contextless" (f: f32, c0, c1, c2: Scalar_Components) -> Vector3f32 {
return {f, f, f} return {f, f, f}
} }
scalar_f32_swizzle4 :: proc(f: f32, c0, c1, c2, c3: Scalar_Components) -> Vector4f32 { @(require_results)
scalar_f32_swizzle4 :: proc "contextless" (f: f32, c0, c1, c2, c3: Scalar_Components) -> Vector4f32 {
return {f, f, f, f} return {f, f, f, f}
} }
vector2f32_swizzle1 :: proc(v: Vector2f32, c0: Vector2_Components) -> f32 { @(require_results)
vector2f32_swizzle1 :: proc "contextless" (v: Vector2f32, c0: Vector2_Components) -> f32 {
return v[c0] return v[c0]
} }
vector2f32_swizzle2 :: proc(v: Vector2f32, c0, c1: Vector2_Components) -> Vector2f32 { @(require_results)
vector2f32_swizzle2 :: proc "contextless" (v: Vector2f32, c0, c1: Vector2_Components) -> Vector2f32 {
return {v[c0], v[c1]} return {v[c0], v[c1]}
} }
vector2f32_swizzle3 :: proc(v: Vector2f32, c0, c1, c2: Vector2_Components) -> Vector3f32 { @(require_results)
vector2f32_swizzle3 :: proc "contextless" (v: Vector2f32, c0, c1, c2: Vector2_Components) -> Vector3f32 {
return {v[c0], v[c1], v[c2]} return {v[c0], v[c1], v[c2]}
} }
vector2f32_swizzle4 :: proc(v: Vector2f32, c0, c1, c2, c3: Vector2_Components) -> Vector4f32 { @(require_results)
vector2f32_swizzle4 :: proc "contextless" (v: Vector2f32, c0, c1, c2, c3: Vector2_Components) -> Vector4f32 {
return {v[c0], v[c1], v[c2], v[c3]} return {v[c0], v[c1], v[c2], v[c3]}
} }
vector3f32_swizzle1 :: proc(v: Vector3f32, c0: Vector3_Components) -> f32 { @(require_results)
vector3f32_swizzle1 :: proc "contextless" (v: Vector3f32, c0: Vector3_Components) -> f32 {
return v[c0] return v[c0]
} }
vector3f32_swizzle2 :: proc(v: Vector3f32, c0, c1: Vector3_Components) -> Vector2f32 { @(require_results)
vector3f32_swizzle2 :: proc "contextless" (v: Vector3f32, c0, c1: Vector3_Components) -> Vector2f32 {
return {v[c0], v[c1]} return {v[c0], v[c1]}
} }
vector3f32_swizzle3 :: proc(v: Vector3f32, c0, c1, c2: Vector3_Components) -> Vector3f32 { @(require_results)
vector3f32_swizzle3 :: proc "contextless" (v: Vector3f32, c0, c1, c2: Vector3_Components) -> Vector3f32 {
return {v[c0], v[c1], v[c2]} return {v[c0], v[c1], v[c2]}
} }
vector3f32_swizzle4 :: proc(v: Vector3f32, c0, c1, c2, c3: Vector3_Components) -> Vector4f32 { @(require_results)
vector3f32_swizzle4 :: proc "contextless" (v: Vector3f32, c0, c1, c2, c3: Vector3_Components) -> Vector4f32 {
return {v[c0], v[c1], v[c2], v[c3]} return {v[c0], v[c1], v[c2], v[c3]}
} }
vector4f32_swizzle1 :: proc(v: Vector4f32, c0: Vector4_Components) -> f32 { @(require_results)
vector4f32_swizzle1 :: proc "contextless" (v: Vector4f32, c0: Vector4_Components) -> f32 {
return v[c0] return v[c0]
} }
vector4f32_swizzle2 :: proc(v: Vector4f32, c0, c1: Vector4_Components) -> Vector2f32 { @(require_results)
vector4f32_swizzle2 :: proc "contextless" (v: Vector4f32, c0, c1: Vector4_Components) -> Vector2f32 {
return {v[c0], v[c1]} return {v[c0], v[c1]}
} }
vector4f32_swizzle3 :: proc(v: Vector4f32, c0, c1, c2: Vector4_Components) -> Vector3f32 { @(require_results)
vector4f32_swizzle3 :: proc "contextless" (v: Vector4f32, c0, c1, c2: Vector4_Components) -> Vector3f32 {
return {v[c0], v[c1], v[c2]} return {v[c0], v[c1], v[c2]}
} }
vector4f32_swizzle4 :: proc(v: Vector4f32, c0, c1, c2, c3: Vector4_Components) -> Vector4f32 { @(require_results)
vector4f32_swizzle4 :: proc "contextless" (v: Vector4f32, c0, c1, c2, c3: Vector4_Components) -> Vector4f32 {
return {v[c0], v[c1], v[c2], v[c3]} return {v[c0], v[c1], v[c2], v[c3]}
} }
scalar_f64_swizzle1 :: proc(f: f64, c0: Scalar_Components) -> f64 { @(require_results)
scalar_f64_swizzle1 :: proc "contextless" (f: f64, c0: Scalar_Components) -> f64 {
return f return f
} }
scalar_f64_swizzle2 :: proc(f: f64, c0, c1: Scalar_Components) -> Vector2f64 { @(require_results)
scalar_f64_swizzle2 :: proc "contextless" (f: f64, c0, c1: Scalar_Components) -> Vector2f64 {
return {f, f} return {f, f}
} }
scalar_f64_swizzle3 :: proc(f: f64, c0, c1, c2: Scalar_Components) -> Vector3f64 { @(require_results)
scalar_f64_swizzle3 :: proc "contextless" (f: f64, c0, c1, c2: Scalar_Components) -> Vector3f64 {
return {f, f, f} return {f, f, f}
} }
scalar_f64_swizzle4 :: proc(f: f64, c0, c1, c2, c3: Scalar_Components) -> Vector4f64 { @(require_results)
scalar_f64_swizzle4 :: proc "contextless" (f: f64, c0, c1, c2, c3: Scalar_Components) -> Vector4f64 {
return {f, f, f, f} return {f, f, f, f}
} }
vector2f64_swizzle1 :: proc(v: Vector2f64, c0: Vector2_Components) -> f64 { @(require_results)
vector2f64_swizzle1 :: proc "contextless" (v: Vector2f64, c0: Vector2_Components) -> f64 {
return v[c0] return v[c0]
} }
vector2f64_swizzle2 :: proc(v: Vector2f64, c0, c1: Vector2_Components) -> Vector2f64 { @(require_results)
vector2f64_swizzle2 :: proc "contextless" (v: Vector2f64, c0, c1: Vector2_Components) -> Vector2f64 {
return {v[c0], v[c1]} return {v[c0], v[c1]}
} }
vector2f64_swizzle3 :: proc(v: Vector2f64, c0, c1, c2: Vector2_Components) -> Vector3f64 { @(require_results)
vector2f64_swizzle3 :: proc "contextless" (v: Vector2f64, c0, c1, c2: Vector2_Components) -> Vector3f64 {
return {v[c0], v[c1], v[c2]} return {v[c0], v[c1], v[c2]}
} }
vector2f64_swizzle4 :: proc(v: Vector2f64, c0, c1, c2, c3: Vector2_Components) -> Vector4f64 { @(require_results)
vector2f64_swizzle4 :: proc "contextless" (v: Vector2f64, c0, c1, c2, c3: Vector2_Components) -> Vector4f64 {
return {v[c0], v[c1], v[c2], v[c3]} return {v[c0], v[c1], v[c2], v[c3]}
} }
vector3f64_swizzle1 :: proc(v: Vector3f64, c0: Vector3_Components) -> f64 { @(require_results)
vector3f64_swizzle1 :: proc "contextless" (v: Vector3f64, c0: Vector3_Components) -> f64 {
return v[c0] return v[c0]
} }
vector3f64_swizzle2 :: proc(v: Vector3f64, c0, c1: Vector3_Components) -> Vector2f64 { @(require_results)
vector3f64_swizzle2 :: proc "contextless" (v: Vector3f64, c0, c1: Vector3_Components) -> Vector2f64 {
return {v[c0], v[c1]} return {v[c0], v[c1]}
} }
vector3f64_swizzle3 :: proc(v: Vector3f64, c0, c1, c2: Vector3_Components) -> Vector3f64 { @(require_results)
vector3f64_swizzle3 :: proc "contextless" (v: Vector3f64, c0, c1, c2: Vector3_Components) -> Vector3f64 {
return {v[c0], v[c1], v[c2]} return {v[c0], v[c1], v[c2]}
} }
vector3f64_swizzle4 :: proc(v: Vector3f64, c0, c1, c2, c3: Vector3_Components) -> Vector4f64 { @(require_results)
vector3f64_swizzle4 :: proc "contextless" (v: Vector3f64, c0, c1, c2, c3: Vector3_Components) -> Vector4f64 {
return {v[c0], v[c1], v[c2], v[c3]} return {v[c0], v[c1], v[c2], v[c3]}
} }
vector4f64_swizzle1 :: proc(v: Vector4f64, c0: Vector4_Components) -> f64 { @(require_results)
vector4f64_swizzle1 :: proc "contextless" (v: Vector4f64, c0: Vector4_Components) -> f64 {
return v[c0] return v[c0]
} }
vector4f64_swizzle2 :: proc(v: Vector4f64, c0, c1: Vector4_Components) -> Vector2f64 { @(require_results)
vector4f64_swizzle2 :: proc "contextless" (v: Vector4f64, c0, c1: Vector4_Components) -> Vector2f64 {
return {v[c0], v[c1]} return {v[c0], v[c1]}
} }
vector4f64_swizzle3 :: proc(v: Vector4f64, c0, c1, c2: Vector4_Components) -> Vector3f64 { @(require_results)
vector4f64_swizzle3 :: proc "contextless" (v: Vector4f64, c0, c1, c2: Vector4_Components) -> Vector3f64 {
return {v[c0], v[c1], v[c2]} return {v[c0], v[c1], v[c2]}
} }
vector4f64_swizzle4 :: proc(v: Vector4f64, c0, c1, c2, c3: Vector4_Components) -> Vector4f64 { @(require_results)
vector4f64_swizzle4 :: proc "contextless" (v: Vector4f64, c0, c1, c2, c3: Vector4_Components) -> Vector4f64 {
return {v[c0], v[c1], v[c2], v[c3]} return {v[c0], v[c1], v[c2], v[c3]}
} }
+477 -261
View File
File diff suppressed because it is too large Load Diff
+109 -39
View File
@@ -3,56 +3,126 @@ package math
import "core:intrinsics" import "core:intrinsics"
@(default_calling_convention="none") @(default_calling_convention="none", private="file")
foreign _ { foreign _ {
@(link_name="llvm.sin.f16") @(link_name="llvm.sin.f16", require_results)
sin_f16 :: proc(θ: f16) -> f16 --- _sin_f16 :: proc(θ: f16) -> f16 ---
@(link_name="llvm.sin.f32") @(link_name="llvm.sin.f32", require_results)
sin_f32 :: proc(θ: f32) -> f32 --- _sin_f32 :: proc(θ: f32) -> f32 ---
@(link_name="llvm.sin.f64") @(link_name="llvm.sin.f64", require_results)
sin_f64 :: proc(θ: f64) -> f64 --- _sin_f64 :: proc(θ: f64) -> f64 ---
@(link_name="llvm.cos.f16") @(link_name="llvm.cos.f16", require_results)
cos_f16 :: proc(θ: f16) -> f16 --- _cos_f16 :: proc(θ: f16) -> f16 ---
@(link_name="llvm.cos.f32") @(link_name="llvm.cos.f32", require_results)
cos_f32 :: proc(θ: f32) -> f32 --- _cos_f32 :: proc(θ: f32) -> f32 ---
@(link_name="llvm.cos.f64") @(link_name="llvm.cos.f64", require_results)
cos_f64 :: proc(θ: f64) -> f64 --- _cos_f64 :: proc(θ: f64) -> f64 ---
@(link_name="llvm.pow.f16") @(link_name="llvm.pow.f16", require_results)
pow_f16 :: proc(x, power: f16) -> f16 --- _pow_f16 :: proc(x, power: f16) -> f16 ---
@(link_name="llvm.pow.f32") @(link_name="llvm.pow.f32", require_results)
pow_f32 :: proc(x, power: f32) -> f32 --- _pow_f32 :: proc(x, power: f32) -> f32 ---
@(link_name="llvm.pow.f64") @(link_name="llvm.pow.f64", require_results)
pow_f64 :: proc(x, power: f64) -> f64 --- _pow_f64 :: proc(x, power: f64) -> f64 ---
@(link_name="llvm.fmuladd.f16") @(link_name="llvm.fmuladd.f16", require_results)
fmuladd_f16 :: proc(a, b, c: f16) -> f16 --- _fmuladd_f16 :: proc(a, b, c: f16) -> f16 ---
@(link_name="llvm.fmuladd.f32") @(link_name="llvm.fmuladd.f32", require_results)
fmuladd_f32 :: proc(a, b, c: f32) -> f32 --- _fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---
@(link_name="llvm.fmuladd.f64") @(link_name="llvm.fmuladd.f64", require_results)
fmuladd_f64 :: proc(a, b, c: f64) -> f64 --- _fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---
@(link_name="llvm.exp.f16") @(link_name="llvm.exp.f16", require_results)
exp_f16 :: proc(x: f16) -> f16 --- _exp_f16 :: proc(x: f16) -> f16 ---
@(link_name="llvm.exp.f32") @(link_name="llvm.exp.f32", require_results)
exp_f32 :: proc(x: f32) -> f32 --- _exp_f32 :: proc(x: f32) -> f32 ---
@(link_name="llvm.exp.f64") @(link_name="llvm.exp.f64", require_results)
exp_f64 :: proc(x: f64) -> f64 --- _exp_f64 :: proc(x: f64) -> f64 ---
} }
@(require_results)
sin_f16 :: proc "contextless" (θ: f16) -> f16 {
return _sin_f16(θ)
}
@(require_results)
sin_f32 :: proc "contextless" (θ: f32) -> f32 {
return _sin_f32(θ)
}
@(require_results)
sin_f64 :: proc "contextless" (θ: f64) -> f64 {
return _sin_f64(θ)
}
@(require_results)
cos_f16 :: proc "contextless" (θ: f16) -> f16 {
return _cos_f16(θ)
}
@(require_results)
cos_f32 :: proc "contextless" (θ: f32) -> f32 {
return _cos_f32(θ)
}
@(require_results)
cos_f64 :: proc "contextless" (θ: f64) -> f64 {
return _cos_f64(θ)
}
@(require_results)
pow_f16 :: proc "contextless" (x, power: f16) -> f16 {
return _pow_f16(x, power)
}
@(require_results)
pow_f32 :: proc "contextless" (x, power: f32) -> f32 {
return _pow_f32(x, power)
}
@(require_results)
pow_f64 :: proc "contextless" (x, power: f64) -> f64 {
return _pow_f64(x, power)
}
@(require_results)
fmuladd_f16 :: proc "contextless" (a, b, c: f16) -> f16 {
return _fmuladd_f16(a, b, c)
}
@(require_results)
fmuladd_f32 :: proc "contextless" (a, b, c: f32) -> f32 {
return _fmuladd_f32(a, b, c)
}
@(require_results)
fmuladd_f64 :: proc "contextless" (a, b, c: f64) -> f64 {
return _fmuladd_f64(a, b, c)
}
@(require_results)
exp_f16 :: proc "contextless" (x: f16) -> f16 {
return _exp_f16(x)
}
@(require_results)
exp_f32 :: proc "contextless" (x: f32) -> f32 {
return _exp_f32(x)
}
@(require_results)
exp_f64 :: proc "contextless" (x: f64) -> f64 {
return _exp_f64(x)
}
@(require_results)
sqrt_f16 :: proc "contextless" (x: f16) -> f16 { sqrt_f16 :: proc "contextless" (x: f16) -> f16 {
return intrinsics.sqrt(x) return intrinsics.sqrt(x)
} }
@(require_results)
sqrt_f32 :: proc "contextless" (x: f32) -> f32 { sqrt_f32 :: proc "contextless" (x: f32) -> f32 {
return intrinsics.sqrt(x) return intrinsics.sqrt(x)
} }
@(require_results)
sqrt_f64 :: proc "contextless" (x: f64) -> f64 { sqrt_f64 :: proc "contextless" (x: f64) -> f64 {
return intrinsics.sqrt(x) return intrinsics.sqrt(x)
} }
@(require_results)
ln_f64 :: proc "contextless" (x: f64) -> f64 { ln_f64 :: proc "contextless" (x: f64) -> f64 {
// The original C code, the long comment, and the constants // The original C code, the long comment, and the constants
// below are from FreeBSD's /usr/src/lib/msun/src/e_log.c // below are from FreeBSD's /usr/src/lib/msun/src/e_log.c
@@ -154,14 +224,14 @@ ln_f64 :: proc "contextless" (x: f64) -> f64 {
return k*LN2_HI - ((hfsq - (s*(hfsq+R) + k*LN2_LO)) - f) return k*LN2_HI - ((hfsq - (s*(hfsq+R) + k*LN2_LO)) - f)
} }
ln_f16 :: proc "contextless" (x: f16) -> f16 { return #force_inline f16(ln_f64(f64(x))) } @(require_results) ln_f16 :: proc "contextless" (x: f16) -> f16 { return #force_inline f16(ln_f64(f64(x))) }
ln_f32 :: proc "contextless" (x: f32) -> f32 { return #force_inline f32(ln_f64(f64(x))) } @(require_results) ln_f32 :: proc "contextless" (x: f32) -> f32 { return #force_inline f32(ln_f64(f64(x))) }
ln_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(ln_f64(f64(x))) } @(require_results) ln_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(ln_f64(f64(x))) }
ln_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(ln_f64(f64(x))) } @(require_results) ln_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(ln_f64(f64(x))) }
ln_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(ln_f64(f64(x))) } @(require_results) ln_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(ln_f64(f64(x))) }
ln_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(ln_f64(f64(x))) } @(require_results) ln_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(ln_f64(f64(x))) }
ln_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))) } @(require_results) ln_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))) }
ln_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))) } @(require_results) ln_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))) }
ln :: proc{ ln :: proc{
ln_f16, ln_f16le, ln_f16be, ln_f16, ln_f16le, ln_f16be,
ln_f32, ln_f32le, ln_f32be, ln_f32, ln_f32le, ln_f32be,
+27 -26
View File
@@ -7,46 +7,47 @@ foreign import "odin_env"
@(default_calling_convention="c") @(default_calling_convention="c")
foreign odin_env { foreign odin_env {
@(link_name="sin") @(link_name="sin", require_results)
sin_f64 :: proc(θ: f64) -> f64 --- sin_f64 :: proc(θ: f64) -> f64 ---
@(link_name="cos") @(link_name="cos", require_results)
cos_f64 :: proc(θ: f64) -> f64 --- cos_f64 :: proc(θ: f64) -> f64 ---
@(link_name="pow") @(link_name="pow", require_results)
pow_f64 :: proc(x, power: f64) -> f64 --- pow_f64 :: proc(x, power: f64) -> f64 ---
@(link_name="fmuladd") @(link_name="fmuladd", require_results)
fmuladd_f64 :: proc(a, b, c: f64) -> f64 --- fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---
@(link_name="ln") @(link_name="ln", require_results)
ln_f64 :: proc(x: f64) -> f64 --- ln_f64 :: proc(x: f64) -> f64 ---
@(link_name="exp") @(link_name="exp", require_results)
exp_f64 :: proc(x: f64) -> f64 --- exp_f64 :: proc(x: f64) -> f64 ---
} }
@(require_results)
sqrt_f64 :: proc "contextless" (x: f64) -> f64 { sqrt_f64 :: proc "contextless" (x: f64) -> f64 {
return intrinsics.sqrt(x) return intrinsics.sqrt(x)
} }
sqrt_f16 :: proc "c" (x: f16) -> f16 { return f16(sqrt_f64(f64(x))) } @(require_results) sqrt_f16 :: proc "c" (x: f16) -> f16 { return f16(sqrt_f64(f64(x))) }
sin_f16 :: proc "c" (θ: f16) -> f16 { return f16(sin_f64(f64(θ))) } @(require_results) sin_f16 :: proc "c" (θ: f16) -> f16 { return f16(sin_f64(f64(θ))) }
cos_f16 :: proc "c" (θ: f16) -> f16 { return f16(cos_f64(f64(θ))) } @(require_results) cos_f16 :: proc "c" (θ: f16) -> f16 { return f16(cos_f64(f64(θ))) }
pow_f16 :: proc "c" (x, power: f16) -> f16 { return f16(pow_f64(f64(x), f64(power))) } @(require_results) pow_f16 :: proc "c" (x, power: f16) -> f16 { return f16(pow_f64(f64(x), f64(power))) }
fmuladd_f16 :: proc "c" (a, b, c: f16) -> f16 { return f16(fmuladd_f64(f64(a), f64(a), f64(c))) } @(require_results) fmuladd_f16 :: proc "c" (a, b, c: f16) -> f16 { return f16(fmuladd_f64(f64(a), f64(a), f64(c))) }
ln_f16 :: proc "c" (x: f16) -> f16 { return f16(ln_f64(f64(x))) } @(require_results) ln_f16 :: proc "c" (x: f16) -> f16 { return f16(ln_f64(f64(x))) }
exp_f16 :: proc "c" (x: f16) -> f16 { return f16(exp_f64(f64(x))) } @(require_results) exp_f16 :: proc "c" (x: f16) -> f16 { return f16(exp_f64(f64(x))) }
sqrt_f32 :: proc "c" (x: f32) -> f32 { return f32(sqrt_f64(f64(x))) } @(require_results) sqrt_f32 :: proc "c" (x: f32) -> f32 { return f32(sqrt_f64(f64(x))) }
sin_f32 :: proc "c" (θ: f32) -> f32 { return f32(sin_f64(f64(θ))) } @(require_results) sin_f32 :: proc "c" (θ: f32) -> f32 { return f32(sin_f64(f64(θ))) }
cos_f32 :: proc "c" (θ: f32) -> f32 { return f32(cos_f64(f64(θ))) } @(require_results) cos_f32 :: proc "c" (θ: f32) -> f32 { return f32(cos_f64(f64(θ))) }
pow_f32 :: proc "c" (x, power: f32) -> f32 { return f32(pow_f64(f64(x), f64(power))) } @(require_results) pow_f32 :: proc "c" (x, power: f32) -> f32 { return f32(pow_f64(f64(x), f64(power))) }
fmuladd_f32 :: proc "c" (a, b, c: f32) -> f32 { return f32(fmuladd_f64(f64(a), f64(a), f64(c))) } @(require_results) fmuladd_f32 :: proc "c" (a, b, c: f32) -> f32 { return f32(fmuladd_f64(f64(a), f64(a), f64(c))) }
ln_f32 :: proc "c" (x: f32) -> f32 { return f32(ln_f64(f64(x))) } @(require_results) ln_f32 :: proc "c" (x: f32) -> f32 { return f32(ln_f64(f64(x))) }
exp_f32 :: proc "c" (x: f32) -> f32 { return f32(exp_f64(f64(x))) } @(require_results) exp_f32 :: proc "c" (x: f32) -> f32 { return f32(exp_f64(f64(x))) }
ln_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(ln_f64(f64(x))) } @(require_results) ln_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(ln_f64(f64(x))) }
ln_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(ln_f64(f64(x))) } @(require_results) ln_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(ln_f64(f64(x))) }
ln_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(ln_f64(f64(x))) } @(require_results) ln_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(ln_f64(f64(x))) }
ln_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(ln_f64(f64(x))) } @(require_results) ln_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(ln_f64(f64(x))) }
ln_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))) } @(require_results) ln_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))) }
ln_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))) } @(require_results) ln_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))) }
ln :: proc{ ln :: proc{
ln_f16, ln_f16le, ln_f16be, ln_f16, ln_f16le, ln_f16be,
ln_f32, ln_f32le, ln_f32be, ln_f32, ln_f32le, ln_f32be,
+14 -12
View File
@@ -117,13 +117,14 @@ erf :: proc{
erf_f64, erf_f64,
} }
erf_f16 :: proc "contextless" (x: f16) -> f16 { return f16(erf_f64(f64(x))) } @(require_results) erf_f16 :: proc "contextless" (x: f16) -> f16 { return f16(erf_f64(f64(x))) }
erf_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(erf_f64(f64(x))) } @(require_results) erf_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(erf_f64(f64(x))) }
erf_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(erf_f64(f64(x))) } @(require_results) erf_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(erf_f64(f64(x))) }
erf_f32 :: proc "contextless" (x: f32) -> f32 { return f32(erf_f64(f64(x))) } @(require_results) erf_f32 :: proc "contextless" (x: f32) -> f32 { return f32(erf_f64(f64(x))) }
erf_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(erf_f64(f64(x))) } @(require_results) erf_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(erf_f64(f64(x))) }
erf_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(erf_f64(f64(x))) } @(require_results) erf_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(erf_f64(f64(x))) }
@(require_results)
erf_f64 :: proc "contextless" (x: f64) -> f64 { erf_f64 :: proc "contextless" (x: f64) -> f64 {
erx :: 0h3FEB0AC160000000 erx :: 0h3FEB0AC160000000
// Coefficients for approximation to erf in [0, 0.84375] // Coefficients for approximation to erf in [0, 0.84375]
@@ -268,13 +269,14 @@ erfc :: proc{
erfc_f64, erfc_f64,
} }
erfc_f16 :: proc "contextless" (x: f16) -> f16 { return f16(erfc_f64(f64(x))) } @(require_results) erfc_f16 :: proc "contextless" (x: f16) -> f16 { return f16(erfc_f64(f64(x))) }
erfc_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(erfc_f64(f64(x))) } @(require_results) erfc_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(erfc_f64(f64(x))) }
erfc_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(erfc_f64(f64(x))) } @(require_results) erfc_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(erfc_f64(f64(x))) }
erfc_f32 :: proc "contextless" (x: f32) -> f32 { return f32(erfc_f64(f64(x))) } @(require_results) erfc_f32 :: proc "contextless" (x: f32) -> f32 { return f32(erfc_f64(f64(x))) }
erfc_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(erfc_f64(f64(x))) } @(require_results) erfc_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(erfc_f64(f64(x))) }
erfc_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(erfc_f64(f64(x))) } @(require_results) erfc_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(erfc_f64(f64(x))) }
@(require_results)
erfc_f64 :: proc "contextless" (x: f64) -> f64 { erfc_f64 :: proc "contextless" (x: f64) -> f64 {
erx :: 0h3FEB0AC160000000 erx :: 0h3FEB0AC160000000
// Coefficients for approximation to erf in [0, 0.84375] // Coefficients for approximation to erf in [0, 0.84375]
+10 -9
View File
@@ -65,7 +65,7 @@ package math
// The polynomial is valid for 33 <= x <= 172; larger values are only used // The polynomial is valid for 33 <= x <= 172; larger values are only used
// in reciprocal and produce denormalized floats. The lower precision there // in reciprocal and produce denormalized floats. The lower precision there
// masks any imprecision in the polynomial. // masks any imprecision in the polynomial.
@(private="file") @(private="file", require_results)
stirling :: proc "contextless" (x: f64) -> (f64, f64) { stirling :: proc "contextless" (x: f64) -> (f64, f64) {
@(static) gamS := [?]f64{ @(static) gamS := [?]f64{
+7.87311395793093628397e-04, +7.87311395793093628397e-04,
@@ -93,6 +93,7 @@ stirling :: proc "contextless" (x: f64) -> (f64, f64) {
return y1, SQRT_TWO_PI * w * y2 return y1, SQRT_TWO_PI * w * y2
} }
@(require_results)
gamma_f64 :: proc "contextless" (x: f64) -> f64 { gamma_f64 :: proc "contextless" (x: f64) -> f64 {
is_neg_int :: proc "contextless" (x: f64) -> bool { is_neg_int :: proc "contextless" (x: f64) -> bool {
if x < 0 { if x < 0 {
@@ -210,14 +211,14 @@ gamma_f64 :: proc "contextless" (x: f64) -> f64 {
} }
gamma_f16 :: proc "contextless" (x: f16) -> f16 { return f16(gamma_f64(f64(x))) } @(require_results) gamma_f16 :: proc "contextless" (x: f16) -> f16 { return f16(gamma_f64(f64(x))) }
gamma_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(gamma_f64(f64(x))) } @(require_results) gamma_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(gamma_f64(f64(x))) }
gamma_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(gamma_f64(f64(x))) } @(require_results) gamma_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(gamma_f64(f64(x))) }
gamma_f32 :: proc "contextless" (x: f32) -> f32 { return f32(gamma_f64(f64(x))) } @(require_results) gamma_f32 :: proc "contextless" (x: f32) -> f32 { return f32(gamma_f64(f64(x))) }
gamma_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(gamma_f64(f64(x))) } @(require_results) gamma_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(gamma_f64(f64(x))) }
gamma_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(gamma_f64(f64(x))) } @(require_results) gamma_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(gamma_f64(f64(x))) }
gamma_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(gamma_f64(f64(x))) } @(require_results) gamma_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(gamma_f64(f64(x))) }
gamma_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(gamma_f64(f64(x))) } @(require_results) gamma_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(gamma_f64(f64(x))) }
gamma :: proc{ gamma :: proc{
gamma_f16, gamma_f16le, gamma_f16be, gamma_f16, gamma_f16le, gamma_f16be,
+10 -8
View File
@@ -80,7 +80,9 @@ package math
// //
@(require_results)
lgamma_f64 :: proc "contextless" (x: f64) -> (lgamma: f64, sign: int) { lgamma_f64 :: proc "contextless" (x: f64) -> (lgamma: f64, sign: int) {
@(require_results)
sin_pi :: proc "contextless" (x: f64) -> f64 { sin_pi :: proc "contextless" (x: f64) -> f64 {
if x < 0.25 { if x < 0.25 {
return -sin(PI * x) return -sin(PI * x)
@@ -345,14 +347,14 @@ lgamma_f64 :: proc "contextless" (x: f64) -> (lgamma: f64, sign: int) {
} }
lgamma_f16 :: proc "contextless" (x: f16) -> (lgamma: f16, sign: int) { r, s := lgamma_f64(f64(x)); return f16(r), s } @(require_results) lgamma_f16 :: proc "contextless" (x: f16) -> (lgamma: f16, sign: int) { r, s := lgamma_f64(f64(x)); return f16(r), s }
lgamma_f32 :: proc "contextless" (x: f32) -> (lgamma: f32, sign: int) { r, s := lgamma_f64(f64(x)); return f32(r), s } @(require_results) lgamma_f32 :: proc "contextless" (x: f32) -> (lgamma: f32, sign: int) { r, s := lgamma_f64(f64(x)); return f32(r), s }
lgamma_f16le :: proc "contextless" (x: f16le) -> (lgamma: f16le, sign: int) { r, s := lgamma_f64(f64(x)); return f16le(r), s } @(require_results) lgamma_f16le :: proc "contextless" (x: f16le) -> (lgamma: f16le, sign: int) { r, s := lgamma_f64(f64(x)); return f16le(r), s }
lgamma_f16be :: proc "contextless" (x: f16be) -> (lgamma: f16be, sign: int) { r, s := lgamma_f64(f64(x)); return f16be(r), s } @(require_results) lgamma_f16be :: proc "contextless" (x: f16be) -> (lgamma: f16be, sign: int) { r, s := lgamma_f64(f64(x)); return f16be(r), s }
lgamma_f32le :: proc "contextless" (x: f32le) -> (lgamma: f32le, sign: int) { r, s := lgamma_f64(f64(x)); return f32le(r), s } @(require_results) lgamma_f32le :: proc "contextless" (x: f32le) -> (lgamma: f32le, sign: int) { r, s := lgamma_f64(f64(x)); return f32le(r), s }
lgamma_f32be :: proc "contextless" (x: f32be) -> (lgamma: f32be, sign: int) { r, s := lgamma_f64(f64(x)); return f32be(r), s } @(require_results) lgamma_f32be :: proc "contextless" (x: f32be) -> (lgamma: f32be, sign: int) { r, s := lgamma_f64(f64(x)); return f32be(r), s }
lgamma_f64le :: proc "contextless" (x: f64le) -> (lgamma: f64le, sign: int) { r, s := lgamma_f64(f64(x)); return f64le(r), s } @(require_results) lgamma_f64le :: proc "contextless" (x: f64le) -> (lgamma: f64le, sign: int) { r, s := lgamma_f64(f64(x)); return f64le(r), s }
lgamma_f64be :: proc "contextless" (x: f64be) -> (lgamma: f64be, sign: int) { r, s := lgamma_f64(f64(x)); return f64be(r), s } @(require_results) lgamma_f64be :: proc "contextless" (x: f64be) -> (lgamma: f64be, sign: int) { r, s := lgamma_f64(f64(x)); return f64be(r), s }
lgamma :: proc{ lgamma :: proc{
lgamma_f16, lgamma_f16le, lgamma_f16be, lgamma_f16, lgamma_f16le, lgamma_f16be,
+9 -8
View File
@@ -90,15 +90,16 @@ log1p :: proc {
log1p_f64le, log1p_f64le,
log1p_f64be, log1p_f64be,
} }
log1p_f16 :: proc "contextless" (x: f16) -> f16 { return f16(log1p_f64(f64(x))) } @(require_results) log1p_f16 :: proc "contextless" (x: f16) -> f16 { return f16(log1p_f64(f64(x))) }
log1p_f32 :: proc "contextless" (x: f32) -> f32 { return f32(log1p_f64(f64(x))) } @(require_results) log1p_f32 :: proc "contextless" (x: f32) -> f32 { return f32(log1p_f64(f64(x))) }
log1p_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(log1p_f64(f64(x))) } @(require_results) log1p_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(log1p_f64(f64(x))) }
log1p_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(log1p_f64(f64(x))) } @(require_results) log1p_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(log1p_f64(f64(x))) }
log1p_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(log1p_f64(f64(x))) } @(require_results) log1p_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(log1p_f64(f64(x))) }
log1p_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(log1p_f64(f64(x))) } @(require_results) log1p_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(log1p_f64(f64(x))) }
log1p_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(log1p_f64(f64(x))) } @(require_results) log1p_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(log1p_f64(f64(x))) }
log1p_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(log1p_f64(f64(x))) } @(require_results) log1p_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(log1p_f64(f64(x))) }
@(require_results)
log1p_f64 :: proc "contextless" (x: f64) -> f64 { log1p_f64 :: proc "contextless" (x: f64) -> f64 {
SQRT2_M1 :: 0h3fda827999fcef34 // sqrt(2)-1 SQRT2_M1 :: 0h3fda827999fcef34 // sqrt(2)-1
SQRT2_HALF_M1 :: 0hbfd2bec333018866 // sqrt(2)/2-1 SQRT2_HALF_M1 :: 0hbfd2bec333018866 // sqrt(2)/2-1
+308
View File
@@ -0,0 +1,308 @@
package math
import "core:math/bits"
// The original C code, the long comment, and the constants
// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
// available from http://www.netlib.org/cephes/cmath.tgz.
// The go code is a simplified version of the original C.
//
// sin.c
//
// Circular sine
//
// SYNOPSIS:
//
// double x, y, sin();
// y = sin( x );
//
// DESCRIPTION:
//
// Range reduction is into intervals of pi/4. The reduction error is nearly
// eliminated by contriving an extended precision modular arithmetic.
//
// Two polynomial approximating functions are employed.
// Between 0 and pi/4 the sine is approximated by
// x + x**3 P(x**2).
// Between pi/4 and pi/2 the cosine is represented as
// 1 - x**2 Q(x**2).
//
// ACCURACY:
//
// Relative error:
// arithmetic domain # trials peak rms
// DEC 0, 10 150000 3.0e-17 7.8e-18
// IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17
//
// Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9. The loss
// is not gradual, but jumps suddenly to about 1 part in 10e7. Results may
// be meaningless for x > 2**49 = 5.6e14.
//
// cos.c
//
// Circular cosine
//
// SYNOPSIS:
//
// double x, y, cos();
// y = cos( x );
//
// DESCRIPTION:
//
// Range reduction is into intervals of pi/4. The reduction error is nearly
// eliminated by contriving an extended precision modular arithmetic.
//
// Two polynomial approximating functions are employed.
// Between 0 and pi/4 the cosine is approximated by
// 1 - x**2 Q(x**2).
// Between pi/4 and pi/2 the sine is represented as
// x + x**3 P(x**2).
//
// ACCURACY:
//
// Relative error:
// arithmetic domain # trials peak rms
// IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17
// DEC 0,+1.07e9 17000 3.0e-17 7.2e-18
//
// Cephes Math Library Release 2.8: June, 2000
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
//
// The readme file at http://netlib.sandia.gov/cephes/ says:
// Some software in this archive may be from the book _Methods and
// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
// International, 1989) or from the Cephes Mathematical Library, a
// commercial product. In either event, it is copyrighted by the author.
// What you see here may be used freely but it comes with no support or
// guarantee.
//
// The two known misprints in the book are repaired here in the
// source listings for the gamma function and the incomplete beta
// integral.
//
// Stephen L. Moshier
// moshier@na-net.ornl.gov
sincos :: proc{
sincos_f16, sincos_f16le, sincos_f16be,
sincos_f32, sincos_f32le, sincos_f32be,
sincos_f64, sincos_f64le, sincos_f64be,
}
sincos_f16 :: proc "contextless" (x: f16) -> (sin, cos: f16) #no_bounds_check {
s, c := sincos_f64(f64(x))
return f16(s), f16(c)
}
sincos_f16le :: proc "contextless" (x: f16le) -> (sin, cos: f16le) #no_bounds_check {
s, c := sincos_f64(f64(x))
return f16le(s), f16le(c)
}
sincos_f16be :: proc "contextless" (x: f16be) -> (sin, cos: f16be) #no_bounds_check {
s, c := sincos_f64(f64(x))
return f16be(s), f16be(c)
}
sincos_f32 :: proc "contextless" (x: f32) -> (sin, cos: f32) #no_bounds_check {
s, c := sincos_f64(f64(x))
return f32(s), f32(c)
}
sincos_f32le :: proc "contextless" (x: f32le) -> (sin, cos: f32le) #no_bounds_check {
s, c := sincos_f64(f64(x))
return f32le(s), f32le(c)
}
sincos_f32be :: proc "contextless" (x: f32be) -> (sin, cos: f32be) #no_bounds_check {
s, c := sincos_f64(f64(x))
return f32be(s), f32be(c)
}
sincos_f64le :: proc "contextless" (x: f64le) -> (sin, cos: f64le) #no_bounds_check {
s, c := sincos_f64(f64(x))
return f64le(s), f64le(c)
}
sincos_f64be :: proc "contextless" (x: f64be) -> (sin, cos: f64be) #no_bounds_check {
s, c := sincos_f64(f64(x))
return f64be(s), f64be(c)
}
sincos_f64 :: proc "contextless" (x: f64) -> (sin, cos: f64) #no_bounds_check {
x := x
PI4A :: 0h3fe921fb40000000 // 7.85398125648498535156e-1 PI/4 split into three parts
PI4B :: 0h3e64442d00000000 // 3.77489470793079817668e-8
PI4C :: 0h3ce8469898cc5170 // 2.69515142907905952645e-15
// special cases
switch {
case x == 0:
return x, 1 // return ±0.0, 1.0
case is_nan(x) || is_inf(x, 0):
return nan_f64(), nan_f64()
}
// make argument positive
sin_sign, cos_sign := false, false
if x < 0 {
x = -x
sin_sign = true
}
j: u64
y, z: f64
if x >= REDUCE_THRESHOLD {
j, z = _trig_reduce_f64(x)
} else {
j = u64(x * (4 / PI)) // integer part of x/(PI/4), as integer for tests on the phase angle
y = f64(j) // integer part of x/(PI/4), as float
if j&1 == 1 { // map zeros to origin
j += 1
y += 1
}
j &= 7 // octant modulo TAU radians (360 degrees)
z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
}
if j > 3 { // reflect in x axis
j -= 4
sin_sign, cos_sign = !sin_sign, !cos_sign
}
if j > 1 {
cos_sign = !cos_sign
}
zz := z * z
cos = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
sin = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
if j == 1 || j == 2 {
sin, cos = cos, sin
}
if cos_sign {
cos = -cos
}
if sin_sign {
sin = -sin
}
return
}
// sin coefficients
@(private="file")
_sin := [?]f64{
0h3de5d8fd1fd19ccd, // 1.58962301576546568060e-10
0hbe5ae5e5a9291f5d, // -2.50507477628578072866e-8
0h3ec71de3567d48a1, // 2.75573136213857245213e-6
0hbf2a01a019bfdf03, // -1.98412698295895385996e-4
0h3f8111111110f7d0, // 8.33333333332211858878e-3
0hbfc5555555555548, // -1.66666666666666307295e-1
}
// cos coefficients
@(private="file")
_cos := [?]f64{
0hbda8fa49a0861a9b, // -1.13585365213876817300e-11,
0h3e21ee9d7b4e3f05, // 2.08757008419747316778e-9,
0hbe927e4f7eac4bc6, // -2.75573141792967388112e-7,
0h3efa01a019c844f5, // 2.48015872888517045348e-5,
0hbf56c16c16c14f91, // -1.38888888888730564116e-3,
0h3fa555555555554b, // 4.16666666666665929218e-2,
}
// REDUCE_THRESHOLD is the maximum value of x where the reduction using Pi/4
// in 3 f64 parts still gives accurate results. This threshold
// is set by y*C being representable as a f64 without error
// where y is given by y = floor(x * (4 / Pi)) and C is the leading partial
// terms of 4/Pi. Since the leading terms (PI4A and PI4B in sin.go) have 30
// and 32 trailing zero bits, y should have less than 30 significant bits.
//
// y < 1<<30 -> floor(x*4/Pi) < 1<<30 -> x < (1<<30 - 1) * Pi/4
//
// So, conservatively we can take x < 1<<29.
// Above this threshold Payne-Hanek range reduction must be used.
@(private="file")
REDUCE_THRESHOLD :: 1 << 29
// _trig_reduce_f64 implements Payne-Hanek range reduction by Pi/4
// for x > 0. It returns the integer part mod 8 (j) and
// the fractional part (z) of x / (Pi/4).
// The implementation is based on:
// "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit"
// K. C. Ng et al, March 24, 1992
// The simulated multi-precision calculation of x*B uses 64-bit integer arithmetic.
_trig_reduce_f64 :: proc "contextless" (x: f64) -> (j: u64, z: f64) #no_bounds_check {
// bd_pi4 is the binary digits of 4/pi as a u64 array,
// that is, 4/pi = Sum bd_pi4[i]*2^(-64*i)
// 19 64-bit digits and the leading one bit give 1217 bits
// of precision to handle the largest possible f64 exponent.
@static bd_pi4 := [?]u64{
0x0000000000000001,
0x45f306dc9c882a53,
0xf84eafa3ea69bb81,
0xb6c52b3278872083,
0xfca2c757bd778ac3,
0x6e48dc74849ba5c0,
0x0c925dd413a32439,
0xfc3bd63962534e7d,
0xd1046bea5d768909,
0xd338e04d68befc82,
0x7323ac7306a673e9,
0x3908bf177bf25076,
0x3ff12fffbc0b301f,
0xde5e2316b414da3e,
0xda6cfd9e4f96136e,
0x9e8c7ecd3cbfd45a,
0xea4f758fd7cbe2f6,
0x7a0e73ef14a525d4,
0xd7f6bf623f1aba10,
0xac06608df8f6d757,
}
PI4 :: PI / 4
if x < PI4 {
return 0, x
}
MASK :: 0x7FF
SHIFT :: 64 - 11 - 1
BIAS :: 1023
// Extract out the integer and exponent such that,
// x = ix * 2 ** exp.
ix := transmute(u64)x
exp := int(ix>>SHIFT&MASK) - BIAS - SHIFT
ix &~= MASK << SHIFT
ix |= 1 << SHIFT
// Use the exponent to extract the 3 appropriate u64 digits from bd_pi4,
// B ~ (z0, z1, z2), such that the product leading digit has the exponent -61.
// Note, exp >= -53 since x >= PI4 and exp < 971 for maximum f64.
digit, bitshift := uint(exp+61)/64, uint(exp+61)%64
z0 := (bd_pi4[digit] << bitshift) | (bd_pi4[digit+1] >> (64 - bitshift))
z1 := (bd_pi4[digit+1] << bitshift) | (bd_pi4[digit+2] >> (64 - bitshift))
z2 := (bd_pi4[digit+2] << bitshift) | (bd_pi4[digit+3] >> (64 - bitshift))
// Multiply mantissa by the digits and extract the upper two digits (hi, lo).
z2hi, _ := bits.mul(z2, ix)
z1hi, z1lo := bits.mul(z1, ix)
z0lo := z0 * ix
lo, c := bits.add(z1lo, z2hi, 0)
hi, _ := bits.add(z0lo, z1hi, c)
// The top 3 bits are j.
j = hi >> 61
// Extract the fraction and find its magnitude.
hi = hi<<3 | lo>>61
lz := uint(bits.leading_zeros(hi))
e := u64(BIAS - (lz + 1))
// Clear implicit mantissa bit and shift into place.
hi = (hi << (lz + 1)) | (lo >> (64 - (lz + 1)))
hi >>= 64 - SHIFT
// Include the exponent and convert to a float.
hi |= e << SHIFT
z = transmute(f64)hi
// Map zeros to origin.
if j&1 == 1 {
j += 1
j &= 7
z -= 1
}
// Multiply the fractional part by pi/4.
return j, z * PI4
}
+9
View File
@@ -20,6 +20,7 @@ Vec4 :: [4]f64
/* /*
2D Simplex noise, standard lattice orientation. 2D Simplex noise, standard lattice orientation.
*/ */
@(require_results)
noise_2d :: proc(seed: i64, coord: Vec2) -> (value: f32) { noise_2d :: proc(seed: i64, coord: Vec2) -> (value: f32) {
// Get points for A2* lattice // Get points for A2* lattice
skew := SKEW_2D * (coord.x + coord.y) skew := SKEW_2D * (coord.x + coord.y)
@@ -35,6 +36,7 @@ noise_2d :: proc(seed: i64, coord: Vec2) -> (value: f32) {
unless your map is centered around an equator. It's a subtle unless your map is centered around an equator. It's a subtle
difference, but the option is here to make it an easy choice. difference, but the option is here to make it an easy choice.
*/ */
@(require_results)
noise_2d_improve_x :: proc(seed: i64, coord: Vec2) -> (value: f32) { noise_2d_improve_x :: proc(seed: i64, coord: Vec2) -> (value: f32) {
// Skew transform and rotation baked into one. // Skew transform and rotation baked into one.
xx := coord.x * ROOT_2_OVER_2 xx := coord.x * ROOT_2_OVER_2
@@ -51,6 +53,7 @@ noise_2d_improve_x :: proc(seed: i64, coord: Vec2) -> (value: f32) {
If Z is vertical in world coordinates, call `noise_3d_improve_xz(x, y, Z)`. If Z is vertical in world coordinates, call `noise_3d_improve_xz(x, y, Z)`.
For a time varied animation, call `noise_3d_improve_xz(x, y, T)`. For a time varied animation, call `noise_3d_improve_xz(x, y, T)`.
*/ */
@(require_results)
noise_3d_improve_xy :: proc(seed: i64, coord: Vec3) -> (value: f32) { noise_3d_improve_xy :: proc(seed: i64, coord: Vec3) -> (value: f32) {
/* /*
Re-orient the cubic lattices without skewing, so Z points up the main lattice diagonal, Re-orient the cubic lattices without skewing, so Z points up the main lattice diagonal,
@@ -75,6 +78,7 @@ noise_3d_improve_xy :: proc(seed: i64, coord: Vec3) -> (value: f32) {
If Z is vertical in world coordinates, call `noise_3d_improve_xz(x, Z, y)` or use `noise_3d_improve_xy`. If Z is vertical in world coordinates, call `noise_3d_improve_xz(x, Z, y)` or use `noise_3d_improve_xy`.
For a time varied animation, call `noise_3d_improve_xz(x, T, y)` or use `noise_3d_improve_xy`. For a time varied animation, call `noise_3d_improve_xz(x, T, y)` or use `noise_3d_improve_xy`.
*/ */
@(require_results)
noise_3d_improve_xz :: proc(seed: i64, coord: Vec3) -> (value: f32) { noise_3d_improve_xz :: proc(seed: i64, coord: Vec3) -> (value: f32) {
/* /*
Re-orient the cubic lattices without skewing, so Y points up the main lattice diagonal, Re-orient the cubic lattices without skewing, so Y points up the main lattice diagonal,
@@ -96,6 +100,7 @@ noise_3d_improve_xz :: proc(seed: i64, coord: Vec3) -> (value: f32) {
Use `noise_3d_improve_xy` or `noise_3d_improve_xz` instead, wherever appropriate. Use `noise_3d_improve_xy` or `noise_3d_improve_xz` instead, wherever appropriate.
They have less diagonal bias. This function's best use is as a fallback. They have less diagonal bias. This function's best use is as a fallback.
*/ */
@(require_results)
noise_3d_fallback :: proc(seed: i64, coord: Vec3) -> (value: f32) { noise_3d_fallback :: proc(seed: i64, coord: Vec3) -> (value: f32) {
/* /*
Re-orient the cubic lattices via rotation, to produce a familiar look. Re-orient the cubic lattices via rotation, to produce a familiar look.
@@ -114,6 +119,7 @@ noise_3d_fallback :: proc(seed: i64, coord: Vec3) -> (value: f32) {
Recommended for time-varied animations which texture a 3D object (W=time) Recommended for time-varied animations which texture a 3D object (W=time)
in a space where Z is vertical. in a space where Z is vertical.
*/ */
@(require_results)
noise_4d_improve_xyz_improve_xy :: proc(seed: i64, coord: Vec4) -> (value: f32) { noise_4d_improve_xyz_improve_xy :: proc(seed: i64, coord: Vec4) -> (value: f32) {
xy := coord.x + coord.y xy := coord.x + coord.y
s2 := xy * -0.21132486540518699998 s2 := xy * -0.21132486540518699998
@@ -133,6 +139,7 @@ noise_4d_improve_xyz_improve_xy :: proc(seed: i64, coord: Vec4) -> (value: f32)
Recommended for time-varied animations which texture a 3D object (W=time) Recommended for time-varied animations which texture a 3D object (W=time)
in a space where Y is vertical. in a space where Y is vertical.
*/ */
@(require_results)
noise_4d_improve_xyz_improve_xz :: proc(seed: i64, coord: Vec4) -> (value: f32) { noise_4d_improve_xyz_improve_xz :: proc(seed: i64, coord: Vec4) -> (value: f32) {
xz := coord.x + coord.z xz := coord.x + coord.z
s2 := xz * -0.21132486540518699998 s2 := xz * -0.21132486540518699998
@@ -152,6 +159,7 @@ noise_4d_improve_xyz_improve_xz :: proc(seed: i64, coord: Vec4) -> (value: f32)
Recommended for time-varied animations which texture a 3D object (W=time) Recommended for time-varied animations which texture a 3D object (W=time)
where there isn't a clear distinction between horizontal and vertical where there isn't a clear distinction between horizontal and vertical
*/ */
@(require_results)
noise_4d_improve_xyz :: proc(seed: i64, coord: Vec4) -> (value: f32) { noise_4d_improve_xyz :: proc(seed: i64, coord: Vec4) -> (value: f32) {
xyz := coord.x + coord.y + coord.z xyz := coord.x + coord.y + coord.z
ww := coord.w * 0.2236067977499788 ww := coord.w * 0.2236067977499788
@@ -164,6 +172,7 @@ noise_4d_improve_xyz :: proc(seed: i64, coord: Vec4) -> (value: f32) {
/* /*
4D OpenSimplex2 noise, fallback lattice orientation. 4D OpenSimplex2 noise, fallback lattice orientation.
*/ */
@(require_results)
noise_4d_fallback :: proc(seed: i64, coord: Vec4) -> (value: f32) { noise_4d_fallback :: proc(seed: i64, coord: Vec4) -> (value: f32) {
// Get points for A4 lattice // Get points for A4 lattice
skew := f64(SKEW_4D) * (coord.x + coord.y + coord.z + coord.w) skew := f64(SKEW_4D) * (coord.x + coord.y + coord.z + coord.w)
+26
View File
@@ -7,6 +7,7 @@ float32_uniform :: float32_range
// Triangular Distribution // Triangular Distribution
// See: http://wikipedia.org/wiki/Triangular_distribution // See: http://wikipedia.org/wiki/Triangular_distribution
@(require_results)
float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64), r: ^Rand = nil) -> f64 { float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64), r: ^Rand = nil) -> f64 {
if hi-lo == 0 { if hi-lo == 0 {
return lo return lo
@@ -24,6 +25,7 @@ float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64), r: ^Rand = nil) -> f64
} }
// Triangular Distribution // Triangular Distribution
// See: http://wikipedia.org/wiki/Triangular_distribution // See: http://wikipedia.org/wiki/Triangular_distribution
@(require_results)
float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32), r: ^Rand = nil) -> f32 { float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32), r: ^Rand = nil) -> f32 {
if hi-lo == 0 { if hi-lo == 0 {
return lo return lo
@@ -41,20 +43,24 @@ float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32), r: ^Rand = nil) -> f32
// Normal/Gaussian Distribution // Normal/Gaussian Distribution
@(require_results)
float64_normal :: proc(mean, stddev: f64, r: ^Rand = nil) -> f64 { float64_normal :: proc(mean, stddev: f64, r: ^Rand = nil) -> f64 {
return norm_float64(r) * stddev + mean return norm_float64(r) * stddev + mean
} }
// Normal/Gaussian Distribution // Normal/Gaussian Distribution
@(require_results)
float32_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 { float32_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
return f32(float64_normal(f64(mean), f64(stddev), r)) return f32(float64_normal(f64(mean), f64(stddev), r))
} }
// Log Normal Distribution // Log Normal Distribution
@(require_results)
float64_log_normal :: proc(mean, stddev: f64, r: ^Rand = nil) -> f64 { float64_log_normal :: proc(mean, stddev: f64, r: ^Rand = nil) -> f64 {
return math.exp(float64_normal(mean, stddev, r)) return math.exp(float64_normal(mean, stddev, r))
} }
// Log Normal Distribution // Log Normal Distribution
@(require_results)
float32_log_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 { float32_log_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
return f32(float64_log_normal(f64(mean), f64(stddev), r)) return f32(float64_log_normal(f64(mean), f64(stddev), r))
} }
@@ -65,6 +71,7 @@ float32_log_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
// Return values range from // Return values range from
// 0 to positive infinity if lambda > 0 // 0 to positive infinity if lambda > 0
// negative infinity to 0 if lambda <= 0 // negative infinity to 0 if lambda <= 0
@(require_results)
float64_exponential :: proc(lambda: f64, r: ^Rand = nil) -> f64 { float64_exponential :: proc(lambda: f64, r: ^Rand = nil) -> f64 {
return - math.ln(1 - float64(r)) / lambda return - math.ln(1 - float64(r)) / lambda
} }
@@ -73,6 +80,7 @@ float64_exponential :: proc(lambda: f64, r: ^Rand = nil) -> f64 {
// Return values range from // Return values range from
// 0 to positive infinity if lambda > 0 // 0 to positive infinity if lambda > 0
// negative infinity to 0 if lambda <= 0 // negative infinity to 0 if lambda <= 0
@(require_results)
float32_exponential :: proc(lambda: f32, r: ^Rand = nil) -> f32 { float32_exponential :: proc(lambda: f32, r: ^Rand = nil) -> f32 {
return f32(float64_exponential(f64(lambda), r)) return f32(float64_exponential(f64(lambda), r))
} }
@@ -87,6 +95,7 @@ float32_exponential :: proc(lambda: f32, r: ^Rand = nil) -> f32 {
// math.gamma(alpha) * math.pow(beta, alpha) // math.gamma(alpha) * math.pow(beta, alpha)
// //
// mean is alpha*beta, variance is math.pow(alpha*beta, 2) // mean is alpha*beta, variance is math.pow(alpha*beta, 2)
@(require_results)
float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 { float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
if alpha <= 0 || beta <= 0 { if alpha <= 0 || beta <= 0 {
panic(#procedure + ": alpha and beta must be > 0.0") panic(#procedure + ": alpha and beta must be > 0.0")
@@ -152,6 +161,7 @@ float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
// math.gamma(alpha) * math.pow(beta, alpha) // math.gamma(alpha) * math.pow(beta, alpha)
// //
// mean is alpha*beta, variance is math.pow(alpha*beta, 2) // mean is alpha*beta, variance is math.pow(alpha*beta, 2)
@(require_results)
float32_gamma :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 { float32_gamma :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_gamma(f64(alpha), f64(beta), r)) return f32(float64_gamma(f64(alpha), f64(beta), r))
} }
@@ -162,6 +172,7 @@ float32_gamma :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
// Required: alpha > 0 and beta > 0 // Required: alpha > 0 and beta > 0
// //
// Return values range between 0 and 1 // Return values range between 0 and 1
@(require_results)
float64_beta :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 { float64_beta :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
if alpha <= 0 || beta <= 0 { if alpha <= 0 || beta <= 0 {
panic(#procedure + ": alpha and beta must be > 0.0") panic(#procedure + ": alpha and beta must be > 0.0")
@@ -178,6 +189,7 @@ float64_beta :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
// Required: alpha > 0 and beta > 0 // Required: alpha > 0 and beta > 0
// //
// Return values range between 0 and 1 // Return values range between 0 and 1
@(require_results)
float32_beta :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 { float32_beta :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_beta(f64(alpha), f64(beta), r)) return f32(float64_beta(f64(alpha), f64(beta), r))
} }
@@ -185,22 +197,26 @@ float32_beta :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
// Pareto distribution, `alpha` is the shape parameter. // Pareto distribution, `alpha` is the shape parameter.
// https://wikipedia.org/wiki/Pareto_distribution // https://wikipedia.org/wiki/Pareto_distribution
@(require_results)
float64_pareto :: proc(alpha: f64, r: ^Rand = nil) -> f64 { float64_pareto :: proc(alpha: f64, r: ^Rand = nil) -> f64 {
return math.pow(1 - float64(r), -1.0 / alpha) return math.pow(1 - float64(r), -1.0 / alpha)
} }
// Pareto distribution, `alpha` is the shape parameter. // Pareto distribution, `alpha` is the shape parameter.
// https://wikipedia.org/wiki/Pareto_distribution // https://wikipedia.org/wiki/Pareto_distribution
@(require_results)
float32_pareto :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 { float32_pareto :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_pareto(f64(alpha), r)) return f32(float64_pareto(f64(alpha), r))
} }
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter. // Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
@(require_results)
float64_weibull :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 { float64_weibull :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
u := 1 - float64(r) u := 1 - float64(r)
return alpha * math.pow(-math.ln(u), 1.0/beta) return alpha * math.pow(-math.ln(u), 1.0/beta)
} }
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter. // Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
@(require_results)
float32_weibull :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 { float32_weibull :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_weibull(f64(alpha), f64(beta), r)) return f32(float64_weibull(f64(alpha), f64(beta), r))
} }
@@ -210,6 +226,7 @@ float32_weibull :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
// `mean_angle` is the in mean angle between 0 and 2pi radians // `mean_angle` is the in mean angle between 0 and 2pi radians
// `kappa` is the concentration parameter which must be >= 0 // `kappa` is the concentration parameter which must be >= 0
// When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi // When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi
@(require_results)
float64_von_mises :: proc(mean_angle, kappa: f64, r: ^Rand = nil) -> f64 { float64_von_mises :: proc(mean_angle, kappa: f64, r: ^Rand = nil) -> f64 {
// Fisher, N.I., "Statistical Analysis of Circular Data", Cambridge University Press, 1993. // Fisher, N.I., "Statistical Analysis of Circular Data", Cambridge University Press, 1993.
@@ -245,6 +262,7 @@ float64_von_mises :: proc(mean_angle, kappa: f64, r: ^Rand = nil) -> f64 {
// `mean_angle` is the in mean angle between 0 and 2pi radians // `mean_angle` is the in mean angle between 0 and 2pi radians
// `kappa` is the concentration parameter which must be >= 0 // `kappa` is the concentration parameter which must be >= 0
// When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi // When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi
@(require_results)
float32_von_mises :: proc(mean_angle, kappa: f32, r: ^Rand = nil) -> f32 { float32_von_mises :: proc(mean_angle, kappa: f32, r: ^Rand = nil) -> f32 {
return f32(float64_von_mises(f64(mean_angle), f64(kappa), r)) return f32(float64_von_mises(f64(mean_angle), f64(kappa), r))
} }
@@ -252,6 +270,7 @@ float32_von_mises :: proc(mean_angle, kappa: f32, r: ^Rand = nil) -> f32 {
// Cauchy-Lorentz Distribution // Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0 // `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
float64_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 { float64_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 {
assert(gamma > 0) assert(gamma > 0)
@@ -261,6 +280,7 @@ float64_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 {
} }
// Cauchy-Lorentz Distribution // Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0 // `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
float32_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 { float32_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
return f32(float64_cauchy_lorentz(f64(x_0), f64(gamma), r)) return f32(float64_cauchy_lorentz(f64(x_0), f64(gamma), r))
} }
@@ -268,12 +288,14 @@ float32_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
// Log Cauchy-Lorentz Distribution // Log Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0 // `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
float64_log_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 { float64_log_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 {
assert(gamma > 0) assert(gamma > 0)
return math.exp(math.tan(math.PI * (float64(r) - 0.5))*gamma + x_0) return math.exp(math.tan(math.PI * (float64(r) - 0.5))*gamma + x_0)
} }
// Log Cauchy-Lorentz Distribution // Log Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0 // `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
float32_log_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 { float32_log_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
return f32(float64_log_cauchy_lorentz(f64(x_0), f64(gamma), r)) return f32(float64_log_cauchy_lorentz(f64(x_0), f64(gamma), r))
} }
@@ -281,6 +303,7 @@ float32_log_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
// Laplace Distribution // Laplace Distribution
// `b` is the scale where `b` > 0 // `b` is the scale where `b` > 0
@(require_results)
float64_laplace :: proc(mean, b: f64, r: ^Rand = nil) -> f64 { float64_laplace :: proc(mean, b: f64, r: ^Rand = nil) -> f64 {
assert(b > 0) assert(b > 0)
p := float64(r)-0.5 p := float64(r)-0.5
@@ -288,6 +311,7 @@ float64_laplace :: proc(mean, b: f64, r: ^Rand = nil) -> f64 {
} }
// Laplace Distribution // Laplace Distribution
// `b` is the scale where `b` > 0 // `b` is the scale where `b` > 0
@(require_results)
float32_laplace :: proc(mean, b: f32, r: ^Rand = nil) -> f32 { float32_laplace :: proc(mean, b: f32, r: ^Rand = nil) -> f32 {
return f32(float64_laplace(f64(mean), f64(b), r)) return f32(float64_laplace(f64(mean), f64(b), r))
} }
@@ -296,6 +320,7 @@ float32_laplace :: proc(mean, b: f32, r: ^Rand = nil) -> f32 {
// Gompertz Distribution // Gompertz Distribution
// `eta` is the shape, `b` is the scale // `eta` is the shape, `b` is the scale
// Both `eta` and `b` must be > 0 // Both `eta` and `b` must be > 0
@(require_results)
float64_gompertz :: proc(eta, b: f64, r: ^Rand = nil) -> f64 { float64_gompertz :: proc(eta, b: f64, r: ^Rand = nil) -> f64 {
if eta <= 0 || b <= 0 { if eta <= 0 || b <= 0 {
panic(#procedure + ": eta and b must be > 0.0") panic(#procedure + ": eta and b must be > 0.0")
@@ -307,6 +332,7 @@ float64_gompertz :: proc(eta, b: f64, r: ^Rand = nil) -> f64 {
// Gompertz Distribution // Gompertz Distribution
// `eta` is the shape, `b` is the scale // `eta` is the shape, `b` is the scale
// Both `eta` and `b` must be > 0 // Both `eta` and `b` must be > 0
@(require_results)
float32_gompertz :: proc(eta, b: f32, r: ^Rand = nil) -> f32 { float32_gompertz :: proc(eta, b: f32, r: ^Rand = nil) -> f32 {
return f32(float64_gompertz(f64(eta), f64(b), r)) return f32(float64_gompertz(f64(eta), f64(b), r))
} }
+1
View File
@@ -15,6 +15,7 @@ import "core:math"
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf] // https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
// https://www.jstatsoft.org/article/view/v005i08 [web page] // https://www.jstatsoft.org/article/view/v005i08 [web page]
// //
@(require_results)
exp_float64 :: proc(r: ^Rand = nil) -> f64 { exp_float64 :: proc(r: ^Rand = nil) -> f64 {
re :: 7.69711747013104972 re :: 7.69711747013104972

Some files were not shown because too many files have changed in this diff Show More