diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index b8e5368..771e710 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -12,8 +12,8 @@ jobs: - ubuntu-20.04 - windows-latest ocaml-version: - - 4.10.1 - - 4.11.1 + - 4.10.x + - 4.13.x env: OCAML_VERSION: ${{ matrix.ocaml-version }} @@ -23,25 +23,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - - name: Cached Infra - uses: actions/cache@v2 - env: - cache-name: cached-opam - with: - path: | - ~/.opam - _build - C:\cygwin - D:/a/eigen/eigen - key: ${{ matrix.os }}-${{ matrix.ocaml-version }}-${{ env.cache-name }}-${{ hashFiles('**/*.opam*') }} - restore-keys: | - ${{ matrix.os }}-${{ matrix.ocaml-version }}-${{ env.cache-name }}- - ${{ matrix.os }}-${{ matrix.ocaml-version }}- - ${{ matrix.os }}- - name: Use OCaml ${{ matrix.ocaml-version }} - uses: avsm/setup-ocaml@v1 + uses: avsm/setup-ocaml@v2 with: ocaml-version: ${{ matrix.ocaml-version }} diff --git a/README.md b/README.md index d66c630..a6d091a 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,12 @@ If you have questions or suggestions, please contact me via [Email](liang.wang@c ## Optional configuration -You can customise the optimization flags used to compile the C++ libeigen by setting `EIGENCPP_OPTFLAGS`, the default value is +You can customise the optimization flags used to compile the C++ libeigen by setting `EIGENCPP_OPTFLAGS`, the default value for `x86_64` is ``` EIGENCPP_OPTFLAGS = -Ofast -march=native -funroll-loops -ffast-math ``` -Similarly you can customise the optimization flags used to compile the eigen library by setting `EIGEN_FLAGS`, the default value is +Similarly you can customise the optimization flags used to compile the eigen library by setting `EIGEN_FLAGS`, the default value for `x86_64` is ``` EIGEN_FLAGS = -O3 -Ofast -march=native -funroll-loops -ffast-math ``` diff --git a/eigen.opam b/eigen.opam index 4bb534a..f8226ab 100644 --- a/eigen.opam +++ b/eigen.opam @@ -13,6 +13,7 @@ depends: [ "ocaml" {>= "4.02"} "ctypes" {>= "0.14.0"} "dune" {>= "2.0.0"} + "dune-configurator" ] synopsis: "Owl's OCaml interface to Eigen3 C++ library" description: diff --git a/eigen/configure/configure.ml b/eigen/configure/configure.ml new file mode 100644 index 0000000..94bbb91 --- /dev/null +++ b/eigen/configure/configure.ml @@ -0,0 +1,106 @@ +(* + * OWL - OCaml Scientific and Engineering Computing + * Copyright (c) 2016-2022 Liang Wang + *) + +module C = Configurator.V1 + +let detect_system_header = + {| + #if __APPLE__ + #include + #if TARGET_OS_IPHONE + #define PLATFORM_NAME "ios" + #else + #define PLATFORM_NAME "mac" + #endif + #elif __linux__ + #if __ANDROID__ + #define PLATFORM_NAME "android" + #else + #define PLATFORM_NAME "linux" + #endif + #elif WIN32 + #define PLATFORM_NAME "windows" + #endif +|} + +let detect_system_arch = + {| + #if __x86_64__ + #define PLATFORM_ARCH "x86_64" + #elif __i386__ + #define PLATFORM_ARCH "x86" + #elif __aarch64__ + #define PLATFORM_ARCH "arm64" + #elif __arm__ + #define PLATFORM_ARCH "arm" + #else + #define PLATFORM_ARCH "unknown" + #endif +|} + +let default_cflags c = + try + Sys.getenv "EIGEN_FLAGS" + |> String.split_on_char ' ' + |> List.filter (fun s -> String.trim s <> "") + with + | Not_found -> + let os = + let header = + let file = Filename.temp_file "discover" "os.h" in + let fd = open_out file in + output_string fd detect_system_header; + close_out fd; + file + in + let platform = + C.C_define.import c ~includes:[ header ] [ "PLATFORM_NAME", String ] + in + match List.map snd platform with + | [ String "android" ] -> `android + | [ String "ios" ] -> `ios + | [ String "linux" ] -> `linux + | [ String "mac" ] -> `mac + | [ String "windows" ] -> `windows + | _ -> `unknown + in + let arch = + let header = + let file = Filename.temp_file "discover" "arch.h" in + let fd = open_out file in + output_string fd detect_system_arch; + close_out fd; + file + in + let arch = + C.C_define.import c ~includes:[ header ] [ "PLATFORM_ARCH", String ] + in + match List.map snd arch with + | [ String "x86_64" ] -> `x86_64 + | [ String "x86" ] -> `x86 + | [ String "arm64" ] -> `arm64 + | [ String "arm" ] -> `arm + | _ -> `unknown + in + [ (* Basic optimisation *) "-g"; "-O3"; "-Ofast" ] + @ (match arch, os with + | `arm64, `mac -> [ "-mcpu=apple-m1" ] + | `arm64, _ -> [ "-march=native" ] + | `x86_64, _ -> [ "-march=native"; "-mfpmath=sse"; "-msse2" ] + | _ -> []) + @ [ (* Experimental switches, -ffast-math may break IEEE754 semantics*) + "-funroll-loops" + ; "-ffast-math" + ] + +let () = + C.main ~name:"eigen" (fun c -> + (* configure compile options *) + let libs = [] in + let cflags = default_cflags c in + (* configure ocaml options *) + (* assemble default config *) + let conf : C.Pkg_config.package_conf = { cflags; libs } in + C.Flags.write_sexp "c_flags.sexp" conf.cflags) diff --git a/eigen/configure/dune b/eigen/configure/dune new file mode 100644 index 0000000..cb62370 --- /dev/null +++ b/eigen/configure/dune @@ -0,0 +1,3 @@ +(executable + (name configure) + (libraries dune.configurator)) diff --git a/eigen/dune b/eigen/dune index f8e1e56..1eb2bda 100644 --- a/eigen/dune +++ b/eigen/dune @@ -1,32 +1,25 @@ -(* -*- tuareg -*- *) - -let eigen_flags = - match Sys.getenv "EIGEN_FLAGS" with - | s -> String.trim s - | exception Not_found -> "-O3 -Ofast -march=native -funroll-loops -ffast-math" - -let () = Printf.ksprintf Jbuild_plugin.V1.send {| (rule (targets ffi_eigen_generated.ml) (deps ../bindings/ffi_eigen_stubgen.exe) (action (with-stdout-to - %%{targets} - (run %%{deps} -ml) - ) - ) -) + %{targets} + (run %{deps} -ml)))) (rule (targets ffi_eigen_generated_stub.c) (deps ../bindings/ffi_eigen_stubgen.exe) (action (with-stdout-to - %%{targets} - (run %%{deps} -c) - ) - ) -) + %{targets} + (run %{deps} -c)))) + +(rule + (targets c_flags.sexp) + (deps + (:deps-conf configure/configure.exe)) + (action + (run %{deps-conf}))) (library (name eigen) @@ -38,7 +31,6 @@ let () = Printf.ksprintf Jbuild_plugin.V1.send {| (language c) (names eigen_utils_stubs ffi_eigen_generated_stub) (include_dirs ../eigen_cpp/lib) - (flags :standard %s) - ) -) -|} eigen_flags + (flags + :standard + (:include c_flags.sexp)))) diff --git a/eigen_cpp/configure/configure.ml b/eigen_cpp/configure/configure.ml new file mode 100644 index 0000000..0bcc82d --- /dev/null +++ b/eigen_cpp/configure/configure.ml @@ -0,0 +1,111 @@ +(* + * OWL - OCaml Scientific and Engineering Computing + * Copyright (c) 2016-2022 Liang Wang + *) + +module C = Configurator.V1 + +let detect_system_header = + {| + #if __APPLE__ + #include + #if TARGET_OS_IPHONE + #define PLATFORM_NAME "ios" + #else + #define PLATFORM_NAME "mac" + #endif + #elif __linux__ + #if __ANDROID__ + #define PLATFORM_NAME "android" + #else + #define PLATFORM_NAME "linux" + #endif + #elif WIN32 + #define PLATFORM_NAME "windows" + #endif +|} + +let detect_system_arch = + {| + #if __x86_64__ + #define PLATFORM_ARCH "x86_64" + #elif __i386__ + #define PLATFORM_ARCH "x86" + #elif __aarch64__ + #define PLATFORM_ARCH "arm64" + #elif __arm__ + #define PLATFORM_ARCH "arm" + #else + #define PLATFORM_ARCH "unknown" + #endif +|} + +let default_cppflags c = + try + String.trim (Sys.getenv "EIGEN_OPTFLAGS") + |> String.split_on_char ' ' + |> List.filter (fun s -> String.trim s <> "") + with + | Not_found -> + let os = + let header = + let file = Filename.temp_file "discover" "os.h" in + let fd = open_out file in + output_string fd detect_system_header; + close_out fd; + file + in + let platform = + C.C_define.import c ~includes:[ header ] [ "PLATFORM_NAME", String ] + in + match List.map snd platform with + | [ String "android" ] -> `android + | [ String "ios" ] -> `ios + | [ String "linux" ] -> `linux + | [ String "mac" ] -> `mac + | [ String "windows" ] -> `windows + | _ -> `unknown + in + let arch = + let header = + let file = Filename.temp_file "discover" "arch.h" in + let fd = open_out file in + output_string fd detect_system_arch; + close_out fd; + file + in + let arch = + C.C_define.import c ~includes:[ header ] [ "PLATFORM_ARCH", String ] + in + match List.map snd arch with + | [ String "x86_64" ] -> `x86_64 + | [ String "x86" ] -> `x86 + | [ String "arm64" ] -> `arm64 + | [ String "arm" ] -> `arm + | _ -> `unknown + in + [ + "-fPIC" + ; "-ansi" + ; "-pedantic" + ; "-O3" + ; "-std=c++11" + ; "-lstdc++" + ] @ (match arch, os with + | `arm64, `mac -> [ "-mcpu=apple-m1" ] + | `arm64, _ -> [ "-march=native" ] + | `x86_64, _ -> [ "-march=native"; "-mfpmath=sse"; "-msse2" ] + | _ -> []) + @ [ (* Experimental switches, -ffast-math may break IEEE754 semantics*) + "-funroll-loops" + ; "-ffast-math" + ] + +let () = + C.main ~name:"eigen_cpp" (fun c -> + (* configure compile options *) + let libs = [] in + let cflags = default_cppflags c in + (* assemble default config *) + let conf : C.Pkg_config.package_conf = { cflags; libs } in + C.Flags.write_sexp "cpp_flags.sexp" conf.cflags) diff --git a/eigen_cpp/configure/dune b/eigen_cpp/configure/dune new file mode 100644 index 0000000..312036b --- /dev/null +++ b/eigen_cpp/configure/dune @@ -0,0 +1,5 @@ +(include_subdirs no) + +(executable + (name configure) + (libraries dune.configurator)) diff --git a/eigen_cpp/dune b/eigen_cpp/dune index b6ddf56..484289d 100644 --- a/eigen_cpp/dune +++ b/eigen_cpp/dune @@ -1,37 +1,17 @@ -(* -*- tuareg -*- *) - -let optflags = - match Sys.getenv "EIGENCPP_OPTFLAGS" with - | s -> - s - | exception Not_found -> - "-Ofast -march=native -funroll-loops -ffast-math" - -let devflags = - match Sys.getenv "EIGENCPP_DIAGNOSTIC" with - | s -> "-Wall -Wno-invalid-partial-specialization -Wno-extern-c-compat -Wno-c++11-long-long -Wno-ignored-attributes "^s - | exception Not_found -> "-w -Wno-invalid-partial-specialization" - -let () = Printf.ksprintf Jbuild_plugin.V1.send {| - (include_subdirs unqualified) +(rule + (targets cpp_flags.sexp) + (deps + (:deps-conf configure/configure.exe)) + (action + (run %{deps-conf}))) + (foreign_library (archive_name eigen_cpp_stubs) (language cxx) (names eigen_tensor eigen_dsmat eigen_spmat) (include_dirs lib lib/unsupported) (flags - :standard - -fPIC - -ansi - -pedantic - -O3 - -std=c++11 - -lstdc++ - %s - %s - ) - ) - -|} devflags optflags + :standard + (:include cpp_flags.sexp))) diff --git a/eigen_cpp/lib/unsupported/Eigen/CXX11/src/Tensor/TensorStorage.h b/eigen_cpp/lib/unsupported/Eigen/CXX11/src/Tensor/TensorStorage.h index 2854a4a..e6a666f 100644 --- a/eigen_cpp/lib/unsupported/Eigen/CXX11/src/Tensor/TensorStorage.h +++ b/eigen_cpp/lib/unsupported/Eigen/CXX11/src/Tensor/TensorStorage.h @@ -31,12 +31,12 @@ namespace Eigen { * * \sa Tensor */ -template class TensorStorage; +template class TensorStorage; // Pure fixed-size storage -template -class TensorStorage +template +class TensorStorage { private: static const std::size_t Size = FixedDimensions::total_size; @@ -66,7 +66,7 @@ class TensorStorage // pure dynamic -template +template class TensorStorage, Options_> { public: