Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
5bca42b049 | |||
e1ba7dd7a9 | |||
837f696971 | |||
afbfd0e781 | |||
0776012d09 | |||
4f8cbd442a | |||
2d309a2cff | |||
f19d93a69a | |||
e034efe8bd | |||
2c457c4275 |
3
.bazelrc
3
.bazelrc
@ -5,8 +5,7 @@ build --enable_platform_specific_config
|
|||||||
build --build_python_zip=false
|
build --build_python_zip=false
|
||||||
|
|
||||||
build:windows --extra_execution_platforms=//:x64_windows-clang-cl
|
build:windows --extra_execution_platforms=//:x64_windows-clang-cl
|
||||||
# @Todo(bazel) We should be able to use @local_config_cc...
|
build:windows --extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows-clang-cl
|
||||||
build:windows --extra_toolchains=@@rules_cc++cc_configure_extension+local_config_cc//:cc-toolchain-x64_windows-clang-cl
|
|
||||||
|
|
||||||
build:linux --repo_env=CC=clang
|
build:linux --repo_env=CC=clang
|
||||||
|
|
||||||
|
11
MODULE.bazel
11
MODULE.bazel
@ -2,12 +2,15 @@
|
|||||||
#
|
#
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
module(name = "asl")
|
module(name = "asl", version = "0.4.0")
|
||||||
|
|
||||||
bazel_dep(name = "platforms", version = "0.0.10")
|
bazel_dep(name = "platforms", version = "0.0.11")
|
||||||
bazel_dep(name = "rules_cc", version = "0.0.17")
|
|
||||||
bazel_dep(name = "rules_license", version = "1.0.0")
|
bazel_dep(name = "rules_license", version = "1.0.0")
|
||||||
|
|
||||||
|
bazel_dep(name = "rules_cc", version = "0.1.1")
|
||||||
|
cc_configure = use_extension("@rules_cc//cc:extensions.bzl", "cc_configure_extension")
|
||||||
|
use_repo(cc_configure, "local_config_cc")
|
||||||
|
|
||||||
bazel_dep(name = "hedron_compile_commands", dev_dependency = True)
|
bazel_dep(name = "hedron_compile_commands", dev_dependency = True)
|
||||||
git_override(
|
git_override(
|
||||||
module_name = "hedron_compile_commands",
|
module_name = "hedron_compile_commands",
|
||||||
@ -15,6 +18,6 @@ git_override(
|
|||||||
commit = "4f28899228fb3ad0126897876f147ca15026151e",
|
commit = "4f28899228fb3ad0126897876f147ca15026151e",
|
||||||
)
|
)
|
||||||
|
|
||||||
bazel_dep(name = "rules_python", version = "1.1.0")
|
bazel_dep(name = "rules_python", version = "1.3.0")
|
||||||
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
|
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
|
||||||
python.toolchain(python_version = "3.13", is_default = True)
|
python.toolchain(python_version = "3.13", is_default = True)
|
||||||
|
88
MODULE.bazel.lock
generated
88
MODULE.bazel.lock
generated
@ -43,7 +43,8 @@
|
|||||||
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
|
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
|
||||||
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
|
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
|
||||||
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
|
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
|
||||||
"https://bcr.bazel.build/modules/platforms/0.0.10/source.json": "f22828ff4cf021a6b577f1bf6341cb9dcd7965092a439f64fc1bb3b7a5ae4bd5",
|
"https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
|
||||||
|
"https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29",
|
||||||
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
|
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
|
||||||
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
|
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
|
||||||
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
|
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
|
||||||
@ -70,11 +71,12 @@
|
|||||||
"https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
|
"https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
|
||||||
"https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
|
"https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
|
||||||
"https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
|
"https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
|
||||||
"https://bcr.bazel.build/modules/rules_cc/0.0.17/source.json": "4db99b3f55c90ab28d14552aa0632533e3e8e5e9aea0f5c24ac0014282c2a7c5",
|
|
||||||
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
|
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
|
||||||
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
|
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
|
||||||
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
|
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
|
||||||
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
|
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
|
||||||
|
"https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
|
||||||
|
"https://bcr.bazel.build/modules/rules_cc/0.1.1/source.json": "d61627377bd7dd1da4652063e368d9366fc9a73920bfa396798ad92172cf645c",
|
||||||
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
|
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
|
||||||
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
|
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
|
||||||
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
|
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
|
||||||
@ -88,10 +90,10 @@
|
|||||||
"https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
|
"https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
|
||||||
"https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
|
"https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
|
||||||
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
|
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
|
||||||
|
"https://bcr.bazel.build/modules/rules_java/8.11.0/MODULE.bazel": "c3d280bc5ff1038dcb3bacb95d3f6b83da8dd27bba57820ec89ea4085da767ad",
|
||||||
|
"https://bcr.bazel.build/modules/rules_java/8.11.0/source.json": "302b52a39259a85aa06ca3addb9787864ca3e03b432a5f964ea68244397e7544",
|
||||||
"https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
|
"https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
|
||||||
"https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
|
"https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
|
||||||
"https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
|
|
||||||
"https://bcr.bazel.build/modules/rules_java/8.6.1/source.json": "f18d9ad3c4c54945bf422ad584fa6c5ca5b3116ff55a5b1bc77e5c1210be5960",
|
|
||||||
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
|
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
|
||||||
"https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
|
"https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
|
||||||
"https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
|
"https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
|
||||||
@ -121,8 +123,8 @@
|
|||||||
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
|
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
|
||||||
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
|
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
|
||||||
"https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
|
"https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
|
||||||
"https://bcr.bazel.build/modules/rules_python/1.1.0/MODULE.bazel": "57e01abae22956eb96d891572490d20e07d983e0c065de0b2170cafe5053e788",
|
"https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
|
||||||
"https://bcr.bazel.build/modules/rules_python/1.1.0/source.json": "29f1fdfd23a40808c622f813bc93e29c3aae277333f03293f667e76159750a0f",
|
"https://bcr.bazel.build/modules/rules_python/1.3.0/source.json": "25932f917cd279c7baefa6cb1d3fa8750a7a29de522024449b19af6eab51f4a0",
|
||||||
"https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
|
"https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
|
||||||
"https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95",
|
"https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95",
|
||||||
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
|
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
|
||||||
@ -140,44 +142,6 @@
|
|||||||
},
|
},
|
||||||
"selectedYankedVersions": {},
|
"selectedYankedVersions": {},
|
||||||
"moduleExtensions": {
|
"moduleExtensions": {
|
||||||
"@@platforms//host:extension.bzl%host_platform": {
|
|
||||||
"general": {
|
|
||||||
"bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=",
|
|
||||||
"usagesDigest": "SeQiIN/f8/Qt9vYQk7qcXp4I4wJeEC0RnQDiaaJ4tb8=",
|
|
||||||
"recordedFileInputs": {},
|
|
||||||
"recordedDirentsInputs": {},
|
|
||||||
"envVariables": {},
|
|
||||||
"generatedRepoSpecs": {
|
|
||||||
"host_platform": {
|
|
||||||
"repoRuleId": "@@platforms//host:extension.bzl%host_platform_repo",
|
|
||||||
"attributes": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"recordedRepoMappingEntries": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@@rules_java+//java:rules_java_deps.bzl%compatibility_proxy": {
|
|
||||||
"general": {
|
|
||||||
"bzlTransitiveDigest": "84xJEZ1jnXXwo8BXMprvBm++rRt4jsTu9liBxz0ivps=",
|
|
||||||
"usagesDigest": "jTQDdLDxsS43zuRmg1faAjIEPWdLAbDAowI1pInQSoo=",
|
|
||||||
"recordedFileInputs": {},
|
|
||||||
"recordedDirentsInputs": {},
|
|
||||||
"envVariables": {},
|
|
||||||
"generatedRepoSpecs": {
|
|
||||||
"compatibility_proxy": {
|
|
||||||
"repoRuleId": "@@rules_java+//java:rules_java_deps.bzl%_compatibility_proxy_repo_rule",
|
|
||||||
"attributes": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"recordedRepoMappingEntries": [
|
|
||||||
[
|
|
||||||
"rules_java+",
|
|
||||||
"bazel_tools",
|
|
||||||
"bazel_tools"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
|
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
|
||||||
"general": {
|
"general": {
|
||||||
"bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=",
|
"bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=",
|
||||||
@ -241,6 +205,42 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"@@rules_python+//python/uv:uv.bzl%uv": {
|
||||||
|
"general": {
|
||||||
|
"bzlTransitiveDigest": "Xpqjnjzy6zZ90Es9Wa888ZLHhn7IsNGbph/e6qoxzw8=",
|
||||||
|
"usagesDigest": "vJ5RHUxAnV24M5swNGiAnkdxMx3Hp/iOLmNANTC5Xc8=",
|
||||||
|
"recordedFileInputs": {},
|
||||||
|
"recordedDirentsInputs": {},
|
||||||
|
"envVariables": {},
|
||||||
|
"generatedRepoSpecs": {
|
||||||
|
"uv": {
|
||||||
|
"repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo",
|
||||||
|
"attributes": {
|
||||||
|
"toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'",
|
||||||
|
"toolchain_names": [
|
||||||
|
"none"
|
||||||
|
],
|
||||||
|
"toolchain_implementations": {
|
||||||
|
"none": "'@@rules_python+//python:none'"
|
||||||
|
},
|
||||||
|
"toolchain_compatible_with": {
|
||||||
|
"none": [
|
||||||
|
"@platforms//:incompatible"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"toolchain_target_settings": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recordedRepoMappingEntries": [
|
||||||
|
[
|
||||||
|
"rules_python+",
|
||||||
|
"platforms",
|
||||||
|
"platforms"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,14 @@ cc_library(
|
|||||||
hdrs = [
|
hdrs = [
|
||||||
"annotations.hpp",
|
"annotations.hpp",
|
||||||
"assert.hpp",
|
"assert.hpp",
|
||||||
|
"bit.hpp",
|
||||||
"config.hpp",
|
"config.hpp",
|
||||||
"defer.hpp",
|
"defer.hpp",
|
||||||
"float.hpp",
|
"float.hpp",
|
||||||
"functional.hpp",
|
"functional.hpp",
|
||||||
"integers.hpp",
|
"integers.hpp",
|
||||||
"meta.hpp",
|
"meta.hpp",
|
||||||
|
"numeric.hpp",
|
||||||
"utility.hpp",
|
"utility.hpp",
|
||||||
],
|
],
|
||||||
srcs = [
|
srcs = [
|
||||||
@ -37,10 +39,12 @@ cc_library(
|
|||||||
"//asl/types:box",
|
"//asl/types:box",
|
||||||
],
|
],
|
||||||
) for name in [
|
) for name in [
|
||||||
|
"bit",
|
||||||
"defer",
|
"defer",
|
||||||
"float",
|
"float",
|
||||||
"functional",
|
"functional",
|
||||||
"integers",
|
"integers",
|
||||||
"meta",
|
"meta",
|
||||||
|
"numeric",
|
||||||
"utility",
|
"utility",
|
||||||
]]
|
]]
|
||||||
|
166
asl/base/bit.hpp
Normal file
166
asl/base/bit.hpp
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
// Copyright 2025 Steven Le Rouzic
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "asl/base/integers.hpp"
|
||||||
|
#include "asl/base/meta.hpp"
|
||||||
|
|
||||||
|
namespace asl
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr bool has_single_bit(is_unsigned_integer auto x)
|
||||||
|
{
|
||||||
|
return x != 0 && ((x - 1) & x) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int popcount(uint8_t v)
|
||||||
|
{
|
||||||
|
v = v - ((v >> 1) & 0x55);
|
||||||
|
v = (v & 0x33) + ((v >> 2) & 0x33);
|
||||||
|
return (v + (v >> 4)) & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int popcount(uint16_t v)
|
||||||
|
{
|
||||||
|
v = v - ((v >> 1) & 0x5555);
|
||||||
|
v = (v & 0x3333) + ((v >> 2) & 0x3333);
|
||||||
|
return static_cast<uint16_t>((v + (v >> 4) & 0x0F0F) * uint16_t{0x0101}) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int popcount(uint32_t v)
|
||||||
|
{
|
||||||
|
v = v - ((v >> 1) & 0x5555'5555);
|
||||||
|
v = (v & 0x3333'3333) + ((v >> 2) & 0x3333'3333);
|
||||||
|
return static_cast<int>(((v + (v >> 4) & 0x0F0F'0F0F) * 0x0101'0101) >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int popcount(uint64_t v)
|
||||||
|
{
|
||||||
|
v = v - ((v >> 1) & 0x5555'5555'5555'5555);
|
||||||
|
v = (v & 0x3333'3333'3333'3333) + ((v >> 2) & 0x3333'3333'3333'3333);
|
||||||
|
return static_cast<int>(((v + (v >> 4) & 0x0F0F'0F0F'0F0F'0F0F) * 0x0101'0101'0101'0101) >> 56);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint8_t propagate_right_one(uint8_t v)
|
||||||
|
{
|
||||||
|
v = v | (v >> 1);
|
||||||
|
v = v | (v >> 2);
|
||||||
|
v = v | (v >> 4);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint16_t propagate_right_one(uint16_t v)
|
||||||
|
{
|
||||||
|
v = v | (v >> 1);
|
||||||
|
v = v | (v >> 2);
|
||||||
|
v = v | (v >> 4);
|
||||||
|
v = v | (v >> 8);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint32_t propagate_right_one(uint32_t v)
|
||||||
|
{
|
||||||
|
v = v | (v >> 1);
|
||||||
|
v = v | (v >> 2);
|
||||||
|
v = v | (v >> 4);
|
||||||
|
v = v | (v >> 8);
|
||||||
|
v = v | (v >> 16);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint64_t propagate_right_one(uint64_t v)
|
||||||
|
{
|
||||||
|
v = v | (v >> 1);
|
||||||
|
v = v | (v >> 2);
|
||||||
|
v = v | (v >> 4);
|
||||||
|
v = v | (v >> 8);
|
||||||
|
v = v | (v >> 16);
|
||||||
|
v = v | (v >> 32);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int countr_zero(is_unsigned_integer auto v)
|
||||||
|
{
|
||||||
|
v = ~v & (v - 1);
|
||||||
|
return popcount(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int countr_one(is_unsigned_integer auto v)
|
||||||
|
{
|
||||||
|
v = v & (~v - 1);
|
||||||
|
return popcount(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int countl_zero(is_unsigned_integer auto v)
|
||||||
|
{
|
||||||
|
v = ~propagate_right_one(v);
|
||||||
|
return popcount(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int countl_one(is_unsigned_integer auto v)
|
||||||
|
{
|
||||||
|
v = ~v;
|
||||||
|
v = ~propagate_right_one(v);
|
||||||
|
return popcount(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<is_unsigned_integer T>
|
||||||
|
constexpr T rotr(T v, int s);
|
||||||
|
|
||||||
|
template<is_unsigned_integer T>
|
||||||
|
constexpr T rotl(T v, int s) // NOLINT(*-no-recursion)
|
||||||
|
{
|
||||||
|
static constexpr int N = sizeof(decltype(v)) * 8;
|
||||||
|
s = s % N;
|
||||||
|
return (s >= 0) ? (v << s) | (v >> (N - s)) : rotr(v, -s);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<is_unsigned_integer T>
|
||||||
|
constexpr T rotr(T v, int s) // NOLINT(*-no-recursion)
|
||||||
|
{
|
||||||
|
static constexpr int N = sizeof(decltype(v)) * 8;
|
||||||
|
s = s % N;
|
||||||
|
return (s >= 0) ? (v >> s) | (v << (N - s)) : rotl(v, -s);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint16_t byteswap(uint16_t v)
|
||||||
|
{
|
||||||
|
return static_cast<uint16_t>((v << 8U) | (v >> 8U));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint32_t byteswap(uint32_t v)
|
||||||
|
{
|
||||||
|
return rotr(v & 0x00ff'00ff, 8) | rotl(v & 0xff00'ff00, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint64_t byteswap(uint64_t v)
|
||||||
|
{
|
||||||
|
return (uint64_t{byteswap(static_cast<uint32_t>(v))} << 32)
|
||||||
|
| uint64_t{byteswap(static_cast<uint32_t>(v >> 32))};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto bit_ceil(is_unsigned_integer auto v)
|
||||||
|
{
|
||||||
|
v -= 1;
|
||||||
|
v = propagate_right_one(v);
|
||||||
|
v += 1;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto bit_floor(is_unsigned_integer auto v)
|
||||||
|
{
|
||||||
|
v = propagate_right_one(v);
|
||||||
|
v = v - (v >> 1);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int bit_width(is_unsigned_integer auto v)
|
||||||
|
{
|
||||||
|
static constexpr int N = sizeof(decltype(v)) * 8;
|
||||||
|
return N - countl_zero(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace asl
|
||||||
|
|
194
asl/base/bit_tests.cpp
Normal file
194
asl/base/bit_tests.cpp
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
// Copyright 2025 Steven Le Rouzic
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
#include "asl/base/bit.hpp"
|
||||||
|
|
||||||
|
#include "asl/testing/testing.hpp"
|
||||||
|
|
||||||
|
ASL_TEST(has_single_bit)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::has_single_bit(4U));
|
||||||
|
ASL_TEST_EXPECT(asl::has_single_bit(1024U));
|
||||||
|
ASL_TEST_EXPECT(asl::has_single_bit(0x8000'0000U));
|
||||||
|
ASL_TEST_EXPECT(asl::has_single_bit(0x0000'8000'0000'0000ULL));
|
||||||
|
ASL_TEST_EXPECT(!asl::has_single_bit(0U));
|
||||||
|
ASL_TEST_EXPECT(!asl::has_single_bit(3U));
|
||||||
|
ASL_TEST_EXPECT(!asl::has_single_bit(341U));
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(popcount) // NOLINT(*-cognitive-complexity)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint8_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint8_t{255}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint8_t{46}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint16_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint16_t{255}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint16_t{65535}) == 16);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint16_t{46}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint32_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint32_t{255}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint32_t{65535}) == 16);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint32_t{65536}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint32_t{46}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(uint32_t{0xffff'ffff}) == 32);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(0x8421'1248'8421'1248) == 16);
|
||||||
|
ASL_TEST_EXPECT(asl::popcount(0xffff'ffff'ffff'ffff) == 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(countr_zero)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{0}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{255}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{0b00011100}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{0b10101010}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{0b10101001}) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(countr_one)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::countr_one(uint8_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::countr_one(uint8_t{255}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::countr_one(uint8_t{0b00011100}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::countr_one(uint8_t{0b10101011}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::countr_one(uint8_t{0b10101001}) == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(countl_zero)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::countl_zero(uint8_t{0}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::countl_zero(uint8_t{255}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::countl_zero(uint8_t{0b00011100}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::countl_zero(uint8_t{0b10101010}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::countl_zero(uint8_t{0b00001001}) == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(countl_one)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::countl_one(uint8_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::countl_one(uint8_t{255}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::countl_one(uint8_t{0b00011100}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::countl_one(uint8_t{0b10101010}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::countl_one(uint8_t{0b11101001}) == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(rotl)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::rotl(uint32_t{0x4000'0100}, 1) == 0x8000'0200);
|
||||||
|
ASL_TEST_EXPECT(asl::rotl(uint32_t{0x4000'0100}, 3) == 0x0000'0802);
|
||||||
|
ASL_TEST_EXPECT(asl::rotl(uint32_t{0x4000'0100}, 0) == 0x4000'0100);
|
||||||
|
ASL_TEST_EXPECT(asl::rotl(uint32_t{0x4000'0100}, -1) == 0x2000'0080);
|
||||||
|
ASL_TEST_EXPECT(asl::rotl(uint32_t{0x4000'0100}, -12) == 0x1004'0000);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(rotr)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::rotr(uint32_t{0x4000'0100}, -1) == 0x8000'0200);
|
||||||
|
ASL_TEST_EXPECT(asl::rotr(uint32_t{0x4000'0100}, -3) == 0x0000'0802);
|
||||||
|
ASL_TEST_EXPECT(asl::rotr(uint32_t{0x4000'0100}, 0) == 0x4000'0100);
|
||||||
|
ASL_TEST_EXPECT(asl::rotr(uint32_t{0x4000'0100}, 1) == 0x2000'0080);
|
||||||
|
ASL_TEST_EXPECT(asl::rotr(uint32_t{0x4000'0100}, 12) == 0x1004'0000);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(byteswap)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::byteswap(uint32_t{0x1234'5678}) == 0x7856'3412);
|
||||||
|
ASL_TEST_EXPECT(asl::byteswap(uint16_t{0x1234}) == 0x3412);
|
||||||
|
ASL_TEST_EXPECT(asl::byteswap(uint64_t{0x0123'4567'89ab'cdef}) == 0xefcd'ab89'6745'2301);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(bit_ceil) // NOLINT(*-cognitive-complexity)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{1}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{2}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{3}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{4}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{5}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{6}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{127}) == 128);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{128}) == 128);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{254}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{255}) == 0);
|
||||||
|
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{1}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{2}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{3}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{4}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{5}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{6}) == 8);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{32000}) == 32768);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{32768}) == 32768);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{35000}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{65535}) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(bit_floor) // NOLINT(*-cognitive-complexity)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{1}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{2}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{3}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{4}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{5}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{6}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{127}) == 64);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{128}) == 128);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{254}) == 128);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{255}) == 128);
|
||||||
|
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{1}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{2}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{3}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{4}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{5}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{6}) == 4);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{32000}) == 16384);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{32768}) == 32768);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{35000}) == 32768);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{65535}) == 32768);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(bit_width) // NOLINT(*-cognitive-complexity)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint8_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint8_t{1}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint8_t{2}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint8_t{3}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint8_t{4}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint8_t{5}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint8_t{6}) == 3);
|
||||||
|
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint16_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint16_t{1}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint16_t{2}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint16_t{3}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint16_t{4}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint16_t{5}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint16_t{6}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint16_t{65535}) == 16);
|
||||||
|
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint32_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint32_t{1}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint32_t{2}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint32_t{3}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint32_t{4}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint32_t{5}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint32_t{6}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint32_t{65535}) == 16);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint32_t{65536}) == 17);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint32_t{0xffff'ffff}) == 32);
|
||||||
|
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint64_t{0}) == 0);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint64_t{1}) == 1);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint64_t{2}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint64_t{3}) == 2);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint64_t{4}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint64_t{5}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint64_t{6}) == 3);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint64_t{65535}) == 16);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint64_t{65536}) == 17);
|
||||||
|
ASL_TEST_EXPECT(asl::bit_width(uint64_t{0xffff'ffff}) == 32);
|
||||||
|
}
|
@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#include "asl/base/meta.hpp"
|
#include "asl/base/meta.hpp"
|
||||||
|
|
||||||
|
using float32_t = float;
|
||||||
|
using float64_t = double;
|
||||||
|
|
||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -9,56 +9,62 @@
|
|||||||
|
|
||||||
namespace asl {
|
namespace asl {
|
||||||
|
|
||||||
template<typename... Args, typename C>
|
template<typename F, typename... Args>
|
||||||
constexpr auto invoke(is_func auto C::* f, auto&& self, Args&&... args)
|
constexpr auto invoke(F&& f, Args&&... args)
|
||||||
-> decltype((self.*f)(std::forward<Args>(args)...))
|
-> decltype(std::forward<F>(f)(std::forward<Args>(args)...))
|
||||||
requires requires {
|
requires (!is_member_ptr<un_cvref_t<F>>) && requires {
|
||||||
(self.*f)(std::forward<Args>(args)...);
|
f(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
return std::forward<F>(f)(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
constexpr auto&& invoke(auto C::* f, same_or_derived_from<C> auto&& arg)
|
||||||
|
{
|
||||||
|
return std::forward<decltype(arg)>(arg).*f;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
constexpr auto&& invoke(auto C::* f, auto&& arg)
|
||||||
|
requires (
|
||||||
|
!same_or_derived_from<decltype(arg), C>
|
||||||
|
&& requires { (*arg).*f; }
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (*std::forward<decltype(arg)>(arg)).*f;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C, typename... Args>
|
||||||
|
constexpr auto invoke(is_func auto C::* f, same_or_derived_from<C> auto&& self, Args&&... args)
|
||||||
|
-> decltype((std::forward<decltype(self)>(self).*f)(std::forward<Args>(args)...))
|
||||||
|
requires requires { (self.*f)(std::forward<Args>(args)...); }
|
||||||
{
|
{
|
||||||
return (std::forward<decltype(self)>(self).*f)(std::forward<Args>(args)...);
|
return (std::forward<decltype(self)>(self).*f)(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args, typename C>
|
template<typename C, typename... Args>
|
||||||
constexpr auto invoke(is_func auto C::* f, auto* self, Args&&... args)
|
constexpr auto invoke(is_func auto C::* f, auto&& self, Args&&... args)
|
||||||
-> decltype((self->*f)(std::forward<Args>(args)...))
|
-> decltype(((*std::forward<decltype(self)>(self)).*f)(std::forward<Args>(args)...))
|
||||||
requires requires {
|
|
||||||
(self->*f)(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
return (self->*f)(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args, typename C>
|
|
||||||
constexpr auto invoke(is_object auto C::* m, auto&& self, Args&&...)
|
|
||||||
-> decltype(self.*m)
|
|
||||||
requires (
|
requires (
|
||||||
sizeof...(Args) == 0 &&
|
!same_or_derived_from<decltype(self), C>
|
||||||
requires { self.*m; }
|
&& requires { ((*self).*f)(std::forward<Args>(args)...); }
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return std::forward<decltype(self)>(self).*m;
|
return ((*std::forward<decltype(self)>(self)).*f)(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args, typename C>
|
template<typename R, typename F, typename... Args>
|
||||||
constexpr auto invoke(is_object auto C::* m, auto* self, Args&&...)
|
constexpr R invoke_r(F&& f, Args&&... args)
|
||||||
-> decltype(self->*m)
|
|
||||||
requires (
|
|
||||||
sizeof...(Args) == 0 &&
|
|
||||||
requires { self->*m; }
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return self->*m;
|
if constexpr (is_void<R>)
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
constexpr auto invoke(auto&& f, Args&&... args)
|
|
||||||
-> decltype(f(std::forward<Args>(args)...))
|
|
||||||
requires requires {
|
|
||||||
f(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
return std::forward<decltype(f)>(f)(std::forward<Args>(args)...);
|
static_cast<void>(invoke(std::forward<F>(f), std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return invoke(std::forward<F>(f), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Void, typename F, typename... Args>
|
template<typename Void, typename F, typename... Args>
|
||||||
@ -79,4 +85,8 @@ concept invocable = requires (F&& f, Args&&... args)
|
|||||||
invoke(std::forward<F>(f), std::forward<Args>(args)...);
|
invoke(std::forward<F>(f), std::forward<Args>(args)...);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename R, typename F, typename... Args>
|
||||||
|
concept invocable_r = invocable<F, Args...>
|
||||||
|
&& (is_void<R> || convertible_to<invoke_result_t<F, Args...>, R>);
|
||||||
|
|
||||||
} // namespace asl
|
} // namespace asl
|
||||||
|
@ -7,9 +7,12 @@
|
|||||||
|
|
||||||
struct HasFunction
|
struct HasFunction
|
||||||
{
|
{
|
||||||
void do_something(int, float) {}
|
void do_something(int, float) const {}
|
||||||
|
int& do_something2(int, float) &;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct HasFunction2 : public HasFunction {};
|
||||||
|
|
||||||
struct HasMember
|
struct HasMember
|
||||||
{
|
{
|
||||||
int member{};
|
int member{};
|
||||||
@ -17,6 +20,8 @@ struct HasMember
|
|||||||
void (*member_fn)(){};
|
void (*member_fn)(){};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct HasMember2 : public HasMember {};
|
||||||
|
|
||||||
struct Functor
|
struct Functor
|
||||||
{
|
{
|
||||||
int64_t operator()() { return 35; }
|
int64_t operator()() { return 35; }
|
||||||
@ -34,7 +39,13 @@ static_assert(asl::same_as<asl::invoke_result_t<Functor>, int64_t>);
|
|||||||
static_assert(asl::same_as<asl::invoke_result_t<Functor, int>, int>);
|
static_assert(asl::same_as<asl::invoke_result_t<Functor, int>, int>);
|
||||||
static_assert(asl::same_as<asl::invoke_result_t<decltype(static_cast<float(*)(float)>(some_func1)), float>, float>);
|
static_assert(asl::same_as<asl::invoke_result_t<decltype(static_cast<float(*)(float)>(some_func1)), float>, float>);
|
||||||
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasFunction::do_something), HasFunction, int, float>, void>);
|
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasFunction::do_something), HasFunction, int, float>, void>);
|
||||||
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasMember::member), const HasMember>, const int&>);
|
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasFunction::do_something), const HasFunction2&, int, float>, void>);
|
||||||
|
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasFunction::do_something), HasFunction*, int, float>, void>);
|
||||||
|
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasFunction::do_something2), HasFunction2&, int, float>, int&>);
|
||||||
|
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasFunction::do_something2), HasFunction*, int, float>, int&>);
|
||||||
|
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasMember::member), HasMember>, int&&>);
|
||||||
|
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasMember::member), const HasMember&>, const int&>);
|
||||||
|
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasMember::member), const HasMember2*>, const int&>);
|
||||||
|
|
||||||
static_assert(asl::invocable<int()>);
|
static_assert(asl::invocable<int()>);
|
||||||
static_assert(!asl::invocable<int(), int>);
|
static_assert(!asl::invocable<int(), int>);
|
||||||
@ -45,8 +56,20 @@ static_assert(asl::invocable<Functor, int>);
|
|||||||
static_assert(!asl::invocable<Functor, void*>);
|
static_assert(!asl::invocable<Functor, void*>);
|
||||||
static_assert(asl::invocable<decltype(static_cast<float(*)(float)>(some_func1)), float>);
|
static_assert(asl::invocable<decltype(static_cast<float(*)(float)>(some_func1)), float>);
|
||||||
static_assert(asl::invocable<decltype(&HasFunction::do_something), HasFunction, int, float>);
|
static_assert(asl::invocable<decltype(&HasFunction::do_something), HasFunction, int, float>);
|
||||||
|
static_assert(asl::invocable<decltype(&HasFunction::do_something), const HasFunction2&, int, float>);
|
||||||
|
static_assert(asl::invocable<decltype(&HasFunction::do_something), HasFunction*, int, float>);
|
||||||
static_assert(!asl::invocable<decltype(&HasFunction::do_something), HasFunction, int, int*>);
|
static_assert(!asl::invocable<decltype(&HasFunction::do_something), HasFunction, int, int*>);
|
||||||
static_assert(asl::invocable<decltype(&HasMember::member), const HasMember>);
|
static_assert(!asl::invocable<decltype(&HasFunction::do_something2), HasFunction, int, float>);
|
||||||
|
static_assert(!asl::invocable<decltype(&HasFunction::do_something2), const HasFunction2&, int, float>);
|
||||||
|
static_assert(asl::invocable<decltype(&HasFunction::do_something2), HasFunction2&, int, float>);
|
||||||
|
static_assert(asl::invocable<decltype(&HasFunction::do_something2), HasFunction*, int, float>);
|
||||||
|
static_assert(!asl::invocable<decltype(&HasFunction::do_something2), HasFunction, int, int*>);
|
||||||
|
static_assert(asl::invocable<decltype(&HasMember::member), const HasMember2>);
|
||||||
|
static_assert(asl::invocable<decltype(&HasMember::member), const HasMember&>);
|
||||||
|
static_assert(asl::invocable<decltype(&HasMember::member), const HasMember2*>);
|
||||||
|
|
||||||
|
static_assert(asl::invocable_r<void*, int*()>);
|
||||||
|
static_assert(!asl::invocable_r<int*, void*()>);
|
||||||
|
|
||||||
ASL_TEST(invoke_member_function)
|
ASL_TEST(invoke_member_function)
|
||||||
{
|
{
|
||||||
@ -89,3 +112,9 @@ ASL_TEST(invoke_lambda)
|
|||||||
ASL_TEST_EXPECT(asl::invoke([](){ return 35; }) == 35);
|
ASL_TEST_EXPECT(asl::invoke([](){ return 35; }) == 35);
|
||||||
ASL_TEST_EXPECT(asl::invoke([](int x){ return x + 2; }, 6) == 8);
|
ASL_TEST_EXPECT(asl::invoke([](int x){ return x + 2; }, 6) == 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASL_TEST(invoke_r)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::invoke_r<int>([]() { return 1ULL; }) == 1);
|
||||||
|
asl::invoke_r<void>([]() { return 1ULL; });
|
||||||
|
}
|
||||||
|
@ -25,6 +25,9 @@ struct empty {};
|
|||||||
|
|
||||||
template<typename T> struct id { using type = T; };
|
template<typename T> struct id { using type = T; };
|
||||||
|
|
||||||
|
struct in_place_t {};
|
||||||
|
static constexpr in_place_t in_place{};
|
||||||
|
|
||||||
template<typename... Args> static constexpr isize_t types_count = sizeof...(Args);
|
template<typename... Args> static constexpr isize_t types_count = sizeof...(Args);
|
||||||
|
|
||||||
template<typename T, T kValue> struct integral_constant { static constexpr T value = kValue; };
|
template<typename T, T kValue> struct integral_constant { static constexpr T value = kValue; };
|
||||||
@ -92,12 +95,6 @@ template<typename T> concept trivially_destructible = __is_trivially_destructibl
|
|||||||
template<typename T> concept copyable = copy_constructible<T> && copy_assignable<T>;
|
template<typename T> concept copyable = copy_constructible<T> && copy_assignable<T>;
|
||||||
template<typename T> concept moveable = move_constructible<T> && move_assignable<T>;
|
template<typename T> concept moveable = move_constructible<T> && move_assignable<T>;
|
||||||
|
|
||||||
template<typename From, typename To>
|
|
||||||
concept convertible_to = __is_convertible(From, To);
|
|
||||||
|
|
||||||
template<typename Derived, class Base>
|
|
||||||
concept derived_from = __is_class(Derived) && __is_class(Base) && convertible_to<const volatile Derived*, const volatile Base*>;
|
|
||||||
|
|
||||||
using nullptr_t = decltype(nullptr);
|
using nullptr_t = decltype(nullptr);
|
||||||
|
|
||||||
template<typename T> struct _un_const_helper { using type = T; };
|
template<typename T> struct _un_const_helper { using type = T; };
|
||||||
@ -154,6 +151,15 @@ template<typename T> struct _is_ptr_helper<T*> : true_type {};
|
|||||||
|
|
||||||
template<typename T> concept is_ptr = _is_ptr_helper<un_cv_t<T>>::value;
|
template<typename T> concept is_ptr = _is_ptr_helper<un_cv_t<T>>::value;
|
||||||
|
|
||||||
|
template<typename From, typename To>
|
||||||
|
concept convertible_to = __is_convertible(From, To);
|
||||||
|
|
||||||
|
template<typename Derived, typename Base>
|
||||||
|
concept derived_from = __is_class(Derived) && __is_class(Base) && convertible_to<const volatile Derived*, const volatile Base*>;
|
||||||
|
|
||||||
|
template<typename Derived, typename Base>
|
||||||
|
concept same_or_derived_from = same_as<un_cvref_t<Derived>, Base> || derived_from<un_cvref_t<Derived>, Base>;
|
||||||
|
|
||||||
template<typename T> struct _tame_helper { using type = T; };
|
template<typename T> struct _tame_helper { using type = T; };
|
||||||
|
|
||||||
#define TAME_HELPER_IMPL(TRAILING) \
|
#define TAME_HELPER_IMPL(TRAILING) \
|
||||||
@ -194,6 +200,17 @@ template<typename R, typename... Args> struct _is_func_helper<R(Args...)> : true
|
|||||||
|
|
||||||
template<typename T> concept is_func = _is_func_helper<tame_t<T>>::value;
|
template<typename T> concept is_func = _is_func_helper<tame_t<T>>::value;
|
||||||
|
|
||||||
|
template<typename T> struct _is_member_ptr_helper : false_type {};
|
||||||
|
template<typename C, typename T> struct _is_member_ptr_helper<T C::*> : true_type
|
||||||
|
{
|
||||||
|
static constexpr bool kIsFunc = is_func<T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> concept is_member_ptr = _is_member_ptr_helper<un_cv_t<T>>::value;
|
||||||
|
|
||||||
|
template<typename T> concept is_member_func_ptr = is_member_ptr<T> && _is_member_ptr_helper<un_cv_t<T>>::kIsFunc;
|
||||||
|
template<typename T> concept is_member_data_ptr = is_member_ptr<T> && !_is_member_ptr_helper<un_cv_t<T>>::kIsFunc;
|
||||||
|
|
||||||
template<typename T> concept is_object = !is_void<T> && !is_ref<T> && !is_func<T>;
|
template<typename T> concept is_object = !is_void<T> && !is_ref<T> && !is_func<T>;
|
||||||
|
|
||||||
template<typename T> struct _array_helper : false_type { using type = T; };
|
template<typename T> struct _array_helper : false_type { using type = T; };
|
||||||
@ -220,20 +237,80 @@ template<> struct _is_floating_point_helper<double> : true_type {};
|
|||||||
|
|
||||||
template<typename T> concept is_floating_point = _is_floating_point_helper<un_cv_t<T>>::value;
|
template<typename T> concept is_floating_point = _is_floating_point_helper<un_cv_t<T>>::value;
|
||||||
|
|
||||||
template<typename T> struct _is_integer_helper : false_type {};
|
template<typename T> struct _integer_traits
|
||||||
template<> struct _is_integer_helper<int8_t> : true_type {};
|
{
|
||||||
template<> struct _is_integer_helper<int16_t> : true_type {};
|
static constexpr bool kSigned = false;
|
||||||
template<> struct _is_integer_helper<int32_t> : true_type {};
|
static constexpr bool kUnsigned = false;
|
||||||
template<> struct _is_integer_helper<int64_t> : true_type {};
|
};
|
||||||
template<> struct _is_integer_helper<uint8_t> : true_type {};
|
|
||||||
template<> struct _is_integer_helper<uint16_t> : true_type {};
|
|
||||||
template<> struct _is_integer_helper<uint32_t> : true_type {};
|
|
||||||
template<> struct _is_integer_helper<uint64_t> : true_type {};
|
|
||||||
|
|
||||||
template<typename T> concept is_integer = _is_integer_helper<un_cv_t<T>>::value;
|
template<> struct _integer_traits<uint8_t>
|
||||||
|
{
|
||||||
|
static constexpr bool kSigned = false;
|
||||||
|
static constexpr bool kUnsigned = true;
|
||||||
|
using as_signed = int8_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct _integer_traits<uint16_t>
|
||||||
|
{
|
||||||
|
static constexpr bool kSigned = false;
|
||||||
|
static constexpr bool kUnsigned = true;
|
||||||
|
using as_signed = int16_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct _integer_traits<uint32_t>
|
||||||
|
{
|
||||||
|
static constexpr bool kSigned = false;
|
||||||
|
static constexpr bool kUnsigned = true;
|
||||||
|
using as_signed = int32_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct _integer_traits<uint64_t>
|
||||||
|
{
|
||||||
|
static constexpr bool kSigned = false;
|
||||||
|
static constexpr bool kUnsigned = true;
|
||||||
|
using as_signed = int64_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct _integer_traits<int8_t>
|
||||||
|
{
|
||||||
|
static constexpr bool kSigned = true;
|
||||||
|
static constexpr bool kUnsigned = false;
|
||||||
|
using as_unsigned = uint8_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct _integer_traits<int16_t>
|
||||||
|
{
|
||||||
|
static constexpr bool kSigned = true;
|
||||||
|
static constexpr bool kUnsigned = false;
|
||||||
|
using as_unsigned = uint16_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct _integer_traits<int32_t>
|
||||||
|
{
|
||||||
|
static constexpr bool kSigned = true;
|
||||||
|
static constexpr bool kUnsigned = false;
|
||||||
|
using as_unsigned = uint32_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct _integer_traits<int64_t>
|
||||||
|
{
|
||||||
|
static constexpr bool kSigned = true;
|
||||||
|
static constexpr bool kUnsigned = false;
|
||||||
|
using as_unsigned = uint64_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> concept is_signed_integer = _integer_traits<T>::kSigned;
|
||||||
|
template<typename T> concept is_unsigned_integer = _integer_traits<T>::kUnsigned;
|
||||||
|
|
||||||
|
template<typename T> concept is_integer = is_signed_integer<T> || is_unsigned_integer<T>;
|
||||||
|
|
||||||
|
template<is_signed_integer T> using as_unsigned_integer = _integer_traits<T>::as_unsigned;
|
||||||
|
template<is_unsigned_integer T> using as_signed_integer = _integer_traits<T>::as_signed;
|
||||||
|
|
||||||
template<typename T> concept is_enum = __is_enum(T);
|
template<typename T> concept is_enum = __is_enum(T);
|
||||||
|
|
||||||
|
template<is_enum T> using underlying_t = __underlying_type(T);
|
||||||
|
|
||||||
template<typename T> struct is_uniquely_represented : false_type {};
|
template<typename T> struct is_uniquely_represented : false_type {};
|
||||||
template<is_integer T> struct is_uniquely_represented<T> : true_type {};
|
template<is_integer T> struct is_uniquely_represented<T> : true_type {};
|
||||||
template<is_enum T> struct is_uniquely_represented<T> : true_type {};
|
template<is_enum T> struct is_uniquely_represented<T> : true_type {};
|
||||||
|
@ -135,6 +135,12 @@ static_assert(!asl::is_ref<void>);
|
|||||||
static_assert(!asl::is_ref<void()>);
|
static_assert(!asl::is_ref<void()>);
|
||||||
static_assert(!asl::is_ref<void() const &&>);
|
static_assert(!asl::is_ref<void() const &&>);
|
||||||
|
|
||||||
|
struct MyClass
|
||||||
|
{
|
||||||
|
int data;
|
||||||
|
int fn(int x) { return x; } // NOLINT
|
||||||
|
};
|
||||||
|
|
||||||
static_assert(asl::is_ptr<int*>);
|
static_assert(asl::is_ptr<int*>);
|
||||||
static_assert(asl::is_ptr<const int* const>);
|
static_assert(asl::is_ptr<const int* const>);
|
||||||
static_assert(asl::is_ptr<const volatile int*>);
|
static_assert(asl::is_ptr<const volatile int*>);
|
||||||
@ -142,6 +148,28 @@ static_assert(!asl::is_ptr<int>);
|
|||||||
static_assert(!asl::is_ptr<void>);
|
static_assert(!asl::is_ptr<void>);
|
||||||
static_assert(!asl::is_ptr<void()>);
|
static_assert(!asl::is_ptr<void()>);
|
||||||
static_assert(!asl::is_ptr<void() const &&>);
|
static_assert(!asl::is_ptr<void() const &&>);
|
||||||
|
static_assert(!asl::is_ptr<int MyClass::*>);
|
||||||
|
static_assert(!asl::is_ptr<int (MyClass::*)(int)>);
|
||||||
|
|
||||||
|
static_assert(!asl::is_member_ptr<int*>);
|
||||||
|
static_assert(!asl::is_member_ptr<void()>);
|
||||||
|
static_assert(!asl::is_member_ptr<void() const &&>);
|
||||||
|
static_assert(asl::is_member_ptr<int MyClass::*>);
|
||||||
|
static_assert(asl::is_member_ptr<int (MyClass::*)(int)>);
|
||||||
|
|
||||||
|
static_assert(!asl::is_member_data_ptr<int*>);
|
||||||
|
static_assert(!asl::is_member_data_ptr<void()>);
|
||||||
|
static_assert(!asl::is_member_data_ptr<void() const &&>);
|
||||||
|
static_assert(asl::is_member_data_ptr<int MyClass::*>);
|
||||||
|
static_assert(!asl::is_member_data_ptr<int (MyClass::*)(int)>);
|
||||||
|
|
||||||
|
static_assert(!asl::is_member_func_ptr<int*>);
|
||||||
|
static_assert(!asl::is_member_func_ptr<void()>);
|
||||||
|
static_assert(!asl::is_member_func_ptr<void() const &&>);
|
||||||
|
static_assert(!asl::is_member_func_ptr<int MyClass::*>);
|
||||||
|
static_assert(asl::is_member_func_ptr<int (MyClass::*)(int)>);
|
||||||
|
static_assert(asl::is_member_func_ptr<int (MyClass::*)(int) const>);
|
||||||
|
static_assert(asl::is_member_func_ptr<int (MyClass::*)(int) volatile &&>);
|
||||||
|
|
||||||
static_assert(asl::same_as<int, asl::tame_t<int>>);
|
static_assert(asl::same_as<int, asl::tame_t<int>>);
|
||||||
static_assert(asl::same_as<int(), asl::tame_t<int()>>);
|
static_assert(asl::same_as<int(), asl::tame_t<int()>>);
|
||||||
@ -224,6 +252,8 @@ static_assert(!asl::convertible_to<const int16_t(&)[], int16_t(&)[]>);
|
|||||||
static_assert(!asl::convertible_to<D(&)[], C(&)[]>);
|
static_assert(!asl::convertible_to<D(&)[], C(&)[]>);
|
||||||
|
|
||||||
static_assert(asl::derived_from<Derived, Base>);
|
static_assert(asl::derived_from<Derived, Base>);
|
||||||
|
static_assert(asl::derived_from<Derived, Derived>);
|
||||||
|
static_assert(asl::derived_from<Base, Base>);
|
||||||
static_assert(!asl::derived_from<Base, Derived>);
|
static_assert(!asl::derived_from<Base, Derived>);
|
||||||
static_assert(!asl::derived_from<D, C>);
|
static_assert(!asl::derived_from<D, C>);
|
||||||
static_assert(!asl::derived_from<C, D>);
|
static_assert(!asl::derived_from<C, D>);
|
||||||
@ -231,6 +261,16 @@ static_assert(!asl::derived_from<uint8_t, uint16_t>);
|
|||||||
static_assert(!asl::derived_from<uint16_t, uint8_t>);
|
static_assert(!asl::derived_from<uint16_t, uint8_t>);
|
||||||
static_assert(!asl::derived_from<int, int>);
|
static_assert(!asl::derived_from<int, int>);
|
||||||
|
|
||||||
|
static_assert(asl::same_or_derived_from<Derived, Base>);
|
||||||
|
static_assert(asl::same_or_derived_from<Derived, Derived>);
|
||||||
|
static_assert(asl::same_or_derived_from<Base, Base>);
|
||||||
|
static_assert(!asl::same_or_derived_from<Base, Derived>);
|
||||||
|
static_assert(!asl::same_or_derived_from<D, C>);
|
||||||
|
static_assert(!asl::same_or_derived_from<C, D>);
|
||||||
|
static_assert(!asl::same_or_derived_from<uint8_t, uint16_t>);
|
||||||
|
static_assert(!asl::same_or_derived_from<uint16_t, uint8_t>);
|
||||||
|
static_assert(asl::same_or_derived_from<int, int>);
|
||||||
|
|
||||||
static_assert(!asl::is_const<int>);
|
static_assert(!asl::is_const<int>);
|
||||||
static_assert(asl::is_const<const int>);
|
static_assert(asl::is_const<const int>);
|
||||||
static_assert(!asl::is_const<const int*>);
|
static_assert(!asl::is_const<const int*>);
|
||||||
@ -332,3 +372,10 @@ static_assert(!asl::same_as<asl::decay_t<int[4][2]>, int*>);
|
|||||||
static_assert(!asl::same_as<asl::decay_t<int[4][2]>, int**>);
|
static_assert(!asl::same_as<asl::decay_t<int[4][2]>, int**>);
|
||||||
static_assert(asl::same_as<asl::decay_t<int[4][2]>, int(*)[2]>);
|
static_assert(asl::same_as<asl::decay_t<int[4][2]>, int(*)[2]>);
|
||||||
static_assert(asl::same_as<asl::decay_t<int(int)>, int(*)(int)>);
|
static_assert(asl::same_as<asl::decay_t<int(int)>, int(*)(int)>);
|
||||||
|
|
||||||
|
enum EnumU8 : uint8_t {};
|
||||||
|
enum EnumI64 : int64_t {};
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::underlying_t<EnumU8>, uint8_t>);
|
||||||
|
static_assert(asl::same_as<asl::underlying_t<EnumI64>, int64_t>);
|
||||||
|
|
||||||
|
43
asl/base/numeric.hpp
Normal file
43
asl/base/numeric.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2025 Steven Le Rouzic
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "asl/base/integers.hpp"
|
||||||
|
#include "asl/base/bit.hpp"
|
||||||
|
#include "asl/base/meta.hpp"
|
||||||
|
|
||||||
|
namespace asl
|
||||||
|
{
|
||||||
|
|
||||||
|
template<is_integer T>
|
||||||
|
constexpr bool is_pow2(T x)
|
||||||
|
{
|
||||||
|
using unsigned_type = select_t<is_unsigned_integer<T>, T, as_unsigned_integer<T>>;
|
||||||
|
return x > 0 && has_single_bit(static_cast<unsigned_type>(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept is_numeric = is_integer<T> || is_floating_point<T>;
|
||||||
|
|
||||||
|
template<is_numeric T>
|
||||||
|
constexpr T min(T a, T b)
|
||||||
|
{
|
||||||
|
return (a <= b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<is_numeric T>
|
||||||
|
constexpr T max(T a, T b)
|
||||||
|
{
|
||||||
|
return (a >= b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<is_numeric T>
|
||||||
|
constexpr T clamp(T x, T a, T b)
|
||||||
|
{
|
||||||
|
return min(max(x, a), b);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace asl
|
||||||
|
|
16
asl/base/numeric_tests.cpp
Normal file
16
asl/base/numeric_tests.cpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2025 Steven Le Rouzic
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
#include "asl/base/numeric.hpp"
|
||||||
|
|
||||||
|
#include "asl/testing/testing.hpp"
|
||||||
|
|
||||||
|
ASL_TEST(is_pow2)
|
||||||
|
{
|
||||||
|
ASL_TEST_EXPECT(asl::is_pow2(4));
|
||||||
|
ASL_TEST_EXPECT(asl::is_pow2(65536));
|
||||||
|
ASL_TEST_EXPECT(!asl::is_pow2(6));
|
||||||
|
ASL_TEST_EXPECT(!asl::is_pow2(1978));
|
||||||
|
ASL_TEST_EXPECT(!asl::is_pow2(0));
|
||||||
|
}
|
@ -47,9 +47,6 @@ template<typename T>
|
|||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
struct in_place_t {};
|
|
||||||
static constexpr in_place_t in_place{};
|
|
||||||
|
|
||||||
template<moveable T>
|
template<moveable T>
|
||||||
constexpr void swap(T& a, T& b)
|
constexpr void swap(T& a, T& b)
|
||||||
{
|
{
|
||||||
@ -72,37 +69,10 @@ constexpr U bit_cast(T value) requires (sizeof(T) == sizeof(U))
|
|||||||
return __builtin_bit_cast(U, value);
|
return __builtin_bit_cast(U, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<is_enum T>
|
||||||
constexpr T min(T a, T b)
|
constexpr auto to_underlying(T value)
|
||||||
{
|
{
|
||||||
return (a <= b) ? a : b;
|
return static_cast<underlying_t<T>>(value);
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr T max(T a, T b)
|
|
||||||
{
|
|
||||||
return (a >= b) ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr uint64_t round_up_pow2(uint64_t v)
|
|
||||||
{
|
|
||||||
ASL_ASSERT(v <= 0x8000'0000'0000'0000);
|
|
||||||
|
|
||||||
v -= 1;
|
|
||||||
|
|
||||||
v |= v >> 1U;
|
|
||||||
v |= v >> 2U;
|
|
||||||
v |= v >> 4U;
|
|
||||||
v |= v >> 8U;
|
|
||||||
v |= v >> 16U;
|
|
||||||
v |= v >> 32U;
|
|
||||||
|
|
||||||
return v + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool is_pow2(isize_t v)
|
|
||||||
{
|
|
||||||
return v > 0 && ((v - 1) & v) == 0; // NOLINT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOLINTBEGIN(*-macro-parentheses)
|
// NOLINTBEGIN(*-macro-parentheses)
|
||||||
|
@ -81,3 +81,20 @@ ASL_TEST(forward_like)
|
|||||||
ASL_TEST_EXPECT(test_fwd_like<int&&>(9) == 4);
|
ASL_TEST_EXPECT(test_fwd_like<int&&>(9) == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class Enum : int // NOLINT
|
||||||
|
{
|
||||||
|
kOne = 1,
|
||||||
|
kTwo = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Enum2 : int // NOLINT
|
||||||
|
{
|
||||||
|
kOne = 1,
|
||||||
|
kTwo = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(asl::to_underlying(Enum::kOne) == 1);
|
||||||
|
static_assert(asl::to_underlying(Enum::kTwo) == 2);
|
||||||
|
static_assert(asl::to_underlying(kOne) == 1);
|
||||||
|
static_assert(asl::to_underlying(kTwo) == 2);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ cc_library(
|
|||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//asl/memory",
|
"//asl/memory",
|
||||||
|
"//asl/memory:allocator",
|
||||||
"//asl/base",
|
"//asl/base",
|
||||||
"//asl/types:span",
|
"//asl/types:span",
|
||||||
"//asl/hashing",
|
"//asl/hashing",
|
||||||
@ -28,6 +29,7 @@ cc_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//asl/base",
|
"//asl/base",
|
||||||
"//asl/memory",
|
"//asl/memory",
|
||||||
|
"//asl/memory:allocator",
|
||||||
"//asl/types:maybe_uninit",
|
"//asl/types:maybe_uninit",
|
||||||
"//asl/hashing",
|
"//asl/hashing",
|
||||||
],
|
],
|
||||||
@ -42,6 +44,7 @@ cc_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//asl/base",
|
"//asl/base",
|
||||||
"//asl/memory",
|
"//asl/memory",
|
||||||
|
"//asl/memory:allocator",
|
||||||
"//asl/hashing",
|
"//asl/hashing",
|
||||||
":hash_set",
|
":hash_set",
|
||||||
],
|
],
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "asl/memory/memory.hpp"
|
#include "asl/memory/memory.hpp"
|
||||||
#include "asl/base/annotations.hpp"
|
#include "asl/base/annotations.hpp"
|
||||||
#include "asl/base/assert.hpp"
|
#include "asl/base/assert.hpp"
|
||||||
|
#include "asl/base/bit.hpp"
|
||||||
#include "asl/types/span.hpp"
|
#include "asl/types/span.hpp"
|
||||||
#include "asl/hashing/hash.hpp"
|
#include "asl/hashing/hash.hpp"
|
||||||
|
|
||||||
@ -320,7 +321,7 @@ public:
|
|||||||
if (new_capacity <= capacity()) { return; }
|
if (new_capacity <= capacity()) { return; }
|
||||||
ASL_ASSERT(new_capacity > kInlineCapacity);
|
ASL_ASSERT(new_capacity > kInlineCapacity);
|
||||||
|
|
||||||
new_capacity = static_cast<isize_t>(round_up_pow2(static_cast<uint64_t>(new_capacity)));
|
new_capacity = static_cast<isize_t>(bit_ceil(static_cast<uint64_t>(new_capacity)));
|
||||||
|
|
||||||
T* old_data = data();
|
T* old_data = data();
|
||||||
const isize_t old_capacity = capacity();
|
const isize_t old_capacity = capacity();
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include "asl/base/annotations.hpp"
|
#include "asl/base/annotations.hpp"
|
||||||
#include "asl/base/utility.hpp"
|
#include "asl/base/utility.hpp"
|
||||||
#include "asl/base/meta.hpp"
|
#include "asl/base/meta.hpp"
|
||||||
|
#include "asl/base/bit.hpp"
|
||||||
|
#include "asl/base/numeric.hpp"
|
||||||
#include "asl/memory/allocator.hpp"
|
#include "asl/memory/allocator.hpp"
|
||||||
#include "asl/memory/memory.hpp"
|
#include "asl/memory/memory.hpp"
|
||||||
#include "asl/types/maybe_uninit.hpp"
|
#include "asl/types/maybe_uninit.hpp"
|
||||||
@ -83,7 +85,7 @@ protected:
|
|||||||
ASL_ASSERT(size > 0);
|
ASL_ASSERT(size > 0);
|
||||||
return max<isize_t>(
|
return max<isize_t>(
|
||||||
kMinCapacity,
|
kMinCapacity,
|
||||||
static_cast<isize_t>(round_up_pow2((static_cast<uint64_t>(size) * 4 + 2) / 3)));
|
static_cast<isize_t>(bit_ceil((static_cast<uint64_t>(size) * 4 + 2) / 3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void insert_inner(
|
static void insert_inner(
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "asl/formatting/format.hpp"
|
#include "asl/formatting/format.hpp"
|
||||||
#include "asl/base/float.hpp"
|
#include "asl/base/float.hpp"
|
||||||
|
#include "asl/base/numeric.hpp"
|
||||||
|
|
||||||
#define JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED 0
|
#define JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED 0
|
||||||
#define JKJ_STATIC_DATA_SECTION_DEFINED 0
|
#define JKJ_STATIC_DATA_SECTION_DEFINED 0
|
||||||
|
@ -9,16 +9,27 @@ package(
|
|||||||
cc_library(
|
cc_library(
|
||||||
name = "memory",
|
name = "memory",
|
||||||
hdrs = [
|
hdrs = [
|
||||||
"allocator.hpp",
|
|
||||||
"layout.hpp",
|
"layout.hpp",
|
||||||
"memory.hpp",
|
"memory.hpp",
|
||||||
],
|
],
|
||||||
srcs = [
|
|
||||||
"allocator.cpp",
|
|
||||||
],
|
|
||||||
deps = [
|
deps = [
|
||||||
"//asl/base",
|
"//asl/base",
|
||||||
],
|
],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "allocator",
|
||||||
|
hdrs = [
|
||||||
|
"allocator.hpp",
|
||||||
|
],
|
||||||
|
srcs = [
|
||||||
|
"allocator.cpp",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//asl/base",
|
||||||
|
"//asl/memory",
|
||||||
|
],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
|
@ -17,6 +17,17 @@ constexpr void* operator new(size_t, void* ptr) noexcept
|
|||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr T* address_of(T& obj)
|
||||||
|
{
|
||||||
|
return __builtin_addressof(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void address_of(const T&& obj) = delete;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
constexpr isize_t memcmp(const void* a, const void* b, isize_t size)
|
constexpr isize_t memcmp(const void* a, const void* b, isize_t size)
|
||||||
{
|
{
|
||||||
return __builtin_memcmp(a, b, static_cast<size_t>(size));
|
return __builtin_memcmp(a, b, static_cast<size_t>(size));
|
||||||
|
@ -14,6 +14,7 @@ cc_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//asl/base",
|
"//asl/base",
|
||||||
"//asl/memory",
|
"//asl/memory",
|
||||||
|
"//asl/memory:allocator",
|
||||||
"//asl/hashing",
|
"//asl/hashing",
|
||||||
],
|
],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
@ -86,6 +87,7 @@ cc_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//asl/base",
|
"//asl/base",
|
||||||
"//asl/memory",
|
"//asl/memory",
|
||||||
|
"//asl/memory:allocator",
|
||||||
],
|
],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
@ -97,6 +99,7 @@ cc_library(
|
|||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//asl/base",
|
"//asl/base",
|
||||||
|
"//asl/memory",
|
||||||
],
|
],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "asl/base/utility.hpp"
|
#include "asl/base/utility.hpp"
|
||||||
#include "asl/base/meta.hpp"
|
#include "asl/base/meta.hpp"
|
||||||
#include "asl/base/functional.hpp"
|
#include "asl/base/functional.hpp"
|
||||||
|
#include "asl/memory/memory.hpp"
|
||||||
|
|
||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
@ -43,7 +44,7 @@ public:
|
|||||||
&& same_as<invoke_result_t<T, Args...>, R>
|
&& same_as<invoke_result_t<T, Args...>, R>
|
||||||
)
|
)
|
||||||
// NOLINTNEXTLINE(*cast*)
|
// NOLINTNEXTLINE(*cast*)
|
||||||
: m_obj{const_cast<void*>(reinterpret_cast<const void*>(&t))}
|
: m_obj{const_cast<void*>(reinterpret_cast<const void*>(address_of(t)))}
|
||||||
, m_invoke{invoke<un_ref_t<T>>}
|
, m_invoke{invoke<un_ref_t<T>>}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ public:
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(*cast*)
|
// NOLINTNEXTLINE(*cast*)
|
||||||
m_obj = const_cast<void*>(reinterpret_cast<const void*>(&t));
|
m_obj = const_cast<void*>(reinterpret_cast<const void*>(address_of(t)));
|
||||||
m_invoke = invoke<un_ref_t<T>>;
|
m_invoke = invoke<un_ref_t<T>>;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
Reference in New Issue
Block a user