If you have improvements, new libraries integrated under oneAPI Math Library (oneMath), or new interfaces to contribute to the oneMath Specification, please send us your pull requests! For getting started, see GitHub howto.
For how to enable a new third-party library, see the guidelines.
Before sending your pull requests, ensure that you follow this checklist:
-
If you are contributing a new interface, refer to the library functionality guidelines. It is strongly advised that you first open an RFC PR with a detailed explanation of the expected use cases.
-
Ensure that your code includes proper documentation.
-
Ensure that the changes are consistent with the coding style.
-
Ensure that unit tests pass. Include logs from tests as attachments to the pull request.
-
Ensure that corresponding maintainer GitHub team is assigned to the PR review.
oneMath focuses on the following criteria:
-
Performance: Functionality that has highly optimized and extensively parallelized routines for applications that require maximum performance.
This means that for a new primitive you should demonstrate that it brings visible performance improvement to some applications.
-
Generality: Functionality is useful in a wide range of applications.
This implies that when you introduce a new function, its API needs to be general enough to be integrated into multiple applications that have similar functionality and that its interface can support multiple hardware (HW).
-
Complexity: Functionality that is not trivial to implement directly or by combining existing primitives.
For the new API to become a part of the open source project, it should be accepted as part of oneMath spec.
For changes impacting the public API or any significant changes in the library, such as adding new backend or changes to the architecture, please follow the RFC process.
Please also provide the following details as part of the RFC:
-
Description of how the new interface meets library functionality guidelines.
-
The definition of the function including the interface and semantics, and how this interface will be extendable for different HW implementations.
-
What existing libraries have implementations of this function and can be used under oneMath.
-
Ensure that corresponding maintainer GitHub team is assigned to the RFC review.
If you find a bug or problem, please open a request under Issues.
Report security issues to onemkl.maintainers@intel.com.
For GitHub questions, issues, RFCs, or PRs you can contact maintainers via one of the following GitHub teams based on the topic:
GitHub team name | Description |
---|---|
@uxlfoundation/onemath-maintain | All oneMath maintainers |
@uxlfoundation/onemath-arch-write | oneMath Architecture maintainers |
@uxlfoundation/onemath-blas-write | oneMath BLAS maintainers |
@uxlfoundation/onemath-dft-write | oneMath DFT maintainers |
@uxlfoundation/onemath-lapack-write | oneMath LAPACK maintainers |
@uxlfoundation/onemath-rng-write | oneMath RNG maintainers |
@uxlfoundation/onemath-sparse-write | oneMath Sparse Algebra maintainers |
@uxlfoundation/onemath-vm-write | oneMath Vector Math maintainers |
Please read MAINTAINERS page for more information about maintainer roles, responsibilities, and how to become one of them.
The general principle is to follow the style of existing/surrounding code. If you are in doubt, use the clang-format
:
clang-format -style=file -i foo.cpp
This formats code using the _clang_format
file found in the oneMath top-level directory. The version of clang-format
is specified in .pre-commit-config.yaml
. Alternatively, you can install and run pre-commit
, which will install the specified clang-format
version automatically:
python3 -m venv <venv-name>
source <venv-name>/bin/activate
pip install pre-commit
cd <path-to-onemath>
pre-commit run --all-files
deactivate
By default, pre-commit
caches data in ~/.cache/pre-commit
. You can set PRE_COMMIT_HOME
to use another location.
-
GN1: Use snake_case for all type names: classes, structures, enums, template type arguments, type aliases.
-
GN2: Use snake_case for all variables (global, local, files, function parameters), global and local constants (including constexpr), functions (member, non-member) and enum values.
-
GN3: Use capitalized SNAKE_CASE only for macros.
-
GF1: Each line of text in the code shall be at most 100 characters long.
-
GF2: Use only spaces, and indent 4 spaces at a time, never use tabs.
-
GF3: The open curly brace is always on the end of the last line of the statement (type, function, namespace declaration or control flow statement), not the start of the next line.
int foo() { // <-- curly brace here
do_something();
}
if (condition) { // <-- curly brace here
do_something();
}
else { // <-- curly brace here
do_something();
}
if (condition) { // <-- curly brace here
do_something();
} else { // <-- Also possible
do_something();
}
- GF4: There is never a space between the parentheses and the parameters in function declaration/invocation or control flow statements.
// Wrong
int foo( int arg_1, float arg_2 );
if ( condition );
call_foo( value_1, value_2 );
for ( int i = 0; i < loop_count; i++ );
// Right
int foo(int arg_1, float arg_2);
if (condition);
call_foo(value_1, value_2);
for (int i = 0; i < loop_count; i++);
-
FA1: Filenames should be lowercase and can include underscores "_".
-
FA2: C++ header files exposed to the user should end in .hpp.
-
FA3: C++ source files should end in .cpp.
-
FA4: All header files shall start with
#pragma once
guards to prevent multiple inclusion, refer to Structure of Header Files for more details. -
FA5: Each header file shall contain items in the following order:
- Copyright
- Single blank line
- Preprocessor guard
- Single blank line
- Include statements (if there)
- Single blank line if include statements are present
- Global macros* (if any)
- Single blank line if macros statements are present
- Type/function declarations wrapped into namespaces
Note: It is not necessary to put all macro definitions here. Sometimes it is convenient to have macros closer to the place where they are used. For example, sometimes it makes more sense to define macros inside the functions that use them (see Macros for more details). However, if the macro is used throughout the library, put it in header file between includes and the namespace declaration.
-
FA6: Each header file shall include other header files in the following order:
- C standard headers
- C++ standard headers
- Single blank line if C/C++ headers are present
- Third party libraries' header files (e.g., SYCL, TBB, OMP, etc.)
- Single blank line if third party headers are present
- Project's header files
-
NS1: Use snake_case: all lowercase, with underscores "_" between words for all namespaces.
-
NS2: The name of a top-level namespace must be the name of the project (oneMath).
-
NS3: Do not indent content inside a namespace scope.
// Wrong! Do not indent
namespace oneapi {
namespace math {
class table { };
} // namespace math
} // namespace oneapi
// Right
namespace oneapi {
namespace math {
class table { };
} // namespace math
} // namespace oneapi
- NS4: Put each namespace on its own line when declaring nested namespaces.
#include "oneapi/math/blas/path_to_some_header.hpp"
namespace oneapi {
namespace math {
namespace blas {
/* ... */
} // namespace blas
} // namespace math
} // namespace oneapi
- FU1: Use snake_case: all lowercase, with
// Underscores between words for all function names.
return_type class_name::function_name(type_1 arg_name_1, type_2 arg_name_2) {
do_something();
}
- FU2: There is never a space between the function name (or operator) and the open brace. This rule applies to both function declaration/definitions and calls.
Declaration
// Wrong
void foo (type arg_name);
void operator() (type arg_name);
void operator bool ();
// Right
void foo(type arg_name);
void operator()(type arg_name);
void operator bool();
Call
// Wrong
const auto x = foo (arg_1, arg_2);
// Right
const auto x = foo(arg_1, arg_2);
- FU3: Do not put the function signature and the body on the same line. The only exception is an empty body, in that case place the curly braces at the same line (see rule FU4).
// Wrong
std::int32_t get_something() const { return something_; }
// Right
std::int32_t get_something() const {
return something_;
}
- FU4: Empty function body shall be at the same line as function signature.
// Wrong
void empty_foo(type arg) {
}
// Right
void empty_foo(type arg) {}
- CS1: Use snake_case: lower case and all words are separated with underscore character (_).
class numeric_table;
class image;
struct params;
- CS2: The acceptable formats for initializer lists are when everything fits on one line:
my_class::my_class(int var) : some_var_(var) {
do_something();
}
If the signature and initializer list are not all on one line, you must line wrap before the colon, indent 8 spaces, put each member on its own line, and align them:
my_class::my_class(int var)
: some_var_(var), // <-- 8 space indent
some_other_var_(var + 1) { // lined up
do_something();
}
As with any other code block, the close curly brace can be on the same line as the open curly, if it fits:
my_class::my_class(int var)
: some_var_(var),
another_var_(0) {}
-
VC1: Use snake_case for all variables, function's arguments and constants.
-
VC2: Use variables and constant names followed by one underscore "_" for private and protected class-level variables.
-
VC3: The assignment operator "=" shall be surrounded by single whitespace.
const auto val = get_some_value();
- ST1: Each of the keywords if/else/do/while/for/switch shall be followed by one space. An open curly brace after the condition shall be prepended with one space.
while (condition) { // <-- one space after `while` and one space before `{`
do_something();
} // <-- `;` is not required
- ST2: Each of the keywords if/else/do/while/for/switch shall always have accompanying curly braces even if they contain a single-line statement.
// Wrong
if (my_const == my_var)
do_something();
// Right
if (my_const == my_var) {
do_something();
}
- ST3: The statements within parentheses for operators if, for, while shall have no spaces adjacent to the open and close parentheses characters:
// Wrong
for ( int i = 0; i < loop_size; i++ ) ...;
// Right
for (int i = 0; i < loop_size; i++) ...;
oneMath uses GoogleTest for functional testing. For more information about how to build and run Unit Tests please see Building and Running Tests.
Be sure to extend the existing tests when fixing an issue, adding a new interface or new implementation under existing interfaces.