-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 3a4d680
Showing
129 changed files
with
12,003 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Modern C++ for Computational Scientists | ||
|
||
Repository view: <https://github.com/EPCCed/APT-CPP> | ||
|
||
Pages view: <https://EPCCed.github.io/APT-CPP/> | ||
|
||
Since the 2011 revision to the C++ language and standard library, the | ||
ways it is now being used are quite different. Used well, these | ||
features enable the programmer to write elegant, reusable and portable | ||
code that runs efficiently on a variety of architectures. | ||
|
||
However it is still a very large and complex tool. This set of | ||
lectures and practical exercises, will cover a minimal set of features | ||
to allow an experienced non-C++ programmer to get to grips with | ||
language. These include: | ||
* defining your own types | ||
* overloading | ||
* templates | ||
* containers | ||
* iterators | ||
* lambdas | ||
* standard algorithms | ||
* threading | ||
|
||
It concludes with a brief discussion of modern frameworks for portable | ||
parallel performance which are commonly implemented in C++. | ||
|
||
* [Lectures](lectures/) | ||
* [Practical exercises](exercises/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# C++ exercise | ||
|
||
Practical exercises for C++ course | ||
|
||
See each subdirectory for further instructions | ||
|
||
* [Complex numbers](complex/) | ||
* [Containers](containers/) | ||
* [Morton-order matrix class template](morton-order/) | ||
* [Using algorithms](algorithm/) | ||
* [Eigen](eigen/) | ||
* [Simple use of threads](threads/) | ||
* [Portable performance with Kokkos](kokkos/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
CXXFLAGS = --std=c++17 | ||
CC = $(CXX) | ||
|
||
ex : ex.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Algorithm use exercise | ||
|
||
In the file `ex.cpp` there is an incomplete program which, by | ||
following the instructions in the comments, you can finish. | ||
|
||
You will likely want to refer to the documentation of the standard | ||
library algorithms, which, for reasons, are split across two headers: | ||
|
||
- <https://en.cppreference.com/w/cpp/algorithm> | ||
|
||
- <https://en.cppreference.com/w/cpp/numeric#Numeric_algorithms> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#include <algorithm> | ||
#include <cstdlib> | ||
#include <functional> | ||
#include <iostream> | ||
#include <numeric> | ||
#include <vector> | ||
|
||
void print_vec(std::vector<int> &vec) { | ||
for (auto &el : vec) { | ||
std::cout << el << " "; | ||
} | ||
std::cout << std::endl << std::endl; | ||
} | ||
|
||
int main(int argc, char* argv[]) { | ||
// First, a warmup of basic algorithm usage | ||
auto nums = std::vector<int>(50); | ||
|
||
// let's initalize our vector with some random numbers | ||
for (int i = 0; i < 50; ++i) { | ||
nums[i] = std::rand() % 100; | ||
} | ||
|
||
// Bonus: can we do this using the algorithms library? Hint - std::generate | ||
// and use the following lambda | ||
auto gen = []() { return std::rand() % 100; }; | ||
|
||
// Your code here.... | ||
|
||
// Now, sort nums. | ||
|
||
// Your code here.... | ||
|
||
std::cout << "Sorted nums: "; | ||
print_vec(nums); | ||
// Reverse sort nums, using (a) sort on its own and (b) using sort and another | ||
// algorithm function | ||
|
||
// Your code here.... | ||
|
||
std::cout << "Reverse sorted nums (a): "; | ||
print_vec(nums); | ||
|
||
// Your code here.... | ||
|
||
std::cout << "Reverse sorted nums (b): "; | ||
print_vec(nums); | ||
|
||
// Now, lets look at a more involved example. We'll be working through Project | ||
// Euler No.2 (https://projecteuler.net/problem=2) "By considering the terms in | ||
// the Fibonacci sequence whose values do not exceed four million, find the sum | ||
// of the even-valued terms" | ||
|
||
// First lets get the fist 47 fibonacci numbers | ||
// BONUS: use std::transform | ||
|
||
auto fibs = std::vector<int>(47); | ||
|
||
// Your code here.... | ||
|
||
|
||
print_vec(fibs); | ||
|
||
// Next, get all that are less than or equal to 4 million, and store them in | ||
// fibs_less HINT: use std::copy_if and std::back_inserter | ||
|
||
auto fibs_less = std::vector<int>(); | ||
|
||
// Your code here.... | ||
|
||
std::cout << "fibs <= 4000000: "; | ||
print_vec(fibs_less); | ||
|
||
// Now, get the evens. Use the same approach as above | ||
auto evens = std::vector<int>(); | ||
|
||
// Your code here.... | ||
|
||
|
||
std::cout << "Evens: "; | ||
print_vec(evens); | ||
|
||
// Finally, let's sum them (hint: std::accumulate) | ||
|
||
int sum = 0; | ||
|
||
std::cout << "Sum of even fibonacci numbers not greater than 4 million: " | ||
<< sum << std::endl; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
CXXFLAGS = --std=c++17 -I../include | ||
|
||
test : complex.o test.o | ||
$(CXX) $^ -o $@ | ||
|
||
test.o : catch.hpp | ||
|
||
catch.hpp : | ||
wget https://github.com/catchorg/Catch2/releases/download/v2.13.6/catch.hpp | ||
|
||
run : test | ||
./test | ||
|
||
clean : | ||
rm -rf *.o test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
This document is available in multiple formats: | ||
* [PDF](instructions.pdf) | ||
* [Markdown](instructions.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#include "complex.hpp" | ||
#include <cmath> | ||
|
||
|
||
|
||
double const& Complex::real() { | ||
return re; | ||
} | ||
|
||
double Complex::imag() const { | ||
return im; | ||
} | ||
|
||
Complex Complex::conj() const { | ||
return Complex{re, -im}; | ||
} | ||
|
||
double Complex::norm() const { | ||
return std::sqrt(norm2()); | ||
} | ||
|
||
double Complex::norm2() const { | ||
return re*re + im*im; | ||
} | ||
|
||
bool operator==(Complex const& a, Complex const& b) { | ||
return (a.re == b.re) && (a.im == b.re); | ||
} | ||
bool operator!=(Complex const& a, Complex const& b) { | ||
return !(a == b); | ||
} | ||
|
||
Complex operator+(Complex const& a, Complex const& b) { | ||
return Complex{a.re + b.re, a.im + b.im}; | ||
} | ||
|
||
|
||
Complex operator*(Complex const& a, Complex const& b) { | ||
// (a + ib)*(c + id) == (a*c - b*d) + i(b*c + a*d) | ||
} | ||
|
||
Complex operator-(Complex const& a) { | ||
return Complex{-a.re, -a.im}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#ifndef CPPEX_COMPLEX_COMPLEX_HPP | ||
#define CPPEX_COMPLEX_COMPLEX_HPP | ||
|
||
// Simple complex number class | ||
class Complex { | ||
public: | ||
// Default value is zero | ||
Complex() = default; | ||
// Construct purely real complex | ||
// Construct from real and imaginary parts | ||
|
||
// Access components | ||
double real() const; | ||
double imag() const; | ||
|
||
// Compute the complex conjugate | ||
Complex conj(); | ||
|
||
// Compute the magnitude and squared magnitude | ||
double norm() const; | ||
double norm2() const; | ||
|
||
// Declare comparisons | ||
friend bool operator==(Complex const& a, Complex const& b); | ||
friend bool operator!=(Complex const& a, Complex const& b); | ||
|
||
// Declare binary arithmetic operators | ||
friend Complex operator+(Complex const& a, Complex const& b); | ||
friend Complex operator-(Complex const& a, Complex const& b); | ||
friend Complex operator*(Complex const& a, Complex const& b); | ||
friend Complex operator/(Complex const& a, Complex const& b); | ||
// Question: how would you declare multiplication and division by a real number? | ||
|
||
// Unary negation | ||
friend Complex operator-(Complex const& a); | ||
|
||
private: | ||
double re = 0.0; | ||
double im = 0.0; | ||
}; | ||
|
||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Introductory C++ exercises | ||
## Rupert Nash | ||
## [email protected] | ||
|
||
The files for this are on [Github](https://github.com/EPCCed/APT-CPP). | ||
|
||
To check out the repository run: | ||
|
||
```bash | ||
git clone https://github.com/EPCCed/APT-CPP | ||
cd APT-CPP/exercises/complex | ||
``` | ||
|
||
## Task | ||
|
||
You have been provided with a simple, *partial* implementation of a complex number class and an associated test program. Your task is to alter the complex.cpp/complex.hpp files until the tests compile and run correctly! (Please don't edit the test.cpp program!). To compile, you need a C++17 capable compiler - on Cirrus the default `gcc` module is fine - then just use `make`. | ||
|
||
This initial program fails: | ||
|
||
```bash | ||
$ module load gcc | ||
$ make | ||
c++ --std=c++17 -I../include -c -o complex.o complex.cpp | ||
complex.cpp:6:24: error: out-of-line definition of 'real' does not match any declaration in 'Complex' | ||
double const& Complex::real() { | ||
^~~~ | ||
./complex.hpp:13:10: note: member declaration does not match because it is const qualified | ||
double real() const; | ||
|
||
``` | ||
You need to start tracking down the bugs and fixing them. |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// Catch2 is a unit testing library | ||
// Here we let it create a main() function for us | ||
#define CATCH_CONFIG_MAIN | ||
#include "catch.hpp" | ||
|
||
#include "complex.hpp" | ||
|
||
TEST_CASE("Complex numbers are constructed real/imag parts readable") { | ||
const Complex zero; | ||
REQUIRE(zero.real() == 0.0); | ||
REQUIRE(zero.imag() == 0.0); | ||
|
||
const Complex one{1.0}; | ||
REQUIRE(one.real() == 1.0); | ||
REQUIRE(one.imag() == 0.0); | ||
|
||
const Complex i{0, 1}; | ||
REQUIRE(i.real() == 0.0); | ||
REQUIRE(i.imag() == 1.0); | ||
|
||
const Complex z1{1, -83}; | ||
const Complex z2 = z1; | ||
REQUIRE(i.real() == 0.0); | ||
REQUIRE(i.imag() == 1.0); | ||
} | ||
|
||
TEST_CASE("Complex numbers can be compared") { | ||
const Complex zero; | ||
const Complex one{1.0}; | ||
const Complex i{0, 1}; | ||
REQUIRE(zero == zero); | ||
REQUIRE(one == one); | ||
REQUIRE(i == i); | ||
REQUIRE(zero != one); | ||
REQUIRE(one != i); | ||
} | ||
|
||
TEST_CASE("Complex numbers can have magnitude computed") { | ||
REQUIRE(Complex{}.norm2() == 0.0); | ||
REQUIRE(Complex{3,4}.norm2() == 25.0); | ||
} | ||
|
||
// Pure real => z == z* | ||
void CheckConjReal(double x) { | ||
Complex z{x}; | ||
REQUIRE(z == z.conj()); | ||
} | ||
// Pure imaginary => z* == -z | ||
void CheckConjImag(double y) { | ||
Complex z{0.0, y}; | ||
|
||
REQUIRE(z == -z.conj()); | ||
} | ||
|
||
TEST_CASE("Complex numbers be conjugated") { | ||
CheckConjReal(0); | ||
CheckConjReal(1); | ||
CheckConjReal(-3.14); | ||
CheckConjReal(1.876e6); | ||
|
||
CheckConjImag(0); | ||
CheckConjImag(1); | ||
CheckConjImag(-3.14); | ||
CheckConjImag(1.876e6); | ||
} | ||
|
||
void CheckZplusZeq2Z(const Complex& z) { | ||
REQUIRE(z + z == Complex{2*z.real(), 2*z.imag()}); | ||
} | ||
void CheckZminusZeq0(const Complex& z) { | ||
REQUIRE(z - z == Complex{}); | ||
} | ||
|
||
TEST_CASE("Complex number can be added and subtracted") { | ||
CheckZplusZeq2Z(1); | ||
CheckZplusZeq2Z(0); | ||
CheckZplusZeq2Z(-1); | ||
|
||
CheckZminusZeq0(1); | ||
CheckZminusZeq0(0); | ||
CheckZminusZeq0(-1); | ||
CheckZminusZeq0(Complex{1,2}); | ||
CheckZminusZeq0(Complex{-42, 1e-3}); | ||
} | ||
|
||
TEST_CASE("Complex numbers can be multiplied") { | ||
const Complex i{0, 1}; | ||
Complex z{1}; | ||
z = z*i; | ||
REQUIRE(z == i); | ||
z = z*i; | ||
REQUIRE(z == Complex{-1}); | ||
z = z*i; | ||
REQUIRE(z == -i); | ||
} |
Oops, something went wrong.