Main development branch is develop. The main branch is used for stable,
ready-to-release code. Use git pull to keep develop branch in your local
repo updated. If you get conflicts when pulling from upstream reset your
local develop to the upstream:
git fetch
git checkout develop
git reset --hard origin/develop
Here origin is the name of the remote upstream repository in your local
repository. If you set custom name for your remote, replace origin with
that name.
For each new feature feature create a new branch from develop. Name your
feature branch <developer name>/<short_feature_description>_dev. Bug fix branches should follow similar pattern, only ending with _fix`. Always
use underscores to separate different words.
git checkout -b shaked/sparse_matrix_transpose_dev
In some instances you also might want to branch off a feature branch, for example to fix a bug or suggest significant changes.
Feature branches should be merged back to the branch from where they were
branched off (typically develop). All merging should be done through
GutHub pull request. Before creating a pull request make sure:
- All tests pass.
- Code compiles cleanly with flags
-Wall -Wpedantic -Wconversion -Wextra. - The new code follows GridKit™ style guidelines.
- There are unit tests for the new code.
- The new code is documented.
- The feature branch is rebased with respect to the target branch.
To rebase your feature branch, first ensure the target branch is up-to-date. Then use
git checkout <feature branch>
git rebase -i <target branch>
to rebase your branch to the target branch. Follow the instructions on the screen. You may need to resolve rebase conflicts.
Once your branch is ready, create pull request using the template provided in the GridKit™ repository. There has to be at least one approval before the pull request can be merged.
The code that does not comply with these guidelines will be fixed in separate pull request(s). Any new contribution should follow closely these guidelines but should not change style in the existing GridKit code.
Return values of member functions should be of type int and used for error
handling. Functions return 0 if no error is encounter, return positive value
for warnings and recoverable error, and negative value for irrecoverable
errors.
If an output is needed (for example, a warning needs to be displayed), use
std::cout and not printf as shown below. There should be a space before
and after each <<. If the line needs to be broken, the << operators should
be aligned:
std::cout << "index out of bounds. Row " << i << " starts at: " << start
<< " and ends at " << end << std::endl;Each class should be implemented in a *.cpp and a *.hpp files with
the same name. Files containing collection of standalone functions should
have a descriptive name starting with lowercase character.
Coding style rules are specified in .clang-format file in GridKit root
directory. Use
clang-format -i <filename>to make sure your code follows the style guidelines.
Keep line length below 80 characters unless a longer line is needed for better clarity of the code. If your line is longer than 90 characters, you are probably doing something wrong.
clang-format is configured so it does not enforce line length; that is
developer's responsibility. Break the long lines at places where it will
improve readability of the code. Running clang-format after that will help
align the code properly in accordance with GridKit coding style.
Local variable names should use C-style name format.
double local_variable; // Yes
double localVariable; // No, using lowercase camel instead of C-style name formatMember variable names should use C-style name format and end with trailing underscore _.
double member_variable_; // Yes
double another_member; // No, there is no trailing underscore to distinguish it from nonmember variables
double memberVariable_; // No, using lowercase camel instead of C-style name formatUse lowercase camel format for function names.
int myFunction(double x); // Yes
int another_function(); // No, using C-style name format
int YetAnotherFunction(); // No, using uppercase camel name formatClass names should us uppercase camel name format.
class MyClass // Yes
{
...
}
class Matrix // Yes
{
...
}
class My_Class // No, using underscore in class name
{
...
}Always define enums inside GridKit namespace. Type names should be
capitalized and the constant names should be uppercase with underscores
(but there is no underscore at the end!).
enum ExampleEnum { CONST_ONE = 0,
CONST_TWO = 8,
YET_ANOTHER_CONST = 17 };If a constant is used in more than one file, define it in Common.h. For
constants with long names, use underscores to separate words in the constant
name. Use all caps (screaming snake case).
constexpr double Pi = 3.1415; // No, use all caps for the constant name
constexpr double SQRT_TWO = 1.4142 // Yes
constexpr double SQRTTWO = 1.4142 // No, the two words not separated by "_"
constexpr double EXP = 2.7183 // Yes The pointer * or reference & belong to the type and there should be no space between them and the type name.
double* x; // Yes
int& n; // Yes
double *x, *y; // No, the pointer symbol is a part of `double*` type
int & n; // No, the reference symbol is a part of `int&` typeUse only spaces for indentation, not tabs. Indent size is 2 spaces.
When defining a class, the code blocks after private, public and protected
should be aligned with opening/closing braces. There should be an empty line
before each definition (except the first one). See example below.
class SomeClass
{
public:
SomeClass();
~SomeClass();
private:
int some_variable_;
protected:
void someFunction();
};All braces should follow Allman style:
namespace SomeNamespace
{
//some code
}For short functions (i.e., empty constructor), do not inline braces.
ClassA::ClassA()
{
}Have opening brace at the next line following for, if, or while
statement. When using else, follow the example below.
if (cond == true)
{
// some code
}
else
{
// some other code
}Have a space between keywords for, while and if and the parenthesis as
shown here:
for (int i = 0; i < n; ++i)
{
// some code
} Do not use one-line ifs and fors. Always use braces.
There should be spaces between arithmetic operators.
x = c * (a + b); // Yes
x = c*(a+b). // No, the clarity is better if there are spaces between
// binary operators and operands.When defining member functions, use one empty line between the functions.
struct MyStruct
{
int memberFunction()
{
// some code
}
int anotherMemberFunction()
{
// some other code
}
};Leave one empty line between all the includes and the first line of the actual code.
#include <iostream>
int main()
{
std::cout
}Header files should be included in 3 separate blocks: standard libraries,
GridKit external dependencies, and GridKit header files. There should be an
empty line between the blocks. External libraries should use <...>, while
GridKit headers should be included with "...".
#include <iostream> // Standard libs headers
#include <cmath>
#include <sundials.h> // GridKit dependencies
#include <idas.h>
#include "Ida.hpp" // GridKit internal header#include <cstring>
#include <SparseMatrix/CooMatrix.hpp>
int main()
{
//some code
return 0;
}The system includes should always be listed first.
Function declarations and function calls should be written on a single line. If a function has large number of parameters, the function should be broken over multiple lines so that each function parameter is on a separate line. All parameters should be aligned with the first parameter in the function.
int myFunction(double x, double y); // Yes, function on a single line
int myFunction(double x1, // Yes, function parameters on a separate lines.
double x2,
double x3,
double x4,
double x5,
double x6,
double x7);
int myFunction(double x1, // No, function broken inconsistently.
double x2, double x3,
double x4,
double x5, double x6, double x7);
int myFunction(
double x1, // No, first parameter should follow the parenthesis.
double x2,
double x3,
double x4,
double x5,
double x6,
double x7
);
Short initializer list should follow the constructor on the same line with
space around :. Long initializer lists should begin on the next line,
indented and starting with :. Initializers should be aligned.
// Short initializer list
MyClass(n, m) : n_(n), m_(m)
{
// ...
}
// Long initializer list
MyClass(n, m)
: n_(n),
m_(m),
pX_(nullptr),
pY_(nullptr),
pZ_(nullptr),
size_(0)
{
// ...
}All classes should be in namespace GridKit. If needed, define additional
namespaces inside GridKit.
namespace GridKit
{
class Solver // Yes, class defined inside GridKit namespace
{
// some code;
};
namespace LinearAlgebra
{
class Vector // Yes, class defined inside GridKit namespace
{
// vector code
};
}
}
class Matrix // No, class is outside GridKit namespace
{
// matrix code
};