Compare commits

...

186 Commits

Author SHA1 Message Date
gingerBill a04d849e30 core:container/lru 2022-02-01 15:24:37 +00:00
gingerBill 8c9505505a Add allocator parameter to rand.perm 2022-02-01 15:23:49 +00:00
gingerBill eac74631ec Correct debug information logic for procedure parameters 2022-02-01 14:11:19 +00:00
gingerBill 85706d559d Fix typo 2022-01-31 20:19:46 +00:00
gingerBill 67ba05cb7c Correct false positive check in check_unique_package_names 2022-01-31 19:33:02 +00:00
gingerBill 2f1aeaf757 Remove the unneeded $ 2022-01-31 15:56:40 +00:00
gingerBill 14a17fb36f Add slice.stable_sort* procedures 2022-01-31 15:55:52 +00:00
gingerBill 1a9ec776cb Unify logic for slice.sort* related procedures 2022-01-31 12:43:20 +00:00
gingerBill da1edac56d Enforce -strict-style in CI 2022-01-31 11:29:05 +00:00
gingerBill 44ec95a983 Fix all_main.odin 2022-01-30 21:55:55 +00:00
gingerBill 1502066303 Correct CI 2022-01-30 21:43:42 +00:00
gingerBill 35a826a0fd Update CI to do odin check examples/all 2022-01-30 21:38:34 +00:00
gingerBill ebb8ca7c26 Add round to linalg_glsl_math.odin 2022-01-30 21:35:05 +00:00
gingerBill 763de44853 Merge pull request #1461 from AquaGeneral/master
Added round to HLSL and GLSL, and isinf/isfinite + isnan to HLSL
2022-01-30 10:46:13 +00:00
Jesse Stiller 62cc752066 Added round to HLSL and GLSL, and isinf/isfinite + isnan to HLSL 2022-01-30 13:57:01 +10:00
gingerBill 965b962b29 Merge pull request #1459 from powerc9000/clay-macos-fixes
Fix mutex and conditions trying to be destroyed twice in unix
2022-01-28 00:24:29 +00:00
powerc9000 2f3c5336d9 Fix mutex and conditions trying to be destroyed twice in unix 2022-01-27 15:38:16 -07:00
gingerBill 3824937295 Remove debug code 2022-01-27 16:30:22 +00:00
gingerBill fc8ddcef5c Merge branch 'master' of https://github.com/odin-lang/Odin 2022-01-27 16:09:44 +00:00
gingerBill 3165b7cf95 Add rand.exp_float64 2022-01-27 16:09:33 +00:00
gingerBill 5eea23cf76 Fix typo 2022-01-27 16:09:05 +00:00
gingerBill 2aa783179e Update doc_format.odin 2022-01-27 16:08:58 +00:00
gingerBill 24e7356825 Add #no_type_assert and #type_assert to disable implicit type assertions with x.(T) 2022-01-27 16:08:47 +00:00
Jeroen van Rijn 2fcba25e50 Merge pull request #1458 from Kelimion/zlib_fix
Fix DEFLATE stored block handling.
2022-01-27 15:10:33 +01:00
Jeroen van Rijn 28bc274449 Fix DEFLATE stored block handling. 2022-01-27 14:58:45 +01:00
gingerBill 16786aac78 Correct int31_max etc 2022-01-27 12:33:34 +00:00
gingerBill 32b37f3429 Support built-in procedures for doc format 2022-01-27 00:08:05 +00:00
gingerBill 5808793cae Merge branch 'master' of https://github.com/odin-lang/Odin 2022-01-26 23:31:53 +00:00
gingerBill 7e11f3cc4b Update doc format to allow for aliases 2022-01-26 23:31:47 +00:00
gingerBill 714ab516c5 Merge pull request #1454 from jasonKercher/fix_segfault
avoid segfault in llvm_backend_general.cpp on map resize
2022-01-26 19:56:59 +00:00
CiD- 498f68c06b avoid segfault on map resize 2022-01-26 14:37:15 -05:00
gingerBill 070b450768 Add ODIN_ERROR_POS_STYLE constant and change runtime.print_caller_location based on that constant 2022-01-26 17:34:39 +00:00
gingerBill 74174eb4ae Remove spurious ) 2022-01-26 16:38:12 +00:00
gingerBill b190404b21 Fix double map dereference indexing 2022-01-26 16:37:16 +00:00
gingerBill 081a5a52a6 Add ODIN_ERROR_POS_STYLE environment variable
Allowing for two different error message styles:
default or odin
    path(line:column) message
unix
    path:line:column: message
