From a317b14cdafb9a3f4e4b16c2281e65b71b2ecf8b Mon Sep 17 00:00:00 2001 From: Stefan Roiser Date: Wed, 20 Jul 2022 10:51:49 +0200 Subject: [PATCH 01/14] remove code --- code/CMakeLists.txt | 49 --- code/CompilerSettings.cmake | 34 -- code/ExercisesCheatSheet_All.md | 248 -------------- code/ExercisesCheatSheet_TheEssentials.md | 156 --------- code/Makefile | 25 -- code/README.md | 1 - code/SolutionTarget.cmake | 7 - code/asan/CMakeLists.txt | 15 - code/asan/Makefile | 11 - code/asan/README.md | 9 - code/asan/asan.cpp | 76 ----- code/asan/solution/asan.sol.cpp | 74 ---- code/atomic/CMakeLists.txt | 20 -- code/atomic/Makefile | 14 - code/atomic/atomic.cpp | 45 --- code/atomic/solution/atomic.sol.cpp | 45 --- code/callgrind/CMakeLists.txt | 15 - code/callgrind/Makefile | 11 - code/callgrind/README.md | 9 - code/callgrind/fibocrunch.cpp | 43 --- code/callgrind/solution/fibocrunch.sol.cpp | 43 --- code/condition_variable/CMakeLists.txt | 20 -- code/condition_variable/Makefile | 11 - .../condition_variable/condition_variable.cpp | 142 -------- .../solution/condition_variable.sol.cpp | 144 -------- code/constness/CMakeLists.txt | 10 - code/constness/Makefile | 7 - code/constness/README.md | 6 - code/constness/constplay.cpp | 70 ---- code/control/CMakeLists.txt | 15 - code/control/Makefile | 12 - code/control/README.md | 15 - code/control/control.cpp | 54 --- code/control/solution/control.sol.cpp | 67 ---- code/cppcheck/CMakeLists.txt | 15 - code/cppcheck/Makefile | 11 - code/cppcheck/README.md | 8 - code/cppcheck/randomize.cpp | 50 --- code/cppcheck/solution/randomize.sol.cpp | 50 --- code/debug/CMakeLists.txt | 15 - code/debug/Makefile | 11 - code/debug/README.md | 15 - code/debug/randomize.cpp | 54 --- code/debug/solution/randomize.sol.cpp | 54 --- code/exercisesIntro.tex | 190 ----------- code/functions/CMakeLists.txt | 21 -- code/functions/Makefile | 15 - code/functions/README.md | 25 -- code/functions/Structs.cpp | 23 -- code/functions/Structs.h | 15 - code/functions/functions.cpp | 33 -- code/functions/solution/functions.sol.cpp | 47 --- code/helgrind/CMakeLists.txt | 20 -- code/helgrind/Makefile | 11 - code/helgrind/README.md | 7 - code/helgrind/fiboMT.cpp | 57 ---- code/helgrind/solution/fiboMT.sol.cpp | 57 ---- code/hello/CMakeLists.txt | 15 - code/hello/Makefile | 15 - code/hello/README.md | 36 -- code/hello/hello.cpp | 7 - code/hello/hello.hpp | 7 - code/hello/main.cpp | 11 - code/loopsRefsAuto/CMakeLists.txt | 15 - code/loopsRefsAuto/Makefile | 14 - code/loopsRefsAuto/README.md | 9 - code/loopsRefsAuto/loopsRefsAuto.cpp | 45 --- .../solution/loopsRefsAuto.sol.cpp | 34 -- code/memcheck/CMakeLists.txt | 31 -- code/memcheck/Makefile | 17 - code/memcheck/Polygons.cpp | 21 -- code/memcheck/Polygons.hpp | 22 -- code/memcheck/README.md | 0 code/memcheck/memleak.cpp | 15 - code/memcheck/solution/Polygons.sol.cpp | 21 -- code/memcheck/solution/Polygons.sol.hpp | 22 -- code/memcheck/solution/memleak.sol.cpp | 15 - code/modern_oo/CMakeLists.txt | 15 - code/modern_oo/Makefile | 11 - code/modern_oo/README.md | 8 - code/modern_oo/particles.cpp | 50 --- code/modern_oo/solution/particles.sol.cpp | 50 --- code/move/CMakeLists.txt | 15 - code/move/Makefile | 11 - code/move/NVector.hpp | 138 -------- code/move/README.md | 13 - code/move/solution/NVector.sol.hpp | 151 --------- code/move/solution/trymove.sol.cpp | 36 -- code/move/trymove.cpp | 35 -- code/operators/CMakeLists.txt | 15 - code/operators/Makefile | 11 - code/operators/README.md | 5 - code/operators/operators.cpp | 105 ------ code/operators/solution/operators.sol.cpp | 180 ---------- code/polymorphism/CMakeLists.txt | 25 -- code/polymorphism/Makefile | 14 - code/polymorphism/Polygons.cpp | 19 -- code/polymorphism/Polygons.hpp | 22 -- code/polymorphism/README.md | 32 -- code/polymorphism/solution/trypoly.sol.cpp | 20 -- code/polymorphism/trypoly.cpp | 16 - code/python/CMakeLists.txt | 24 -- code/python/Complex.hpp | 69 ---- code/python/Makefile | 21 -- code/python/README.md | 11 - code/python/mandel.cpp | 12 - code/python/mandel.hpp | 9 - code/python/mandel.py | 25 -- code/python/mandel_cwrapper.cpp | 9 - code/python/mandel_cwrapper.hpp | 5 - code/python/mandel_module.cpp | 31 -- code/python/solution/mandel.sol.py | 22 -- code/python/solution/mandel.solctype.py | 25 -- code/race/CMakeLists.txt | 20 -- code/race/Makefile | 14 - code/race/README.md | 6 - code/race/racing.cpp | 38 --- code/race/solution/racing.sol.cpp | 41 --- code/smartPointers/CMakeLists.txt | 18 - code/smartPointers/Makefile | 11 - code/smartPointers/README.md | 22 -- code/smartPointers/smartPointers.cpp | 316 ------------------ .../solution/smartPointers.sol.cpp | 294 ---------------- code/spaceship/CMakeLists.txt | 18 - code/spaceship/Makefile | 11 - code/spaceship/README.md | 16 - code/spaceship/solution/spaceship.sol.cpp | 33 -- code/spaceship/spaceship.cpp | 40 --- code/stl/CMakeLists.txt | 20 -- code/stl/Complex.hpp | 74 ---- code/stl/Makefile | 14 - code/stl/README.md | 9 - code/stl/randomize.cpp | 36 -- code/stl/randomize.nostl.cpp | 47 --- code/stl/solution/randomize.sol.cpp | 52 --- code/templates/CMakeLists.txt | 17 - code/templates/Complex.hpp | 74 ---- code/templates/Makefile | 11 - code/templates/OrderedVector.hpp | 63 ---- code/templates/README.md | 16 - code/templates/playwithsort.cpp | 34 -- code/templates/solution/OrderedVector.sol.hpp | 69 ---- code/templates/solution/playwithsort.sol.cpp | 101 ------ code/valgrind/CMakeLists.txt | 15 - code/valgrind/Makefile | 11 - code/valgrind/README.md | 6 - code/valgrind/randomize.cpp | 53 --- code/valgrind/solution/randomize.sol.cpp | 54 --- code/virtual_inheritance/CMakeLists.txt | 26 -- code/virtual_inheritance/Makefile | 17 - code/virtual_inheritance/README.md | 11 - code/virtual_inheritance/TextBox.cpp | 18 - code/virtual_inheritance/TextBox.hpp | 32 -- code/virtual_inheritance/solution/TextBox.cpp | 18 - code/virtual_inheritance/solution/TextBox.hpp | 32 -- .../solution/trymultiherit.sol.cpp | 19 -- code/virtual_inheritance/trymultiherit.cpp | 14 - 157 files changed, 5820 deletions(-) delete mode 100644 code/CMakeLists.txt delete mode 100644 code/CompilerSettings.cmake delete mode 100644 code/ExercisesCheatSheet_All.md delete mode 100644 code/ExercisesCheatSheet_TheEssentials.md delete mode 100644 code/Makefile delete mode 100644 code/README.md delete mode 100644 code/SolutionTarget.cmake delete mode 100644 code/asan/CMakeLists.txt delete mode 100644 code/asan/Makefile delete mode 100644 code/asan/README.md delete mode 100644 code/asan/asan.cpp delete mode 100644 code/asan/solution/asan.sol.cpp delete mode 100644 code/atomic/CMakeLists.txt delete mode 100644 code/atomic/Makefile delete mode 100644 code/atomic/atomic.cpp delete mode 100644 code/atomic/solution/atomic.sol.cpp delete mode 100644 code/callgrind/CMakeLists.txt delete mode 100644 code/callgrind/Makefile delete mode 100644 code/callgrind/README.md delete mode 100644 code/callgrind/fibocrunch.cpp delete mode 100644 code/callgrind/solution/fibocrunch.sol.cpp delete mode 100644 code/condition_variable/CMakeLists.txt delete mode 100644 code/condition_variable/Makefile delete mode 100644 code/condition_variable/condition_variable.cpp delete mode 100644 code/condition_variable/solution/condition_variable.sol.cpp delete mode 100644 code/constness/CMakeLists.txt delete mode 100644 code/constness/Makefile delete mode 100644 code/constness/README.md delete mode 100644 code/constness/constplay.cpp delete mode 100644 code/control/CMakeLists.txt delete mode 100644 code/control/Makefile delete mode 100644 code/control/README.md delete mode 100644 code/control/control.cpp delete mode 100644 code/control/solution/control.sol.cpp delete mode 100644 code/cppcheck/CMakeLists.txt delete mode 100644 code/cppcheck/Makefile delete mode 100644 code/cppcheck/README.md delete mode 100644 code/cppcheck/randomize.cpp delete mode 100644 code/cppcheck/solution/randomize.sol.cpp delete mode 100644 code/debug/CMakeLists.txt delete mode 100644 code/debug/Makefile delete mode 100644 code/debug/README.md delete mode 100644 code/debug/randomize.cpp delete mode 100644 code/debug/solution/randomize.sol.cpp delete mode 100644 code/exercisesIntro.tex delete mode 100644 code/functions/CMakeLists.txt delete mode 100644 code/functions/Makefile delete mode 100644 code/functions/README.md delete mode 100644 code/functions/Structs.cpp delete mode 100644 code/functions/Structs.h delete mode 100644 code/functions/functions.cpp delete mode 100644 code/functions/solution/functions.sol.cpp delete mode 100644 code/helgrind/CMakeLists.txt delete mode 100644 code/helgrind/Makefile delete mode 100644 code/helgrind/README.md delete mode 100644 code/helgrind/fiboMT.cpp delete mode 100644 code/helgrind/solution/fiboMT.sol.cpp delete mode 100644 code/hello/CMakeLists.txt delete mode 100644 code/hello/Makefile delete mode 100644 code/hello/README.md delete mode 100644 code/hello/hello.cpp delete mode 100644 code/hello/hello.hpp delete mode 100644 code/hello/main.cpp delete mode 100644 code/loopsRefsAuto/CMakeLists.txt delete mode 100644 code/loopsRefsAuto/Makefile delete mode 100644 code/loopsRefsAuto/README.md delete mode 100644 code/loopsRefsAuto/loopsRefsAuto.cpp delete mode 100644 code/loopsRefsAuto/solution/loopsRefsAuto.sol.cpp delete mode 100644 code/memcheck/CMakeLists.txt delete mode 100644 code/memcheck/Makefile delete mode 100644 code/memcheck/Polygons.cpp delete mode 100644 code/memcheck/Polygons.hpp delete mode 100644 code/memcheck/README.md delete mode 100644 code/memcheck/memleak.cpp delete mode 100644 code/memcheck/solution/Polygons.sol.cpp delete mode 100644 code/memcheck/solution/Polygons.sol.hpp delete mode 100644 code/memcheck/solution/memleak.sol.cpp delete mode 100644 code/modern_oo/CMakeLists.txt delete mode 100644 code/modern_oo/Makefile delete mode 100644 code/modern_oo/README.md delete mode 100644 code/modern_oo/particles.cpp delete mode 100644 code/modern_oo/solution/particles.sol.cpp delete mode 100644 code/move/CMakeLists.txt delete mode 100644 code/move/Makefile delete mode 100644 code/move/NVector.hpp delete mode 100644 code/move/README.md delete mode 100644 code/move/solution/NVector.sol.hpp delete mode 100644 code/move/solution/trymove.sol.cpp delete mode 100644 code/move/trymove.cpp delete mode 100644 code/operators/CMakeLists.txt delete mode 100644 code/operators/Makefile delete mode 100644 code/operators/README.md delete mode 100644 code/operators/operators.cpp delete mode 100644 code/operators/solution/operators.sol.cpp delete mode 100644 code/polymorphism/CMakeLists.txt delete mode 100644 code/polymorphism/Makefile delete mode 100644 code/polymorphism/Polygons.cpp delete mode 100644 code/polymorphism/Polygons.hpp delete mode 100644 code/polymorphism/README.md delete mode 100644 code/polymorphism/solution/trypoly.sol.cpp delete mode 100644 code/polymorphism/trypoly.cpp delete mode 100644 code/python/CMakeLists.txt delete mode 100644 code/python/Complex.hpp delete mode 100644 code/python/Makefile delete mode 100644 code/python/README.md delete mode 100644 code/python/mandel.cpp delete mode 100644 code/python/mandel.hpp delete mode 100644 code/python/mandel.py delete mode 100644 code/python/mandel_cwrapper.cpp delete mode 100644 code/python/mandel_cwrapper.hpp delete mode 100644 code/python/mandel_module.cpp delete mode 100644 code/python/solution/mandel.sol.py delete mode 100644 code/python/solution/mandel.solctype.py delete mode 100644 code/race/CMakeLists.txt delete mode 100644 code/race/Makefile delete mode 100644 code/race/README.md delete mode 100644 code/race/racing.cpp delete mode 100644 code/race/solution/racing.sol.cpp delete mode 100644 code/smartPointers/CMakeLists.txt delete mode 100644 code/smartPointers/Makefile delete mode 100644 code/smartPointers/README.md delete mode 100644 code/smartPointers/smartPointers.cpp delete mode 100644 code/smartPointers/solution/smartPointers.sol.cpp delete mode 100644 code/spaceship/CMakeLists.txt delete mode 100644 code/spaceship/Makefile delete mode 100644 code/spaceship/README.md delete mode 100644 code/spaceship/solution/spaceship.sol.cpp delete mode 100644 code/spaceship/spaceship.cpp delete mode 100644 code/stl/CMakeLists.txt delete mode 100644 code/stl/Complex.hpp delete mode 100644 code/stl/Makefile delete mode 100644 code/stl/README.md delete mode 100644 code/stl/randomize.cpp delete mode 100644 code/stl/randomize.nostl.cpp delete mode 100644 code/stl/solution/randomize.sol.cpp delete mode 100644 code/templates/CMakeLists.txt delete mode 100644 code/templates/Complex.hpp delete mode 100644 code/templates/Makefile delete mode 100644 code/templates/OrderedVector.hpp delete mode 100644 code/templates/README.md delete mode 100644 code/templates/playwithsort.cpp delete mode 100644 code/templates/solution/OrderedVector.sol.hpp delete mode 100644 code/templates/solution/playwithsort.sol.cpp delete mode 100644 code/valgrind/CMakeLists.txt delete mode 100644 code/valgrind/Makefile delete mode 100644 code/valgrind/README.md delete mode 100644 code/valgrind/randomize.cpp delete mode 100644 code/valgrind/solution/randomize.sol.cpp delete mode 100644 code/virtual_inheritance/CMakeLists.txt delete mode 100644 code/virtual_inheritance/Makefile delete mode 100644 code/virtual_inheritance/README.md delete mode 100644 code/virtual_inheritance/TextBox.cpp delete mode 100644 code/virtual_inheritance/TextBox.hpp delete mode 100644 code/virtual_inheritance/solution/TextBox.cpp delete mode 100644 code/virtual_inheritance/solution/TextBox.hpp delete mode 100644 code/virtual_inheritance/solution/trymultiherit.sol.cpp delete mode 100644 code/virtual_inheritance/trymultiherit.cpp diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt deleted file mode 100644 index fc84814f..00000000 --- a/code/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -# -# Main project for building all of the exercises at once. -# - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( cpluspluscourse LANGUAGES CXX ) - -# Make sure that the project is built "out of source". As an "in source" build -# would interfere with the simple Makefiles coming with the code. -if( "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}" ) - message( FATAL_ERROR "The tutorial code must be built out of source!" ) -endif() - -# Include the test (hello world) project. -add_subdirectory( hello ) - -# Include the exercises that (should) work on all platforms. -add_subdirectory( asan ) -add_subdirectory( atomic ) -add_subdirectory( callgrind ) -add_subdirectory( condition_variable ) -add_subdirectory( constness ) -add_subdirectory( control ) -add_subdirectory( cppcheck ) -add_subdirectory( debug ) -add_subdirectory( functions ) -add_subdirectory( loopsRefsAuto ) -add_subdirectory( memcheck ) -add_subdirectory( modern_oo ) -add_subdirectory( move ) -add_subdirectory( operators ) -add_subdirectory( polymorphism ) -add_subdirectory( race ) -add_subdirectory( smartPointers ) -add_subdirectory( templates ) -add_subdirectory( valgrind ) -add_subdirectory( virtual_inheritance ) - -# Include the non-Windows-native exercises. -if( NOT MSVC ) - add_subdirectory( helgrind ) - add_subdirectory( python ) -endif() - -# Include the gcc-only exercises. -if( NOT APPLE AND NOT MSVC ) - add_subdirectory( stl ) -endif() diff --git a/code/CompilerSettings.cmake b/code/CompilerSettings.cmake deleted file mode 100644 index 01d2208a..00000000 --- a/code/CompilerSettings.cmake +++ /dev/null @@ -1,34 +0,0 @@ -# -# Small module used in every project to set up the default "compilation -# environment". -# - -# Guard this file against multiple inclusions. -get_property( _compilersSet GLOBAL PROPERTY COMPILER_SETTINGS_DONE SET ) -if( _compilersSet ) - unset( _compilersSet ) - return() -endif() -set_property( GLOBAL PROPERTY COMPILER_SETTINGS_DONE TRUE ) - - -# Set up a Debug build type by default, if the user didn't ask for something -# else. -if( NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES ) - set( CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Choose the type of build." FORCE ) - set_property( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Release" "MinSizeRel" "RelWithDebInfo" ) -endif() - -# Use C++17 in the project by default, or as high of a value as possible. -set( CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to use" ) -set( CMAKE_CXX_EXTENSIONS FALSE CACHE BOOL "(Dis)Allow C++ extensions" ) - -# Enable (almost) all warnings for the build. -if( ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) OR - ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra" ) -elseif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4" ) -endif() diff --git a/code/ExercisesCheatSheet_All.md b/code/ExercisesCheatSheet_All.md deleted file mode 100644 index 953b1fd6..00000000 --- a/code/ExercisesCheatSheet_All.md +++ /dev/null @@ -1,248 +0,0 @@ -HEP C++ Course cheat sheet -========================== - -List of exercises per day, with preferred order and solution overview. -Each exercise is in its own directory and referred to in the following by the name of the directory -For each day, the exercises are given in order in which they should be done. - -Day 1 - Basics Exercises ------------------------- - -### Hello World (directory: `hello`) - -Just try to compile and run `./hello` to make sure that everything is set up correctly. - -### Functions (directory: `functions`) - -pass by copy / pass by reference - -- Write a `printFiveCharacters(SlowToCopy)` function using the existing function as a model. Change its name - if overloading isn't desired. -- Call it in `main()`. -- Make sure that the signature is `(SlowToCopy const & a)` to avoid copies. -- Try to modify the data in the structs. Compare what happens for each of `(SlowToCopy a), (SlowToCopy & a), (SlowToCopyy const & a)`. - -### Control Structures (directory: `control`) - -The idea of this exercise is to play with all kinds of possible loops and control structures and to understand how they work. - -- change from a C++98 style for loop to range-based loop -- replace if / else statement with conditional operator -- change from a for loop to while and do/while loop -- change an if statement to a switch statement - -### Auto & Refercences (directory: `loopsRefsAuto`) - -- Write an indexed for loop to initialise the members of the structs. The program should not print garbage numbers. -- Use `auto const &` to prevent copies in the second loop. -- Understand the difference to `auto &`, get in the habit of using const references. - -Day 2 - OO Exercises --------------------- - -### Polymorphism (directory: `polymorphism`) - -First create a Pentagon and an Hexagon and call computePerimeter. Can be used to break the ice. -Second step is to call parent's computePerimeter methods meaning : - -```cpp -Polygon *poly = new Hexagon(1.0); -poly->computePerimeter(); -``` -and check what is called, in regular and virtual method case - -### `modern_oo` - -Insert one `= delete`, one `= default` and one `override`. - -### Virtual inheritance (directory: `virtual_inheritance`) - -First create a TextBox and try to call draw. -There will be an error that the member is ambiguous, due to multiple inheritance. -Fix code by calling it on both parents using types : - -```cpp - TextBox *tb = new TextBox(...) - Rectangle *r = tb; - r->draw(); -``` - -See the output and check the ids printed, 2 different ones. - -Retry with virtual inheritance. -See and solve the compilation issue about missing Drawable constructor. Understand that it's now called directly from TextBox constructor and call it explicitly from there with a new id. -See the new id being printed twice. - - -### Operators (directory: `operators`) - -This exercise is about making `main` run successfully by completing the implementation of `Fraction`. -Implement a constructor for `Fraction` and add two integer data members for numerator and denominator. -Comment out everything in `main` except the first two LOCs. -This should compile now and print nothing. - -Then uncomment the `std::cout` statements and implement `operator<<` for `Fraction`. -Compile and run. - -Proceed this way through the entire exercise. -There are multiple possibilities to implement some operators, e.g. as members, as hidden friends, or as free functions. -Also when and where to normalize a fraction is up to the students. -All solutions are fine, as long as the `main` function runs successfully. - -Day 3 ------ - -Exercises of day 3 are special as they will have been played (quickly) during the course. But people should replay them and discover the tools by themselves. - -### Compiler - -Based on the functions exercise, we are replaying the compilation steps manually. - -A "break the ice" exercise here would be to ask people to do the first step (preprocessor) and make a poll on how many lines of C++ are present in the output. It will vary depending on setups, versions, OS, etc... - -Then the important part is to play with nm and the -C option of C++filt to be able to decode symbols, find them and thus address a build error that mentions missing symbols. - -Another important bit is ldd and inspecting library dependencies. - -Notes: -- `--std=` >= c++11 is needed to initialise the structs. -- The Makefile skips the generation of the object file for functions.cpp. This might surprise some people. - -### Debugging (directory: `debug`) - -The goal there is really to play, look around and try things. Tutors may have a lot of questions here on "how do you...". - -The solution of the crash is simply an inversion of 2 lines in the code where definition of v and it's randomization are inverted. - -### Clang format (any directory) - -The students can try this on any example. -Please warn the students: If they want to revert later, they should pick an example with no local changes. -Just follow the instructions on the slide deck. -It is also fine if the mentor demonstrates it quickly. -Please advise the students they should use `.clang-format` files from their projects before they start developing their own one. - -### Address sanitizer (`asan`) - -The goal is to play with asan, and learn to read the very detailed hints it gives when it detects an error. - -There's two bugs and one memory leak: -- `stackOverflow()` overflows the stack by writing past the end of an array in the for loop. -- `useAfterFree()` returns a reference to a temporary. One should return a copy. -- `memoryLeak()` lets a string leak. - -### `valgrind` - -Again the point is to play with the tool. -In this example, we use an already deleted array. Simply the delete statement in the code appears too early - -Second part of the exercise goes back to the gdb exercise. Here we see an access out of array bound. It's due to bad case in 'len' in createAndFillVector (or why should you name your variables wisely and avoid macros). -Interestingly this out of bound access will usually not fail but read the next variable in memory and thus biais the computation. -Second part can be skipped if time is missing - -### `cppcheck` - -Simple example of a static analysis tool. -The code shows no problem, even with valgrind and still mayb biais its result. - -The basic goal is to run the tool, find the problem and fix it. The problem is a typo in the declaration of the v vector where + has become -, thus creating a out of bound error. - -The second goal is to understand why it os not crashing neither detected by valgrind. Here gdb is useful and one needs to inspect the address of variables in memory to understand that the compiler aligns variables and thus leaves space after v that is considered allocated by valgrind. -That second part can be skipped. - -### `memcheck` - -Simple example of a memory leak and how valgrind helps a lot with this. -Not so simple solution here. And the use of gdb with steping at the level of the destructor call is recommended. Give it as a hint to people. - -The solution is that the wrong destructor is called when calling "delete hexa" because the constructor is not virtual while it should be. - -### `callgrind` - -The goal is again to play. With the optimized version, it's interesting to see how much the startup time dominates the few computations done. -This exercise can be skipped - -### `helgrind` - -This is a concurrency exercise and thus rather be kept for Day 5 although the tool is presented on Day 3. -Usually the program works fine, and valgrind is happy. The race condition is indeed hard to trigger, but nevertheless spotted easily by helgrind. -The title string is just deleted too early. -This exercise should be skipped if time is missing - - -Day 4 - Modern C++ Exercises ----------------------------- - -### Constness (directory: `constness`) - -The idea is to find out which lines are not correct, due to constness. -Ideal to break the ice as can be organized as a quizz of which line would fail or not with correction under the form of compiler validation. - -### Generic programming (directory: `templates`) - -This exercise has several levels. People not at ease can stop after first level and go to next exercise. Alternatively, they may do level 1 and 3 and skip 2. - -Level 1 : just use the given Complex class in OrderedVector and see it works out of the box thanks to generic code in OrderedVector. - -Level 2 : add a template argument for the ordering in OrderedVector. -The idea is to add an extra template argument "Compare" that is a functor comparing 2 arguments and an extra member "m_compare" of type "Compare" to the OrderedVector class. Then the comparison in the add function can be replaced by - -```cpp -m_compare(arg1, arg2); -``` -It can then be tried with e.g. reverse ordering of strings or an order of Complex based on Manhattan distance (https://en.wikipedia.org/wiki/Taxicab_geometry) - -Level 3 : use the genericity of the Complex class and play with Complex of integers or Complex of Complex - -### Smart pointers (directory: `smartPointers`) - -Here we have four code snippets that will benefit from using smart pointers. - -- `problem1` is a simple case of usage of `make_unique` with an observer pattern where the raw pointer should be used. -- `problem2` is an example of a collection of pointers. Move semantic has to be used to transfer ownership of newly created objects to the container (alternatively, `emplace_back`). -- `problem3` is an example of shared ownership where `std::shared_pointer` should be used. -- `problem4` demonstrates the usage of `shared_ptr` as class members. It has a second part where a `weak_ptr` can be used, but can be skipped if not enough time. - -### Standard algorithms and lambdas (directory: `stl`) - -The goal is to use STL algorithms. I would advise to start in this order : - - - random_shuffle - - adjacent_difference - - first accumulate (the one for sums) - - second accumulate (using lambda to compute sum of squares) - - generate (involves a state to be captured by reference) - -### Move semantic (directory: `move`) - -See with valgrind the number of copies and memory allocations in the problem, due to lack of move semantic. -Implement the move semantic based on swap (copy paste from the slides). -See in valgrind the improvements. - - -Day 5 ------ - -On day 5, the advice it to first work on exercises from Day 3 and 4 that were left aside. - -### `race` - -Typical race condition where a simple mutex and lock_guard "solves" the problem. - -The second step is to look at the execution time and find out that it's not really a solution. One could then try an atomic and see the difference, although I do not introduce them in the course - -### `atomic` - -Exactly the same race condition as above. Fix them using an `atomic`. - -*Optional*: Compare run times for lock and atomic solution. Those are likely not very different, as many locks are implemented using atomics. - -### condition_variable - -Small example where 4 consumer threads are notified by a producer. -1. The production phase is not protected by a lock. -2. When the consumers are waking up, they don't release the lock that's tied to the condition variable, so they cannot wake up in parallel. - -### `python` - -This is playing with low level C++/python interfacing. All the c code is provided, so the only task is to use the different implementations (C, C++ manual interface, ctype) from python and see the speed of each of them. diff --git a/code/ExercisesCheatSheet_TheEssentials.md b/code/ExercisesCheatSheet_TheEssentials.md deleted file mode 100644 index 624a2655..00000000 --- a/code/ExercisesCheatSheet_TheEssentials.md +++ /dev/null @@ -1,156 +0,0 @@ -HEP C++ Course cheat sheet -========================== - -List of exercises per day, with preferred order and solution overview. -Each exercise is in its own directory and referred to in the following by the name of the directory -For each day, the exercises are given in order in which they should be done. - -Day 1 - Basics Exercises ------------------------- - -### Hello World (directory: `hello`) - -Just try to compile and run `./hello` to make sure that everything is set up correctly. - -### Functions (directory: `functions`) - -pass by copy / pass by reference - -- Write a `printFiveCharacters(SlowToCopy)` function using the existing function as a model. Change its name - if overloading isn't desired. -- Call it in `main()`. -- Make sure that the signature is `(SlowToCopy const & a)` to avoid copies. -- Try to modify the data in the structs. Compare what happens for each of `(SlowToCopy a), (SlowToCopy & a), (SlowToCopyy const & a)`. - -### Control Structures (directory: `control`) - -The idea of this exercise is to play with all kinds of possible loops and control structures and to understand how they work. - -- change from a C++98 style for loop to range-based loop -- replace if / else statement with conditional operator -- change from a for loop to while and do/while loop -- change an if statement to a switch statement - -### Auto & Refercences (directory: `loopsRefsAuto`) - -- Write an indexed for loop to initialise the members of the structs. The program should not print garbage numbers. -- Use `auto const &` to prevent copies in the second loop. -- Understand the difference to `auto &`, get in the habit of using const references. - - -Day 2 - Tools Exercises ------------------------ - - -The tools exercises of day 2 are special as they will have been played (quickly) during the course. But people should replay them and discover the tools by themselves. - - -### Compiler - -Based on the functions exercise, we are replaying the compilation steps manually. - -A "break the ice" exercise here would be to ask people to do the first step (preprocessor) and make a poll on how many lines of C++ are present in the output. It will vary depending on setups, versions, OS, etc... - -Then the important part is to play with nm and the -C option of C++filt to be able to decode symbols, find them and thus address a build error that mentions missing symbols. - -Another important bit is ldd and inspecting library dependencies. - -Notes: -- `--std=` >= c++11 is needed to initialise the structs. -- The Makefile skips the generation of the object file for functions.cpp. This might surprise some people. - -### Debugging (directory: `debug`) - -The goal there is really to play, look around and try things. Tutors may have a lot of questions here on "how do you...". - -The solution of the crash is simply an inversion of 2 lines in the code where definition of v and it's randomization are inverted. - -### Clang format (any directory) - -The students can try this on any example. -Please warn the students: If they want to revert later, they should pick an example with no local changes. -Just follow the instructions on the slide deck. -It is also fine if the mentor demonstrates it quickly. -Please advise the students they should use `.clang-format` files from their projects before they start developing their own one. - -Day 2 - OO Exercises --------------------- - -### Polymorphism (directory: `polymorphism`) - -First create a Pentagon and an Hexagon and call computePerimeter. Can be used to break the ice. -Second step is to call parent's computePerimeter methods meaning : - -```cpp -Polygon *poly = new Hexagon(1.0); -poly->computePerimeter(); -``` -and check what is called, in regular and virtual method case - -### Virtual inheritance (directory: `virtual_inheritance`) - -First create a TextBox and try to call draw. -There will be an error that the member is ambiguous, due to multiple inheritance. -Fix code by calling it on both parents using types : - -```cpp - TextBox *tb = new TextBox(...) - Rectangle *r = tb; - r->draw(); -``` - -See the output and check the ids printed, 2 different ones. - -Retry with virtual inheritance. -See and solve the compilation issue about missing Drawable constructor. Understand that it's now called directly from TextBox constructor and call it explicitly from there with a new id. -See the new id being printed twice. - - -### Operators (directory: `operators`) - -This exercise is about making `main` run successfully by completing the implementation of `Fraction`. -Implement a constructor for `Fraction` and add two integer data members for numerator and denominator. -Comment out everything in `main` except the first two LOCs. -This should compile now and print nothing. - -Then uncomment the `std::cout` statements and implement `operator<<` for `Fraction`. -Compile and run. - -Proceed this way through the entire exercise. -There are multiple possibilities to implement some operators, e.g. as members, as hidden friends, or as free functions. -Also when and where to normalize a fraction is up to the students. -All solutions are fine, as long as the `main` function runs successfully. - -Day 3 - Modern C++ Exercises ----------------------------- - -### Constness (directory: `constness`) - -The idea is to find out which lines are not correct, due to constness. -Ideal to break the ice as can be organized as a quizz of which line would fail or not with correction under the form of compiler validation. - -### Generic programming (directory: `templates`) - -This exercise has several levels. People not at ease can stop after first level and go to next exercise. Alternatively, they may do level 1 and 3 and skip 2. - -Level 1 : just use the given Complex class in OrderedVector and see it works out of the box thanks to generic code in OrderedVector. - -** stop after level 1, the rest is for the advanced course ** - -### Smart pointers (directory: `smartPointers`) - -Here we have four code snippets that will benefit from using smart pointers. - - - `problem1` is a simple case of usage of `make_unique` with an observer pattern where the raw pointer should be used. - - `problem2` is an example of a collection of pointers. Use `emplace_back` to transfer ownership of newly created objects to the container. You might need to briefly explain what `std::move` does, if needed. - - ** problem 3 and 4 is for the advanced course ** - -### Standard algorithms and lambdas (directory: `stl`) - -The goal is to use STL algorithms. I would advise to start in this order : - - - random_shuffle - - adjacent_difference - - first accumulate (the one for sums) - - second accumulate (using lambda to compute sum of squares) - - generate (involves a state to be captured by reference) diff --git a/code/Makefile b/code/Makefile deleted file mode 100644 index 761cb7b6..00000000 --- a/code/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -compile: *.tex - pdflatex -shell-escape $< - pdflatex -shell-escape $< - -TESTDIRS = callgrind cppcheck control hello move python smartPointers templates virtual_inheritance \ - debug helgrind lambdas memcheck polymorphism race stl valgrind -NOCOMPILETESTDIRS = constness - -solution: - for dir in ${TESTDIRS}; do \ - cd $${dir}; \ - make $@; \ - cd ..; \ - done - -clean: - rm -f *.aux *.log *.nav *.out *.pyg *.snm *.vrb *.toc - for dir in ${TESTDIRS} ${NOCOMPILETESTDIRS}; do \ - cd $${dir}; \ - make clean; \ - cd ..; \ - done - -clobber: clean - rm -f *.pdf diff --git a/code/README.md b/code/README.md deleted file mode 100644 index 19a828b9..00000000 --- a/code/README.md +++ /dev/null @@ -1 +0,0 @@ -The subdirectory `hello` is used to check that your machine is correctly installed. diff --git a/code/SolutionTarget.cmake b/code/SolutionTarget.cmake deleted file mode 100644 index 277a6c0e..00000000 --- a/code/SolutionTarget.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# -# Trivial module to set up the "solution" target for all projects. -# - -if( NOT TARGET solution ) - add_custom_target( solution ) -endif() diff --git a/code/asan/CMakeLists.txt b/code/asan/CMakeLists.txt deleted file mode 100644 index e6ffd6f4..00000000 --- a/code/asan/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( asan LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( asan "asan.cpp" ) - -# Create the "solution executable". -add_executable( asan.sol EXCLUDE_FROM_ALL "solution/asan.sol.cpp" ) -add_dependencies( solution asan.sol ) diff --git a/code/asan/Makefile b/code/asan/Makefile deleted file mode 100644 index 9c635be0..00000000 --- a/code/asan/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: asan -solution: asan.sol - -clean: - rm -f *o *so asan *~ asan.sol - -asan : asan.cpp - $(CXX) -std=c++17 -o $@ $^ - -asan.sol : solution/asan.sol.cpp - $(CXX) -std=c++17 -o $@ $^ diff --git a/code/asan/README.md b/code/asan/README.md deleted file mode 100644 index 9cea5dc5..00000000 --- a/code/asan/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Using address sanitizer - -Here, we explore address sanitizer (asan). The program `asan.cpp` has two bugs and a memory leak, -which should be relatively easy to find. It might or might not crash when run in its current state. -The goal is to compile the program with and without asan instrumentation and learn to read the very -detailed analysis of the program it generates. - -## Instructions -There's three tasks listed in the source code. diff --git a/code/asan/asan.cpp b/code/asan/asan.cpp deleted file mode 100644 index e537777d..00000000 --- a/code/asan/asan.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include -#include - -// Task 1: -// Here we write past the end of a character array on the stack. -// This doesn't necessarily crash the program, but it's certainly a bad idea, -// as it will corrupt data. -// -// - Compile and run the program without address sanitizer. Maybe you are lucky -// and it doesn't crash, but the arrays are probably corrupted now. -// (To make it crash, you can write more characters, but that's not necessary for -// what we want to try with asan.) -// - Add -// -fsanitize=address -fno-omit-frame-pointer -g -// to the compile options and retry. -// - For the Makefile, just add the above flags to the command line. -// - For CMake, either add to asan/CMakeLists.txt: -// target_compile_options(asan PUBLIC -fsanitize=address -fno-omit-frame-pointer -g) -// target_link_libraries(asan PUBLIC -fsanitize=address) -// or reconfigure the entire project with: -// cmake -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer -g" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address" . -// Note: If you reconfigure everything, all other exercises will also be built with asan instrumentation! -// - Run the program, and inspect asan's output. It should give a detailed description of -// the problem, where the memory was allocated, etc. -// - Fix the problem. -void stackOverflow() { - char a[] = "1234"; - char b[] = "5678"; - - std::cout << "a='" << a << "\'\n"; - std::cout << "b='" << b << "\'\n"; - - char* ptr = a; - - std::cout << "Now writing into the array:\n"; - for (unsigned int i = 0; i < 10; ++i) { - ptr[i] = static_cast('a' + i); - } - - std::cout << "a='" << a << "\'\n"; - std::cout << "b='" << b << "\'\n"; -} - -// Task 2: -// Never return references or pointers to stack memory -// or temporary variables. They vanish when the function returns. -// - After you fixed the problem in Task 1, asan should immediately point to the function below. Try it. -// - If asan doesn't report a "use-after-free", the compiler might have inlined the function. -// You can try different optimisation flags such as -O0 / -O1 / -O2 -// - Fix the problem. -std::string& useAfterFree() { - auto str = std::make_unique("A temporary string"); - return *str; -} - -// Task 3: -// Use this functions to test leak sanitizer. -// - Start the program with -// ASAN_OPTIONS=detect_leaks=1 ./asan -// and see how the information given there helps tracing down the leak. -// - The fix is relatively easy: -// - Option 1: Do as in useAfterFree() -// - Option 2: Put the string on the stack. -std::string& memoryLeak() { - auto str = new std::string("This string will leak"); - return *str; -} - -int main() { - stackOverflow(); - std::cout << "String from useAfterFree is:'" << useAfterFree() << "\'\n"; - std::cout << "Dynamically allocated string is:'" << memoryLeak() << "\'\n"; - - return 0; -} diff --git a/code/asan/solution/asan.sol.cpp b/code/asan/solution/asan.sol.cpp deleted file mode 100644 index e38cb75a..00000000 --- a/code/asan/solution/asan.sol.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include - -// Task 1: -// Here we write past the end of a character array on the stack. -// This doesn't necessarily crash the program, but it's certainly a bad idea, -// as it will corrupt data. -// -// - Compile and run the program without address sanitizer. Maybe you are lucky -// and it doesn't crash, but the arrays are probably corrupted now. -// (To make it crash, you can write more characters, but that's not necessary for -// what we want to try with asan.) -// - Add -// -fsanitize=address -fno-omit-frame-pointer -g -// to the compile options and retry. -// - For the Makefile, just add the above flags to the command line. -// - For CMake, either add to asan/CMakeLists.txt: -// target_compile_options(asan PUBLIC -fsanitize=address -fno-omit-frame-pointer -g) -// target_link_libraries(asan PUBLIC -fsanitize=address) -// or reconfigure the entire project with: -// cmake -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer -g" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address" . -// Note: If you reconfigure everything, all other exercises will also be built with asan instrumentation! -// - Run the program, and inspect asan's output. It should give a detailed description of -// the problem, where the memory was allocated, etc. -// - Fix the problem. -void stackOverflow() { - char a[] = "1234"; - char b[] = "5678"; - - std::cout << "a='" << a << "\'\n"; - std::cout << "b='" << b << "\'\n"; - - char* ptr = a; - - std::cout << "Now writing into the array:\n"; - for (unsigned int i = 0; i < std::size(a)-1; ++i) { // do not touch the 0 byte at the end - ptr[i] = static_cast('a' + i); - } - - std::cout << "a='" << a << "\'\n"; - std::cout << "b='" << b << "\'\n"; -} - -// Task 2: -// Never return references or pointers to stack memory -// or temporary variables. They vanish when the function returns. -// - After you fixed the problem in Task 1, asan should immediately point to the function below. Try it. -// - If asan doesn't report a "use-after-free", the compiler might have inlined the function. -// You can try different optimisation flags such as -O0 / -O1 / -O2 -// - Fix the problem. -std::string useAfterFree() { - return "A temporary string"; -} - -// Task 3: -// Use this functions to test leak sanitizer. -// - Start the program with -// ASAN_OPTIONS=detect_leaks=1 ./asan -// and see how the information given there helps tracing down the leak. -// - The fix is relatively easy: -// - Option 1: Do as in useAfterFree() -// - Option 2: Put the string on the stack. -std::string memoryLeak() { - return "This string will not leak"; -} - -int main() { - stackOverflow(); - std::cout << "String from useAfterFree is:'" << useAfterFree() << "\'\n"; - std::cout << "Dynamically allocated string is:'" << memoryLeak() << "\'\n"; - - return 0; -} diff --git a/code/atomic/CMakeLists.txt b/code/atomic/CMakeLists.txt deleted file mode 100644 index 8e89d4bf..00000000 --- a/code/atomic/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( atomic LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Figure out how to use the platform's thread capabilities. -find_package( Threads REQUIRED ) - -# Create the user's executable. -add_executable( atomic "atomic.cpp" ) -target_link_libraries( atomic PRIVATE Threads::Threads ) - -# Create the "solution executable". -add_executable( atomic.sol EXCLUDE_FROM_ALL "solution/atomic.sol.cpp" ) -target_link_libraries( atomic.sol PRIVATE Threads::Threads ) -add_dependencies( solution atomic.sol ) diff --git a/code/atomic/Makefile b/code/atomic/Makefile deleted file mode 100644 index 7462bc2b..00000000 --- a/code/atomic/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -PROGRAM_NAME=atomic - -all: $(PROGRAM_NAME) -solution: $(PROGRAM_NAME).sol - - -clean: - rm -f *o $(PROGRAM_NAME) *~ core $(PROGRAM_NAME).sol - -$(PROGRAM_NAME) : $(PROGRAM_NAME).cpp - ${CXX} -g -std=c++17 -O2 -pthread -Wall -Wextra -L. -o $@ $< - -$(PROGRAM_NAME).sol : solution/$(PROGRAM_NAME).sol.cpp - ${CXX} -g -std=c++17 -O2 -pthread -Wall -Wextra -L. -o $@ $< diff --git a/code/atomic/atomic.cpp b/code/atomic/atomic.cpp deleted file mode 100644 index 99045aa7..00000000 --- a/code/atomic/atomic.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include - -/* - * You know this program already from "racing". It tries to increment an integer 200 times in two threads. - * Last time, we fixed the race condition using a lock, but now we'll try atomics. - * - * Tasks: - * - Replace the counter 'a' by an atomic. Run the program, and check for race conditions. - * - Go back to 'racing', and check the execution time of the atomic vs the lock solution, e.g. using - * time ./atomic - * You might have to increase the number of tries if it completes too fast. - */ - -int main() { - int nError = 0; - - for (int j = 0; j < 1000; j++) { - int a = 0; - - // Increment the variable a 100 times: - auto inc100 = [&a](){ - for (int i = 0; i < 100; ++i) { - a++; - } - }; - - // Run with two threads - std::thread t1(inc100); - std::thread t2(inc100); - for (auto t : {&t1,&t2}) t->join(); - - // Check - if (a != 200) { - std::cout << "Race: " << a << ' '; - nError++; - } else { - std::cout << '.'; - } - } - std::cout << '\n'; - - return nError; -} diff --git a/code/atomic/solution/atomic.sol.cpp b/code/atomic/solution/atomic.sol.cpp deleted file mode 100644 index 93407e18..00000000 --- a/code/atomic/solution/atomic.sol.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include - -/* - * You know this program already from "racing". It tries to increment an integer 200 times in two threads. - * Last time, we fixed the race condition using a lock, but now we'll try atomics. - * - * Tasks: - * - Replace the counter 'a' by an atomic. Run the program, and check for race conditions. - * - Go back to 'racing', and check the execution time of the atomic vs the lock solution, e.g. using - * time ./atomic - * You might have to increase the number of tries if it completes too fast. - */ - -int main() { - int nError = 0; - - for (int j = 0; j < 1000; j++) { - std::atomic a{0}; - - // Increment the variable a 100 times: - auto inc100 = [&a](){ - for (int i = 0; i < 100; ++i) { - a++; - } - }; - - // Run with two threads - std::thread t1(inc100); - std::thread t2(inc100); - for (auto t : {&t1,&t2}) t->join(); - - // Check - if (a != 200) { - std::cout << "Race: " << a << ' '; - nError++; - } else { - std::cout << '.'; - } - } - std::cout << '\n'; - - return nError; -} diff --git a/code/callgrind/CMakeLists.txt b/code/callgrind/CMakeLists.txt deleted file mode 100644 index 31253c6a..00000000 --- a/code/callgrind/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( callgrind LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( fibocrunch "fibocrunch.cpp" ) - -# Create the "solution executable". -add_executable( fibocrunch.sol EXCLUDE_FROM_ALL "solution/fibocrunch.sol.cpp" ) -add_dependencies( solution fibocrunch.sol ) diff --git a/code/callgrind/Makefile b/code/callgrind/Makefile deleted file mode 100644 index 7649344d..00000000 --- a/code/callgrind/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: fibocrunch -solution : fibocrunch.sol - -clean: - rm -f *o fibocrunch *~ fibocrunch.sol fibocrunch.nostl core callgrind.out.* - -fibocrunch : fibocrunch.cpp - ${CXX} -g -O0 -Wall -Wextra -L. -o $@ $< - -fibocrunch.sol : solution/fibocrunch.sol.cpp - ${CXX} -Wall -Wextra -L. -o $@ $< diff --git a/code/callgrind/README.md b/code/callgrind/README.md deleted file mode 100644 index 58a28809..00000000 --- a/code/callgrind/README.md +++ /dev/null @@ -1,9 +0,0 @@ - -## Instructions - -* compile, run, it will be slow -* change nb iterations to 20 -* run with `valgrind --tool=callgrind` -* look at output with kcachegrind -* change fibo call to fibo2 -* observe the change in kcachegrind diff --git a/code/callgrind/fibocrunch.cpp b/code/callgrind/fibocrunch.cpp deleted file mode 100644 index 547adecd..00000000 --- a/code/callgrind/fibocrunch.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -#define NBITERATIONS 20 -#define MAX 40 - -unsigned int add(unsigned int a, unsigned int b) { - return a + b; -} - -unsigned int mul(unsigned int a, unsigned int b) { - return a * b; -} - -unsigned int power(unsigned int a, unsigned int b) { - unsigned int res = 1; - for (unsigned int i = 0; i < b; i++) res *= a; - return res; -} - -unsigned int fibo(int a) { - if (a == 1 || a == 0) { - return 1; - } else { - return fibo(a-1)+fibo(a-2); - } -} - -unsigned int fibo2(int n) { - return static_cast((1/sqrt(5)) * (pow(((1 + sqrt(5)) / 2), n) - pow(((1 - sqrt(5)) / 2), n))); -} - -int main() { - for (unsigned int i = 0; i < NBITERATIONS; i++) { - unsigned int a = rand()%MAX; - unsigned int b = rand()%MAX; - add(a, b); - mul(a, b); - power(a, b); - fibo(a); - } -} diff --git a/code/callgrind/solution/fibocrunch.sol.cpp b/code/callgrind/solution/fibocrunch.sol.cpp deleted file mode 100644 index 6037bbce..00000000 --- a/code/callgrind/solution/fibocrunch.sol.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -#define NBITERATIONS 20 -#define MAX 40 - -unsigned int add(unsigned int a, unsigned int b) { - return a + b; -} - -unsigned int mul(unsigned int a, unsigned int b) { - return a * b; -} - -unsigned int power(unsigned int a, unsigned int b) { - unsigned int res = 1; - for (unsigned int i = 0; i < b; i++) res *= a; - return res; -} - -unsigned int fibo(int a) { - if (a == 1 || a == 0) { - return 1; - } else { - return fibo(a-1)+fibo(a-2); - } -} - -unsigned int fibo2(int n) { - return static_cast((1/sqrt(5)) * (pow(((1 + sqrt(5)) / 2), n) - pow(((1 - sqrt(5)) / 2), n))); -} - -int main() { - for (unsigned int i = 0; i < NBITERATIONS; i++) { - unsigned int a = rand()%MAX; - unsigned int b = rand()%MAX; - add(a, b); - mul(a, b); - power(a, b); - fibo2(a); - } -} diff --git a/code/condition_variable/CMakeLists.txt b/code/condition_variable/CMakeLists.txt deleted file mode 100644 index 01fd699c..00000000 --- a/code/condition_variable/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( condition_variable LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Figure out how to use the platform's thread capabilities. -find_package( Threads REQUIRED ) - -# Create the user's executable. -add_executable( condition_variable "condition_variable.cpp" ) -target_link_libraries( condition_variable PRIVATE Threads::Threads ) - -# Create the "solution executable". -add_executable( condition_variable.sol EXCLUDE_FROM_ALL "solution/condition_variable.sol.cpp" ) -target_link_libraries( condition_variable.sol PRIVATE Threads::Threads ) -add_dependencies( solution condition_variable.sol ) diff --git a/code/condition_variable/Makefile b/code/condition_variable/Makefile deleted file mode 100644 index 19c7ecad..00000000 --- a/code/condition_variable/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: condition_variable -solution: condition_variable.sol - -clean: - rm -f *o condition_variable *~ core condition_variable.sol - -% : %.cpp - ${CXX} -g -std=c++17 -O0 -pthread -Wall -Wextra -L. -o $@ $< - -condition_variable.sol : solution/condition_variable.sol.cpp - ${CXX} -g -std=c++17 -O0 -pthread -Wall -Wextra -L. -o $@ $< diff --git a/code/condition_variable/condition_variable.cpp b/code/condition_variable/condition_variable.cpp deleted file mode 100644 index f6c66faa..00000000 --- a/code/condition_variable/condition_variable.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -/* - * ------------------------------------------------------------ - * Setup and helpers. You don't need to change any code here. - * ------------------------------------------------------------ - */ -using namespace std::chrono_literals; // We can write 1s - -std::mutex cout_mutex{}; // We need this to synchronise printing - -// Print contents of the stream to cout in a thread-safe manner. -// This class consumes stream inputs, buffers them, and writes them -// out when destructed respecting the cout_mutex. -class SafeCout { - std::stringstream stream; - -public: - ~SafeCout() { - std::scoped_lock coutLock{cout_mutex}; - std::cout << stream.str(); - } - - template - SafeCout & operator<<(T&& arg) { - stream << std::forward(arg); - return *this; - } -}; - - -// A mock data object -struct Data { - bool isReady() const { - return _isReady; - } - - bool _isReady = false; - bool _isConsistent = false; -}; - - -// The function that processes the data. You don't need to touch it. -// It will check whether the data are in a consistent state, and -// idle a bit to simulate longer data processing. -// Note: It should run in parallel. -bool process(unsigned int threadIdx, Data const & data) { - bool processingOK = true; - - SafeCout{} << '[' << threadIdx << "] I'm starting to process the data now\n"; - if (!data._isConsistent) { - processingOK = false; - SafeCout{} << '[' << threadIdx << "] ERROR data isn't fully ready! Race condition!\n"; - } - - // Burn some CPU cycles to simulate intensive data processing. - const auto startTime = std::chrono::high_resolution_clock::now(); - int dummyCounter = 0; - while (std::chrono::high_resolution_clock::now() - startTime < 5s) { - ++dummyCounter; - } - return processingOK; -} - -/* - * ------------------------------------------------------------ - * Exercise code you need to work on. - * ------------------------------------------------------------ - * This program tries to implement a producer/multi-consumer dependency between threads. - * One producer provides some data, and multiple consumers wait for the data to become ready. - * - * The threads communicate via std::condition_variable, but the implementation is incomplete. - * - * Tasks: - * 1. Run the program and understand why the consumer threads start running too early (on some - * platforms, at least ...). - * Run it multiple times if necessary. - * Why do they wake up although they should remain sleeping? - * 2. Fix the race condition by protecting the data production phase with a lock. - * 3. When you run the program now, the consumers should start running only after the data are ready. - * Why do they run one by one, though? - * Check the CPU consumption with a tool like top in a second shell. - * Ideally, we want 400% utilisation. - * 4. Fix the consumer waiting phase like in the lecture to make the consumers run in parallel. - * Check the CPU consumption again. - */ - - -int main() { - std::mutex mutex; - std::condition_variable cond; - Data data; - - // DATA-PROCESSING THREADS - // Here we start the processing threads. They have to wait for the data to be ready, - // and then they should process it in parallel. - auto processData = [&](unsigned int threadIdx){ - SafeCout{} << '[' << threadIdx << "] I'm starting to wait\n"; - - std::unique_lock lock{mutex}; - cond.wait(lock, [&](){ return data.isReady(); }); - - auto result = process(threadIdx, data); - - SafeCout{} << '[' << threadIdx << "] Done " << (result ? "OK" : "with failure!") << '\n'; - }; - - std::vector consumers; - for (unsigned int i=0; i < 4; ++i) { - consumers.emplace_back(processData, i); - } - - // DATA-PRODUCER THREAD - // This thread produces the data. We simulate a complicated way of producing the data - // by making the thread wait for a few seconds during the data production. - std::thread producer([&](){ - SafeCout{} << "[p] Starting to produce data\n"; - data._isReady = true; - // Sleep a bit to simulate a complicated set up phase - std::this_thread::sleep_for(6s); - data._isConsistent = true; - - SafeCout{} << "[p] Data ready now\n"; - - // Wake up all threads - cond.notify_all(); - }); - - // Join all threads, so we don't terminate prematurely - producer.join(); - for (auto & t : consumers) { - t.join(); - } - - return 0; -} diff --git a/code/condition_variable/solution/condition_variable.sol.cpp b/code/condition_variable/solution/condition_variable.sol.cpp deleted file mode 100644 index 058d9f9b..00000000 --- a/code/condition_variable/solution/condition_variable.sol.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -/* - * ------------------------------------------------------------ - * Setup and helpers. You don't need to change any code here. - * ------------------------------------------------------------ - */ -using namespace std::chrono_literals; // We can write 1s - -std::mutex cout_mutex{}; // We need this to synchronise printing - -// Print contents of the stream to cout in a thread-safe manner. -// This class consumes stream inputs, buffers them, and writes them -// out when destructed respecting the cout_mutex. -class SafeCout { - std::stringstream stream; - -public: - ~SafeCout() { - std::scoped_lock coutLock{cout_mutex}; - std::cout << stream.str(); - } - - template - SafeCout & operator<<(T&& arg) { - stream << std::forward(arg); - return *this; - } -}; - - -// A mock data object -struct Data { - bool isReady() const { - return _isReady; - } - - bool _isReady = false; - bool _isConsistent = false; -}; - - -// The function that processes the data. You don't need to touch it. -// It will check whether the data are in a consistent state, and -// idle a bit to simulate longer data processing. -// Note: It should run in parallel. -bool process(unsigned int threadIdx, Data const & data) { - bool processingOK = true; - - SafeCout{} << '[' << threadIdx << "] I'm starting to process the data now\n"; - if (!data._isConsistent) { - processingOK = false; - SafeCout{} << '[' << threadIdx << "] ERROR data isn't fully ready! Race condition!\n"; - } - - // Burn some CPU cycles to simulate intensive data processing. - const auto startTime = std::chrono::high_resolution_clock::now(); - int dummyCounter = 0; - while (std::chrono::high_resolution_clock::now() - startTime < 5s) { - ++dummyCounter; - } - return processingOK; -} - -/* - * ------------------------------------------------------------ - * Exercise code you need to work on. - * ------------------------------------------------------------ - * This program tries to implement a producer/multi-consumer dependency between threads. - * One producer provides some data, and multiple consumers wait for the data to become ready. - * - * The threads communicate via std::condition_variable, but the implementation is incomplete. - * - * Tasks: - * 1. Run the program and understand why the consumer threads start running too early (on some - * platforms, at least ...). - * Run it multiple times if necessary. - * Why do they wake up although they should remain sleeping? - * 2. Fix the race condition by protecting the data production phase with a lock. - * 3. When you run the program now, the consumers should start running only after the data are ready. - * Why do they run one by one, though? - * Check the CPU consumption with a tool like top in a second shell. - * Ideally, we want 400% utilisation. - * 4. Fix the consumer waiting phase like in the lecture to make the consumers run in parallel. - * Check the CPU consumption again. - */ - - -int main() { - std::mutex mutex; - std::condition_variable cond; - Data data; - - // DATA-PROCESSING THREADS - // Here we start the processing threads. They have to wait for the data to be ready, - // and then they should process it in parallel. - auto processData = [&](unsigned int threadIdx){ - SafeCout{} << '[' << threadIdx << "] I'm starting to wait\n"; - { - std::unique_lock lock{mutex}; - cond.wait(lock, [&](){ return data.isReady(); }); - } - auto result = process(threadIdx, data); - - SafeCout{} << '[' << threadIdx << "] Done " << (result ? "OK" : "with failure!") << '\n'; - }; - - std::vector consumers; - for (unsigned int i=0; i < 4; ++i) { - consumers.emplace_back(processData, i); - } - - // DATA-PRODUCER THREAD - // This thread produces the data. We simulate a complicated way of producing the data - // by making the thread wait for a few seconds during the data production. - std::thread producer([&](){ - SafeCout{} << "[p] Starting to produce data\n"; - { - std::scoped_lock lock(mutex); - data._isReady = true; - // Sleep a bit to simulate a complicated set up phase - std::this_thread::sleep_for(6s); - data._isConsistent = true; - } - SafeCout{} << "[p] Data ready now\n"; - - // Wake up all threads - cond.notify_all(); - }); - - // Join all threads, so we don't terminate prematurely - producer.join(); - for (auto & t : consumers) { - t.join(); - } - - return 0; -} diff --git a/code/constness/CMakeLists.txt b/code/constness/CMakeLists.txt deleted file mode 100644 index 538656f3..00000000 --- a/code/constness/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( constness LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) - -# Create the user's executable. -add_executable( constplay "constplay.cpp" ) diff --git a/code/constness/Makefile b/code/constness/Makefile deleted file mode 100644 index a4e309c2..00000000 --- a/code/constness/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: constplay - -clean: - rm -f *o constplay *~ constplay.sol - -constplay : constplay.cpp - ${CXX} -Wall -Wextra -L. -o $@ $< diff --git a/code/constness/README.md b/code/constness/README.md deleted file mode 100644 index 991daa9e..00000000 --- a/code/constness/README.md +++ /dev/null @@ -1,6 +0,0 @@ - -## Instructions - -* open `constplay.cpp` -* try to find out which lines will be problematic -* try to compile and check your findings diff --git a/code/constness/constplay.cpp b/code/constness/constplay.cpp deleted file mode 100644 index 2ce465b4..00000000 --- a/code/constness/constplay.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include - -int identity(int a) { - return a; -}; - -int identityConst(const int a) { - return a; -}; - -int* identityp(int* a) { - return a; -}; - -const int* identitypConst(const int *a) { - return a; -}; - -struct ConstTest { - void hello(std::string &s) { - std::cout << "Hello " << s << '\n'; - } - void helloConst(std::string &s) const { - std::cout << "Hello " << s << '\n'; - } -}; - -int main() { - // try pointer to constant - int a = 1, b = 2; - int const *i = &a; - *i = 5; - i = &b; - - // try constant pointer - int * const j = &a; - *j = 5; - j = &b; - - // try constant pointer to constant - int const * const k = &a; - *k = 5; - k = &b; - - // try constant arguments of functions - int l = 0; - const int m = 0; - identity(l); - identity(m); - identityConst(l); - identityConst(m); - - // try constant arguments of functions with pointers - int *p = 0; - const int *r = 0; - identityp(p); - identityp(r); - identitypConst(p); - identitypConst(r); - - // try constant method in a class - ConstTest t; - const ConstTest tc; - std::string s("World"); - t.hello(s); - tc.hello(s); - t.helloConst(s); - tc.helloConst(s); -} diff --git a/code/control/CMakeLists.txt b/code/control/CMakeLists.txt deleted file mode 100644 index 9b306229..00000000 --- a/code/control/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( control LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( control "control.cpp" ) - -# Create the "solution executable". -add_executable( control.sol EXCLUDE_FROM_ALL "solution/control.sol.cpp" ) -add_dependencies( solution control.sol ) diff --git a/code/control/Makefile b/code/control/Makefile deleted file mode 100644 index 356338ab..00000000 --- a/code/control/Makefile +++ /dev/null @@ -1,12 +0,0 @@ - -all: control -solution: control.sol - -clean: - rm -f *o *~ control control.sol - -control : control.cpp - $(CXX) --std=c++17 -g -Wall -Wextra -o $@ $^ - -control.sol: solution/control.sol.cpp - $(CXX) --std=c++17 -g -Wall -Wextra -o $@ $^ diff --git a/code/control/README.md b/code/control/README.md deleted file mode 100644 index cf327123..00000000 --- a/code/control/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Instructions - -## Part 1 - -* Replace the C++98-style for loop with a range-based loop -* Replace the if / else statement with a conditional operator - -## Part 2 - -* Replace the for loop with a while loop -* Try it with a do / while loop - -## Part 3 - -* Replace the if / else statement with a switch statement diff --git a/code/control/control.cpp b/code/control/control.cpp deleted file mode 100644 index 61991d3e..00000000 --- a/code/control/control.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include - -constexpr unsigned int numbers[]{1000001, 1000002, 1000003, 1000004, 1000005, 1000006, 1000007, 1000008, 1000009}; - -bool isodd(unsigned int i) { return i % 2 == 1; } - -void part1() { - int sum_odd = 0; - int sum_eve = 0; - for (int i = 0; i < 9; ++i) { - unsigned int num = numbers[i]; - if (isodd(num)) { - sum_odd += num; - } else { - sum_eve += num; - } - } - std::cout << "Sums: odd = " << sum_odd << ", even = " << sum_eve << "\n"; -} - -void part2() { - // print smallest n for which 1 + 2 + ... + n > 10000 - int sum = 0; - for (int i = 1; ; i++) { - sum += i; - if (sum > 10000) { - std::cout << i << "\n"; - break; - } - } -} - -enum class Language { English, French, German, Italian, Other }; - -void part3(Language l) { - if (l == Language::English) { - std::cout << "Hello\n"; - } else if (l == Language::French) { - std::cout << "Salut\n"; - } else if (l == Language::German) { - std::cout << "Hallo\n"; - } else if (l == Language::Italian) { - std::cout << "Ciao\n"; - } else { - std::cout << "I don't speak your language\n"; - } -} - -int main() { - part1(); - part2(); - part3(Language::English); - return 0; -} diff --git a/code/control/solution/control.sol.cpp b/code/control/solution/control.sol.cpp deleted file mode 100644 index ce03ccba..00000000 --- a/code/control/solution/control.sol.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include - -constexpr unsigned int numbers[]{1000001, 1000002, 1000003, 1000004, 1000005, 1000006, 1000007, 1000008, 1000009}; - -bool isodd(unsigned int i) { return i % 2 == 1; } - -void part1() { - int sum_odd = 0; - int sum_eve = 0; - for (unsigned int num : numbers) { - // Note the usage of ternary expression to select the sum to which we add - // the ternary expression returns a reference to the right sum - (isodd(num) ? sum_odd : sum_eve) += num; - } - std::cout << "Sums: odd = " << sum_odd << ", even = " << sum_eve << "\n"; -} - -void part2() { - // print smallest n for which 1 + 2 + ... + n > 10000 - int sum = 0; - int i = 0; - while (sum <= 10000) { - ++i; - sum += i; - } - std::cout << i << "\n"; -} - -void part2bis() { - // print smallest n for which 1 + 2 + ... + n > 10000 - int sum = 0; - int i = 0; - do { - ++i; - sum += i; - } while (sum <= 10000); - std::cout << i << "\n"; -} - -enum class Language { English, French, German, Italian, Other }; - -void part3(Language l) { - switch (l) { - case Language::English: - std::cout << "Hello\n"; - break; - case Language::French: - std::cout << "Salut\n"; - break; - case Language::German: - std::cout << "Hallo\n"; - break; - case Language::Italian: - std::cout << "Ciao\n"; - break; - default: - std::cout << "Don't speak your language\n"; - } -} - -int main() { - part1(); - part2(); - part2bis(); - part3(Language::English); - return 0; -} diff --git a/code/cppcheck/CMakeLists.txt b/code/cppcheck/CMakeLists.txt deleted file mode 100644 index 50bc85d8..00000000 --- a/code/cppcheck/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( cppcheck LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( cppcheck_randomize "randomize.cpp" ) - -# Create the "solution executable". -add_executable( cppcheck_randomize.sol EXCLUDE_FROM_ALL "solution/randomize.sol.cpp" ) -add_dependencies( solution cppcheck_randomize.sol ) diff --git a/code/cppcheck/Makefile b/code/cppcheck/Makefile deleted file mode 100644 index 4c864661..00000000 --- a/code/cppcheck/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: randomize -solution: randomize.sol - -clean: - rm -f *o randomize *~ randomize.sol - -randomize : randomize.cpp - ${CXX} -g -O0 -Wall -Wextra -L. -o $@ $< - -randomize.sol : solution/randomize.sol.cpp - ${CXX} -g -O0 -Wall -Wextra -L. -o $@ $< diff --git a/code/cppcheck/README.md b/code/cppcheck/README.md deleted file mode 100644 index 98fe0d93..00000000 --- a/code/cppcheck/README.md +++ /dev/null @@ -1,8 +0,0 @@ - -## Instructions - -* compile, run, see that it works -* use valgrind : no issue -* use cppcheck, see the problem -* analyze the issue, and fix it -* bonus : understand why valgrind did not complain and how the standard deviation could be biased ( hint : use gdb and check addresses of v and diffs). diff --git a/code/cppcheck/randomize.cpp b/code/cppcheck/randomize.cpp deleted file mode 100644 index 45d31c0b..00000000 --- a/code/cppcheck/randomize.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include - -#define LEN 1000 -#define STEP 10 - -void swap(int *a, int*b) { - int c = *a; - *a = *b; - *b = c; -} - -void randomize(int* v, unsigned int len) { - // we randomize via len random inversions - for (unsigned int i = 0; i < len; i++) { - int a = rand()%len; - int b = rand()%len; - swap(v+a, v+b); - } -} - -void fillVector(int* v, unsigned int len) { - for (unsigned int i = 0; i < len; i++) v[i] = i*STEP; -} - -int main() { - int v[LEN-1]; - // create and randomize vector - fillVector(v, LEN+1); - randomize(v, LEN+1); - - // compute diffs - int diffs[LEN]; - for (unsigned int i = 0; i < LEN; i++) - diffs[i] = v[i+1] - v[i]; - - // compute standard deviation of it - float sum = 0; - float sumsq = 0; - for (unsigned int i = 0; i < LEN; i ++) { - sum += diffs[i]; - sumsq += diffs[i]*diffs[i]; - } - float mean = sum/LEN; - float stddev = sqrt(sumsq/LEN - mean*mean) ; - std::cout << "Range = [0, " << STEP*LEN << "]\n" - << "Mean = " << mean - << "\nStdDev = " << stddev << '\n'; -} diff --git a/code/cppcheck/solution/randomize.sol.cpp b/code/cppcheck/solution/randomize.sol.cpp deleted file mode 100644 index f48454b0..00000000 --- a/code/cppcheck/solution/randomize.sol.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include - -#define LEN 1000 -#define STEP 10 - -void swap(int *a, int*b) { - int c = *a; - *a = *b; - *b = c; -} - -void randomize(int* v, unsigned int len) { - // we randomize via len random inversions - for (unsigned int i = 0; i < len; i++) { - int a = rand()%len; - int b = rand()%len; - swap(v+a, v+b); - } -} - -void fillVector(int* v, unsigned int len) { - for (unsigned int i = 0; i < len; i++) v[i] = i*STEP; -} - -int main() { - int v[LEN+1]; - // create and randomize vector - fillVector(v, LEN+1); - randomize(v, LEN+1); - - // compute diffs - int diffs[LEN]; - for (unsigned int i = 0; i < LEN; i++) - diffs[i] = v[i+1] - v[i]; - - // compute standard deviation of it - float sum = 0; - float sumsq = 0; - for (unsigned int i = 0; i < LEN; i ++) { - sum += diffs[i]; - sumsq += diffs[i]*diffs[i]; - } - float mean = sum/LEN; - float stddev = sqrt(sumsq/LEN - mean*mean) ; - std::cout << "Range = [0, " << STEP*LEN << "]\n" - << "Mean = " << mean - << "\nStdDev = " << stddev << '\n'; -} diff --git a/code/debug/CMakeLists.txt b/code/debug/CMakeLists.txt deleted file mode 100644 index 929ae8ac..00000000 --- a/code/debug/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( debug LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( debug_randomize "randomize.cpp" ) - -# Create the "solution executable". -add_executable( debug_randomize.sol EXCLUDE_FROM_ALL "solution/randomize.sol.cpp" ) -add_dependencies( solution debug_randomize.sol ) diff --git a/code/debug/Makefile b/code/debug/Makefile deleted file mode 100644 index 414fc622..00000000 --- a/code/debug/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: randomize -solution: randomize.sol - -clean: - rm -f *o randomize *~ randomize.sol core - -randomize : randomize.cpp - ${CXX} -g -O0 -L. -o $@ $< - -randomize.sol : solution/randomize.sol.cpp - ${CXX} -g -O0 -Wall -Wextra -L. -o $@ $< diff --git a/code/debug/README.md b/code/debug/README.md deleted file mode 100644 index 4c53f527..00000000 --- a/code/debug/README.md +++ /dev/null @@ -1,15 +0,0 @@ -## Instructions for the "debug" exercise - -* compile, run, see the crash -* run it in gdb -* inspect backtrace, variables -* find problem and fix bug -* try stepping, breakpoints -* use -Wall -Wextra and see warning - - -### Go back to the "valgrind" exercise - -* check it with valgrind -* analyze the issue, see that the variance was biaised -* fix the issue diff --git a/code/debug/randomize.cpp b/code/debug/randomize.cpp deleted file mode 100644 index 6a208fbf..00000000 --- a/code/debug/randomize.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include - -#define LEN 1000 -#define STEP 7 - -void swap(int *a, int*b) { - int c = *a; - *a = *b; - *b = c; -} - -void randomize(int* v, unsigned int len) { - // we randomize via len random inversions - for (unsigned int i = 0; i < len; i++) { - int a = rand()%len; - int b = rand()%len; - swap(v+a, v+b); - } -} - -void createAndFillVector(int** v, unsigned int len) { - *v = new int[LEN]; - for (unsigned int i = 0; i < len; i++) (*v)[i] = i*STEP; -} - -int main() { - int *v = nullptr; - // create and randomize vector - randomize(v, LEN+1); - createAndFillVector(&v, LEN+1); - - // compute diffs - int *diffs = new int[LEN]; - for (unsigned int i = 0; i < LEN; i++) - diffs[i] = v[i+1] - v[i]; - - // compute standard deviation of it - float sum = 0; - float sumsq = 0; - for (unsigned int i = 0; i < LEN; i ++) { - sum += diffs[i]; - sumsq += diffs[i]*diffs[i]; - } - float mean = sum/LEN; - float stddev = sqrt(sumsq/LEN - mean*mean) ; - std::cout << "Range = [0, " << STEP*LEN << "]\n" - << "Mean = " << mean - << "\nStdDev = " << stddev << '\n'; - - delete[] v; - delete[] diffs; -} diff --git a/code/debug/solution/randomize.sol.cpp b/code/debug/solution/randomize.sol.cpp deleted file mode 100644 index 46462bf6..00000000 --- a/code/debug/solution/randomize.sol.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include - -#define LEN 1000 -#define STEP 7 - -void swap(int *a, int*b) { - int c = *a; - *a = *b; - *b = c; -} - -void randomize(int* v, unsigned int len) { - // we randomize via len random inversions - for (unsigned int i = 0; i < len; i++) { - int a = rand()%len; - int b = rand()%len; - swap(v+a, v+b); - } -} - -void createAndFillVector(int** v, unsigned int len) { - *v = new int[len]; - for (unsigned int i = 0; i < len; i++) (*v)[i] = i*STEP; -} - -int main() { - int *v = nullptr; - // create and randomize vector - createAndFillVector(&v, LEN+1); - randomize(v, LEN+1); - - // compute diffs - int *diffs = new int[LEN]; - for (unsigned int i = 0; i < LEN; i++) - diffs[i] = v[i+1] - v[i]; - - // compute standard deviation of it - float sum = 0; - float sumsq = 0; - for (unsigned int i = 0; i < LEN; i ++) { - sum += diffs[i]; - sumsq += diffs[i]*diffs[i]; - } - float mean = sum/LEN; - float stddev = sqrt(sumsq/LEN - mean*mean) ; - std::cout << "Range = [0, " << STEP*LEN << "]\n" - << "Mean = " << mean - << "\nStdDev = " << stddev << '\n'; - - delete[] v; - delete[] diffs; -} diff --git a/code/exercisesIntro.tex b/code/exercisesIntro.tex deleted file mode 100644 index 53577c8a..00000000 --- a/code/exercisesIntro.tex +++ /dev/null @@ -1,190 +0,0 @@ -\documentclass[compress]{beamer} -\usetheme{Warsaw} -\useoutertheme{split} - -\usepackage{minted} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Improvement on the default split theme : added line numbers % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\setbeamercolor{frametitle}{fg=white} -\setbeamercolor{frametitle right}{fg=white} - -\defbeamertemplate*{footline}{mysplit theme} -{% - \leavevmode% - \hbox{\begin{beamercolorbox}[wd=.5\paperwidth,ht=2.5ex,dp=1.125ex,leftskip=.3cm plus1fill,rightskip=.3cm]{author in head/foot}% - \usebeamerfont{author in head/foot}\insertshortauthor - \end{beamercolorbox}% - \begin{beamercolorbox}[wd=.4\paperwidth,ht=2.5ex,dp=1.125ex,leftskip=.3cm,rightskip=.3cm plus1fil]{title in head/foot}% - \usebeamerfont{title in head/foot}\insertshorttitle - \end{beamercolorbox}}% - \begin{beamercolorbox}[wd=.1\paperwidth,ht=2.5ex,dp=1.125ex,leftskip=.1cm plus1fill,rightskip=.1cm]{date in head/foot} - \usebeamerfont{date in head/foot} \insertframenumber{} / \inserttotalframenumber - \end{beamercolorbox} - \vskip0pt% -} - -\defbeamertemplate*{headline}{mysplit theme} -{% - \leavevmode% - \begin{beamercolorbox}[wd=.45\paperwidth,ht=2.5ex,dp=1.125ex]{section in head/foot}% - \insertsectionnavigationhorizontal{.4\paperwidth}{\hskip0pt plus1filll}{}% - \end{beamercolorbox}% - \begin{beamercolorbox}[wd=.55\paperwidth,ht=2.5ex,dp=1.125ex]{subsection in head/foot}% - \insertsubsectionnavigationhorizontal{.6\paperwidth}{}{\hskip0pt plus1filll}% - \end{beamercolorbox}% -} - -\newcommand{\cpp}{C$^{++}$} - -\title{Exercises HowTo} -\author[B. Gruber, S. Hageboeck, S. Ponce]{Based on the work of \\ S\'ebastien Ponce \\ \texttt{sebastien.ponce@cern.ch}} -\institute{CERN} -\date{March 2022} -\pgfdeclareimage[height=0.5cm]{cernlogo}{CERN-logo.jpg} -\logo{\pgfuseimage{cernlogo}} - -\begin{document} - -\begin{frame} - \titlepage -\end{frame} - -\begin{frame} - \frametitle{Setup requirements} - \begin{exampleblock}{Required} - \begin{itemize} - \item decent \cpp editor - \item any \cpp compiler supporting \cpp17 - \end{itemize} - \end{exampleblock} - \begin{alertblock}{Good to have} - \begin{itemize} - \item \texttt{git} for getting/managing your code - \item \texttt{gdb} to debug your problems - \item valgrind, kcachegrind, cppcheck, clang-format, clang-tidy for corresponding exercises - \end{itemize} - \end{alertblock} - \begin{block}{\cpp and python specific needs} - \begin{itemize} - \item python3, libpython3-dev - \item ctypes, matplotlib, numpy python packages - \end{itemize} - \end{block} -\end{frame} - -\begin{frame}[fragile] - \setlength{\textwidth}{11.2cm} - \frametitle{How to get exercises' code} - \begin{exampleblock}{Best way} - \small - \begin{verbatim} - -git clone https://github.com/hsf-training/cpluspluscourse.git -cd cpluspluscourse/code - \end{verbatim} - \end{exampleblock} - \begin{alertblock}{Alternative} - \small - \begin{verbatim} - -wget https://github.com/hsf-training/cpluspluscourse/archive\ -/refs/heads/master.zip -unzip master.zip -cd cpluspluscourse-master/code - \end{verbatim} - \end{alertblock} -\end{frame} - -\begin{frame} - \frametitle{Anatomy of an exercise} - Each exercise is in a subdirectory with mainly 3 sets of files - \begin{exampleblock}{*.hpp and *.cpp files} - \begin{itemize} - \item the code to understand and fix/complete - \item you never start from scratch - \end{itemize} - \end{exampleblock} - \begin{block}{Makefile / cmake} - \begin{itemize} - \item prepared Makefile for easy compilation - \item ``make'' and ``make clean'' are available - \item cmake is also supported - \end{itemize} - \end{block} - \begin{alertblock}{solution subdirectory} - \begin{itemize} - \item one possible solution to the exercise (``make solution'') - \item please do not use before trying ! - \end{itemize} - \end{alertblock} -\end{frame} - -\begin{frame} - \frametitle{Just follow the instructions} - \begin{itemize} - \item Each exercise comes with a set of instructions in the course - \item See for example exercise on polymorphism - \item Also present in exercise subdir in markdown format - \begin{itemize} - \item Very practical to read on github - \end{itemize} - \end{itemize} - \begin{alertblock}{Exercise Time} - \begin{itemize} - \item go to code/polymorphism - \item look at the code - \item open test.cpp - \item create a Pentagon, call its perimeter method - \item create an Hexagon, call its perimeter method - \item create an Hexagon, call its parent's perimeter method - \item retry with virtual methods - \end{itemize} - \end{alertblock} -\end{frame} - -\begin{frame}[fragile] - \frametitle{How to test your setup} - \begin{exampleblock}{Just use hello exercise} - \begin{itemize} - \item go to code/hello - \item follow the README - \end{itemize} - \end{exampleblock} - \begin{block}{Practically} - \begin{minted}{shell} - cd code/hello - \end{minted} - \begin{itemize} - \item g++ and make - \begin{minted}[gobble=6]{shell} - make - export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. - ./hello - \end{minted} - \item valgrind, callgrind and X11 - \begin{minted}[gobble=6]{shell} - valgrind --tool=callgrind ./hello; kcachegrind - \end{minted} - \item cppcheck - \begin{minted}[gobble=6]{shell} - cppcheck . - \end{minted} - \end{itemize} - \end{block} -\end{frame} - -\begin{frame} - \frametitle{How to get help} - \Large Several channels available - \begin{itemize} - \item Training Notebook - \item Mattermost channel - \item Zoom rooms with mentors - \end{itemize} - All links and details on the indico page of the event -\end{frame} - -\end{document} diff --git a/code/functions/CMakeLists.txt b/code/functions/CMakeLists.txt deleted file mode 100644 index fc51e809..00000000 --- a/code/functions/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( functions LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( functions "Structs.h" "Structs.cpp" "functions.cpp" ) - -# Create the "solution executable". -add_executable( functions.sol EXCLUDE_FROM_ALL "Structs.h" "Structs.cpp" "solution/functions.sol.cpp" ) -target_include_directories(functions.sol PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") -add_dependencies( solution functions.sol ) - -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) - target_compile_definitions( functions PRIVATE _CRT_SECURE_NO_WARNINGS ) - target_compile_definitions( functions.sol PRIVATE _CRT_SECURE_NO_WARNINGS ) -endif() diff --git a/code/functions/Makefile b/code/functions/Makefile deleted file mode 100644 index 6bc249ed..00000000 --- a/code/functions/Makefile +++ /dev/null @@ -1,15 +0,0 @@ - -all: functions -solution: functions.sol - -clean: - rm -f *o *~ functions functions.sol - -%.o: %.cpp %.h - ${CXX} -std=c++17 -Wall -Wextra -c -o $@ $< - -functions : functions.cpp Structs.o - ${CXX} -std=c++17 -Wall -Wextra -o $@ $^ - -functions.sol : solution/functions.sol.cpp Structs.o - ${CXX} -I. -std=c++17 -Wall -Wextra -o $@ $^ diff --git a/code/functions/README.md b/code/functions/README.md deleted file mode 100644 index d376c063..00000000 --- a/code/functions/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Functions and how arguments are passed in C++ - -Here, we will look a bit into how arguments are passed into functions. -You will find an example where everything is passed by value (by copy), but there is a struct that is slow to copy. -We will try to work with it without copying it. - -# Instructions - -## Step 1 - -Check out `functions.cpp`, compile it (`make`) and run the program. -Check out `Structs.h`. It defines two structs that we will work with : `FastToCopy` and `SlowToCopy`. -They are exactly what their name says, so let's try to avoid copying the latter. - -## Step 2 - -Using `printFiveCharacters()` as an example, write a function that prints the first five characters of `SlowToCopy`. Call it in `main()`. - -## Step 3 - -Try passing by copy and passing by reference, see the difference. - -## Step 4 - -When passing by reference, ensure that your `printFiveCharacters` cannot inadvertently modify the original object. To test its const correctness, try adding something like `argument.data[0] = 'a';` to your print function. Try both with and without const attributes in your print function's signature. diff --git a/code/functions/Structs.cpp b/code/functions/Structs.cpp deleted file mode 100644 index d3b42da8..00000000 --- a/code/functions/Structs.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "Structs.h" - -#include -#include -#include -#include - -/// Construct a new instance of SlowToCopy. -SlowToCopy::SlowToCopy() { - strncpy(data, "Large type", sizeof(data)); -} - -/// Construct a new instance of SlowToCopy. -SlowToCopy::SlowToCopy(const char* string) { - strncpy(data, string, sizeof(data)); -} - -/// Construct a new instance of SlowToCopy, copying the data from 'other'. -SlowToCopy::SlowToCopy(const SlowToCopy& other) { - printf("%s: Please don't copy me. This is slow.\n", __func__); - std::this_thread::sleep_for(std::chrono::seconds(3)); - memcpy(data, other.data, sizeof(data)); -} diff --git a/code/functions/Structs.h b/code/functions/Structs.h deleted file mode 100644 index f255d146..00000000 --- a/code/functions/Structs.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -struct FastToCopy { - char data[10]; -}; - -struct SlowToCopy { - char data[1000000]; - - // Functions to create and copy this struct. - // We go into details on the next days. - SlowToCopy(); - SlowToCopy(const char* string); - SlowToCopy(const SlowToCopy& other); -}; diff --git a/code/functions/functions.cpp b/code/functions/functions.cpp deleted file mode 100644 index ac7373e0..00000000 --- a/code/functions/functions.cpp +++ /dev/null @@ -1,33 +0,0 @@ - -/* Tasks: - * 1. Check out Structs.h. It defines two structs that we will work with. - * FastToCopy - * SlowToCopy - * They are exactly what their name says, so let's try to avoid copying the latter. - * 2. Using "printFiveCharacters()" as an example, write a function that prints the first five characters of "SlowToCopy". - * Call it in main(). - * 3. Try passing by copy and passing by reference, see the difference. - * 4. When passing by reference, ensure that your "printFiveCharacters" cannot inadvertently modify the original object. - * To test its const correctness, try adding something like - * argument.data[0] = 'a'; - * to your print function. - * Try both with and without const attributes in your print function's signature. - */ - -#include "Structs.h" // The data structs we will work with - -#include // For printing - -void printFiveCharacters(FastToCopy argument) { - printf("The first five characters are '%.5s'\n", argument.data); -} - -int main() { - FastToCopy fast = {"abcdef"}; - printFiveCharacters(fast); - - SlowToCopy slow = {"ghijkl"}; - // print it here - - return 0; -} diff --git a/code/functions/solution/functions.sol.cpp b/code/functions/solution/functions.sol.cpp deleted file mode 100644 index 454257c3..00000000 --- a/code/functions/solution/functions.sol.cpp +++ /dev/null @@ -1,47 +0,0 @@ - -/* Tasks: - * 1. Check out Structs.h. It defines two structs that we will work with. - * FastToCopy - * SlowToCopy - * They are exactly what their name says, so let's try to avoid copying the latter. - * 2. Using "printFiveCharacters()" as an example, write a function that prints the first five characters of "SlowToCopy". - * Call it in main(). - * 3. Try passing by copy and passing by reference, see the difference. - * 4. When passing by reference, ensure that your "printFiveCharacters" cannot inadvertently modify the original object. - * To test its const correctness, try adding something like - * argument.data[0] = 'a'; - * to your print function. - * Try both with and without const attributes in your print function's signature. - */ - -#include "Structs.h" // The data structs we will work with - -#include // For printing - -void printFiveCharacters(FastToCopy argument) { - printf("The first five characters are '%.5s'\n", argument.data); -} - -void printFiveCharacters(const SlowToCopy & argument) { - //argument.data[0] = '\n' ; // EXPECTED COMPILATION ERROR - printf("The first five characters are '%.5s'\n", argument.data); -} - -void printFiveCharactersWithCopy(SlowToCopy argument) { - printf("The first five characters are '%.5s'\n", argument.data); - // We can actually modify the argument if we want, since it's a copy: - argument.data[0] = 'a'; -} - -int main() { - FastToCopy fast = {"abcdef"}; - printFiveCharacters(fast); - - SlowToCopy slow = {"ghijkl"}; - printFiveCharacters(slow); - - printf("Now printing with copy:\n"); - printFiveCharactersWithCopy(slow); - - return 0; -} diff --git a/code/helgrind/CMakeLists.txt b/code/helgrind/CMakeLists.txt deleted file mode 100644 index 039658b5..00000000 --- a/code/helgrind/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( helgrind LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Figure out how to use the platform's thread capabilities. -find_package( Threads REQUIRED ) - -# Create the user's executable. -add_executable( fiboMT "fiboMT.cpp" ) -target_link_libraries( fiboMT PRIVATE Threads::Threads ) - -# Create the "solution executable". -add_executable( fiboMT.sol EXCLUDE_FROM_ALL "solution/fiboMT.sol.cpp" ) -target_link_libraries( fiboMT.sol PRIVATE Threads::Threads ) -add_dependencies( solution fiboMT.sol ) diff --git a/code/helgrind/Makefile b/code/helgrind/Makefile deleted file mode 100644 index 8fec2597..00000000 --- a/code/helgrind/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: fiboMT -solution: fiboMT.sol - -clean: - rm -f *o fiboMT *~ fiboMT.sol core - -fiboMT : fiboMT.cpp - ${CXX} -g -O0 -Wall -Wextra -pthread -o $@ $< - -fiboMT.sol : solution/fiboMT.sol.cpp - ${CXX} -g -O0 -Wall -Wextra -pthread -o $@ $< diff --git a/code/helgrind/README.md b/code/helgrind/README.md deleted file mode 100644 index 408ae6ba..00000000 --- a/code/helgrind/README.md +++ /dev/null @@ -1,7 +0,0 @@ - -## Instructions - -* compile, run -* check it with valgrind. You may see strange behavior but it may be perfectly fine. -* check it with valgrind --tool=helgrind -* understand issue and fix diff --git a/code/helgrind/fiboMT.cpp b/code/helgrind/fiboMT.cpp deleted file mode 100644 index fb4b25a8..00000000 --- a/code/helgrind/fiboMT.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#define NBITERATIONS 5 -#define MIN 22 -#define MAX 25 - -struct WorkToDo { - char* title; - int a; -}; - -unsigned int fibo(unsigned a) { - if (a == 1 || a == 0) { - return 1; - } else { - return fibo(a-1)+fibo(a-2); - } -} - -void * computation(void* arg) { - WorkToDo *work = (WorkToDo*) arg; - unsigned long f = fibo(work->a); - free(work->title); - work->title = 0; - return (void*)f; -} - -void launchFibo(const char* title, int a) { - pthread_t t; - WorkToDo w; - w.title = strdup(title); - w.a = a; - if (pthread_create(&t, NULL, computation, &w)) { - std::cerr << "Error creating thread\n"; - return; - } - struct timespec sl = {.tv_sec = 0, .tv_nsec=1000}; - nanosleep(&sl, NULL); - std::cout << "Computing " << w.title << '\n'; - void *result; - pthread_join(t, &(result)); - std::cout << title << " = " << (unsigned long)result << '\n'; -} - -int main() { - for (unsigned int i = 0; i < NBITERATIONS; i++) { - unsigned int a = MIN+rand()%(MAX-MIN); - std::stringstream ss; - ss << "Fibo(" << a << ")"; - launchFibo(ss.str().c_str(), a); - } -} diff --git a/code/helgrind/solution/fiboMT.sol.cpp b/code/helgrind/solution/fiboMT.sol.cpp deleted file mode 100644 index ac22bee3..00000000 --- a/code/helgrind/solution/fiboMT.sol.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#define NBITERATIONS 5 -#define MIN 22 -#define MAX 25 - -struct WorkToDo { - char* title; - int a; -}; - -unsigned int fibo(unsigned a) { - if (a == 1 || a == 0) { - return 1; - } else { - return fibo(a-1)+fibo(a-2); - } -} - -void * computation(void* arg) { - WorkToDo *work = (WorkToDo*) arg; - unsigned long f = fibo(work->a); - return (void*)f; -} - -void launchFibo(const char* title, int a) { - pthread_t t; - WorkToDo w; - w.title = strdup(title); - w.a = a; - if (pthread_create(&t, NULL, computation, &w)) { - std::cerr << "Error creating thread\n"; - return; - } - struct timespec sl = {.tv_sec = 0, .tv_nsec=1000}; - nanosleep(&sl, NULL); - std::cout << "Computing " << w.title << '\n'; - free(w.title); - w.title = 0; - void *result; - pthread_join(t, &(result)); - std::cout << title << " = " << (unsigned long)result << '\n'; -} - -int main() { - for (unsigned int i = 0; i < NBITERATIONS; i++) { - unsigned int a = MIN+rand()%(MAX-MIN); - std::stringstream ss; - ss << "Fibo(" << a << ")"; - launchFibo(ss.str().c_str(), a); - } -} diff --git a/code/hello/CMakeLists.txt b/code/hello/CMakeLists.txt deleted file mode 100644 index 6fa53b65..00000000 --- a/code/hello/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( hello LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) - -# Set up the library. -add_library( helloLib "hello.hpp" "hello.cpp" ) -set_target_properties( helloLib PROPERTIES OUTPUT_NAME "hello" ) - -# Set up the executable. -add_executable( hello "main.cpp" ) -target_link_libraries( hello PRIVATE helloLib ) diff --git a/code/hello/Makefile b/code/hello/Makefile deleted file mode 100644 index b4059990..00000000 --- a/code/hello/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -all: libhello.a hello - -solution: all - -clean: - rm -f *.o *.a *.so hello *~ callgrind.out.* - -hello.o: hello.cpp hello.hpp - $(CXX) --std=c++17 -c -g -Wall -Wextra -o $@ $< - -libhello.a: hello.o - ar rcs $@ $< - -hello : main.cpp libhello.a - $(CXX) --std=c++17 -g -Wall -Wextra -o $@ $^ diff --git a/code/hello/README.md b/code/hello/README.md deleted file mode 100644 index 7388913b..00000000 --- a/code/hello/README.md +++ /dev/null @@ -1,36 +0,0 @@ - -# Hello World ! - -This example should help to check that your machine is well installed. - -## make vs cmake - -On any linux like system, provided you have a "recent enough" g++, this should work out of the box: -``` -make -./hello -``` - -On native Windows, build with `cmake`: -``` -mkdir build -cd build -cmake .. -cmake --build . -Debug/hello.exe -``` - -## valgrind & callgrind & graphical tools - -Try: -``` -valgrind --tool=callgrind ./hello -kcachegrind -``` - -## cppcheck - -Try: -``` -cppcheck *.hpp *.cpp -``` diff --git a/code/hello/hello.cpp b/code/hello/hello.cpp deleted file mode 100644 index 327f97ba..00000000 --- a/code/hello/hello.cpp +++ /dev/null @@ -1,7 +0,0 @@ - -#include -#include "hello.hpp" - -void printHello(int i) { - std::cout << "Hello, world " << i << '\n'; -} diff --git a/code/hello/hello.hpp b/code/hello/hello.hpp deleted file mode 100644 index d53f7ae8..00000000 --- a/code/hello/hello.hpp +++ /dev/null @@ -1,7 +0,0 @@ - -#ifndef HELLO_HPP -#define HELLO_HPP - -void printHello(int i) ; - -#endif diff --git a/code/hello/main.cpp b/code/hello/main.cpp deleted file mode 100644 index 522c13f8..00000000 --- a/code/hello/main.cpp +++ /dev/null @@ -1,11 +0,0 @@ - -#include -#include "hello.hpp" - -int main() { - int n = 3; - for (int i = 0; i < n; i++) { - printHello(i); - } - return 0; -} diff --git a/code/loopsRefsAuto/CMakeLists.txt b/code/loopsRefsAuto/CMakeLists.txt deleted file mode 100644 index 7afe5f3f..00000000 --- a/code/loopsRefsAuto/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( loopsRefsAuto LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( loopsRefsAuto "loopsRefsAuto.cpp" ) - -# Create the "solution executable". -add_executable( loopsRefsAuto.sol EXCLUDE_FROM_ALL "solution/loopsRefsAuto.sol.cpp" ) -add_dependencies( solution loopsRefsAuto.sol ) diff --git a/code/loopsRefsAuto/Makefile b/code/loopsRefsAuto/Makefile deleted file mode 100644 index 322609f1..00000000 --- a/code/loopsRefsAuto/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -all: loopsRefsAuto -solution: loopsRefsAuto.sol - -clean: - rm -f *o *~ loopsRefsAuto loopsRefsAuto.sol - -%.o: %.cpp %.h - ${CXX} -std=c++17 -Wall -Wextra -c -o $@ $< - -loopsRefsAuto : loopsRefsAuto.cpp - ${CXX} -std=c++17 -Wall -Wextra -o $@ $^ - -loopsRefsAuto.sol : solution/loopsRefsAuto.sol.cpp - ${CXX} -std=c++17 -Wall -Wextra -o $@ $^ diff --git a/code/loopsRefsAuto/README.md b/code/loopsRefsAuto/README.md deleted file mode 100644 index 2587f7f7..00000000 --- a/code/loopsRefsAuto/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Exercise about for loops, references and the `auto` keyword. - -Here, we are playing with a struct that doesn't like to be copied. Imagine that this is some large data -that is expensive to copy. We will learn how to work with an array of such data without copying it. - -## Instructions: -- Open `loopsRefsAuto.cpp`, and familiarise yourself with what happens in `main()`. -- Compile (`make`) and run the program. -- In the source file, you will find further tasks. diff --git a/code/loopsRefsAuto/loopsRefsAuto.cpp b/code/loopsRefsAuto/loopsRefsAuto.cpp deleted file mode 100644 index 912e29ce..00000000 --- a/code/loopsRefsAuto/loopsRefsAuto.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include - -struct DontCopyMe { - int resultA; - int resultB; - - // This is material for the second day: - DontCopyMe() = default; - DontCopyMe(const DontCopyMe& other) : - resultA(other.resultA), - resultB(other.resultB) - { printf("Please don't copy me\n"); } -}; - -int main() { - // We create an array of DontCopyMe structs: - DontCopyMe collection[10]; - - // Task 1: - // Write a for loop that initialises each struct's resultA and resultB with ascending integers. - // Verify the output of the program before and after you do this. - - - // Task 2: - // We use a range-based for loop to analyse the array of structs. - // The problem is: we are copying every DontCopyMe ... - // Fix this loop using references. - // Hint: Fix the type declaration "auto" in the loop head. - int resultA = 0; - int resultB = 0; - for (auto item : collection) { - resultA += item.resultA; - resultB += item.resultB; - } - - - printf("resultA = %d\tresultB = %d\n", resultA, resultB); - - return 0; -} - -// Task 3: -// Think about which loop needs write access to the DontCopyMe. -// Make sure that all references that don't need write access are const. -// Hint: C++ understands "auto const". diff --git a/code/loopsRefsAuto/solution/loopsRefsAuto.sol.cpp b/code/loopsRefsAuto/solution/loopsRefsAuto.sol.cpp deleted file mode 100644 index 2eb2ba96..00000000 --- a/code/loopsRefsAuto/solution/loopsRefsAuto.sol.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include - -struct DontCopyMe { - int resultA; - int resultB ; - - // This is material for the second day: - DontCopyMe() = default; - DontCopyMe(const DontCopyMe& other): - resultA(other.resultA), - resultB(other.resultB) - { printf("Please don't copy me\n"); } -}; - -int main() { - - DontCopyMe collection[10]; - - for ( int i = 0 ; i<10 ; ++i ) { - collection[i].resultA = i; - collection[i].resultB = 2*i; - } - - int resultA = 0; - int resultB = 0; - for (auto const & item : collection) { - resultA += item.resultA; - resultB += item.resultB; - } - - printf("resultA = %d\tresultB = %d\n", resultA, resultB); - - return 0; -} diff --git a/code/memcheck/CMakeLists.txt b/code/memcheck/CMakeLists.txt deleted file mode 100644 index b5d5689f..00000000 --- a/code/memcheck/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( memcheck LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's library. -add_library( memcheckPoly "Polygons.hpp" "Polygons.cpp" ) -set_target_properties( memcheckPoly PROPERTIES OUTPUT_NAME "poly" ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) - target_compile_definitions( memcheckPoly PRIVATE _USE_MATH_DEFINES ) -endif() - -# Create the user's executable. -add_executable( memleak "memleak.cpp" ) -target_link_libraries( memleak PRIVATE memcheckPoly ) - -# Create the "solution library". -add_library( memcheckPolySol EXCLUDE_FROM_ALL "solution/Polygons.sol.hpp" "solution/Polygons.sol.cpp" ) -set_target_properties( memcheckPolySol PROPERTIES OUTPUT_NAME "polysol" ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) - target_compile_definitions( memcheckPolySol PRIVATE _USE_MATH_DEFINES ) -endif() - -# Create the "solution executable". -add_executable( memleak.sol EXCLUDE_FROM_ALL "solution/memleak.sol.cpp" ) -target_link_libraries( memleak.sol PRIVATE memcheckPolySol ) -add_dependencies( solution memleak.sol ) diff --git a/code/memcheck/Makefile b/code/memcheck/Makefile deleted file mode 100644 index 3a5ebccc..00000000 --- a/code/memcheck/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -all: libpoly.so memleak -solution: libpolysol.so memleak.sol - -clean: - rm -f *o *so memleak *~ memleak.sol vgcore* - -libpoly.so: Polygons.cpp Polygons.hpp - $(CXX) -g -Wall -Wextra -shared -fPIC -o $@ $< - -memleak : memleak.cpp libpoly.so - $(CXX) -g -Wall -Wextra -o $@ $^ - -libpolysol.so: solution/Polygons.sol.cpp solution/Polygons.sol.hpp - $(CXX) -g -Wall -Wextra -shared -fPIC -o $@ $< - -memleak.sol : solution/memleak.sol.cpp libpolysol.so - $(CXX) -g -Wall -Wextra -o $@ $^ diff --git a/code/memcheck/Polygons.cpp b/code/memcheck/Polygons.cpp deleted file mode 100644 index 039e4866..00000000 --- a/code/memcheck/Polygons.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "Polygons.hpp" -#include -#include -#include -#include - -Polygon::Polygon(int n, float radius) : m_nbSides(n), m_radius(radius) {}; - -float Polygon::computePerimeter() { - std::cout << "Generic computePerimeter for polygons\n"; - return 2*m_nbSides*std::sin(static_cast(M_PI)/m_nbSides)*m_radius; -} - -Hexagon::Hexagon(char* name, float radius) : Polygon(6, radius) { - m_name = strdup(name); -} - -Hexagon::~Hexagon() { - free(m_name); - m_name = 0; -} diff --git a/code/memcheck/Polygons.hpp b/code/memcheck/Polygons.hpp deleted file mode 100644 index c36985b8..00000000 --- a/code/memcheck/Polygons.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -class Polygon { -public: - Polygon(int n, float radius); - ~Polygon(){}; - float computePerimeter(); -protected: - int m_nbSides; - float m_radius; -}; - -class Hexagon : public Polygon { -public: - Hexagon(char* name, float radius); - Hexagon(const Hexagon&) = delete; - Hexagon& operator=(const Hexagon&) = delete; - ~Hexagon(); - char* name() const {return m_name;}; -private: - char* m_name; -}; diff --git a/code/memcheck/README.md b/code/memcheck/README.md deleted file mode 100644 index e69de29b..00000000 diff --git a/code/memcheck/memleak.cpp b/code/memcheck/memleak.cpp deleted file mode 100644 index 87f08932..00000000 --- a/code/memcheck/memleak.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "Polygons.hpp" -#include - -Polygon* getHexa(char* name, float radius) { - return new Hexagon(name, radius); -} - -int main() { - // create an Hexagon, call its perimeter method - Polygon *hexa = getHexa((char*)"hexa", 1.0); - std::cout << "Hexa : perimeter = " << hexa->computePerimeter() << "\n\n"; - - // memory deallocation - delete hexa; -} diff --git a/code/memcheck/solution/Polygons.sol.cpp b/code/memcheck/solution/Polygons.sol.cpp deleted file mode 100644 index f216ba8b..00000000 --- a/code/memcheck/solution/Polygons.sol.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "Polygons.sol.hpp" -#include -#include -#include -#include - -Polygon::Polygon(int n, float radius) : m_nbSides(n), m_radius(radius) {}; - -float Polygon::computePerimeter() { - std::cout << "Generic computePerimeter for polygons\n"; - return 2*m_nbSides*std::sin(static_cast(M_PI)/m_nbSides)*m_radius; -} - -Hexagon::Hexagon(char* name, float radius) : Polygon(6, radius) { - m_name = strdup(name); -} - -Hexagon::~Hexagon() { - free(m_name); - m_name = 0; -} diff --git a/code/memcheck/solution/Polygons.sol.hpp b/code/memcheck/solution/Polygons.sol.hpp deleted file mode 100644 index 5cf0668f..00000000 --- a/code/memcheck/solution/Polygons.sol.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -class Polygon { -public: - Polygon(int n, float radius); - virtual ~Polygon(){}; - float computePerimeter(); -protected: - int m_nbSides; - float m_radius; -}; - -class Hexagon : public Polygon { -public: - Hexagon(char* name, float radius); - Hexagon(const Hexagon&) = delete; - Hexagon& operator=(const Hexagon&) = delete; - ~Hexagon(); - char* name() const {return m_name;}; -private: - char* m_name; -}; diff --git a/code/memcheck/solution/memleak.sol.cpp b/code/memcheck/solution/memleak.sol.cpp deleted file mode 100644 index e229f5fd..00000000 --- a/code/memcheck/solution/memleak.sol.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "Polygons.sol.hpp" -#include - -Polygon* getHexa(char* name, float radius) { - return new Hexagon(name, radius); -} - -int main() { - // create an Hexagon, call its perimeter method - Polygon *hexa = getHexa((char*)"hexa", 1.0); - std::cout << "Hexa : perimeter = " << hexa->computePerimeter() << "\n\n"; - - // memory deallocation - delete hexa; -} diff --git a/code/modern_oo/CMakeLists.txt b/code/modern_oo/CMakeLists.txt deleted file mode 100644 index 26171c93..00000000 --- a/code/modern_oo/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( modern_oo LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( particles "particles.cpp" ) - -# Create the "solution executable". -add_executable( particles.sol EXCLUDE_FROM_ALL "solution/particles.sol.cpp" ) -add_dependencies( solution particles.sol ) diff --git a/code/modern_oo/Makefile b/code/modern_oo/Makefile deleted file mode 100644 index 34c72d54..00000000 --- a/code/modern_oo/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: particles -solution: particles.sol - -clean: - rm -f *o particles particles.sol *~ callgrind.out.* - -particles: particles.cpp - ${CXX} -g -std=c++17 -Wall -Wextra -o $@ $< - -particles.sol : solution/particles.sol.cpp - ${CXX} -g -std=c++17 -Wall -Wextra -o $@ $< diff --git a/code/modern_oo/README.md b/code/modern_oo/README.md deleted file mode 100644 index 23bf956d..00000000 --- a/code/modern_oo/README.md +++ /dev/null @@ -1,8 +0,0 @@ - -## Prerequisites - -* know about classes in ancient C++ - -## Instructions - -* insert one `= delete`, one `= default` and one `override`. diff --git a/code/modern_oo/particles.cpp b/code/modern_oo/particles.cpp deleted file mode 100644 index 39789169..00000000 --- a/code/modern_oo/particles.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include // pour std::rand() -#include -#include - -class Particle - { - public : - Particle( double mass ) : mass_(mass) {} - double mass() { return mass_ ; } - virtual std::string name() { return "Particle" ; } - virtual ~Particle() {} - private : - Particle( const Particle & ) ; // non copiable - double mass_ ; - } ; - -class ChargedParticle : public Particle - { - public : - ChargedParticle( double mass, double charge ) - : Particle(mass), charge_(charge) {} - double charge() { return charge_ ; } - virtual std::string name() { return "ChargedParticle" ; } - private : - double charge_ ; - } ; - -void print( Particle & p ) - { - std::cout << p.name() << '\n' ; - std::cout << " mass = " << p.mass() << '\n' ; - } - -int main() - { - for ( int i = 0 ; i < 5 ; ++i ) - { - if ( std::rand() < (0.5 * double(RAND_MAX)) ) - { - Particle p(2) ; - print(p) ; - } - else - { - ChargedParticle p(1,1) ; - print(p) ; - std::cout << " charge = " << p.charge() << '\n' ; - } - } - } diff --git a/code/modern_oo/solution/particles.sol.cpp b/code/modern_oo/solution/particles.sol.cpp deleted file mode 100644 index ab5a0a2a..00000000 --- a/code/modern_oo/solution/particles.sol.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include // pour std::rand() -#include -#include - -class Particle - { - public : - Particle( double mass ) : mass_(mass) {} - Particle( const Particle & ) = delete ; - virtual ~Particle() = default ; - double mass() { return mass_ ; } - virtual std::string name() { return "Particle" ; } - private : - double mass_ ; - } ; - -class ChargedParticle : public Particle - { - public : - ChargedParticle( double mass, double charge ) - : Particle(mass), charge_(charge) {} - double charge() { return charge_ ; } - std::string name() override { return "ChargedParticle" ; } - private : - double charge_ = 0.0 ; - } ; - -void display( Particle & p ) - { - std::cout << p.name() << '\n' ; - std::cout << " mass = " << p.mass() << '\n' ; - } - -int main() - { - for ( int i = 0 ; i < 5 ; ++i ) - { - if ( std::rand() < (0.5 * double(RAND_MAX)) ) - { - Particle p(2) ; - display(p) ; - } - else - { - ChargedParticle p(1,1) ; - display(p) ; - std::cout << " charge = " << p.charge() << '\n' ; - } - } - } diff --git a/code/move/CMakeLists.txt b/code/move/CMakeLists.txt deleted file mode 100644 index 25e99bfb..00000000 --- a/code/move/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( move LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( trymove "NVector.hpp" "trymove.cpp" ) - -# Create the "solution executable". -add_executable( trymove.sol EXCLUDE_FROM_ALL "solution/NVector.sol.hpp" "solution/trymove.sol.cpp" ) -add_dependencies( solution trymove.sol ) diff --git a/code/move/Makefile b/code/move/Makefile deleted file mode 100644 index 16cc5b2a..00000000 --- a/code/move/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: trymove -solution: trymove.sol - -clean: - rm -f *o trymove trymove.sol *~ callgrind.out.* - -trymove : trymove.cpp NVector.hpp - ${CXX} -g -std=c++11 -O0 -Wall -Wextra -L. -o $@ $< - -trymove.sol : solution/trymove.sol.cpp solution/NVector.sol.hpp - ${CXX} -g -std=c++11 -O0 -Wall -Wextra -L. -o $@ $< diff --git a/code/move/NVector.hpp b/code/move/NVector.hpp deleted file mode 100644 index 03058907..00000000 --- a/code/move/NVector.hpp +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include -#include -#include - -template -class NVector { -public: - typedef T BaseType; - - NVector(); - NVector(T initialValue, T inc); - NVector(const NVector &other); - ~NVector(); - - NVector& operator-() const; - NVector& operator+(const NVector other) const; - NVector& operator-(const NVector other) const; - NVector& operator*(const NVector other) const; - NVector& operator*(const T factor) const; - NVector& operator/(const T dividend) const; - NVector& operator=(const NVector other); - NVector& operator+=(const NVector other); - T sqnorm() const; - bool operator<(const NVector a) const; - - void print(std::ostream& os) const; -private: - T *m_data; -}; - -template -NVector::NVector() { - m_data = new T[N]; -} - -template -NVector::NVector(T initialValue, T inc) : - NVector() { - T curValue = initialValue; - std::generate(m_data, m_data+N, - [&curValue, inc]() { T cur = curValue; - curValue += inc; - return cur;}); -} - -template -NVector::NVector(const NVector& other) { - m_data = new T[N]; - std::copy(other.m_data, other.m_data+N, m_data); -} - -template -NVector::~NVector() { - if (m_data) delete[](m_data); -} - -template -NVector& NVector::operator-() const { - NVector res; - std::transform(m_data, m_data+N, res.m_data, - [](T a) {return -a;}); - return res; -} - -template -NVector& NVector::operator+(const NVector other) const { - NVector res; - std::transform(m_data, m_data+N, - other.m_data, res.m_data, - [](T a, T b) {return a + b;}); - return res; -} - -template -NVector& NVector::operator-(const NVector other) const { - NVector res; - std::transform(m_data, m_data+N, - other.m_data, res.m_data, - [](T a, T b) {return a - b;}); - return res; -} - -template -NVector& NVector::operator*(const T factor) const { - NVector res; - std::transform(m_data, m_data+N, res.m_dat, - [factor](T a) {return a * factor;}); - return res; -} - -template -NVector& NVector::operator/(const T dividend) const { - NVector res; - std::transform(m_data, m_data+N, res.m_data, - [dividend](T a) {return a / dividend;}); - return res; -} - -template -NVector& NVector::operator=(const NVector other) { - if (m_data) delete[](m_data); - m_data = new T[N]; - std::copy(other.m_data, other.m_data+N, m_data); - return *this; -} - -template -NVector& NVector::operator+=(const NVector other) { - std::transform(m_data, m_data+N, - other.m_data, m_data, - [](T a, T b) {return a + b;}); - return *this; -} - -template -T NVector::sqnorm() const { - return std::inner_product(m_data, m_data + N, m_data, T()); -} - -template -bool NVector::operator<(const NVector other) const { - return this->sqnorm() < other.sqnorm(); -} - -template -void NVector::print(std::ostream& os) const { - std::for_each(m_data, m_data+N, [&os](T a) { os << a << ", ";}); -} - -template -std::ostream& operator<<(std::ostream& os, - const NVector& c) { - os << "("; - c.print(os); - os << ")"; - return os; -} diff --git a/code/move/README.md b/code/move/README.md deleted file mode 100644 index 187ac1a1..00000000 --- a/code/move/README.md +++ /dev/null @@ -1,13 +0,0 @@ - -## Prerequisites - -* be able to use simple templated code - -## Instructions - -* look at the code and run it with callgrind -* understand how inefficient it is -* implement move semantic the easy way in NVector -* run with callgrind and see no improvement -* understand why and fix trymove.cpp -* see efficiency improvements diff --git a/code/move/solution/NVector.sol.hpp b/code/move/solution/NVector.sol.hpp deleted file mode 100644 index 66a459db..00000000 --- a/code/move/solution/NVector.sol.hpp +++ /dev/null @@ -1,151 +0,0 @@ -#include -#include -#include -#include - -template -class NVector { -public: - typedef T BaseType; - - NVector(); - NVector(T initialValue, T inc); - NVector(const NVector &other); - NVector(NVector &&other); - ~NVector(); - - NVector& operator-() const; - NVector& operator+(const NVector& other) const; - NVector& operator-(const NVector& other) const; - NVector& operator*(const NVector& other) const; - NVector& operator*(const T factor) const; - NVector& operator/(const T dividend) const; - NVector& operator=(NVector other); - NVector& operator+=(const NVector& other); - T sqnorm() const; - bool operator<(const NVector& a) const; - - void print(std::ostream& os) const; - template friend void swap(NVector &a, NVector &b); -private: - T *m_data; -}; - - -template -NVector::NVector() { - m_data = new T[N]; -} - -template -NVector::NVector(T initialValue, T inc) : - NVector() { - T curValue = initialValue; - std::generate(m_data, m_data+N, - [&curValue, inc]() { T cur = curValue; - curValue += inc; - return cur;}); -} - -template -NVector::NVector(const NVector& other) { - m_data = new T[N]; - std::copy(other.m_data, other.m_data+N, m_data); -} - -template -NVector::NVector(NVector&& other) : NVector() { - swap(*this, other); -} - -template -NVector::~NVector() { - if (m_data) delete[](m_data); -} - -template -NVector& NVector::operator-() const { - NVector res; - std::transform(m_data, m_data+N, res.m_data, - [](T a) {return -a;}); - return res; -} - -template -NVector& NVector::operator+(const NVector& other) const { - NVector res; - std::transform(m_data, m_data+N, - other.m_data, res.m_data, - [](T a, T b) {return a + b;}); - return res; -} - -template -NVector& NVector::operator-(const NVector& other) const { - NVector res; - std::transform(m_data, m_data+N, - other.m_data, res.m_data, - [](T a, T b) {return a - b;}); - return res; -} - -template -NVector& NVector::operator*(const T factor) const { - NVector res; - std::transform(m_data, m_data+N, res.m_dat, - [factor](T a) {return a * factor;}); - return res; -} - -template -NVector& NVector::operator/(const T dividend) const { - NVector res; - std::transform(m_data, m_data+N, res.m_data, - [dividend](T a) {return a / dividend;}); - return res; -} - -template -NVector& NVector::operator=(NVector other) { - swap(*this, other); - return *this; -} - -template -NVector& NVector::operator+=(const NVector& other) { - std::transform(m_data, m_data+N, - other.m_data, m_data, - [](T a, T b) {return a + b;}); - return *this; -} - -template -T NVector::sqnorm() const { - return std::inner_product(m_data, m_data+N, m_data, T()); -} - -template -bool NVector::operator<(const NVector& other) const { - return this->sqnorm() < other.sqnorm(); -} - -template -void NVector::print(std::ostream& os) const { - std::for_each(m_data, m_data+N, [&os](T a) { os << a << ", ";}); -} - -template -std::ostream& operator<<(std::ostream& os, - const NVector& c) { - os << "("; - c.print(os); - os << ")"; - return os; -} - -template -void swap(NVector &a, NVector &b) { - T* tmp_data = a.m_data; - a.m_data = b.m_data; - b.m_data = tmp_data; -}; diff --git a/code/move/solution/trymove.sol.cpp b/code/move/solution/trymove.sol.cpp deleted file mode 100644 index da68749e..00000000 --- a/code/move/solution/trymove.sol.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include "NVector.sol.hpp" - -template -void swap(std::vector &v, int a, int b) { - T mem = std::move(v[a]); - v[a] = std::move(v[b]); - v[b] = std::move(mem); - // even better - //swap(v[a], v[b]); -} - -template -void randomize(std::vector &v) { - // we randomize via len random inversions - std::size_t len = v.size(); - for (std::size_t i = 0; i < len; i++) { - int a = rand()%len; - int b = rand()%len; - swap(v, a, b); - } -} - -template -std::vector getRandomVector(int len) { - // allocate vectors - std::vector v(len); - // randomize v - randomize(v); - return v; -} - -int main() { - std::vector> v = getRandomVector >(10000); -} diff --git a/code/move/trymove.cpp b/code/move/trymove.cpp deleted file mode 100644 index 0cff87cd..00000000 --- a/code/move/trymove.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include "NVector.hpp" - -template -void swap(std::vector &v, int a, int b) { - T mem = v[a]; - v[a] = v[b]; - v[b] = mem; -} - -template -void randomize(std::vector &v) { - // we randomize via len random inversions - std::size_t len = v.size(); - for (std::size_t i = 0; i < len; i++) { - int a = rand()%len; - int b = rand()%len; - swap(v, a, b); - } -} - -template -std::vector getRandomVector(int len) { - // allocate vectors - std::vector v(len); - // fill and randomize v - for (int i = 0; i < len; i++) v[i] = T(); - randomize(v); - return v; -} - -int main() { - std::vector> v = getRandomVector >(10000); -} diff --git a/code/operators/CMakeLists.txt b/code/operators/CMakeLists.txt deleted file mode 100644 index 9bedb0ee..00000000 --- a/code/operators/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( operators LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( operators "operators.cpp" ) - -# Create the "solution executable". -add_executable( operators.sol EXCLUDE_FROM_ALL "solution/operators.sol.cpp" ) -add_dependencies( solution operators.sol ) diff --git a/code/operators/Makefile b/code/operators/Makefile deleted file mode 100644 index 6766b5fb..00000000 --- a/code/operators/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: operators -solution: operators.sol - -clean: - rm -f *o operators *~ operators.sol - -operators : operators.cpp - ${CXX} -g -std=c++17 -O0 -Wall -Wextra -L. -o $@ $< - -operators.sol : solution/operators.sol.cpp - ${CXX} -g -std=c++17 -O0 -Wall -Wextra -L. -o $@ $< diff --git a/code/operators/README.md b/code/operators/README.md deleted file mode 100644 index 7d70d91c..00000000 --- a/code/operators/README.md +++ /dev/null @@ -1,5 +0,0 @@ - -## Instructions - -* inspect main and complete the implementation of class Fraction step by step -* you can comment out parts of main to test in between diff --git a/code/operators/operators.cpp b/code/operators/operators.cpp deleted file mode 100644 index 177e20da..00000000 --- a/code/operators/operators.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include - -class Fraction { - // TODO: constructors and operators -}; - -// TODO:operators - - -void printAndCheck(const std::string & what, const Fraction & result, const Fraction & expected) { - const bool passed = result == expected; - std::cout << std::left << std::setw(40) << what << ": " << (passed ? "PASS" : "** FAIL **") << " " << result << "\n"; -} -void printAndCheck(const std::string & what, bool result, bool expected) { - const bool passed = result == expected; - std::cout << std::left << std::setw(40) << what << ": " << (passed ? "PASS" : "** FAIL **") << " " << result << "\n"; -} - -int main() { - // create a fraction with values 3 (which is 3/1) and 1/3 - const Fraction three{3}; - const Fraction athird{1, 3}; - - // print the fractions - std::cout << "Three: " << three << '\n'; - std::cout << "One third: " << athird << '\n'; - - // multiply fraction with an int - // the printAndCheck function requires operator<< and operator==: - printAndCheck("One third times two", athird * 2, Fraction{2, 3}); - // ensure symmetry - printAndCheck("One third times two", 2 * athird, Fraction{2, 3}); - - // multiply two fractions - printAndCheck("Three times one third", three * athird, Fraction{1, 1}); - // normalize the fraction after multiplication so the above statement - // prints 1/1 instead of e.g. 3/3 - // you might need to compute the greatest common divisor, for which you can - // use the function std::gcd(a, b) from the header - printAndCheck("Three times one third", 3 * athird, Fraction{1, 1}); - - // multiply in place - Fraction f = athird; - f *= 2; - printAndCheck("One third times two", f, Fraction{2, 3}); - - f = athird; - f *= athird; - printAndCheck("One third times one third", f, Fraction{1, 9}); - - f = athird; - f *= f *= f; - printAndCheck("One third times itself twice", f, Fraction{1, 81}); - - // you might have some redundancy between the implementation of operator* and - // operator*=. Can you refactor your code and implement operator* in terms of - // operator*=? - - // add an int to a fraction - printAndCheck("One third plus 2", athird + 2, Fraction{7, 3}); - // ensure symmetry - printAndCheck("2 plus one third", 2 + athird, Fraction{7, 3}); - - // add two fractions - printAndCheck("One third plus two sixth", athird + Fraction{2, 6}, Fraction{2, 3}); - // normalize the fraction after addition too so the above statement - // prints 2/3 instead of 12/18 - // make sure the normalization between addition and multiplication is not - // duplicated, e.g. by putting it into a separate method - - // add in place - f = athird; - f += f += 1; - printAndCheck("One third plus one and added to itself", f, Fraction{8, 3}); - // again, try to refactor and implement operator+ in terms of operator+= - - std::cout << std::boolalpha; // print bools as 'true' or 'false' from now on - - // more equality comparisons - printAndCheck("One third == one third", (athird == Fraction{1, 3}), true); - printAndCheck("One third != one forth", (athird != Fraction{1, 4}), true); - printAndCheck("One third == two sixth", (athird == Fraction{2, 6}), true); - printAndCheck("One third != three sixth", (athird != Fraction{3, 6}), true); - // try to implement operator!= in terms of operator== - - // more comparisons - const Fraction afourth{1, 4}; - printAndCheck("athird < athird", (athird < athird), false); - printAndCheck("afourth < athird", (afourth < athird), true); - printAndCheck("athird <= athird", (athird <= athird), true); - printAndCheck("athird <= afourth", (athird <= afourth), false); - printAndCheck("athird > athird", (athird > athird), false); - printAndCheck("afourth > athird", (afourth > athird), false); - printAndCheck("athird >= athird", (athird >= athird), true); - printAndCheck("athird >= afourth", (athird >= afourth), true); - // the operators <=, >= and > can typically be implemented just in terms of - // operator<. Can you do this as well? ;) - - // take aways on operators: - // * we can very often implement an arithemtic operator@ in terms of - // operator@= - // * it usually suffices to implement operator< and operator== and derive the - // other relational operators from them. C++20 will do part of this automatically. -} diff --git a/code/operators/solution/operators.sol.cpp b/code/operators/solution/operators.sol.cpp deleted file mode 100644 index 48d1b08d..00000000 --- a/code/operators/solution/operators.sol.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include -#include - -class Fraction { - public: - explicit Fraction(int i) : m_num(i), m_denom(1) {} - Fraction(int num, int denom) : m_num(num), m_denom(denom) {} - - int num() const { return m_num; } - int denom() const { return m_denom; } - - void normalize() { - const int gcd = std::gcd(m_num, m_denom); - m_num /= gcd; - m_denom /= gcd; - } - - Fraction& operator*=(int i) { - m_num *= i; - normalize(); - return *this; - } - - Fraction& operator*=(Fraction f) { - m_num *= f.num(); - m_denom *= f.denom(); - normalize(); - return *this; - } - - Fraction& operator+=(int i) { - m_num += i * m_denom; - return *this; - } - - Fraction& operator+=(Fraction f) { - m_num *= f.denom(); - m_num += f.num() * m_denom; - m_denom *= f.denom(); - normalize(); - return *this; - } - - private: - int m_num, m_denom; -}; - -std::ostream& operator<<(std::ostream& os, Fraction r) { - os << r.num() << "/" << r.denom(); - return os; -} - -Fraction operator*(Fraction r, int i) { return r *= i; } - -Fraction operator*(int i, Fraction r) { return r * i; } - -Fraction operator*(Fraction a, Fraction b) { return a *= b; } - -Fraction operator+(Fraction r, int i) { return r += i; } - -Fraction operator+(int i, Fraction r) { return r + i; } - -Fraction operator+(Fraction a, Fraction b) { return a += b; } - -bool operator==(Fraction a, Fraction b) { - a.normalize(); - b.normalize(); - return a.num() == b.num() && a.denom() == b.denom(); -} - -bool operator<(Fraction a, Fraction b) { - return a.num() * b.denom() < b.num() * a.denom(); -} - -bool operator!=(Fraction a, Fraction b) { return !(a == b); } - -bool operator>(Fraction a, Fraction b) { return b < a; } - -bool operator<=(Fraction a, Fraction b) { return !(a > b); } - -bool operator>=(Fraction a, Fraction b) { return !(a < b); } - - -void printAndCheck(const std::string & what, const Fraction & result, const Fraction & expected) { - const bool passed = result == expected; - std::cout << std::left << std::setw(40) << what << ": " << (passed ? "PASS" : "** FAIL **") << " " << result << "\n"; -} -void printAndCheck(const std::string & what, bool result, bool expected) { - const bool passed = result == expected; - std::cout << std::left << std::setw(40) << what << ": " << (passed ? "PASS" : "** FAIL **") << " " << result << "\n"; -} - -int main() { - // create a fraction with values 3 (which is 3/1) and 1/3 - const Fraction three{3}; - const Fraction athird{1, 3}; - - // print the fractions - std::cout << "Three: " << three << '\n'; - std::cout << "One third: " << athird << '\n'; - - // multiply fraction with an int - // the printAndCheck function requires operator<< and operator==: - printAndCheck("One third times two", athird * 2, Fraction{2, 3}); - // ensure symmetry - printAndCheck("One third times two", 2 * athird, Fraction{2, 3}); - - // multiply two fractions - printAndCheck("Three times one third", three * athird, Fraction{1, 1}); - // normalize the fraction after multiplication so the above statement - // prints 1/1 instead of e.g. 3/3 - // you might need to compute the greatest common divisor, for which you can - // use the function std::gcd(a, b) from the header - printAndCheck("Three times one third", 3 * athird, Fraction{1, 1}); - - // multiply in place - Fraction f = athird; - f *= 2; - printAndCheck("One third times two", f, Fraction{2, 3}); - - f = athird; - f *= athird; - printAndCheck("One third times one third", f, Fraction{1, 9}); - - f = athird; - f *= f *= f; - printAndCheck("One third times itself twice", f, Fraction{1, 81}); - - // you might have some redundancy between the implementation of operator* and - // operator*=. Can you refactor your code and implement operator* in terms of - // operator*=? - - // add an int to a fraction - printAndCheck("One third plus 2", athird + 2, Fraction{7, 3}); - // ensure symmetry - printAndCheck("2 plus one third", 2 + athird, Fraction{7, 3}); - - // add two fractions - printAndCheck("One third plus two sixth", athird + Fraction{2, 6}, Fraction{2, 3}); - // normalize the fraction after addition too so the above statement - // prints 2/3 instead of 12/18 - // make sure the normalization between addition and multiplication is not - // duplicated, e.g. by putting it into a separate method - - // add in place - f = athird; - f += f += 1; - printAndCheck("One third plus one and added to itself", f, Fraction{8, 3}); - // again, try to refactor and implement operator+ in terms of operator+= - - std::cout << std::boolalpha; // print bools as 'true' or 'false' from now on - - // more equality comparisons - printAndCheck("One third == one third", (athird == Fraction{1, 3}), true); - printAndCheck("One third != one forth", (athird != Fraction{1, 4}), true); - printAndCheck("One third == two sixth", (athird == Fraction{2, 6}), true); - printAndCheck("One third != three sixth", (athird != Fraction{3, 6}), true); - // try to implement operator!= in terms of operator== - - // more comparisons - const Fraction afourth{1, 4}; - printAndCheck("athird < athird", (athird < athird), false); - printAndCheck("afourth < athird", (afourth < athird), true); - printAndCheck("athird <= athird", (athird <= athird), true); - printAndCheck("athird <= afourth", (athird <= afourth), false); - printAndCheck("athird > athird", (athird > athird), false); - printAndCheck("afourth > athird", (afourth > athird), false); - printAndCheck("athird >= athird", (athird >= athird), true); - printAndCheck("athird >= afourth", (athird >= afourth), true); - // the operators <=, >= and > can typically be implemented just in terms of - // operator<. Can you do this as well? ;) - - // take aways on operators: - // * we can very often implement an arithemtic operator@ in terms of - // operator@= - // * it usually suffices to implement operator< and operator== and derive the - // other relational operators from them. C++20 will do part of this automatically. -} diff --git a/code/polymorphism/CMakeLists.txt b/code/polymorphism/CMakeLists.txt deleted file mode 100644 index cf9963a6..00000000 --- a/code/polymorphism/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( polymorhism LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's library. -add_library( polymorphismPoly "Polygons.hpp" "Polygons.cpp" ) -target_include_directories( polymorphismPoly PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" ) -set_target_properties( polymorphismPoly PROPERTIES OUTPUT_NAME "poly" ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) - target_compile_definitions( polymorphismPoly PRIVATE _USE_MATH_DEFINES ) -endif() - -# Create the user's executable. -add_executable( trypoly "trypoly.cpp" ) -target_link_libraries( trypoly PRIVATE polymorphismPoly ) - -# Create the "solution executable". -add_executable( trypoly.sol EXCLUDE_FROM_ALL "solution/trypoly.sol.cpp" ) -target_link_libraries( trypoly.sol PRIVATE polymorphismPoly ) -add_dependencies( solution trypoly.sol ) diff --git a/code/polymorphism/Makefile b/code/polymorphism/Makefile deleted file mode 100644 index 41af0f2e..00000000 --- a/code/polymorphism/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -all: trypoly -solution: trypoly.sol - -clean: - rm -f *o *so trypoly *~ trypoly.sol - -libpoly.so: Polygons.cpp Polygons.hpp - $(CXX) -std=c++11 -Wsuggest-override -g -Wall -Wextra -shared -fPIC -o $@ $< - -trypoly : trypoly.cpp libpoly.so - $(CXX) -std=c++11 -Wsuggest-override -g -Wall -Wextra -o $@ $^ - -trypoly.sol : solution/trypoly.sol.cpp libpoly.so - $(CXX) -std=c++11 -g -Wall -Wextra -I. -o $@ $^ diff --git a/code/polymorphism/Polygons.cpp b/code/polymorphism/Polygons.cpp deleted file mode 100644 index 156fb402..00000000 --- a/code/polymorphism/Polygons.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "Polygons.hpp" -#include -#include - -Polygon::Polygon(int n, float radius) : m_nbSides(n), m_radius(radius) {}; - -float Polygon::computePerimeter() { - std::cout << "Generic computePerimeter for polygons\n"; - return 2*m_nbSides*std::sin(static_cast(M_PI)/m_nbSides)*m_radius; -} - -Pentagon::Pentagon(float radius) : Polygon(5, radius) {} - -Hexagon::Hexagon(float radius) : Polygon(6, radius) {} - -float Hexagon::computePerimeter() { - std::cout << "Optimized computePerimeter for hexagons\n"; - return 6 * m_radius; -} diff --git a/code/polymorphism/Polygons.hpp b/code/polymorphism/Polygons.hpp deleted file mode 100644 index 00d8bdfb..00000000 --- a/code/polymorphism/Polygons.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -class Polygon { -public: - Polygon(int n, float radius); - float computePerimeter(); -protected: - int m_nbSides; - float m_radius; -}; - -class Pentagon : public Polygon { -public: - Pentagon(float radius); -}; - -class Hexagon : public Polygon { -public: - Hexagon(float radius); - // 6*radius is easier than generic case - float computePerimeter(); -}; diff --git a/code/polymorphism/README.md b/code/polymorphism/README.md deleted file mode 100644 index 4adbcef0..00000000 --- a/code/polymorphism/README.md +++ /dev/null @@ -1,32 +0,0 @@ -## Instructions for the "polymorphism" exercise - -Step 1 -* look at the code -* open `trypoly.cpp` -* create a Pentagon, call its `perimeter` method -* Compile via `make`, execute via `./trypoly` - * you may have to add current directory to your LD_LIBRARY_PATH : -```shell - export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. -``` -* create an Hexagon, call its `perimeter` method -* recompile and check what happens - -Step 2 -* create an Hexagon, call its parent’s `perimeter` method -* recompile and check again -* retry with virtual methods - - -## Instructions for the "compiler chain" exercise - -* preprocess `Polygons.cpp` (`cpp` or `gcc -E -o output`) -* compile `Polygons.o` and `trypoly.o` (`g++ -c -o output`) -* use `nm` to check symbols in '.o' files -* look at the `Makefile` -* try `make clean; make` -* see linking stage using `g++ -v` - * just add a -v in the Makefile command for trypoly - * run make clean; make - * look at the collect 2 line, from the end up to '-o trypoly' -* see library dependencies with `ldd` diff --git a/code/polymorphism/solution/trypoly.sol.cpp b/code/polymorphism/solution/trypoly.sol.cpp deleted file mode 100644 index e598bee2..00000000 --- a/code/polymorphism/solution/trypoly.sol.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "Polygons.hpp" -#include - -int main() { - // create a Pentagon, call its perimeter method - Pentagon penta{1.0}; - std::cout << "Penta : perimeter = " << penta.computePerimeter() << "\n\n"; - - // create a Hexagon, call its perimeter method - Hexagon hexa{1.0}; - std::cout << "Hexa : perimeter = " << hexa.computePerimeter() << "\n\n"; - - // create a Hexagon, call the perimeter method through a reference to Polygon - Hexagon hexa2{1.0}; - Polygon &poly = hexa2; - std::cout << "Hexa : perimeter = " << hexa2.computePerimeter() << '\n' - << "Hexa as Poly : perimeter = " << poly.computePerimeter() << '\n'; - - // retry virtual method -} diff --git a/code/polymorphism/trypoly.cpp b/code/polymorphism/trypoly.cpp deleted file mode 100644 index 97e200df..00000000 --- a/code/polymorphism/trypoly.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "Polygons.hpp" -#include - -int main() { - // create a Pentagon, call its perimeter method - - - // create a Hexagon, call its perimeter method - - - // create a Hexagon, call the perimeter method through a reference to Polygon - - - // retry virtual method - -} diff --git a/code/python/CMakeLists.txt b/code/python/CMakeLists.txt deleted file mode 100644 index 0c596556..00000000 --- a/code/python/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.12 ) -project( python LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) - -# Find Python for the build. -find_package( Python3 COMPONENTS Development REQUIRED ) - -# Build the C++ shared library. -add_library( mandel SHARED Complex.hpp mandel.hpp mandel.cpp ) - -# Build a "C wrapper" around the C++ shared library. -add_library( mandelc SHARED mandel_cwrapper.hpp mandel_cwrapper.cpp ) -target_link_libraries( mandelc PUBLIC mandel ) - -# Build the Python module around the C++ shared library. -add_library( mandelm SHARED mandel_module.cpp ) -target_link_libraries( mandelm PRIVATE Python3::Python mandel ) -set_target_properties( mandelm PROPERTIES - PREFIX "" - OUTPUT_NAME "mandel" ) diff --git a/code/python/Complex.hpp b/code/python/Complex.hpp deleted file mode 100644 index ddbcf012..00000000 --- a/code/python/Complex.hpp +++ /dev/null @@ -1,69 +0,0 @@ -template -class Complex_t { -public: - Complex_t(T r, T i); - Complex_t(T r); - Complex_t(); - - T real() const {return m_r;}; - T imaginary() const {return m_i;}; - - Complex_t operator+(const Complex_t& other) const; - Complex_t operator-(const Complex_t& other) const; - Complex_t operator*(const Complex_t& other) const; - Complex_t operator*(const T factor) const; - Complex_t operator/(const T dividend) const; - Complex_t& operator+=(const Complex_t& other); - bool operator<(const Complex_t& a) const; -private: - T m_r, m_i; -}; - -typedef Complex_t<> Complex; - -template -Complex_t::Complex_t() {} - -template -Complex_t::Complex_t(T r) : m_r(r), m_i(0) {} - -template -Complex_t::Complex_t(T r, T i) : m_r(r), m_i(i) {} - -template -Complex_t Complex_t::operator+(const Complex_t& other) const { - return Complex_t(m_r + other.m_r, m_i + other.m_i); -} - -template -Complex_t Complex_t::operator-(const Complex_t& other) const { - return Complex_t(m_r - other.m_r, m_i - other.m_i); -} - -template -Complex_t Complex_t::operator*(const Complex_t& other) const { - return Complex_t(m_r*other.m_r - m_i*other.m_i, - m_r*other.m_i + m_i*other.m_r); -} - -template -Complex_t Complex_t::operator*(const T factor) const { - return Complex_t(m_r*factor, m_i*factor); -} - -template -Complex_t Complex_t::operator/(const T dividend) const { - return Complex_t(m_r/dividend, m_i/dividend); -} - -template -Complex_t& Complex_t::operator+=(const Complex_t& other) { - m_r += other.m_r; - m_i += other.m_i; - return *this; -} - -template -bool Complex_t::operator<(const Complex_t& other) const { - return (m_r*m_r+m_i*m_i) < (other.m_r*other.m_r+other.m_i*other.m_i); -} diff --git a/code/python/Makefile b/code/python/Makefile deleted file mode 100644 index 478cf27b..00000000 --- a/code/python/Makefile +++ /dev/null @@ -1,21 +0,0 @@ - -all: mandel.so libmandelc.so -solution: mandel.so libmandelc.so - -mandel.so:mandel_module.o libmandel.so - ${CXX} -shared -Wl,-undefined,dynamic_lookup $^ -o $@ `python3-config --ldflags` - -mandel_module.o:mandel_module.cpp - ${CXX} -pthread -O3 -Wall -std=c++14 -fPIC -I. `python3-config --cflags` -c $< -o $@ - -libmandelc.so:mandel_cwrapper.o libmandel.so - ${CXX} -shared $^ -o $@ - -mandel_cwrapper.o:mandel_cwrapper.cpp - ${CXX} -O3 -Wall -std=c++14 -fPIC -c $< -o $@ - -libmandel.so:mandel.cpp Complex.hpp - ${CXX} -shared -O3 -Wall -std=c++14 -fPIC $< -o $@ - -clean: - rm -rf *.o *.so *~ *pyc *pyo *svg diff --git a/code/python/README.md b/code/python/README.md deleted file mode 100644 index b921cebb..00000000 --- a/code/python/README.md +++ /dev/null @@ -1,11 +0,0 @@ - -## Instructions - -* look at the original python code `mandel.py` -* time it (`time python3 mandel.py`) -* look at the code in `mandel.hpp/cpp` -* look at the python module mandel `mandel_module.cpp` -* compile and modify `mandel.py` to use it -* see the gain in time -* look at the C wrapper in `mandel_cwrapper.cpp` -* modify `mandel.py` to use `libmandelc` directly with ctypes diff --git a/code/python/mandel.cpp b/code/python/mandel.cpp deleted file mode 100644 index 9b429ace..00000000 --- a/code/python/mandel.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "mandel.hpp" - -int mandel(const Complex &a) { - Complex z = 0; - for (int n = 1; n < 100; n++) { - z = z*z + a; - if (Complex(2) < z) { - return n; - } - } - return -1; -} diff --git a/code/python/mandel.hpp b/code/python/mandel.hpp deleted file mode 100644 index f7cf9962..00000000 --- a/code/python/mandel.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "Complex.hpp" - -/** - * computes number of iterations of the mandelbrot - * formula you need before reaching a norm > 2 - * returned value is -1 if 100 iterations are reached - * without reaching it - */ -int mandel(const Complex &a); diff --git a/code/python/mandel.py b/code/python/mandel.py deleted file mode 100644 index cf42edc2..00000000 --- a/code/python/mandel.py +++ /dev/null @@ -1,25 +0,0 @@ -from pylab import * -from numpy import NaN - -def m(a): - z = 0 - for n in range(1, 100): - z = z**2 + a - if abs(z) > 2: - return n - return NaN - -X = arange(-2, .5, .002) -Y = arange(-1, 1, .002) -Z = zeros((len(Y), len(X))) - -for iy, y in enumerate(Y): - print (iy, "of", len(Y)) - for ix, x in enumerate(X): - Z[iy,ix] = m(x + 1j * y) - -imshow(Z, cmap = plt.cm.prism, interpolation = 'none', extent = (X.min(), X.max(), Y.min(), Y.max())) -xlabel("Re(c)") -ylabel("Im(c)") -savefig("mandelbrot_python.svg") -show() diff --git a/code/python/mandel_cwrapper.cpp b/code/python/mandel_cwrapper.cpp deleted file mode 100644 index 6f481eb0..00000000 --- a/code/python/mandel_cwrapper.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "mandel_cwrapper.hpp" - -extern "C" { - - int mandel(float r, float i) { - return mandel(Complex(r, i)); - } - -} diff --git a/code/python/mandel_cwrapper.hpp b/code/python/mandel_cwrapper.hpp deleted file mode 100644 index 5e3bf388..00000000 --- a/code/python/mandel_cwrapper.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "mandel.hpp" - -extern "C" { - int mandel(float r, float i); -} diff --git a/code/python/mandel_module.cpp b/code/python/mandel_module.cpp deleted file mode 100644 index 9a87ffbf..00000000 --- a/code/python/mandel_module.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include "mandel.hpp" - -static PyObject * mandel_wrapper(PyObject * self, - PyObject * args) { - // Parse Input - float r, i; - if (!PyArg_ParseTuple(args, "ff", &r, &i)) return NULL; - // Call C function - int result = mandel(Complex(r, i)); - // Build returned objects - return PyLong_FromLong(result); -} - -static PyMethodDef mandelMethods[] = { - {"mandel", mandel_wrapper, METH_VARARGS, "computes nb of iterations for mandelbrot set for a given complex number"}, - {NULL, NULL, 0, NULL} -}; - -static struct PyModuleDef mandelModule = { - PyModuleDef_HEAD_INIT, - "mandel", /* name of module */ - NULL, /* module documentation */ - -1, /* size of per-interpreter state of the module, - or -1 if the module keeps state in global variables. */ - mandelMethods -}; - -PyMODINIT_FUNC PyInit_mandel(void) { - return PyModule_Create(&mandelModule); -} diff --git a/code/python/solution/mandel.sol.py b/code/python/solution/mandel.sol.py deleted file mode 100644 index bb442589..00000000 --- a/code/python/solution/mandel.sol.py +++ /dev/null @@ -1,22 +0,0 @@ -from pylab import * -from numpy import NaN -from mandel import mandel - -X = arange(-2, .5, .002) -Y = arange(-1, 1, .002) -Z = zeros((len(Y), len(X))) - -for iy, y in enumerate(Y): - print (iy, "of", len(Y)) - for ix, x in enumerate(X): - v = mandel(x, y) - if v >= 0 : - Z[iy,ix] = v - else: - Z[iy,ix] = NaN - -imshow(Z, cmap = plt.cm.prism, interpolation = 'none', extent = (X.min(), X.max(), Y.min(), Y.max())) -xlabel("Re(c)") -ylabel("Im(c)") -savefig("mandelbrot_python.svg") -show() diff --git a/code/python/solution/mandel.solctype.py b/code/python/solution/mandel.solctype.py deleted file mode 100644 index da6f9313..00000000 --- a/code/python/solution/mandel.solctype.py +++ /dev/null @@ -1,25 +0,0 @@ -from pylab import * -from numpy import NaN -from ctypes import * - -# interface with C library -libmandel = CDLL('libmandelc.so') - -X = arange(-2, .5, .002) -Y = arange(-1, 1, .002) -Z = zeros((len(Y), len(X))) - -for iy, y in enumerate(Y): - print (iy, "of", len(Y)) - for ix, x in enumerate(X): - v = libmandel.mandel(c_float(x), c_float(y)) - if v >= 0 : - Z[iy,ix] = v - else: - Z[iy,ix] = NaN - -imshow(Z, cmap = plt.cm.prism, interpolation = 'none', extent = (X.min(), X.max(), Y.min(), Y.max())) -xlabel("Re(c)") -ylabel("Im(c)") -savefig("mandelbrot_python.svg") -show() diff --git a/code/race/CMakeLists.txt b/code/race/CMakeLists.txt deleted file mode 100644 index 3a35ffe6..00000000 --- a/code/race/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( race LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Figure out how to use the platform's thread capabilities. -find_package( Threads REQUIRED ) - -# Create the user's executable. -add_executable( racing "racing.cpp" ) -target_link_libraries( racing PRIVATE Threads::Threads ) - -# Create the "solution executable". -add_executable( racing.sol EXCLUDE_FROM_ALL "solution/racing.sol.cpp" ) -target_link_libraries( racing.sol PRIVATE Threads::Threads ) -add_dependencies( solution racing.sol ) diff --git a/code/race/Makefile b/code/race/Makefile deleted file mode 100644 index f43769b5..00000000 --- a/code/race/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -PROGRAM_NAME=racing - -all: $(PROGRAM_NAME) -solution: $(PROGRAM_NAME).sol - - -clean: - rm -f *o $(PROGRAM_NAME) *~ core $(PROGRAM_NAME).sol - -$(PROGRAM_NAME) : $(PROGRAM_NAME).cpp - ${CXX} -g -std=c++17 -O2 -pthread -Wall -Wextra -L. -o $@ $< - -$(PROGRAM_NAME).sol : solution/$(PROGRAM_NAME).sol.cpp - ${CXX} -g -std=c++17 -O2 -pthread -Wall -Wextra -L. -o $@ $< diff --git a/code/race/README.md b/code/race/README.md deleted file mode 100644 index 181331df..00000000 --- a/code/race/README.md +++ /dev/null @@ -1,6 +0,0 @@ - -## Instructions - -* compile, run many times, see what happens -* use a mutex to fix the issue -* see the difference in execution time diff --git a/code/race/racing.cpp b/code/race/racing.cpp deleted file mode 100644 index 3d75b896..00000000 --- a/code/race/racing.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -/* - * This program tries to increment an integer 200 times in two threads. - * Check whether the result is indeed always 200. - */ - -int main() { - int nError = 0; - - for (int j = 0; j < 1000; j++) { - int a = 0; - - // Increment the variable a 100 times: - auto inc100 = [&a](){ - for (int i = 0; i < 100; ++i) { - a++; - } - }; - - // Run with two threads - std::thread t1(inc100); - std::thread t2(inc100); - for (auto t : {&t1,&t2}) t->join(); - - // Check - if (a != 200) { - std::cout << "Race: " << a << ' '; - nError++; - } else { - std::cout << '.'; - } - } - std::cout << '\n'; - - return nError; -} diff --git a/code/race/solution/racing.sol.cpp b/code/race/solution/racing.sol.cpp deleted file mode 100644 index 92e4306b..00000000 --- a/code/race/solution/racing.sol.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include - -/* - * This program tries to increment an integer 200 times in two threads. - * We fix the race condition by locking a mutex before each increment. - */ - -int main() { - int nError = 0; - - for (int j = 0; j < 1000; j++) { - int a = 0; - std::mutex aMutex; - - // Increment the variable a 100 times: - auto inc100 = [&a,&aMutex](){ - for (int i = 0; i < 100; ++i) { - std::scoped_lock lock{aMutex}; - a++; - } - }; - - // Run with two threads - std::thread t1(inc100); - std::thread t2(inc100); - for (auto t : {&t1,&t2}) t->join(); - - // Check - if (a != 200) { - std::cout << "Race: " << a << ' '; - nError++; - } else { - std::cout << '.'; - } - } - std::cout << '\n'; - - return nError; -} diff --git a/code/smartPointers/CMakeLists.txt b/code/smartPointers/CMakeLists.txt deleted file mode 100644 index ff97cfc7..00000000 --- a/code/smartPointers/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( smartPointers LANGUAGES CXX ) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( smartPointers "smartPointers.cpp" ) - -# Create the "solution executable". -add_executable( smartPointers.sol EXCLUDE_FROM_ALL "solution/smartPointers.sol.cpp" ) -add_dependencies( solution smartPointers.sol ) diff --git a/code/smartPointers/Makefile b/code/smartPointers/Makefile deleted file mode 100644 index 18867906..00000000 --- a/code/smartPointers/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: smartPointers -solution: smartPointers.sol - -clean: - rm -f *o *so smartPointers *~ smartPointers.sol - -% : %.cpp - $(CXX) -g -std=c++17 -Wall -Wextra -o $@ $< - -%.sol : solution/%.sol.cpp - $(CXX) -g -std=c++17 -Wall -Wextra -o $@ $< diff --git a/code/smartPointers/README.md b/code/smartPointers/README.md deleted file mode 100644 index a5b34994..00000000 --- a/code/smartPointers/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Writing leak-free C++. - -Here we have four code snippets that will benefit from using smart pointers. By replacing every explicit `new` with `make_unique` or `make_shared`, (alternatively by explicitly instantiating smart pointers) we will fix memory leaks, and make most cleanup code unnecessary. - -## Prerequisites - -* Which pointer is used for what? - * Raw pointer - * [`std::unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr) - * [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr) -* C++-14 for `std::make_unique` / `std::make_shared`. Understand what these functions do. -* Helpful: Move semantics for `problem2()`, but can do without. - -## Instructions - -* Compile and run the program. It doesn't generate any output. -* Run with valgrind to check for leaks -``` -valgrind --leak-check=full --track-origins=yes ./smartPointers -``` -* Go through `problem1()` to `problem3()` and fix the leaks using smart pointers. -* `problem4()` is the most difficult. Skip if not enough time. diff --git a/code/smartPointers/smartPointers.cpp b/code/smartPointers/smartPointers.cpp deleted file mode 100644 index 439ef02e..00000000 --- a/code/smartPointers/smartPointers.cpp +++ /dev/null @@ -1,316 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - - -/* - * Please fix all memory leaks / ownership problems using smart pointers. - * (Verify by running the program with valgrind!) - * - * Remember that: - * - The ownership of data is expressed using unique_ptr. - * - "Observer" access without ownership is expressed using raw pointers. - * - Shared access to data is expressed using shared_ptr. - */ - - -/* -------------------------------------------------------------------------------------------- - * 1: Always use smart pointers when you use new. - * - * A frequent source of leaks is a function that terminates earlier than the programmer thought. - * - * - Fix the leak using a smart pointer. - * - The arguments of sumEntries() don't need to change, as it has only read access. - * -------------------------------------------------------------------------------------------- - */ - -// Declare a function to do something with the data. No need to change it. -double sumEntries(const double* data, std::size_t size) { - if (size > 200) - throw std::invalid_argument("I only want to sum 200 numbers or less."); - - return std::reduce(data, data + size, 0); -} - -// Often, data are owned by one entity, and only used by others. Fix the leak. -void doStuffWithData() { - constexpr std::size_t arraySize = 10000; - auto data = new double[arraySize]; - - sumEntries(data, arraySize); - - delete[] data; -} - - -void problem1() { - try { - doStuffWithData(); - } catch (std::exception& e) { - std::cerr << "problem1(): Do stuff with data terminated with exception:\n" << e.what() - << "\n We may have a memory leak now.\n"; - } -} - - - -/* -------------------------------------------------------------------------------------------- - * 2: Storing unique_ptr in collections. - * - * Often, one has to store pointers to objects in collections. Fix the memory leaks using unique_ptr. - * - * Notes: - * - Factory functions should return objects either directly or using smart pointers. - * This is good practice, because it clearly shows who owns an object. Fix the return type of the factory function. - * - The vector should own the objects, so try to store them using smart pointers. - * - Since the visitor function doesn't accept smart pointers, find a solution to pass the objects. - * Note that this works without shared_ptr! - * -------------------------------------------------------------------------------------------- - */ - -// This is a large object. We maybe shouldn't copy it, so using a pointer is advisable to pass it around. -struct LargeObject { - double fData[100000]; -}; - -// A factory function to create large objects. -LargeObject* createLargeObject() { - auto object = new LargeObject(); - // Do more setting up of object here - // ... - - return object; -} - -// A function to do something with the objects. -// Note that since we don't own the object, we don't need a smart pointer as argument. -void visitLargeObject(LargeObject* object) { - object->fData[0] = 1.; -} - -void problem2() { - std::vector largeObjects; - - for (unsigned int i=0; i < 10; ++i) { - auto newObj = createLargeObject(); - largeObjects.push_back(newObj); - } - - for (const auto& obj : largeObjects) { - visitLargeObject(obj); - } -} - - - -/* -------------------------------------------------------------------------------------------- - * 3: Shared ownership. - * - * Most of the time, ownership can be solved by having one owner (with unique_ptr) and one or - * more observers. Sometimes, we need to truly share data, though. - * - * Here is an example of a completely messed up ownership model. It leaks about 1/10 of the times - * it is invoked. - * - Verify this by running it in a loop using a command like: - * while true; do valgrind --leak-check=full --track-origins=yes ./smartPointers 2>&1 | grep -B 5 -A 5 problem3 && exit 1; done - * - Fix the ownership model using shared_ptr! - * - Convert the vectors to holding shared_ptr. - * - Fix the arguments of the functions. - * - Speed optimisation: - * Make sure that you don't create & destroy a shared_ptr in the for loop in problem3() and when calling processElement(). - * -------------------------------------------------------------------------------------------- - */ - -// This removes the element in the middle of the vector. -void removeMiddle(std::vector& collection) { - auto middlePosition = collection.begin() + collection.size()/2; - - // Must not delete element when erasing from collection, because it's also in the copy ... - collection.erase(middlePosition, middlePosition+1); -} - -// This removes a random element. -// Note that this leaks if the element happens to be the same -// that's removed above ... -void removeRandom(std::vector& collection) { - auto pos = collection.begin() + time(nullptr) % collection.size(); - - collection.erase(pos, pos+1); -} - -// Do something with an element. -// Just a dummy function, for you to figure out how to pass an object -// managed by a shared_ptr to a function. -void processElement(const LargeObject* /*element*/) { } - - -// We have pointers to objects in two different collections. We work a bit with -// the collections, and then we try to terminate leak free. Without a shared ownership -// model, this becomes a mess. -void problem3() { - // Let's generate a vector with 10 pointers to LargeObject - std::vector objVector(10); - for (auto& ptr : objVector) { - ptr = new LargeObject(); - } - - // Let's copy it - std::vector objVectorCopy(objVector); - - - // Now we work with the objects: - removeMiddle(objVector); - removeRandom(objVectorCopy); - // ... - // ... - for (auto elm : objVector) { - processElement(elm); - } - - - // Now try to figure out what has to be deleted. It's a mess ... - // Fix using shared_ptr, so the following code becomes unnecessary: - for (auto objPtr : objVector) { - delete objPtr; - } - - for (auto objPtr : objVectorCopy) { - // If the element is in the original collection, it was already deleted. - if (std::find(objVector.begin(), objVector.end(), objPtr) == objVector.end()) { - delete objPtr; - } - } -} - - - -/* -------------------------------------------------------------------------------------------- - * 4: Smart pointers as class members. - * - * Class members that are pointers can quickly become a problem. - * Firstly, if only raw pointers are used, the intended ownership is unclear. - * Secondly, it's easy to overlook that a member has to be deleted. - * Thirdly, pointer members usually require you to implement copy or move constructors and assignment - * operators (--> rule of 3, rule of 5). - * Since C++-11, one can solve a few of those problems using smart pointers. - * - * 4.1: - * The class "Owner" owns some data, but it is broken. If you copy it like in - * problem4_1(), you have two pointers pointing to the same data, but both think - * that they own the data. - * - Comment in problem4_1() in main(). - * - Verify that it crashes. Try running valgrind ./smartPointers, it should give you some hints as to - * what's happening. - * - Fix the Owner class by using a shared_ptr for its _largeObj, which we can copy as much as we want. - * - Note: Now you even don't need a destructor. - * - * 4.2: **BONUS** - * We go beyond the scope of the lecture now, and use a weak pointer. - * These are used to observe a shared_ptr, but unlike the shared_ptr, they don't prevent the deletion - * of the underlying object if all shared_ptr go out of scope. - * To *use* the observed data, one has to create a shared_ptr from the weak_ptr, so that it is guaranteed that - * the underlying object is alive. - * - * In our case, the observer class wants to observe the data of the owner, but it doesn't need to own it. - * To do this, we use a weak pointer. - * - * Tasks: - * - Comment in problem4_2() in main(). - * - Investigate the crash. Use a debugger, run in valgrind, compile with -fsanitize=address ... - * - Rewrite the interface of Owner::getData() such that the observer can see the shared_ptr to the large object. - * - Set up the Observer such that it stores a weak pointer that observes the large object. - * - In Observer::processData(), access the weak pointer, and use the data *only* if the memory is still alive. - * Note: What you need is weak_ptr::lock(). Check out the documentation and the example at the bottom: - * https://en.cppreference.com/w/cpp/memory/weak_ptr/lock - * -------------------------------------------------------------------------------------------- - */ - -class Owner { -public: - Owner() : - _largeObj(new LargeObject()) { } - - ~Owner() { - std::cout << "problem4(): I think I'm the owner. I'm deallocating " << _largeObj << " now.\n"; - delete _largeObj; - } - - const LargeObject* getData() const { - return _largeObj; - } - -private: - LargeObject* _largeObj; -}; - - -void problem4_1() { - std::vector owners; - - for (unsigned int i=0; i < 5; ++i) { - Owner owner; - owners.push_back(owner); - } - - /* Starting from here, we have a problem: - * We created all these data owners, but the ones in the vector are copies of the owner objects in the loop. - * When those originals are destroyed, the memory is deallocated. The copies now - * point to the deallocated memory! - * We can fix this using copy constructors (but we don't want to copy the data), - * using move semantics or using shared_ptr. - */ -} - - -class Observer { -public: - Observer(const Owner& owner) : - _largeObj(owner.getData()) { } - - double processData() const { - if (_largeObj) { - return _largeObj->fData[0]; - } - - return -1.; - } - -private: - const LargeObject* _largeObj; // We don't own this. -}; - - - -void problem4_2() { - // We directly construct 5 owners inside the vector to get around problem4_1: - std::vector owners(5); - std::vector observers; - - observers.reserve(owners.size()); - for (const auto& owner : owners) { - observers.emplace_back(owner); - } - - // Now let's destroy the owners: - owners.clear(); - - for (const auto& observer : observers) { - // Problem: We don't know if the data is alive ... - // TODO: Fix Observer! - // observer.processData(); - } -} - - -int main() { - problem1(); - problem2(); - problem3(); -// problem4_1(); - problem4_2(); -} diff --git a/code/smartPointers/solution/smartPointers.sol.cpp b/code/smartPointers/solution/smartPointers.sol.cpp deleted file mode 100644 index 912af3c4..00000000 --- a/code/smartPointers/solution/smartPointers.sol.cpp +++ /dev/null @@ -1,294 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* - * Please fix all memory leaks / ownership problems using smart pointers. - * (Verify by running the program with valgrind!) - * - * Remember that: - * - The ownership of data is expressed using unique_ptr. - * - "Observer" access without ownership is expressed using raw pointers. - * - Shared access to data is expressed using shared_ptr. - */ - - -/* -------------------------------------------------------------------------------------------- - * 1: Always use smart pointers when you use new. - * - * A frequent source of leaks is a function that terminates earlier than the programmer thought. - * - * - Fix the leak using a smart pointer. - * - The arguments of sumEntries() don't need to change, as it has only read access. - * -------------------------------------------------------------------------------------------- - */ - -// Declare a function to do something with the data. No need to change it. -double sumEntries(const double* data, std::size_t size) { - if (size > 200) - throw std::invalid_argument("I only want to sum 200 numbers or less."); - - return std::reduce(data, data + size, 0.); -} - -// Often, data are owned by one entity, and only used by others. Fix the leak. -void doStuffWithData() { - constexpr std::size_t arraySize = 10000; - auto data = std::make_unique(arraySize); - - sumEntries(data.get(), arraySize); -} - -void problem1() { - try { - doStuffWithData(); - } catch (std::exception& e) { - std::cerr << "problem1(): Do stuff with data terminated with exception:\n" << e.what() << '\n'; - } -} - - - -/* -------------------------------------------------------------------------------------------- - * 2: Storing unique_ptr in collections. - * - * Often, one has to store pointers to objects in collections. Fix the memory leaks using unique_ptr. - * - * Notes: - * - Factory functions should return objects either directly or using smart pointers. - * This is good practice, because it clearly shows who owns an object. Fix the return type of the factory function. - * - The vector should own the objects, so try to store them using smart pointers. - * - Since the visitor function doesn't accept smart pointers, find a solution to pass the objects. - * Note that this works without shared_ptr! - * -------------------------------------------------------------------------------------------- - */ - -// This is a large object. We maybe shouldn't copy it, so using a pointer is advisable to pass it around. -struct LargeObject { - double fData[100000]; -}; - -// A factory function to create large objects. -std::unique_ptr createLargeObject() { - auto object = std::make_unique(); - // Do more setting up of object here - // ... - - return object; -} - -// A function to do something with the objects. -// Note that since we don't own the object, we don't need a smart pointer as argument. -void visitLargeObject(LargeObject* object) { - object->fData[0] = 1.; -} - -void problem2() { - std::vector> largeObjects; - - for (unsigned int i=0; i < 10; ++i) { - auto newObj = createLargeObject(); - largeObjects.push_back(std::move(newObj)); // Can only have one copy, so need to "give up" newObj by moving it into the vector. - - // Alternatively: - // largeObject.push_back(createLargeObject()); - } - - for (const auto& obj : largeObjects) { - visitLargeObject(obj.get()); - } -} - - - -/* -------------------------------------------------------------------------------------------- - * 3: Shared ownership. - * - * Most of the time, ownership can be solved by having one owner (with unique_ptr) and one or - * more observers. Sometimes, we need to truly share data, though. - * - * Here is an example of a completely messed up ownership model. It leaks about 1/10 of the times - * it is invoked. - * - Verify this by running it in a loop using a command like: - * while true; do valgrind --leak-check=full --track-origins=yes ./smartPointers 2>&1 | grep -B 5 -A 5 problem3 && exit 1; done - * - Fix the ownership model using shared_ptr! - * - Convert the vectors to holding shared_ptr. - * - Fix the arguments of the functions. - * - Speed optimisation: - * Make sure that you don't create & destroy a shared_ptr in the for loop in problem3() and when calling processElement(). - * -------------------------------------------------------------------------------------------- - */ - -// This removes the element in the middle of the vector. -void removeMiddle(std::vector>& collection) { - auto middlePosition = collection.begin() + collection.size()/2; - - // Must not delete element when erasing from collection, because it's also in the copy ... - collection.erase(middlePosition, middlePosition+1); -} - -// This removes a random element. -// Note that this leaks if the element happens to be the same -// that's removed above ... -void removeRandom(std::vector>& collection) { - auto pos = collection.begin() + time(nullptr) % collection.size(); - - collection.erase(pos, pos+1); -} - -// Do something with an element. -// Just a dummy function, for you to figure out how to pass an object -// managed by a shared_ptr to a function. -void processElement(const LargeObject* /*element*/) { } - - -// We have pointers to objects in two different collections. We work a bit with -// the collections, and then we try to terminate leak free. Without a shared ownership -// model, this becomes a mess. -void problem3() { - // Let's generate a vector with 10 pointers to LargeObject - std::vector> objVector; - objVector.reserve(10); - for (unsigned int i = 0; i < 10; i++) { - objVector.emplace_back(new LargeObject()); - } - - // Let's copy it - std::vector> objVectorCopy(objVector); - - - // Now we work with the objects: - removeMiddle(objVector); - removeRandom(objVectorCopy); - // ... - // ... - for (const auto& elm : objVector) { - processElement(elm.get()); - } - - // Destruction happens automatically! -} - - - -/* -------------------------------------------------------------------------------------------- - * 4: Smart pointers as class members. - * - * Class members that are pointers can quickly become a problem. - * Firstly, if only raw pointers are used, the intended ownerships are unclear. - * Secondly, it's easy to overlook that a member has to be deleted. - * Thirdly, pointer members usually require to implement copy or move constructors or assignment - * operators. - * Since C++-11, one can solve those problems using smart pointers. - * - * 4.1: - * The class "Owner" owns some data, but it is broken. If you copy it like in - * problem4_1(), you have two pointers pointing to the same data, but both think - * that they own the data. - * - Comment in problem4_1() in main(). - * - Verify that it crashes. Try running valgrind ./smartPointers, it should give you some hints as to - * what's happening. - * - Fix the Owner class by using a shared_ptr for its _largeObj, which we can copy as much as we want. - * - Note: Now you even don't need a destructor. - * - * 4.2: **BONUS** - * We go beyond the scope of the lecture now, and use a weak pointer. - * These are used to observe a shared_ptr, but unlike the shared_ptr, they don't prevent the deletion - * of the underlying object if all shared_ptr go out of scope. - * To *use* the observed data, one has to create a shared_ptr from the weak_ptr, so that it is guaranteed that - * the underlying object is alive. - * - * In our case, the observer class wants to observe the data of the owner, but it doesn't need to own it. - * To do this, we use a weak pointer. - * - * Tasks: - * - Comment in the line in problem4_2() that crashes the program. - * - Rewrite the interface of Owner::getData() such that the observer can see the shared_ptr to the large object. - * - Set up the Observer such that it stores a weak pointer that observes the large object. - * - In Observer::processData(), access the weak pointer, and use the data *only* if the memory is still alive. - * Note: What you need is weak_ptr::lock(). Check out the documentation and the example at the bottom: - * https://en.cppreference.com/w/cpp/memory/weak_ptr/lock - * -------------------------------------------------------------------------------------------- - */ - -class Owner { -public: - Owner() : - _largeObj(new LargeObject()) { } - - std::shared_ptr getData() const { - return _largeObj; - } - -private: - std::shared_ptr _largeObj; -}; - - -void problem4_1() { - std::vector owners; - - for (unsigned int i=0; i < 5; ++i) { - Owner owner; - owners.push_back(owner); - } - - // No problem now. Every object is deallocated only once. -} - - -class Observer { -public: - Observer(const Owner& owner) : - _largeObj(owner.getData()) { } - - double processData() const { - if (auto data = _largeObj.lock(); data) { // Needs c++-17 - return data->fData[0]; - } - - return -1.; - } - -private: - std::weak_ptr _largeObj; // We don't own this. -}; - - - -void problem4_2() { - // We directly construct 5 owners inside the vector to get around problem4_1: - std::vector owners(5); - std::vector observers; - - observers.reserve(owners.size()); - for (const auto& owner : owners) { - observers.emplace_back(owner); - } - - // Now let's destroy the owners: - owners.clear(); - - for (const auto& observer : observers) { - observer.processData(); - } -} - - - - - -int main() { - problem1(); - problem2(); - problem3(); - problem4_1(); - problem4_2(); -} diff --git a/code/spaceship/CMakeLists.txt b/code/spaceship/CMakeLists.txt deleted file mode 100644 index 25c73197..00000000 --- a/code/spaceship/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.12 ) -project( spaceship LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# Create the user's executable. -add_executable( spaceship "spaceship.cpp" ) - -# Create the "solution executable". -add_executable( spaceship.sol EXCLUDE_FROM_ALL "solution/spaceship.sol.cpp" ) -add_dependencies( solution spaceship.sol ) diff --git a/code/spaceship/Makefile b/code/spaceship/Makefile deleted file mode 100644 index 1812dcf7..00000000 --- a/code/spaceship/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: spaceship -solution: spaceship.sol - -clean: - rm -f *o *so spaceship *~ spaceship.sol - -% : %.cpp - $(CXX) -g -std=c++20 -Wall -Wextra -o $@ $< - -%.sol : solution/%.sol.cpp - $(CXX) -g -std=c++20 -Wall -Wextra -o $@ $< diff --git a/code/spaceship/README.md b/code/spaceship/README.md deleted file mode 100644 index 72cdf6fc..00000000 --- a/code/spaceship/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# The art of <=> - -Here we explore: -- how <=> are == differing. -- when to use or not to use the compiler default implementations. - -## Prerequisites - -* Being able to overload an operator, especially `==` and `<=>`. - -## Instructions - -0. Compile and run the program. We are not fully happy with the default implementation of `<=>` for our `Complex` class, which considers 1|2 as smaller than 1.5|1.5. -1. Modify it so that the ordering is based on the norm of the complexes. -2. Because you do not use any more the default implementation of `<=>` you had to provide also an implementation for `==`. What happens if you deduce it from `<=>` (using `(((*this)<=>other)==0)`) ? -3. Try to restore the default implementation for `==` only. diff --git a/code/spaceship/solution/spaceship.sol.cpp b/code/spaceship/solution/spaceship.sol.cpp deleted file mode 100644 index 8e209c70..00000000 --- a/code/spaceship/solution/spaceship.sol.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include - -struct Complex - { - double r, i ; - double norm() const { return std::sqrt(r*r+i*i) ; } - auto operator<=>( Complex const & other ) const - { return (norm()<=>other.norm()) ; } - bool operator==( Complex const & other ) const = default ; - } ; - -std::ostream & operator<<( std::ostream & os, std::partial_ordering cmp ) - { return (os<<'<'<<(cmp<0)<<'|'<<(cmp==0)<<'|'<<(cmp>0)<<'>') ; } - -std::ostream & operator<<( std::ostream & os, Complex const & c ) - { return (os< -void compare( T lhs, T rhs ) - { - std::cout< "<rhs)<({ 1., 2. },{ 1.5, 1.5 }) ; - compare({ 1., 0. },{ 0., 1. }) ; - std::cout< -#include -#include - -/* - -We are not fully happy with the default implementation of `<=>`for our `Complex` class below. -1. Modify it so that the ordering is based on the norm of the complexes. -2. Because you do not use any more the default implementation of `<=>` you had to provide also an implementation for `==`. What happens if you deduce it from `<=>` (using `(((*this)<=>other)==0)`) ? -3. Try to restore the default implementation for `==` only. - -*/ - -struct Complex - { - double r, i ; - double norm() const { return std::sqrt(r*r+i*i) ; } - auto operator<=>( Complex const & other ) const = default ; - } ; - -std::ostream & operator<<( std::ostream & os, std::partial_ordering cmp ) - { return (os<<'<'<<(cmp<0)<<'|'<<(cmp==0)<<'|'<<(cmp>0)<<'>') ; } - -std::ostream & operator<<( std::ostream & os, Complex const & c ) - { return (os< -void compare( T lhs, T rhs ) - { - std::cout< "<rhs)<({ 1., 2. },{ 1.5, 1.5 }) ; - compare({ 1., 0. },{ 0., 1. }) ; - std::cout< - -template -class Complex_t { -public: - Complex_t(T r, T i); - Complex_t(); - - T real() const {return m_r;}; - T imaginary() const {return m_i;}; - - Complex_t operator+(const Complex_t& other) const; - Complex_t operator-(const Complex_t& other) const; - Complex_t operator*(const Complex_t& other) const; - Complex_t operator*(const T factor) const; - Complex_t operator/(const T dividend) const; - Complex_t& operator+=(const Complex_t& other); - bool operator<(const Complex_t& a) const; -private: - T m_r{}, m_i{}; -}; - -typedef Complex_t<> Complex; - -template -Complex_t::Complex_t() {} - -template -Complex_t::Complex_t(T r, T i) : m_r(r), m_i(i) {} - -template -Complex_t Complex_t::operator+(const Complex_t& other) const { - return Complex_t(m_r + other.m_r, m_i + other.m_i); -} - -template -Complex_t Complex_t::operator-(const Complex_t& other) const { - return Complex_t(m_r - other.m_r, m_i - other.m_i); -} - -template -Complex_t Complex_t::operator*(const Complex_t& other) const { - return Complex_t(m_r*other.m_r - m_i*other.m_i, - m_r*other.m_i + m_i*other.m_r); -} - -template -Complex_t Complex_t::operator*(const T factor) const { - return Complex_t(m_r*factor, m_i*factor); -} - -template -Complex_t Complex_t::operator/(const T dividend) const { - return Complex_t(m_r/dividend, m_i/dividend); -} - -template -Complex_t& Complex_t::operator+=(const Complex_t& other) { - m_r += other.m_r; - m_i += other.m_i; - return *this; -} - -template -bool Complex_t::operator<(const Complex_t& other) const { - return (m_r*m_r+m_i*m_i) < (other.m_r*other.m_r+other.m_i*other.m_i); -} - -template -std::ostream& operator<<(std::ostream& os, - const Complex_t& c) { - os << "(" << c.real() << ", " << c.imaginary() << ")"; - return os; -} diff --git a/code/stl/Makefile b/code/stl/Makefile deleted file mode 100644 index 28431845..00000000 --- a/code/stl/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -all: randomize.nostl randomize -solution: randomize.sol - -clean: - rm -f *o randomize *~ randomize.sol randomize.nostl - -randomize : randomize.cpp - ${CXX} -std=c++17 -g -O0 -Wall -Wextra -L. -o $@ $< - -randomize.nostl : randomize.nostl.cpp - ${CXX} -std=c++17 -g -O0 -Wall -Wextra -L. -o $@ $< - -randomize.sol : solution/randomize.sol.cpp - ${CXX} -std=c++17 -g -O0 -Wall -Wextra -I. -L. -o $@ $< diff --git a/code/stl/README.md b/code/stl/README.md deleted file mode 100644 index c77385c8..00000000 --- a/code/stl/README.md +++ /dev/null @@ -1,9 +0,0 @@ - -## Instructions - -* look at the non STL code in randomize.nostl.cpp - * it creates a vector of ints at regular intervals - * it randomizes them - * it computes differences between consecutive ints and the mean and variance of it -* open randomize.cpp and complete the “translation” to the STL -* see how easy it is to reuse the code with complex numbers, by calling `compute` with objects of type `Complex` diff --git a/code/stl/randomize.cpp b/code/stl/randomize.cpp deleted file mode 100644 index d59d6a59..00000000 --- a/code/stl/randomize.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include -#include -#include "Complex.hpp" - -using namespace std; - -template -void compute(int len, T initial, T step) { - // allocate vectors - std::vector v(len+1), diffs(len+1); - - // fill and randomize v - generate(, , [](...) { ...; }); - shuffle(..., std::default_random_engine{}); - - // compute differences - adjacent_difference(...); - - // compute standard deviation of it - T sum = accumulate(...); - T sumsq = accumulate(..., [](...) { ...; }); - T mean = sum/len; - T variance = sumsq/len - mean*mean; - - std::cout << "Range = [" << initial << ", " << step*len << "]\n" - << "Mean = " << mean << '\n' - << "Variance = " << variance << '\n'; -} - -int main() { - compute(1000, 0.0, 7.0); - // call compute here with Complex -} diff --git a/code/stl/randomize.nostl.cpp b/code/stl/randomize.nostl.cpp deleted file mode 100644 index 83f2cd2d..00000000 --- a/code/stl/randomize.nostl.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include -#include - -#define LEN 1000 -#define STEP 7 - -void randomize(int* v, unsigned int len) { - // we randomize via len random inversions - for (unsigned int i = 0; i < len; i++) { - int a = rand()%len; - int b = rand()%len; - int mem = v[a]; - v[a] = v[b]; - v[b] = mem; - } -} - -int main() { - // create vector - int *v = new int[LEN+1]; - for (unsigned int i = 0; i <= LEN; i++) v[i] = i*STEP; - - // randomize it - randomize(v, LEN+1); - - // compute diffs - int *diffs = new int[LEN]; - for (unsigned int i = 0; i < LEN; i++) - diffs[i] = v[i+1] - v[i]; - - // compute standard deviation of it - float sum = 0; - float sumsq = 0; - for (unsigned int i = 0; i < LEN; i ++) { - sum += diffs[i]; - sumsq += diffs[i]*diffs[i]; - } - float mean = sum/LEN; - float stddev = sqrt(sumsq/LEN - mean*mean) ; - std::cout << "Range = [0, " << STEP*LEN << "]\n" - << "Mean = " << mean - << "\nStdDev = " << stddev << '\n'; - - delete[] v; - delete[] diffs; -} diff --git a/code/stl/solution/randomize.sol.cpp b/code/stl/solution/randomize.sol.cpp deleted file mode 100644 index 9ad71015..00000000 --- a/code/stl/solution/randomize.sol.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include -#include -#include "Complex.hpp" - -using namespace std; - -template -struct Generator { - T m_value, m_step; - Generator(T initial, T step):m_value(initial), m_step(step){}; - T operator()() { - T cur_value = m_value; - m_value += m_step; - return cur_value; - } -}; - -template -struct sumsquare { - T operator()(const T& s, const T& a) { return s + a * a; }; -}; - -template -void compute(int len, T initial, T step) { - // allocate vectors - std::vector v(len+1), diffs(len+1); - - // fill and randomize v - generate(v.begin(), v.end(), Generator(initial, step)); - shuffle(v.begin(), v.end(), std::default_random_engine{}); - - // compute differences - adjacent_difference(v.begin(), v.end(), diffs.begin()); - - // compute standard deviation of it - T sum = reduce(diffs.begin()+1, diffs.end(), T()); - T sumsq = reduce(diffs.begin()+1, diffs.end(), T(), sumsquare()); - T mean = sum/len; - T variance = sumsq/len - mean*mean; - - std::cout << "Range = [" << initial << ", " << step*len << "]\n" - << "Mean = " << mean << '\n' - << "Variance = " << variance << '\n'; -} - -int main() { - compute(1000, 0.0, 7.0); - compute(1000, Complex(0,0), Complex(1,2)); -} diff --git a/code/templates/CMakeLists.txt b/code/templates/CMakeLists.txt deleted file mode 100644 index d3f01cdf..00000000 --- a/code/templates/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( templates LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( playwithsort "Complex.hpp" "OrderedVector.hpp" "playwithsort.cpp" ) - -# Create the "solution executable". -add_executable( playwithsort.sol EXCLUDE_FROM_ALL - "Complex.hpp" "solution/OrderedVector.sol.hpp" "solution/playwithsort.sol.cpp" ) -target_include_directories( playwithsort.sol PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" ) -add_dependencies( solution playwithsort.sol ) diff --git a/code/templates/Complex.hpp b/code/templates/Complex.hpp deleted file mode 100644 index d32ee522..00000000 --- a/code/templates/Complex.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#include - -template -class Complex_t { -public: - Complex_t(T r, T i); - Complex_t(); - - T real() const {return m_r;}; - T imaginary() const {return m_i;}; - - Complex_t operator+(const Complex_t& other) const; - Complex_t operator-(const Complex_t& other) const; - Complex_t operator*(const Complex_t& other) const; - Complex_t operator*(const T factor) const; - Complex_t operator/(const T dividend) const; - Complex_t& operator+=(const Complex_t& other); - bool operator<(const Complex_t& a) const; -private: - T m_r{}, m_i{}; -}; - -typedef Complex_t<> Complex; - -template -Complex_t::Complex_t() {} - -template -Complex_t::Complex_t(T r, T i) : m_r(r), m_i(i) {} - -template -Complex_t Complex_t::operator+(const Complex_t& other) const { - return Complex_t(m_r + other.m_r, m_i + other.m_i); -} - -template -Complex_t Complex_t::operator-(const Complex_t& other) const { - return Complex_t(m_r - other.m_r, m_i - other.m_i); -} - -template -Complex_t Complex_t::operator*(const Complex_t& other) const { - return Complex_t(m_r*other.m_r - m_i*other.m_i, - m_r*other.m_i + m_i*other.m_r); -} - -template -Complex_t Complex_t::operator*(const T factor) const { - return Complex_t(m_r*factor, m_i*factor); -} - -template -Complex_t Complex_t::operator/(const T dividend) const { - return Complex_t(m_r/dividend, m_i/dividend); -} - -template -Complex_t& Complex_t::operator+=(const Complex_t& other) { - m_r += other.m_r; - m_i += other.m_i; - return *this; -} - -template -bool Complex_t::operator<(const Complex_t& other) const { - return (m_r*m_r+m_i*m_i) < (other.m_r*other.m_r+other.m_i*other.m_i); -} - -template -std::ostream& operator<<(std::ostream& os, - const Complex_t& c) { - os << "(" << c.real() << ", " << c.imaginary() << ")"; - return os; -} diff --git a/code/templates/Makefile b/code/templates/Makefile deleted file mode 100644 index 79aa5475..00000000 --- a/code/templates/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: playwithsort -solution: playwithsort.sol - -clean: - rm -f *o *so playwithsort *~ playwithsort.sol - -playwithsort : playwithsort.cpp OrderedVector.hpp Complex.hpp - $(CXX) -std=c++11 -g -O0 -Wall -Wextra -o $@ $< - -playwithsort.sol : solution/playwithsort.sol.cpp solution/OrderedVector.sol.hpp Complex.hpp - $(CXX) -std=c++11 -g -O0 -Wall -Wextra -I. -o $@ $< diff --git a/code/templates/OrderedVector.hpp b/code/templates/OrderedVector.hpp deleted file mode 100644 index 0116cfff..00000000 --- a/code/templates/OrderedVector.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include - -template -class OrderedVector { -public: - OrderedVector(unsigned int maxLen); - ~OrderedVector(); - OrderedVector(const OrderedVector&) = delete; - OrderedVector& operator=(const OrderedVector&) = delete; - bool add(ElementType value); - ElementType& get(unsigned int n); - ElementType& operator[](unsigned int n); -private: - unsigned int m_len; - unsigned int m_maxLen; - ElementType* m_data; -}; - -template -OrderedVector::~OrderedVector() { - delete[](m_data); -} - -template -OrderedVector::OrderedVector(unsigned int maxLen) : -m_len(0), m_maxLen(maxLen) { - m_data = new ElementType[m_maxLen]; -} - -template -bool OrderedVector::add(ElementType value) { - if (m_len >= m_maxLen) { - return false; - } - // find insertion point - unsigned int insertIndex = 0; - while (insertIndex < m_len && m_data[insertIndex] < value) - insertIndex++; - // move end of vector - unsigned int index = m_len; - while (index > insertIndex) { - m_data[index] = m_data[index-1]; - index--; - } - // actual insertion - m_data[index] = value; - m_len++; - return true; -} - -template -ElementType& OrderedVector::get(unsigned int n) { - if (n >= m_len) { - throw std::out_of_range("too big"); - } - return m_data[n]; -} - -template -ElementType& OrderedVector::operator[](unsigned int n) { - return get(n); -} diff --git a/code/templates/README.md b/code/templates/README.md deleted file mode 100644 index 2d1a97b6..00000000 --- a/code/templates/README.md +++ /dev/null @@ -1,16 +0,0 @@ - -## Instructions - -Beginners -* look at the `OrderedVector` code -* compile and run `playwithsort.cpp`. See the ordering -* modify `playwithsort.cpp` and reuse `OrderedVector` with `Complex` - -Intermediary -* improve `OrderedVector` to template the ordering -* test reverse ordering of strings (from the last letter) -* test order based on [Manhattan distance](https://en.wikipedia.org/wiki/Taxicab_geometry) with complex type - -Bonus -* check the implementation of `Complex` -* try ordering complex of complex diff --git a/code/templates/playwithsort.cpp b/code/templates/playwithsort.cpp deleted file mode 100644 index 3d3cb936..00000000 --- a/code/templates/playwithsort.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "OrderedVector.hpp" -#include "Complex.hpp" -#include -#include -#include - -/* -struct OrderFunctor { - bool operator() (const TYPE &s, const TYPE &t) const { - } -}; -*/ - -int main() { - std::cout << "Integer\n"; - OrderedVector v(10); - for (int i = 10; i > 0; i--) - v.add(i); - for (int i = 0; i < 10; i++) - std::cout << v[i] << " "; - std::cout << "\n\n"; - - std::cout << "String\n"; - OrderedVector vs(5); - vs.add(std::string("one")); - vs.add(std::string("two")); - vs.add(std::string("three")); - vs.add(std::string("four")); - vs.add(std::string("five")); - for (int i = 0; i < 5; i++) - std::cout << vs[i] << " "; - std::cout << "\n\n"; - -} diff --git a/code/templates/solution/OrderedVector.sol.hpp b/code/templates/solution/OrderedVector.sol.hpp deleted file mode 100644 index da6cb49b..00000000 --- a/code/templates/solution/OrderedVector.sol.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include - -template -struct less { - bool operator() (const T& x, const T& y) const {return x > -class OrderedVector { -public: - OrderedVector(unsigned int maxLen); - ~OrderedVector(); - OrderedVector(const OrderedVector&) = delete; - OrderedVector& operator=(const OrderedVector&) = delete; - bool add(ElementType value); - ElementType& get(unsigned int n); - ElementType& operator[](unsigned int n); -private: - unsigned int m_len; - unsigned int m_maxLen; - Compare m_compare; - ElementType* m_data; -}; - -template -OrderedVector::~OrderedVector() { - delete[](m_data); -} - -template -OrderedVector::OrderedVector(unsigned int maxLen) : -m_len(0), m_maxLen(maxLen), m_compare() { - m_data = new ElementType[m_maxLen]; -} - -template -bool OrderedVector::add(ElementType value) { - if (m_len >= m_maxLen) { - return false; - } - // find insertion point - unsigned int insertIndex = 0; - while (insertIndex < m_len && m_compare(m_data[insertIndex], value)) - insertIndex++; - // move end of vector - unsigned int index = m_len; - while (index > insertIndex) { - m_data[index] = m_data[index-1]; - index--; - } - // actual insertion - m_data[index] = value; - m_len++; - return true; -} - -template -ElementType& OrderedVector::get(unsigned int n) { - if (n >= m_len) { - throw std::out_of_range("too big"); - } - return m_data[n]; -} - -template -ElementType& OrderedVector::operator[](unsigned int n) { - return get(n); -} diff --git a/code/templates/solution/playwithsort.sol.cpp b/code/templates/solution/playwithsort.sol.cpp deleted file mode 100644 index 4fef5a09..00000000 --- a/code/templates/solution/playwithsort.sol.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "OrderedVector.sol.hpp" -#include "Complex.hpp" -#include -#include -#include -#include - -struct RevOrderString { - bool operator() (const std::string &s, const std::string &t) const { - std::string rs = s; - std::string rt = t; - std::reverse(rs.begin(), rs.end()); - std::reverse(rt.begin(), rt.end()); - return rs < rt; - } -}; - -struct ManhattanOrder { - bool operator() (const Complex &a, const Complex &b) const { - return std::abs(a.real()) + std::abs(a.imaginary()) < std::abs(b.real()) + std::abs(b.imaginary()); - } -}; - -int main() { - std::cout << "Integer\n"; - OrderedVector v(10); - for (int i = 10; i > 0; i--) - v.add(i); - for (int i = 0; i < 10; i++) - std::cout << v[i] << " "; - std::cout << "\n\n"; - - std::cout << "String\n"; - OrderedVector vs(5); - vs.add(std::string("one")); - vs.add(std::string("two")); - vs.add(std::string("three")); - vs.add(std::string("four")); - vs.add(std::string("five")); - for (int i = 0; i < 5; i++) - std::cout << vs[i] << " "; - std::cout << "\n\n"; - - std::cout << "Complex\n"; - OrderedVector vc(5); - vc.add(Complex(1.5,0.0)); - vc.add(Complex(1.0,1.0)); - vc.add(Complex(-1.0,0.0)); - vc.add(Complex(1.0,2.0)); - vc.add(Complex(0.0,0.0)); - for (int i = 0; i < 5; i++) - std::cout << vc[i] << " "; - std::cout << "\n\n"; - - std::cout << "String\n"; - OrderedVector vsr(5); - vsr.add(std::string("one")); - vsr.add(std::string("two")); - vsr.add(std::string("three")); - vsr.add(std::string("four")); - vsr.add(std::string("five")); - for (int i = 0; i < 5; i++) - std::cout << vsr[i] << " "; - std::cout << "\n\n"; - - std::cout << "Complex with manhatan order\n"; - OrderedVector vcm(5); - vcm.add(Complex(1.5,0.0)); - vcm.add(Complex(1.0,1.0)); - vcm.add(Complex(-1.0,0.0)); - vcm.add(Complex(1.0,2.0)); - vcm.add(Complex(0.0,0.0)); - for (int i = 0; i < 5; i++) - std::cout << vcm[i] << " "; - std::cout << "\n\n"; - - std::cout << "Int Complex\n"; - typedef Complex_t IComplex; - OrderedVector vci(5); - vci.add(IComplex(2,0)); - vci.add(IComplex(1,1)); - vci.add(IComplex(-1,0)); - vci.add(IComplex(1,2)); - vci.add(IComplex(0,0)); - for (int i = 0; i < 5; i++) - std::cout << vci[i] << " "; - std::cout << "\n\n"; - - std::cout << "Very Complex\n"; - typedef Complex_t VComplex; - OrderedVector vcv(5); - vcv.add(VComplex(Complex(2,0),Complex(1,0))); - vcv.add(VComplex(Complex(2,0),Complex(0,2))); - vcv.add(VComplex(Complex(1,0),Complex(0,0))); - vcv.add(VComplex(Complex(0,1),Complex(1,0))); - vcv.add(VComplex(Complex(2,0),Complex(0,0))); - for (int i = 0; i < 5; i++) - std::cout << vcv[i] << " "; - std::cout << "\n\n"; - -} diff --git a/code/valgrind/CMakeLists.txt b/code/valgrind/CMakeLists.txt deleted file mode 100644 index 640db190..00000000 --- a/code/valgrind/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( valgrind LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's executable. -add_executable( valgrind_randomize "randomize.cpp" ) - -# Create the "solution executable". -add_executable( valgrind_randomize.sol EXCLUDE_FROM_ALL "solution/randomize.sol.cpp" ) -add_dependencies( solution valgrind_randomize.sol ) diff --git a/code/valgrind/Makefile b/code/valgrind/Makefile deleted file mode 100644 index 4b45b44f..00000000 --- a/code/valgrind/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: randomize -solution: randomize.sol - -clean: - rm -f *o randomize *~ randomize.sol core - -randomize : randomize.cpp - ${CXX} -g -O0 -Wall -Wextra -L. -o $@ $< - -randomize.sol : solution/randomize.sol.cpp - ${CXX} -g -O0 -Wall -Wextra -L. -o $@ $< diff --git a/code/valgrind/README.md b/code/valgrind/README.md deleted file mode 100644 index 991367c1..00000000 --- a/code/valgrind/README.md +++ /dev/null @@ -1,6 +0,0 @@ - -## Instructions - -* compile, run, it should work -* run with valgrind (`valgrind ./randomize`) -* fix the problem diff --git a/code/valgrind/randomize.cpp b/code/valgrind/randomize.cpp deleted file mode 100644 index ccb29250..00000000 --- a/code/valgrind/randomize.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include -#include - -#define LEN 1000 -#define STEP 7 - -void swap(int *a, int*b) { - int c = *a; - *a = *b; - *b = c; -} - -void randomize(int* v, unsigned int len) { - // we randomize via len random inversions - for (unsigned int i = 0; i < len; i++) { - int a = rand()%len; - int b = rand()%len; - swap(v+a, v+b); - } -} - -void createAndFillVector(int** v, unsigned int len) { - *v = new int[len]; - for (unsigned int i = 0; i < len; i++) (*v)[i] = i*STEP; -} - -int main() { - int *v; - // create and randomize vector - createAndFillVector(&v, LEN+1); - randomize(v, LEN+1); - - // compute diffs - int *diffs = new int[LEN]; - for (unsigned int i = 0; i < LEN; i++) - diffs[i] = v[i+1] - v[i]; - delete[] v; - delete[] diffs; - - // compute standard deviation of it - float sum = 0; - float sumsq = 0; - for (unsigned int i = 0; i < LEN; i ++) { - sum += diffs[i]; - sumsq += diffs[i]*diffs[i]; - } - float mean = sum/LEN; - float stddev = sqrt(sumsq/LEN - mean*mean) ; - std::cout << "Range = [0, " << STEP*LEN << "]\n" - << "Mean = " << mean - << "\nStdDev = " << stddev << '\n'; -} diff --git a/code/valgrind/solution/randomize.sol.cpp b/code/valgrind/solution/randomize.sol.cpp deleted file mode 100644 index 39fb469e..00000000 --- a/code/valgrind/solution/randomize.sol.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include - -#define LEN 1000 -#define STEP 7 - -void swap(int *a, int*b) { - int c = *a; - *a = *b; - *b = c; -} - -void randomize(int* v, unsigned int len) { - // we randomize via len random inversions - for (unsigned int i = 0; i < len; i++) { - int a = rand()%len; - int b = rand()%len; - swap(v+a, v+b); - } -} - -void createAndFillVector(int** v, unsigned int len) { - *v = new int[len]; - for (unsigned int i = 0; i < len; i++) (*v)[i] = i*STEP; -} - -int main() { - int *v; - // create and randomize vector - createAndFillVector(&v, LEN+1); - randomize(v, LEN+1); - - // compute diffs - int *diffs = new int[LEN]; - for (unsigned int i = 0; i < LEN; i++) - diffs[i] = v[i+1] - v[i]; - delete[] v; - - // compute standard deviation of it - float sum = 0; - float sumsq = 0; - for (unsigned int i = 0; i < LEN; i ++) { - sum += diffs[i]; - sumsq += diffs[i]*diffs[i]; - } - delete[] diffs; - - float mean = sum/LEN; - float stddev = sqrt(sumsq/LEN - mean*mean) ; - std::cout << "Range = [0, " << STEP*LEN << "]\n" - << "Mean = " << mean - << "\nStdDev = " << stddev << '\n'; -} diff --git a/code/virtual_inheritance/CMakeLists.txt b/code/virtual_inheritance/CMakeLists.txt deleted file mode 100644 index 835cd33f..00000000 --- a/code/virtual_inheritance/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ - -# Set up the project. -cmake_minimum_required( VERSION 3.1 ) -project( virtual_inheritance LANGUAGES CXX ) - -# Set up the compilation environment. -include( "${CMAKE_CURRENT_SOURCE_DIR}/../CompilerSettings.cmake" ) -include( "${CMAKE_CURRENT_SOURCE_DIR}/../SolutionTarget.cmake" ) - -# Create the user's library. -add_library( textbox "TextBox.hpp" "TextBox.cpp" ) -target_include_directories( textbox PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" ) - -# Create the user's executable. -add_executable( trymultiherit "trymultiherit.cpp" ) -target_link_libraries( trymultiherit PRIVATE textbox ) - -# Create the solution's library. -add_library( textboxsol EXCLUDE_FROM_ALL "solution/TextBox.hpp" "solution/TextBox.cpp" ) -target_include_directories( textboxsol PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/solution" ) -add_dependencies( solution textboxsol ) - -# Create the "solution executable". -add_executable( trymultiherit.sol EXCLUDE_FROM_ALL "solution/trymultiherit.sol.cpp" ) -target_link_libraries( trymultiherit.sol PRIVATE textboxsol ) -add_dependencies( solution trymultiherit.sol ) diff --git a/code/virtual_inheritance/Makefile b/code/virtual_inheritance/Makefile deleted file mode 100644 index 252b5dc6..00000000 --- a/code/virtual_inheritance/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -all: trymultiherit -solution: trymultiherit.sol - -clean: - rm -f *o *so trymultiherit *~ trymultiherit.sol - -libtextbox.so: TextBox.cpp TextBox.hpp - $(CXX) -Wall -Wextra -shared -fPIC -o $@ $< - -trymultiherit : trymultiherit.cpp libtextbox.so - $(CXX) -Wall -Wextra -L. -o $@ $^ - -libtextboxsol.so: solution/TextBox.cpp solution/TextBox.hpp - $(CXX) -Wall -Wextra -shared -fPIC -o $@ $< - -trymultiherit.sol : solution/trymultiherit.sol.cpp libtextboxsol.so - $(CXX) -Wall -Wextra -I. -L. -o $@ $^ diff --git a/code/virtual_inheritance/README.md b/code/virtual_inheritance/README.md deleted file mode 100644 index 5a995598..00000000 --- a/code/virtual_inheritance/README.md +++ /dev/null @@ -1,11 +0,0 @@ - -## Instructions - -Step 1 -* look at the code -* open `trymultiherit.cpp` -* create a `TextBox` and call `draw` -* Fix the code to call both draws by using types - -Step 2 -* retry with virtual inheritance diff --git a/code/virtual_inheritance/TextBox.cpp b/code/virtual_inheritance/TextBox.cpp deleted file mode 100644 index 77bff8ea..00000000 --- a/code/virtual_inheritance/TextBox.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "TextBox.hpp" -#include - -Drawable::Drawable(int id) : m_id(id) {}; - -void Drawable::draw() { - std::cout << "Drawing " << m_id << '\n'; -}; - -Rectangle::Rectangle(int id, float width, float height) : - Drawable(id), m_width(width), m_height(height) {} - -Text::Text(int id, const std::string &content) : - Drawable(id), m_content(content) {} - -TextBox::TextBox(const std::string &content, - float width, float height) : - Rectangle(1, width, height), Text(2, content) {} diff --git a/code/virtual_inheritance/TextBox.hpp b/code/virtual_inheritance/TextBox.hpp deleted file mode 100644 index e910f839..00000000 --- a/code/virtual_inheritance/TextBox.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -class Drawable { -public: - Drawable(int id); - void draw(); -private: - int m_id; -}; - -class Rectangle : public Drawable { -public: - Rectangle(int id, float width, float height); -protected: - float m_width; - float m_height; -}; - -class Text : public Drawable { -public: - Text(int id, const std::string &content); -protected: - std::string m_content; -}; - -class TextBox : public Rectangle, public Text { -public: - TextBox(const std::string &content, - float width, float height); -}; diff --git a/code/virtual_inheritance/solution/TextBox.cpp b/code/virtual_inheritance/solution/TextBox.cpp deleted file mode 100644 index 2e9c301c..00000000 --- a/code/virtual_inheritance/solution/TextBox.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "TextBox.hpp" -#include - -Drawable::Drawable(int id) : m_id(id) {}; - -void Drawable::draw() { - std::cout << "Drawing " << m_id << '\n'; -}; - -Rectangle::Rectangle(int id, float width, float height) : - Drawable(id), m_width(width), m_height(height) {} - -Text::Text(int id, std::string content) : - Drawable(id), m_content(content) {} - -TextBox::TextBox(std::string content, - float width, float height) : - Drawable(3), Rectangle(1, width, height), Text(2, content) {} diff --git a/code/virtual_inheritance/solution/TextBox.hpp b/code/virtual_inheritance/solution/TextBox.hpp deleted file mode 100644 index 9dae50bb..00000000 --- a/code/virtual_inheritance/solution/TextBox.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -class Drawable { -public: - Drawable(int id); - void draw(); -private: - int m_id; -}; - -class Rectangle : public virtual Drawable { -public: - Rectangle(int id, float width, float height); -protected: - float m_width; - float m_height; -}; - -class Text : public virtual Drawable { -public: - Text(int id, std::string content); -protected: - std::string m_content; -}; - -class TextBox : public Rectangle, public Text { -public: - TextBox(std::string content, - float width, float height); -}; diff --git a/code/virtual_inheritance/solution/trymultiherit.sol.cpp b/code/virtual_inheritance/solution/trymultiherit.sol.cpp deleted file mode 100644 index 358b5298..00000000 --- a/code/virtual_inheritance/solution/trymultiherit.sol.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "TextBox.hpp" -#include - -int main() { - // create a TextBox and call draw - TextBox tb("my text", 10, 5); - // tb.draw(); - // error: request for member ‘draw’ is ambiguous - - // Fix the code to call both draws by using types - Rectangle &r = tb; - r.draw(); - Text &t = tb; - t.draw(); - - // retry with virtual inheritance - // error: no matching function for call to ‘Drawable::Drawable()’ - // add a default constructor to Drawable or call the constructor from TextBox -} diff --git a/code/virtual_inheritance/trymultiherit.cpp b/code/virtual_inheritance/trymultiherit.cpp deleted file mode 100644 index 8410cecc..00000000 --- a/code/virtual_inheritance/trymultiherit.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "TextBox.hpp" -#include - -int main() { - // create a TextBox and call draw - - - // Fix the code to call both draws by using types - - - // try with virtual inheritance - - -} From 0a0cc8114ff2d5ab173e7d59be98fceb709fa2bf Mon Sep 17 00:00:00 2001 From: Stefan Roiser Date: Wed, 20 Jul 2022 10:53:24 +0200 Subject: [PATCH 02/14] remove docker --- docker/Dockerfile | 53 ----------------------------------------- docker/README.md | 43 --------------------------------- docker/build.sh | 8 ------- docker/name.txt | 1 - docker/push.sh | 6 ----- docker/run.sh | 6 ----- docker/run_x11_linux.sh | 8 ------- docker/run_x11_macos.sh | 9 ------- docker/run_x11_win.sh | 9 ------- docker/versions.sh | 18 -------------- docker/xeyes_linux.sh | 5 ---- docker/xeyes_macos.sh | 6 ----- docker/xeyes_win.sh | 6 ----- 13 files changed, 178 deletions(-) delete mode 100644 docker/Dockerfile delete mode 100644 docker/README.md delete mode 100755 docker/build.sh delete mode 100644 docker/name.txt delete mode 100755 docker/push.sh delete mode 100755 docker/run.sh delete mode 100755 docker/run_x11_linux.sh delete mode 100755 docker/run_x11_macos.sh delete mode 100755 docker/run_x11_win.sh delete mode 100755 docker/versions.sh delete mode 100755 docker/xeyes_linux.sh delete mode 100755 docker/xeyes_macos.sh delete mode 100755 docker/xeyes_win.sh diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index 5b81df61..00000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,53 +0,0 @@ - -# Version 2, en Python3 - -FROM gcc:11.2.0 - -# Ensure use of bash - -SHELL ["/bin/bash","-c"] - -# Timezone - -ENV TZ=Europe/Paris - -# Apt-get General Preparation - -RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections -ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update \ -&& apt-get install -y apt-utils - -# C++ Tools - -RUN apt-get install -y build-essential \ -&& apt-get install -y cmake \ -&& apt-get install -y cppcheck \ -&& apt-get install -y libc6-dbg gdb \ -&& apt-get install -y binutils graphviz \ -&& apt-get install -y valgrind kcachegrind - -# For GDB not to complain - -RUN echo "set auto-load safe-path /" > /root/.gdbinit - -# Python -# It seems I MUST say 3.7 for dev :s - -RUN apt-get install -y python3 \ -&& apt-get install -y python3-dev \ -&& apt-get install -y python3-pip \ -&& apt-get install -y python3-tk - -RUN pip3 install numpy -RUN pip3 install matplotlib - -# Other - -RUN rm -rf /var/lib/apt/lists/* -ENV PATH=${PATH}:. -ENV LD_LIBRARY_PATH=. - -# Start a shell by default - -CMD bash diff --git a/docker/README.md b/docker/README.md deleted file mode 100644 index 6b98bbc4..00000000 --- a/docker/README.md +++ /dev/null @@ -1,43 +0,0 @@ - ---- -# Building and sharing the image - -* `build.sh` : apply the Dokerfile recipe, building a local image whose name is taken from `name.txt`. -* `push.sh` (unavailable since migratiom to github): push the image `name.txt` to the registry, which requires access rights to this registry. - - ---- -# Starting a container - -* `run.sh` : start a container from the image `name.txt`, and run the command given as arguments (default is `bash`). The current directory is mounted as `/work`, and this is where the command is executed. -* `run_x11_macos.sh` : same as `run.sh`, plus X11 forwarding, in macOS flavor. It requires some prerequisites: see next section. -* `run_x11_linux.sh` : same as `run.sh`, plus X11 forwarding, in linux flavor. -* `run_x11_win.sh` : same as `run.sh`, plus X11 forwarding, in windows flavor. It requires some prerequisites: see next section. -* `versions.sh` : type `./run.sh ./versions.sh` within the `docker` directory, and you should check the version of the installed tools in the image. - - ---- -# X11 applications - -For the use of applications with X11 graphics, especially `kcachegrind`, one must setup the forwarding of X11 commands from the container to the host machine, which may be turn complex, depending on your system. We provide a set of scripts `run_x11_.sh`. Except for linux, it requires to start an X11 server emulator, and define some environment variable `MYIP`, which should contain the IP number associated your host and X11 session. We give below some tricks for each system. Once you think it should work, try the script `xeyes_.sh`. - -## macOS - -1. Install and start XQuartz. -1. Search for your IP number, using terminal command `ifconfig` and searching for `inet` lines. -1. Define `export MYIP=`. -1. Check with `xeyes_macos.sh`. -1. Run `run_x11_macos.sh`. - -## Linux - -1. Check with `xeyes_linux.sh`. -1. Run `run_x11_linux.sh`. - -## Windows - -1. Install and start Xming or Exceed. For Xming, we recommend those options: `Xming :0 -multiwindow -clipboard -ac`. -1. The applications above should enable you to get some IP number, typically `10.0.75.1` for Exceed. -1. Define `export MYIP=`. -1. Check with `xeyes_win.sh`. -1. Run `run_x11_win.sh`. diff --git a/docker/build.sh b/docker/build.sh deleted file mode 100755 index e287973c..00000000 --- a/docker/build.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -SCRIPT_NAME=${BASH_SOURCE[0]} -SCRIPT_DIR=`dirname ${SCRIPT_NAME}` -cd ${SCRIPT_DIR} - -docker build -f Dockerfile -t `cat name.txt` . -# --force-rm --no-cache diff --git a/docker/name.txt b/docker/name.txt deleted file mode 100644 index d9d1b7aa..00000000 --- a/docker/name.txt +++ /dev/null @@ -1 +0,0 @@ -cpluspluscourse:v6 diff --git a/docker/push.sh b/docker/push.sh deleted file mode 100755 index 7126ff5c..00000000 --- a/docker/push.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -SCRIPT_NAME=${BASH_SOURCE[0]} -SCRIPT_DIR=`dirname ${SCRIPT_NAME}` - -docker push `cat ${SCRIPT_DIR}/name.txt` diff --git a/docker/run.sh b/docker/run.sh deleted file mode 100755 index c1e1320d..00000000 --- a/docker/run.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -SCRIPT_NAME=${BASH_SOURCE[0]} -SCRIPT_DIR=`dirname ${SCRIPT_NAME}` - -docker run --security-opt seccomp=unconfined -it --rm -v $PWD:/work -w /work `cat ${SCRIPT_DIR}/name.txt` $* diff --git a/docker/run_x11_linux.sh b/docker/run_x11_linux.sh deleted file mode 100755 index 769e4e0b..00000000 --- a/docker/run_x11_linux.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -SCRIPT_NAME=${BASH_SOURCE[0]} -SCRIPT_DIR=`dirname ${SCRIPT_NAME}` - -xhost + - -docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rw --security-opt seccomp=unconfined -it --rm -v $PWD:/work -w /work `cat ${SCRIPT_DIR}/name.txt` $* diff --git a/docker/run_x11_macos.sh b/docker/run_x11_macos.sh deleted file mode 100755 index 5d6ff6c4..00000000 --- a/docker/run_x11_macos.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -SCRIPT_NAME=${BASH_SOURCE[0]} -SCRIPT_DIR=`dirname ${SCRIPT_NAME}` - -export DISPLAY=${MYIP}:0 -xhost + ${MYIP} - -docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rw --security-opt seccomp=unconfined -it --rm -v $PWD:/work -w /work `cat ${SCRIPT_DIR}/name.txt` $* diff --git a/docker/run_x11_win.sh b/docker/run_x11_win.sh deleted file mode 100755 index a03150d1..00000000 --- a/docker/run_x11_win.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -SCRIPT_NAME=${BASH_SOURCE[0]} -SCRIPT_DIR=`dirname ${SCRIPT_NAME}` - -export DISPLAY=${MYIP}:0 -xhost + ${MYIP} - -docker run -e DISPLAY=$DISPLAY --security-opt seccomp=unconfined -it --rm -v $PWD:/work -w /work `cat ${SCRIPT_DIR}/name.txt` $* diff --git a/docker/versions.sh b/docker/versions.sh deleted file mode 100755 index 42f64413..00000000 --- a/docker/versions.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -echo -g++ --version - -echo -make --version - -echo -cppcheck --version - -echo -gdb --version - -echo -valgrind --version - -echo diff --git a/docker/xeyes_linux.sh b/docker/xeyes_linux.sh deleted file mode 100755 index 7d564b02..00000000 --- a/docker/xeyes_linux.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -xhost + - -docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rw gns3/xeyes diff --git a/docker/xeyes_macos.sh b/docker/xeyes_macos.sh deleted file mode 100755 index b0d00d20..00000000 --- a/docker/xeyes_macos.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -export DISPLAY=${MYIP}:0 -xhost + ${MYIP} - -docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rw gns3/xeyes diff --git a/docker/xeyes_win.sh b/docker/xeyes_win.sh deleted file mode 100755 index 13075abc..00000000 --- a/docker/xeyes_win.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -export DISPLAY=${MYIP}:0 -xhost + ${MYIP} - -docker run -e DISPLAY=$DISPLAY gns3/xeyes From 06d4e5a9a2d27f062aae24de622d4077596b7800 Mon Sep 17 00:00:00 2001 From: Stefan Roiser Date: Wed, 20 Jul 2022 10:55:30 +0200 Subject: [PATCH 03/14] remove notes --- notes/2016timing | 6 ------ notes/2017timing | 7 ------- notes/2018timing | 17 ----------------- notes/2019Timing | 14 -------------- notes/2020Timing | 13 ------------- 5 files changed, 57 deletions(-) delete mode 100644 notes/2016timing delete mode 100644 notes/2017timing delete mode 100644 notes/2018timing delete mode 100644 notes/2019Timing delete mode 100644 notes/2020Timing diff --git a/notes/2016timing b/notes/2016timing deleted file mode 100644 index 10c6c680..00000000 --- a/notes/2016timing +++ /dev/null @@ -1,6 +0,0 @@ -did 1-2-3 + object orientation in first 3h -stopped after memcheck on day 2 -added 20mn on day 3 to finish (not doing helgrind/ccpcheck) - -1 exercise done for real (templates, 1-4 only) -others done together, and some skipped completely diff --git a/notes/2017timing b/notes/2017timing deleted file mode 100644 index e2351a4f..00000000 --- a/notes/2017timing +++ /dev/null @@ -1,7 +0,0 @@ -First day : 1, 2 fast, 3 and 4 up to constness + went through functors a first time - did together virtual inheritance exercise - skipped the others -Second day : went to the end of tools - did all exercises but all on the screen -Third day : the rest, with only 5mn of delay at the end - did more or ess the exercises on the screen (basically looking at the solution) diff --git a/notes/2018timing b/notes/2018timing deleted file mode 100644 index f9cfb1a8..00000000 --- a/notes/2018timing +++ /dev/null @@ -1,17 +0,0 @@ -Day 1 : - Started from start, fast on basics - Did no exercise (only looked at virtual inheritance one) - stopped after constness, but went through functors and templates a 1st time - -Day 2 : - Redid functors and templates - went through all tools - Did fully the exercise on templates - Did all exercises on tools except helgrind - -Day 3 : - C++11 and 14 in first half up to move semantic - Redid move semantic in 2nd half and finished C++11/14 - Then did python and finally C++17 - only 5mn late - No exercises whatsoever diff --git a/notes/2019Timing b/notes/2019Timing deleted file mode 100644 index ed0e5271..00000000 --- a/notes/2019Timing +++ /dev/null @@ -1,14 +0,0 @@ -Day 1 : - pause after 1:40 before static members in OO - stopped at end of More C++ features (after move and copy elision) - -Day 2 : - repeated move semantic and started tools up to debugging. Did advanced OO up to pure virtual methods then pause - end of advanced OO, operators, templates (and exercise), STL, functors - -Day 3 : - repeated functors and templates quickly, finished advanced C++ - valgrind and cppcheck exercise (minus helgrind), python and concurrency (minus condition variables) - -Corrections : - slide 188 diff --git a/notes/2020Timing b/notes/2020Timing deleted file mode 100644 index c2cd5271..00000000 --- a/notes/2020Timing +++ /dev/null @@ -1,13 +0,0 @@ -Day 1 : - pause after 1:20 before starting Object Orientation - stopped after constness - -Day 2 (on video conference) : - quick recap (15 mn) of course 1 - pause after advanced OO - Then tools until callgrind (included) - -Day 3 (on video conference) : - static code analysis (helgrind was skipped) - pause after templates, before STL - finished advanced C++ and did C++ and python From b6a007f839024a41c8ec4f8a13ddb7df8c3aa7df Mon Sep 17 00:00:00 2001 From: Stefan Roiser Date: Wed, 20 Jul 2022 11:00:20 +0200 Subject: [PATCH 04/14] remove talk --- talk/C++Course.tex | 137 - talk/CERN-logo.jpg | Bin 32146 -> 0 bytes talk/Makefile | 19 - talk/basicconcepts/arrayspointers.tex | 111 - talk/basicconcepts/auto.tex | 39 - talk/basicconcepts/basicconcepts.tex | 13 - talk/basicconcepts/classenum.tex | 222 - talk/basicconcepts/control.tex | 284 -- talk/basicconcepts/coresyntax.tex | 163 - talk/basicconcepts/functions.tex | 279 -- talk/basicconcepts/headersinterfaces.tex | 75 - talk/basicconcepts/inline.tex | 81 - talk/basicconcepts/operators.tex | 68 - talk/basicconcepts/references.tex | 52 - talk/basicconcepts/scopesnamespaces.tex | 179 - talk/concurrency/atomic.tex | 99 - talk/concurrency/concurrency.tex | 6 - talk/concurrency/condition.tex | 114 - talk/concurrency/mutexes.tex | 220 - talk/concurrency/threadsasync.tex | 127 - talk/expert/cpp20concepts.tex | 250 - talk/expert/cpp20spaceship.tex | 232 - talk/expert/expert.tex | 7 - talk/expert/perfectforwarding.tex | 248 - talk/expert/sfinae.tex | 287 -- talk/expert/variadictemplate.tex | 88 - talk/introduction/BjarneStroustrup.jpg | Bin 41547 -> 0 bytes talk/introduction/goals.tex | 28 - talk/introduction/history.tex | 117 - talk/introduction/introduction.tex | 4 - talk/introduction/ritchie.jpeg | Bin 10180 -> 0 bytes talk/morelanguage/AtlasLego.jpg | Bin 591305 -> 0 bytes talk/morelanguage/constexpr.tex | 116 - talk/morelanguage/constness.tex | 104 - talk/morelanguage/copyelision.tex | 42 - talk/morelanguage/exceptions.tex | 247 - talk/morelanguage/lambda.tex | 302 -- talk/morelanguage/morelanguage.tex | 12 - talk/morelanguage/morestl.tex | 208 - talk/morelanguage/move.tex | 259 - talk/morelanguage/raii.tex | 274 -- talk/morelanguage/stl.tex | 321 -- talk/morelanguage/templates.tex | 185 - talk/objectorientation/adl.tex | 146 - talk/objectorientation/advancedoo.tex | 509 -- talk/objectorientation/allocations.tex | 128 - talk/objectorientation/constructors.tex | 342 -- talk/objectorientation/functors.tex | 49 - talk/objectorientation/inheritance.tex | 294 -- talk/objectorientation/objectorientation.tex | 12 - talk/objectorientation/objectsclasses.tex | 151 - talk/objectorientation/operators.tex | 100 - talk/objectorientation/static.tex | 23 - talk/objectorientation/typecasting.tex | 66 - talk/python/cppyy.png | Bin 290496 -> 0 bytes talk/python/cppyy.tex | 33 - talk/python/cppyy2.png | Bin 104561 -> 0 bytes talk/python/ctypes.tex | 55 - talk/python/marryingcandcpp.tex | 80 - talk/python/modulewriting.tex | 69 - talk/python/python.tex | 6 - talk/setup.tex | 284 -- talk/tikz-uml.sty | 4429 ------------------ talk/tools/compiling.tex | 174 - talk/tools/debugging.tex | 71 - talk/tools/editors.tex | 29 - talk/tools/formatting.tex | 40 - talk/tools/profiling.tex | 42 - talk/tools/sanitizers.tex | 212 - talk/tools/staticanalysis.tex | 109 - talk/tools/tools.tex | 11 - talk/tools/valgrind.tex | 138 - talk/tools/vcs.tex | 49 - talk/vscode-tricks.txt | 11 - 74 files changed, 13281 deletions(-) delete mode 100644 talk/C++Course.tex delete mode 100644 talk/CERN-logo.jpg delete mode 100644 talk/Makefile delete mode 100644 talk/basicconcepts/arrayspointers.tex delete mode 100644 talk/basicconcepts/auto.tex delete mode 100644 talk/basicconcepts/basicconcepts.tex delete mode 100644 talk/basicconcepts/classenum.tex delete mode 100644 talk/basicconcepts/control.tex delete mode 100644 talk/basicconcepts/coresyntax.tex delete mode 100644 talk/basicconcepts/functions.tex delete mode 100644 talk/basicconcepts/headersinterfaces.tex delete mode 100644 talk/basicconcepts/inline.tex delete mode 100644 talk/basicconcepts/operators.tex delete mode 100644 talk/basicconcepts/references.tex delete mode 100644 talk/basicconcepts/scopesnamespaces.tex delete mode 100644 talk/concurrency/atomic.tex delete mode 100644 talk/concurrency/concurrency.tex delete mode 100644 talk/concurrency/condition.tex delete mode 100644 talk/concurrency/mutexes.tex delete mode 100644 talk/concurrency/threadsasync.tex delete mode 100644 talk/expert/cpp20concepts.tex delete mode 100644 talk/expert/cpp20spaceship.tex delete mode 100644 talk/expert/expert.tex delete mode 100644 talk/expert/perfectforwarding.tex delete mode 100644 talk/expert/sfinae.tex delete mode 100644 talk/expert/variadictemplate.tex delete mode 100644 talk/introduction/BjarneStroustrup.jpg delete mode 100644 talk/introduction/goals.tex delete mode 100644 talk/introduction/history.tex delete mode 100644 talk/introduction/introduction.tex delete mode 100644 talk/introduction/ritchie.jpeg delete mode 100644 talk/morelanguage/AtlasLego.jpg delete mode 100644 talk/morelanguage/constexpr.tex delete mode 100644 talk/morelanguage/constness.tex delete mode 100644 talk/morelanguage/copyelision.tex delete mode 100644 talk/morelanguage/exceptions.tex delete mode 100644 talk/morelanguage/lambda.tex delete mode 100644 talk/morelanguage/morelanguage.tex delete mode 100644 talk/morelanguage/morestl.tex delete mode 100644 talk/morelanguage/move.tex delete mode 100644 talk/morelanguage/raii.tex delete mode 100644 talk/morelanguage/stl.tex delete mode 100644 talk/morelanguage/templates.tex delete mode 100644 talk/objectorientation/adl.tex delete mode 100644 talk/objectorientation/advancedoo.tex delete mode 100644 talk/objectorientation/allocations.tex delete mode 100644 talk/objectorientation/constructors.tex delete mode 100644 talk/objectorientation/functors.tex delete mode 100644 talk/objectorientation/inheritance.tex delete mode 100644 talk/objectorientation/objectorientation.tex delete mode 100644 talk/objectorientation/objectsclasses.tex delete mode 100644 talk/objectorientation/operators.tex delete mode 100644 talk/objectorientation/static.tex delete mode 100644 talk/objectorientation/typecasting.tex delete mode 100644 talk/python/cppyy.png delete mode 100644 talk/python/cppyy.tex delete mode 100644 talk/python/cppyy2.png delete mode 100644 talk/python/ctypes.tex delete mode 100644 talk/python/marryingcandcpp.tex delete mode 100644 talk/python/modulewriting.tex delete mode 100644 talk/python/python.tex delete mode 100644 talk/setup.tex delete mode 100644 talk/tikz-uml.sty delete mode 100644 talk/tools/compiling.tex delete mode 100644 talk/tools/debugging.tex delete mode 100644 talk/tools/editors.tex delete mode 100644 talk/tools/formatting.tex delete mode 100644 talk/tools/profiling.tex delete mode 100644 talk/tools/sanitizers.tex delete mode 100644 talk/tools/staticanalysis.tex delete mode 100644 talk/tools/tools.tex delete mode 100644 talk/tools/valgrind.tex delete mode 100644 talk/tools/vcs.tex delete mode 100644 talk/vscode-tricks.txt diff --git a/talk/C++Course.tex b/talk/C++Course.tex deleted file mode 100644 index b6a45fb3..00000000 --- a/talk/C++Course.tex +++ /dev/null @@ -1,137 +0,0 @@ -\documentclass[compress]{beamer} -\usetheme{Warsaw} -\useoutertheme{split} - -\input{setup} - -\newboolean{onlybasics} -\setboolean{onlybasics}{false} -\IfFileExists{onlybasics.tex}{\input{onlybasics}}{} - -\begin{document} - -\showboxdepth=\maxdimen -\showboxbreadth=\maxdimen - -\begin{frame} - \titlepage -\end{frame} - -\begin{frame} - \frametitle{Foreword} - \begin{block}{What this course is not} - \begin{itemize} - \item It is not for absolute beginners - \item It is not for experts - \item It is not complete at all (would need 3 weeks...) - \begin{itemize} - \item although is it already too long for the time we have - \item \inserttotalframenumber{} slides, \insertpresentationendpage{} pages, 10s of exercises... - \end{itemize} - \end{itemize} - \end{block} - \begin{block}{How I see it} - \begin{description} - \item[Adaptative] pick what you want - \item[Interactive] tell me what to skip/insist on - \item[Practical] let's spend time on real code - \end{description} - \end{block} - \begin{block}{Where to find latest version ?} - \begin{itemize} - \item pdf format at {\small \url{http://cern.ch/sponce/C++Course}} - \item full sources at {\scriptsize \url{https://github.com/hsf-training/cpluspluscourse}} - \end{itemize} - \end{block} -\end{frame} - - -\begin{frame} - \frametitle{More courses} - \begin{block}{The HSF Software Training Center} - A set of course modules on more software engineering aspects prepared from within the HEP community - \begin{itemize} - \item Unix shell - \item Python - \item Version control (git, gitlab, github) - \item ... - \end{itemize} - {\small \url{https://hepsoftwarefoundation.org/training/curriculum.html}} - \end{block} - -\end{frame} - -\begin{frame} - \frametitle{Outline} - \begin{multicols}{2} - \tableofcontents[sectionstyle=show,subsectionstyle=hide] - \end{multicols} -\end{frame} - -\begin{frame} - \frametitle{Detailed outline} - %\vspace{-0.5cm} - \begin{scriptsize} - \begin{multicols}{3} - \tableofcontents[sectionstyle=show,subsectionstyle=show] - \end{multicols} - \end{scriptsize} -\end{frame} - -\include{introduction/introduction} -\include{basicconcepts/basicconcepts} - -% basic version has subset of tools at this stage -\ifthenelse{\boolean{onlybasics}}{ - \section[Tool]{Useful tools} - \input{tools/editors} - \input{tools/vcs} - \input{tools/formatting} - \input{tools/compiling} - \input{tools/debugging} -}{} - -% basic version only keeps a subset of these 2 chapters -\ifthenelse{\boolean{onlybasics}}{ - \section[OO]{Object orientation (OO)} - \input{objectorientation/objectsclasses} - \input{objectorientation/inheritance} - \input{objectorientation/constructors} - \input{objectorientation/static} - \input{objectorientation/allocations} - \input{objectorientation/advancedoo} - \input{objectorientation/typecasting} - \input{objectorientation/operators} - \input{objectorientation/functors} - - \section[More]{Core modern \cpp} - \input{morelanguage/constness} - \input{morelanguage/exceptions} - \input{morelanguage/templates} - \input{morelanguage/stl} - \input{morelanguage/lambda} - \input{morelanguage/raii} -} { - \include{objectorientation/objectorientation} - \include{morelanguage/morelanguage} -} - -% do not include these chapters in basic version -\ifthenelse{\boolean{onlybasics}}{}{ - \include{expert/expert} - \include{tools/tools} - \include{concurrency/concurrency} - \include{python/python} -} - -\begin{frame} - \frametitle{This is the end} - \begin{center} - \Huge Questions ?\\ - \vspace{.5cm} - \tiny \href{https://github.com/hsf-training/cpluspluscourse}{https://github.com/hsf-training/cpluspluscourse}\\ - \tiny \href{http://cern.ch/sponce/C++Course}{http://cern.ch/sponce/C++Course} - \end{center} -\end{frame} - -\end{document} diff --git a/talk/CERN-logo.jpg b/talk/CERN-logo.jpg deleted file mode 100644 index c241dfafbe2da82ecbc90e81efaa9870de85bbab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32146 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