diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 0000000..0cf5ea5 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": "No Configurations" +} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..3da647a --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,8 @@ +{ + "ExpandedNodes": [ + "", + "\\build" + ], + "SelectedNode": "\\build", + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/eigsol_gpu/project-colors.json b/.vs/eigsol_gpu/project-colors.json new file mode 100644 index 0000000..069efb9 --- /dev/null +++ b/.vs/eigsol_gpu/project-colors.json @@ -0,0 +1,11 @@ +{ + "Version": 1, + "ProjectMap": { + "a2fe74e1-b743-11d0-ae1a-00a0c90fffc3": { + "ProjectGuid": "a2fe74e1-b743-11d0-ae1a-00a0c90fffc3", + "DisplayName": "Miscellaneous Files", + "ColorIndex": -1 + } + }, + "NextColorIndex": 0 +} \ No newline at end of file diff --git a/.vs/eigsol_gpu/v17/.suo b/.vs/eigsol_gpu/v17/.suo new file mode 100644 index 0000000..abb1574 Binary files /dev/null and b/.vs/eigsol_gpu/v17/.suo differ diff --git a/.vs/eigsol_gpu/v17/Browse.VC.db b/.vs/eigsol_gpu/v17/Browse.VC.db new file mode 100644 index 0000000..e796e94 Binary files /dev/null and b/.vs/eigsol_gpu/v17/Browse.VC.db differ diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000..7c113b1 Binary files /dev/null and b/.vs/slnx.sqlite differ diff --git a/build.bat b/build.bat index a36d58b..0d97163 100644 --- a/build.bat +++ b/build.bat @@ -3,13 +3,17 @@ ctime -begin timeBuild.ctm @rem /WX /W4 /wd4201 /wd4100 /wd4189 /wd4244 /wd4127 /wd4456 -set CommonCompilerFlags="/nologo /Zi /FC" +@rem set CommonCompilerFlags="/nologo /Zi /FC" +set CommonCompilerFlags=/nologo /Zi /FC +@rem /WX /W4 /wd4201 /wd4100 /wd4189 /wd4244 /wd4127 /wd4456 set CudaSources=../src/cuda_entry_point.cu set Sources=../src/main.c - +set CudaLib=D:/lib/cudatoolkit/lib/x64 +set CudaSolver=%CudaLib%/cusolver.lib IF NOT EXIST .\build mkdir .\build pushd .\build -nvcc -Xcompiler %CommonCompilerFlags% -o program.exe %Sources% %CudaSources% +cl %CommonCompilerFlags% %Sources% -Feprogram.exe +@rem nvcc -Xcompiler %CommonCompilerFlags% -o program.exe %Sources% %CudaSources% -lcusolver set LastError=%ERRORLEVEL% popd diff --git a/build/.vs/ProjectSettings.json b/build/.vs/ProjectSettings.json new file mode 100644 index 0000000..0cf5ea5 --- /dev/null +++ b/build/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": "No Configurations" +} \ No newline at end of file diff --git a/build/.vs/VSWorkspaceState.json b/build/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..72fc59c --- /dev/null +++ b/build/.vs/VSWorkspaceState.json @@ -0,0 +1,7 @@ +{ + "ExpandedNodes": [ + "" + ], + "SelectedNode": "\\program.exe", + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/build/.vs/build/project-colors.json b/build/.vs/build/project-colors.json new file mode 100644 index 0000000..069efb9 --- /dev/null +++ b/build/.vs/build/project-colors.json @@ -0,0 +1,11 @@ +{ + "Version": 1, + "ProjectMap": { + "a2fe74e1-b743-11d0-ae1a-00a0c90fffc3": { + "ProjectGuid": "a2fe74e1-b743-11d0-ae1a-00a0c90fffc3", + "DisplayName": "Miscellaneous Files", + "ColorIndex": -1 + } + }, + "NextColorIndex": 0 +} \ No newline at end of file diff --git a/build/.vs/build/v17/.suo b/build/.vs/build/v17/.suo new file mode 100644 index 0000000..6fc6967 Binary files /dev/null and b/build/.vs/build/v17/.suo differ diff --git a/build/.vs/build/v17/Browse.VC.db b/build/.vs/build/v17/Browse.VC.db new file mode 100644 index 0000000..86cd8fa Binary files /dev/null and b/build/.vs/build/v17/Browse.VC.db differ diff --git a/build/.vs/slnx.sqlite b/build/.vs/slnx.sqlite new file mode 100644 index 0000000..5d9a3fc Binary files /dev/null and b/build/.vs/slnx.sqlite differ diff --git a/build/program.rdi b/build/program.rdi new file mode 100644 index 0000000..ef5c9f1 Binary files /dev/null and b/build/program.rdi differ diff --git a/build/ut b/build/ut new file mode 100644 index 0000000..e69de29 diff --git a/external/cusolver_common.h b/external/cusolver_common.h new file mode 100644 index 0000000..c8bd31e --- /dev/null +++ b/external/cusolver_common.h @@ -0,0 +1,261 @@ +/* + * Copyright 2014 NVIDIA Corporation. All rights reserved. + * + * NOTICE TO LICENSEE: + * + * This source code and/or documentation ("Licensed Deliverables") are + * subject to NVIDIA intellectual property rights under U.S. and + * international Copyright laws. + * + * These Licensed Deliverables contained herein is PROPRIETARY and + * CONFIDENTIAL to NVIDIA and is being provided under the terms and + * conditions of a form of NVIDIA software license agreement by and + * between NVIDIA and Licensee ("License Agreement") or electronically + * accepted by Licensee. Notwithstanding any terms or conditions to + * the contrary in the License Agreement, reproduction or disclosure + * of the Licensed Deliverables to any third party without the express + * written consent of NVIDIA is prohibited. + * + * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE + * LICENSE AGREEMENT, NVIDIA MAKES NO REPRESENTATION ABOUT THE + * SUITABILITY OF THESE LICENSED DELIVERABLES FOR ANY PURPOSE. IT IS + * PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. + * NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE LICENSED + * DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, + * NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. + * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE + * LICENSE AGREEMENT, IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY + * SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY + * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THESE LICENSED DELIVERABLES. + * + * U.S. Government End Users. These Licensed Deliverables are a + * "commercial item" as that term is defined at 48 C.F.R. 2.101 (OCT + * 1995), consisting of "commercial computer software" and "commercial + * computer software documentation" as such terms are used in 48 + * C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Government + * only as a commercial end item. Consistent with 48 C.F.R.12.212 and + * 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all + * U.S. Government End Users acquire the Licensed Deliverables with + * only those rights set forth herein. + * + * Any use of the Licensed Deliverables in individual and commercial + * software must include, in the user documentation and internal + * comments to the code, the above Disclaimer and U.S. Government End + * Users Notice. + */ + +#if !defined(CUSOLVER_COMMON_H_) + #define CUSOLVER_COMMON_H_ + + #include "library_types.h" + + #ifndef CUSOLVERAPI + #ifdef _WIN32 + #define CUSOLVERAPI __stdcall + #else + #define CUSOLVERAPI + #endif + #endif + + #if defined(_MSC_VER) +typedef __int64 int64_t; + #else + #include + #endif + +typedef int cusolver_int_t; + + #define CUSOLVER_VER_MAJOR 11 + #define CUSOLVER_VER_MINOR 6 + #define CUSOLVER_VER_PATCH 4 + #define CUSOLVER_VER_BUILD 38 + #define CUSOLVER_VERSION \ + (CUSOLVER_VER_MAJOR * 1000 + CUSOLVER_VER_MINOR * 100 + CUSOLVER_VER_PATCH) + +//------------------------------------------------------------------------------ + + #if !defined(_MSC_VER) + #define CUSOLVER_CPP_VERSION __cplusplus + #elif _MSC_FULL_VER >= 190024210 // Visual Studio 2015 Update 3 + #define CUSOLVER_CPP_VERSION _MSVC_LANG + #else + #define CUSOLVER_CPP_VERSION 0 + #endif + +//------------------------------------------------------------------------------ + + #if !defined(DISABLE_CUSOLVER_DEPRECATED) + + #if CUSOLVER_CPP_VERSION >= 201402L + + #define CUSOLVER_DEPRECATED(new_func) \ + [[deprecated("please use " #new_func " instead")]] + + #elif defined(_MSC_VER) + + #define CUSOLVER_DEPRECATED(new_func) \ + __declspec(deprecated("please use " #new_func " instead")) + + #elif defined(__INTEL_COMPILER) || defined(__clang__) || \ + (defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))) + + #define CUSOLVER_DEPRECATED(new_func) \ + __attribute__((deprecated("please use " #new_func " instead"))) + + #elif defined(__GNUC__) || defined(__xlc__) + + #define CUSOLVER_DEPRECATED(new_func) __attribute__((deprecated)) + + #else + + #define CUSOLVER_DEPRECATED(new_func) + + #endif // defined(__cplusplus) && __cplusplus >= 201402L + //------------------------------------------------------------------------------ + + #if CUSOLVER_CPP_VERSION >= 201703L + + #define CUSOLVER_DEPRECATED_ENUM(new_enum) \ + [[deprecated("please use " #new_enum " instead")]] + + #elif defined(__clang__) || \ + (defined(__GNUC__) && __GNUC__ >= 6 && !defined(__PGI)) + + #define CUSOLVER_DEPRECATED_ENUM(new_enum) \ + __attribute__((deprecated("please use " #new_enum " instead"))) + + #else + + #define CUSOLVER_DEPRECATED_ENUM(new_enum) + + #endif // defined(__cplusplus) && __cplusplus >= 201402L + + #else // defined(DISABLE_CUSOLVER_DEPRECATED) + + #define CUSOLVER_DEPRECATED(new_func) + #define CUSOLVER_DEPRECATED_ENUM(new_enum) + + #endif // !defined(DISABLE_CUSOLVER_DEPRECATED) + + #undef CUSOLVER_CPP_VERSION + + #if defined(__cplusplus) +extern "C" { + #endif /* __cplusplus */ + + typedef enum { + CUSOLVER_STATUS_SUCCESS = 0, + CUSOLVER_STATUS_NOT_INITIALIZED = 1, + CUSOLVER_STATUS_ALLOC_FAILED = 2, + CUSOLVER_STATUS_INVALID_VALUE = 3, + CUSOLVER_STATUS_ARCH_MISMATCH = 4, + CUSOLVER_STATUS_MAPPING_ERROR = 5, + CUSOLVER_STATUS_EXECUTION_FAILED = 6, + CUSOLVER_STATUS_INTERNAL_ERROR = 7, + CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED = 8, + CUSOLVER_STATUS_NOT_SUPPORTED = 9, + CUSOLVER_STATUS_ZERO_PIVOT = 10, + CUSOLVER_STATUS_INVALID_LICENSE = 11, + CUSOLVER_STATUS_IRS_PARAMS_NOT_INITIALIZED = 12, + CUSOLVER_STATUS_IRS_PARAMS_INVALID = 13, + CUSOLVER_STATUS_IRS_PARAMS_INVALID_PREC = 14, + CUSOLVER_STATUS_IRS_PARAMS_INVALID_REFINE = 15, + CUSOLVER_STATUS_IRS_PARAMS_INVALID_MAXITER = 16, + CUSOLVER_STATUS_IRS_INTERNAL_ERROR = 20, + CUSOLVER_STATUS_IRS_NOT_SUPPORTED = 21, + CUSOLVER_STATUS_IRS_OUT_OF_RANGE = 22, + CUSOLVER_STATUS_IRS_NRHS_NOT_SUPPORTED_FOR_REFINE_GMRES = 23, + CUSOLVER_STATUS_IRS_INFOS_NOT_INITIALIZED = 25, + CUSOLVER_STATUS_IRS_INFOS_NOT_DESTROYED = 26, + CUSOLVER_STATUS_IRS_MATRIX_SINGULAR = 30, + CUSOLVER_STATUS_INVALID_WORKSPACE = 31 + } cusolverStatus_t; + + typedef enum { + CUSOLVER_EIG_TYPE_1 = 1, + CUSOLVER_EIG_TYPE_2 = 2, + CUSOLVER_EIG_TYPE_3 = 3 + } cusolverEigType_t; + + typedef enum { + CUSOLVER_EIG_MODE_NOVECTOR = 0, + CUSOLVER_EIG_MODE_VECTOR = 1 + } cusolverEigMode_t; + + typedef enum { + CUSOLVER_EIG_RANGE_ALL = 1001, + CUSOLVER_EIG_RANGE_I = 1002, + CUSOLVER_EIG_RANGE_V = 1003, + } cusolverEigRange_t; + + typedef enum { + CUSOLVER_INF_NORM = 104, + CUSOLVER_MAX_NORM = 105, + CUSOLVER_ONE_NORM = 106, + CUSOLVER_FRO_NORM = 107, + } cusolverNorm_t; + + typedef enum { + CUSOLVER_IRS_REFINE_NOT_SET = 1100, + CUSOLVER_IRS_REFINE_NONE = 1101, + CUSOLVER_IRS_REFINE_CLASSICAL = 1102, + CUSOLVER_IRS_REFINE_CLASSICAL_GMRES = 1103, + CUSOLVER_IRS_REFINE_GMRES = 1104, + CUSOLVER_IRS_REFINE_GMRES_GMRES = 1105, + CUSOLVER_IRS_REFINE_GMRES_NOPCOND = 1106, + + CUSOLVER_PREC_DD = 1150, + CUSOLVER_PREC_SS = 1151, + CUSOLVER_PREC_SHT = 1152, + + } cusolverIRSRefinement_t; + + typedef enum { + CUSOLVER_R_8I = 1201, + CUSOLVER_R_8U = 1202, + CUSOLVER_R_64F = 1203, + CUSOLVER_R_32F = 1204, + CUSOLVER_R_16F = 1205, + CUSOLVER_R_16BF = 1206, + CUSOLVER_R_TF32 = 1207, + CUSOLVER_R_AP = 1208, + CUSOLVER_C_8I = 1211, + CUSOLVER_C_8U = 1212, + CUSOLVER_C_64F = 1213, + CUSOLVER_C_32F = 1214, + CUSOLVER_C_16F = 1215, + CUSOLVER_C_16BF = 1216, + CUSOLVER_C_TF32 = 1217, + CUSOLVER_C_AP = 1218, + } cusolverPrecType_t; + + typedef enum { + CUSOLVER_ALG_0 = 0, /* default algorithm */ + CUSOLVER_ALG_1 = 1, + CUSOLVER_ALG_2 = 2 + } cusolverAlgMode_t; + + typedef enum { + CUBLAS_STOREV_COLUMNWISE = 0, + CUBLAS_STOREV_ROWWISE = 1 + } cusolverStorevMode_t; + + typedef enum { + CUBLAS_DIRECT_FORWARD = 0, + CUBLAS_DIRECT_BACKWARD = 1 + } cusolverDirectMode_t; + + cusolverStatus_t CUSOLVERAPI + cusolverGetProperty(libraryPropertyType type, int *value); + + cusolverStatus_t CUSOLVERAPI cusolverGetVersion(int *version); + + #if defined(__cplusplus) +} + #endif /* __cplusplus */ + +#endif // CUSOLVER_COMMON_H_ diff --git a/out/grid.bin b/out/grid.bin new file mode 100644 index 0000000..a6ba9ad Binary files /dev/null and b/out/grid.bin differ diff --git a/out/grid.dat b/out/grid.dat new file mode 100644 index 0000000..8a3f38d --- /dev/null +++ b/out/grid.dat @@ -0,0 +1,1000 @@ + 0.000000e+00 + 1.000000e-02 + 2.000000e-02 + 3.000000e-02 + 4.000000e-02 + 5.000000e-02 + 6.000000e-02 + 7.000000e-02 + 8.000000e-02 + 9.000000e-02 + 1.000000e-01 + 1.100000e-01 + 1.200000e-01 + 1.300000e-01 + 1.400000e-01 + 1.500000e-01 + 1.600000e-01 + 1.700000e-01 + 1.800000e-01 + 1.900000e-01 + 2.000000e-01 + 2.100000e-01 + 2.200000e-01 + 2.300000e-01 + 2.400000e-01 + 2.500000e-01 + 2.600000e-01 + 2.700000e-01 + 2.800000e-01 + 2.900000e-01 + 3.000000e-01 + 3.100000e-01 + 3.200000e-01 + 3.300000e-01 + 3.400000e-01 + 3.500000e-01 + 3.600000e-01 + 3.700000e-01 + 3.800000e-01 + 3.900000e-01 + 4.000000e-01 + 4.100000e-01 + 4.200000e-01 + 4.300000e-01 + 4.400000e-01 + 4.500000e-01 + 4.600000e-01 + 4.700000e-01 + 4.800000e-01 + 4.900000e-01 + 5.000000e-01 + 5.100000e-01 + 5.200000e-01 + 5.300000e-01 + 5.400000e-01 + 5.500000e-01 + 5.600000e-01 + 5.700000e-01 + 5.800000e-01 + 5.900000e-01 + 6.000000e-01 + 6.100000e-01 + 6.200000e-01 + 6.300000e-01 + 6.400000e-01 + 6.500000e-01 + 6.600000e-01 + 6.700000e-01 + 6.800000e-01 + 6.900000e-01 + 7.000000e-01 + 7.100000e-01 + 7.200000e-01 + 7.300000e-01 + 7.400000e-01 + 7.500000e-01 + 7.600000e-01 + 7.700000e-01 + 7.800000e-01 + 7.900000e-01 + 8.000000e-01 + 8.100000e-01 + 8.200000e-01 + 8.300000e-01 + 8.400000e-01 + 8.500000e-01 + 8.600000e-01 + 8.700000e-01 + 8.800000e-01 + 8.900000e-01 + 9.000000e-01 + 9.100000e-01 + 9.200000e-01 + 9.300000e-01 + 9.400000e-01 + 9.500000e-01 + 9.600000e-01 + 9.700000e-01 + 9.800000e-01 + 9.900000e-01 + 1.000000e+00 + 1.010000e+00 + 1.020000e+00 + 1.030000e+00 + 1.040000e+00 + 1.050000e+00 + 1.060000e+00 + 1.070000e+00 + 1.080000e+00 + 1.090000e+00 + 1.100000e+00 + 1.110000e+00 + 1.120000e+00 + 1.130000e+00 + 1.140000e+00 + 1.150000e+00 + 1.160000e+00 + 1.170000e+00 + 1.180000e+00 + 1.190000e+00 + 1.200000e+00 + 1.210000e+00 + 1.220000e+00 + 1.230000e+00 + 1.240000e+00 + 1.250000e+00 + 1.260000e+00 + 1.270000e+00 + 1.280000e+00 + 1.290000e+00 + 1.300000e+00 + 1.310000e+00 + 1.320000e+00 + 1.330000e+00 + 1.340000e+00 + 1.350000e+00 + 1.360000e+00 + 1.370000e+00 + 1.380000e+00 + 1.390000e+00 + 1.400000e+00 + 1.410000e+00 + 1.420000e+00 + 1.430000e+00 + 1.440000e+00 + 1.450000e+00 + 1.460000e+00 + 1.470000e+00 + 1.480000e+00 + 1.490000e+00 + 1.500000e+00 + 1.510000e+00 + 1.520000e+00 + 1.530000e+00 + 1.540000e+00 + 1.550000e+00 + 1.560000e+00 + 1.570000e+00 + 1.580000e+00 + 1.590000e+00 + 1.600000e+00 + 1.610000e+00 + 1.620000e+00 + 1.630000e+00 + 1.640000e+00 + 1.650000e+00 + 1.660000e+00 + 1.670000e+00 + 1.680000e+00 + 1.690000e+00 + 1.700000e+00 + 1.710000e+00 + 1.720000e+00 + 1.730000e+00 + 1.740000e+00 + 1.750000e+00 + 1.760000e+00 + 1.770000e+00 + 1.780000e+00 + 1.790000e+00 + 1.800000e+00 + 1.810000e+00 + 1.820000e+00 + 1.830000e+00 + 1.840000e+00 + 1.850000e+00 + 1.860000e+00 + 1.870000e+00 + 1.880000e+00 + 1.890000e+00 + 1.900000e+00 + 1.910000e+00 + 1.920000e+00 + 1.930000e+00 + 1.940000e+00 + 1.950000e+00 + 1.960000e+00 + 1.970000e+00 + 1.980000e+00 + 1.990000e+00 + 2.000000e+00 + 2.010000e+00 + 2.020000e+00 + 2.030000e+00 + 2.040000e+00 + 2.050000e+00 + 2.060000e+00 + 2.070000e+00 + 2.080000e+00 + 2.090000e+00 + 2.100000e+00 + 2.110000e+00 + 2.120000e+00 + 2.130000e+00 + 2.140000e+00 + 2.150000e+00 + 2.160000e+00 + 2.170000e+00 + 2.180000e+00 + 2.190000e+00 + 2.200000e+00 + 2.210000e+00 + 2.220000e+00 + 2.230000e+00 + 2.240000e+00 + 2.250000e+00 + 2.260000e+00 + 2.270000e+00 + 2.280000e+00 + 2.290000e+00 + 2.300000e+00 + 2.310000e+00 + 2.320000e+00 + 2.330000e+00 + 2.340000e+00 + 2.350000e+00 + 2.360000e+00 + 2.370000e+00 + 2.380000e+00 + 2.390000e+00 + 2.400000e+00 + 2.410000e+00 + 2.420000e+00 + 2.430000e+00 + 2.440000e+00 + 2.450000e+00 + 2.460000e+00 + 2.470000e+00 + 2.480000e+00 + 2.490000e+00 + 2.500000e+00 + 2.510000e+00 + 2.520000e+00 + 2.530000e+00 + 2.540000e+00 + 2.550000e+00 + 2.560000e+00 + 2.570000e+00 + 2.580000e+00 + 2.590000e+00 + 2.600000e+00 + 2.610000e+00 + 2.620000e+00 + 2.630000e+00 + 2.640000e+00 + 2.650000e+00 + 2.660000e+00 + 2.670000e+00 + 2.680000e+00 + 2.690000e+00 + 2.700000e+00 + 2.710000e+00 + 2.720000e+00 + 2.730000e+00 + 2.740000e+00 + 2.750000e+00 + 2.760000e+00 + 2.770000e+00 + 2.780000e+00 + 2.790000e+00 + 2.800000e+00 + 2.810000e+00 + 2.820000e+00 + 2.830000e+00 + 2.840000e+00 + 2.850000e+00 + 2.860000e+00 + 2.870000e+00 + 2.880000e+00 + 2.890000e+00 + 2.900000e+00 + 2.910000e+00 + 2.920000e+00 + 2.930000e+00 + 2.940000e+00 + 2.950000e+00 + 2.960000e+00 + 2.970000e+00 + 2.980000e+00 + 2.990000e+00 + 3.000000e+00 + 3.010000e+00 + 3.020000e+00 + 3.030000e+00 + 3.040000e+00 + 3.050000e+00 + 3.060000e+00 + 3.070000e+00 + 3.080000e+00 + 3.090000e+00 + 3.100000e+00 + 3.110000e+00 + 3.120000e+00 + 3.130000e+00 + 3.140000e+00 + 3.150000e+00 + 3.160000e+00 + 3.170000e+00 + 3.180000e+00 + 3.190000e+00 + 3.200000e+00 + 3.210000e+00 + 3.220000e+00 + 3.230000e+00 + 3.240000e+00 + 3.250000e+00 + 3.260000e+00 + 3.270000e+00 + 3.280000e+00 + 3.290000e+00 + 3.300000e+00 + 3.310000e+00 + 3.320000e+00 + 3.330000e+00 + 3.340000e+00 + 3.350000e+00 + 3.360000e+00 + 3.370000e+00 + 3.380000e+00 + 3.390000e+00 + 3.400000e+00 + 3.410000e+00 + 3.420000e+00 + 3.430000e+00 + 3.440000e+00 + 3.450000e+00 + 3.460000e+00 + 3.470000e+00 + 3.480000e+00 + 3.490000e+00 + 3.500000e+00 + 3.510000e+00 + 3.520000e+00 + 3.530000e+00 + 3.540000e+00 + 3.550000e+00 + 3.560000e+00 + 3.570000e+00 + 3.580000e+00 + 3.590000e+00 + 3.600000e+00 + 3.610000e+00 + 3.620000e+00 + 3.630000e+00 + 3.640000e+00 + 3.650000e+00 + 3.660000e+00 + 3.670000e+00 + 3.680000e+00 + 3.690000e+00 + 3.700000e+00 + 3.710000e+00 + 3.720000e+00 + 3.730000e+00 + 3.740000e+00 + 3.750000e+00 + 3.760000e+00 + 3.770000e+00 + 3.780000e+00 + 3.790000e+00 + 3.800000e+00 + 3.810000e+00 + 3.820000e+00 + 3.830000e+00 + 3.840000e+00 + 3.850000e+00 + 3.860000e+00 + 3.870000e+00 + 3.880000e+00 + 3.890000e+00 + 3.900000e+00 + 3.910000e+00 + 3.920000e+00 + 3.930000e+00 + 3.940000e+00 + 3.950000e+00 + 3.960000e+00 + 3.970000e+00 + 3.980000e+00 + 3.990000e+00 + 4.000000e+00 + 4.010000e+00 + 4.020000e+00 + 4.030000e+00 + 4.040000e+00 + 4.050000e+00 + 4.060000e+00 + 4.070000e+00 + 4.080000e+00 + 4.090000e+00 + 4.100000e+00 + 4.110000e+00 + 4.120000e+00 + 4.130000e+00 + 4.140000e+00 + 4.150000e+00 + 4.160000e+00 + 4.170000e+00 + 4.180000e+00 + 4.190000e+00 + 4.200000e+00 + 4.210000e+00 + 4.220000e+00 + 4.230000e+00 + 4.240000e+00 + 4.250000e+00 + 4.260000e+00 + 4.270000e+00 + 4.280000e+00 + 4.290000e+00 + 4.300000e+00 + 4.310000e+00 + 4.320000e+00 + 4.330000e+00 + 4.340000e+00 + 4.350000e+00 + 4.360000e+00 + 4.370000e+00 + 4.380000e+00 + 4.390000e+00 + 4.400000e+00 + 4.410000e+00 + 4.420000e+00 + 4.430000e+00 + 4.440000e+00 + 4.450000e+00 + 4.460000e+00 + 4.470000e+00 + 4.480000e+00 + 4.490000e+00 + 4.500000e+00 + 4.510000e+00 + 4.520000e+00 + 4.530000e+00 + 4.540000e+00 + 4.550000e+00 + 4.560000e+00 + 4.570000e+00 + 4.580000e+00 + 4.590000e+00 + 4.600000e+00 + 4.610000e+00 + 4.620000e+00 + 4.630000e+00 + 4.640000e+00 + 4.650000e+00 + 4.660000e+00 + 4.670000e+00 + 4.680000e+00 + 4.690000e+00 + 4.700000e+00 + 4.710000e+00 + 4.720000e+00 + 4.730000e+00 + 4.740000e+00 + 4.750000e+00 + 4.760000e+00 + 4.770000e+00 + 4.780000e+00 + 4.790000e+00 + 4.800000e+00 + 4.810000e+00 + 4.820000e+00 + 4.830000e+00 + 4.840000e+00 + 4.850000e+00 + 4.860000e+00 + 4.870000e+00 + 4.880000e+00 + 4.890000e+00 + 4.900000e+00 + 4.910000e+00 + 4.920000e+00 + 4.930000e+00 + 4.940000e+00 + 4.950000e+00 + 4.960000e+00 + 4.970000e+00 + 4.980000e+00 + 4.990000e+00 + 5.000000e+00 + 5.010000e+00 + 5.020000e+00 + 5.030000e+00 + 5.040000e+00 + 5.050000e+00 + 5.060000e+00 + 5.070000e+00 + 5.080000e+00 + 5.090000e+00 + 5.100000e+00 + 5.110000e+00 + 5.120000e+00 + 5.130000e+00 + 5.140000e+00 + 5.150000e+00 + 5.160000e+00 + 5.170000e+00 + 5.180000e+00 + 5.190000e+00 + 5.200000e+00 + 5.210000e+00 + 5.220000e+00 + 5.230000e+00 + 5.240000e+00 + 5.250000e+00 + 5.260000e+00 + 5.270000e+00 + 5.280000e+00 + 5.290000e+00 + 5.300000e+00 + 5.310000e+00 + 5.320000e+00 + 5.330000e+00 + 5.340000e+00 + 5.350000e+00 + 5.360000e+00 + 5.370000e+00 + 5.380000e+00 + 5.390000e+00 + 5.400000e+00 + 5.410000e+00 + 5.420000e+00 + 5.430000e+00 + 5.440000e+00 + 5.450000e+00 + 5.460000e+00 + 5.470000e+00 + 5.480000e+00 + 5.490000e+00 + 5.500000e+00 + 5.510000e+00 + 5.520000e+00 + 5.530000e+00 + 5.540000e+00 + 5.550000e+00 + 5.560000e+00 + 5.570000e+00 + 5.580000e+00 + 5.590000e+00 + 5.600000e+00 + 5.610000e+00 + 5.620000e+00 + 5.630000e+00 + 5.640000e+00 + 5.650000e+00 + 5.660000e+00 + 5.670000e+00 + 5.680000e+00 + 5.690000e+00 + 5.700000e+00 + 5.710000e+00 + 5.720000e+00 + 5.730000e+00 + 5.740000e+00 + 5.750000e+00 + 5.760000e+00 + 5.770000e+00 + 5.780000e+00 + 5.790000e+00 + 5.800000e+00 + 5.810000e+00 + 5.820000e+00 + 5.830000e+00 + 5.840000e+00 + 5.850000e+00 + 5.860000e+00 + 5.870000e+00 + 5.880000e+00 + 5.890000e+00 + 5.900000e+00 + 5.910000e+00 + 5.920000e+00 + 5.930000e+00 + 5.940000e+00 + 5.950000e+00 + 5.960000e+00 + 5.970000e+00 + 5.980000e+00 + 5.990000e+00 + 6.000000e+00 + 6.010000e+00 + 6.020000e+00 + 6.030000e+00 + 6.040000e+00 + 6.050000e+00 + 6.060000e+00 + 6.070000e+00 + 6.080000e+00 + 6.090000e+00 + 6.100000e+00 + 6.110000e+00 + 6.120000e+00 + 6.130000e+00 + 6.140000e+00 + 6.150000e+00 + 6.160000e+00 + 6.170000e+00 + 6.180000e+00 + 6.190000e+00 + 6.200000e+00 + 6.210000e+00 + 6.220000e+00 + 6.230000e+00 + 6.240000e+00 + 6.250000e+00 + 6.260000e+00 + 6.270000e+00 + 6.280000e+00 + 6.290000e+00 + 6.300000e+00 + 6.310000e+00 + 6.320000e+00 + 6.330000e+00 + 6.340000e+00 + 6.350000e+00 + 6.360000e+00 + 6.370000e+00 + 6.380000e+00 + 6.390000e+00 + 6.400000e+00 + 6.410000e+00 + 6.420000e+00 + 6.430000e+00 + 6.440000e+00 + 6.450000e+00 + 6.460000e+00 + 6.470000e+00 + 6.480000e+00 + 6.490000e+00 + 6.500000e+00 + 6.510000e+00 + 6.520000e+00 + 6.530000e+00 + 6.540000e+00 + 6.550000e+00 + 6.560000e+00 + 6.570000e+00 + 6.580000e+00 + 6.590000e+00 + 6.600000e+00 + 6.610000e+00 + 6.620000e+00 + 6.630000e+00 + 6.640000e+00 + 6.650000e+00 + 6.660000e+00 + 6.670000e+00 + 6.680000e+00 + 6.690000e+00 + 6.700000e+00 + 6.710000e+00 + 6.720000e+00 + 6.730000e+00 + 6.740000e+00 + 6.750000e+00 + 6.760000e+00 + 6.770000e+00 + 6.780000e+00 + 6.790000e+00 + 6.800000e+00 + 6.810000e+00 + 6.820000e+00 + 6.830000e+00 + 6.840000e+00 + 6.850000e+00 + 6.860000e+00 + 6.870000e+00 + 6.880000e+00 + 6.890000e+00 + 6.900000e+00 + 6.910000e+00 + 6.920000e+00 + 6.930000e+00 + 6.940000e+00 + 6.950000e+00 + 6.960000e+00 + 6.970000e+00 + 6.980000e+00 + 6.990000e+00 + 7.000000e+00 + 7.010000e+00 + 7.020000e+00 + 7.030000e+00 + 7.040000e+00 + 7.050000e+00 + 7.060000e+00 + 7.070000e+00 + 7.080000e+00 + 7.090000e+00 + 7.100000e+00 + 7.110000e+00 + 7.120000e+00 + 7.130000e+00 + 7.140000e+00 + 7.150000e+00 + 7.160000e+00 + 7.170000e+00 + 7.180000e+00 + 7.190000e+00 + 7.200000e+00 + 7.210000e+00 + 7.220000e+00 + 7.230000e+00 + 7.240000e+00 + 7.250000e+00 + 7.260000e+00 + 7.270000e+00 + 7.280000e+00 + 7.290000e+00 + 7.300000e+00 + 7.310000e+00 + 7.320000e+00 + 7.330000e+00 + 7.340000e+00 + 7.350000e+00 + 7.360000e+00 + 7.370000e+00 + 7.380000e+00 + 7.390000e+00 + 7.400000e+00 + 7.410000e+00 + 7.420000e+00 + 7.430000e+00 + 7.440000e+00 + 7.450000e+00 + 7.460000e+00 + 7.470000e+00 + 7.480000e+00 + 7.490000e+00 + 7.500000e+00 + 7.510000e+00 + 7.520000e+00 + 7.530000e+00 + 7.540000e+00 + 7.550000e+00 + 7.560000e+00 + 7.570000e+00 + 7.580000e+00 + 7.590000e+00 + 7.600000e+00 + 7.610000e+00 + 7.620000e+00 + 7.630000e+00 + 7.640000e+00 + 7.650000e+00 + 7.660000e+00 + 7.670000e+00 + 7.680000e+00 + 7.690000e+00 + 7.700000e+00 + 7.710000e+00 + 7.720000e+00 + 7.730000e+00 + 7.740000e+00 + 7.750000e+00 + 7.760000e+00 + 7.770000e+00 + 7.780000e+00 + 7.790000e+00 + 7.800000e+00 + 7.810000e+00 + 7.820000e+00 + 7.830000e+00 + 7.840000e+00 + 7.850000e+00 + 7.860000e+00 + 7.870000e+00 + 7.880000e+00 + 7.890000e+00 + 7.900000e+00 + 7.910000e+00 + 7.920000e+00 + 7.930000e+00 + 7.940000e+00 + 7.950000e+00 + 7.960000e+00 + 7.970000e+00 + 7.980000e+00 + 7.990000e+00 + 8.000000e+00 + 8.010000e+00 + 8.020000e+00 + 8.030000e+00 + 8.040000e+00 + 8.050000e+00 + 8.060000e+00 + 8.070000e+00 + 8.080000e+00 + 8.090000e+00 + 8.100000e+00 + 8.110000e+00 + 8.120000e+00 + 8.130000e+00 + 8.140000e+00 + 8.150000e+00 + 8.160000e+00 + 8.170000e+00 + 8.180000e+00 + 8.190000e+00 + 8.200000e+00 + 8.210000e+00 + 8.220000e+00 + 8.230000e+00 + 8.240000e+00 + 8.250000e+00 + 8.260000e+00 + 8.270000e+00 + 8.280000e+00 + 8.290000e+00 + 8.300000e+00 + 8.310000e+00 + 8.320000e+00 + 8.330000e+00 + 8.340000e+00 + 8.350000e+00 + 8.360000e+00 + 8.370000e+00 + 8.380000e+00 + 8.390000e+00 + 8.400000e+00 + 8.410000e+00 + 8.420000e+00 + 8.430000e+00 + 8.440000e+00 + 8.450000e+00 + 8.460000e+00 + 8.470000e+00 + 8.480000e+00 + 8.490000e+00 + 8.500000e+00 + 8.510000e+00 + 8.520000e+00 + 8.530000e+00 + 8.540000e+00 + 8.550000e+00 + 8.560000e+00 + 8.570000e+00 + 8.580000e+00 + 8.590000e+00 + 8.600000e+00 + 8.610000e+00 + 8.620000e+00 + 8.630000e+00 + 8.640000e+00 + 8.650000e+00 + 8.660000e+00 + 8.670000e+00 + 8.680000e+00 + 8.690000e+00 + 8.700000e+00 + 8.710000e+00 + 8.720000e+00 + 8.730000e+00 + 8.740000e+00 + 8.750000e+00 + 8.760000e+00 + 8.770000e+00 + 8.780000e+00 + 8.790000e+00 + 8.800000e+00 + 8.810000e+00 + 8.820000e+00 + 8.830000e+00 + 8.840000e+00 + 8.850000e+00 + 8.860000e+00 + 8.870000e+00 + 8.880000e+00 + 8.890000e+00 + 8.900000e+00 + 8.910000e+00 + 8.920000e+00 + 8.930000e+00 + 8.940000e+00 + 8.950000e+00 + 8.960000e+00 + 8.970000e+00 + 8.980000e+00 + 8.990000e+00 + 9.000000e+00 + 9.010000e+00 + 9.020000e+00 + 9.030000e+00 + 9.040000e+00 + 9.050000e+00 + 9.060000e+00 + 9.070000e+00 + 9.080000e+00 + 9.090000e+00 + 9.100000e+00 + 9.110000e+00 + 9.120000e+00 + 9.130000e+00 + 9.140000e+00 + 9.150000e+00 + 9.160000e+00 + 9.170000e+00 + 9.180000e+00 + 9.190000e+00 + 9.200000e+00 + 9.210000e+00 + 9.220000e+00 + 9.230000e+00 + 9.240000e+00 + 9.250000e+00 + 9.260000e+00 + 9.270000e+00 + 9.280000e+00 + 9.290000e+00 + 9.300000e+00 + 9.310000e+00 + 9.320000e+00 + 9.330000e+00 + 9.340000e+00 + 9.350000e+00 + 9.360000e+00 + 9.370000e+00 + 9.380000e+00 + 9.390000e+00 + 9.400000e+00 + 9.410000e+00 + 9.420000e+00 + 9.430000e+00 + 9.440000e+00 + 9.450000e+00 + 9.460000e+00 + 9.470000e+00 + 9.480000e+00 + 9.490000e+00 + 9.500000e+00 + 9.510000e+00 + 9.520000e+00 + 9.530000e+00 + 9.540000e+00 + 9.550000e+00 + 9.560000e+00 + 9.570000e+00 + 9.580000e+00 + 9.590000e+00 + 9.600000e+00 + 9.610000e+00 + 9.620000e+00 + 9.630000e+00 + 9.640000e+00 + 9.650000e+00 + 9.660000e+00 + 9.670000e+00 + 9.680000e+00 + 9.690000e+00 + 9.700000e+00 + 9.710000e+00 + 9.720000e+00 + 9.730000e+00 + 9.740000e+00 + 9.750000e+00 + 9.760000e+00 + 9.770000e+00 + 9.780000e+00 + 9.790000e+00 + 9.800000e+00 + 9.810000e+00 + 9.820000e+00 + 9.830000e+00 + 9.840000e+00 + 9.850000e+00 + 9.860000e+00 + 9.870000e+00 + 9.880000e+00 + 9.890000e+00 + 9.900000e+00 + 9.910000e+00 + 9.920000e+00 + 9.930000e+00 + 9.940000e+00 + 9.950000e+00 + 9.960000e+00 + 9.970000e+00 + 9.980000e+00 + 1.000000e+01 diff --git a/py_notebook/.ipynb_checkpoints/EigsolGPU_test-checkpoint.ipynb b/py_notebook/.ipynb_checkpoints/EigsolGPU_test-checkpoint.ipynb new file mode 100644 index 0000000..d42c265 --- /dev/null +++ b/py_notebook/.ipynb_checkpoints/EigsolGPU_test-checkpoint.ipynb @@ -0,0 +1,33 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "1d08e1d3-0f62-467e-8217-9eaf458afeb4", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/py_notebook/EigsolGPU_test.ipynb b/py_notebook/EigsolGPU_test.ipynb new file mode 100644 index 0000000..bad0722 --- /dev/null +++ b/py_notebook/EigsolGPU_test.ipynb @@ -0,0 +1,90 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "id": "1d08e1d3-0f62-467e-8217-9eaf458afeb4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import numpy as np\n", + "from matplotlib import pyplot as plt\n", + "\n", + "x = np.linspace(0, 2*2.0*np.pi, 1000)\n", + "y = np.sin(x)\n", + "\n", + "\n", + "grid_bin = np.fromfile(\"../out/grid.bin\", dtype=np.float64)\n", + "plt.plot(grid_bin, grid_bin)\n", + "grid = np.loadtxt(\"../out/grid.dat\")\n", + "plt.plot(grid, grid, linestyle='--')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8cda5f82-13ac-4b95-aed4-f999a8dbd185", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ce5642b3-6387-45f7-aaaf-dfb9085b3d49", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4866585-9cb8-4eb8-a8c6-0489f831c55d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/base/base_context_cracking.h b/src/base/base_context_cracking.h new file mode 100644 index 0000000..f3ed4d6 --- /dev/null +++ b/src/base/base_context_cracking.h @@ -0,0 +1,178 @@ +#ifndef BASE_CONTEXT_CRACKING_H +#define BASE_CONTEXT_CRACKING_H + +// NOTE(antonl): +// This header is used for "context cracking", ie figuring out compile time context things like +// platform etc. + +// For now this is just copy pasted from RJFs layer, and probably that's all that's needed. + + +/////////////////////////////////////////////// +//~ MSVC extraction + +#if defined(_MSC_VER) + +# define COMPILER_MSVC 1 + +# if defined(_WIN32) +# define OS_WINDOWS 1 +# else +# error _MSC_VER is defined, but _WIN32 is not. This setup is not supported. +# endif + +# if defined(_M_AMD64) +# define ARCH_X64 1 +# elif defined(_M_IX86) +# define ARCH_X86 1 +# elif defined(_M_ARM64) +# define ARCH_ARM64 1 +# elif defined(_M_ARM) +# define ARCH_ARM32 1 +# else +# error Target architecture is not supported. _MSC_VER is defined, but one of {_M_AMD64, _M_IX86, _M_ARM64, _M_ARM} is not. +# endif + +#if _MSC_VER >= 1920 +#define COMPILER_MSVC_YEAR 2019 +#elif _MSC_VER >= 1910 +#define COMPILER_MSVC_YEAR 2017 +#elif _MSC_VER >= 1900 +#define COMPILER_MSVC_YEAR 2015 +#elif _MSC_VER >= 1800 +#define COMPILER_MSVC_YEAR 2013 +#elif _MSC_VER >= 1700 +#define COMPILER_MSVC_YEAR 2012 +#elif _MSC_VER >= 1600 +#define COMPILER_MSVC_YEAR 2010 +#elif _MSC_VER >= 1500 +#define COMPILER_MSVC_YEAR 2008 +#elif _MSC_VER >= 1400 +#define COMPILER_MSVC_YEAR 2005 +#else +#define COMPILER_MSVC_YEAR 0 +#endif + +//////////////////////////////// +//~ rjf: Clang Extraction + +#elif defined(__clang__) + +# define COMPILER_CLANG 1 + +# if defined(__APPLE__) && defined(__MACH__) +# define OS_MAC 1 +# elif defined(__gnu_linux__) +# define OS_LINUX 1 +# else +# error __clang__ is defined, but one of {__APPLE__, __gnu_linux__} is not. This setup is not supported. +# endif + +# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) +# define ARCH_X64 1 +# elif defined(i386) || defined(__i386) || defined(__i386__) +# define ARCH_X86 1 +# elif defined(__aarch64__) +# define ARCH_ARM64 1 +# elif defined(__arm__) +# define ARCH_ARM32 1 +# else +# error Target architecture is not supported. __clang__ is defined, but one of {__amd64__, __amd64, __x86_64__, __x86_64, i386, __i386, __i386__, __aarch64__, __arm__} is not. +# endif + +//////////////////////////////// +//~ rjf: GCC Extraction + +#elif defined(__GNUC__) || defined(__GNUG__) + +# define COMPILER_GCC 1 + +# if defined(__gnu_linux__) +# define OS_LINUX 1 +# else +# error __GNUC__ or __GNUG__ is defined, but __gnu_linux__ is not. This setup is not supported. +# endif + +# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) +# define ARCH_X64 1 +# elif defined(i386) || defined(__i386) || defined(__i386__) +# define ARCH_X86 1 +# elif defined(__aarch64__) +# define ARCH_ARM64 1 +# elif defined(__arm__) +# define ARCH_ARM32 1 +# else +# error Target architecture is not supported. __GNU_C__ or __GNUG__ is defined, but one of {__amd64__, __amd64, __x86_64__, __x86_64, i386, __i386, __i386__, __aarch64__, __arm__} is not. +# endif + +#else +# error Compiler is not supported. _MSC_VER, __clang__, __GNUC__, or __GNUG__ must be defined. +#endif + +#if defined(ARCH_X64) +# define ARCH_64BIT 1 +#elif defined(ARCH_X86) +# define ARCH_32BIT 1 + +#endif + +//////////////////////////////// +//~ rjf: Language + +#if defined(__cplusplus) +# define LANG_CPP 1 +#else +# define LANG_C 1 +#endif + +//////////////////////////////// +//~ rjf: Zero + +#if !defined(ARCH_32BIT) +# define ARCH_32BIT 0 +#endif +#if !defined(ARCH_64BIT) +# define ARCH_64BIT 0 +#endif +#if !defined(ARCH_X64) +# define ARCH_X64 0 +#endif +#if !defined(ARCH_X86) +# define ARCH_X86 0 +#endif +#if !defined(ARCH_ARM64) +# define ARCH_ARM64 0 +#endif +#if !defined(ARCH_ARM32) +# define ARCH_ARM32 0 +#endif +#if !defined(COMPILER_MSVC) +# define COMPILER_MSVC 0 +#endif +#if !defined(COMPILER_GCC) +# define COMPILER_GCC 0 +#endif +#if !defined(COMPILER_CLANG) +# define COMPILER_CLANG 0 +#endif +#if !defined(OS_WINDOWS) +# define OS_WINDOWS 0 +#endif +#if !defined(OS_LINUX) +# define OS_LINUX 0 +#endif +#if !defined(OS_MAC) +# define OS_MAC 0 +#endif +#if !defined(LANG_CPP) +# define LANG_CPP 0 +#endif +#if !defined(LANG_C) +# define LANG_C 0 +#endif + +// TODO(antonl); +// Build options context cracking, need to figure out what we should use here first. +#define BUILD_DEBUG 1 + +#endif /* BASE_CONTEXT_CRACKING_H */ diff --git a/src/base/base_core.h b/src/base/base_core.h new file mode 100644 index 0000000..91fd56f --- /dev/null +++ b/src/base/base_core.h @@ -0,0 +1,294 @@ +#ifndef BASE_TYPES_H +#define BASE_TYPES_H + +#include +#include +#include + +///////////////////////// +//~ Macros + +///////////////////////// +//- Linking keywords + +// TODO(anton): Understand this, yoinked from rjf's layer. +#if LANG_CPP +# define no_name_mangle extern "C" +#else +# define no_name_mangle +#endif + +// TODO(anton): OS_WINDOWS dll import/export macros + +///////////////////////// +//- Keywords +// Static is stupid and means different things depending on context in C and C++. +// These defines increases readability. +#define function static // Function internal to compilation unit. +#define local_persist static +#define global static +#define fallthrough // for use in switch statements, for clarity.. + +// TODO(anton): Understand and add good comment on this. +#if LANG_CPP +# define root_global no_name_mangle +# define root_function function +#else +# define root_global extern +# define root_function function +#endif + +#define inline_function inline static + +#if OS_WINDOWS +# pragma section(".roglob", read) +# define read_only __declspec(allocate(".roglob")) +#else +# define read_only +#endif + +#if COMPILER_MSVC +# define per_thread __declspec(thread) +#else +# error Thread keyword not abstracted on compiler. +#endif + +///////////////////////// +//- Memory operations +// It's nice to put these in macros, so we can swap out the functionality from standard library, eventually. +#define MemoryCopy memcpy +#define MemoryMove memmove +#define MemorySet memset + +// NOTE(anton): This gives a 4127 compiler warning for the sizeof conditional. This should be ignored +#define MemoryCopyStruct(dst, src) do { Assert(sizeof(*(dst)) == sizeof(*(src))); MemoryCopy((dst), (src), sizeof(*(dst))); } while(0) + +#define MemoryZero(ptr, size) MemorySet((ptr), 0, (size)) +#define MemoryZeroStruct(ptr) MemoryZero((ptr), sizeof(*(ptr))) +#define MemoryZeroArray(arr) MemoryZero((arr), sizeof(arr)) + +///////////////////////// +//- Integer/pointer/array/type manipulations + +#define ArrayCount(a) (sizeof(a) / sizeof((a)[0])) +#define IntFromPtr(p) (U64)(((U8*)p) - 0) +#define PtrFromInt(i) (void*)(((U8*)0) + i) +#define Member(type, member_name) ((type *)0)->member_name +// TODO(anton): Understand why this becomes offset actually +#define OffsetOf(type, member_name) IntFromPtr(&Member(type, member_name)) +// TODO(anton): Understand this +#define BaseFromMember(type, member_name, ptr) (type *)((U8 *)(ptr) - OffsetOf(type, member_name)) + +#define Bytes(n) (n) +#define Kilobytes(n) (n << 10) // 2^10 == 1024 etc +#define Megabytes(n) (n << 20) +#define Gigabytes(n) (((U64)n) << 30) +#define Terabytes(n) (((U64)n) << 40) + +#define Thousand(n) ((n)*1000) +#define Million(n) ((n)*1000000) +#define Billion(n) ((n)*1000000000LL) + +#define AbsoluteValueU64(x) (U64)llabs((U64)(x)) + +///////////////////////// +//- Linked list helpers + +#define CheckNull(p) ((p)==0) +#define SetNull(p) ((p)=0) +// Link list helper macros that are a bit involved + +// Suffixes N,P,Z means that we have (N)ext, (P)rev arguments and/or a (Z)ero check and/or set argument +// f, l, n are "first", "last", "node" I think? +// DLL +// Doubly Linked List: Each node has a prev and next pointer. Operations: Push back, Push front, remove +#define DLLInsert_NPZ(f,l,p,n,next,prev,zchk,zset) \ +(zchk(f) ? (((f) = (l) = (n)), zset((n)->next), zset((n)->prev)) :\ +zchk(p) ? (zset((n)->prev), (n)->next = (f), (zchk(f) ? (0) : ((f)->prev = (n))), (f) = (n)) :\ +((zchk((p)->next) ? (0) : (((p)->next->prev) = (n))), (n)->next = (p)->next, (n)->prev = (p), (p)->next = (n),\ +((p) == (l) ? (l) = (n) : (0)))) + +#define DLLPushBack_NPZ(f,l,n,next,prev,zchk,zset) DLLInsert_NPZ(f,l,l,n,next,prev,zchk,zset) + +#define DLLPushBack_NP(f, l, n, next, prev, zchk) \ +(zchk(f) ? ((f)=(l)=(n),(n)->next=(n)->prev=0) : ((n)->prev=(l),(l)->next=(n),(l)=(n),(n)->next=0)) + +// If f == n we put f to f->next, and f->prev = 0. +// Else if l == n, we put l=l->prev, l->next = 0. +// If l != n and f != n we set n->next->prev to n->prev, and n->prev->next to n->next + +#define DLLRemove_NP(f, l, n, next, prev) (((f) == (n) ? \ +((f)=(f)->next, (f)->prev=0) : \ +(l) == (n) ? \ +((l)=(l)->prev, (l)->next=0) : \ +((n)->next->prev=(n)->prev, \ +(n)->prev->next=(n)->next) )) + +#define DLLRemove_NPZ(f,l,n,next,prev,zchk,zset) (((f)==(n))?\ +((f)=(f)->next, (zchk(f) ? (zset(l)) : zset((f)->prev))):\ +((l)==(n))?\ +((l)=(l)->prev, (zchk(l) ? (zset(f)) : zset((l)->next))):\ +((zchk((n)->next) ? (0) : ((n)->next->prev=(n)->prev)),\ +(zchk((n)->prev) ? (0) : ((n)->prev->next=(n)->next)))) + +#define DLLPushBack(f, l, n) DLLPushBack_NPZ(f, l, n, next, prev, CheckNull, SetNull) +// For front push I can just switch prev/next! +#define DLLPushFront(f, l, n) DLLPushBack_NPZ(l, f, n, prev, next, CheckNull, SetNull) +#define DLLRemove(f, l, n) DLLRemove_NPZ(f, l, n, next, prev, CheckNull, SetNull) + + +// SLL, queue or stack. +// These are from rjf's layer. + +//////////////// +// Queue +// Queue has only a next pointer. But we can push from front also. +// zchk = zero check, zset = zero set +#define QueuePush_NZ(f, l, n, next, zchk, zset) (zchk(f)?\ +(((f)=(l)=(n)), zset((n)->next)):\ +((l)->next=(n),(l)=(n),zset((n)->next))) + +#define QueuePushFront_NZ(f, l, n, next, zchk, zset) ( zchk(f) ? \ +((f)=(l)=(n)), zset((n)->next) : \ +((n)->next = (f)), ((f) = (n)) ) + +#define QueuePop_NZ(f, l, next, zchk, zset) ( (f)==(l) ? \ +(zset(f), zset(l)) : ((f)=(f)->next)) + +#define QueuePush(f, l, n) QueuePush_NZ(f, l, n, next, CheckNull, SetNull) +#define QueuePushFront(f, l, n) QueuePushFront_NZ(f, l, n, next, CheckNull, SetNull) +#define QueuePop(f, l) QueuePop_NZ(f, l, next, CheckNull, SetNull) + +//////////////// +// Stack +#define StackPush_N(f, n, next) ((n)->next=(f), (f)=(n)) // Take the first element and set it to n->next, and set the first element to the node n. +#define StackPop_NZ(f, next, zchk) (zchk(f) ? 0 : ((f)=(f)->next)) // If first element is not zero we say that the first element is f->next, ie we pop f and put f->next on top. + +#define StackPush(f, n) StackPush_N(f, n, next) +#define StackPop(f) StackPop_NZ(f, next, CheckNull) + +///////////////////////// +//- Clamp/min/max +#define Min(a, b) (((a)<(b)) ? (a) : (b)) +#define Max(a, b) (((a)>(b)) ? (a) : (b)) +#define ClampTop(x, a) Min(x,a) // "Top" since we are cutting off anything above Min(x,a) +#define ClampBot(a, x) Max(a,x) // "Bot" since we're cutting off anything below Max(a,x) +// If a > x we get a, else we see if b < x and then get b if true, else x. +// TODO(anton): Is this actually what we want from a Clamp? +#define Clamp(a, x, b) (((a)>(x))?(a):((b)<(x))?(b):(x)) + +//- loop +#define DeferLoop(start, end) for(int _i_ = ((start), 0); _i_ == 0; _i_ += 1, (end)) +#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end)) + +#define EachEnumVal(type, it) type it = (type)0; it < type##_COUNT; it = (type)(it+1) +#define EachNonZeroEnumVal(type, it) type it = (type)1; it < type##_COUNT; it = (type)(it+1) + + +///////////////////////// +//~ Base types +typedef int8_t S8; +typedef int16_t S16; +typedef int32_t S32; +typedef int64_t S64; +typedef uint8_t U8; +typedef uint16_t U16; +typedef uint32_t U32; +typedef uint64_t U64; +typedef S8 B8; +typedef S16 B16; +typedef S32 B32; +typedef S64 B64; +typedef float F32; +typedef double F64; +typedef void VoidFunction(void); + +///////////////////////// +//~ Numerical limits +read_only global U8 U8Max = 0xFF; +read_only global U8 U8Min = 0; +read_only global U32 U32Max = 0xFFFFFFFF; +read_only global U32 U32Min = 0; +read_only global U64 U64Max = 0xFFFFFFFFFFFFFFFF; + +// TODO(anton): Rest of the limits, unsigned and signed integer values +read_only global U32 SignF32 = 0x80000000; + + +//- compiler, shut up! helpers +#define unused_variable(name) (void)name + +///////////////////////// +//~ Base enums + +// Describing a 2-coordinate system +typedef enum Axis2 +{ + Axis2_Invalid = -1, + Axis2_X, + Axis2_Y, + Axis2_COUNT +} +Axis2; +#define Axis2_flip(a) ((Axis2)(!(a))) + +// Corners of a rectangle. +// 00 ----- 10 +// | | +// 01 ----- 11 +typedef enum Corner +{ + Corner_Invalid = -1, + Corner_00, + Corner_01, + Corner_10, + Corner_11, + Corner_COUNT +} +Corner; + +//////////////////////////////// +//~ Member Offset Helper + +typedef struct MemberOffset MemberOffset; +struct MemberOffset +{ + U64 v; +}; + +#define MemberOff(S, member) (MemberOffset){OffsetOf(S, member)} +#define MemberOffLit(S, member) {OffsetOf(S, member)} +#define MemberFromOff(ptr, type, memoff) (*(type *)((U8 *)ptr + memoff.v)) + +///////////////////////// +//~ Assertions + +#if OS_WINDOWS +# define break_debugger() __debugbreak() +#else +# error not implemented +#endif + +#undef Assert +#define Assert(b) do { if(!(b)) { break_debugger(); } } while(0) + +#if !defined(LOG_NOT_IMPLEMENTED) +# define LOG_NOT_IMPLEMENTED printf("\nFATAL ERROR: Not implemented yet.\n"); Assert(false); exit(1); +#endif + +///////////////////////// +//~ Bit patterns +#define AlignUpToPow2(bytes_to_align, alignment_bytes) (((bytes_to_align) + (alignment_bytes - 1)) & ~(alignment_bytes - 1)) + +inline_function F32 +absolute_value_F32(F32 f) +{ + union { U32 u; F32 f; } x; + x.f = f; + x.u = x.u & ~SignF32; + return x.f; +} + +// TODO(anton): Understand rjf's bit patterns + +#endif //BASE_TYPES_H diff --git a/src/base/base_inc.c b/src/base/base_inc.c new file mode 100644 index 0000000..7194c58 --- /dev/null +++ b/src/base/base_inc.c @@ -0,0 +1,4 @@ +#include "base_math.c" +#include "base_memory.c" +#include "base_strings.c" +#include "base_thread_context.c" \ No newline at end of file diff --git a/src/base/base_inc.h b/src/base/base_inc.h new file mode 100644 index 0000000..0598745 --- /dev/null +++ b/src/base/base_inc.h @@ -0,0 +1,11 @@ +#ifndef BASE_H +#define BASE_H + +#include "base_context_cracking.h" +#include "base_core.h" +#include "base_math.h" +#include "base_memory.h" +#include "base_strings.h" +#include "base_thread_context.h" + +#endif //BASE_H diff --git a/src/base/base_math.c b/src/base/base_math.c new file mode 100644 index 0000000..40e9cb0 --- /dev/null +++ b/src/base/base_math.c @@ -0,0 +1,107 @@ +//- Vec2 F32 +root_function Vec2_F32 +vec2_F32(F32 x, F32 y) +{ + Vec2_F32 result; + result.x = x; + result.y = y; + return result; +} + +root_function Vec2_F32 add2_F32(Vec2_F32 a, Vec2_F32 b) { return vec2_F32(a.x+b.x, a.y+b.y); } +root_function Vec2_F32 sub2_F32(Vec2_F32 a, Vec2_F32 b) { return vec2_F32(a.x-b.x, a.y-b.y); } + +//- Vec2 S32 +root_function Vec2_S32 +vec2_S32(S32 x, S32 y) +{ + Vec2_S32 result; + result.x = x; + result.y = y; + return result; +} + + +root_function Vec2_S64 +vec2_S64(S64 x, S64 y) +{ + Vec2_S64 result; + result.x = x; + result.y = y; + return result; +} + +root_function Vec3_F32 +vec3_F32(F32 x, F32 y, F32 z) +{ + Vec3_F32 result; + result.x = x; + result.y = y; + result.z = z; + return result; +} + +root_function Vec4_F32 +vec4_F32(F32 x, F32 y, F32 z, F32 w) +{ + Vec4_F32 result; + result.x = x; + result.y = y; + result.z = z; + result.w = w; + return result; +} + +//~ Range functions +root_function Rng2_F32 +rng2_F32(Vec2_F32 min, Vec2_F32 max) +{ + Rng2_F32 result = { min, max }; + return result; +} + +root_function Rng2_F32 +shift2_F32(Rng2_F32 r, Vec2_F32 v) { + // Shift the rectangle r by vector v. + r.x0 += v.x; + r.y0 += v.y; + r.x1 += v.x; + r.y1 += v.y; + return r; +} + +root_function Rng2_F32 +pad2_F32(Rng2_F32 r, F32 x) +{ + // Pad subtracts the p0 by value x on both axes, and adds to p1 on both axes, + // resulting in a rectangle that is value x larger than input rectangle r on both axes. + Vec2_F32 min = sub2_F32(r.min, vec2_F32(x, x)); + Vec2_F32 max = add2_F32(r.max, vec2_F32(x, x)); + return rng2_F32(min, max); +} + +root_function Vec2_F32 +dim2_F32(Rng2_F32 rng) +{ + return vec2_F32(absolute_value_F32(rng.max.x - rng.min.x), + absolute_value_F32(rng.max.y - rng.min.y)); +} + +// Check if a rect contains a point +root_function B32 +rng2_contains_vec2_F32(Rng2_F32 r, Vec2_F32 x) +{ + B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); + return c; +} + +root_function Rng2_F32 +rng2_intersect_f32(Rng2_F32 a, Rng2_F32 b) +{ + Rng2_F32 c; + c.p0.x = Max(a.min.x, b.min.x); + c.p0.y = Max(a.min.y, b.min.y); + c.p1.x = Min(a.max.x, b.max.x); + c.p1.y = Min(a.max.y, b.max.y); + return c; +} \ No newline at end of file diff --git a/src/base/base_math.h b/src/base/base_math.h new file mode 100644 index 0000000..9942379 --- /dev/null +++ b/src/base/base_math.h @@ -0,0 +1,149 @@ +#ifndef BASE_MATH_H +#define BASE_MATH_H + +////////////////////////// +//~ Macros + +#define floor_F32(f) floorf(f) + + +////////////////////////// +//~ Vector types + +//- 2-vectors +typedef union Vec2_S32 Vec2_S32; +union Vec2_S32 +{ + struct + { + S32 x; + S32 y; + }; + S32 v[2]; +}; + +typedef union Vec2_S64 Vec2_S64; +union Vec2_S64 +{ + struct + { + S64 x; + S64 y; + }; + S64 v[2]; +}; + +typedef union Vec2_F32 Vec2_F32; +union Vec2_F32 +{ + struct + { + F32 x; + F32 y; + }; + F32 v[2]; +}; + +//- 3-vectors + +typedef union Vec3_F32 Vec3_F32; +union Vec3_F32 +{ + struct + { + F32 x; + F32 y; + F32 z; + }; + F32 v[3]; +}; + +//- 4-vectors +typedef union Vec4_F32 Vec4_F32; +union Vec4_F32 +{ + struct + { + F32 x; + F32 y; + F32 z; + F32 w; + }; + struct + { + Vec2_F32 xy; + Vec2_F32 zw; + }; + F32 v[4]; +}; + +//- vector macros +#define vec2_F32_from_vec(v) vec2_F32((F32)(v).x, (F32)(v).y); +#define vec2_S32_from_vec(v) vec2_S32((S32)(v).x, (S32)(v).y); +#define vec2_S64_from_vec(v) vec2_S64((S64)(v).x, (S64)(v).y); +////////////////////////// +//~ Matrix types +typedef struct Mat3x3_F32 Mat3x3_F32; +struct Mat3x3_F32 +{ + F32 elements[3][3]; +}; + +typedef struct Mat4x4_F32 Mat4x4_F32; +struct Mat4x4_F32 +{ + F32 elements[4][4]; +}; + +////////////////////////// +//~ Range types + +//- 2D interval +// +typedef union Rng2_F32 Rng2_F32; +union Rng2_F32 +{ + struct + { + Vec2_F32 min; + Vec2_F32 max; + }; + struct + { + Vec2_F32 p0; + Vec2_F32 p1; + }; + struct + { + F32 x0; + F32 y0; + F32 x1; + F32 y1; + }; + Vec2_F32 v[2]; +}; + +//~ Vector functions + +//- Vec2 F32 +root_function Vec2_F32 vec2_F32(F32 x, F32 y); +root_function Vec2_F32 add2_F32(Vec2_F32 a, Vec2_F32 b); +root_function Vec2_F32 sub2_F32(Vec2_F32 a, Vec2_F32 b); + +//- Vec2 S32 +root_function Vec2_S32 vec2_S32(S32 x, S32 y); + +root_function Vec2_S64 vec2_S64(S64 x, S64 y); + +root_function Vec3_F32 vec3_F32(F32 x, F32 y, F32 z); + +root_function Vec4_F32 vec4_F32(F32 x, F32 y, F32 z, F32 w); + +//~ Range functions +root_function Rng2_F32 rng2_F32(Vec2_F32 min, Vec2_F32 max); +root_function Rng2_F32 shift2_F32(Rng2_F32 r, Vec2_F32 v); +root_function Rng2_F32 pad2_F32(Rng2_F32 r, F32 x); +root_function Vec2_F32 dim2_F32(Rng2_F32 rng); +root_function B32 rng2_contains_vec2_F32(Rng2_F32 r, Vec2_F32 x); +root_function Rng2_F32 rng2_intersect_f32(Rng2_F32 a, Rng2_F32 b); +#endif //BASE_MATH_H diff --git a/src/base/base_memory.c b/src/base/base_memory.c new file mode 100644 index 0000000..e92d4a1 --- /dev/null +++ b/src/base/base_memory.c @@ -0,0 +1,166 @@ +#include +#include + +#if !defined(m_reserve) +#error missing definition for 'm_reserve' type: (U64)->void* +#endif +#if !defined(m_commit) +#error missing definition for 'm_commit' type: (void*, U64)->void +#endif +#if !defined(m_decommit) +#error missing definition for 'm_decommit' type: (void*, U64)->void +#endif +#if !defined(m_release) +#error missing definition for 'm_release' type: (void*, U64)->void +#endif + +static Arena *g_scratch_arena = 0; + +root_function void +m_change_memory_noop(void *ptr, U64 size) {} + +// Malloc implementation of the M_Base_memory +root_function void* +m_malloc_reserve(U64 size) { + return malloc(size); +} + +root_function void +m_malloc_release(void *ptr, U64 size) { + free(ptr); +} + +//~ 64-bit memory arena + +root_function Arena +*m_make_arena_reserve(U64 reserve_size) { + Arena *result = 0; + U64 initial_commit_size = ARENA_COMMIT_GRANULARITY; + if (reserve_size >= initial_commit_size) { + void *memory = m_reserve(reserve_size); + // Since we use "header" space we must ensure the initial commit can fit the Arena struct. + Assert(initial_commit_size >= sizeof(Arena)); + m_commit(memory, ARENA_COMMIT_GRANULARITY); + result = (Arena*)memory;//(Arena*)result; <- this has to be mistake in Allen's video.. ? + // After we have pointed to our newly reserved and commited memory, + // we fill in the "header" parts, which are just the members of the arena type. + result->capacity = reserve_size; + result->commit_pos = initial_commit_size; + result->align = 8; // 8-bytes alignment? + result->pos = sizeof(Arena); // Here we point the position to after the Arena "header" section. + } + return result; +} + +root_function Arena* +m_make_arena() { + Arena* result = m_make_arena_reserve(M_DEFAULT_RESERVE_SIZE); + return result; +} + +// NOTE(anton): rjf calls this "arena push no zero", as opposed to pushing a zeroed array. +// Not sure why we would make this differentiation, maybe not important. + +root_function void* +m_arena_push(Arena *arena, U64 size) { + void *result = 0; + if (arena->pos + size <= arena->capacity) { + /*U8 *base = (U8 *)arena; // Get memory base pointer. + // Adjust by any alignment if necessary. + // Doing modulo ensures we get a number in the 0-align-1 range. + U64 post_align_pos = (arena->pos + (arena->align-1)): + post_align_pos = post_align_pos % arena->align; + // What's happening here? Almost certainly the align will overflow here? + // Are we filling the allocated space backwards or what's up? + // TODO(anton): UNDERSTAND + U64 align = post_align_pos - arena->pos; + result = base + arena->pos + align; + arena->pos += size + align;*/ + // Do Allen4th version until I understand the above. + result = ((U8*) arena) + arena->pos; + arena->pos += size; // increment pos by what we want to push + + U64 p = arena->pos; + U64 commit_p = arena->commit_pos; + if (p > commit_p) { + U64 p_aligned = AlignUpToPow2(p, M_COMMIT_BLOCK_SIZE); + U64 next_commit_p = ClampTop(p_aligned, arena->capacity); // Make sure new commit_p won't overshoot capacity + U64 commit_size = next_commit_p - commit_p; + m_commit((U8 *)arena + commit_p, commit_size); + arena->commit_pos = next_commit_p; + } + } else { + // NOTE(anton): Should implement some fallback but now we fail. + } + return result; +} + +root_function void +m_arena_pop_to(Arena *arena, U64 pos) { + if (pos < arena->pos) { + arena->pos = pos; + + U64 p = arena->pos; + U64 p_aligned = AlignUpToPow2(p, M_COMMIT_BLOCK_SIZE); + U64 next_commit_p = ClampTop(p_aligned, arena->capacity); + + U64 commit_p = arena->commit_pos; + if (next_commit_p < commit_p) { + U64 decommit_size = commit_p - next_commit_p; + m_decommit((U8 *)arena + next_commit_p, decommit_size); + arena->commit_pos = next_commit_p; + } + } +} + +root_function void m_arena_pop(Arena* arena, U64 size) { + U64 min_pos = sizeof(Arena); + U64 size_to_pop = Min(size, arena->pos); + U64 new_pos = arena->pos - size_to_pop; + new_pos = Max(new_pos, min_pos); + m_arena_pop_to(arena, new_pos); +} + +/** Push size and set the memory to zero. */ +root_function void* +m_arena_push_zero(Arena *arena, U64 size) { + void *result = m_arena_push(arena, size); + MemoryZero(result, size); + return result; +} + +root_function void +m_arena_clear(Arena *arena) +{ + // We clear the input arena by popping off everything + // after the actual Arena information. + m_arena_pop_to(arena, sizeof(Arena)); +} + +root_function void +m_arena_align(Arena *arena, U64 pow2_alignment) { + U64 p = arena->pos; + U64 p_aligned = AlignUpToPow2(p, pow2_alignment); + U64 z = p_aligned - p; + if (z > 0) { + m_arena_push(arena, z); + } +} + +root_function void +m_arena_release(Arena* arena) { + m_release(arena, arena->capacity); +} + +root_function ArenaTemp +m_arena_temp_begin(Arena *arena) { + ArenaTemp temp = { 0 }; + temp.arena = arena; + temp.pos = arena->pos; + return temp; +} + +root_function void +m_arena_temp_end(ArenaTemp temp) { + m_arena_pop_to(temp.arena, temp.pos); +} diff --git a/src/base/base_memory.h b/src/base/base_memory.h new file mode 100644 index 0000000..907a14c --- /dev/null +++ b/src/base/base_memory.h @@ -0,0 +1,61 @@ +/* date = April 20th 2023 9:43 pm */ + +#ifndef BASE_MEMORY_H +#define BASE_MEMORY_H + +#if !defined(ARENA_COMMIT_GRANULARITY) +#define ARENA_COMMIT_GRANULARITY Kilobytes(4) +#endif + +#if !defined(ARENA_DECOMMIT_THRESHOLD) +#define ARENA_DECOMMIT_THRESHOLD Megabytes(64) +#endif + +#if !defined(M_DEFAULT_RESERVE_SIZE) +#define M_DEFAULT_RESERVE_SIZE Megabytes(512) +#endif + +#if !defined(M_COMMIT_BLOCK_SIZE) +#define M_COMMIT_BLOCK_SIZE Megabytes(64) +#endif + +// We store this information in the header of the allocated memory for the arena!!! +typedef struct Arena Arena; +struct Arena { + U64 pos; + U64 commit_pos; + U64 capacity; + U64 align; +}; + +typedef struct ArenaTemp ArenaTemp; +struct ArenaTemp { + Arena *arena; + U64 pos; +}; + +root_function void m_change_memory_noop(void *ptr, U64 size); + +root_function Arena* m_make_arena_reserve(U64 reserve_size); +root_function Arena* m_make_arena(); + +root_function void m_arena_release(Arena *arena); +root_function void* m_arena_push(Arena *arena, U64 size); +root_function void m_arena_pop_to(Arena *arena, U64 pos); +root_function void m_arena_pop(Arena* arena, U64 size); +root_function void m_arena_align(Arena *arena, U64 pow2_alignment); +root_function void* m_arena_push_zero(Arena *arena, U64 size); +root_function void m_arena_clear(Arena *arena); + +#define PushArray(arena, type, count) (type *)m_arena_push((arena), sizeof(type)*(count)) +#define PushArrayZero(arena, type, count) (type *)m_arena_push_zero((arena), sizeof(type)*(count)) + +//~ temp arena + +root_function ArenaTemp m_arena_temp_begin(Arena *arena); +root_function void m_arena_temp_end(ArenaTemp temp); + +// TODO(anton): Not sure when I should use this? +#define ArenaTempBlock(arena, name) ArenaTemp name = { 0 }; DeferLoop(name = m_arena_temp_begin(arena), m_arena_temp_end(name)) + +#endif //BASE_MEMORY_H diff --git a/src/base/base_strings.c b/src/base/base_strings.c new file mode 100644 index 0000000..5a8ea3b --- /dev/null +++ b/src/base/base_strings.c @@ -0,0 +1,510 @@ +#include + +//~ Helpers +root_function U64 +calculate_string_C_string_length(char *cstr) { + /*U64 length = 0; + for(char* p = cstr; p != '\0'; p += 1) { + length += 1; + } + return length;*/ + // A cool way to write this is this while loop + U64 length = 0; + for (/* empty here means just while loop*/; + /* While we're not at null terminator */ cstr[length]; + /* Increment */ length += 1); + + // Then we're actually done and just return length; + return length; +} + + +//~ Constructors +root_function String8 +str8(U8 *str, U64 size) { + String8 string; + string.str = str; + string.size = size; + return string; +} + +root_function String8 +str8_range(U8 *first, U8 *one_past_last) { + String8 string; + string.str = first; + string.size = (U64)(one_past_last - first); + return string; +} + +//~ Substrings +//- String8 +root_function String8 +str8_substr(String8 string, U64 first, U64 one_past_last) { + // We get a substring from the range one_past_last - first + U64 min = first; + U64 max = one_past_last; + // Logic to prepare for swithing input to a range instead of first/one_past_last + if (max > string.size) { + max = string.size; + } + if (min > string.size) { + min = string.size; + } + if (min > max) { + U64 swap = min; + min = max; + max = swap; + } + string.size = max - min; + string.str += min; // Increment the pointer of the String8 to the min. + return string; +} + +root_function String8 str8_prefix(String8 string, U64 size) { return str8_substr(string, 0, size); } +root_function String8 str8_chop(String8 string, U64 amount) { return str8_substr(string, 0, string.size-amount); } +root_function String8 str8_suffix(String8 string, U64 size) { return str8_substr(string, string.size-size, string.size); } +root_function String8 str8_skip(String8 string, U64 amount) { return str8_substr(string, amount, string.size); } + +// String16 +// String32 + +//~ Lists +//- String8 +root_function void +str8_list_push_node(String8List *list, String8Node *n) { + QueuePush(list->first, list->last, n); + list->node_count += 1; + list->total_size += n->string.size; +} + +root_function void +str8_list_push_node_front(String8List *list, String8Node *n) { + QueuePushFront(list->first, list->last, n); + list->node_count += 1; + list->total_size += n->string.size; +} + +// Wrapper that pushes the memory for a node onto the arena, and then puts the node in the linked list (in the back). +root_function void +str8_list_push(Arena *arena, String8List *list, String8 string) { + String8Node *n = PushArrayZero(arena, String8Node, 1); + n->string = string; + str8_list_push_node(list, n); +} + +// Wrapper that pushes the memory for a node onto the arena, and then puts the node in the linked list (in the front). +root_function void +str8_list_push_front(Arena *arena, String8List *list, String8 string) { + String8Node *n = PushArrayZero(arena, String8Node, 1); + n->string = string; + str8_list_push_node_front(list, n); +} + +root_function void +str8_list_concat(String8List *list, String8List *to_push) { + // If to_push is a non-zero length String8List, + // we add it to the input list. + if (to_push->first) { + list->node_count += to_push->node_count; + list->total_size += to_push->total_size; + // If the input list's last element is null + // we had a zero length input list, and we just set the input list equal to to_push + if (list->last == 0) { + *list = *to_push; + } else { + // Else we append the to_push list to the input list. + list->last->next = to_push->first; + list->last = to_push->last; + } + } + // TODO(anton): Why are we zeroing the memory here? + MemoryZero(to_push, sizeof(*to_push)); + //LOG_NOT_IMPLEMENTED; +} + +// TODO(anton): Understand this function and write comments about the logic. +root_function String8List +str8_split(Arena *arena, String8 string, int split_count, String8 *splits) { + + String8List list = { 0 }; + + U64 split_start = 0; + for (U64 i = 0; i < string.size; i += 1) + { + B32 was_split = 0; + for (int split_idx = 0; split_idx < split_count; split_idx += 1) + { + B32 match = 0; + if (i + splits[split_idx].size <= string.size) + { + match = 1; + for (U64 split_i = 0; split_i < splits[split_idx].size && i + split_i < string.size; split_i += 1) + { + if (splits[split_idx].str[split_i] != string.str[i + split_i]) + { + match = 0; + break; + + } + } + } + if (match) + { + String8 split_string = str8(string.str + split_start, i - split_start); + str8_list_push(arena, &list, split_string); + split_start = i + splits[split_idx].size; + i += splits[split_idx].size - 1; + was_split = 1; + break; + } + } + + if (was_split == 0 && i == string.size - 1) + { + String8 split_string = str8(string.str + split_start, i + 1 - split_start); + str8_list_push(arena, &list, split_string); + break; + } + } + + return list; +} + +// TODO(anton): Understand this function and write good comments explaining. +root_function String8 +str8_list_join(Arena *arena, String8List list, StringJoin *optional_params) { + // rjf: setup join parameters + StringJoin join = { 0 }; + if (optional_params != 0) + { + MemoryCopy(&join, optional_params, sizeof(join)); + } + + // rjf: calculate size & allocate + U64 sep_count = 0; + if (list.node_count > 1) + { + sep_count = list.node_count - 1; + } + String8 result = { 0 }; + result.size = (list.total_size + join.pre.size + + sep_count*join.sep.size + join.post.size); + result.str = PushArray(arena, U8, result.size + 1); + + // rjf: fill + U8 *ptr = result.str; + MemoryCopy(ptr, join.pre.str, join.pre.size); + ptr += join.pre.size; + for (String8Node *node = list.first; node; node = node->next) + { + MemoryCopy(ptr, node->string.str, node->string.size); + ptr += node->string.size; + if (node != list.last) + { + MemoryCopy(ptr, join.sep.str, join.sep.size); + ptr += join.sep.size; + } + } + MemoryCopy(ptr, join.post.str, join.post.size); + ptr += join.post.size; + + // rjf: add null + result.str[result.size] = 0; + + return result; +} + +//~ Allocation and format strings +root_function String8 +str8_copy(Arena *arena, String8 string) { + String8 result; + result.size = string.size; + result.str = PushArray(arena, U8, string.size + 1); + MemoryCopy(result.str, string.str, string.size); + result.str[string.size] = 0; // TODO(anton): What is this? + return result; +} + +root_function String8 +str8_pushfv(Arena *arena, char *fmt, va_list args) { + + // Might need to try a second time so copy args + va_list args2; + va_copy(args2, args); + + // Try to build string using 1024 bytes + U64 buffer_size = 1024; + U8 *buffer = PushArray(arena, U8, buffer_size); + // The vsnprintf takes the bundled arguments list args and puts the format strings it into buffer. + U64 actual_size = vsnprintf((char*)buffer, buffer_size, fmt, args); + + String8 result = { 0 }; + if (actual_size < buffer_size) { + // The first try worked and we can pop whatever wasn't used from the buffer + // and get our resulting string. + m_arena_pop(arena, buffer_size - actual_size - 1); // -1 because of null terminated in char *fmt? + result = str8(buffer, actual_size); + } else { + // If first try failed we try again with better size + m_arena_pop(arena, buffer_size); + U8 *fixed_buffer = PushArray(arena, U8, actual_size + 1); + U64 final_size = vsnprintf((char*)fixed_buffer, actual_size + 1, fmt, args2); + result = str8(fixed_buffer, final_size); + } + + // va_end to help compiler do its thing. + va_end(args2); + + return result; +} + +root_function String8 +str8_pushf(Arena *arena, char*fmt, ...) { + String8 result = { 0 }; + va_list args; + va_start(args, fmt); + result = str8_pushfv(arena, fmt, args); + va_end(args); + return result; +} + +root_function void +str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...) { + va_list args; + va_start(args, fmt); + String8 string = str8_pushfv(arena, fmt, args); + va_end(args); + str8_list_push(arena, list, string); +} + +//~ Unicode conversions + +#define bitmask1 0x01 // Mask first bit +#define bitmask2 0x03 // Mask 2 bits, 3 = 0x03 = 0000 0011 = 2^2 - 1 +#define bitmask3 0x07 // Mask 3 bits, 7 = 0x07 = 0000 0111 = 2^3 - 1 +#define bitmask4 0x0F // Mask 4 bits, 15 = 0x0F = 0000 1111 = 2^4 - 1 +#define bitmask5 0x1F // Mask 5 bits, 31 = 0x1F = 0001 1111 = 2^5 - 1 +#define bitmask6 0x3F // Mask 6 bits, 63 = 0x3F = 0011 1111 = 2^6 - 1 +#define bitmask7 0x7F // Mask 7 bits, 127 = 0x7F = 0111 1111 = 2^7 - 1 +#define bitmask8 0xFF // Mask 8 bits, 255 = 0xFF = 1111 1111 = 2^8 - 1 + +// Note that we're only decoding valid cases and not handling invalid/errors +root_function DecodeCodepoint +decode_from_utf8(U8 *str, U64 max) { + // This table will give us wheter or not we have a codepoint encoded by one, two, three or four bytes. + local_persist U8 utf8_class[] = { + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 0, 0, 0, 0, + 0, 0, 0, 0, + 2, 2, 2, 2, + 3, 3, + 4, + 5 // error + }; + + DecodeCodepoint result = { ~((U32)0), 1 }; + // We'll shift out the lowest 3 bits since those are not important in the decoding. + // This is the byte >> 3 into the static array. + U8 byte = str[0]; + U8 byte_class = utf8_class[byte >> 3]; + + switch (byte_class) { + case 1: { + // Just a single byte encoding. + result.codepoint = byte; // Actually the 8th bit must be zero for valid UTF encoding. + } break; + + case 2: { + if (2 <= max) { + U8 cont_byte = str[1]; + // Check the second byte + if (utf8_class[cont_byte >> 3] == 0) { + // codepoint is 32-bits + // The case with two bytes has byte1 110xxxxx, ie encoded in the last 5 bits. + // and byte2 is 10xxxxxx, encoded in the last 6 bits. So we use mask5 on first byte, shift by 6, + // and mask6 on second byte. + result.codepoint = (byte & bitmask5) << 6; + result.codepoint |= (cont_byte & bitmask6); + result.advance = 2; + } + } + } break; + + case 3: { + if (3 <= max) { + // encoded by 3 bytes, so we have two more cont_bytes. + U8 cont_byte[2] = { str[1], str[2] }; + if (utf8_class[cont_byte[0] >> 3] == 0 && utf8_class[cont_byte[1] >> 3] == 0) { + // For this case the first byte is encoded in the last 4 bits, 1110xxxx + // The second and third is 10xxxxxx (last 6 bits) + result.codepoint = (byte & bitmask4) << 12; + result.codepoint |= (cont_byte[0] & bitmask6) << 6; + result.codepoint |= (cont_byte[1] & bitmask6); + result.advance = 3; + } + } + } break; + + case 4: { + if (4 <= max) { + U8 cont_byte[3] = { str[1], str[2], str[3] }; + if (utf8_class[cont_byte[0] >> 3] == 0 && + utf8_class[cont_byte[1] >> 3] == 0 && + utf8_class[cont_byte[2] >> 3] == 0) { + // Here first byte is encoded in last 3 bits, and byte 2,3,4 are encoded in last 6 bits. + // Thus we shift the first byte by 3*6 = 18 bits into the 32 bit codepoint; + result.codepoint = (byte & bitmask3) << 18; + result.codepoint |= (cont_byte[0] & bitmask6) << 12; + result.codepoint |= (cont_byte[1] & bitmask6) << 6; + result.codepoint |= (cont_byte[2] & bitmask6); + result.advance = 4; + } + } + } break; + } + + return result; +} + +// Encode function +root_function U32 +utf8_from_codepoint(U8* out, U32 codepoint) { + U8 bit8 = 0x80; + U32 advance = 0; + + if (codepoint <= bitmask7 /* 0111 1111 */) { + // We know that the whole encoding is in the last 7 bits, so it's a 1 byte encoding + out[0] = (U8)codepoint; + advance = 1; + + } else if (codepoint <= 0x07FF /*0000 0111 1111 1111*/) { + // The case with two bytes has byte1 110xxxxx, ie encoded in the last 5 bits. + // and byte2 is 10xxxxxx, encoded in the last 6 bits. + out[0] = (bitmask2 << 6) | ((codepoint >> 6) & bitmask5); + out[1] = bit8 | (codepoint & bitmask6); + advance = 2; + + } else if (codepoint <= 0xFFFF /* 1111 1111 1111 1111 */) { + // For this case the first byte is encoded in the last 4 bits, 1110xxxx + // The second and third is 10xxxxxx (last 6 bits) + out[0] = (bitmask3 << 5) | ((codepoint >> 12) & bitmask4); + out[1] = bit8 | ((codepoint >> 6) & bitmask6); + out[2] = bit8 | ((codepoint) & bitmask6); + advance = 3; + + } else if (codepoint <= 0x10FFFF /*0001 0000 1111 1111 1111 1111 */) { + // Here first byte is encoded in last 3 bits, and byte 2,3,4 are encoded in last 6 bits. + // Thus we shift the first byte by 3*6 = 18 bits into the 32 bit codepoint; + out[0] = (bitmask4 << 4) | ((codepoint >> 18) & bitmask3); + out[1] = bit8 | ((codepoint >> 12) & bitmask6); + out[2] = bit8 | ((codepoint >> 6) & bitmask6); + out[3] = bit8 | ((codepoint) & bitmask6); + advance = 4; + } else { + out[0] = '?'; // ERrror? + advance = 1; + } + + return advance; +} + +root_function DecodeCodepoint decode_from_utf16(U16 *str, U64 max) { + DecodeCodepoint result = { ~((U32)0), 1 }; + result.codepoint = str[0]; + result.advance = 1; + // Usually codepoints fit into a single 16 bit chunk. + // But when we're not in the ranges 0x0000 to 0xD7FF and 0xE000 to 0xFFFF, + // we need two 16 bit stores. + // So what we have in str[0] = W1 is the "high surrogate", and + // str[1] = W2 is the "low surrogate". We then get the codepoint U = U' + 0x10000, + // where U' is a 20-bit number with the 10 lower bits from W1 in the high bits, and 10 lower bits of W2 in the lower. + if (max > 1) { + U16 w1 = str[0]; + U16 w2 = str[1]; + if (0xD800 <= w1 && w1 < 0xDC00 && 0xDC00 <= w2 && w2 < 0xE000) { + // Get W1 ten bits + U16 y = w1 - 0xD800; + U16 x = w2 - 0xDC00; + U32 uprim = (y << 10) | x; + result.codepoint = uprim + 0x10000; + result.advance = 2; + } + } + return result; +} + +root_function U32 utf16_from_codepoint(U16* out, U32 codepoint) { + + U32 advance = 1; + if (codepoint == ~((U32)0)) { + // Error? + out[0] = (U16)'?'; + } else if (codepoint < 0x10000) { + // single 16 bit code unit + out[0] = (U16)codepoint; + } else { + // store 20 bits in uprim + U32 uprim = codepoint - 0x10000; + // create W1 + out[0] = 0xD800 + (uprim >> 10); + // 0x03FF = bitmask for 10 lowest bits + // create W2 + out[1] = 0xDC00 + (uprim & 0x03FF); + advance = 2; + } + return advance; +} + +// TODO(anton): understand this and write comments on steps +root_function String8 +str8_from16(Arena *arena, String16 string) { + U64 cap = string.size*3; + U8 *str = PushArray(arena, U8, cap + 1); + U16 *ptr = string.str; + U16 *one_past_last = ptr + string.size; + U64 size = 0; + DecodeCodepoint consume; + for (; ptr < one_past_last;) { + consume = decode_from_utf16(ptr, one_past_last - ptr); + ptr += consume.advance; + size += utf8_from_codepoint(str + size, consume.codepoint); + } + str[size] = 0; + m_arena_pop(arena, cap - size); + return str8(str, size); +} + +root_function String8 +str8_from32(Arena *arena, String32 string) { + +} + +// TODO(anton): understand this and write comments on steps +root_function String16 +str16_from8(Arena* arena, String8 string) { + U64 cap = string.size*2; + U16 *str = PushArray(arena, U16, cap + 1); + U8 *ptr = string.str; + U8 *one_past_last = ptr + string.size; + U64 size = 0; + DecodeCodepoint consume; + for (; ptr < one_past_last;) { + consume = decode_from_utf8(ptr, one_past_last - ptr); + ptr += consume.advance; + size += utf16_from_codepoint(str + size, consume.codepoint); + } + str[size] = 0; + m_arena_pop(arena, 2*(cap - size)); + String16 result; + result.str = str; + result.size = size; + return result; +} + +root_function String32 +str32_from8(Arena *arena, String8 string) { + +} diff --git a/src/base/base_strings.h b/src/base/base_strings.h new file mode 100644 index 0000000..acdaec7 --- /dev/null +++ b/src/base/base_strings.h @@ -0,0 +1,124 @@ +/* date = April 23rd 2023 10:47 am */ + +#ifndef BASE_STRINGS_H +#define BASE_STRINGS_H + +// We decide that the basic string handling will be immutable. +// This means that whatever memory we got when initialising the string is what we have to live with. +// This will give us easy interfaces and work for most cases. +// The downside is that it might not have the best performance, always. +// In such cases we will develop special code for handling the special cases. + +///////////////////////// +//~ Basic string types, lists and arrays + +typedef struct String8 String8; +struct String8 { + U8* str; + U64 size; +}; + +typedef struct String16 String16; +struct String16 { + U16 *str; + U64 size; +}; + +typedef struct String32 String32; +struct String32 { + U32 *str; + U64 size; +}; + +typedef struct String8Node String8Node; +struct String8Node { + String8Node *next; + String8 string; +}; + +typedef struct String8List String8List; +struct String8List { + String8Node *first; + String8Node *last; + U64 node_count; + U64 total_size; +}; + +typedef struct String8Array String8Array; +struct String8Array { + U64 count; + String8 *v; +}; + +///////////////////////// +//~ String operations +typedef struct StringJoin StringJoin; +struct StringJoin { + String8 pre; + String8 sep; + String8 post; +}; + +typedef struct DecodeCodepoint DecodeCodepoint; +struct DecodeCodepoint { + U32 codepoint; + U32 advance; +}; + + +///////////////////////// +//~ String operations +//~ String functions + +//- Helpers +root_function U64 calculate_string_C_string_length(char *cstr); + +//- Constructors +root_function String8 str8(U8 *str, U64 size); +// Get a String8 from a C-string. +#define str8_C(cstring) str8((U8 *)cstring,calculate_string_C_string_length(cstring)) +// Get a String8 from a literal +#define str8_lit(s) str8((U8*)(s), sizeof(s) - 1) // -1 since we don't want null terminated, + // but this still stores the null char for interop with APIs + // that expect Cstrings. +// Specify a Str8 as just its struct members +#define str8_lit_comp(s) {(U8*)(s), sizeof(s)-1} +root_function String8 str8_range(U8 *first, U8 *one_past_last); + +#define str8_struct(ptr) str8((U8 *)(ptr), sizeof(*(ptr))) + +//- Substrings +root_function String8 str8_substr(String8 string, U64 first, U64 one_past_last); +root_function String8 str8_prefix(String8 string, U64 size); +root_function String8 str8_chop(String8 string, U64 amount); +root_function String8 str8_suffix(String8 string, U64 size); +root_function String8 str8_skip(String8 string, U64 amount); + +// Used in format strings! +#define str8_expand(s) (int)((s).size), ((s).str) + +//- Lists +root_function void str8_list_push_node(String8List *list, String8Node *n); +root_function void str8_list_push_node_front(String8List *list, String8Node *n); +root_function void str8_list_push(Arena *arena, String8List *list, String8 string); +root_function void str8_list_push_front(Arena *arena, String8List *list, String8 string); +root_function void str8_list_concat(String8List *list, String8List *to_push); +root_function String8List str8_split(Arena *arena, String8 string, int split_count, String8 *splits); +root_function String8 str8_list_join(Arena *arena, String8List list, StringJoin *optional_params); + +//- Allocation and format strings +root_function String8 str8_copy(Arena *arena, String8 string); +root_function String8 str8_pushfv(Arena *arena, char *fmt, va_list args); +root_function String8 str8_pushf(Arena *arena, char* fmt, ...); +root_function void str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...); + +//~ Unicode conversions +root_function DecodeCodepoint decode_from_utf8(U8 *str, U64 max); +root_function U32 utf8_from_codepoint(U8* out, U32 codepoint); +root_function DecodeCodepoint decode_from_utf16(U16 *str, U64 max); +root_function U32 utf16_from_codepoint(U16* out, U32 codepoint); +root_function String8 str8_from16(Arena *arena, String16 string); +root_function String8 str8_from32(Arena *arena, String32 string); +root_function String16 str16_from8(Arena* arena, String8 string); +root_function String32 str32_from8(Arena *arena, String8 string); +#endif //BASE_STRINGS_H diff --git a/src/base/base_thread_context.c b/src/base/base_thread_context.c new file mode 100644 index 0000000..124d84f --- /dev/null +++ b/src/base/base_thread_context.c @@ -0,0 +1,82 @@ + +root_function ThreadContext +thread_context_alloc(void) +{ + ThreadContext result = { 0 }; + + for (U64 arena_index = 0; arena_index < ArrayCount(result.arenas); arena_index += 1) + { + result.arenas[arena_index] = m_make_arena_reserve(Gigabytes(8)); + } + return result; +} + +root_function void +thread_context_release(ThreadContext *context) +{ + for (U64 arena_index = 0; arena_index < ArrayCount(context->arenas); arena_index += 1) + { + m_arena_release(context->arenas[arena_index]); + } +} + + +per_thread ThreadContext *tl_thread_context; + +no_name_mangle void +thread_context_set(ThreadContext *context) +{ + tl_thread_context = context; +} + +no_name_mangle ThreadContext * +thread_context_get(void) +{ + return tl_thread_context; +} + + +root_function B32 is_main_thread(void) +{ + ThreadContext *context = thread_context_get(); + return context->is_main_thread; +} + +root_function ArenaTemp +scratch_get(Arena **conflicts, U64 conflict_count) +{ + ArenaTemp scratch = { 0 }; + ThreadContext *thread_context = thread_context_get(); + for (U64 arena_index = 0; arena_index < ArrayCount(thread_context->arenas); arena_index += 1) + { + B32 is_conflicting = 0; + for(Arena **conflict = conflicts; conflict < conflicts+conflict_count; conflict += 1) + { + if(*conflict == thread_context->arenas[arena_index]) + { + is_conflicting = 1; + break; + } + } + if(is_conflicting == 0) + { + scratch.arena = thread_context->arenas[arena_index]; + scratch.pos = scratch.arena->pos; + break; + } + } + return scratch; +} + +root_function void +base_main_thread_entry(void (*entry)(void), U64 argument_count, char **arguments) +{ + // Here we get memory for the thread arenas, and notify that it's a main thread. + ThreadContext thread_context = thread_context_alloc(); + thread_context.is_main_thread = 1; + // Here we set it to the global thread context variable + thread_context_set(&thread_context); + // Then call the entry point function for our program + entry(); + thread_context_release(&thread_context); +} \ No newline at end of file diff --git a/src/base/base_thread_context.h b/src/base/base_thread_context.h new file mode 100644 index 0000000..42a0776 --- /dev/null +++ b/src/base/base_thread_context.h @@ -0,0 +1,39 @@ +/* date = April 29th 2023 9:18 pm */ + +#ifndef BASE_THREAD_CONTEXT_H +#define BASE_THREAD_CONTEXT_H + +typedef struct ThreadContext ThreadContext; +struct ThreadContext +{ + Arena *arenas[2]; // WHy 2 arenas? + char *file_name; + U64 line_number; + U8 thread_name[32]; + U64 thread_name_size; + B32 is_main_thread; +}; + +//root_function ThreadContext make_thread_context(void); + +root_function ThreadContext thread_context_alloc(void); +root_function void thread_context_release(ThreadContext *context); + +no_name_mangle void +thread_context_set(ThreadContext *context); +no_name_mangle ThreadContext * +thread_context_gett(void); + + +root_function B32 is_main_thread(void); + +//~ scratch memory +root_function ArenaTemp scratch_get(Arena **conflicts, U64 conflict_count); +#define scratch_release(temp) m_arena_temp_end(temp) + +//~ entry +// Takes a function pointer to the app entry function. +root_function void +base_main_thread_entry(void (*entry)(void), U64 argument_count, char **arguments); + +#endif //BASE_THREAD_CONTEXT_H diff --git a/src/cuda_entry_point.cu b/src/cuda_entry_point.cu index 517bb6c..d1552cf 100644 --- a/src/cuda_entry_point.cu +++ b/src/cuda_entry_point.cu @@ -1,19 +1,28 @@ #include - +#include "../external/cusolver_common.h" #define no_name_mangle extern "C" - - __global__ void hello_from_GPU() { printf("HELLO FROM GPUUUU"); } +void check_cusolver_version() { + + int major=-1, minor=-1, patch=-1; + cusolverGetProperty(MAJOR_VERSION, &major); + cusolverGetProperty(MINOR_VERSION, &minor); + cusolverGetProperty(PATCH_LEVEL, &patch); + printf("CUSOLVER Version (Major,Minor,PatchLevel): %d.%d.%d\n", major,minor,patch); + +} + no_name_mangle void cuda_entry_point() { - hello_from_GPU<<<1, 1>>>(); + check_cusolver_version(); + hello_from_GPU<<<1, 1>>>(); cudaDeviceSynchronize(); } diff --git a/src/kernels.h b/src/kernels.h index b7899cf..9a005e7 100644 --- a/src/kernels.h +++ b/src/kernels.h @@ -1,5 +1,2 @@ - - -// Forward declarations void cuda_entry_point(); diff --git a/src/main.c b/src/main.c index c66a48a..7a31579 100644 --- a/src/main.c +++ b/src/main.c @@ -1,17 +1,97 @@ #include +// --- +// Header includes +#include "base/base_inc.h" +#include "os/os_inc.h" + + +// CUDA headers #include "kernels.h" +// --- +// .C includes +#include "base/base_inc.c" +#include "os/os_inc.c" +#include "os/os_entry_point.c" -int main() { +#define grid_file_path_bin "D:\\dev\\eigsol_gpu\\out\\grid.bin" +#define grid_file_path "D:\\dev\\eigsol_gpu\\out\\grid.dat" + +typedef struct Grid Grid; +struct Grid { + F64 start; + F64 end; + U32 num_steps; + F64 *points; +}; + +typedef struct BSplineCtx BSplineCtx; +struct BSplineCtx { + U32 order; +}; + + +void write_array_binary_F64(String8 path_to_file, F64 *values, U32 array_size) +{ + OS_Handle file_handle = OS_file_open(OS_AccessFlag_Write | OS_AccessFlag_CreateNew, + path_to_file); + { + ArenaTemp scratch = scratch_get(0, 0); + String8List list = {0}; + String8 temp = {0}; + temp.str = (U8*)values; + temp.size = sizeof(F64)*array_size; + str8_list_push(scratch.arena, &list, temp); + OS_file_write(scratch.arena, file_handle, 0, list, 0); + } + OS_file_close(file_handle); +} + + +void write_array_F64(String8 path_to_file, F64 *values, U32 array_size, char* fmt) +{ + OS_Handle file_handle = OS_file_open(OS_AccessFlag_Write | OS_AccessFlag_CreateNew, + path_to_file); + { + ArenaTemp scratch = scratch_get(0, 0); + String8List list = {0}; + for(U32 i = 0; i < array_size; i++) + { + str8_list_pushf(scratch.arena, &list, fmt, values[i]); + } + OS_file_write(scratch.arena, file_handle, 0, list, 0); + } + OS_file_close(file_handle); + +} + + +void EntryPoint() { + OS_InitReceipt os_receipt = OS_init(); + OS_InitGfxReceipt os_gfx_receipt = OS_gfx_init(os_receipt); + + Arena *arena = m_make_arena(); + + Grid grid = {0}; + grid.start = 0.0; + grid.end = 10.0; + grid.num_steps = 1000; + + grid.points = PushArrayZero(arena, F64, grid.num_steps); + F64 step_size = (grid.end-grid.start)/(F64)grid.num_steps; + grid.points[0] = grid.start; + grid.points[grid.num_steps-1] = grid.end; + for(U32 i = 1; i < grid.num_steps-1; i++) { + grid.points[i] = grid.points[i-1] + step_size; + } + + write_array_binary_F64(str8_lit(grid_file_path_bin), grid.points, grid.num_steps); + write_array_F64(str8_lit(grid_file_path), grid.points, grid.num_steps, "%13.6e\n"); + - cuda_entry_point(); - printf("hello"); - - - return 0; } diff --git a/src/os/os_core.c b/src/os/os_core.c new file mode 100644 index 0000000..24db847 --- /dev/null +++ b/src/os/os_core.c @@ -0,0 +1,5 @@ +root_function B32 +OS_handle_match(OS_Handle a, OS_Handle b) +{ + return a.u64[0] == b.u64[0]; +} \ No newline at end of file diff --git a/src/os/os_core.h b/src/os/os_core.h new file mode 100644 index 0000000..8b66327 --- /dev/null +++ b/src/os/os_core.h @@ -0,0 +1,90 @@ +#ifndef OS_CORE_H +#define OS_CORE_H + +typedef U32 OS_AccessFlags; +enum { + OS_AccessFlag_Read = (1<<0), + OS_AccessFlag_Write = (1<<1), + OS_AccessFlag_Execute = (1<<2), + OS_AccessFlag_CreateNew = (1<<3), + OS_AccessFlag_All = 0xFFFFFFFF, +}; + +typedef struct OS_Handle OS_Handle; +struct OS_Handle { + U64 u64[1]; +}; + +typedef enum OS_ErrorCode +{ + OS_ErrorCode_Null, + OS_ErrorCode_COUNT +} OS_ErrorCode; + +typedef struct OS_Error OS_Error; +struct OS_Error { + OS_Error *next; + OS_ErrorCode code; +}; + +typedef struct OS_ErrorList OS_ErrorList; +struct OS_ErrorList { + OS_Error *first; + OS_Error *last; + U64 count; +}; + +typedef struct OS_InitReceipt OS_InitReceipt; +struct OS_InitReceipt +{ + U64 u64[1]; +}; + +typedef U64 OS_Timestamp; + +typedef struct OS_FileAttributes OS_FileAttributes; +struct OS_FileAttributes +{ + U64 size; + OS_Timestamp last_modified; +}; + +//////////////////////////////// +//~ Helpers +root_function B32 OS_handle_match(OS_Handle a, OS_Handle b); + +//////////////////////////////// +//~ @os_per_backend Memory + +root_function U64 OS_page_size(void); +root_function void* OS_reserve(U64 size); +root_function void OS_release(void *ptr, U64 size); +root_function void OS_commit(void *ptr, U64 size); +root_function void OS_decommit(void *ptr, U64 size); +root_function void OS_set_memory_access_flags(void *ptr, U64 size, OS_AccessFlags flags); + +//////////////////////////////// +//~ Thread and process types + +typedef void OS_Thread_Function(void *params); // void function pointer ? + +root_function OS_InitReceipt OS_init(void); +root_function void OS_thread_context_set(void *ptr); +root_function void* OS_thread_context_get(void); + +//////////////////////////////// +//~ @os_per_backend File System +root_function OS_Handle OS_file_open(OS_AccessFlags access_flags, String8 path); +root_function void OS_file_close(OS_Handle file); +root_function String8 OS_file_read(Arena *arena, OS_Handle file, U64 min, U64 max); +// We supply whatever we want to write as a String8List, +// so we can pull data from different places with no intermediate buffer. +root_function void OS_file_write(Arena *arena, OS_Handle file, U64 off, + String8List data, OS_ErrorList *out_errors); +root_function OS_FileAttributes OS_attributes_from_file(OS_Handle file); + +/////////////////////////////// +//~ @os_per_backend Numerical value to string conversion +root_function String8List OS_to_string_list_F64(Arena *arena, F64 *values, U32 values_size, String8 format); + +#endif /* OS_CORE_H */ diff --git a/src/os/os_entry_point.c b/src/os/os_entry_point.c new file mode 100644 index 0000000..cab9923 --- /dev/null +++ b/src/os/os_entry_point.c @@ -0,0 +1,5 @@ +#if OS_WINDOWS +#include "win32/os_entry_point_win32.c" +#else +#error Entry point not defined +#endif \ No newline at end of file diff --git a/src/os/os_gfx.c b/src/os/os_gfx.c new file mode 100644 index 0000000..4cb7229 --- /dev/null +++ b/src/os/os_gfx.c @@ -0,0 +1,20 @@ +#include "os_gfx_meta.c" + + +root_function B32 +OS_key_press(OS_EventList *events, OS_Handle window, OS_Key key) +{ + B32 result = 0; + for(OS_Event *e = events->first; e != 0; e = e->next) + { + + if(e->kind == OS_EventKind_Press && OS_handle_match(window, e->window) && e->key == key) + // TODO(anton): modifiers + { + OS_consume_event(events, e); + result = 1; + break; + } + } + return result; +} \ No newline at end of file diff --git a/src/os/os_gfx.h b/src/os/os_gfx.h new file mode 100644 index 0000000..6eea74e --- /dev/null +++ b/src/os/os_gfx.h @@ -0,0 +1,94 @@ +#ifndef OS_GFX_H +#define OS_GFX_H + +typedef U32 OS_Window_Flags; + +typedef struct OS_InitGfxReceipt OS_InitGfxReceipt; +struct OS_InitGfxReceipt +{ + U64 u64[1]; +}; + +#include "os_gfx_meta.h" + +//////////////////////////////// +//~ Cursor Types + +typedef enum OS_Cursor +{ + OS_Cursor_Pointer, + OS_Cursor_IBar, + OS_Cursor_LeftRight, + OS_Cursor_UpDown, + OS_Cursor_DownRight, + OS_Cursor_UpRight, + OS_Cursor_UpDownLeftRight, + OS_Cursor_HandPoint, + OS_Cursor_Disabled, + OS_Cursor_COUNT, +} +OS_Cursor; + +//////////////////////////////// +//~ Events +typedef enum OS_EventKind +{ + OS_EventKind_Null, + OS_EventKind_Press, + OS_EventKind_Release, + OS_EventKind_MouseMove, + OS_EventKind_Text, + OS_EventKind_Scroll, + OS_EventKind_WindowLoseFocus, + OS_EventKind_WindowClose, + OS_EventKind_FileDrop, + OS_EventKind_Wakeup, + OS_EventKind_COUNT +} +OS_EventKind; + + +typedef struct OS_Event OS_Event; +struct OS_Event +{ + OS_Event *next; + OS_Event *prev; + OS_Handle window; + OS_EventKind kind; + //OS_Modifiers modifiers; + OS_Key key; + U32 character; + Vec2_F32 position; + Vec2_F32 scroll; + String8 path; +}; + +typedef struct OS_EventList OS_EventList; +struct OS_EventList +{ + OS_Event *first; + OS_Event *last; + U64 count; +}; + +//////////////////////////////// +//~ Event Helpers +root_function U64 OS_character_from_key(OS_Key key); +root_function String8 OS_string_from_event(Arena *arena, OS_Event *event); +root_function B32 OS_key_press(OS_EventList *events, OS_Handle window, OS_Key key); +root_function B32 OS_key_release(OS_EventList *events, OS_Handle window); +root_function B32 OS_text_codepoint(OS_EventList *events, OS_Handle window, U32 codepoint); +root_function Vec2_F32 OS_mouse_from_window(OS_Handle handle); + +//////////////////////////////// +//~ @os_per_backend Init and windowing +root_function OS_InitGfxReceipt OS_gfx_init(OS_InitReceipt os_init_receipt); +root_function OS_Handle OS_window_open(OS_Window_Flags flags, Vec2_S64 size, String8 title); +root_function Rng2_F32 OS_client_rect_from_window(OS_Handle window_handle); + +//////////////////////////////// +//~ @os_per_backend Events +root_function OS_EventList OS_get_events(Arena *arena); +root_function void OS_consume_event(OS_EventList *events, OS_Event *event); + +#endif /* OS_GFX_H */ diff --git a/src/os/os_gfx_meta.c b/src/os/os_gfx_meta.c new file mode 100644 index 0000000..5df8d70 --- /dev/null +++ b/src/os/os_gfx_meta.c @@ -0,0 +1,95 @@ +String8 os_g_key_string_table[92] = +{ + str8_lit_comp("Null"), + str8_lit_comp("Escape"), + str8_lit_comp("F1"), + str8_lit_comp("F2"), + str8_lit_comp("F3"), + str8_lit_comp("F4"), + str8_lit_comp("F5"), + str8_lit_comp("F6"), + str8_lit_comp("F7"), + str8_lit_comp("F8"), + str8_lit_comp("F9"), + str8_lit_comp("F10"), + str8_lit_comp("F11"), + str8_lit_comp("F12"), + str8_lit_comp("F13"), + str8_lit_comp("F14"), + str8_lit_comp("F15"), + str8_lit_comp("F16"), + str8_lit_comp("F17"), + str8_lit_comp("F18"), + str8_lit_comp("F19"), + str8_lit_comp("F20"), + str8_lit_comp("F21"), + str8_lit_comp("F22"), + str8_lit_comp("F23"), + str8_lit_comp("F24"), + str8_lit_comp("Grave Accent"), + str8_lit_comp("0"), + str8_lit_comp("1"), + str8_lit_comp("2"), + str8_lit_comp("3"), + str8_lit_comp("4"), + str8_lit_comp("5"), + str8_lit_comp("6"), + str8_lit_comp("7"), + str8_lit_comp("8"), + str8_lit_comp("9"), + str8_lit_comp("Minus"), + str8_lit_comp("Equal"), + str8_lit_comp("Backspace"), + str8_lit_comp("Delete"), + str8_lit_comp("Tab"), + str8_lit_comp("A"), + str8_lit_comp("B"), + str8_lit_comp("C"), + str8_lit_comp("D"), + str8_lit_comp("E"), + str8_lit_comp("F"), + str8_lit_comp("G"), + str8_lit_comp("H"), + str8_lit_comp("I"), + str8_lit_comp("J"), + str8_lit_comp("K"), + str8_lit_comp("L"), + str8_lit_comp("M"), + str8_lit_comp("N"), + str8_lit_comp("O"), + str8_lit_comp("P"), + str8_lit_comp("Q"), + str8_lit_comp("R"), + str8_lit_comp("S"), + str8_lit_comp("T"), + str8_lit_comp("U"), + str8_lit_comp("V"), + str8_lit_comp("W"), + str8_lit_comp("X"), + str8_lit_comp("Y"), + str8_lit_comp("Z"), + str8_lit_comp("Space"), + str8_lit_comp("Enter"), + str8_lit_comp("Ctrl"), + str8_lit_comp("Shift"), + str8_lit_comp("Alt"), + str8_lit_comp("Up"), + str8_lit_comp("Left"), + str8_lit_comp("Down"), + str8_lit_comp("Right"), + str8_lit_comp("Page Up"), + str8_lit_comp("Page Down"), + str8_lit_comp("Home"), + str8_lit_comp("End"), + str8_lit_comp("Forward Slash"), + str8_lit_comp("Period"), + str8_lit_comp("Comma"), + str8_lit_comp("Quote"), + str8_lit_comp("Left Bracket"), + str8_lit_comp("Right Bracket"), + str8_lit_comp("Insert"), + str8_lit_comp("Left Mouse Button"), + str8_lit_comp("Middle Mouse Button"), + str8_lit_comp("Right Mouse Button"), + str8_lit_comp("Semicolon"), +}; diff --git a/src/os/os_gfx_meta.h b/src/os/os_gfx_meta.h new file mode 100644 index 0000000..1cc6b07 --- /dev/null +++ b/src/os/os_gfx_meta.h @@ -0,0 +1,114 @@ +/* date = April 5th 2024 7:56 pm */ + +#ifndef OS_GFX_META_H +#define OS_GFX_META_H + +// TODO(anton): This is generated code in Ryans codebase. I just copy it here now and make some generation +// myself later. + + +typedef enum OS_Key +{ + OS_Key_Null, + OS_Key_Esc, + OS_Key_F1, + OS_Key_F2, + OS_Key_F3, + OS_Key_F4, + OS_Key_F5, + OS_Key_F6, + OS_Key_F7, + OS_Key_F8, + OS_Key_F9, + OS_Key_F10, + OS_Key_F11, + OS_Key_F12, + OS_Key_F13, + OS_Key_F14, + OS_Key_F15, + OS_Key_F16, + OS_Key_F17, + OS_Key_F18, + OS_Key_F19, + OS_Key_F20, + OS_Key_F21, + OS_Key_F22, + OS_Key_F23, + OS_Key_F24, + OS_Key_GraveAccent, + OS_Key_0, + OS_Key_1, + OS_Key_2, + OS_Key_3, + OS_Key_4, + OS_Key_5, + OS_Key_6, + OS_Key_7, + OS_Key_8, + OS_Key_9, + OS_Key_Minus, + OS_Key_Equal, + OS_Key_Backspace, + OS_Key_Delete, + OS_Key_Tab, + OS_Key_A, + OS_Key_B, + OS_Key_C, + OS_Key_D, + OS_Key_E, + OS_Key_F, + OS_Key_G, + OS_Key_H, + OS_Key_I, + OS_Key_J, + OS_Key_K, + OS_Key_L, + OS_Key_M, + OS_Key_N, + OS_Key_O, + OS_Key_P, + OS_Key_Q, + OS_Key_R, + OS_Key_S, + OS_Key_T, + OS_Key_U, + OS_Key_V, + OS_Key_W, + OS_Key_X, + OS_Key_Y, + OS_Key_Z, + OS_Key_Space, + OS_Key_Enter, + OS_Key_Ctrl, + OS_Key_Shift, + OS_Key_Alt, + OS_Key_Up, + OS_Key_Left, + OS_Key_Down, + OS_Key_Right, + OS_Key_PageUp, + OS_Key_PageDown, + OS_Key_Home, + OS_Key_End, + OS_Key_ForwardSlash, + OS_Key_Period, + OS_Key_Comma, + OS_Key_Quote, + OS_Key_LeftBracket, + OS_Key_RightBracket, + OS_Key_Insert, + OS_Key_MouseLeft, + OS_Key_MouseMiddle, + OS_Key_MouseRight, + OS_Key_Semicolon, + OS_Key_COUNT, +} +OS_Key; + +root_global String8 os_g_key_string_table[92]; + + + + + +#endif //OS_GFX_META_H diff --git a/src/os/os_inc.c b/src/os/os_inc.c new file mode 100644 index 0000000..9fa5346 --- /dev/null +++ b/src/os/os_inc.c @@ -0,0 +1,9 @@ +#include "os/os_core.c" +#include "os/os_gfx.c" + +#if OS_WINDOWS +#include "win32/os_core_win32.c" +#include "win32/os_gfx_win32.c" +#else +# error OS layer for this platform not implemented yet +#endif \ No newline at end of file diff --git a/src/os/os_inc.h b/src/os/os_inc.h new file mode 100644 index 0000000..876d7b4 --- /dev/null +++ b/src/os/os_inc.h @@ -0,0 +1,28 @@ +#ifndef OS_INC_H +#define OS_INC_H + +// TODO(anton): Change this to OS implementations of the memory +#if !defined(m_reserve) +#define m_reserve OS_reserve +#endif +#if !defined(m_commit) +#define m_commit OS_commit +#endif +#if !defined(m_decommit) +#define m_decommit OS_decommit +#endif +#if !defined(m_release) +#define m_release OS_release +#endif + +#include "os/os_core.h" +#include "os/os_gfx.h" + +#if OS_WINDOWS +# include "win32/os_core_win32.h" +# include "win32/os_gfx_win32.h" +#else +# error OS layer for this platform not implemented yet +#endif + +#endif //OS_INC_H diff --git a/src/os/win32/os_core_win32.c b/src/os/win32/os_core_win32.c new file mode 100644 index 0000000..070e8bd --- /dev/null +++ b/src/os/win32/os_core_win32.c @@ -0,0 +1,299 @@ +#pragma comment(lib, "user32") +#pragma comment(lib, "winmm") +#pragma comment(lib, "shell32") +#pragma comment(lib, "Shlwapi.lib") + +//~ Memory +root_function U64 +OS_page_size(void) { + SYSTEM_INFO info; + GetSystemInfo(&info); + return info.dwPageSize; +} + +root_function void +*OS_reserve(U64 size) { + U64 gb_snapped_size = size; + // Align the reserved memory to nearest gigabyte? + gb_snapped_size += M_DEFAULT_RESERVE_SIZE - 1; + gb_snapped_size -= gb_snapped_size % M_DEFAULT_RESERVE_SIZE; + void *ptr = VirtualAlloc(0, gb_snapped_size, MEM_RESERVE, PAGE_NOACCESS); + return ptr; +} + +root_function void +OS_release(void *ptr, U64 size) { + VirtualFree(ptr, 0, MEM_RELEASE); +} + +root_function void +OS_commit(void *ptr, U64 size) { + U64 page_snapped_size = size; + page_snapped_size += OS_page_size() - 1; + page_snapped_size -= page_snapped_size%OS_page_size(); + VirtualAlloc(ptr, page_snapped_size, MEM_COMMIT, PAGE_READWRITE); +} + +root_function void +OS_decommit(void *ptr, U64 size){ + VirtualFree(ptr, size, MEM_DECOMMIT); +} + +//~ Thread +root_function OS_InitReceipt OS_init(void) +{ + if (is_main_thread() && os_g_w32_state == 0) + { + Arena *arena = m_make_arena_reserve(Gigabytes(1)); + os_g_w32_state = PushArray(arena, OS_W32_State, 1); + os_g_w32_state->arena = arena; + + os_g_w32_state->thread_arena = m_make_arena_reserve(Kilobytes(256)); + + } + + OS_InitReceipt out; + out.u64[0] = 1; + return out; +} + + +root_function void OS_thread_context_set(void *ptr) { + TlsSetValue(os_g_w32_state->thread_context_index, ptr); +} + +root_function void* OS_thread_context_get(void) { + void *result = TlsGetValue(os_g_w32_state->thread_context_index); + return result; +} + +/* // TODO(anton): This is an interesting function to protect virtual allocs, but it doesn't look like it's +used in the app template right now. I'll add it when I need it. +root_function void +OS_set_memory_access_flags(void *ptr, U64 size, OS_AccessFlags flags) { + + U64 page_snapped_size = size; + page_snapped_size += OS_page_size() - 1; + page_snapped_size -= page_snapped_size%OS_page_size(); + + + DWORD new_flags = 0; + { + switch(flags) + { + default: + { + new_flags = PAGE_NOACCESS; + }break; +#define Map(win32_code, bitflags) case bitflags:{new_flags = win32_code;}break + Map(PAGE_EXECUTE, OS_AccessFlag_Execute); + Map(PAGE_EXECUTE_READ, OS_AccessFlag_Execute|OS_AccessFlag_Read); + Map(PAGE_EXECUTE_READWRITE, OS_AccessFlag_Execute|OS_AccessFlag_Read|OS_AccessFlag_Write); + Map(PAGE_EXECUTE_WRITECOPY, OS_AccessFlag_Execute|OS_AccessFlag_Write); + Map(PAGE_READONLY, OS_AccessFlag_Read); + Map(PAGE_READWRITE, OS_AccessFlag_Read|OS_AccessFlag_Write); +#undef Map + } + } + + + DWORD old_flags = 0; + VirtualProtect(ptr, page_snapped_size, new_flags, &old_flags); +} +*/ + + + +//~ @os_per_backend File System +root_function OS_Handle +OS_file_open(OS_AccessFlags access_flags, String8 path) { + ArenaTemp scratch = scratch_get(0, 0); + String16 path16 = str16_from8(scratch.arena, path); + + // Map to win32 access flags + DWORD desired_access = 0; + if(access_flags & OS_AccessFlag_Read) { desired_access |= GENERIC_READ; } + if(access_flags & OS_AccessFlag_Write) { desired_access |= GENERIC_WRITE; } + + DWORD share_mode = 0; + + SECURITY_ATTRIBUTES security_attributes = { + (DWORD)sizeof(SECURITY_ATTRIBUTES), + 0, + 0, + }; + + // Map to win32 creation disposition + DWORD creation_disposition = 0; + if(!(access_flags & OS_AccessFlag_CreateNew)) { + creation_disposition = OPEN_EXISTING; + } else { + creation_disposition = CREATE_ALWAYS; + } + + + DWORD flags_and_attribs = 0; + HANDLE template_file = 0; + + HANDLE file = CreateFileW((WCHAR*)path16.str, + desired_access, + share_mode, + &security_attributes, + creation_disposition, + flags_and_attribs, + template_file); + + if(file == INVALID_HANDLE_VALUE) { + // TODO(anton): Append to errors + // + DWORD error = GetLastError(); + break_debugger(); + } + + // Map to abstract handle + OS_Handle handle = {0}; + handle.u64[0] = (U64)file; + + scratch_release(scratch); + return handle; +} + +root_function void +OS_file_close(OS_Handle file) { + HANDLE handle = (HANDLE)file.u64[0]; + if(handle != INVALID_HANDLE_VALUE) { + CloseHandle(handle); + } +} + +root_function String8 +OS_file_read(Arena *arena, OS_Handle file, U64 min, U64 max) { + String8 result = {0}; + + HANDLE handle = (HANDLE)file.u64[0]; + if(handle == INVALID_HANDLE_VALUE) { + // TODO(anton): accumulate errors + } else { + U64 bytes_to_read = AbsoluteValueU64(max - min); + U64 bytes_actually_read = 0; + result.str = PushArray(arena, U8, bytes_to_read); + result.size = 0; + U8 *ptr = result.str; + U8 *one_past_last = result.str + bytes_to_read; + + for(;;) { + U64 unread = (U64)(one_past_last - ptr); + DWORD to_read = (DWORD)(ClampTop(unread, U32Max)); + DWORD did_read = 0; + // TODO(anton): Understand WINAPI + if(!ReadFile(handle, ptr, to_read, &did_read, 0)) { + break; + } + ptr += did_read; + result.size += did_read; + if(ptr >= one_past_last) { + break; + } + + } + } + return result; +} + +root_function OS_FileAttributes +OS_attributes_from_file(OS_Handle file) +{ + HANDLE handle = (HANDLE)file.u64[0]; + OS_FileAttributes attrs = {0}; + U32 high_bits = 0; + U32 low_bits = GetFileSize(handle, (DWORD *)&high_bits); + FILETIME last_write_time = {0}; + GetFileTime(handle, 0, 0, &last_write_time); + attrs.size = (U64)low_bits | (((U64)high_bits) << 32); + attrs.last_modified = ((U64)last_write_time.dwLowDateTime) | + (((U64)last_write_time.dwHighDateTime) << 32); + return attrs; +} + +root_function void +OS_file_write(Arena *arena, OS_Handle file, U64 off, String8List data, OS_ErrorList *out_errors) { + HANDLE handle = (HANDLE)file.u64[0]; + if(handle == 0 || handle == INVALID_HANDLE_VALUE) + { + // TODO(anton): accumulate errors + } + else for(String8Node *node = data.first; node != 0; node = node->next) + { + U8 *ptr = node->string.str; + U8 *opl = ptr + node->string.size; + for(;;) + { + U64 unwritten = (U64)(opl - ptr); + DWORD to_write = (DWORD)(ClampTop(unwritten, U32Max)); + DWORD did_write = 0; + // TODO(anton): understand winapi + if(!WriteFile(handle, ptr, to_write, &did_write, 0)) + { + goto fail_out; + } + ptr += did_write; + if(ptr >= opl) + { + break; + } + } + } + fail_out:; +} + +root_function Rng2_F32 +OS_client_rect_from_window(OS_Handle window_handle) +{ + Rng2_F32 rect = {0}; + OS_W32_Window *window = (OS_W32_Window *)window_handle.u64[0]; + if(window != 0) + { + RECT w32_rect = {0}; + if(GetClientRect(window->hwnd, &w32_rect)) + { + rect.x0 = (F32)w32_rect.left; + rect.y0 = (F32)w32_rect.top; + rect.x1 = (F32)w32_rect.right; + rect.y1 = (F32)w32_rect.bottom; + } + } + return rect; +} + +root_function String8List +OS_to_string_list_F64(Arena *arena, F64 *values, U32 values_size, String8 format) +{ + // Parse the format string, assume it is of the form + // numchars.precisione\n, for example "13.6e" + if(format.size < 3 || format.str[2] != '.') + { + break_debugger(); + OutputDebugStringA("Wrong format when converting values to string list"); + exit(1); + } + U8 first_parse[3]; + first_parse[0] = format.str[0]; + first_parse[1] = format.str[1]; + first_parse[2] = '\0'; + // We can add space for the dot right away since this is assumed in the formatting. + U32 character_length = (U32)StrToIntA(first_parse) + 1; + + + String8List out = {0}; + for(U32 i = 0; i < values_size; i++) + { + String8 value_string = {0}; + value_string.size = character_length; + value_string.str = PushArrayZero(arena, U8, character_length); + StringCchPrintfA(value_string.str, character_length, "%e\n", values[i]); + str8_list_push(arena, &out, value_string); + } + + return out; +} + diff --git a/src/os/win32/os_core_win32.h b/src/os/win32/os_core_win32.h new file mode 100644 index 0000000..e7b1e26 --- /dev/null +++ b/src/os/win32/os_core_win32.h @@ -0,0 +1,51 @@ +/* date = April 25th 2023 9:46 pm */ + +#ifndef OS_CORE_WIN32_H +#define OS_CORE_WIN32_H + +// To avoid C4042 error when including windows we use some +// preprocessor praga macro things.. So when including the windows headers we +// won't have defined the "function" keyword (we define it in base_core.h), +// and then we redefine it after when popping. +#pragma push_macro("function") +#undef function +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#pragma pop_macro("function") + + +// We have a nice debugbreak assert macro, but it is nice to have one also specifically for windows HRESULT +#define AssertHR(hr) Assert(SUCCEEDED(hr)) + +///////////////////////////////////// + +// Processes and threads +typedef struct OS_W32_Thread OS_W32_Thread; +struct OS_W32_Thread +{ + OS_W32_Thread *next; + HANDLE handle; + DWORD thread_id; + void *params; + OS_Thread_Function *func; +}; + + +///////////////////////////////////// +// Global state +typedef struct OS_W32_State OS_W32_State; +struct OS_W32_State +{ + Arena *arena; + + Arena *thread_arena; + DWORD thread_context_index; +}; + +global HINSTANCE os_g_w32_hinstance; +global OS_W32_State *os_g_w32_state; + +//root_function OS_W32_Window* OS_W32_window_from_handle(OS_Handle handle); +#endif //OS_CORE_WIN32_H diff --git a/src/os/win32/os_entry_point_win32.c b/src/os/win32/os_entry_point_win32.c new file mode 100644 index 0000000..fa4078e --- /dev/null +++ b/src/os/win32/os_entry_point_win32.c @@ -0,0 +1,9 @@ +function void EntryPoint(void); + + +int WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR lp_cmd_line, int n_show_cmd) +{ + os_g_w32_hinstance = instance; + base_main_thread_entry(EntryPoint, (U64)__argc, __argv); + return 0; +} \ No newline at end of file diff --git a/src/os/win32/os_gfx_win32.c b/src/os/win32/os_gfx_win32.c new file mode 100644 index 0000000..5d0a28f --- /dev/null +++ b/src/os/win32/os_gfx_win32.c @@ -0,0 +1,328 @@ +#pragma comment(lib, "gdi32") + +#define OS_W32_GraphicalWindowClassName L"ApplicationWindowClass" + +root_function OS_InitGfxReceipt +OS_gfx_init(OS_InitReceipt os_init_receipt) +{ + if (is_main_thread() && os_g_w32_gfx_state == 0) + { + + { + // Global state + Arena *arena = m_make_arena_reserve(Gigabytes(1)); + os_g_w32_gfx_state = PushArray(arena, OS_W32_Gfx_State, 1); + os_g_w32_gfx_state->arena = arena; + os_g_w32_gfx_state->window_arena = m_make_arena_reserve(Gigabytes(1)); + } + // TODO(antonl) DPI awareness + + // Register window class + { + /* WNDCLASSW window_class = { 0 }; */ + /* window_class.style = CS_HREDRAW | CS_VREDRAW; */ + /* window_class.lpfnWndProc = OS_W32_WindowProc; */ + /* window_class.hInstance = g_os_w32_hinstance; */ + /* window_class.lpszClassName = OS_W32_GraphicalWindowClassName; */ + /* window_class.hCursor = LoadCursor(0, IDC_ARROW); */ + /* RegisterClassW(&window_class); */ + WNDCLASSEXW window_class = {0}; + window_class.cbSize = sizeof(WNDCLASSEXW); + window_class.lpfnWndProc = OS_W32_window_proc; + window_class.hInstance = os_g_w32_hinstance; + window_class.lpszClassName = OS_W32_GraphicalWindowClassName; + if(!RegisterClassExW(&window_class)) + { + break_debugger(); + } + } + + // Rjf makes a "global invisible window", but why? + { + os_g_w32_gfx_state->global_hwnd = CreateWindowExW(0, + OS_W32_GraphicalWindowClassName, + L"", + WS_OVERLAPPEDWINDOW, + 100,100, + 0,0, + 0,0, + os_g_w32_hinstance, 0); + os_g_w32_gfx_state->global_hdc = GetDC(os_g_w32_gfx_state->global_hwnd); + } + } + + OS_InitGfxReceipt out; + out.u64[0] = 1; + return out; +} + +root_function OS_Handle +OS_W32_handle_from_window(OS_W32_Window *window) +{ + OS_Handle handle = { 0 }; + handle.u64[0] = (U64)window; + return handle; +} + +root_function OS_W32_Window* +OS_W32_window_from_handle(OS_Handle handle) +{ + OS_W32_Window *window = (OS_W32_Window *)handle.u64[0]; + return window; +} + +root_function OS_Handle +OS_window_open(OS_Window_Flags flags, Vec2_S64 size, String8 title) +{ + OS_Handle handle = { 0 }; + + { + // Window allocation + OS_W32_Window *window = os_g_w32_gfx_state->free_window; + { + // Windows are stored in a stack on the gfx state + if (window != 0) + { + StackPop(os_g_w32_gfx_state->free_window); + } + else + { + window = PushArray(os_g_w32_gfx_state->window_arena, OS_W32_Window, 1); + } + MemoryZeroStruct(window); + DLLPushBack(os_g_w32_gfx_state->first_window, os_g_w32_gfx_state->last_window, window); + } + + // Open window + HWND hwnd = 0; + HDC hdc = 0; + { + ArenaTemp scratch = scratch_get(0, 0); + String16 title16 = str16_from8(scratch.arena, title); + hwnd = CreateWindowExW(0, + OS_W32_GraphicalWindowClassName, (LPCWSTR)title16.str, + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, + size.x, size.y, 0, 0, os_g_w32_hinstance, 0); + hdc = GetDC(hwnd); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)window); + scratch_release(scratch); + } + + { + window->hwnd = hwnd; + window->hdc = hdc; + } + + handle = OS_W32_handle_from_window(window); + } + return handle; +} + +function LRESULT +OS_W32_window_proc(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param) +{ + LRESULT result = 0; + + OS_Event *event = 0; + OS_W32_Window *window = (OS_W32_Window *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + OS_Handle window_handle = OS_W32_handle_from_window(window); + ArenaTemp scratch = scratch_get(&os_w32_tl_events_arena, 1); + OS_EventList fallback_event_list = {0}; + if(os_w32_tl_events_arena == 0) + { + os_w32_tl_events_arena = scratch.arena; + os_w32_tl_events_list = &fallback_event_list; + } + + B32 is_release = 0; + Axis2 scroll_axis = Axis2_Y; + switch(message) + { + default: + { + result = DefWindowProcW(hwnd, message, w_param, l_param); + } break; + + //- General window events + case WM_CLOSE: + { + event = PushArray(os_w32_tl_events_arena, OS_Event, 1); + event->kind = OS_EventKind_WindowClose; + event->window = window_handle; + } break; + + //- Mouse buttons + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + { + ReleaseCapture(); + is_release = 1; + } fallthrough; + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + { + if(is_release == 0) + { + SetCapture(hwnd); + } + OS_EventKind kind = is_release ? OS_EventKind_Release : OS_EventKind_Press; + OS_Key key = OS_Key_MouseLeft; + switch(message) + { + case WM_MBUTTONUP: case WM_MBUTTONDOWN: key = OS_Key_MouseMiddle; break; + case WM_RBUTTONUP: case WM_RBUTTONDOWN: key = OS_Key_MouseRight; break; + } + event = PushArray(os_w32_tl_events_arena, OS_Event, 1); + event->kind = kind; + event->window = window_handle; + event->key = key; + event->position = OS_mouse_from_window(window_handle); + } break; + + //- Keyboard events + case WM_SYSKEYDOWN: case WM_SYSKEYUP: + { + result = DefWindowProcW(hwnd, message, w_param, l_param); + } fallthrough; + case WM_KEYDOWN: + case WM_KEYUP: + { + // TODO(anton): Just check this thing with was down, is down.., WINAPI crap + B32 was_down = !!(l_param & (1 << 30)); + B32 is_down = !(l_param & (1 << 31)); + OS_EventKind kind = is_down ? OS_EventKind_Press : OS_EventKind_Release; + + // TODO(anton): Here we use statics but maybe we should not... + // Could just move this out and pre-init or generate it and include or whatever... + // probably should just be in some meta header. + local_persist OS_Key key_table[256] = {0}; + local_persist B32 key_table_initialised = 0; + if(!key_table_initialised) + { + key_table_initialised = 1; + + for (U32 i = 'A', j = OS_Key_A; i <= 'Z'; i += 1, j += 1) + { + key_table[i] = (OS_Key)j; + } + for (U32 i = '0', j = OS_Key_0; i <= '9'; i += 1, j += 1) + { + key_table[i] = (OS_Key)j; + } + for (U32 i = VK_F1, j = OS_Key_F1; i <= VK_F24; i += 1, j += 1) + { + key_table[i] = (OS_Key)j; + } + + key_table[VK_ESCAPE] = OS_Key_Esc; + key_table[VK_OEM_3] = OS_Key_GraveAccent; + key_table[VK_OEM_MINUS] = OS_Key_Minus; + key_table[VK_OEM_PLUS] = OS_Key_Equal; + key_table[VK_BACK] = OS_Key_Backspace; + key_table[VK_TAB] = OS_Key_Tab; + key_table[VK_SPACE] = OS_Key_Space; + key_table[VK_RETURN] = OS_Key_Enter; + key_table[VK_CONTROL] = OS_Key_Ctrl; + key_table[VK_SHIFT] = OS_Key_Shift; + key_table[VK_MENU] = OS_Key_Alt; + key_table[VK_UP] = OS_Key_Up; + key_table[VK_LEFT] = OS_Key_Left; + key_table[VK_DOWN] = OS_Key_Down; + key_table[VK_RIGHT] = OS_Key_Right; + key_table[VK_DELETE] = OS_Key_Delete; + key_table[VK_PRIOR] = OS_Key_PageUp; + key_table[VK_NEXT] = OS_Key_PageDown; + key_table[VK_HOME] = OS_Key_Home; + key_table[VK_END] = OS_Key_End; + key_table[VK_OEM_2] = OS_Key_ForwardSlash; + key_table[VK_OEM_PERIOD] = OS_Key_Period; + key_table[VK_OEM_COMMA] = OS_Key_Comma; + key_table[VK_OEM_7] = OS_Key_Quote; + key_table[VK_OEM_4] = OS_Key_LeftBracket; + key_table[VK_OEM_6] = OS_Key_RightBracket; + key_table[VK_INSERT] = OS_Key_Insert; + key_table[VK_OEM_1] = OS_Key_Semicolon; + } + + OS_Key key = OS_Key_Null; + if(w_param < ArrayCount(key_table)) + { + key = key_table[w_param]; + } + + event = PushArray(os_w32_tl_events_arena, OS_Event, 1); + event->kind = kind; + event->window = window_handle; + event->key = key; + } break; + + + } + // If we registered an event we push it to the event list. + if(event) + { + DLLPushBack(os_w32_tl_events_list->first, os_w32_tl_events_list->last, event); + os_w32_tl_events_list->count += 1; + } + + scratch_release(scratch); + return result; +} + +root_function Vec2_F32 +OS_mouse_from_window(OS_Handle handle) +{ + Vec2_F32 result = vec2_F32(-100, -100); + OS_W32_Window *window = OS_W32_window_from_handle(handle); + if(window != 0) + { + POINT point; + if(GetCursorPos(&point)) + { + if(ScreenToClient(window->hwnd, &point)) + { + result = vec2_F32(point.x, point.y); + } + } + } + + return result; +} + +root_function OS_EventList +OS_get_events(Arena* arena) +{ + OS_EventList list = {0}; + os_w32_tl_events_arena = arena; + os_w32_tl_events_list = &list; + for(MSG message; PeekMessage(&message, 0, 0, 0, PM_REMOVE);) + { + TranslateMessage(&message); + DispatchMessage(&message); + } + os_w32_tl_events_arena = 0; + os_w32_tl_events_list = 0; + + return list; +} + +root_function void +OS_consume_event(OS_EventList *events, OS_Event *event) +{ + DLLRemove(events->first, events->last, event); + events->count -= 1; + event->kind = OS_EventKind_Null; +} + +root_function void +OS_window_first_paint(OS_Handle handle) +{ + ArenaTemp scratch = scratch_get(0,0); + OS_W32_Window *window = OS_W32_window_from_handle(handle); + ShowWindow(window->hwnd, SW_SHOW); + UpdateWindow(window->hwnd); + scratch_release(scratch); +} \ No newline at end of file diff --git a/src/os/win32/os_gfx_win32.h b/src/os/win32/os_gfx_win32.h new file mode 100644 index 0000000..76a0f06 --- /dev/null +++ b/src/os/win32/os_gfx_win32.h @@ -0,0 +1,36 @@ +#ifndef OS_GFX_WIN32_H +#define OS_GFX_WIN32_H + +typedef struct OS_W32_Window OS_W32_Window; +struct OS_W32_Window +{ + OS_W32_Window *next; + OS_W32_Window *prev; + HWND hwnd; + HDC hdc; +}; + +typedef struct OS_W32_Gfx_State OS_W32_Gfx_State; +struct OS_W32_Gfx_State +{ + Arena *arena; + HWND global_hwnd; + HDC global_hdc; + + Arena *window_arena; + OS_W32_Window *first_window; + OS_W32_Window *last_window; + OS_W32_Window *free_window; +}; + +root_global OS_W32_Gfx_State *os_g_w32_gfx_state = 0; +extern per_thread Arena *os_w32_tl_events_arena = 0; +extern per_thread OS_EventList *os_w32_tl_events_list = 0; + +root_function OS_Handle OS_W32_handle_from_window(OS_W32_Window *window); +root_function OS_W32_Window *OS_W32_window_from_handle(OS_Handle handle); +function LRESULT OS_W32_window_proc(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param); + + + +#endif // OS_GFX_WIN32_H diff --git a/timeBuild.ctm b/timeBuild.ctm index b2cd111..e7ef7ed 100644 Binary files a/timeBuild.ctm and b/timeBuild.ctm differ