2022-01-26 16:09:22 +00:00
gingerBill fb86c23dbd Keep -vet happy 2022-01-25 16:41:31 +00:00
gingerBill cb6a4ebf60 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-01-25 16:40:31 +00:00
gingerBill 1bf8328606 Strip unneeded semicolons 2022-01-25 16:40:25 +00:00
Jeroen van Rijn 6a7f39453b Merge pull request #1450 from Kelimion/bit_array
bit_array: Fix initial size.
2022-01-25 17:14:42 +01:00
Jeroen van Rijn 515fd2a228 bit_array: Fix initial size. 2022-01-25 17:08:32 +01:00
gingerBill dd3322ac1f Update all_main.odin to include all the crypto packages 2022-01-25 14:34:48 +00:00
gingerBill f16f1d932e Fix #1448 2022-01-25 14:24:15 +00:00
gingerBill a3e7b2baa1 Revert change 2022-01-25 12:42:45 +00:00
gingerBill fadf9b5309 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-01-25 12:39:12 +00:00
gingerBill f6a087775e Disable early return from check_proc_info 2022-01-25 12:39:06 +00:00
Jeroen van Rijn d5f7e181a0 Merge pull request #1449 from Kelimion/zlib_change
zlib: update Huffman builder.
2022-01-25 12:23:34 +01:00
Jeroen van Rijn 65f8722afc zlib: update Huffman builder. 2022-01-25 12:18:10 +01:00
gingerBill c0479f1564 Handle line comment better 2022-01-24 23:42:04 +00:00
gingerBill fe0b5bf4e2 Parse comments on enums fields 2022-01-24 23:28:59 +00:00
gingerBill f20105ddfe Update docs for packages fmt and io 2022-01-24 23:07:06 +00:00
gingerBill 42ab882db4 Remove debug code 2022-01-24 15:56:26 +00:00
gingerBill dcc9e61362 Correct string_append_token 2022-01-24 14:52:43 +00:00
gingerBill 2554c72bb2 Update CommentGroup parsing for struct types 2022-01-24 14:47:33 +00:00
gingerBill 49872e40dc Comment out calls 2022-01-24 14:46:56 +00:00
gingerBill 849fe01e70 Add lb_add_debug_local_variable call to procedure arguments 2022-01-24 14:13:24 +00:00
gingerBill d269dbcd40 Add comment for the internals of assert 2022-01-23 22:01:54 +00:00
gingerBill 18e639f59b Add strings.split_lines* procedures 2022-01-23 21:35:03 +00:00
gingerBill 6ad262c2df Migrate odin-html-docs to pkg.odin-lang.org repo 2022-01-23 16:52:08 +00:00
gingerBill 10b97a1b39 Update style.css 2022-01-23 16:36:37 +00:00
gingerBill 56b4e0a3c3 Fix #1267 2022-01-23 15:40:46 +00:00
gingerBill 27dbe84f79 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-01-23 09:53:56 +00:00
gingerBill 0711d4e5fe Correct bit_set printing 2022-01-23 09:53:50 +00:00
Jeroen van Rijn 1e46537959 Merge pull request #1443 from graphitemaster/patch-1
Fix fread definition
2022-01-23 09:39:43 +01:00
Dale Weiler a5e1693774 Fix fread definition 2022-01-23 03:12:59 -05:00
gingerBill 63771bc6e8 Merge pull request #1441 from Platin21/fix/multiple-llvm-versions
Makes it possible to use llvm 12 13 and 11 for building on macOS
2022-01-22 20:22:00 +00:00
Platin21 8516e2e7e3 Changed match to be arbitrary width
(cant do exact match as we never know how much subversion's llvm does)
2022-01-22 20:50:05 +01:00
gingerBill b3c3e41706 Correct directory comment printing 2022-01-22 19:49:46 +00:00
gingerBill 59f3a009fa Update header-lower.txt.html 2022-01-22 19:46:22 +00:00
Platin21 9bc5b84c4d Removes maybe unsupported versions 2022-01-22 20:40:04 +01:00
gingerBill f9265c14bf Update footer.txt.html 2022-01-22 19:37:35 +00:00
Platin21 9c1e1a63a2 Added pattern function so we can match whatever llvm versions we want
Right now we match every version that is 13 something for arm64 on macOS
And for x86 we allow any above 11 and including 11
2022-01-22 20:29:57 +01:00
gingerBill 4dc5839e3d Add header-lower.txt.html 2022-01-22 17:09:10 +00:00
gingerBill fdcb9deaff Generate core and vendor library collection; add package sidebar for the entire collection 2022-01-22 17:07:24 +00:00
gingerBill fe6539fad9 Add more to examples/all/all_vendor.odin 2022-01-22 17:03:55 +00:00
Platin21 0e06383620 Changed make file so that it allows for multiple LLVM versions instead of a single one on Darwin 2022-01-22 17:34:43 +01:00
gingerBill cfbc1a447b Correct inverse and inverse_transpose for 2x2 matrices 2022-01-20 13:18:37 +00:00
gingerBill 1b23dd2257 Add home page 2022-01-20 01:02:26 +00:00
gingerBill b612edba5a Improve detail styling 2022-01-20 00:36:44 +00:00
gingerBill d39c05b183 Simplify tag printing 2022-01-20 00:19:58 +00:00
gingerBill 3a3cb521ab Support tag printing 2022-01-20 00:19:24 +00:00
gingerBill 5b97ff0b48 General improves including comment formatting 2022-01-20 00:13:26 +00:00
gingerBill 2b918ada4b Add .Private information to doc-format 2022-01-19 17:15:10 +00:00
gingerBill b5754b6ed9 Print examples correctly 2022-01-19 16:35:50 +00:00
gingerBill 07ee23f817 Simplify dir tree generation 2022-01-19 16:28:01 +00:00
gingerBill ecdaac9921 Unify are_types_identical_unique_tuples 2022-01-19 15:14:15 +00:00
gingerBill 5ff82fc113 Correct tuple name checking for doc writing 2022-01-19 15:11:42 +00:00
gingerBill 28a816ef25 Allow for entity grouping in structs and procedure signatures with the Odin doc-format 2022-01-19 14:57:27 +00:00
gingerBill 6bdb210ad8 More improvements to the styling 2022-01-19 13:34:54 +00:00
gingerBill db08847f9a Improve rendering to match the main website's CSS 2022-01-19 13:20:38 +00:00
gingerBill 841c428273 Merge pull request #1433 from odin-lang/html-docs-printer
Initial Work on HTML Docs Printer
2022-01-18 11:03:41 +00:00
gingerBill 6b830f42b6 Improve stylization with collapsible directories; Fix name padding 2022-01-17 23:48:46 +00:00
gingerBill fb01dfe048 Improve docs_writer.cpp 2022-01-17 22:17:07 +00:00
gingerBill c7a9c8274f Improve type printing 2022-01-17 22:16:32 +00:00
gingerBill cafb6e5587 Correct //+private for odin doc 2022-01-17 21:33:20 +00:00
gingerBill e9ae6e20e8 Fix code, source code links, and add recursive make directory 2022-01-17 20:50:40 +00:00
gingerBill 2ca2dbcc92 Correct distinct printing 2022-01-17 19:23:24 +00:00
gingerBill 0d4642825f Correct package docs parsing 2022-01-17 19:07:25 +00:00
gingerBill 8eda756714 Add printing for constants, variables, types, and procedure groups 2022-01-17 19:01:16 +00:00
gingerBill c85ac955f7 Simplify docs to hide the copyright 2022-01-17 19:00:47 +00:00
gingerBill 97922406fe Improve printing for record types 2022-01-17 18:23:30 +00:00
gingerBill 76ccce2942 Begin work on a html doc printer 2022-01-17 17:57:55 +00:00
gingerBill 686dbb4421 Correct odin doc comment printing 2022-01-17 14:43:42 +00:00
gingerBill cd6898439e Comment out link_section on procedures 2022-01-17 12:17:13 +00:00
gingerBill 95620aaf2a Update examples/all 2022-01-17 11:48:15 +00:00
gingerBill 1d293749c2 Move core:path to core:path/slashpath
This is to reduce the confusion that occurs between that package and the `core:path/filepath` package
2022-01-17 11:38:15 +00:00
gingerBill 2d35a5c1af Merge pull request #1431 from AquaGeneral/master
Extraneous parameters in hlsl/glsl.saturate removed
2022-01-17 10:52:19 +00:00
Jesse Stiller d4ea02a877 Extraneous parameters in hlsl/glsl.saturate removed
This is a breaking change to anyone who used glsl/hlsl.saturate functions prior, but the y and z parameters never were used and do not conform to how the saturate function works in HLSL:  https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-saturate

Note however GLSL does not contain a saturate function, but removing it does not accomplish anything good IMO.
2022-01-17 12:19:06 +10:00
gingerBill 2a325b3da0 Update ODIN_ENDIAN usage 2022-01-16 12:25:39 +00:00
gingerBill f0529535e0 ODIN_ENDIAN changed to an enum constant; ODIN_ENUM_STRING is the new string version of the old constant 2022-01-15 17:53:18 +00:00
gingerBill 3f59c45740 Remove main creation in llvm_backend.cpp and have it done purely in the runtime package (partial bootstrapping) 2022-01-15 17:42:10 +00:00
gingerBill 29ebe0c3c9 Rename architecture 386 to i386 2022-01-15 17:40:00 +00:00
gingerBill 6c48670819 Make ODIN_BUILD_MODE a enum type 2022-01-15 17:34:35 +00:00
gingerBill 51dcbc80c3 Add LLVMAddMergedLoadStoreMotionPass on -debug -opt:0 2022-01-15 16:26:14 +00:00
gingerBill 9ecbadd457 Simplify procedure parameters callee logic 2022-01-15 16:16:11 +00:00
gingerBill 79f32d7b71 Remove unused lbDefer kind 2022-01-15 16:03:37 +00:00
gingerBill 7501cc2f17 Remove dead code 2022-01-15 16:01:23 +00:00
gingerBill a390ef41f8 Fix swizzle logic within lb_build_assign_stmt_array 2022-01-15 15:55:01 +00:00
gingerBill bb9c2f7aad Merge branch 'master' of https://github.com/odin-lang/Odin 2022-01-15 15:38:15 +00:00
gingerBill 6aa80ee8e4 Correct _start as an entry point 2022-01-15 15:38:09 +00:00
Jeroen van Rijn 0741bc37cc Merge pull request #1427 from oskarnp/macos-linker-fix
Fix invalid linker flags passed to clang on macOS
2022-01-14 17:05:28 +01:00
oskarnp c6ed3fa4b5 Fix invalid linker flags passed to clang on macOS 2022-01-14 10:48:41 -05:00
Jeroen van Rijn e277102947 Merge pull request #1426 from jasonKercher/fix_queue
fix push_back and pop_front
2022-01-14 16:45:54 +01:00
CiD- 6cf5371d7d fix push_back and pop_front 2022-01-14 10:17:49 -05:00
gingerBill e15f714660 Define wasm _start entry point in Odin code 2022-01-13 15:18:47 +00:00
gingerBill 4f77151ebc Merge pull request #1389 from ap29600/slice_scanner
Add slice/scanner proc
2022-01-13 14:10:17 +00:00
gingerBill 9a46463078 Merge pull request #1399 from kleeon/master
Fixed wrong function name in vendor/OpenGL/README.md
2022-01-13 12:06:53 +00:00
gingerBill a0816bb581 Merge pull request #1424 from jasonKercher/os_linux
os_linux additions + libc to syscalls
2022-01-13 12:06:40 +00:00
gingerBill b33ca6651e Rename proc_* to entry_* 2022-01-13 12:05:22 +00:00
gingerBill 315a08f33f Add main to proc_unix.odin 2022-01-13 12:04:42 +00:00
Jeroen van Rijn 50668fa7a6 Merge pull request #1425 from graphitemaster/more_linux_shared_library_fixes
Fixes for shared library initialization and finalization
2022-01-13 06:36:19 +01:00
Dale Weiler ee260986a9 more fixes 2022-01-13 00:19:04 -05:00
gingerBill c9bc759624 Correct calling convention 2022-01-12 23:04:31 +00:00
gingerBill 80f175cdb0 Add empty main dynamic builds for *nix systems 2022-01-12 20:40:34 +00:00
gingerBill 8f03811842 Fix typo 2022-01-12 20:30:34 +00:00
gingerBill 3def94505e Add dynamic to error message for -build-mode 2022-01-12 20:28:11 +00:00
gingerBill e30f16b1f3 Correct -init for *nix 2022-01-12 20:17:30 +00:00
gingerBill 7df93ea504 Initialize runtime.args__ through main 2022-01-12 20:16:46 +00:00
gingerBill 6209b02bf9 Add intrinsics._entry_point call to _odin_entry_point 2022-01-12 20:16:04 +00:00
gingerBill 75b7f2b9fe Correct -init for *nix to be a different procedure 2022-01-12 20:13:38 +00:00
gingerBill f1521aa980 Add proc_windows.odin for custom entry points 2022-01-12 20:10:23 +00:00
gingerBill fb0a3ab7c1 Correct linkage for entry point procedures on Windows 2022-01-12 20:07:17 +00:00
CiD- 8eaafd5242 check correct errno in _readlink 2022-01-12 14:51:49 -05:00
CiD- 774951e8c0 os_linux additions + libc to syscalls 2022-01-12 14:36:18 -05:00
gingerBill 5ec93677a0 Correct look for entry point in llvm backend (Windows only currently) 2022-01-12 19:27:49 +00:00
gingerBill 7e4067c44c Begin work to move entry point code to Odin itself rather than in C++ side 2022-01-12 19:19:43 +00:00
gingerBill f2f6c3c67d Merge branch 'master' of https://github.com/odin-lang/Odin 2022-01-11 10:56:13 +00:00
gingerBill 847b05013f Disable DEFAULT_TO_THREADED_CHECKER until race condition is found 2022-01-11 10:56:07 +00:00
gingerBill d308473075 Merge pull request #1421 from graphitemaster/linux_shared_library_fixes
Linux shared library fixes
2022-01-10 23:18:04 +00:00
Dale Weiler 4334dbe69a disable this warning 2022-01-10 18:00:38 -05:00
Dale Weiler 8f91e9307c shared library fixes 2022-01-10 17:57:33 -05:00
gingerBill 32ec1162bf Use more {} ctor 2022-01-10 14:52:47 +00:00
gingerBill 7cc265e14c Add mutex guards for signature scopes 2022-01-10 14:50:28 +00:00
gingerBill 6f3e450c50 Move error handling code to a separate file 2022-01-10 14:03:36 +00:00
gingerBill cb1080d56c Fix check_procedure_bodies to allow multiple threads caused by a typo 2022-01-10 13:31:34 +00:00
gingerBill 80bd1eb615 Fix polymorphic matrix element with a minor hack 2022-01-10 12:19:49 +00:00
gingerBill fb53402914 Merge pull request #1402 from jasonKercher/syscalls
add more Linux syscalls
2022-01-10 11:50:45 +00:00
gingerBill 731853ce78 Merge pull request #1416 from Naboris/utf16-typo
fix typo in utf16 decode_to_utf8
2022-01-10 11:50:04 +00:00
gingerBill f0260e9771 Merge pull request #1420 from odin-lang/linalg-to-use-matrix-type
Update matrix types to be the native Odin `matrix` types
2022-01-10 11:49:49 +00:00
gingerBill af612bc7e9 Update matrix types to be the native Odin matrix types 2022-01-10 11:32:27 +00:00
Jeroen van Rijn d76dd95c0b Merge pull request #1418 from wbogocki/patch-1
Fix link to Odin blog
2022-01-09 16:10:50 +01:00
Wojciech Bogócki 1cff72ad62 Fix link to Odin blog 2022-01-09 22:43:12 +08:00
Naboris 773cfac449 fix typo 2022-01-08 09:49:21 +01:00
Jeroen van Rijn b02f2953ac Merge pull request #1410 from Kelimion/sort_map
Fix unused imports.
2022-01-07 06:47:54 +01:00
Jeroen van Rijn 566a750899 Fix unused imports. 2022-01-07 06:12:00 +01:00
Jeroen van Rijn 1d1d684cbc Merge pull request #1407 from Platin21/feature/fix-supervisor-call
Fix Syscall Intrinsic on ARM64 MacOS
2022-01-05 17:02:24 +01:00
Platin21 7a14acaa01 Fixes syscall intrinsic on macOS they use a slightly different section + register for the id 2022-01-05 16:49:58 +01:00
gingerBill 057174497a Merge pull request #1406 from terickson001/schar
add schar to core:c and core:c/libc
2022-01-05 00:50:24 +00:00
Tyler Erickson 8c9597b24b add schar to core:c and core:c/libc 2022-01-04 16:45:16 -08:00
gingerBill 72862ce30d Fix minor typo in c/frontend/preprocess 2022-01-04 11:48:18 +00:00
gingerBill d0f4cb1de4 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-01-04 11:47:05 +00:00
gingerBill 17613185e7 Support struct field tags in odin doc format 2022-01-04 11:44:34 +00:00
Jeroen van Rijn 00ff1fbca2 Merge pull request #1403 from Platin21/feature/fix-open-syscall
Fixes open system call (Thanks TIM!)
2022-01-03 20:48:09 +01:00
gingerBill f15bb0b424 Fix quaternion casting 2022-01-03 19:45:27 +00:00
gingerBill f818d0feb1 Fix #1344 2022-01-03 19:43:22 +00:00
Platin21 8ff6f95571 Removes the default create flag 2022-01-03 20:40:56 +01:00
Platin21 68e5f57e27 Fixes open system call (Thanks TIM!) 2022-01-03 20:34:57 +01:00
CiD- 38e5e13b3f add more Linux syscalls 2022-01-03 09:24:39 -05:00
gingerBill defc1672c3 Revert fix #1344 2022-01-03 13:48:12 +00:00
gingerBill 12f459b5fb Fix #1344 2022-01-03 13:12:39 +00:00
gingerBill e6b8f7e77a Fix #1398 2022-01-03 12:54:31 +00:00
gingerBill 236b08cb49 Fix #1356 2022-01-03 12:51:32 +00:00
gingerBill e4f28de3de Fix #1311 2022-01-03 12:14:01 +00:00
kleeon 750ee4ecdb Fixed wrong function name in README.md 2021-12-30 15:49:07 +03:00
Andrea Piseri 92e70b9a58 use multipointers instead of simple pointers 2021-12-28 16:22:34 +01:00
Andrea Piseri 822da9d12d Merge branch 'master' into slice_scanner 2021-12-28 16:12:15 +01:00
Andrea Piseri 5d80e24224 Add slice/scanner proc 2021-12-23 12:49:40 +01:00
151 changed files with 7025 additions and 4124 deletions
+21 -9
View File
@@ -17,13 +17,16 @@ jobs:
run: ./odin report
timeout-minutes: 1
- name: Odin check
run: ./odin check examples/demo/demo.odin -vet
run: ./odin check examples/demo -vet
timeout-minutes: 10
- name: Odin run
run: ./odin run examples/demo/demo.odin
run: ./odin run examples/demo
timeout-minutes: 10
- name: Odin run -debug
run: ./odin run examples/demo/demo.odin -debug
run: ./odin run examples/demo -debug
timeout-minutes: 10
- name: Odin check examples/all
run: ./odin check examples/all -strict-style
timeout-minutes: 10
- name: Core library tests
run: |
@@ -54,13 +57,16 @@ jobs:
run: ./odin report
timeout-minutes: 1
- name: Odin check
run: ./odin check examples/demo/demo.odin -vet
run: ./odin check examples/demo -vet
timeout-minutes: 10
- name: Odin run
run: ./odin run examples/demo/demo.odin
run: ./odin run examples/demo
timeout-minutes: 10
- name: Odin run -debug
run: ./odin run examples/demo/demo.odin -debug
run: ./odin run examples/demo -debug
timeout-minutes: 10
- name: Odin check examples/all
run: ./odin check examples/all -strict-style
timeout-minutes: 10
- name: Core library tests
run: |
@@ -91,19 +97,25 @@ jobs:
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/demo/demo.odin -vet
odin check examples/demo -vet
timeout-minutes: 10
- name: Odin run
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo/demo.odin
odin run examples/demo
timeout-minutes: 10
- name: Odin run -debug
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo/demo.odin -debug
odin run examples/demo -debug
timeout-minutes: 10
- name: Odin check examples/all
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style
timeout-minutes: 10
- name: Core library tests
shell: cmd
+22 -10
View File
@@ -8,22 +8,34 @@ CC=clang
OS=$(shell uname)
ifeq ($(OS), Darwin)
ARCH=$(shell uname -m)
LLVM_CONFIG=llvm-config
LLVM_CONFIG=
# LLVM Version Setting
LLVM_VERSION_PATTERN="^11\."
LLVM_VERSION="11"
# allow for arm only llvm's with version 13
ifeq ($(ARCH), arm64)
LLVM_VERSION="13"
LLVM_VERSION_PATTERN="^13"
endif
LLVM_VERSIONS = "13.%.%"
else
# allow for x86 / amd64 all llvm versions begining from 11
LLVM_VERSIONS = "13.%.%" "12.0.1" "11.1.0"
endif
ifneq ($(shell llvm-config --version | grep $(LLVM_VERSION_PATTERN)),)
LLVM_VERSION_PATTERN_SEPERATOR = )|(
LLVM_VERSION_PATTERNS_ESCAPED_DOT = $(subst .,\.,$(LLVM_VERSIONS))
LLVM_VERSION_PATTERNS_REPLACE_PERCENT = $(subst %,.*,$(LLVM_VERSION_PATTERNS_ESCAPED_DOT))
LLVM_VERSION_PATTERN_REMOVE_ELEMENTS = $(subst " ",$(LLVM_VERSION_PATTERN_SEPERATOR),$(LLVM_VERSION_PATTERNS_REPLACE_PERCENT))
LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR = $(subst ",,$(LLVM_VERSION_PATTERN_REMOVE_ELEMENTS))
LLVM_VERSION_PATTERN = "^(($(LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR)))"
ifneq ($(shell llvm-config --version | grep -E $(LLVM_VERSION_PATTERN)),)
LLVM_CONFIG=llvm-config
else
$(error "Requirement: llvm-config must be version $(LLVM_VERSION)")
endif
ifeq ($(ARCH), arm64)
$(error "Requirement: llvm-config must be base version 13 for arm64")
else
$(error "Requirement: llvm-config must be base version greater than 11 for amd64/x86")
endif
endif
LDFLAGS:=$(LDFLAGS) -liconv
CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags)
+1 -1
View File
@@ -84,7 +84,7 @@ The official Odin Language specification.
### Articles
#### [The Odin Blog](https://odin-lang.org/blog)
#### [The Odin Blog](https://odin-lang.org/news/)
The official blog of the Odin programming language, featuring announcements, news, and in-depth articles by the Odin team and guests.
+1 -1
View File
@@ -2,7 +2,7 @@
package builtin
nil :: nil;
false :: 0!==0;
false :: 0!=0;
true :: 0==0;
ODIN_OS :: ODIN_OS;
+3 -1
View File
@@ -3,6 +3,8 @@ package c
import builtin "core:builtin"
char :: builtin.u8 // assuming -funsigned-char
schar :: builtin.i8
short :: builtin.i16
int :: builtin.i32
long :: builtin.i32 when (ODIN_OS == "windows" || size_of(builtin.rawptr) == 4) else builtin.i64
@@ -46,7 +48,7 @@ int_least64_t :: builtin.i64
uint_least64_t :: builtin.u64
// Same on Windows, Linux, and FreeBSD
when ODIN_ARCH == "386" || ODIN_ARCH == "amd64" {
when ODIN_ARCH == "i386" || ODIN_ARCH == "amd64" {
int_fast8_t :: builtin.i8
uint_fast8_t :: builtin.u8
int_fast16_t :: builtin.i32
+1 -1
View File
@@ -956,7 +956,7 @@ substitute_token :: proc(cpp: ^Preprocessor, tok: ^Token, args: ^Macro_Arg) -> ^
continue
}
if tok.lit == "__VA__OPT__" && tok.next.lit == "(" {
if tok.lit == "__VA_OPT__" && tok.next.lit == "(" {
opt_arg := read_macro_arg_one(cpp, &tok, tok.next.next, true)
if has_varargs(args) {
for t := opt_arg.tok; t.kind != .EOF; t = t.next {
+1 -1
View File
@@ -149,7 +149,7 @@ foreign libc {
putchar :: proc() -> int ---
puts :: proc(s: cstring) -> int ---
ungetc :: proc(c: int, stream: ^FILE) -> int ---
fread :: proc(ptr: rawptr, size: size_t, stream: ^FILE) -> size_t ---
fread :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t ---
fwrite :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t ---
// 7.21.9 File positioning functions
+2
View File
@@ -3,6 +3,8 @@ package libc
import "core:c"
char :: c.char // assuming -funsigned-char
schar :: c.schar
short :: c.short
int :: c.int
long :: c.long
+3
View File
@@ -5,6 +5,9 @@
List of contributors:
Jeroen van Rijn: Initial implementation, optimization.
*/
// package compress is a collection of utilities to aid with other compression packages
package compress
import "core:io"
+13 -10
View File
@@ -111,9 +111,9 @@ ZFAST_MASK :: ((1 << ZFAST_BITS) - 1)
*/
Huffman_Table :: struct {
fast: [1 << ZFAST_BITS]u16,
firstcode: [16]u16,
firstcode: [17]u16,
maxcode: [17]int,
firstsymbol: [16]u16,
firstsymbol: [17]u16,
size: [288]u8,
value: [288]u16,
}
@@ -244,7 +244,7 @@ allocate_huffman_table :: proc(allocator := context.allocator) -> (z: ^Huffman_T
@(optimization_mode="speed")
build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
sizes: [HUFFMAN_MAX_BITS+1]int
next_code: [HUFFMAN_MAX_BITS]int
next_code: [HUFFMAN_MAX_BITS+1]int
k := int(0)
@@ -256,14 +256,14 @@ build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
}
sizes[0] = 0
for i in 1..<(HUFFMAN_MAX_BITS+1) {
for i in 1 ..< HUFFMAN_MAX_BITS {
if sizes[i] > (1 << uint(i)) {
return E_Deflate.Huffman_Bad_Sizes
}
}
code := int(0)
for i in 1..<HUFFMAN_MAX_BITS {
for i in 1 ..= HUFFMAN_MAX_BITS {
next_code[i] = code
z.firstcode[i] = u16(code)
z.firstsymbol[i] = u16(k)
@@ -538,19 +538,20 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
final = compress.read_bits_lsb(z, 1)
type = compress.read_bits_lsb(z, 2)
// fmt.printf("Final: %v | Type: %v\n", final, type);
// fmt.printf("Final: %v | Type: %v\n", final, type)
switch type {
case 0:
// fmt.printf("Method 0: STORED\n")
// Uncompressed block
// Discard bits until next byte boundary
compress.discard_to_next_byte_lsb(z)
uncompressed_len := i16(compress.read_bits_lsb(z, 16))
length_check := i16(compress.read_bits_lsb(z, 16))
uncompressed_len := u16(compress.read_bits_lsb(z, 16))
length_check := u16(compress.read_bits_lsb(z, 16))
// fmt.printf("LEN: %v, ~LEN: %v, NLEN: %v, ~NLEN: %v\n", uncompressed_len, ~uncompressed_len, length_check, ~length_check);
// fmt.printf("LEN: %v, ~LEN: %v, NLEN: %v, ~NLEN: %v\n", uncompressed_len, ~uncompressed_len, length_check, ~length_check)
if ~uncompressed_len != length_check {
@@ -567,10 +568,12 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
write_byte(z, u8(lit))
uncompressed_len -= 1
}
assert(uncompressed_len == 0)
case 3:
return E_Deflate.BType_3
case:
// log.debugf("Err: %v | Final: %v | Type: %v\n", err, final, type);
// fmt.printf("Err: %v | Final: %v | Type: %v\n", err, final, type)
if type == 1 {
// Use fixed code lengths.
build_huffman(z_repeat, Z_FIXED_LENGTH[:]) or_return
+1 -1
View File
@@ -88,7 +88,7 @@ create :: proc(max_index: int, min_index := 0, allocator := context.allocator) -
res = Bit_Array{
bias = min_index,
}
return res, resize_if_needed(&res, size_in_bits)
return res, resize_if_needed(&res, legs)
}
/*
+183
View File
@@ -0,0 +1,183 @@
package container_lru
import "core:intrinsics"
import "core:mem"
_ :: intrinsics
_ :: mem
Node :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) {
prev, next: ^Node(Key, Value),
key: Key,
value: Value,
}
// Cache is an LRU cache. It automatically removes entries as new entries are
// added if the capacity is reached. Entries are removed based on how recently
// they were used where the oldest entries are removed first.
Cache :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) {
head: ^Node(Key, Value),
tail: ^Node(Key, Value),
entries: map[Key]^Node(Key, Value),
count: int,
capacity: int,
node_allocator: mem.Allocator,
on_remove: proc(key: Key, value: Value, user_data: rawptr),
on_remove_user_data: rawptr,
call_on_remove_on_destroy: bool,
}
// init initializes a Cache
init :: proc(c: ^$C/Cache($Key, $Value), capacity: int, entries_allocator := context.allocator, node_allocator := context.allocator) {
c.entries.allocator = entries_allocator
c.node_allocator = node_allocator
c.capacity = capacity
}
// destroy deinitializes a Cache
destroy :: proc(c: ^$C/Cache($Key, $Value)) {
for _, node in c.entries {
if c.call_on_remove_on_destroy && c.on_remove != nil {
c.on_remove(node.key, node.value, c.on_remove_user_data)
}
free(node, c.node_allocator)
}
clear(&c.entries)
delete(c.entries)
c.head = nil
c.tail = nil
c.count = 0
}
// set the given key value pair. This operation updates the recent usage of the item.
set :: proc(c: ^$C/Cache($Key, $Value), key: Key, value: Value) -> mem.Allocator_Error {
if e, ok := c.entries[key]; ok {
e.value = value
return nil
}
e := new(Node(Key, Value), c.node_allocator) or_return
e.key = key
e.value = value
_push_front_node(c, e)
if c.count > c.capacity {
_remove_node(c, c.tail)
}
c.entries[key] = e
return nil
}
// get a value from the cache from a given key. This operation updates the usage of the item.
get :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> (value: Value, ok: bool) #optional_ok {
e: ^Node(Key, Value)
e, ok = c.entries[key]
if !ok {
return
}
_pop_node(c, e)
_push_front_node(c, e)
return e.value, true
}
// get_ptr gets the pointer to a value the cache from a given key. This operation updates the usage of the item.
get_ptr :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> (value: ^Value, ok: bool) #optional_ok {
e: ^Node(Key, Value)
e, ok = c.entries[key]
if !ok {
return
}
_pop_node(c, e)
_push_front_node(c, e)
return &e.value, true
}
// peek gets the value from the cache from a given key without updating the recent usage.
peek :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> (value: Value, ok: bool) #optional_ok {
e: ^Node(Key, Value)
e, ok = c.entries[key]
if !ok {
return
}
return e.value, true
}
// exists checks for the existence of a value from a given key without updating the recent usage.
exists :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> bool {
return key in c.entries
}
// remove removes an item from the cache.
remove :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> bool {
e, ok := c.entries[key]
if !ok {
return false
}
_remove_node(c, e)
return true
}
@(private)
_remove_node :: proc(c: ^$C/Cache($Key, $Value), node: ^Node(Key, Value)) {
if c.head == node {
c.head = node.next
}
if c.tail == node {
c.tail = node.prev
}
if node.prev != nil {
node.prev.next = node.next
}
if node.next != nil {
node.next.prev = node.prev
}
node.prev = nil
node.next = nil
c.count -= 1
delete_key(&c.entries, node.key)
if c.on_remove != nil {
c.on_remove(node.key, node.value, c.on_remove_user_data)
}
free(node, c.node_allocator)
}
@(private)
_push_front_node :: proc(c: ^$C/Cache($Key, $Value), e: ^Node(Key, Value)) {
if c.head != nil {
e.next = c.head
e.next.prev = e
}
c.head = e
if c.tail == nil {
c.tail = e
}
e.prev = nil
c.count += 1
}
@(private)
_pop_node :: proc(c: ^$C/Cache($Key, $Value), e: ^Node(Key, Value)) {
if e == nil {
return
}
if e.prev != nil {
e.prev.next = e.next
}
if e.next != nil {
e.next.prev = e.prev
}
e.prev = nil
e.next = nil
}
+5 -1
View File
@@ -2,6 +2,7 @@ package container_queue
import "core:builtin"
import "core:runtime"
_ :: runtime
// Dynamically resizable double-ended queue/ring-buffer
Queue :: struct($T: typeid) {
@@ -86,7 +87,8 @@ push_back :: proc(q: ^$Q/Queue($T), elem: T) -> bool {
if space(q^) == 0 {
_grow(q) or_return
}
q.data[q.len] = elem
idx := (q.offset+uint(q.len))%builtin.len(q.data)
q.data[idx] = elem
q.len += 1
return true
}
@@ -126,6 +128,7 @@ pop_back_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) {
pop_front :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> (elem: T) {
assert(condition=q.len > 0, loc=loc)
elem = q.data[q.offset]
q.offset = (q.offset+1)%builtin.len(q.data)
q.len -= 1
return
}
@@ -133,6 +136,7 @@ pop_front :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> (elem: T) {
pop_front_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) {
if q.len > 0 {
elem = q.data[q.offset]
q.offset = (q.offset+1)%builtin.len(q.data)
q.len -= 1
ok = true
}
+1 -1
View File
@@ -22,7 +22,7 @@ fe_from_bytes :: #force_inline proc (out1: ^Tight_Field_Element, arg1: []byte, a
assert(len(arg1) == 16)
when ODIN_ARCH == "386" || ODIN_ARCH == "amd64" {
when ODIN_ARCH == "i386" || ODIN_ARCH == "amd64" {
// While it may be unwise to do deserialization here on our
// own when fiat-crypto provides equivalent functionality,
// doing it this way provides a little under 3x performance
+2 -2
View File
@@ -52,7 +52,7 @@ keccakf :: proc "contextless" (st: ^[25]u64) {
t: u64 = ---
bc: [5]u64 = ---
when ODIN_ENDIAN != "little" {
when ODIN_ENDIAN != .Little {
v: uintptr = ---
for i = 0; i < 25; i += 1 {
v := uintptr(&st[i])
@@ -98,7 +98,7 @@ keccakf :: proc "contextless" (st: ^[25]u64) {
st[0] ~= keccakf_rndc[r]
}
when ODIN_ENDIAN != "little" {
when ODIN_ENDIAN != .Little {
for i = 0; i < 25; i += 1 {
v = uintptr(&st[i])
t = st[i]
+4 -4
View File
@@ -44,7 +44,7 @@ hash_bytes_224 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_224]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_224 will hash the given input and write the
@@ -123,7 +123,7 @@ hash_bytes_256 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256 will hash the given input and write the
@@ -202,7 +202,7 @@ hash_bytes_384 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_384]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_384 will hash the given input and write the
@@ -281,7 +281,7 @@ hash_bytes_512 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_512]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_512 will hash the given input and write the
+1 -1
View File
@@ -46,7 +46,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash);
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
+1 -1
View File
@@ -47,7 +47,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash);
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
+1 -1
View File
@@ -346,7 +346,7 @@ _do_blocks :: proc (ctx: ^Context, dst, src: []byte, nr_blocks: int) {
// Until dedicated assembly can be written leverage the fact that
// the callers of this routine ensure that src/dst are valid.
when ODIN_ARCH == "386" || ODIN_ARCH == "amd64" {
when ODIN_ARCH == "i386" || ODIN_ARCH == "amd64" {
// util.PUT_U32_LE/util.U32_LE are not required on little-endian
// systems that also happen to not be strict about aligned
// memory access.
+1 -1
View File
@@ -41,7 +41,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash);
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
+4 -4
View File
@@ -44,7 +44,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_224 will hash the given input and write the
@@ -123,7 +123,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256 will hash the given input and write the
@@ -202,7 +202,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_384 will hash the given input and write the
@@ -281,7 +281,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_512 will hash the given input and write the
+16 -16
View File
@@ -50,7 +50,7 @@ hash_bytes_128_3 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_128_3 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_128_3(transmute([]byte)(data), hash);
hash_bytes_to_buffer_128_3(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_128_3 will hash the given input and write the
@@ -135,7 +135,7 @@ hash_bytes_128_4 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_128_4 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_128_4(transmute([]byte)(data), hash);
hash_bytes_to_buffer_128_4(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_128_4 will hash the given input and write the
@@ -220,7 +220,7 @@ hash_bytes_128_5 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_128_5 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_128_5(transmute([]byte)(data), hash);
hash_bytes_to_buffer_128_5(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_128_5 will hash the given input and write the
@@ -305,7 +305,7 @@ hash_bytes_160_3 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_160_3 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_160_3(transmute([]byte)(data), hash);
hash_bytes_to_buffer_160_3(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_160_3 will hash the given input and write the
@@ -390,7 +390,7 @@ hash_bytes_160_4 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_160_4 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_160_4(transmute([]byte)(data), hash);
hash_bytes_to_buffer_160_4(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_160_4 will hash the given input and write the
@@ -475,7 +475,7 @@ hash_bytes_160_5 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_160_5 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_160_5(transmute([]byte)(data), hash);
hash_bytes_to_buffer_160_5(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_160_5 will hash the given input and write the
@@ -560,7 +560,7 @@ hash_bytes_192_3 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_192_3 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_192_3(transmute([]byte)(data), hash);
hash_bytes_to_buffer_192_3(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_192_3 will hash the given input and write the
@@ -645,7 +645,7 @@ hash_bytes_192_4 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_192_4 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_192_4(transmute([]byte)(data), hash);
hash_bytes_to_buffer_192_4(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_192_4 will hash the given input and write the
@@ -730,7 +730,7 @@ hash_bytes_192_5 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_192_5 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_192_5(transmute([]byte)(data), hash);
hash_bytes_to_buffer_192_5(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_192_5 will hash the given input and write the
@@ -815,7 +815,7 @@ hash_bytes_224_3 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_224_3 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_224_3(transmute([]byte)(data), hash);
hash_bytes_to_buffer_224_3(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_224_3 will hash the given input and write the
@@ -900,7 +900,7 @@ hash_bytes_224_4 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_224_4 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_224_4(transmute([]byte)(data), hash);
hash_bytes_to_buffer_224_4(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_224_4 will hash the given input and write the
@@ -985,7 +985,7 @@ hash_bytes_224_5 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_224_5 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_224_5(transmute([]byte)(data), hash);
hash_bytes_to_buffer_224_5(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_224_5 will hash the given input and write the
@@ -1070,7 +1070,7 @@ hash_bytes_256_3 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256_3 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256_3(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256_3(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256_3 will hash the given input and write the
@@ -1155,7 +1155,7 @@ hash_bytes_256_4 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256_4 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256_4(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256_4(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256_4 will hash the given input and write the
@@ -1240,7 +1240,7 @@ hash_bytes_256_5 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256_5 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256_5(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256_5(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256_5 will hash the given input and write the
@@ -1332,7 +1332,7 @@ update :: proc(ctx: ^Haval_Context, data: []byte) {
}
ctx.count[1] += str_len >> 29
when ODIN_ENDIAN == "little" {
when ODIN_ENDIAN == .Little {
if rmd_len + str_len >= 128 {
copy(util.slice_to_bytes(ctx.block[:])[rmd_len:], data[:fill_len])
block(ctx, ctx.rounds)
+4 -4
View File
@@ -44,7 +44,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_224 will hash the given input and write the
@@ -123,7 +123,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256 will hash the given input and write the
@@ -202,7 +202,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_384 will hash the given input and write the
@@ -281,7 +281,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_512 will hash the given input and write the
+4 -4
View File
@@ -49,7 +49,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_224 will hash the given input and write the
@@ -131,7 +131,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256 will hash the given input and write the
@@ -213,7 +213,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_384 will hash the given input and write the
@@ -295,7 +295,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_512 will hash the given input and write the
+1 -1
View File
@@ -40,7 +40,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash);
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
+1 -1
View File
@@ -44,7 +44,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash);
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
+1 -1
View File
@@ -43,7 +43,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash);
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
+4 -4
View File
@@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_128 will hash the given input and write the
@@ -121,7 +121,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_160 will hash the given input and write the
@@ -197,7 +197,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256 will hash the given input and write the
@@ -273,7 +273,7 @@ hash_bytes_320 :: proc(data: []byte) -> [DIGEST_SIZE_320]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_320 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_320(transmute([]byte)(data), hash);
hash_bytes_to_buffer_320(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_320 will hash the given input and write the
+1 -1
View File
@@ -43,7 +43,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash);
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
+4 -4
View File
@@ -48,7 +48,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_224 will hash the given input and write the
@@ -127,7 +127,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256 will hash the given input and write the
@@ -206,7 +206,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_384 will hash the given input and write the
@@ -285,7 +285,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_512 will hash the given input and write the
+4 -4
View File
@@ -47,7 +47,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_224 will hash the given input and write the
@@ -126,7 +126,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256 will hash the given input and write the
@@ -205,7 +205,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_384 will hash the given input and write the
@@ -284,7 +284,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_512 will hash the given input and write the
+2 -2
View File
@@ -46,7 +46,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_128 will hash the given input and write the
@@ -128,7 +128,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256 will hash the given input and write the
+1 -1
View File
@@ -42,7 +42,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash);
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
+2 -2
View File
@@ -44,7 +44,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_256 will hash the given input and write the
@@ -122,7 +122,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_512 will hash the given input and write the
+3 -3
View File
@@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_128 will hash the given input and write the
@@ -124,7 +124,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_160 will hash the given input and write the
@@ -203,7 +203,7 @@ hash_bytes_192 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_192 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_192(transmute([]byte)(data), hash);
hash_bytes_to_buffer_192(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_192 will hash the given input and write the
+3 -3
View File
@@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_128 will hash the given input and write the
@@ -124,7 +124,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_160 will hash the given input and write the
@@ -203,7 +203,7 @@ hash_bytes_192 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer_192 :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer_192(transmute([]byte)(data), hash);
hash_bytes_to_buffer_192(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer_192 will hash the given input and write the
+1 -1
View File
@@ -42,7 +42,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
// computed hash to the second parameter.
// It requires that the destination buffer is at least as big as the digest size
hash_string_to_buffer :: proc(data: string, hash: []byte) {
hash_bytes_to_buffer(transmute([]byte)(data), hash);
hash_bytes_to_buffer(transmute([]byte)(data), hash)
}
// hash_bytes_to_buffer will hash the given input and write the
+6 -6
View File
@@ -27,7 +27,7 @@
// Construction history, or BSP trees would make the format too large to serve its purpose.
// The facilities of the formats to store meta data should make the format flexible enough
// for most uses. Adding HxA support should be something anyone can do in a days work.
//
// Structure:
// ----------
// HxA is designed to be extremely simple to parse, and is therefore based around conventions. It has
@@ -45,17 +45,17 @@
// of a number of named layers. All layers in the stack have the same number of elements. Each layer
// describes one property of the primitive. Each layer can have multiple channels and each layer can
// store data of a different type.
//
// HaX stores 3 kinds of nodes
// - Pixel data.
// - Polygon geometry data.
// - Meta data only.
//
// Pixel Nodes stores pixels in a layer stack. A layer may store things like Albedo, Roughness,
// Reflectance, Light maps, Masks, Normal maps, and Displacement. Layers use the channels of the
// layers to store things like color. The length of the layer stack is determined by the type and
// dimensions stored in the
//
// Geometry data is stored in 3 separate layer stacks for: vertex data, corner data and face data. The
// vertex data stores things like verities, blend shapes, weight maps, and vertex colors. The first
// layer in a vertex stack has to be a 3 channel layer named "position" describing the base position
@@ -63,7 +63,7 @@
// for things like UV, normals, and adjacency. The first layer in a corner stack has to be a 1 channel
// integer layer named "index" describing the vertices used to form polygons. The last value in each
// polygon has a negative - 1 index to indicate the end of the polygon.
//
// Example:
// A quad and a tri with the vertex index:
// [0, 1, 2, 3] [1, 4, 2]
@@ -72,7 +72,7 @@
// The face stack stores values per face. the length of the face stack has to match the number of
// negative values in the index layer in the corner stack. The face stack can be used to store things
// like material index.
//
// Storage
// -------
// All data is stored in little endian byte order with no padding. The layout mirrors the structs
+2 -2
View File
@@ -285,8 +285,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any) -> (err: Marshal_Error) {
case runtime.Type_Info_Integer:
switch info.endianness {
case .Platform: return false
case .Little: return ODIN_ENDIAN != "little"
case .Big: return ODIN_ENDIAN != "big"
case .Little: return ODIN_ENDIAN != .Little
case .Big: return ODIN_ENDIAN != .Big
}
}
return false
+1 -1
View File
@@ -64,6 +64,7 @@ If not present, the width is whatever is necessary to represent the value.
Precision is specified after the (optional) width followed by a period followed by a decimal number.
If no period is present, a default precision is used.
A period with no following number specifies a precision of 0.
Examples:
%f default width, default precision
%8f width 8, default precision
@@ -84,7 +85,6 @@ Other flags:
add leading 0z for dozenal (%#z)
add leading 0x or 0X for hexadecimal (%#x or %#X)
remove leading 0x for %p (%#p)
' ' (space) leave a space for elided sign in numbers (% d)
0 pad with leading zeros rather than spaces
+29 -8
View File
@@ -11,6 +11,7 @@ import "core:time"
import "core:unicode/utf8"
import "core:intrinsics"
// Internal data structure that stores the required information for formatted printing
Info :: struct {
minus: bool,
plus: bool,
@@ -46,9 +47,13 @@ Register_User_Formatter_Error :: enum {
// it is prefixed with `_` rather than marked with a private attribute so that users can access it if necessary
_user_formatters: ^map[typeid]User_Formatter
// set_user_formatters assigns m to a global value allowing the user have custom print formatting for specific
// types
set_user_formatters :: proc(m: ^map[typeid]User_Formatter) {
_user_formatters = m
}
// register_user_formatter assigns a formatter to a specific typeid. set_user_formatters must be called
// before any use of this procedure.
register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Register_User_Formatter_Error {
if _user_formatters == nil {
return .No_User_Formatter
@@ -61,7 +66,7 @@ register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Regist
}
// aprint* procedures return a string that was allocated with the current context
// aprint procedure return a string that was allocated with the current context
// They must be freed accordingly
aprint :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
@@ -69,12 +74,16 @@ aprint :: proc(args: ..any, sep := " ") -> string {
sbprint(buf=&str, args=args, sep=sep)
return strings.to_string(str)
}
// aprintln procedure return a string that was allocated with the current context
// They must be freed accordingly
aprintln :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.init_builder(&str)
sbprintln(buf=&str, args=args, sep=sep)
return strings.to_string(str)
}
// aprintf procedure return a string that was allocated with the current context
// They must be freed accordingly
aprintf :: proc(fmt: string, args: ..any) -> string {
str: strings.Builder
strings.init_builder(&str)
@@ -83,19 +92,21 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
}
// tprint* procedures return a string that was allocated with the current context's temporary allocator
// tprint procedure return a string that was allocated with the current context's temporary allocator
tprint :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.init_builder(&str, context.temp_allocator)
sbprint(buf=&str, args=args, sep=sep)
return strings.to_string(str)
}
// tprintln procedure return a string that was allocated with the current context's temporary allocator
tprintln :: proc(args: ..any, sep := " ") -> string {
str: strings.Builder
strings.init_builder(&str, context.temp_allocator)
sbprintln(buf=&str, args=args, sep=sep)
return strings.to_string(str)
}
// tprintf procedure return a string that was allocated with the current context's temporary allocator
tprintf :: proc(fmt: string, args: ..any) -> string {
str: strings.Builder
strings.init_builder(&str, context.temp_allocator)
@@ -104,21 +115,24 @@ tprintf :: proc(fmt: string, args: ..any) -> string {
}
// bprint* procedures return a string using a buffer from an array
// bprint procedures return a string using a buffer from an array
bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string {
sb := strings.builder_from_slice(buf[0:len(buf)])
return sbprint(buf=&sb, args=args, sep=sep)
}
// bprintln procedures return a string using a buffer from an array
bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string {
sb := strings.builder_from_slice(buf[0:len(buf)])
return sbprintln(buf=&sb, args=args, sep=sep)
}
// bprintf procedures return a string using a buffer from an array
bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string {
sb := strings.builder_from_slice(buf[0:len(buf)])
return sbprintf(&sb, fmt, ..args)
}
// formatted assert
assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool {
if !condition {
p := context.assertion_failure_proc
@@ -131,6 +145,7 @@ assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_locati
return condition
}
// formatted panic
panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! {
p := context.assertion_failure_proc
if p == nil {
@@ -142,24 +157,26 @@ panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! {
// sbprint formats using the default print settings and writes to buf
sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
wprint(w=strings.to_writer(buf), args=args, sep=sep)
return strings.to_string(buf^)
}
// sbprintln formats using the default print settings and writes to buf
sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
wprintln(w=strings.to_writer(buf), args=args, sep=sep)
return strings.to_string(buf^)
}
// sbprintf formats according to the specififed format string and writes to buf
sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string {
wprintf(w=strings.to_writer(buf), fmt=fmt, args=args)
return strings.to_string(buf^)
}
// wprint formats using the default print settings and writes to w
wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
fi: Info
fi.writer = w
@@ -194,6 +211,7 @@ wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
return int(size1 - size0)
}
// wprintln formats using the default print settings and writes to w
wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
fi: Info
fi.writer = w
@@ -214,6 +232,7 @@ wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
return int(size1 - size0)
}
// wprintf formats according to the specififed format string and writes to w
wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int {
fi: Info
arg_index: int = 0
@@ -493,11 +512,13 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int {
return int(size1 - size0)
}
// wprint_type is a utility procedure to write a ^runtime.Type_Info value to w
wprint_type :: proc(w: io.Writer, info: ^runtime.Type_Info) -> (int, io.Error) {
n, err := reflect.write_type(w, info)
io.flush(auto_cast w)
return n, err
}
// wprint_typeid is a utility procedure to write a typeid value to w
wprint_typeid :: proc(w: io.Writer, id: typeid) -> (int, io.Error) {
n, err := reflect.write_type(w, type_info_of(id))
io.flush(auto_cast w)
@@ -829,7 +850,7 @@ _pad :: proc(fi: ^Info, s: string) {
fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) {
switch verb {
case 'f', 'F', 'v':
case 'f', 'F', 'g', 'G', 'v':
prec: int = 3
if fi.prec_set {
prec = fi.prec
@@ -1092,8 +1113,8 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "") {
case runtime.Type_Info_Integer:
switch info.endianness {
case .Platform: return false
case .Little: return ODIN_ENDIAN != "little"
case .Big: return ODIN_ENDIAN != "big"
case .Little: return ODIN_ENDIAN != .Little
case .Big: return ODIN_ENDIAN != .Big
}
}
return false
+6 -1
View File
@@ -34,11 +34,16 @@ stderr := io.Writer{
},
}
// print* procedures return the number of bytes written
// print formats using the default print settings and writes to stdout
print :: proc(args: ..any, sep := " ") -> int { return wprint(w=stdout, args=args, sep=sep) }
// println formats using the default print settings and writes to stdout
println :: proc(args: ..any, sep := " ") -> int { return wprintln(w=stdout, args=args, sep=sep) }
// printf formats according to the specififed format string and writes to stdout
printf :: proc(fmt: string, args: ..any) -> int { return wprintf(stdout, fmt, ..args) }
// eprint formats using the default print settings and writes to stderr
eprint :: proc(args: ..any, sep := " ") -> int { return wprint(w=stderr, args=args, sep=sep) }
// eprintln formats using the default print settings and writes to stderr
eprintln :: proc(args: ..any, sep := " ") -> int { return wprintln(w=stderr, args=args, sep=sep) }
// eprintf formats according to the specififed format string and writes to stderr
eprintf :: proc(fmt: string, args: ..any) -> int { return wprintf(stderr, fmt, ..args) }
+9 -1
View File
@@ -5,15 +5,18 @@ import "core:runtime"
import "core:os"
import "core:io"
// fprint formats using the default print settings and writes to fd
fprint :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
w := io.to_writer(os.stream_from_handle(fd))
return wprint(w=w, args=args, sep=sep)
}
// fprintln formats using the default print settings and writes to fd
fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
w := io.to_writer(os.stream_from_handle(fd))
return wprintln(w=w, args=args, sep=sep)
}
// fprintf formats according to the specififed format string and writes to fd
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
w := io.to_writer(os.stream_from_handle(fd))
return wprintf(w, fmt, ..args)
@@ -27,11 +30,16 @@ fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) {
return wprint_typeid(w, id)
}
// print* procedures return the number of bytes written
// 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) }
// 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) }
// printf formats according to the specififed format string and writes to os.stdout
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 :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stderr, args=args, sep=sep) }
// 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) }
// eprintf formats according to the specififed format string and writes to os.stderr
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
+1 -1
View File
@@ -96,7 +96,7 @@ XXH3_128_canonical_from_hash :: proc(hash: XXH128_hash_t) -> (canonical: XXH128_
#assert(size_of(XXH128_canonical) == size_of(XXH128_hash_t))
t := hash
when ODIN_ENDIAN == "little" {
when ODIN_ENDIAN == .Little {
t.high = byte_swap(t.high)
t.low = byte_swap(t.low)
}
+2
View File
@@ -6,6 +6,8 @@
Jeroen van Rijn: Initial implementation, optimization.
Ginger Bill: Cosmetic changes.
*/
// package image implements a general 2D image library to be used with other image related packages
package image
import "core:bytes"
+1 -1
View File
@@ -189,7 +189,7 @@ write_image_as_ppm :: proc(filename: string, image: ^image.Image) -> (success: b
img := image
// PBM 16-bit images are big endian
when ODIN_ENDIAN == "little" {
when ODIN_ENDIAN == .Little {
if img.depth == 16 {
// The pixel components are in Big Endian. Let's byteswap back.
input := mem.slice_data_cast([]u16, img.pixels.buf[:])
+6 -1
View File
@@ -6,6 +6,11 @@
Jeroen van Rijn: Initial implementation.
Ginger Bill: Cosmetic changes.
*/
// package png implements a PNG image reader
//
// The PNG specification is at https://www.w3.org/TR/PNG/.
package png
import "core:compress"
@@ -1611,7 +1616,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
}
}
}
when ODIN_ENDIAN == "little" {
when ODIN_ENDIAN == .Little {
if img.depth == 16 {
// The pixel components are in Big Endian. Let's byteswap.
input := mem.slice_data_cast([]u16be, img.pixels.buf[:])
+5
View File
@@ -197,3 +197,8 @@ type_field_index_of :: proc($T: typeid, $name: string) -> uintptr ---
type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) ---
type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) ---
// Internal compiler use only
__entry_point :: proc() ---
+39 -2
View File
@@ -1,9 +1,13 @@
// package io provides basic interfaces for generic data stream primitives.
// The purpose of this package is wrap existing data structures and their
// operations into an abstracted stream interface.
package io
import "core:intrinsics"
import "core:runtime"
import "core:unicode/utf8"
// Seek whence values
Seek_From :: enum {
Start = 0, // seek relative to the origin of the file
Current = 1, // seek relative to the current offset
@@ -139,6 +143,10 @@ destroy :: proc(s: Stream) -> Error {
return .Empty
}
// 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
// bytes read along with the error.
read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
if s.stream_vtable != nil && s.impl_read != nil {
n, err = s->impl_read(p)
@@ -150,6 +158,7 @@ read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
return 0, .Empty
}
// 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) {
if s.stream_vtable != nil && s.impl_write != nil {
n, err = s->impl_write(p)
@@ -161,6 +170,13 @@ write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Erro
return 0, .Empty
}
// seek sets the offset of the next read or write to offset.
//
// .Start means seek relative to the origin of the file.
// .Current means seek relative to the current offset.
// .End means seek relative to the end.
//
// 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) {
if s.stream_vtable != nil && s.impl_seek != nil {
return s->impl_seek(offset, whence)
@@ -168,6 +184,8 @@ seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error)
return 0, .Empty
}
// The behaviour of close after the first call is stream implementation defined.
// Different streams may document their own behaviour.
close :: proc(s: Closer) -> Error {
if s.stream_vtable != nil && s.impl_close != nil {
return s->impl_close()
@@ -184,6 +202,7 @@ flush :: proc(s: Flusher) -> Error {
return .None
}
// 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 {
if s.stream_vtable == nil {
return 0
@@ -214,7 +233,12 @@ size :: proc(s: Stream) -> i64 {
// read_at reads len(p) bytes into p starting with the provided offset in the underlying Reader_At stream r.
// It returns the number of bytes read and any error if occurred.
//
// When read_at returns n < len(p), it returns a non-nil Error explaining why.
//
// 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) {
defer if n_read != nil {
n_read^ += n
@@ -245,6 +269,11 @@ read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n:
}
// write_at writes len(p) bytes into p starting with the provided offset in the underlying Writer_At stream w.
// It returns the number of bytes written and any error if occurred.
//
// If write_at is writing to a Writer_At which has a seek offset, then write_at should not affect the underlying
// seek offset.
write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) {
defer if n_written != nil {
n_written^ += n
@@ -294,6 +323,7 @@ read_from :: proc(w: Reader_From, r: Reader) -> (n: i64, err: Error) {
}
// read_byte reads and returns the next byte from r.
read_byte :: proc(r: Byte_Reader, n_read: ^int = nil) -> (b: byte, err: Error) {
defer if err == nil && n_read != nil {
n_read^ += 1
@@ -347,6 +377,7 @@ _write_byte :: proc(w: Byte_Writer, c: byte, n_written: ^int = nil) -> (err: Err
return err
}
// read_rune reads a single UTF-8 encoded Unicode codepoint and returns the rune and its size in bytes.
read_rune :: proc(br: Rune_Reader, n_read: ^int = nil) -> (ch: rune, size: int, err: Error) {
defer if err == nil && n_read != nil {
n_read^ += size
@@ -405,10 +436,12 @@ unread_rune :: proc(s: Rune_Scanner) -> Error {
}
// 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) {
return write(s, transmute([]byte)str, n_written)
}
// write_rune writes a UTF-8 encoded rune to w.
write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err: Error) {
defer if err == nil && n_written != nil {
n_written^ += size
@@ -430,12 +463,16 @@ write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err
}
// read_full expected exactly len(buf) bytes from r into buf.
read_full :: proc(r: Reader, buf: []byte) -> (n: int, err: Error) {
return read_at_least(r, buf, len(buf))
}
// read_at_least reads from r into buf until it has read at least min bytes. It returns the number
// of bytes copied and an error if fewer bytes were read. `.EOF` is only returned if no bytes were read.
// `.Unexpected_EOF` is returned when an `.EOF ` is returned by the passed Reader after reading
// fewer than min bytes. If len(buf) is less than min, `.Short_Buffer` is returned.
read_at_least :: proc(r: Reader, buf: []byte, min: int) -> (n: int, err: Error) {
if len(buf) < min {
return 0, .Short_Buffer
+2 -4
View File
@@ -2,12 +2,10 @@
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
An arbitrary precision mathematics implementation in Odin.
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
This file collects public proc maps and their aliases.
*/
package math_big
/*
+2 -4
View File
@@ -1,11 +1,9 @@
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
An arbitrary precision mathematics implementation in Odin.
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
*/
package math_big
import "core:intrinsics"
+6
View File
@@ -0,0 +1,6 @@
/*
A BigInt implementation in Odin.
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
*/
package math_big
+2 -4
View File
@@ -1,11 +1,9 @@
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
An arbitrary precision mathematics implementation in Odin.
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
*/
package math_big
import "core:intrinsics"
+3 -5
View File
@@ -1,12 +1,7 @@
//+ignore
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
A BigInt implementation in Odin.
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
========================== Low-level routines ==========================
IMPORTANT: `internal_*` procedures make certain assumptions about their input.
@@ -29,6 +24,9 @@
TODO: Handle +/- Infinity and NaN.
*/
//+ignore
package math_big
import "core:mem"
+2
View File
@@ -8,6 +8,8 @@
This file contains logical operations like `and`, `or` and `xor`.
*/
package math_big
/*
+2
View File
@@ -8,6 +8,8 @@
This file contains prime finding operations.
*/
package math_big
import rnd "core:math/rand"
+2
View File
@@ -15,6 +15,8 @@
These aren't exported for the same reasons.
*/
package math_big
import "core:intrinsics"
+2
View File
@@ -8,6 +8,8 @@
This file contains basic arithmetic operations like `add`, `sub`, `mul`, `div`, ...
*/
package math_big
import "core:intrinsics"
+2
View File
@@ -12,6 +12,8 @@
- Use Barrett reduction for non-powers-of-two.
- Also look at extracting and splatting several digits at once.
*/
package math_big
import "core:intrinsics"
+2 -1
View File
@@ -1,4 +1,3 @@
//+ignore
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
@@ -7,6 +6,8 @@
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
*/
//+ignore
package math_big
import "core:time"
+16 -16
View File
@@ -69,29 +69,29 @@ rotate_left :: proc(x: uint, k: int) -> uint {
}
from_be_u8 :: proc(i: u8) -> u8 { return i }
from_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
from_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
from_be_u64 :: proc(i: u64) -> u64 { 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) } }
from_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
from_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
from_be_u64 :: proc(i: u64) -> u64 { 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) } }
from_le_u8 :: proc(i: u8) -> u8 { return i }
from_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
from_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
from_le_u64 :: proc(i: u64) -> u64 { 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) } }
from_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
from_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
from_le_u64 :: proc(i: u64) -> u64 { 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) } }
to_be_u8 :: proc(i: u8) -> u8 { return i }
to_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
to_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
to_be_u64 :: proc(i: u64) -> u64 { 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) } }
to_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
to_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
to_be_u64 :: proc(i: u64) -> u64 { 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) } }
to_le_u8 :: proc(i: u8) -> u8 { return i }
to_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
to_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
to_le_u64 :: proc(i: u64) -> u64 { 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) } }
to_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
to_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
to_le_u64 :: proc(i: u64) -> u64 { 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) } }
+19 -62
View File
@@ -1,6 +1,7 @@
package linalg
import "core:math"
import "core:builtin"
import "core:intrinsics"
// Generic
@@ -60,14 +61,7 @@ quaternion256_dot :: proc(a, b: $T/quaternion256) -> (c: f64) {
dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quaternion256_dot}
inner_product :: dot
outer_product :: proc(a: $A/[$M]$E, b: $B/[$N]E) -> (out: [M][N]E) where IS_NUMERIC(E) #no_bounds_check {
for i in 0..<M {
for j in 0..<N {
out[i][j] = a[i]*b[j]
}
}
return
}
outer_product :: builtin.outer_product
quaternion_inverse :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0)
@@ -163,65 +157,28 @@ identity :: proc($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check {
return m
}
trace :: proc(m: $T/[$N][N]$E) -> (tr: E) {
for i in 0..<N {
tr += m[i][i]
}
return
}
trace :: builtin.matrix_trace
transpose :: builtin.transpose
transpose :: proc(a: $T/[$N][$M]$E) -> (m: (T when N == M else [M][N]E)) #no_bounds_check {
for j in 0..<M {
for i in 0..<N {
m[j][i] = a[i][j]
}
}
return
}
matrix_mul :: proc(a, b: $M/[$N][N]$E) -> (c: M)
matrix_mul :: proc(a, b: $M/matrix[$N, N]$E) -> (c: M)
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
for i in 0..<N {
for k in 0..<N {
for j in 0..<N {
c[k][i] += a[j][i] * b[k][j]
}
}
}
return
return a * b
}
matrix_comp_mul :: proc(a, b: $M/[$J][$I]$E) -> (c: M)
matrix_comp_mul :: proc(a, b: $M/matrix[$I, $J]$E) -> (c: M)
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
for j in 0..<J {
for i in 0..<I {
c[j][i] = a[j][i] * b[j][i]
}
}
return
return hadamard_product(a, b)
}
matrix_mul_differ :: proc(a: $A/[$J][$I]$E, b: $B/[$K][J]E) -> (c: [K][I]E)
matrix_mul_differ :: proc(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 {
for k in 0..<K {
for j in 0..<J {
for i in 0..<I {
c[k][i] += a[j][i] * b[k][j]
}
}
}
return
return a * b
}
matrix_mul_vector :: proc(a: $A/[$I][$J]$E, b: $B/[I]E) -> (c: B)
matrix_mul_vector :: proc(a: $A/matrix[$I, $J]$E, b: $B/[J]E) -> (c: B)
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
for i in 0..<I {
for j in 0..<J {
c[j] += a[i][j] * b[i]
}
}
return
return a * b
}
quaternion_mul_quaternion :: proc(q1, q2: $Q) -> Q where IS_QUATERNION(Q) {
@@ -270,8 +227,8 @@ mul :: proc{
vector_to_ptr :: proc(v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check {
return &v[0]
}
matrix_to_ptr :: proc(m: ^$A/[$I][$J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check {
return &m[0][0]
matrix_to_ptr :: proc(m: ^$A/matrix[$I, $J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check {
return &m[0, 0]
}
to_ptr :: proc{vector_to_ptr, matrix_to_ptr}
@@ -330,10 +287,10 @@ array_cast :: proc(v: $A/[$N]$T, $Elem_Type: typeid) -> (w: [N]Elem_Type) #no_bo
return
}
matrix_cast :: proc(v: $A/[$M][$N]$T, $Elem_Type: typeid) -> (w: [M][N]Elem_Type) #no_bounds_check {
for i in 0..<M {
for j in 0..<N {
w[i][j] = Elem_Type(v[i][j])
matrix_cast :: proc(v: $A/matrix[$M, $N]$T, $Elem_Type: typeid) -> (w: matrix[M, N]Elem_Type) #no_bounds_check {
for j in 0..<N {
for i in 0..<M {
w[i, j] = Elem_Type(v[i, j])
}
}
return
@@ -357,6 +314,6 @@ to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return array_cast(v, ui
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) }
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) }
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) }
to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256) }
+37 -19
View File
@@ -473,6 +473,25 @@ floor_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {floor(x.x), floor(x.y), fl
floor_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
round :: proc{
round_f32,
round_f64,
round_vec2,
round_vec3,
round_vec4,
round_dvec2,
round_dvec3,
round_dvec4,
}
round_vec2 :: proc "c" (x: vec2) -> vec2 { return {round(x.x), round(x.y)} }
round_vec3 :: proc "c" (x: vec3) -> vec3 { return {round(x.x), round(x.y), round(x.z)} }
round_vec4 :: proc "c" (x: vec4) -> vec4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
round_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {round(x.x), round(x.y)} }
round_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {round(x.x), round(x.y), round(x.z)} }
round_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
ceil :: proc{
ceil_f32,
ceil_f64,
@@ -693,23 +712,22 @@ saturate :: proc{
saturate_uvec3,
saturate_uvec4,
}
saturate_i32 :: proc "c" (x, y, z: i32) -> i32 { return builtin.clamp(x, 0, 1) }
saturate_u32 :: proc "c" (x, y, z: u32) -> u32 { return builtin.clamp(x, 0, 1) }
saturate_f32 :: proc "c" (x, y, z: f32) -> f32 { return builtin.clamp(x, 0, 1) }
saturate_f64 :: proc "c" (x, y, z: f64) -> f64 { return builtin.clamp(x, 0, 1) }
saturate_vec2 :: proc "c" (x, y, z: vec2) -> vec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
saturate_vec3 :: proc "c" (x, y, z: vec3) -> vec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
saturate_vec4 :: proc "c" (x, y, z: vec4) -> vec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
saturate_dvec2 :: proc "c" (x, y, z: dvec2) -> dvec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
saturate_dvec3 :: proc "c" (x, y, z: dvec3) -> dvec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
saturate_dvec4 :: proc "c" (x, y, z: dvec4) -> dvec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
saturate_ivec2 :: proc "c" (x, y, z: ivec2) -> ivec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
saturate_ivec3 :: proc "c" (x, y, z: ivec3) -> ivec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
saturate_ivec4 :: proc "c" (x, y, z: ivec4) -> ivec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
saturate_uvec2 :: proc "c" (x, y, z: uvec2) -> uvec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
saturate_uvec3 :: proc "c" (x, y, z: uvec3) -> uvec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
saturate_uvec4 :: proc "c" (x, y, z: uvec4) -> uvec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
saturate_i32 :: proc "c" (v: i32) -> i32 { return builtin.clamp(v, 0, 1) }
saturate_u32 :: proc "c" (v: u32) -> u32 { return builtin.clamp(v, 0, 1) }
saturate_f32 :: proc "c" (v: f32) -> f32 { return builtin.clamp(v, 0, 1) }
saturate_f64 :: proc "c" (v: f64) -> f64 { return builtin.clamp(v, 0, 1) }
saturate_vec2 :: proc "c" (v: vec2) -> vec2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
saturate_vec3 :: proc "c" (v: vec3) -> vec3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
saturate_vec4 :: proc "c" (v: vec4) -> vec4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
saturate_dvec2 :: proc "c" (v: dvec2) -> dvec2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
saturate_dvec3 :: proc "c" (v: dvec3) -> dvec3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
saturate_dvec4 :: proc "c" (v: dvec4) -> dvec4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
saturate_ivec2 :: proc "c" (v: ivec2) -> ivec2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
saturate_ivec3 :: proc "c" (v: ivec3) -> ivec3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
saturate_ivec4 :: proc "c" (v: ivec4) -> ivec4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
saturate_uvec2 :: proc "c" (v: uvec2) -> uvec2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
saturate_uvec3 :: proc "c" (v: uvec3) -> uvec3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
saturate_uvec4 :: proc "c" (v: uvec4) -> uvec4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
mix :: proc{
mix_f32,
@@ -1597,7 +1615,7 @@ quatNlerp :: proc "c" (a, b: quat, t: f32) -> (c: quat) {
c.y = a.y + (b.y-a.y)*t
c.z = a.z + (b.z-a.z)*t
c.w = a.w + (b.w-a.w)*t
return c/builtin.abs(c)
return c/quat(builtin.abs(c))
}
quatSlerp :: proc "c" (x, y: quat, t: f32) -> (q: quat) {
@@ -1699,7 +1717,7 @@ dquatNlerp :: proc "c" (a, b: dquat, t: f64) -> (c: dquat) {
c.y = a.y + (b.y-a.y)*t
c.z = a.z + (b.z-a.z)*t
c.w = a.w + (b.w-a.w)*t
return c/builtin.abs(c)
return c/dquat(builtin.abs(c))
}
dquatSlerp :: proc "c" (x, y: dquat, t: f64) -> (q: dquat) {
@@ -23,6 +23,7 @@ log_f32 :: proc "c" (x: f32) -> f32 { return math.ln(x) }
exp2_f32 :: proc "c" (x: f32) -> f32 { return math.pow(f32(2), x) }
sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) }
floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) }
round_f32 :: proc "c" (x: f32) -> f32 { return math.round(x) }
ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) }
mod_f32 :: proc "c" (x, y: f32) -> f32 { return math.mod(x, y) }
fract_f32 :: proc "c" (x: f32) -> f32 {
@@ -53,6 +54,7 @@ log_f64 :: proc "c" (x: f64) -> f64 { return math.ln(x) }
exp2_f64 :: proc "c" (x: f64) -> f64 { return math.pow(f64(2), x) }
sign_f64 :: proc "c" (x: f64) -> f64 { return math.sign(x) }
floor_f64 :: proc "c" (x: f64) -> f64 { return math.floor(x) }
round_f64 :: proc "c" (x: f64) -> f64 { return math.round(x) }
ceil_f64 :: proc "c" (x: f64) -> f64 { return math.ceil(x) }
mod_f64 :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) }
fract_f64 :: proc "c" (x: f64) -> f64 {
+96 -16
View File
@@ -551,6 +551,23 @@ floor_double2 :: proc "c" (x: double2) -> double2 { return {floor(x.x), floor(x.
floor_double3 :: proc "c" (x: double3) -> double3 { return {floor(x.x), floor(x.y), floor(x.z)} }
floor_double4 :: proc "c" (x: double4) -> double4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
round :: proc{
round_float,
round_double,
round_float2,
round_float3,
round_float4,
round_double2,
round_double3,
round_double4,
}
round_float2 :: proc "c" (x: float2) -> float2 { return {round(x.x), round(x.y)} }
round_float3 :: proc "c" (x: float3) -> float3 { return {round(x.x), round(x.y), round(x.z)} }
round_float4 :: proc "c" (x: float4) -> float4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
round_double2 :: proc "c" (x: double2) -> double2 { return {round(x.x), round(x.y)} }
round_double3 :: proc "c" (x: double3) -> double3 { return {round(x.x), round(x.y), round(x.z)} }
round_double4 :: proc "c" (x: double4) -> double4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
ceil :: proc{
ceil_float,
@@ -570,6 +587,69 @@ ceil_double3 :: proc "c" (x: double3) -> double3 { return {ceil(x.x), ceil(x.y),
ceil_double4 :: proc "c" (x: double4) -> double4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} }
isfinite_float :: proc "c" (x: float) -> bool { return !isinf_float(x) }
isfinite_float2 :: proc "c" (x: float2) -> bool2 { return {isfinite_float(x.x), isfinite_float(x.y)} }
isfinite_float3 :: proc "c" (x: float3) -> bool3 { return {isfinite_float(x.x), isfinite_float(x.y), isfinite_float(x.z)} }
isfinite_float4 :: proc "c" (x: float4) -> bool4 { return {isfinite_float(x.x), isfinite_float(x.y), isfinite_float(x.z), isfinite_float(x.w)} }
isfinite_double :: proc "c" (x: double) -> bool { return !isinf_double(x) }
isfinite_double2 :: proc "c" (x: double2) -> bool2 { return {isfinite_double(x.x), isfinite_double(x.y)} }
isfinite_double3 :: proc "c" (x: double3) -> bool3 { return {isfinite_double(x.x), isfinite_double(x.y), isfinite_double(x.z)} }
isfinite_double4 :: proc "c" (x: double4) -> bool4 { return {isfinite_double(x.x), isfinite_double(x.y), isfinite_double(x.z), isfinite_double(x.w)} }
// isfinite is the opposite of isinf and returns true if the number is neither positive-infinite or negative-infinite
isfinite :: proc{
isfinite_float,
isfinite_float2,
isfinite_float3,
isfinite_float4,
isfinite_double,
isfinite_double2,
isfinite_double3,
isfinite_double4,
}
isinf_float :: proc "c" (x: float) -> bool { return x * 0.5 == x }
isinf_float2 :: proc "c" (x: float2) -> bool2 { return {isinf_float(x.x), isinf_float(x.y)} }
isinf_float3 :: proc "c" (x: float3) -> bool3 { return {isinf_float(x.x), isinf_float(x.y), isinf_float(x.z)} }
isinf_float4 :: proc "c" (x: float4) -> bool4 { return {isinf_float(x.x), isinf_float(x.y), isinf_float(x.z), isinf_float(x.w)} }
isinf_double :: proc "c" (x: double) -> bool { return x * 0.5 == x }
isinf_double2 :: proc "c" (x: double2) -> bool2 { return {isinf_double(x.x), isinf_double(x.y)} }
isinf_double3 :: proc "c" (x: double3) -> bool3 { return {isinf_double(x.x), isinf_double(x.y), isinf_double(x.z)} }
isinf_double4 :: proc "c" (x: double4) -> bool4 { return {isinf_double(x.x), isinf_double(x.y), isinf_double(x.z), isinf_double(x.w)} }
// isinf is the opposite of isfinite and returns true if the number is either positive-infinite or negative-infinite
isinf :: proc{
isinf_float,
isinf_float2,
isinf_float3,
isinf_float4,
isinf_double,
isinf_double2,
isinf_double3,
isinf_double4,
}
isnan_float2 :: proc "c" (x: float2) -> bool2 { return {isnan_float(x.x), isnan_float(x.y)} }
isnan_float3 :: proc "c" (x: float3) -> bool3 { return {isnan_float(x.x), isnan_float(x.y), isnan_float(x.z)} }
isnan_float4 :: proc "c" (x: float4) -> bool4 { return {isnan_float(x.x), isnan_float(x.y), isnan_float(x.z), isnan_float(x.w)} }
isnan_double2 :: proc "c" (x: double2) -> bool2 { return {isnan_double(x.x), isnan_double(x.y)} }
isnan_double3 :: proc "c" (x: double3) -> bool3 { return {isnan_double(x.x), isnan_double(x.y), isnan_double(x.z)} }
isnan_double4 :: proc "c" (x: double4) -> bool4 { return {isnan_double(x.x), isnan_double(x.y), isnan_double(x.z), isnan_double(x.w)} }
// isnan returns true if the input value is the special case of Not-A-Number
isnan :: proc{
isnan_float,
isnan_float2,
isnan_float3,
isnan_float4,
isnan_double,
isnan_double2,
isnan_double3,
isnan_double4,
}
fmod :: proc{
fmod_float,
fmod_double,
@@ -772,22 +852,22 @@ saturate :: proc{
saturate_uint3,
saturate_uint4,
}
saturate_int :: proc "c" (x, y, z: int) -> int { return builtin.clamp(x, 0, 1) }
saturate_uint :: proc "c" (x, y, z: uint) -> uint { return builtin.clamp(x, 0, 1) }
saturate_float :: proc "c" (x, y, z: float) -> float { return builtin.clamp(x, 0, 1) }
saturate_double :: proc "c" (x, y, z: double) -> double { return builtin.clamp(x, 0, 1) }
saturate_float2 :: proc "c" (x, y, z: float2) -> float2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
saturate_float3 :: proc "c" (x, y, z: float3) -> float3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
saturate_float4 :: proc "c" (x, y, z: float4) -> float4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
saturate_double2 :: proc "c" (x, y, z: double2) -> double2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
saturate_double3 :: proc "c" (x, y, z: double3) -> double3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
saturate_double4 :: proc "c" (x, y, z: double4) -> double4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
saturate_int2 :: proc "c" (x, y, z: int2) -> int2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
saturate_int3 :: proc "c" (x, y, z: int3) -> int3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
saturate_int4 :: proc "c" (x, y, z: int4) -> int4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
saturate_uint2 :: proc "c" (x, y, z: uint2) -> uint2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
saturate_uint3 :: proc "c" (x, y, z: uint3) -> uint3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
saturate_uint4 :: proc "c" (x, y, z: uint4) -> uint4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
saturate_int :: proc "c" (v: int) -> int { return builtin.clamp(v, 0, 1) }
saturate_uint :: proc "c" (v: uint) -> uint { return builtin.clamp(v, 0, 1) }
saturate_float :: proc "c" (v: float) -> float { return builtin.clamp(v, 0, 1) }
saturate_double :: proc "c" (v: double) -> double { return builtin.clamp(v, 0, 1) }
saturate_float2 :: proc "c" (v: float2) -> float2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
saturate_float3 :: proc "c" (v: float3) -> float3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
saturate_float4 :: proc "c" (v: float4) -> float4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
saturate_double2 :: proc "c" (v: double2) -> double2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
saturate_double3 :: proc "c" (v: double3) -> double3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
saturate_double4 :: proc "c" (v: double4) -> double4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
saturate_int2 :: proc "c" (v: int2) -> int2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
saturate_int3 :: proc "c" (v: int3) -> int3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
saturate_int4 :: proc "c" (v: int4) -> int4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
saturate_uint2 :: proc "c" (v: uint2) -> uint2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
saturate_uint3 :: proc "c" (v: uint3) -> uint3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
saturate_uint4 :: proc "c" (v: uint4) -> uint4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
lerp :: proc{
@@ -26,7 +26,9 @@ 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) }
sign_float :: proc "c" (x: float) -> float { return math.sign(x) }
floor_float :: proc "c" (x: float) -> float { return math.floor(x) }
round_float :: proc "c" (x: float) -> float { return math.round(x) }
ceil_float :: proc "c" (x: float) -> float { return math.ceil(x) }
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) }
frac_float :: proc "c" (x: float) -> float {
if x >= 0 {
@@ -35,6 +37,7 @@ frac_float :: proc "c" (x: float) -> float {
return math.trunc(-x) + x
}
cos_double :: proc "c" (x: double) -> double { return math.cos(x) }
sin_double :: proc "c" (x: double) -> double { return math.sin(x) }
tan_double :: proc "c" (x: double) -> double { return math.tan(x) }
@@ -59,7 +62,9 @@ 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) }
sign_double :: proc "c" (x: double) -> double { return math.sign(x) }
floor_double :: proc "c" (x: double) -> double { return math.floor(x) }
round_double :: proc "c" (x: double) -> double { return math.round(x) }
ceil_double :: proc "c" (x: double) -> double { return math.ceil(x) }
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) }
frac_double :: proc "c" (x: double) -> double {
if x >= 0 {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+5
View File
@@ -1,5 +1,10 @@
package linalg
/*
These procedures are to allow for swizzling with non-compile (runtime) known components
*/
Scalar_Components :: enum u8 {
x = 0,
r = 0,
+214
View File
@@ -0,0 +1,214 @@
package rand
import "core:math"
// exp_float64 returns a exponential distribution in the range (0, max(f64)],
// with an exponential distribution who rate parameter is 1 (lambda) and whose mean
// is 1 (1/lambda).
//
// To produce a distribution with a differetn rate parameter, divide the result by
// the desired rate parameter
//
// "The Ziggurat Method for Generating Random Variables"
// Authors: George Marsaglia, Wai Wan Tsang
// Submitted: 2000-04-15. Published: 2000-10-02.
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
// https://www.jstatsoft.org/article/view/v005i08 [web page]
//
exp_float64 :: proc(r: ^Rand = nil) -> f64 {
re :: 7.69711747013104972
@(static)
ke := [256]u32{
0xe290a139, 0x0, 0x9beadebc, 0xc377ac71, 0xd4ddb990,
0xde893fb8, 0xe4a8e87c, 0xe8dff16a, 0xebf2deab, 0xee49a6e8,
0xf0204efd, 0xf19bdb8e, 0xf2d458bb, 0xf3da104b, 0xf4b86d78,
0xf577ad8a, 0xf61de83d, 0xf6afb784, 0xf730a573, 0xf7a37651,
0xf80a5bb6, 0xf867189d, 0xf8bb1b4f, 0xf9079062, 0xf94d70ca,
0xf98d8c7d, 0xf9c8928a, 0xf9ff175b, 0xfa319996, 0xfa6085f8,
0xfa8c3a62, 0xfab5084e, 0xfadb36c8, 0xfaff0410, 0xfb20a6ea,
0xfb404fb4, 0xfb5e2951, 0xfb7a59e9, 0xfb95038c, 0xfbae44ba,
0xfbc638d8, 0xfbdcf892, 0xfbf29a30, 0xfc0731df, 0xfc1ad1ed,
0xfc2d8b02, 0xfc3f6c4d, 0xfc5083ac, 0xfc60ddd1, 0xfc708662,
0xfc7f8810, 0xfc8decb4, 0xfc9bbd62, 0xfca9027c, 0xfcb5c3c3,
0xfcc20864, 0xfccdd70a, 0xfcd935e3, 0xfce42ab0, 0xfceebace,
0xfcf8eb3b, 0xfd02c0a0, 0xfd0c3f59, 0xfd156b7b, 0xfd1e48d6,
0xfd26daff, 0xfd2f2552, 0xfd372af7, 0xfd3eeee5, 0xfd4673e7,
0xfd4dbc9e, 0xfd54cb85, 0xfd5ba2f2, 0xfd62451b, 0xfd68b415,
0xfd6ef1da, 0xfd750047, 0xfd7ae120, 0xfd809612, 0xfd8620b4,
0xfd8b8285, 0xfd90bcf5, 0xfd95d15e, 0xfd9ac10b, 0xfd9f8d36,
0xfda43708, 0xfda8bf9e, 0xfdad2806, 0xfdb17141, 0xfdb59c46,
0xfdb9a9fd, 0xfdbd9b46, 0xfdc170f6, 0xfdc52bd8, 0xfdc8ccac,
0xfdcc542d, 0xfdcfc30b, 0xfdd319ef, 0xfdd6597a, 0xfdd98245,
0xfddc94e5, 0xfddf91e6, 0xfde279ce, 0xfde54d1f, 0xfde80c52,
0xfdeab7de, 0xfded5034, 0xfdefd5be, 0xfdf248e3, 0xfdf4aa06,
0xfdf6f984, 0xfdf937b6, 0xfdfb64f4, 0xfdfd818d, 0xfdff8dd0,
0xfe018a08, 0xfe03767a, 0xfe05536c, 0xfe07211c, 0xfe08dfc9,
0xfe0a8fab, 0xfe0c30fb, 0xfe0dc3ec, 0xfe0f48b1, 0xfe10bf76,
0xfe122869, 0xfe1383b4, 0xfe14d17c, 0xfe1611e7, 0xfe174516,
0xfe186b2a, 0xfe19843e, 0xfe1a9070, 0xfe1b8fd6, 0xfe1c8289,
0xfe1d689b, 0xfe1e4220, 0xfe1f0f26, 0xfe1fcfbc, 0xfe2083ed,
0xfe212bc3, 0xfe21c745, 0xfe225678, 0xfe22d95f, 0xfe234ffb,
0xfe23ba4a, 0xfe241849, 0xfe2469f2, 0xfe24af3c, 0xfe24e81e,
0xfe25148b, 0xfe253474, 0xfe2547c7, 0xfe254e70, 0xfe25485a,
0xfe25356a, 0xfe251586, 0xfe24e88f, 0xfe24ae64, 0xfe2466e1,
0xfe2411df, 0xfe23af34, 0xfe233eb4, 0xfe22c02c, 0xfe22336b,
0xfe219838, 0xfe20ee58, 0xfe20358c, 0xfe1f6d92, 0xfe1e9621,
0xfe1daef0, 0xfe1cb7ac, 0xfe1bb002, 0xfe1a9798, 0xfe196e0d,
0xfe1832fd, 0xfe16e5fe, 0xfe15869d, 0xfe141464, 0xfe128ed3,
0xfe10f565, 0xfe0f478c, 0xfe0d84b1, 0xfe0bac36, 0xfe09bd73,
0xfe07b7b5, 0xfe059a40, 0xfe03644c, 0xfe011504, 0xfdfeab88,
0xfdfc26e9, 0xfdf98629, 0xfdf6c83b, 0xfdf3ec01, 0xfdf0f04a,
0xfdedd3d1, 0xfdea953d, 0xfde7331e, 0xfde3abe9, 0xfddffdfb,
0xfddc2791, 0xfdd826cd, 0xfdd3f9a8, 0xfdcf9dfc, 0xfdcb1176,
0xfdc65198, 0xfdc15bb3, 0xfdbc2ce2, 0xfdb6c206, 0xfdb117be,
0xfdab2a63, 0xfda4f5fd, 0xfd9e7640, 0xfd97a67a, 0xfd908192,
0xfd8901f2, 0xfd812182, 0xfd78d98e, 0xfd7022bb, 0xfd66f4ed,
0xfd5d4732, 0xfd530f9c, 0xfd48432b, 0xfd3cd59a, 0xfd30b936,
0xfd23dea4, 0xfd16349e, 0xfd07a7a3, 0xfcf8219b, 0xfce7895b,
0xfcd5c220, 0xfcc2aadb, 0xfcae1d5e, 0xfc97ed4e, 0xfc7fe6d4,
0xfc65ccf3, 0xfc495762, 0xfc2a2fc8, 0xfc07ee19, 0xfbe213c1,
0xfbb8051a, 0xfb890078, 0xfb5411a5, 0xfb180005, 0xfad33482,
0xfa839276, 0xfa263b32, 0xf9b72d1c, 0xf930a1a2, 0xf889f023,
0xf7b577d2, 0xf69c650c, 0xf51530f0, 0xf2cb0e3c, 0xeeefb15d,
0xe6da6ecf,
}
@(static)
we := [256]f32{
2.0249555e-09, 1.486674e-11, 2.4409617e-11, 3.1968806e-11,
3.844677e-11, 4.4228204e-11, 4.9516443e-11, 5.443359e-11,
5.905944e-11, 6.344942e-11, 6.7643814e-11, 7.1672945e-11,
7.556032e-11, 7.932458e-11, 8.298079e-11, 8.654132e-11,
9.0016515e-11, 9.3415074e-11, 9.674443e-11, 1.0001099e-10,
1.03220314e-10, 1.06377254e-10, 1.09486115e-10, 1.1255068e-10,
1.1557435e-10, 1.1856015e-10, 1.2151083e-10, 1.2442886e-10,
1.2731648e-10, 1.3017575e-10, 1.3300853e-10, 1.3581657e-10,
1.3860142e-10, 1.4136457e-10, 1.4410738e-10, 1.4683108e-10,
1.4953687e-10, 1.5222583e-10, 1.54899e-10, 1.5755733e-10,
1.6020171e-10, 1.6283301e-10, 1.6545203e-10, 1.6805951e-10,
1.7065617e-10, 1.732427e-10, 1.7581973e-10, 1.7838787e-10,
1.8094774e-10, 1.8349985e-10, 1.8604476e-10, 1.8858298e-10,
1.9111498e-10, 1.9364126e-10, 1.9616223e-10, 1.9867835e-10,
2.0119004e-10, 2.0369768e-10, 2.0620168e-10, 2.087024e-10,
2.1120022e-10, 2.136955e-10, 2.1618855e-10, 2.1867974e-10,
2.2116936e-10, 2.2365775e-10, 2.261452e-10, 2.2863202e-10,
2.311185e-10, 2.3360494e-10, 2.360916e-10, 2.3857874e-10,
2.4106667e-10, 2.4355562e-10, 2.4604588e-10, 2.485377e-10,
2.5103128e-10, 2.5352695e-10, 2.560249e-10, 2.585254e-10,
2.6102867e-10, 2.6353494e-10, 2.6604446e-10, 2.6855745e-10,
2.7107416e-10, 2.7359479e-10, 2.761196e-10, 2.7864877e-10,
2.8118255e-10, 2.8372119e-10, 2.8626485e-10, 2.888138e-10,
2.9136826e-10, 2.939284e-10, 2.9649452e-10, 2.9906677e-10,
3.016454e-10, 3.0423064e-10, 3.0682268e-10, 3.0942177e-10,
3.1202813e-10, 3.1464195e-10, 3.1726352e-10, 3.19893e-10,
3.2253064e-10, 3.251767e-10, 3.2783135e-10, 3.3049485e-10,
3.3316744e-10, 3.3584938e-10, 3.3854083e-10, 3.4124212e-10,
3.4395342e-10, 3.46675e-10, 3.4940711e-10, 3.5215003e-10,
3.5490397e-10, 3.5766917e-10, 3.6044595e-10, 3.6323455e-10,
3.660352e-10, 3.6884823e-10, 3.7167386e-10, 3.745124e-10,
3.773641e-10, 3.802293e-10, 3.8310827e-10, 3.860013e-10,
3.8890866e-10, 3.918307e-10, 3.9476775e-10, 3.9772008e-10,
4.0068804e-10, 4.0367196e-10, 4.0667217e-10, 4.09689e-10,
4.1272286e-10, 4.1577405e-10, 4.1884296e-10, 4.2192994e-10,
4.250354e-10, 4.281597e-10, 4.313033e-10, 4.3446652e-10,
4.3764986e-10, 4.408537e-10, 4.4407847e-10, 4.4732465e-10,
4.5059267e-10, 4.5388301e-10, 4.571962e-10, 4.6053267e-10,
4.6389292e-10, 4.6727755e-10, 4.70687e-10, 4.741219e-10,
4.7758275e-10, 4.810702e-10, 4.845848e-10, 4.8812715e-10,
4.9169796e-10, 4.9529775e-10, 4.989273e-10, 5.0258725e-10,
5.0627835e-10, 5.100013e-10, 5.1375687e-10, 5.1754584e-10,
5.21369e-10, 5.2522725e-10, 5.2912136e-10, 5.330522e-10,
5.370208e-10, 5.4102806e-10, 5.45075e-10, 5.491625e-10,
5.532918e-10, 5.5746385e-10, 5.616799e-10, 5.6594107e-10,
5.7024857e-10, 5.746037e-10, 5.7900773e-10, 5.834621e-10,
5.8796823e-10, 5.925276e-10, 5.971417e-10, 6.018122e-10,
6.065408e-10, 6.113292e-10, 6.1617933e-10, 6.2109295e-10,
6.260722e-10, 6.3111916e-10, 6.3623595e-10, 6.4142497e-10,
6.4668854e-10, 6.5202926e-10, 6.5744976e-10, 6.6295286e-10,
6.6854156e-10, 6.742188e-10, 6.79988e-10, 6.858526e-10,
6.9181616e-10, 6.978826e-10, 7.04056e-10, 7.103407e-10,
7.167412e-10, 7.2326256e-10, 7.2990985e-10, 7.366886e-10,
7.4360473e-10, 7.5066453e-10, 7.5787476e-10, 7.6524265e-10,
7.7277595e-10, 7.80483e-10, 7.883728e-10, 7.9645507e-10,
8.047402e-10, 8.1323964e-10, 8.219657e-10, 8.309319e-10,
8.401528e-10, 8.496445e-10, 8.594247e-10, 8.6951274e-10,
8.799301e-10, 8.9070046e-10, 9.018503e-10, 9.134092e-10,
9.254101e-10, 9.378904e-10, 9.508923e-10, 9.644638e-10,
9.786603e-10, 9.935448e-10, 1.0091913e-09, 1.025686e-09,
1.0431306e-09, 1.0616465e-09, 1.08138e-09, 1.1025096e-09,
1.1252564e-09, 1.1498986e-09, 1.1767932e-09, 1.206409e-09,
1.2393786e-09, 1.276585e-09, 1.3193139e-09, 1.3695435e-09,
1.4305498e-09, 1.508365e-09, 1.6160854e-09, 1.7921248e-09,
}
@(static)
fe := [256]f32{
1, 0.9381437, 0.90046996, 0.87170434, 0.8477855, 0.8269933,
0.8084217, 0.7915276, 0.77595687, 0.7614634, 0.7478686,
0.7350381, 0.72286767, 0.71127474, 0.70019263, 0.6895665,
0.67935055, 0.6695063, 0.66000086, 0.65080583, 0.6418967,
0.63325197, 0.6248527, 0.6166822, 0.60872537, 0.60096896,
0.5934009, 0.58601034, 0.5787874, 0.57172304, 0.5648092,
0.5580383, 0.5514034, 0.5448982, 0.5385169, 0.53225386,
0.5261042, 0.52006316, 0.5141264, 0.50828975, 0.5025495,
0.496902, 0.49134386, 0.485872, 0.48048335, 0.4751752,
0.46994483, 0.46478975, 0.45970762, 0.45469615, 0.44975325,
0.44487688, 0.44006512, 0.43531612, 0.43062815, 0.42599955,
0.42142874, 0.4169142, 0.41245446, 0.40804818, 0.403694,
0.3993907, 0.39513698, 0.39093173, 0.38677382, 0.38266218,
0.37859577, 0.37457356, 0.37059465, 0.3666581, 0.362763,
0.35890847, 0.35509375, 0.351318, 0.3475805, 0.34388044,
0.34021714, 0.3365899, 0.33299807, 0.32944095, 0.32591796,
0.3224285, 0.3189719, 0.31554767, 0.31215525, 0.30879408,
0.3054636, 0.3021634, 0.29889292, 0.2956517, 0.29243928,
0.28925523, 0.28609908, 0.28297043, 0.27986884, 0.27679393,
0.2737453, 0.2707226, 0.2677254, 0.26475343, 0.26180625,
0.25888354, 0.25598502, 0.2531103, 0.25025907, 0.24743107,
0.24462597, 0.24184346, 0.23908329, 0.23634516, 0.23362878,
0.23093392, 0.2282603, 0.22560766, 0.22297576, 0.22036438,
0.21777324, 0.21520215, 0.21265087, 0.21011916, 0.20760682,
0.20511365, 0.20263945, 0.20018397, 0.19774707, 0.19532852,
0.19292815, 0.19054577, 0.1881812, 0.18583426, 0.18350479,
0.1811926, 0.17889754, 0.17661946, 0.17435817, 0.17211354,
0.1698854, 0.16767362, 0.16547804, 0.16329853, 0.16113494,
0.15898713, 0.15685499, 0.15473837, 0.15263714, 0.15055119,
0.14848037, 0.14642459, 0.14438373, 0.14235765, 0.14034624,
0.13834943, 0.13636707, 0.13439907, 0.13244532, 0.13050574,
0.1285802, 0.12666863, 0.12477092, 0.12288698, 0.12101672,
0.119160056, 0.1173169, 0.115487166, 0.11367077, 0.11186763,
0.11007768, 0.10830083, 0.10653701, 0.10478614, 0.10304816,
0.101323, 0.09961058, 0.09791085, 0.09622374, 0.09454919,
0.09288713, 0.091237515, 0.08960028, 0.087975375, 0.08636274,
0.08476233, 0.083174095, 0.081597984, 0.08003395, 0.07848195,
0.076941945, 0.07541389, 0.07389775, 0.072393484, 0.07090106,
0.069420435, 0.06795159, 0.066494495, 0.06504912, 0.063615434,
0.062193416, 0.060783047, 0.059384305, 0.057997175,
0.05662164, 0.05525769, 0.053905312, 0.052564494, 0.051235236,
0.049917534, 0.048611384, 0.047316793, 0.046033762, 0.0447623,
0.043502413, 0.042254124, 0.041017443, 0.039792392,
0.038578995, 0.037377283, 0.036187284, 0.035009038,
0.033842582, 0.032687962, 0.031545233, 0.030414443, 0.02929566,
0.02818895, 0.027094385, 0.026012046, 0.024942026, 0.023884421,
0.022839336, 0.021806888, 0.020787204, 0.019780423, 0.0187867,
0.0178062, 0.016839107, 0.015885621, 0.014945968, 0.014020392,
0.013109165, 0.012212592, 0.011331013, 0.01046481, 0.009614414,
0.008780315, 0.007963077, 0.0071633533, 0.006381906,
0.0056196423, 0.0048776558, 0.004157295, 0.0034602648,
0.0027887989, 0.0021459677, 0.0015362998, 0.0009672693,
0.00045413437,
}
for {
j := uint32(r)
i := j & 0xFF
x := f64(j) * f64(we[i])
if j < ke[i] {
return x
}
if i == 0 {
return re - math.ln(float64(r))
}
if fe[i]+f32(float64(r))*(fe[i-1]-fe[i]) < f32(math.exp(-x)) {
return x
}
}
}
+6 -8
View File
@@ -2,6 +2,12 @@ package rand
import "core:math"
// norm_float64 returns a normally distributed f64 in the range -max(f64) through +max(f64) inclusive,
// with a standard normal distribution with a mean of 0 and standard deviation of 1.
//
// sample = norm_float64() * std_dev + mean
//
//
// Normal distribution
//
@@ -11,12 +17,6 @@ import "core:math"
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
// https://www.jstatsoft.org/article/view/v005i08 [web page]
//
// norm_float64 returns a normally distributed f64 in the range -max(f64) through +max(f64) inclusive,
// with a standard normal distribution with a mean of 0 and standard deviation of 1.
//
// sample = norm_float64() * std_dev + mean
//
norm_float64 :: proc(r: ^Rand = nil) -> f64 {
rn :: 3.442619855899
@@ -49,7 +49,6 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 {
0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a,
0x7ba90bdc, 0x7a722176, 0x77d664e5,
}
@(static)
wn := [128]f32{
1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10,
@@ -85,7 +84,6 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 {
1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09,
1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09,
}
@(static)
fn := [128]f32{
1.00000000, 0.9635997, 0.9362827, 0.9130436, 0.89228165,
+5 -5
View File
@@ -70,7 +70,7 @@ int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 {
if n&(n-1) == 0 {
return int31(r) & (n-1)
}
max := i32((1<<31) - 1 - (1<<31)&u32(n))
max := i32((1<<31) - 1 - (1<<31)%u32(n))
v := int31(r)
for v > max {
v = int31(r)
@@ -85,7 +85,7 @@ int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 {
if n&(n-1) == 0 {
return int63(r) & (n-1)
}
max := i64((1<<63) - 1 - (1<<63)&u64(n))
max := i64((1<<63) - 1 - (1<<63)%u64(n))
v := int63(r)
for v > max {
v = int63(r)
@@ -100,7 +100,7 @@ int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 {
if n&(n-1) == 0 {
return int127(r) & (n-1)
}
max := i128((1<<63) - 1 - (1<<63)&u128(n))
max := i128((1<<127) - 1 - (1<<127)%u128(n))
v := int127(r)
for v > max {
v = int127(r)
@@ -142,8 +142,8 @@ read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
}
// perm returns a slice of n ints in a pseudo-random permutation of integers in the range [0, n)
perm :: proc(n: int, r: ^Rand = nil) -> []int {
m := make([]int, n)
perm :: proc(n: int, r: ^Rand = nil, allocator := context.allocator) -> []int {
m := make([]int, n, allocator)
for i := 0; i < n; i += 1 {
j := int_max(i+1, r)
m[i] = m[j]
+20 -2
View File
@@ -11,7 +11,7 @@ String :: distinct Array(byte)
Version_Type_Major :: 0
Version_Type_Minor :: 2
Version_Type_Patch :: 1
Version_Type_Patch :: 4
Version_Type :: struct {
major, minor, patch: u8,
@@ -77,9 +77,15 @@ Pkg :: struct {
flags: Pkg_Flags,
docs: String,
files: Array(File_Index),
entities: Array(Entity_Index),
entries: Array(Scope_Entry),
}
Scope_Entry :: struct {
name: String,
entity: Entity_Index,
}
Entity_Kind :: enum u32le {
Invalid = 0,
Constant = 1,
@@ -89,6 +95,7 @@ Entity_Kind :: enum u32le {
Proc_Group = 5,
Import_Name = 6,
Library_Name = 7,
Builtin = 8,
}
Entity_Flag :: enum u32le {
@@ -105,8 +112,13 @@ Entity_Flag :: enum u32le {
Type_Alias = 20,
Builtin_Pkg_Builtin = 30,
Builtin_Pkg_Intrinsics = 31,
Var_Thread_Local = 40,
Var_Static = 41,
Private = 50,
}
Entity_Flags :: distinct bit_set[Entity_Flag; u64le]
@@ -122,6 +134,10 @@ Entity :: struct {
_: u32le, // reserved for init
comment: String,
docs: String,
// May be used by (Struct fields and procedure fields):
// .Variable
// .Constant
field_group_index: i32le,
// May used by:
// .Variable
@@ -242,6 +258,8 @@ Type :: struct {
polymorphic_params: Type_Index,
// Used By: .Struct, .Union
where_clauses: Array(String),
// Used By: .Struct
tags: Array(String),
}
Type_Flags_Basic :: distinct bit_set[Type_Flag_Basic; u32le]
+24 -1
View File
@@ -296,6 +296,8 @@ foreign libc {
@(link_name="readdir_r$INODE64") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
@(link_name="fcntl") _unix_fcntl :: proc(fd: Handle, cmd: c.int, buf: ^byte) -> c.int ---
@(link_name="fchmod") _unix_fchmod :: proc(fildes: Handle, mode: u16) -> c.int ---
@(link_name="malloc") _unix_malloc :: proc(size: int) -> rawptr ---
@(link_name="calloc") _unix_calloc :: proc(num, size: int) -> rawptr ---
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
@@ -305,6 +307,8 @@ foreign libc {
@(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int ---
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
@(link_name="strerror") _darwin_string_error :: proc(num : c.int) -> cstring ---
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
}
@@ -319,16 +323,35 @@ get_last_error :: proc() -> int {
return __error()^
}
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
get_last_error_string :: proc() -> string {
return cast(string)_darwin_string_error(cast(c.int)get_last_error())
}
open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (Handle, Errno) {
cstr := strings.clone_to_cstring(path)
handle := _unix_open(cstr, i32(flags), u16(mode))
delete(cstr)
if handle == -1 {
return INVALID_HANDLE, 1
}
when ODIN_OS == "darwin" && ODIN_ARCH == "arm64" {
if mode != 0 {
err := fchmod(handle, cast(u16)mode)
if err != 0 {
_unix_close(handle)
return INVALID_HANDLE, 1
}
}
}
return handle, 0
}
fchmod :: proc(fildes: Handle, mode: u16) -> Errno {
return cast(Errno)_unix_fchmod(fildes, mode)
}
close :: proc(fd: Handle) {
_unix_close(fd)
}
+233 -48
View File
@@ -266,33 +266,142 @@ X_OK :: 1 // Test for execute permission
W_OK :: 2 // Test for write permission
R_OK :: 4 // Test for read permission
AT_FDCWD :: -100
AT_REMOVEDIR :: uintptr(0x200)
AT_SYMLINK_NOFOLLOW :: uintptr(0x100)
_unix_open :: proc(path: cstring, flags: int, mode: int = 0o000) -> Handle {
when ODIN_ARCH != "arm64" {
res := int(intrinsics.syscall(unix.SYS_open, uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
} else { // NOTE: arm64 does not have open
res := int(intrinsics.syscall(unix.SYS_openat, uintptr(AT_FDCWD), uintptr(rawptr(path), uintptr(flags), uintptr(mode))))
}
return -1 if res < 0 else Handle(res)
}
_unix_close :: proc(fd: Handle) -> int {
return int(intrinsics.syscall(unix.SYS_close, uintptr(fd)))
}
_unix_read :: proc(fd: Handle, buf: rawptr, size: uint) -> int {
return int(intrinsics.syscall(unix.SYS_read, uintptr(fd), uintptr(buf), uintptr(size)))
}
_unix_write :: proc(fd: Handle, buf: rawptr, size: uint) -> int {
return int(intrinsics.syscall(unix.SYS_write, uintptr(fd), uintptr(buf), uintptr(size)))
}
_unix_seek :: proc(fd: Handle, offset: i64, whence: int) -> i64 {
when ODIN_ARCH == "amd64" || ODIN_ARCH == "arm64" {
return i64(intrinsics.syscall(unix.SYS_lseek, uintptr(fd), uintptr(offset), uintptr(whence)))
} else {
low := uintptr(offset & 0xFFFFFFFF)
high := uintptr(offset >> 32)
result: i64
res := i64(intrinsics.syscall(unix.SYS__llseek, uintptr(fd), high, low, &result, uintptr(whence)))
return -1 if res < 0 else result
}
}
_unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> int {
when ODIN_ARCH == "amd64" {
return int(intrinsics.syscall(unix.SYS_stat, uintptr(rawptr(path)), uintptr(stat)))
} else when ODIN_ARCH != "arm64" {
return int(intrinsics.syscall(unix.SYS_stat64, uintptr(rawptr(path)), uintptr(stat)))
} else { // NOTE: arm64 does not have stat
return int(intrinsics.syscall(unix.SYS_fstatat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(stat), 0))
}
}
_unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> int {
when ODIN_ARCH == "amd64" || ODIN_ARCH == "arm64" {
return int(intrinsics.syscall(unix.SYS_fstat, uintptr(fd), uintptr(stat)))
} else {
return int(intrinsics.syscall(unix.SYS_fstat64, uintptr(fd), uintptr(stat)))
}
}
_unix_lstat :: proc(path: cstring, stat: ^OS_Stat) -> int {
when ODIN_ARCH == "amd64" {
return int(intrinsics.syscall(unix.SYS_lstat, uintptr(rawptr(path)), uintptr(stat)))
} else when ODIN_ARCH != "arm64" {
return int(intrinsics.syscall(unix.SYS_lstat64, uintptr(rawptr(path)), uintptr(stat)))
} else { // NOTE: arm64 does not have any lstat
return int(intrinsics.syscall(unix.SYS_fstatat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(stat), AT_SYMLINK_NOFOLLOW))
}
}
_unix_readlink :: proc(path: cstring, buf: rawptr, bufsiz: uint) -> int {
when ODIN_ARCH != "arm64" {
return int(intrinsics.syscall(unix.SYS_readlink, uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz)))
} else { // NOTE: arm64 does not have readlink
return int(intrinsics.syscall(unix.SYS_readlinkat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz)))
}
}
_unix_access :: proc(path: cstring, mask: int) -> int {
when ODIN_ARCH != "arm64" {
return int(intrinsics.syscall(unix.SYS_access, uintptr(rawptr(path)), uintptr(mask)))
} else { // NOTE: arm64 does not have access
return int(intrinsics.syscall(unix.SYS_faccessat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(mask)))
}
}
_unix_getcwd :: proc(buf: rawptr, size: uint) -> int {
return int(intrinsics.syscall(unix.SYS_getcwd, uintptr(buf), uintptr(size)))
}
_unix_chdir :: proc(path: cstring) -> int {
return int(intrinsics.syscall(unix.SYS_chdir, uintptr(rawptr(path))))
}
_unix_rename :: proc(old, new: cstring) -> int {
when ODIN_ARCH != "arm64" {
return int(intrinsics.syscall(unix.SYS_rename, uintptr(rawptr(old)), uintptr(rawptr(new))))
} else { // NOTE: arm64 does not have rename
return int(intrinsics.syscall(unix.SYS_renameat, uintptr(AT_FDCWD), uintptr(rawptr(old)), uintptr(rawptr(new))))
}
}
_unix_unlink :: proc(path: cstring) -> int {
when ODIN_ARCH != "arm64" {
return int(intrinsics.syscall(unix.SYS_unlink, uintptr(rawptr(path))))
} else { // NOTE: arm64 does not have unlink
return int(intrinsics.syscall(unix.SYS_unlinkat, uintptr(AT_FDCWD), uintptr(rawptr(path), 0)))
}
}
_unix_rmdir :: proc(path: cstring) -> int {
when ODIN_ARCH != "arm64" {
return int(intrinsics.syscall(unix.SYS_rmdir, uintptr(rawptr(path))))
} else { // NOTE: arm64 does not have rmdir
return int(intrinsics.syscall(unix.SYS_unlinkat, uintptr(AT_FDCWD), uintptr(rawptr(path)), AT_REMOVEDIR))
}
}
_unix_mkdir :: proc(path: cstring, mode: u32) -> int {
when ODIN_ARCH != "arm64" {
return int(intrinsics.syscall(unix.SYS_mkdir, uintptr(rawptr(path)), uintptr(mode)))
} else { // NOTE: arm64 does not have mkdir
return int(intrinsics.syscall(unix.SYS_mkdirat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(mode)))
}
}
foreign libc {
@(link_name="__errno_location") __errno_location :: proc() -> ^int ---
@(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---
@(link_name="close") _unix_close :: proc(fd: Handle) -> c.int ---
@(link_name="read") _unix_read :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
@(link_name="write") _unix_write :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
@(link_name="lseek64") _unix_seek :: proc(fd: Handle, offset: i64, whence: c.int) -> i64 ---
@(link_name="gettid") _unix_gettid :: proc() -> u64 ---
@(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---
@(link_name="stat64") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> c.int ---
@(link_name="lstat") _unix_lstat :: proc(path: cstring, stat: ^OS_Stat) -> c.int ---
@(link_name="fstat") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int ---
@(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir ---
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
@(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) ---
@(link_name="readdir_r") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
@(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t ---
@(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int ---
@(link_name="malloc") _unix_malloc :: proc(size: c.size_t) -> rawptr ---
@(link_name="calloc") _unix_calloc :: proc(num, size: c.size_t) -> rawptr ---
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---
@(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---
@(link_name="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> cstring ---
@(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int ---
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
@@ -308,51 +417,57 @@ is_path_separator :: proc(r: rune) -> bool {
return r == '/'
}
// determine errno from syscall return value
@private
_get_errno :: proc(res: int) -> Errno {
if res < 0 && res > -4096 {
return Errno(-res)
}
return 0
}
// get errno from libc
get_last_error :: proc() -> int {
return __errno_location()^
}
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
cstr := strings.clone_to_cstring(path)
handle := _unix_open(cstr, c.int(flags), c.int(mode))
delete(cstr)
if handle == -1 {
return INVALID_HANDLE, Errno(get_last_error())
handle := _unix_open(cstr, flags, mode)
defer delete(cstr)
if handle < 0 {
return INVALID_HANDLE, _get_errno(int(handle))
}
return handle, ERROR_NONE
}
close :: proc(fd: Handle) -> Errno {
result := _unix_close(fd)
if result == -1 {
return Errno(get_last_error())
}
return ERROR_NONE
return _get_errno(_unix_close(fd))
}
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
bytes_read := _unix_read(fd, &data[0], c.size_t(len(data)))
if bytes_read == -1 {
return -1, Errno(get_last_error())
if bytes_read < 0 {
return -1, _get_errno(bytes_read)
}
return int(bytes_read), ERROR_NONE
return bytes_read, ERROR_NONE
}
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_written := _unix_write(fd, &data[0], c.size_t(len(data)))
if bytes_written == -1 {
return -1, Errno(get_last_error())
bytes_written := _unix_write(fd, &data[0], uint(len(data)))
if bytes_written < 0 {
return -1, _get_errno(bytes_written)
}
return int(bytes_written), ERROR_NONE
}
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
res := _unix_seek(fd, offset, c.int(whence))
if res == -1 {
return -1, Errno(get_last_error())
res := _unix_seek(fd, offset, whence)
if res < 0 {
return -1, _get_errno(int(res))
}
return res, ERROR_NONE
}
@@ -365,6 +480,75 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
return max(s.size, 0), ERROR_NONE
}
rename :: proc(old_path, new_path: string) -> Errno {
old_path_cstr := strings.clone_to_cstring(old_path, context.temp_allocator)
new_path_cstr := strings.clone_to_cstring(new_path, context.temp_allocator)
return _get_errno(_unix_rename(old_path_cstr, new_path_cstr))
}
remove :: proc(path: string) -> Errno {
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
return _get_errno(_unix_unlink(path_cstr))
}
make_directory :: proc(path: string, mode: u32 = 0o775) -> Errno {
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
return _get_errno(_unix_mkdir(path_cstr, mode))
}
remove_directory :: proc(path: string) -> Errno {
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
return _get_errno(_unix_rmdir(path_cstr))
}
is_file_handle :: proc(fd: Handle) -> bool {
s, err := _fstat(fd)
if err != ERROR_NONE {
return false
}
return S_ISREG(s.mode)
}
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
s: OS_Stat
err: Errno
if follow_links {
s, err = _stat(path)
} else {
s, err = _lstat(path)
}
if err != ERROR_NONE {
return false
}
return S_ISREG(s.mode)
}
is_dir_handle :: proc(fd: Handle) -> bool {
s, err := _fstat(fd)
if err != ERROR_NONE {
return false
}
return S_ISDIR(s.mode)
}
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
s: OS_Stat
err: Errno
if follow_links {
s, err = _stat(path)
} else {
s, err = _lstat(path)
}
if err != ERROR_NONE {
return false
}
return S_ISDIR(s.mode)
}
is_file :: proc {is_file_path, is_file_handle}
is_dir :: proc {is_dir_path, is_dir_handle}
// NOTE(bill): Uses startup to initialize it
@@ -401,8 +585,8 @@ _stat :: proc(path: string) -> (OS_Stat, Errno) {
s: OS_Stat
result := _unix_stat(cstr, &s)
if result == -1 {
return s, Errno(get_last_error())
if result < 0 {
return s, _get_errno(result)
}
return s, ERROR_NONE
}
@@ -414,8 +598,8 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
s: OS_Stat
result := _unix_lstat(cstr, &s)
if result == -1 {
return s, Errno(get_last_error())
if result < 0 {
return s, _get_errno(result)
}
return s, ERROR_NONE
}
@@ -424,8 +608,8 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
_fstat :: proc(fd: Handle) -> (OS_Stat, Errno) {
s: OS_Stat
result := _unix_fstat(fd, &s)
if result == -1 {
return s, Errno(get_last_error())
if result < 0 {
return s, _get_errno(result)
}
return s, ERROR_NONE
}
@@ -482,9 +666,9 @@ _readlink :: proc(path: string) -> (string, Errno) {
buf := make([]byte, bufsz)
for {
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
if rc == -1 {
if rc < 0 {
delete(buf)
return "", Errno(get_last_error())
return "", _get_errno(rc)
} else if rc == int(bufsz) {
// NOTE(laleksic, 2021-01-21): Any cleaner way to resize the slice?
bufsz *= 2
@@ -530,9 +714,9 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
access :: proc(path: string, mask: int) -> (bool, Errno) {
cstr := strings.clone_to_cstring(path)
defer delete(cstr)
result := _unix_access(cstr, c.int(mask))
if result == -1 {
return false, Errno(get_last_error())
result := _unix_access(cstr, mask)
if result < 0 {
return false, _get_errno(result)
}
return true, ERROR_NONE
}
@@ -567,11 +751,12 @@ get_current_directory :: proc() -> string {
page_size := get_page_size()
buf := make([dynamic]u8, page_size)
for {
#no_bounds_check cwd := _unix_getcwd(cstring(&buf[0]), c.size_t(len(buf)))
if cwd != nil {
return string(cwd)
#no_bounds_check res := _unix_getcwd(&buf[0], uint(len(buf)))
if res >= 0 {
return strings.string_from_nul_terminated_ptr(&buf[0], len(buf))
}
if Errno(get_last_error()) != ERANGE {
if _get_errno(res) != ERANGE {
return ""
}
resize(&buf, len(buf)+page_size)
@@ -582,8 +767,8 @@ get_current_directory :: proc() -> string {
set_current_directory :: proc(path: string) -> (err: Errno) {
cstr := strings.clone_to_cstring(path, context.temp_allocator)
res := _unix_chdir(cstr)
if res == -1 {
return Errno(get_last_error())
if res < 0 {
return _get_errno(res)
}
return ERROR_NONE
}
+5
View File
@@ -0,0 +1,5 @@
package path
#panic(
`core:path/slashpath - for paths separated by forward slashes, e.g. paths in URLs, this does not deal with OS-specific paths
core:path/filepath - uses either forward slashes or backslashes depending on the operating system, deals with Windows/NT paths with volume letters or backslashes (on the related platforms)`)
@@ -1,4 +1,4 @@
package path
package slashpath
import "core:strings"
import "core:unicode/utf8"
@@ -1,9 +1,9 @@
// The path package is only to be used for paths separated by forward slashes,
// The slashpath package is only to be used for paths separated by forward slashes,
// e.g. paths in URLs
//
// This package does not deal with Windows/NT paths with volume letters or backslashes
// To manipulate operating system specific paths, use the path/filepath package
package path
package slashpath
import "core:strings"
+23
View File
@@ -386,6 +386,29 @@ Raw_Cstring :: struct {
}
/*
// Defined internally by the compiler
Odin_Build_Mode_Type :: enum int {
Executable,
Dynamic,
Object,
Assembly,
LLVM_IR,
}
*/
Odin_Build_Mode_Type :: type_of(ODIN_BUILD_MODE)
/*
// Defined internally by the compiler
Odin_Endian_Type :: enum int {
Unknown,
Little,
Big,
}
*/
Odin_Endian_Type :: type_of(ODIN_ENDIAN)
/////////////////////////////
// Init Startup Procedures //
/////////////////////////////
+4
View File
@@ -614,6 +614,10 @@ raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_str
@(disabled=ODIN_DISABLE_ASSERT)
assert :: proc(condition: bool, message := "", loc := #caller_location) {
if !condition {
// NOTE(bill): This is wrapped in a procedure call
// to improve performance to make the CPU not
// execute speculatively, making it about an order of
// magnitude faster
proc(message: string, loc: Source_Code_Location) {
p := context.assertion_failure_proc
if p == nil {
+12 -12
View File
@@ -146,14 +146,14 @@ matrix2x2_inverse_transpose :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y:
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
when intrinsics.type_is_integer(T) {
y[0, 0] = +x[1, 1] / d
y[1, 0] = -x[1, 0] / d
y[0, 1] = -x[0, 1] / d
y[1, 0] = -x[0, 1] / d
y[0, 1] = -x[1, 0] / d
y[1, 1] = +x[0, 0] / d
} else {
id := 1 / d
y[0, 0] = +x[1, 1] * id
y[1, 0] = -x[1, 0] * id
y[0, 1] = -x[0, 1] * id
y[1, 0] = -x[0, 1] * id
y[0, 1] = -x[1, 0] * id
y[1, 1] = +x[0, 0] * id
}
return
@@ -214,16 +214,16 @@ matrix1x1_inverse :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
matrix2x2_inverse :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
when intrinsics.type_is_integer(T) {
y[0, 0] = x[1, 1] / d
y[0, 1] = x[1, 0] / d
y[1, 0] = x[0, 1] / d
y[1, 1] = x[0, 0] / d
y[0, 0] = +x[1, 1] / d
y[0, 1] = -x[0, 1] / d
y[1, 0] = -x[1, 0] / d
y[1, 1] = +x[0, 0] / d
} else {
id := 1 / d
y[0, 0] = x[1, 1] * id
y[0, 1] = x[1, 0] * id
y[1, 0] = x[0, 1] * id
y[1, 1] = x[0, 0] * id
y[0, 0] = +x[1, 1] * id
y[0, 1] = -x[0, 1] * id
y[1, 0] = -x[1, 0] * id
y[1, 1] = +x[0, 0] * id
}
return
}
+33
View File
@@ -0,0 +1,33 @@
//+private
//+build linux, darwin, freebsd
package runtime
import "core:intrinsics"
when ODIN_BUILD_MODE == .Dynamic {
@(link_name="_odin_entry_point", linkage="strong", require/*, link_section=".init"*/)
_odin_entry_point :: proc "c" () {
context = default_context()
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
}
@(link_name="_odin_exit_point", linkage="strong", require/*, link_section=".fini"*/)
_odin_exit_point :: proc "c" () {
context = default_context()
#force_no_inline _cleanup_runtime()
}
@(link_name="main", linkage="strong", require)
main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
return 0
}
} else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
@(link_name="main", linkage="strong", require)
main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
args__ = argv[:argc]
context = default_context()
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
#force_no_inline _cleanup_runtime()
return 0
}
}
+19
View File
@@ -0,0 +1,19 @@
//+private
//+build wasm32, wasm64
package runtime
import "core:intrinsics"
when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
@(link_name="_start", linkage="strong", require, export)
_start :: proc "c" () {
context = default_context()
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
}
@(link_name="_end", linkage="strong", require, export)
_end :: proc "c" () {
context = default_context()
#force_no_inline _cleanup_runtime()
}
}
+45
View File
@@ -0,0 +1,45 @@
//+private
//+build windows
package runtime
import "core:intrinsics"
when ODIN_BUILD_MODE == .Dynamic {
@(link_name="DllMain", linkage="strong", require)
DllMain :: proc "stdcall" (hinstDLL: rawptr, fdwReason: u32, lpReserved: rawptr) -> b32 {
context = default_context()
switch fdwReason {
case 1: // DLL_PROCESS_ATTACH
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
case 0: // DLL_PROCESS_DETACH
#force_no_inline _cleanup_runtime()
case 2: // DLL_THREAD_ATTACH
break
case 3: // DLL_THREAD_DETACH
break
}
return true
}
} else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
when ODIN_ARCH == "i386" || ODIN_NO_CRT {
@(link_name="mainCRTStartup", linkage="strong", require)
mainCRTStartup :: proc "stdcall" () -> i32 {
context = default_context()
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
#force_no_inline _cleanup_runtime()
return 0
}
} else {
@(link_name="main", linkage="strong", require)
main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
args__ = argv[:argc]
context = default_context()
#force_no_inline _startup_runtime()
intrinsics.__entry_point()
#force_no_inline _cleanup_runtime()
return 0
}
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ IS_WASM :: ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64"
@(private)
RUNTIME_LINKAGE :: "strong" when (
(ODIN_USE_SEPARATE_MODULES ||
ODIN_BUILD_MODE == "dynamic" ||
ODIN_BUILD_MODE == .Dynamic ||
!ODIN_NO_CRT) &&
!IS_WASM) else "internal"
RUNTIME_REQUIRE :: true
+15 -5
View File
@@ -143,11 +143,21 @@ print_int :: proc "contextless" (x: int) { print_i64(i64(x)) }
print_caller_location :: proc "contextless" (using loc: Source_Code_Location) {
print_string(file_path)
print_byte('(')
print_u64(u64(line))
print_byte(':')
print_u64(u64(column))
print_byte(')')
when ODIN_ERROR_POS_STYLE == .Default {
print_byte('(')
print_u64(u64(line))
print_byte(':')
print_u64(u64(column))
print_byte(')')
} else when ODIN_ERROR_POS_STYLE == .Unix {
print_byte(':')
print_u64(u64(line))
print_byte(':')
print_u64(u64(column))
print_byte(':')
} else {
#panic("unhandled ODIN_ERROR_POS_STYLE")
}
}
print_typeid :: proc "contextless" (id: typeid) {
if id == nil {
+1 -1
View File
@@ -22,4 +22,4 @@ windows_trap_type_assertion :: proc "contextless" () -> ! {
when ODIN_NO_CRT {
@(require)
foreign import crt_lib "procs_windows_amd64.asm"
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
q, r: [2]u64
sr: u32 = 0
low :: 1 when ODIN_ENDIAN == "big" else 0
low :: 1 when ODIN_ENDIAN == .Big else 0
high :: 1 - low
U64_BITS :: 8*size_of(u64)
U128_BITS :: 8*size_of(u128)
+17
View File
@@ -304,6 +304,23 @@ filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -
return r[:]
}
scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U)->V, allocator := context.allocator) -> []V {
if len(s) == 0 { return {} }
res := make([]V, len(s), allocator)
p := as_ptr(s)
q := as_ptr(res)
r := initializer
for l := len(s); l > 0; l -= 1 {
r = f(r, p[0])
q[0] = r
p = p[1:]
q = q[1:]
}
return res
}
min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
+31 -488
View File
@@ -1,10 +1,5 @@
package slice
import "core:intrinsics"
_ :: intrinsics
ORD :: intrinsics.type_is_ordered
Ordering :: enum {
Less = -1,
Equal = 0,
@@ -38,7 +33,7 @@ cmp_proc :: proc($E: typeid) -> (proc(E, E) -> Ordering) where ORD(E) {
sort :: proc(data: $T/[]$E) where ORD(E) {
when size_of(E) != 0 {
if n := len(data); n > 1 {
_quick_sort(data, 0, n, _max_depth(n))
_quick_sort_general(data, 0, n, _max_depth(n), struct{}{}, .Ordered)
}
}
}
@@ -48,7 +43,7 @@ sort :: proc(data: $T/[]$E) where ORD(E) {
sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
when size_of(E) != 0 {
if n := len(data); n > 1 {
_quick_sort_less(data, 0, n, _max_depth(n), less)
_quick_sort_general(data, 0, n, _max_depth(n), less, .Less)
}
}
}
@@ -56,7 +51,33 @@ sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
when size_of(E) != 0 {
if n := len(data); n > 1 {
_quick_sort_cmp(data, 0, n, _max_depth(n), cmp)
_quick_sort_general(data, 0, n, _max_depth(n), cmp, .Cmp)
}
}
}
// stable_sort sorts a slice
stable_sort :: proc(data: $T/[]$E) where ORD(E) {
when size_of(E) != 0 {
if n := len(data); n > 1 {
_stable_sort_general(data, struct{}{}, .Ordered)
}
}
}
// stable_sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
stable_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
when size_of(E) != 0 {
if n := len(data); n > 1 {
_stable_sort_general(data, less, .Less)
}
}
}
stable_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
when size_of(E) != 0 {
if n := len(data); n > 1 {
_stable_sort_general(data, cmp, .Cmp)
}
}
}
@@ -79,6 +100,7 @@ is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool {
return true
}
is_sorted_by_cmp :: is_sorted_cmp
is_sorted_cmp :: proc(array: $T/[]$E, cmp: proc(i, j: E) -> Ordering) -> bool {
for i := len(array)-1; i > 0; i -= 1 {
if cmp(array[i], array[i-1]) == .Equal {
@@ -140,489 +162,10 @@ is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K
return true
}
@(private)
_max_depth :: proc(n: int) -> int { // 2*ceil(log2(n+1))
depth: int
_max_depth :: proc(n: int) -> (depth: int) { // 2*ceil(log2(n+1))
for i := n; i > 0; i >>= 1 {
depth += 1
}
return depth * 2
}
@(private)
_quick_sort :: proc(data: $T/[]$E, a, b, max_depth: int) where ORD(E) #no_bounds_check {
median3 :: proc(data: T, m1, m0, m2: int) #no_bounds_check {
if data[m1] < data[m0] {
swap(data, m1, m0)
}
if data[m2] < data[m1] {
swap(data, m2, m1)
if data[m1] < data[m0] {
swap(data, m1, m0)
}
}
}
do_pivot :: proc(data: T, lo, hi: int) -> (midlo, midhi: int) #no_bounds_check {
m := int(uint(lo+hi)>>1)
if hi-lo > 40 {
s := (hi-lo)/8
median3(data, lo, lo+s, lo+s*2)
median3(data, m, m-s, m+s)
median3(data, hi-1, hi-1-s, hi-1-s*2)
}
median3(data, lo, m, hi-1)
pivot := lo
a, c := lo+1, hi-1
for ; a < c && data[a] < data[pivot]; a += 1 {
}
b := a
for {
for ; b < c && !(data[pivot] < data[b]); b += 1 { // data[b] <= pivot
}
for ; b < c && data[pivot] < data[c-1]; c -=1 { // data[c-1] > pivot
}
if b >= c {
break
}
swap(data, b, c-1)
b += 1
c -= 1
}
protect := hi-c < 5
if !protect && hi-c < (hi-lo)/4 {
dups := 0
if !(data[pivot] < data[hi-1]) {
swap(data, c, hi-1)
c += 1
dups += 1
}
if !(data[b-1] < data[pivot]) {
b -= 1
dups += 1
}
if !(data[m] < data[pivot]) {
swap(data, m, b-1)
b -= 1
dups += 1
}
protect = dups > 1
}
if protect {
for {
for ; a < b && !(data[b-1] < data[pivot]); b -= 1 {
}
for ; a < b && data[a] < data[pivot]; a += 1 {
}
if a >= b {
break
}
swap(data, a, b-1)
a += 1
b -= 1
}
}
swap(data, pivot, b-1)
return b-1, c
}
a, b, max_depth := a, b, max_depth
if b-a > 12 { // only use shell sort for lengths <= 12
if max_depth == 0 {
_heap_sort(data, a, b)
return
}
max_depth -= 1
mlo, mhi := do_pivot(data, a, b)
if mlo-a < b-mhi {
_quick_sort(data, a, mlo, max_depth)
a = mhi
} else {
_quick_sort(data, mhi, b, max_depth)
b = mlo
}
}
if b-a > 1 {
// Shell short with gap 6
for i in a+6..<b {
if data[i] < data[i-6] {
swap(data, i, i-6)
}
}
_insertion_sort(data, a, b)
}
}
@(private)
_insertion_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) #no_bounds_check {
for i in a+1..<b {
for j := i; j > a && data[j] < data[j-1]; j -= 1 {
swap(data, j, j-1)
}
}
}
@(private)
_heap_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) #no_bounds_check {
sift_down :: proc(data: T, lo, hi, first: int) #no_bounds_check {
root := lo
for {
child := 2*root + 1
if child >= hi {
break
}
if child+1 < hi && data[first+child] < data[first+child+1] {
child += 1
}
if !(data[first+root] < data[first+child]) {
return
}
swap(data, first+root, first+child)
root = child
}
}
first, lo, hi := a, 0, b-a
for i := (hi-1)/2; i >= 0; i -= 1 {
sift_down(data, i, hi, first)
}
for i := hi-1; i >= 0; i -= 1 {
swap(data, first, first+i)
sift_down(data, lo, i, first)
}
}
@(private)
_quick_sort_less :: proc(data: $T/[]$E, a, b, max_depth: int, less: proc(i, j: E) -> bool) #no_bounds_check {
median3 :: proc(data: T, m1, m0, m2: int, less: proc(i, j: E) -> bool) #no_bounds_check {
if less(data[m1], data[m0]) {
swap(data, m1, m0)
}
if less(data[m2], data[m1]) {
swap(data, m2, m1)
if less(data[m1], data[m0]) {
swap(data, m1, m0)
}
}
}
do_pivot :: proc(data: T, lo, hi: int, less: proc(i, j: E) -> bool) -> (midlo, midhi: int) #no_bounds_check {
m := int(uint(lo+hi)>>1)
if hi-lo > 40 {
s := (hi-lo)/8
median3(data, lo, lo+s, lo+s*2, less)
median3(data, m, m-s, m+s, less)
median3(data, hi-1, hi-1-s, hi-1-s*2, less)
}
median3(data, lo, m, hi-1, less)
pivot := lo
a, c := lo+1, hi-1
for ; a < c && less(data[a], data[pivot]); a += 1 {
}
b := a
for {
for ; b < c && !less(data[pivot], data[b]); b += 1 { // data[b] <= pivot
}
for ; b < c && less(data[pivot], data[c-1]); c -=1 { // data[c-1] > pivot
}
if b >= c {
break
}
swap(data, b, c-1)
b += 1
c -= 1
}
protect := hi-c < 5
if !protect && hi-c < (hi-lo)/4 {
dups := 0
if !less(data[pivot], data[hi-1]) {
swap(data, c, hi-1)
c += 1
dups += 1
}
if !less(data[b-1], data[pivot]) {
b -= 1
dups += 1
}
if !less(data[m], data[pivot]) {
swap(data, m, b-1)
b -= 1
dups += 1
}
protect = dups > 1
}
if protect {
for {
for ; a < b && !less(data[b-1], data[pivot]); b -= 1 {
}
for ; a < b && less(data[a], data[pivot]); a += 1 {
}
if a >= b {
break
}
swap(data, a, b-1)
a += 1
b -= 1
}
}
swap(data, pivot, b-1)
return b-1, c
}
a, b, max_depth := a, b, max_depth
if b-a > 12 { // only use shell sort for lengths <= 12
if max_depth == 0 {
_heap_sort_less(data, a, b, less)
return
}
max_depth -= 1
mlo, mhi := do_pivot(data, a, b, less)
if mlo-a < b-mhi {
_quick_sort_less(data, a, mlo, max_depth, less)
a = mhi
} else {
_quick_sort_less(data, mhi, b, max_depth, less)
b = mlo
}
}
if b-a > 1 {
// Shell short with gap 6
for i in a+6..<b {
if less(data[i], data[i-6]) {
swap(data, i, i-6)
}
}
_insertion_sort_less(data, a, b, less)
}
}
@(private)
_insertion_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) #no_bounds_check {
for i in a+1..<b {
for j := i; j > a && less(data[j], data[j-1]); j -= 1 {
swap(data, j, j-1)
}
}
}
@(private)
_heap_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) #no_bounds_check {
sift_down :: proc(data: T, lo, hi, first: int, less: proc(i, j: E) -> bool) #no_bounds_check {
root := lo
for {
child := 2*root + 1
if child >= hi {
break
}
if child+1 < hi && less(data[first+child], data[first+child+1]) {
child += 1
}
if !less(data[first+root], data[first+child]) {
return
}
swap(data, first+root, first+child)
root = child
}
}
first, lo, hi := a, 0, b-a
for i := (hi-1)/2; i >= 0; i -= 1 {
sift_down(data, i, hi, first, less)
}
for i := hi-1; i >= 0; i -= 1 {
swap(data, first, first+i)
sift_down(data, lo, i, first, less)
}
}
@(private)
_quick_sort_cmp :: proc(data: $T/[]$E, a, b, max_depth: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
median3 :: proc(data: T, m1, m0, m2: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
if cmp(data[m1], data[m0]) == .Less {
swap(data, m1, m0)
}
if cmp(data[m2], data[m1]) == .Less {
swap(data, m2, m1)
if cmp(data[m1], data[m0]) == .Less {
swap(data, m1, m0)
}
}
}
do_pivot :: proc(data: T, lo, hi: int, cmp: proc(i, j: E) -> Ordering) -> (midlo, midhi: int) #no_bounds_check {
m := int(uint(lo+hi)>>1)
if hi-lo > 40 {
s := (hi-lo)/8
median3(data, lo, lo+s, lo+s*2, cmp)
median3(data, m, m-s, m+s, cmp)
median3(data, hi-1, hi-1-s, hi-1-s*2, cmp)
}
median3(data, lo, m, hi-1, cmp)
pivot := lo
a, c := lo+1, hi-1
for ; a < c && cmp(data[a], data[pivot]) == .Less; a += 1 {
}
b := a
for {
for ; b < c && cmp(data[pivot], data[b]) >= .Equal; b += 1 { // data[b] <= pivot
}
for ; b < c && cmp(data[pivot], data[c-1]) == .Less; c -=1 { // data[c-1] > pivot
}
if b >= c {
break
}
swap(data, b, c-1)
b += 1
c -= 1
}
protect := hi-c < 5
if !protect && hi-c < (hi-lo)/4 {
dups := 0
if cmp(data[pivot], data[hi-1]) != .Less {
swap(data, c, hi-1)
c += 1
dups += 1
}
if cmp(data[b-1], data[pivot]) != .Less {
b -= 1
dups += 1
}
if cmp(data[m], data[pivot]) != .Less {
swap(data, m, b-1)
b -= 1
dups += 1
}
protect = dups > 1
}
if protect {
for {
for ; a < b && cmp(data[b-1], data[pivot]) >= .Equal; b -= 1 {
}
for ; a < b && cmp(data[a], data[pivot]) == .Less; a += 1 {
}
if a >= b {
break
}
swap(data, a, b-1)
a += 1
b -= 1
}
}
swap(data, pivot, b-1)
return b-1, c
}
a, b, max_depth := a, b, max_depth
if b-a > 12 { // only use shell sort for lengths <= 12
if max_depth == 0 {
_heap_sort_cmp(data, a, b, cmp)
return
}
max_depth -= 1
mlo, mhi := do_pivot(data, a, b, cmp)
if mlo-a < b-mhi {
_quick_sort_cmp(data, a, mlo, max_depth, cmp)
a = mhi
} else {
_quick_sort_cmp(data, mhi, b, max_depth, cmp)
b = mlo
}
}
if b-a > 1 {
// Shell short with gap 6
for i in a+6..<b {
if cmp(data[i], data[i-6]) == .Less {
swap(data, i, i-6)
}
}
_insertion_sort_cmp(data, a, b, cmp)
}
}
@(private)
_insertion_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
for i in a+1..<b {
for j := i; j > a && cmp(data[j], data[j-1]) == .Less; j -= 1 {
swap(data, j, j-1)
}
}
}
@(private)
_heap_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
sift_down :: proc(data: T, lo, hi, first: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
root := lo
for {
child := 2*root + 1
if child >= hi {
break
}
if child+1 < hi && cmp(data[first+child], data[first+child+1]) == .Less {
child += 1
}
if cmp(data[first+root], data[first+child]) >= .Equal {
return
}
swap(data, first+root, first+child)
root = child
}
}
first, lo, hi := a, 0, b-a
for i := (hi-1)/2; i >= 0; i -= 1 {
sift_down(data, i, hi, first, cmp)
}
for i := hi-1; i >= 0; i -= 1 {
swap(data, first, first+i)
sift_down(data, lo, i, first, cmp)
}
}
+200
View File
@@ -0,0 +1,200 @@
//+private
package slice
import "core:intrinsics"
_ :: intrinsics
ORD :: intrinsics.type_is_ordered
Sort_Kind :: enum {
Ordered,
Less,
Cmp,
}
_quick_sort_general :: proc(data: $T/[]$E, a, b, max_depth: int, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check {
less :: #force_inline proc(a, b: E, call: P) -> bool {
when KIND == .Ordered {
return a < b
} else when KIND == .Less {
return call(a, b)
} else when KIND == .Cmp {
return call(a, b) == .Less
} else {
#panic("unhandled Sort_Kind")
}
}
insertion_sort :: proc(data: $T/[]$E, a, b: int, call: P) #no_bounds_check {
for i in a+1..<b {
for j := i; j > a && less(data[j], data[j-1], call); j -= 1 {
swap(data, j, j-1)
}
}
}
heap_sort :: proc(data: $T/[]$E, a, b: int, call: P) #no_bounds_check {
sift_down :: proc(data: T, lo, hi, first: int, call: P) #no_bounds_check {
root := lo
for {
child := 2*root + 1
if child >= hi {
break
}
if child+1 < hi && less(data[first+child], data[first+child+1], call) {
child += 1
}
if !less(data[first+root], data[first+child], call) {
return
}
swap(data, first+root, first+child)
root = child
}
}
first, lo, hi := a, 0, b-a
for i := (hi-1)/2; i >= 0; i -= 1 {
sift_down(data, i, hi, first, call)
}
for i := hi-1; i >= 0; i -= 1 {
swap(data, first, first+i)
sift_down(data, lo, i, first, call)
}
}
median3 :: proc(data: T, m1, m0, m2: int, call: P) #no_bounds_check {
if less(data[m1], data[m0], call) {
swap(data, m1, m0)
}
if less(data[m2], data[m1], call) {
swap(data, m2, m1)
if less(data[m1], data[m0], call) {
swap(data, m1, m0)
}
}
}
do_pivot :: proc(data: T, lo, hi: int, call: P) -> (midlo, midhi: int) #no_bounds_check {
m := int(uint(lo+hi)>>1)
if hi-lo > 40 {
s := (hi-lo)/8
median3(data, lo, lo+s, lo+s*2, call)
median3(data, m, m-s, m+s, call)
median3(data, hi-1, hi-1-s, hi-1-s*2, call)
}
median3(data, lo, m, hi-1, call)
pivot := lo
a, c := lo+1, hi-1
for ; a < c && less(data[a], data[pivot], call); a += 1 {
}
b := a
for {
for ; b < c && !less(data[pivot], data[b], call); b += 1 { // data[b] <= pivot
}
for ; b < c && less(data[pivot], data[c-1], call); c -=1 { // data[c-1] > pivot
}
if b >= c {
break
}
swap(data, b, c-1)
b += 1
c -= 1
}
protect := hi-c < 5
if !protect && hi-c < (hi-lo)/4 {
dups := 0
if !less(data[pivot], data[hi-1], call) {
swap(data, c, hi-1)
c += 1
dups += 1
}
if !less(data[b-1], data[pivot], call) {
b -= 1
dups += 1
}
if !less(data[m], data[pivot], call) {
swap(data, m, b-1)
b -= 1
dups += 1
}
protect = dups > 1
}
if protect {
for {
for ; a < b && !less(data[b-1], data[pivot], call); b -= 1 {
}
for ; a < b && less(data[a], data[pivot], call); a += 1 {
}
if a >= b {
break
}
swap(data, a, b-1)
a += 1
b -= 1
}
}
swap(data, pivot, b-1)
return b-1, c
}
a, b, max_depth := a, b, max_depth
if b-a > 12 { // only use shell sort for lengths <= 12
if max_depth == 0 {
heap_sort(data, a, b, call)
return
}
max_depth -= 1
mlo, mhi := do_pivot(data, a, b, call)
if mlo-a < b-mhi {
_quick_sort_general(data, a, mlo, max_depth, call, KIND)
a = mhi
} else {
_quick_sort_general(data, mhi, b, max_depth, call, KIND)
b = mlo
}
}
if b-a > 1 {
// Shell short with gap 6
for i in a+6..<b {
if less(data[i], data[i-6], call) {
swap(data, i, i-6)
}
}
insertion_sort(data, a, b, call)
}
}
// merge sort
_stable_sort_general :: proc(data: $T/[]$E, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check {
less :: #force_inline proc(a, b: E, call: P) -> bool {
when KIND == .Ordered {
return a < b
} else when KIND == .Less {
return call(a, b)
} else when KIND == .Cmp {
return call(a, b) == .Less
} else {
#panic("unhandled Sort_Kind")
}
}
n := len(data)
for i in 1..<n {
for j := i; j > 0 && less(data[j], data[j-1], call); j -= 1 {
swap(data, j, j-1)
}
}
}
+3
View File
@@ -4,6 +4,9 @@ import "core:intrinsics"
import "core:runtime"
import "core:slice"
_ :: runtime
_ :: slice
map_entries_by_key :: proc(m: ^$M/map[$K]$V, loc := #caller_location) where intrinsics.type_is_ordered(K) {
Entry :: struct {
hash: uintptr,
+70
View File
@@ -353,6 +353,76 @@ split_after_n_iterator :: proc(s: ^string, sep: string, n: int) -> (string, bool
}
@(private)
_trim_cr :: proc(s: string) -> string {
n := len(s)
if n > 0 {
if s[n-1] == '\r' {
return s[:n-1]
}
}
return s
}
split_lines :: proc(s: string, allocator := context.allocator) -> []string {
sep :: "\n"
lines := _split(s, sep, 0, -1, allocator)
for line in &lines {
line = _trim_cr(line)
}
return lines
}
split_lines_n :: proc(s: string, n: int, allocator := context.allocator) -> []string {
sep :: "\n"
lines := _split(s, sep, 0, n, allocator)
for line in &lines {
line = _trim_cr(line)
}
return lines
}
split_lines_after :: proc(s: string, allocator := context.allocator) -> []string {
sep :: "\n"
lines := _split(s, sep, len(sep), -1, allocator)
for line in &lines {
line = _trim_cr(line)
}
return lines
}
split_lines_after_n :: proc(s: string, n: int, allocator := context.allocator) -> []string {
sep :: "\n"
lines := _split(s, sep, len(sep), n, allocator)
for line in &lines {
line = _trim_cr(line)
}
return lines
}
split_lines_iterator :: proc(s: ^string) -> (line: string, ok: bool) {
sep :: "\n"
line = _split_iterator(s, sep, 0, -1) or_return
return _trim_cr(line), true
}
split_lines_n_iterator :: proc(s: ^string, n: int) -> (line: string, ok: bool) {
sep :: "\n"
line = _split_iterator(s, sep, 0, n) or_return
return _trim_cr(line), true
}
split_lines_after_iterator :: proc(s: ^string) -> (line: string, ok: bool) {
sep :: "\n"
line = _split_iterator(s, sep, len(sep), -1) or_return
return _trim_cr(line), true
}
split_lines_after_n_iterator :: proc(s: ^string, n: int) -> (line: string, ok: bool) {
sep :: "\n"
line = _split_iterator(s, sep, len(sep), n) or_return
return _trim_cr(line), true
}
+36 -37
View File
@@ -1,44 +1,43 @@
package sync
// A barrier enabling multiple threads to synchronize the beginning of some computation
/*
* Example:
*
* package example
*
* import "core:fmt"
* import "core:sync"
* import "core:thread"
*
* barrier := &sync.Barrier{};
*
* main :: proc() {
* fmt.println("Start");
*
* THREAD_COUNT :: 4;
* threads: [THREAD_COUNT]^thread.Thread;
*
* sync.barrier_init(barrier, THREAD_COUNT);
* defer sync.barrier_destroy(barrier);
*
*
* for _, i in threads {
* threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
* // Same messages will be printed together but without any interleaving
* fmt.println("Getting ready!");
* sync.barrier_wait(barrier);
* fmt.println("Off their marks they go!");
* });
* }
*
* for t in threads {
* thread.destroy(t); // join and free thread
* }
* fmt.println("Finished");
* }
*
*/
A barrier enabling multiple threads to synchronize the beginning of some computation
Example:
package example
import "core:fmt"
import "core:sync"
import "core:thread"
barrier := &sync.Barrier{};
main :: proc() {
fmt.println("Start");
THREAD_COUNT :: 4;
threads: [THREAD_COUNT]^thread.Thread;
sync.barrier_init(barrier, THREAD_COUNT);
defer sync.barrier_destroy(barrier);
for _, i in threads {
threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
// Same messages will be printed together but without any interleaving
fmt.println("Getting ready!");
sync.barrier_wait(barrier);
fmt.println("Off their marks they go!");
});
}
for t in threads {
thread.destroy(t); // join and free thread
}
fmt.println("Finished");
}
*/
Barrier :: struct {
mutex: Blocking_Mutex,
cond: Condition,
+34 -37
View File
@@ -67,44 +67,41 @@ wait_group_wait_with_timeout :: proc(wg: ^Wait_Group, duration: time.Duration) -
// A barrier enabling multiple threads to synchronize the beginning of some computation
/*
* Example:
*
* package example
*
* import "core:fmt"
* import "core:sync"
* import "core:thread"
*
* barrier := &sync.Barrier{}
*
* main :: proc() {
* fmt.println("Start")
*
* THREAD_COUNT :: 4
* threads: [THREAD_COUNT]^thread.Thread
*
* sync.barrier_init(barrier, THREAD_COUNT)
* defer sync.barrier_destroy(barrier)
*
*
* for _, i in threads {
* threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
* // Same messages will be printed together but without any interleaving
* fmt.println("Getting ready!")
* sync.barrier_wait(barrier)
* fmt.println("Off their marks they go!")
* })
* }
*
* for t in threads {
* thread.destroy(t) // join and free thread
* }
* fmt.println("Finished")
* }
*
*/
A barrier enabling multiple threads to synchronize the beginning of some computation
Example:
package example
import "core:fmt"
import "core:sync"
import "core:thread"
barrier := &sync.Barrier{}
main :: proc() {
fmt.println("Start")
THREAD_COUNT :: 4
threads: [THREAD_COUNT]^thread.Thread
sync.barrier_init(barrier, THREAD_COUNT)
for _, i in threads {
threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
// Same messages will be printed together but without any interleaving
fmt.println("Getting ready!")
sync.barrier_wait(barrier)
fmt.println("Off their marks they go!")
})
}
for t in threads {
thread.destroy(t) // join and free thread
}
fmt.println("Finished")
}
*/
Barrier :: struct {
mutex: Mutex,
cond: Cond,
+24 -26
View File
@@ -29,12 +29,12 @@ mutex_try_lock :: proc(m: ^Mutex) -> bool {
return _mutex_try_lock(m)
}
// Example:
//
// if mutex_guard(&m) {
// ...
// }
//
/*
Example:
if mutex_guard(&m) {
...
}
*/
@(deferred_in=mutex_unlock)
mutex_guard :: proc(m: ^Mutex) -> bool {
mutex_lock(m)
@@ -80,25 +80,24 @@ rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) {
rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
return _rw_mutex_try_shared_lock(rw)
}
// Example:
//
// if rw_mutex_guard(&m) {
// ...
// }
//
/*
Example:
if rw_mutex_guard(&m) {
...
}
*/
@(deferred_in=rw_mutex_unlock)
rw_mutex_guard :: proc(m: ^RW_Mutex) -> bool {
rw_mutex_lock(m)
return true
}
// Example:
//
// if rw_mutex_shared_guard(&m) {
// ...
// }
//
/*
Example:
if rw_mutex_shared_guard(&m) {
...
}
*/
@(deferred_in=rw_mutex_shared_unlock)
rw_mutex_shared_guard :: proc(m: ^RW_Mutex) -> bool {
rw_mutex_shared_lock(m)
@@ -127,13 +126,12 @@ recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
return _recursive_mutex_try_lock(m)
}
// Example:
//
// if recursive_mutex_guard(&m) {
// ...
// }
//
/*
Example:
if recursive_mutex_guard(&m) {
...
}
*/
@(deferred_in=recursive_mutex_unlock)
recursive_mutex_guard :: proc(m: ^Recursive_Mutex) -> bool {
recursive_mutex_lock(m)
+24 -27
View File
@@ -82,13 +82,12 @@ atomic_mutex_try_lock :: proc(m: ^Atomic_Mutex) -> bool {
return ok
}
// Example:
//
// if atomic_mutex_guard(&m) {
// ...
// }
//
/*
Example:
if atomic_mutex_guard(&m) {
...
}
*/
@(deferred_in=atomic_mutex_unlock)
atomic_mutex_guard :: proc(m: ^Atomic_Mutex) -> bool {
atomic_mutex_lock(m)
@@ -193,25 +192,24 @@ atomic_rw_mutex_try_shared_lock :: proc(rw: ^Atomic_RW_Mutex) -> bool {
return false
}
// Example:
//
// if atomic_rw_mutex_guard(&m) {
// ...
// }
//
/*
Example:
if atomic_rw_mutex_guard(&m) {
...
}
*/
@(deferred_in=atomic_rw_mutex_unlock)
atomic_rw_mutex_guard :: proc(m: ^Atomic_RW_Mutex) -> bool {
atomic_rw_mutex_lock(m)
return true
}
// Example:
//
// if atomic_rw_mutex_shared_guard(&m) {
// ...
// }
//
/*
Example:
if atomic_rw_mutex_shared_guard(&m) {
...
}
*/
@(deferred_in=atomic_rw_mutex_shared_unlock)
atomic_rw_mutex_shared_guard :: proc(m: ^Atomic_RW_Mutex) -> bool {
atomic_rw_mutex_shared_lock(m)
@@ -270,13 +268,12 @@ atomic_recursive_mutex_try_lock :: proc(m: ^Atomic_Recursive_Mutex) -> bool {
return true
}
// Example:
//
// if atomic_recursive_mutex_guard(&m) {
// ...
// }
//
/*
Example:
if atomic_recursive_mutex_guard(&m) {
...
}
*/
@(deferred_in=atomic_recursive_mutex_unlock)
atomic_recursive_mutex_guard :: proc(m: ^Atomic_Recursive_Mutex) -> bool {
atomic_recursive_mutex_lock(m)

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