├── .gitignore ├── README.md ├── exam_questions ├── cpp.md ├── python.md └── rules.txt ├── examples ├── arrays.cpp ├── control_flow.cpp ├── errors │ ├── c_err.cpp │ ├── include │ │ └── ap_error.hpp │ ├── try.cpp │ ├── try2.cpp │ ├── try3.cpp │ ├── try4.cpp │ ├── try5.cpp │ └── try6.cpp ├── files.cpp ├── functions1.cpp ├── functions2.cpp ├── hello_again │ ├── Makefile │ ├── Makefile2 │ ├── include │ │ └── hello.hpp │ ├── main.cpp │ └── src │ │ └── hello.cpp ├── hello_world.cpp ├── inheritance │ ├── basic.cpp │ ├── multi.cpp │ ├── polym.cpp │ ├── templ.cpp │ └── virtual_dctor.cpp ├── interactive.cpp ├── lambdas │ └── lambdas.cpp ├── limits.cpp ├── matrix_cblas.cpp ├── memory │ ├── new.cpp │ ├── new2.cpp │ ├── new3.cpp │ ├── new4.cpp │ ├── new5.cpp │ ├── unique.cpp │ └── unique2.cpp ├── my_first_class.cpp ├── my_first_class2.cpp ├── operators1.cpp ├── operators2.cpp ├── params1.cpp ├── params2.cpp ├── pointers1.cpp ├── pointers2.cpp ├── sfml │ ├── basic.cpp │ ├── life.cpp │ └── sfml.md ├── sstreams │ ├── cppstring.cpp │ ├── cstrings.cpp │ ├── input.cpp │ ├── print.cpp │ ├── split.cpp │ ├── stringstreams.cpp │ └── test.txt ├── templates │ ├── class_templates.cpp │ ├── function_templates.cpp │ ├── non_type.cpp │ ├── special.cpp │ └── variadic.cpp ├── timings │ ├── simple_timer.cpp │ ├── test_timings.cpp │ └── timer.cpp ├── types.cpp ├── variables.cpp └── vectors.cpp ├── extra_exercises ├── assignment2_cpp.md ├── assignment_cpp.md ├── eqn.PNG ├── gnuplot_example_for_jacobi.jp ├── jacobi.gif ├── jacobiEq1.jpg ├── jacobiFigure1.jpg └── list2.png ├── file.txt ├── hello_world.pdf ├── lecture_notes ├── Lecture_notes1.md ├── Lecture_notes2.md ├── Lecture_notes3.md ├── Lecture_notes4.md ├── Lecture_notes5.md ├── Lecture_notes6.md ├── Lecture_notes7.md ├── bonus │ └── DataFrame.md ├── git.md └── pictures │ ├── final.jpg │ ├── fire.png │ ├── git_cartoon.png │ └── git_commit.png ├── python ├── Exercises1.ipynb ├── Exercises2.ipynb ├── Exercises3.ipynb ├── Exercises4.ipynb ├── Exercises5.ipynb ├── Exercises6.ipynb ├── Lecture1.ipynb ├── Lecture2.ipynb ├── Lecture3.ipynb ├── Lecture4.ipynb ├── Lecture5.ipynb ├── Lecture6.ipynb ├── anim.py ├── cars.csv ├── conda.md ├── example.csv ├── example_empty.csv ├── pybind11 │ ├── matrix_cpp.cpp │ ├── matrix_cpp.hpp │ └── pybind11.ipynb ├── python_exam_questions.md ├── shapes.cpp └── solutions1.ipynb └── solutions ├── extra ├── jacobi │ ├── gif.gp │ ├── include │ │ ├── mesh.hpp │ │ └── solver.hpp │ ├── jacobi.gif │ └── main.cpp └── linked_list │ ├── include │ └── list.hpp │ └── main.cpp ├── lecture1 ├── convert.cpp ├── root.cpp ├── sort.cpp └── square.cpp ├── lecture2 ├── eq1.cpp ├── eq2.cpp └── resursive.cpp ├── lecture3 ├── complex.cpp └── equation │ ├── Makefile │ ├── include │ ├── coeffs.hpp │ └── eq.hpp │ ├── main.cpp │ └── src │ ├── coeffs.cpp │ └── eq.cpp ├── lecture4 ├── A.txt ├── B.txt ├── C.txt ├── complex.cpp ├── equation │ ├── include │ │ ├── coeffs.hpp │ │ └── eq.hpp │ └── main.cpp ├── matrix.cpp └── sum.cpp ├── lecture5 ├── A.txt ├── B.txt ├── matrix_raw.cpp └── matrix_smart.cpp └── lecture6 └── shapes.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.x 2 | *.o 3 | *.kdev4 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advanced Programming 2022 2 | 3 | The course will cover c++(17) topics from basics to advanced, python3 and how to combine the two. 4 | 5 | ### references: 6 | - [Programming -- Principles and Practice using C++ (Second Edition), Bjarne Stroustrup ](https://www.stroustrup.com/programming.html) 7 | - [A Tour of C++, Bjarne Stroustrup](https://www.stroustrup.com/Tour.html) 8 | - [Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) 9 | - [learncpp.com](https://www.learncpp.com/) 10 | 11 | 12 | ### some info: 13 | - exam dates are not yet set, but Winter Session is probably in February 14 | - exam format is probably written (with questions similar/identical to "test yourself" sections and code snippets similar to homework) 15 | - contact information (email, zoom and unofficial discord) are in Moodle (access from units, sissa or ict emails) 16 | - video recordings probably on moodle as well 17 | - exercise discussions will be at the last part of every lecture 18 | - **homework will not be checked, but you absolutely have to do it if you hope to learn anything** 19 | - questions through email/discord are welcome, but might take time to answer, try to ask them at breaks/exercise sessions (help each other through discord is also encouraged, I will moderate the discussion to make sure nothing wrong is being said) 20 | 21 | ### Dates and rooms: 22 | 23 | Martedì 04/10 – Aula 128-129 24 | 25 | - hello world 26 | - variable types, keywords 27 | - control flow 28 | - first intro to classes 29 | 30 | Giovedì 06/10 – Aula 128-129 31 | 32 | - functions 33 | - references and pointers 34 | - class member functions and constructors 35 | - review of last homework 36 | - survival crush course on git 37 | 38 | Martedì 11/10 – cancelled 39 | 40 | Giovedì 13/10 – cancelled 41 | 42 | Martedì 18/10 – zoom 43 | 44 | - general program structure 45 | - Makefiles 46 | - operator overloads 47 | - working with text files 48 | 49 | Giovedì 20/10 – zoom 50 | 51 | - templates: functions, classes, specialization 52 | - std::array and std::vector 53 | 54 | Martedì 25/10 – Aula 128-129 55 | 56 | - memory menagement 57 | - smart pointers 58 | - copy constructors and assignment operators 59 | 60 | Giovedì 27/10 – Aula 128-129 61 | 62 | - exercise session 63 | 64 | Martedì 01/11 – Festa 65 | 66 | Giovedì 03/11 – Festa 67 | 68 | Martedì 08/11 – Aula 128-129 69 | 70 | - inheritance 71 | - dynamic polymorphism 72 | 73 | Giovedì 10/11 – Aula 128-129 74 | 75 | - exercise session 76 | 77 | Martedì 15/11 – Aula 004 78 | 79 | - lambda functions 80 | - strings/streams 81 | - various topics: timing, command line parameters 82 | 83 | Giovedì 17/11 – Aula 128-129 84 | 85 | - exercise session 86 | 87 | Martedì 22/11 – Aula 004 88 | 89 | - introduction to python: 90 | - conda, jyputer 91 | - variables, types, lists, control flow 92 | - functions 93 | 94 | Giovedì 24/11 – Aula 005 95 | 96 | Martedì 29/11 – Aula 128-129 97 | 98 | Giovedì 01/12 – Aula 128-129 99 | 100 | Martedì 06/12 – AULA 139 101 | 102 | Giovedì 08/12 – Festa 103 | 104 | Martedì 13/12 – Aula 128-129 105 | 106 | Giovedì 15/12 – Aula 128-129 107 | 108 | Martedì 20/12 – Aula 128-129 109 | 110 | Giovedì 22/12 – Aula 128-129 -------------------------------------------------------------------------------- /exam_questions/cpp.md: -------------------------------------------------------------------------------- 1 | 1. name at least 5 variable types in c++ 2 | 2. what is "int overflow"? 3 | 3. why `using namespace std` might not be a good idea? 4 | 4. which header do you have to include for the access to std::cout? 5 | 5. what would be the simplest "legal" program in c++? 6 | 6. what is the difference in c++ between `struct` and `class`? 7 | 7. what does `break` statement do in a loop in c++? 8 | 8. what does `continue` statement do in a loop? 9 | 9. how do you define a static array of type int and size 7? 10 | 10. what can you use to read interactive user input? 11 | 11. What is a reference? 12 | 12. What is a difference between passing variables to functions by reference and by value? 13 | 13. Why do we want to pass variables to functions by reference rather than by pointer? 14 | 14. If the function accepts pointers (signature `int function(int* a)`), how do you pass a variable defined as `int x` to it? 15 | 15. Why do we want to use `const` modifier whenever possible? 16 | 16. If you have a pointer named `p`, how do you access a value it points to? What is the name of that process? 17 | 17. What value is stored in the pointer variable itself? 18 | 18. What can you say about a function that has signature `void function()`? 19 | 19. What is an `auto` keyword? 20 | 20. What is function overloading? 21 | 21. What is a recursive function? 22 | 22. What is the role of a constructor in a class? 23 | 23. How can we change private member variables of a class? 24 | 24. How do you create an object file with `g++`? 25 | 25. Why can't you just have eveything in one file? 26 | 26. What is the purpose of a "header guard"? 27 | 27. What does `-IFOLDER_NAME` mean when passed to `g++`? 28 | 28. Do tabs matter in a `Makefile`? 29 | 29. What does `$@` mean in a `Makefile`? 30 | 30. What does `$^` mean in a `Makefile`? 31 | 31. How to use `make` with a makefile that is not named `Makefile`? 32 | 32. What does it mean if a function is a friend of a class? 33 | 33. Why should non-class member operators be friends of classes? 34 | 34. Which header do you need to include to work with files? 35 | 35. How do you open a file in append mode? 36 | 36. how do you allocate a dynamic array in C++? 37 | 37. whats the difference between `delete` and `delete[]`? 38 | 38. when do you need to overload assignment operator for your class? 39 | 39. when do you need to create a copy constructor for your class? 40 | 40. when do you need to create a move constructor for your class? 41 | 41. what should you do if your class allocates resources, but you are sure you will never need a copy constructor? 42 | 42. what are protected class members? 43 | 43. what are virtual functions? 44 | 44. what is an abstract class? 45 | 45. explain dynamic (runtime) polymorphism 46 | 46. why destructors should be made virtual? 47 | 47. what is this `[](){}()`? 48 | 48. what's the general structure of a lambda function? 49 | 49. what does "mutable" keyword do in a lambda function? 50 | 51 | -------------------------------------------------------------------------------- /exam_questions/python.md: -------------------------------------------------------------------------------- 1 | 1. How do you create markdown cell in Jupyter? (with keyboard commands) 2 | 3 | 2. How do you delete a cell in Jupyter (with keyboard command)? 4 | 5 | 3. How do you add a cell above the current one in Jupyter (with keyboard command)? 6 | 7 | 4. What advantage does conda environment provide over a system-wide installation of python? 8 | 9 | 5. What does it mean that variables are dynamically typed in python? 10 | 11 | 6. What's the difference between python and C/C++ integers? 12 | 13 | 7. Explain the difference between lists, sets and tuples in python. 14 | 15 | 8. What does negative index mean when accessing list elements? 16 | 17 | 9. How do you print the first N elements of a list? 18 | 19 | 10. How do you print every Nth element of a list? 20 | 21 | 11. How do you print the reverse list? 22 | 23 | 12. Give an example of a list comprehension. 24 | 25 | 13. Give an example of cell and line magic commands in Jupyter. 26 | 27 | 14. Write a "hello world" function in python (syntax errors are not ok in hello world even on paper). 28 | 29 | 15. What are keyword function arguments in python and what is their advantage? 30 | 31 | 16. Why shouldn't you do `from numpy import *`? 32 | 33 | 17. What is the advantage of using numpy arrays over lists? What are the dangers? 34 | 35 | 18. What's the most widely used package for plotting in python? 36 | 37 | 19. What's the purpose of `__str__` method in a python class? 38 | 39 | 20. What package can you use in python for symbolic calculations? 40 | 41 | 21. What are decorators? Write an example (minor syntax errors are ok here) 42 | 43 | 22. Name two ways of calling c++ code from python. 44 | 45 | 23. What is pandas? Name at least 5 functions from that package. 46 | 47 | -------------------------------------------------------------------------------- /exam_questions/rules.txt: -------------------------------------------------------------------------------- 1 | You will have to write the answers to all the questions. 2 | The time limit is 4 hours, but I expect that 3 will be absolutely enough for most people. 3 | In addition to the questions, there will be 15-20 wrong code snippets. 4 | In the wrong code, you just need to find the mistake and explain why it's wrong, correct code is not required to write. 5 | You can write explanations in English, Italian, French, Spanish or Russian if you want. Cursive is fine, but please make it readable. 6 | Questions requiring long explanations are worth more than those requiring a precise answer. 7 | Questions (within python and c++ sections) will come in random order to make it harder to cheat. 8 | You will be provided paper, but please bring your own NON red pens. 9 | The passing number of points has not been decided yet. 10 | 11 | -------------------------------------------------------------------------------- /examples/arrays.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | int N{5}; 5 | const int NN{5}; 6 | int arr[5]; 7 | int arr2[N];//THIS COMPILES, BUT IS VERY BAD, DON'T DO IT 8 | int arr3[NN]; 9 | 10 | for(int i=0;i 2 | 3 | int main(){ 4 | int x{5}, y{7}; 5 | //just to see how if looks and works 6 | if(x==3){ 7 | std::cout<<"yes, x is 3"<=3){break;} 44 | std::cout<< i <<" "; 45 | } 46 | std::cout< 2 | #include 3 | 4 | int main() { 5 | double d = std::sqrt(4); 6 | std::cout << d << " " << errno << std::endl; 7 | 8 | d = std::sqrt(-4); 9 | std::cout << d << " " << errno << std::endl; 10 | 11 | d = 0; 12 | 13 | errno = 0; 14 | 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/errors/try.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | class CMyException: public std::exception{ 7 | const char* what() const noexcept override{ 8 | return "My exception happened"; 9 | } 10 | }; 11 | 12 | int main(){ 13 | // throw 999; //if you don't catch it'll call std::terminate 14 | try{ 15 | throw 777; 16 | } 17 | catch (int excep){ 18 | std::cout << "Caught Exception " << excep << '\n'; 19 | } 20 | 21 | try{ 22 | throw CMyException(); 23 | 24 | }catch (std::exception& e){ 25 | std::cout << e.what() << std::endl; 26 | } 27 | 28 | try 29 | { 30 | double* myarray= new double[10000000000000000]; 31 | } 32 | catch (std::exception& e) 33 | { 34 | std::cout << "Standard exception: " << e.what() << std::endl; 35 | } 36 | 37 | return 0; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /examples/errors/try2.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | struct Negative_number {}; 6 | 7 | struct Bigger_than_expected {}; 8 | 9 | // implment a square root function that "deals with" negative 10 | // numbers. Moreover according to the logic of the program, d should 11 | // never be greater than 50 12 | double square_root(const double d) { 13 | // test the pre-conditions 14 | if (d < 0) 15 | throw Negative_number{}; 16 | if (d > 50) 17 | throw Bigger_than_expected{}; 18 | return std::sqrt(d); 19 | } 20 | 21 | 22 | int main() { 23 | try { 24 | std::cout << "please insert a number\n"; 25 | double number; 26 | std::cin >> number; 27 | auto d = square_root(number); 28 | std::cout << "square root of " << number << " is " << d << '\n'; 29 | return 0; 30 | } catch (const Negative_number) { 31 | std::cerr << "The square root of a negative number is a complex number.\n" 32 | "square_root() is " 33 | << "limited to handle positive double numbers.\n"; 34 | return 1; 35 | } catch (const Bigger_than_expected) { 36 | std::cerr << "The function square_root has been called with a parameter " 37 | "greater than 50.\n" 38 | << "This means there is a bug in the algorithm that generated " 39 | "this number.\n"; 40 | return 2; 41 | } catch (...) { 42 | std::cerr << "Unknown exception. Aborting.\n"; 43 | return 3; 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /examples/errors/try3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ap_error.hpp" 5 | 6 | struct Square_root_invalid : public std::exception { 7 | std::string message; 8 | Square_root_invalid(std::string s) : message{std::move(s)} {} 9 | const char* what() const noexcept override { return message.c_str(); } 10 | }; 11 | 12 | double square_root(const double d) { 13 | // test the pre-conditions 14 | 15 | AP_ERROR(d >= 0 && d <= 50, Square_root_invalid) 16 | << "In our library the argument must be positive and less or equal than " 17 | "50.\n\nYou passed " 18 | << d << ".\n"; 19 | 20 | // AP_ERROR(d >= 0 && d <= 50) << "In our library the argument must be 21 | // positive " 22 | // "and less or equal than 50.\n"; 23 | 24 | // AP_ERROR_GE(d, 0) << "Cannot handle negative numbers.\n"; 25 | 26 | // AP_ERROR_LE(d, 50) << "According to the implemented algorithm, the argument must be less than 50.\n"; 27 | 28 | // AP_ERROR_IN_RANGE(d,0,50); 29 | 30 | return sqrt(d); 31 | } 32 | 33 | 34 | int main() { 35 | try { 36 | // double* myarray= new double[10000000000000000]; 37 | 38 | std::cout << "please insert a number\n"; 39 | double number; 40 | std::cin >> number; 41 | double d = square_root(number); 42 | std::cout << "square root of " << number << " is " << d << '\n'; 43 | return 0; 44 | } catch (const std::exception& e) { 45 | std::cerr << e.what() << std::endl; 46 | return 1; 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /examples/errors/try4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ap_error.hpp" 6 | 7 | double square_root(const double d) { 8 | // test the pre-conditions 9 | //assert(d >= 0 && d <= 50); // provided by C, no execeptions 10 | 11 | //this can be turned off with -DNDEBUG 12 | AP_ASSERT(d >= 0 && d <= 50) << "d should be in the range [0,50]"; 13 | 14 | // AP_ASSERT_IN_RANGE(d,0,50); 15 | return sqrt(d); 16 | } 17 | 18 | int main() { 19 | try { 20 | std::cout << "please insert a number\n"; 21 | double number; 22 | std::cin >> number; 23 | double d = square_root(number); 24 | std::cout << "square root of " << number << " is " << d << '\n'; 25 | return 0; 26 | } catch (const std::exception& e) { 27 | std::cerr << e.what() << '\n'; 28 | return 1; 29 | } catch (...) { 30 | std::cerr << "Unknown exception. Aborting.\n"; 31 | return 3; 32 | } 33 | 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /examples/errors/try5.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "ap_error.hpp" 6 | 7 | class Foo { 8 | public: 9 | Foo() { std::cout << "Foo" << std::endl; } 10 | ~Foo() { std::cout << "~Foo" << std::endl; } 11 | }; 12 | 13 | class Bar { 14 | public: 15 | Bar() { std::cout << "Bar" << std::endl; } 16 | ~Bar() { std::cout << "~Bar" << std::endl; } 17 | }; 18 | 19 | class Vector { 20 | double* elem; 21 | 22 | public: 23 | Vector(const unsigned int l) : elem{new double[l]} { 24 | std::cout << "Vector" << std::endl; 25 | } 26 | ~Vector() { 27 | delete[] elem; 28 | std::cout << "~Vector" << std::endl; 29 | } 30 | }; 31 | 32 | class ManyResources { 33 | double* ptr; 34 | Vector v; 35 | 36 | public: 37 | ManyResources() : ptr{nullptr}, v{3} { 38 | std::cout << "Manyresources" << std::endl; 39 | try { 40 | ptr = new double[5]; 41 | AP_ERROR(false) << "Error in ManyResources ctor." << std::endl; 42 | } catch (...) { 43 | delete[] ptr; // <---- 44 | throw; // re-throw 45 | } 46 | } 47 | 48 | ~ManyResources() { 49 | std::cout << "~Manyresources" << std::endl; 50 | delete[] ptr; // <---- 51 | } 52 | }; 53 | 54 | int main() { 55 | Foo f; 56 | int* raw_ptr = new int[7]; // do not use raw ptr 57 | try { 58 | // int * raw_ptr=new int[7]; // wrong because raw_ptr would not be visible 59 | // inside the catch-clause 60 | ManyResources mr; 61 | Bar b; 62 | 63 | } catch (const std::exception& e) { 64 | std::cerr << e.what() << std::endl; 65 | 66 | delete[] raw_ptr; //comment and valgrind 67 | return 1; 68 | 69 | } catch (...) { 70 | std::cerr << "Unknown exception. Aborting.\n" << std::endl; 71 | 72 | delete[] raw_ptr; // <--- 73 | return 2; 74 | } 75 | 76 | delete[] raw_ptr; // <--- 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /examples/errors/try6.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "ap_error.hpp" 6 | 7 | class Vector { 8 | std::unique_ptr elem; 9 | 10 | public: 11 | Vector(const unsigned int l) : elem{new double[l]} {} 12 | 13 | Vector(Vector&&) noexcept = default; 14 | Vector& operator=(Vector&&) noexcept = default; 15 | 16 | double& operator[](const unsigned int i) noexcept { return elem[i]; } 17 | 18 | const double& operator[](const unsigned int i) const noexcept { 19 | return elem[i]; 20 | } 21 | 22 | ~Vector() noexcept { std::cout << "~Vector\n"; } 23 | }; 24 | 25 | class ManyResources { 26 | std::unique_ptr ptr; 27 | Vector v; 28 | 29 | public: 30 | ManyResources() : ptr{new double[5]}, v{3} { 31 | std::cout << "ManyResources ctor\n"; 32 | AP_ERROR(false) << "I am simulating something wrong.\n"; 33 | } 34 | ~ManyResources() noexcept { std::cout << "~ManyResources\n"; } 35 | }; 36 | 37 | int main() { 38 | try { 39 | std::unique_ptr up{new int[7]}; // RAII 40 | ManyResources mr; 41 | 42 | } catch (const std::exception& e) { 43 | std::cerr << e.what() << std::endl; 44 | return 1; 45 | 46 | } catch (...) { 47 | std::cerr << "Unknown exception. Aborting.\n" << std::endl; 48 | return 2; 49 | } 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /examples/files.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | //you can do the same things as with std::cout and std::cin 6 | 7 | //this will create "test.txt" if it doesn't exist or overwrite if it does 8 | std::ofstream filevar("test.txt"); 9 | //filvar.open("name.txt") 10 | filevar << "1 2 3"<> a >>b >>c; 18 | }else{ 19 | std::cout<<"failed opening the file"< 2 | 3 | //simple function example 4 | //it's just a syntax example, it's not optimal at all 5 | int add_two(int a){ 6 | return a+2; 7 | } 8 | 9 | //this will not change a 10 | void add_two_wrong(int a){ 11 | a=a+2; 12 | } 13 | 14 | //this will change a 15 | void add_two_ref(int& a){ 16 | a=a+2; 17 | } 18 | 19 | //same example as the first, but optimal 20 | //renamed to avoid ambiguity 21 | int add_two_best(const int& a){ 22 | return a+2; 23 | } 24 | 25 | //this will change a and b 26 | //can overload the function because the number of variables is different 27 | void add_two_ref(int&a, int&b){ 28 | a=a+2; 29 | b=b+2; 30 | } 31 | 32 | //this will change a and b 33 | //can overload the function because the type of variable is different 34 | void add_two_ref(double& a){ 35 | a=a+2; 36 | } 37 | 38 | //now let's look at c-style (don't use it unless interfacing with c libraries) 39 | //this will change a 40 | void add_two_p(int* a){ 41 | *a=*a+2; 42 | } 43 | 44 | 45 | int main(){ 46 | 47 | int a{2}; 48 | //"auto" keyword is very useful when you don't remember the type of the function 49 | //or when it is complicated 50 | auto b=add_two(a); 51 | std::cout<<" a is "< 2 | 3 | //a recursive function example 4 | long long int factorial(int N){ 5 | if(N==1){ 6 | return 1; 7 | }else{ 8 | return N*factorial(N-1); 9 | } 10 | } 11 | 12 | 13 | int main(){ 14 | 15 | auto f=factorial(5); 16 | std::cout< 2 | #include "hello.hpp" 3 | 4 | void hello(){ 5 | std::cout<<"Hello, World!"< 2 | 3 | int main(){ 4 | //printing on screen 5 | std::cout<<"Hello World!"< 2 | //the most basic example 3 | 4 | //base ("parent") class 5 | class Polygon { 6 | protected: 7 | int width, height; 8 | public: 9 | void set_values (int a, int b){ 10 | width=a; height=b; 11 | } 12 | }; 13 | 14 | //derived ("child") class 15 | class Rectangle: public Polygon { 16 | public: 17 | int area(){ 18 | return width*height; 19 | } 20 | }; 21 | 22 | class Triangle: public Polygon { 23 | public: 24 | int area(){ 25 | return width*height/2; 26 | } 27 | }; 28 | 29 | int main () { 30 | Rectangle rect; 31 | Triangle trgl; 32 | rect.set_values(4,5); 33 | trgl.set_values(4,5); 34 | //rect.height=10; //won't work with "protected" member 35 | std::cout << rect.area() << std::endl; 36 | std::cout << trgl.area() << std::endl; 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /examples/inheritance/multi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | //multiple inheritance example 3 | 4 | //one base class 5 | class Colour{ 6 | private: 7 | int r; 8 | int g; 9 | int b; 10 | public: 11 | Colour(){}; 12 | Colour(const int& r0, const int& g0, const int& b0):r(r0),g(g0),b(b0){}; 13 | void set_colour(const int& r0, const int& g0, const int& b0){ 14 | r=r0; g=g0; b=b0; 15 | } 16 | void print_colour(){ 17 | std::cout<< r<< " "< 2 | //examples of dynamic polymoprhism 3 | 4 | class Polygon { 5 | protected: 6 | int width, height; 7 | public: 8 | void set_values (int a, int b) 9 | { width=a; height=b; } 10 | virtual int area (){ return 0; } 11 | // virtual int area ()=0;//makes the class abstract, then you can't have an object of it 12 | //pure virtual functions must be overriden, otherwise the child class is also abstract 13 | }; 14 | 15 | class Rectangle: public Polygon { 16 | public: 17 | //override helps compiler and makes sure you don't type anything wrong 18 | int area() override{ 19 | return width * height; 20 | } 21 | }; 22 | 23 | class Triangle: public Polygon { 24 | public: 25 | int area() override{ 26 | return (width * height / 2); 27 | } 28 | }; 29 | 30 | int main () { 31 | Rectangle rect; 32 | Triangle trgl; 33 | Polygon poly; 34 | Polygon * ppoly1 = ▭ 35 | Polygon * ppoly2 = &trgl; 36 | Polygon * ppoly3 = &poly; 37 | ppoly1->set_values (4,5); 38 | ppoly2->set_values (4,5); 39 | ppoly3->set_values (4,5); 40 | std::cout << ppoly1->area() << std::endl; 41 | std::cout << ppoly2->area() << std::endl; 42 | std::cout << ppoly3->area() << std::endl; 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /examples/inheritance/templ.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class CBase1{ 5 | public: 6 | T field1; 7 | CBase1(const T& f0):field1(f0),field2{f0},field3(f0){}; 8 | ~CBase1(){std::cout<<"base1 dctor called"< 30 | class CDerived1:public CBase1, public CBase2{ 31 | public: 32 | T field4; 33 | CDerived1(const T& f0):CBase1(f0),CBase2(f0){ 34 | field4=f0; 35 | }; 36 | ~CDerived1(){std::cout<<"derived dctor called"<field1<<" "<field2<<" "< c(11); 48 | std::cout< 2 | //TL;DR: if destructor is not virtual, you risk leaking memory 3 | 4 | template 5 | class CBase1{ 6 | public: 7 | T field1; 8 | CBase1(const T& f0):field1(f0){}; 9 | // virtual 10 | ~CBase1(){std::cout<<"base dctor called"< 14 | class CDerived1:public CBase1{ 15 | public: 16 | T field2; 17 | T* arr; 18 | CDerived1(const T& f0):CBase1(f0){ 19 | field2=f0; 20 | arr=new int[10]; 21 | }; 22 | ~CDerived1(){free(arr); std::cout<<"derived dctor called"< c(11); 29 | // std::cout<* ptr=new CDerived1(7); 33 | //instead: 34 | CDerived1* c1 = new CDerived1(12); 35 | CBase1* ptr=c1; 36 | delete ptr; 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /examples/interactive.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | std::string name; 6 | int n{0}; 7 | int N[4]; 8 | std::cout<<"What is your name?"<> name; 10 | std::cout << "Hello, "<< name<< "! Whats is your favorite number?"<< std::endl; 11 | std::cin >>n; 12 | std::cout<< "The square of your favorite number is: "<> N[0] >> N[1] >> N[2] >> N[3]; 15 | std::cout << "your numbers are:" < 2 | #include 3 | #include 4 | #include 5 | 6 | //this is a functor 7 | //in fact, compiler will generate something like this for lambda functions 8 | struct Hi{ 9 | void operator()(){ 10 | std::cout<<"Hi!"< vec,vec2; 21 | vec.resize(10,0); 22 | vec2.resize(10,0); 23 | int count{0}; 24 | 25 | //this all are valid expressions that do nothing 26 | [](){}; 27 | []{}(); 28 | []{}; 29 | 30 | 31 | //actually, every lambda has it's own type, but you don't have to worry about that with auto 32 | auto addition = [](int x, int y)->double { return x + y; }; 33 | 34 | //capture by reference 35 | int a{0}; 36 | auto print_a = [&a]{std::cout<y;}); 69 | 70 | //for_each can be replaced by a range loop usually 71 | std::for_each(vec.begin(),vec.end(),[](int i){std::cout< 2 | #include // for std::numeric_limits 3 | 4 | int main () { 5 | //ignore unknown syntax for now 6 | std::cout << "Minimum value for int: " << std::numeric_limits::min() << std::endl; 7 | std::cout << "Maximum value for int: " << std::numeric_limits::max() << std::endl; 8 | std::cout << "Minimum value for long int: " << std::numeric_limits::min() << std::endl; 9 | std::cout << "Maximum value for long int: " << std::numeric_limits::max() << std::endl; 10 | std::cout << "Minimum value for double: " << std::numeric_limits::min() << std::endl; 11 | std::cout << "Maximum value for double: " << std::numeric_limits::max() << std::endl; 12 | std::cout << "Minimum value for float: " << std::numeric_limits::min() << std::endl; 13 | std::cout << "Maximum value for float: " << std::numeric_limits::max() << std::endl; 14 | 15 | int x{2147483647}; 16 | 17 | std::cout<<(x+10)< 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include //to call cblas_dgemm to compare results 11 | #include 12 | 13 | //compile with either -lblas or -lopenblas depending on what you have in your system 14 | //and -std=c++17 if you have an old compiler 15 | 16 | template 17 | class CMatrix { 18 | public: 19 | int size; 20 | std::vector data; 21 | CMatrix(int N){ 22 | size = N; 23 | data.resize(N*N); 24 | } 25 | CMatrix(){}; 26 | void print_to_file(const std::string& file); 27 | void read_from_file(const std::string& file); 28 | CMatrix operator*(const CMatrix& B); 29 | bool operator==(const CMatrix& B); 30 | void random_fill(); 31 | 32 | }; 33 | 34 | 35 | template 36 | void CMatrix::read_from_file(const std::string& file){ 37 | std::ifstream filevar(file); 38 | if(filevar){ 39 | filevar>>size; 40 | data.resize(size*size); 41 | for (int i=0;i>data[i*size+j]; 44 | } 45 | } 46 | filevar.close();} 47 | else{ 48 | std::cout<<"coudn't open the file "< 55 | void CMatrix::print_to_file(const std::string& file){ 56 | std::ofstream filevar(file); 57 | filevar< 68 | CMatrix CMatrix::operator*(const CMatrix& B){ 69 | if (size != B.size) { 70 | std::cout<<"The two matrices are not of the same size! The result will be nonsense."< C(size); 73 | for (int i=0;i 85 | bool CMatrix::operator==(const CMatrix& B){ 86 | //specializing the templates for ints and not ints 87 | if (std::is_integral_v == true) {//we are dealing with integers 88 | for (int i=0;i 1e-6 ) { 98 | return false; 99 | } 100 | } 101 | return true; 102 | } 103 | }//== 104 | 105 | template 106 | void CMatrix::random_fill(){ 107 | constexpr auto low_bound = 0; 108 | constexpr auto up_bound = 100; 109 | //take the seed from current time 110 | auto seed = std::chrono::system_clock::now().time_since_epoch().count(); 111 | std::default_random_engine dre(seed);//engine 112 | std::uniform_int_distribution di(low_bound,up_bound);//distribution 113 | std::generate(data.begin(), data.end(), [&](){ return di(dre);});//fill 114 | }; 115 | 116 | 117 | 118 | int main (int argc, char **argv){ 119 | int N=1000; 120 | CMatrix A(N),B(N); 121 | A.random_fill(); 122 | B.random_fill(); 123 | auto C=A*B; 124 | CMatrix C_blas(N); 125 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, N,N,N,1,&A.data[0],N,&B.data[0],N,0,&C_blas.data[0],N); 126 | //we can check that our multiplication was correct 127 | if (C == C_blas) { 128 | std::cout<< "it worked" < 2 | 3 | template 4 | class MyClass{ 5 | public: 6 | T* data; 7 | MyClass(){}; 8 | MyClass(const int& N); 9 | ~MyClass(); 10 | }; 11 | 12 | template 13 | MyClass::MyClass(const int& N) { 14 | data=new T[N]; 15 | for(int i=0;i 22 | MyClass::~MyClass() { 23 | delete[] data; 24 | data=nullptr; 25 | std::cout<<"destructor called"< obj(10); 41 | 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /examples/memory/new2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class CMyClass{ 5 | public: 6 | T* data; 7 | size_t size; 8 | CMyClass(const int& N); 9 | ~CMyClass(); 10 | void print(); 11 | // CMyClass& operator=(const CMyClass& p); 12 | 13 | }; 14 | 15 | template 16 | CMyClass::CMyClass(const int& N) { 17 | data=new T[N]; 18 | size=N; 19 | for(int i=0;i 27 | CMyClass::~CMyClass() { 28 | delete[] data; 29 | data=nullptr; 30 | std::cout<<"destructor called"< 35 | void CMyClass::print() { 36 | for(int i=0;i 43 | CMyClass& CMyClass::operator=(const CMyClass& p){ 44 | std::cout<<"assignment operator called"< obj(10); 71 | CMyClass obj2(10); 72 | 73 | obj2=obj; 74 | obj2.print(); 75 | 76 | return 0; 77 | } 78 | 79 | -------------------------------------------------------------------------------- /examples/memory/new3.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | template 5 | class CMyClass{ 6 | public: 7 | T* data; 8 | size_t size; 9 | CMyClass(const int& N); 10 | ~CMyClass(); 11 | void print(); 12 | // CMyClass& operator=(const CMyClass& p); 13 | CMyClass operator+(const CMyClass& p); 14 | 15 | }; 16 | 17 | template 18 | CMyClass::CMyClass(const int& N) { 19 | data=new T[N]; 20 | size=N; 21 | for(int i=0;i 29 | CMyClass::~CMyClass() { 30 | delete[] data; 31 | data=nullptr; 32 | std::cout<<"destructor called"< 37 | void CMyClass::print() { 38 | for(int i=0;i 46 | CMyClass& CMyClass::operator=(const CMyClass& p){ 47 | std::cout<<"assignment operator called"< 72 | CMyClass CMyClass::operator+ ( const CMyClass& p ) { 73 | std::cout<<"plus operator called"< result(size); 78 | for(int i=0;i obj(10); 88 | CMyClass obj2(10); 89 | //THIS ACTUALLY NEVER CALLS ASSIGNMENT OPERATOR! 90 | auto obj3=obj2+obj; 91 | obj3.print(); 92 | return 0; 93 | } 94 | 95 | -------------------------------------------------------------------------------- /examples/memory/new4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class CMyClass{ 5 | public: 6 | T* data; 7 | size_t size; 8 | CMyClass(const int& N); 9 | ~CMyClass(); 10 | void print(); 11 | CMyClass& operator=(const CMyClass& p); 12 | CMyClass operator+(const CMyClass& p); 13 | CMyClass(const CMyClass& p); 14 | 15 | }; 16 | 17 | template 18 | CMyClass::CMyClass(const int& N) { 19 | data=new T[N]; 20 | size=N; 21 | for(int i=0;i 29 | CMyClass::~CMyClass() { 30 | delete[] data; 31 | data=nullptr; 32 | std::cout<<"destructor called"< 37 | void CMyClass::print() { 38 | for(int i=0;i 46 | CMyClass& CMyClass::operator=(const CMyClass& p){ 47 | std::cout<<"assignment operator called"< 72 | CMyClass::CMyClass ( const CMyClass& p ) { 73 | std::cout<<"copy constructor called"< 96 | void a_function(CMyClass obj){ 97 | std::cout< 102 | CMyClass CMyClass::operator+ ( const CMyClass& p ) { 103 | std::cout<<"plus operator called"< result(size); 108 | for(int i=0;i obj(10); 118 | CMyClass obj2(10); 119 | //THIS ACTUALLY NEVER CALLS ASSIGNMENT OPERATOR! 120 | auto obj3=obj2+obj; 121 | obj3.print(); 122 | //will crash without a copy constructor 123 | a_function(obj); 124 | //another use of copy constructor 125 | CMyClass obj4(obj3); 126 | 127 | 128 | CMyClass obj5(obj3+obj2); 129 | return 0; 130 | } 131 | 132 | -------------------------------------------------------------------------------- /examples/memory/new5.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class CMyClass{ 5 | public: 6 | T* data; 7 | size_t size; 8 | CMyClass(const int& N); 9 | ~CMyClass(); 10 | void print(); 11 | CMyClass& operator=(const CMyClass& p); 12 | CMyClass& operator=(CMyClass&& p); 13 | CMyClass operator+(const CMyClass& p); 14 | CMyClass(const CMyClass& p); 15 | CMyClass(CMyClass&& p); 16 | 17 | }; 18 | 19 | template 20 | CMyClass::CMyClass(const int& N) { 21 | data=new T[N]; 22 | size=N; 23 | for(int i=0;i 31 | CMyClass::~CMyClass() { 32 | delete[] data; 33 | data=nullptr; 34 | std::cout<<"destructor called"< 39 | void CMyClass::print() { 40 | for(int i=0;i 48 | CMyClass& CMyClass::operator=(const CMyClass& p){ 49 | std::cout<<"assignment operator called"< 74 | CMyClass& CMyClass::operator=(CMyClass&& p){ 75 | std::cout<<"move assignment operator called"< 95 | CMyClass::CMyClass ( const CMyClass& p ) { 96 | std::cout<<"copy constructor called"< 115 | CMyClass::CMyClass ( CMyClass && p ) { 116 | std::cout<<"move constructor called"< 133 | void a_function(CMyClass obj){ 134 | std::cout< 139 | CMyClass CMyClass::operator+ ( const CMyClass& p ) { 140 | std::cout<<"plus operator called"< result(size); 145 | for(int i=0;i obj(10); 155 | CMyClass obj2(10); 156 | //THIS ACTUALLY NEVER CALLS ASSIGNMENT OPERATOR! 157 | auto obj3=obj2+obj; 158 | obj3.print(); 159 | //will crash without a copy constructor 160 | // a_function(obj); 161 | //another use of copy constructor 162 | // CMyClass obj4(obj3); 163 | 164 | //obj3 still exists, but assume it can't be used anymore 165 | auto obj5=std::move(obj3); 166 | 167 | obj5=std::move(obj2); 168 | 169 | return 0; 170 | } 171 | 172 | 173 | -------------------------------------------------------------------------------- /examples/memory/unique.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | void function(int* p){ 6 | std::cout< p(new int[5]); 12 | for(int i=0;i<5;i++){ 13 | p[i]=i; 14 | std::cout< 2 | #include 3 | 4 | template 5 | class CMyClass{ 6 | public: 7 | std::unique_ptr data; 8 | size_t size; 9 | CMyClass(const int& N); 10 | void print(); 11 | CMyClass& operator=(const CMyClass& p); 12 | CMyClass& operator=(CMyClass&& p); 13 | CMyClass operator+(const CMyClass& p); 14 | CMyClass(const CMyClass& p); 15 | CMyClass(CMyClass&& p); 16 | 17 | }; 18 | 19 | template 20 | CMyClass::CMyClass(const int& N) { 21 | //instead of new 22 | data=std::make_unique(N); 23 | size=N; 24 | for(int i=0;i 33 | void CMyClass::print() { 34 | for(int i=0;i 42 | CMyClass& CMyClass::operator=(const CMyClass& p){ 43 | std::cout<<"assignment operator called"< 58 | CMyClass& CMyClass::operator=(CMyClass&& p){ 59 | std::cout<<"move assignment operator called"< 72 | CMyClass::CMyClass ( const CMyClass& p ) { 73 | std::cout<<"copy constructor called"< 89 | CMyClass::CMyClass ( CMyClass && p ) { 90 | std::cout<<"move constructor called"< 106 | void a_function(CMyClass obj){ 107 | std::cout< 112 | CMyClass CMyClass::operator+ ( const CMyClass& p ) { 113 | std::cout<<"plus operator called"< result(size); 118 | for(int i=0;i obj(10); 128 | CMyClass obj2(10); 129 | //THIS ACTUALLY NEVER CALLS ASSIGNMENT OPERATOR! 130 | auto obj3=obj2+obj; 131 | obj2.print(); 132 | 133 | //will crash without a copy constructor 134 | a_function(obj); 135 | //another use of copy constructor 136 | CMyClass obj4(obj3); 137 | 138 | //obj3 still exists, but assume it can't be used anymore 139 | auto obj5=std::move(obj); 140 | 141 | obj5=std::move(obj2); 142 | obj5.print(); 143 | return 0; 144 | } 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /examples/my_first_class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //despite the name and the look this is NOT the struct from C, it's the same as "class" 4 | //but with default "public" visibility of class fields. 5 | struct CCoords{ 6 | double x; 7 | double y; 8 | }; 9 | 10 | //by default all variables are private 11 | class CAnotherCoords{ 12 | public: 13 | double x; 14 | double y; 15 | }; 16 | 17 | int main(){ 18 | CCoords var; 19 | CAnotherCoords var2; 20 | var.x=2; 21 | var.y=3; 22 | var2.x=2; 23 | var2.y=3; 24 | std::cout<< var.x << " " << var.y< 2 | 3 | class CCoords{ 4 | double x; 5 | double y; 6 | public: 7 | //default constructor 8 | CCoords(){ 9 | x=0;y=0; 10 | } 11 | //constructor with a parameter 12 | //a different syntax with the initializer list 13 | //it's "just a syntax" here, but can be important when member variable is also of some class type 14 | //pay attention to the initialization order! 15 | CCoords(double x1, double y1):x(x1),y(y1){ 16 | } 17 | //only need the declaration here 18 | void print(); 19 | //try to implement them yourself! 20 | auto getx();//this is c++14 standard 21 | auto gety(); 22 | void setx(); 23 | void sety(); 24 | }; 25 | 26 | void CCoords::print() { 27 | std::cout< 2 | #include 3 | 4 | //example of overloading arithmetic operators 5 | 6 | class CCoords{ 7 | double x; 8 | double y; 9 | public: 10 | CCoords(){ 11 | x=0;y=0; 12 | } 13 | CCoords(const double& x0,const double& y0):x(x0),y(y0){} 14 | CCoords operator+(const CCoords& b) { 15 | CCoords result; 16 | result.x = x + b.x; 17 | result.y = y + b.y; 18 | return result; 19 | }//operator+ 20 | /* //this is a wrong way, as it becomes non-commutative 21 | CCoords operator+(const int& b) { 22 | CCoords result; 23 | result.x = x + b; 24 | result.y = y + b; 25 | return result; 26 | }//operator+ 27 | */ 28 | friend CCoords operator+(const CCoords& c, const int& b); 29 | friend CCoords operator+(const int& b, const CCoords& c); 30 | 31 | //have to assume it can be non-integer 32 | bool operator==(const CCoords& b) { 33 | bool result{false}; 34 | if ((std::fabs(x-b.x)<10e-9) && (std::fabs(y-b.y)<10e-9)){ 35 | result=true; 36 | } 37 | return result; 38 | }//operator== 39 | void print(){ 40 | std::cout<<"x is "< 2 | #include 3 | 4 | struct CCoords{ 5 | double x; 6 | double y; 7 | CCoords(){ x=0;y=0; } 8 | CCoords operator+(const CCoords& b); 9 | bool operator==(const CCoords& b); 10 | 11 | //instead of a print function we can overload << 12 | //get a habit to make it a friend in case you change to proper private values 13 | friend std::ostream& operator<<(std::ostream& os, const CCoords& c); 14 | //a totally nonsense overload just to show that we can 15 | void operator[](const int& N){ 16 | std::cout<<"What did you intend to do with calling [] on coordinates?..."< 2 | 3 | 4 | int main( int argc, char *argv[] ){ 5 | //argc - number of command line input parameters 6 | //argv - contains the parameters 7 | 8 | //you can check if the user forgot to pass an expected parameter: 9 | if (argc<2){ 10 | std::cout<<"USAGE: "< 2 | #include 3 | #include 4 | 5 | //play around with this file and see what passing different "wrong" things does 6 | 7 | int main(int argc, char * const argv[]) { 8 | 9 | //c-style way to parse parameters 10 | //they should be passed like "-a 1 -b 9" 11 | int a{0}, b{0}, c{0}, d{0}; 12 | int res{0}; 13 | while( (res = getopt(argc, argv, "a:b:c:d:") ) != -1 ) { 14 | switch(res){ 15 | case 'a': 16 | a = std::atoi(optarg); 17 | break; 18 | case 'b': 19 | b = std::atoi(optarg) ; 20 | break; 21 | case 'c': 22 | c = std::atoi(optarg) ; 23 | break; 24 | case 'd': 25 | d = std::atoi(optarg) ; 26 | break; 27 | }//switch 28 | }//while 29 | 30 | 31 | std::cout<< "a: " < 2 | //look at this file until you understand everything 3 | //it's very important 4 | 5 | 6 | void add_two(int& a){ 7 | std::cout<<"function with reference was called" < 2 | 3 | //passing arrays to a function 4 | void print_array(int* arr, const int N){ 5 | //accessing "normally" 6 | for(int i=0;i 2 | 3 | int main(){ 4 | sf::RenderWindow window(sf::VideoMode(700, 700), "Hello, World!"); 5 | sf::CircleShape shape(200.f); 6 | shape.setFillColor(sf::Color::Green); 7 | //this is how most games are run, it's an infinite "while" loop 8 | while (window.isOpen()){ 9 | sf::Event event; 10 | while (window.pollEvent(event)){ 11 | //without this, the window won't react to close button 12 | if (event.type == sf::Event::Closed){ 13 | window.close(); 14 | } 15 | //an example of keyboard interaction 16 | if (event.type == sf::Event::KeyPressed){ 17 | switch (event.key.code){ 18 | case sf::Keyboard::Q: 19 | window.close(); 20 | break; 21 | }//switch 22 | }//if keypressed 23 | }//while poll event 24 | 25 | window.clear(); 26 | window.draw(shape); 27 | window.display(); 28 | 29 | }//main game loop 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /examples/sfml/life.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | //this is an example file, where everything is in one file for "historical" reasons 8 | //please don't write your programs like that, create a normal code structure with headers 9 | 10 | //flags to compile: 11 | //g++ -lsfml-window -lsfml-graphics -lsfml-system 12 | 13 | 14 | class CGrid: public sf::Drawable{ 15 | public: 16 | std::vector field; //remember that you can't use vector for an MPI version 17 | std::vector old_field; 18 | float step; 19 | int N_x; 20 | int N_y; 21 | mutable sf::RectangleShape dead; //inherited draw is const and complains about trying to modify, mutable negates that! 22 | mutable sf::RectangleShape alive; 23 | CGrid(); 24 | CGrid(const int NN_x,const int NN_y,const int s); 25 | virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; 26 | void click(const int x, const int y); 27 | void next_generation(); 28 | void reset(); 29 | void save(); 30 | void read(std::ifstream& file); 31 | void scroll(const char dir);//jumps 5 squares in the direction 32 | private: 33 | bool should_i_live(const int i, const int j); 34 | bool should_i_die(const int i, const int j); 35 | }; 36 | //default constructor 37 | CGrid::CGrid(){ 38 | step=0; 39 | N_x=0; 40 | N_y=0; 41 | dead.setSize(sf::Vector2f(step,step)); 42 | dead.setFillColor(sf::Color::White); 43 | dead.setOutlineThickness(-1.f); 44 | dead.setOutlineColor(sf::Color(80,80,80)); 45 | alive.setSize(sf::Vector2f(step,step)); 46 | alive.setFillColor(sf::Color(0,128,0)); 47 | } 48 | //constructor with a parameter; 49 | CGrid::CGrid(const int NN_x, const int NN_y, const int s){ 50 | N_x=NN_x; 51 | N_y=NN_y; 52 | std::vector temp(N_x*N_y,false); 53 | step=s; 54 | field=temp; 55 | old_field=temp; 56 | dead.setSize(sf::Vector2f(step,step)); 57 | dead.setFillColor(sf::Color::White); 58 | dead.setOutlineThickness(-1.f); 59 | dead.setOutlineColor(sf::Color(211,211,211)); 60 | alive.setSize(sf::Vector2f(step,step)); 61 | alive.setFillColor(sf::Color(0,128,0)); 62 | } 63 | 64 | void CGrid::draw(sf::RenderTarget& target, sf::RenderStates states) const{ 65 | for(auto i=0;i> temp; 96 | //file >> field[i*N_x+j]; 97 | } 98 | } 99 | old_field=field; 100 | }; 101 | 102 | void CGrid::reset(){ 103 | std::fill(field.begin(), field.end(), false); 104 | std::fill(old_field.begin(), old_field.end(), false); 105 | }; 106 | 107 | void CGrid::click(const int x, const int y){ 108 | int x_coord=(int)x/step; 109 | int y_coord=(int)y/step; 110 | field[x_coord*N_x+y_coord]=!field[x_coord*N_x+y_coord]; 111 | old_field[x_coord*N_x+y_coord]=!old_field[x_coord*N_x+y_coord]; 112 | }; 113 | 114 | void CGrid::scroll(const char dir){ 115 | const int jump=5;//in case need to change 116 | switch (dir){ 117 | case 'd': 118 | for(auto i=0;i0)&&(i0)&&(j0)&&(i0)&&(j3)){result=true;} 202 | return result; 203 | }; 204 | 205 | 206 | void CGrid::next_generation(){ 207 | for(auto i=0;i1){ 227 | std::ifstream config; 228 | config.open(argv[1]); 229 | if (!config){ 230 | std::cerr << "Error opening the file. Ignoring." <1){ 301 | std::ifstream config; 302 | config.open(argv[1]); 303 | if (!config){ 304 | std::cerr << "Error opening the file. Ignoring." < 15 | 16 | int main(){ 17 | sf::RenderWindow window(sf::VideoMode(700, 700), "Hello, World!"); 18 | sf::CircleShape shape(200.f); 19 | shape.setFillColor(sf::Color::Green); 20 | //this is how most games are run, it's an infinite "while" loop 21 | while (window.isOpen()){ 22 | sf::Event event; 23 | while (window.pollEvent(event)){ 24 | //without this, the window won't react to close button 25 | if (event.type == sf::Event::Closed){ 26 | window.close(); 27 | } 28 | //an example of keyboard interaction 29 | if (event.type == sf::Event::KeyPressed){ 30 | switch (event.key.code){ 31 | case sf::Keyboard::Q: 32 | window.close(); 33 | break; 34 | }//switch 35 | }//if keypressed 36 | }//while poll event 37 | 38 | window.clear(); 39 | window.draw(shape); 40 | window.display(); 41 | 42 | }//main game loop 43 | return 0; 44 | } 45 | ``` 46 | 47 | Compile it with 48 | 49 | ``` 50 | g++ -o hello_sfml.x -lsfml-graphics -lsfml-window -lsfml-system basic.cpp 51 | ``` 52 | 53 | If this compiles, then everything has been installed correctly. If you installed manually (from github instead of a repository), you might need to specify the include folder when you compile and update your `LIBRARY_PATH` and `LD_LIBRARY_PATH` environmental libraries. 54 | 55 | 56 | There is a more advanced example, where you can see how to draw more complicated staff and move things - game of life. 57 | 58 | To compile the "game of life" example, do 59 | 60 | ``` 61 | g++ -lsfml-window -lsfml-graphics -lsfml-system -o life.x life.cpp 62 | ``` 63 | 64 | Then, running `./life.x` should open a window with a field where you can draw anything by clicking on the squares. Once you are done drawing, press the space key to start the "game". You can pose it any time with the `p` or space keys. You can save the file with the `s` key. The file will be named "renameMe.txt". When you start the program, you can give it the save file so that you wouldn't need to draw again. You can move the screen with the arrow keys. To quit, press `q`. 65 | 66 | ### Exercises (for people who completely have nothing else to do): 67 | 68 | **Exercise1:** Modify the game of life to have "periodic boundary conditions" (so that the things would just move over the edges rather then disappear). 69 | 70 | **Exercise2:** Try to write a snake game. 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /examples/sstreams/cppstring.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main () { 5 | 6 | std::string str1 = "Hello"; 7 | std::string str2 = "World"; 8 | std::string str3; 9 | int len ; 10 | 11 | // copy str1 into str3 12 | str3 = str1; 13 | std::cout << "str3 : " << str3 << std::endl; 14 | 15 | // concatenates str1 and str2 16 | str3 = str1 + str2; 17 | std::cout << "str1 + str2 : " << str3 << std::endl; 18 | 19 | // total length of str3 after concatenation 20 | len = str3.size(); 21 | std::cout << "str3.size() : " << len << std::endl; 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/sstreams/cstrings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main () { 5 | 6 | //things in " " are already null-terminated 7 | char str1[10] = "Hello"; 8 | char str2[10] = "World"; 9 | char str3[10]; 10 | int len ; 11 | 12 | // copy str1 into str3 13 | strcpy( str3, str1); 14 | std::cout << "strcpy( str3, str1) : " << str3 << std::endl; 15 | 16 | // concatenates str1 and str2 17 | strcat( str1, str2); 18 | std::cout << "strcat( str1, str2): " << str1 << std::endl; 19 | 20 | // total lenghth of str1 after concatenation 21 | len = strlen(str1); 22 | std::cout << "strlen(str1) : " << len << std::endl; 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /examples/sstreams/input.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main( int argc, char *argv[] ){ 5 | std::istringstream ss(argv[1]); 6 | int x{0}; 7 | //we try to read a number from the first passed argument 8 | if (!(ss >> x)) { 9 | std::cerr << "Invalid number: " << argv[1] << std::endl; 10 | } else if (!ss.eof()) { 11 | std::cerr << "There are trailing characters after the number: " << argv[1] << std::endl; 12 | std::cout<<"number was "< 2 | #include 3 | 4 | //to avoid writing two functions for printing to file and for printing on screen 5 | template 6 | void print_value(std::ostream& os,const T& val){ 7 | os< 2 | #include 3 | 4 | int main( int argc, char *argv[] ){ 5 | 6 | std::istringstream ss("1a2a3a4a5a6a7"); 7 | std::string token; 8 | 9 | while(std::getline(ss, token, 'a')) { 10 | std::cout << token << " "; 11 | } 12 | std::cout< 2 | #include //stingstreams 3 | #include 4 | 5 | int main(){ 6 | int a{90}; 7 | std::ostringstream ss; 8 | ss<> n; 19 | 20 | // Print the number 21 | std::cout << n << std::endl; 22 | } 23 | -------------------------------------------------------------------------------- /examples/sstreams/test.txt: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /examples/templates/class_templates.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class CMyClass{ 5 | public: 6 | T field1; 7 | T field2; 8 | CMyClass(const T& a, const T& b); 9 | template 10 | void print_extra(const M& val); 11 | }; 12 | 13 | 14 | template 15 | CMyClass::CMyClass ( const T& a, const T& b ) { 16 | field1=a; 17 | field2=b; 18 | } 19 | 20 | template 21 | template 22 | void CMyClass::print_extra(const M& val) { 23 | std::cout<< field1<<" "< var(7,8); 30 | var.print_extra(9.1); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /examples/templates/function_templates.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | void print(const T& x){ 5 | //all we need is the operator << be defined for the type T 6 | std::cout< 10 | T sum(const T& a, const T& b){ 11 | return a+b; 12 | } 13 | 14 | 15 | template 16 | void weird_function(T1& a, T2& b){ 17 | a=a+1; 18 | b=b-1; 19 | } 20 | 21 | 22 | int main(){ 23 | int a{8}; 24 | double b{9.7}; 25 | print(a); 26 | print(b); 27 | //we can force a choice if we want 28 | print(b); 29 | //here if you don't specify "double" compiler will complain cause it can't decide 30 | auto c=sum(a,b); 31 | print(c); 32 | weird_function(a,b); 33 | print(a); 34 | print(b); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /examples/templates/non_type.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //we can template on any "integral" type parameter, for example int,long int, short int, etc 4 | template 5 | void add_number(T& var){ 6 | var=var+N; 7 | } 8 | 9 | int main(){ 10 | double b{4.7}; 11 | add_number(b); 12 | std::cout< 2 | #include 3 | 4 | template 5 | class CMyClass{ 6 | public: 7 | void Function(); 8 | 9 | }; 10 | 11 | 12 | template 13 | void CMyClass::Function(){ 14 | if constexpr(std::is_same_v){ 15 | std::cout<<"we are dealing with int"<){ 18 | std::cout<<"we are dealing with double"<){ 21 | std::cout<<"something \"integer\" "< var; 29 | var.Function(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /examples/templates/variadic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | template 5 | void myPrint(const T& arg){ 6 | std::cout< 11 | void myPrint(const T& arg, const Types&... args){ 12 | std::cout< 2 | #include 3 | #include 4 | #include 5 | #include //the easiest platform-independent way to make your program sleep 6 | 7 | 8 | class CSimple_Timer{ 9 | std::chrono::time_point t_start; 10 | std::string time_what; 11 | void print_time(){ 12 | auto t_end = std::chrono::steady_clock::now(); 13 | auto total = std::chrono::duration_cast(t_end - t_start).count(); 14 | std::cout< 2 | #include 3 | #include //the easiest platform-independent way to make your program sleep 4 | 5 | int main(){ 6 | 7 | std::chrono::time_point t_start; 8 | 9 | t_start = std::chrono::steady_clock::now();//we could just use auto 10 | 11 | //the easiest platform-independent way to make your program sleep 12 | std::this_thread::sleep_for(std::chrono::milliseconds(2000)); 13 | 14 | auto t_end = std::chrono::steady_clock::now(); 15 | 16 | //the difference returns another type, not time_point 17 | auto total = std::chrono::duration_cast(t_end-t_start).count(); 18 | 19 | //microseconds are to small, not too reliable, so we get 2000+ 20 | std::cout<<"we have measured: "<(t_start.time_since_epoch()).count()<(t_test.time_since_epoch()).count()< 2 | #include 3 | #include 4 | #include 5 | #include //the easiest platform-independent way to make your program sleep 6 | 7 | 8 | //to type less and maybe change clocks if needed 9 | using CHRONO = std::chrono::steady_clock; 10 | using TIME_UNIT = std::chrono::milliseconds; 11 | 12 | struct Timer_Data{ 13 | unsigned int n_calls; 14 | TIME_UNIT elapsed; 15 | }; 16 | 17 | std::ostream& operator<<(std::ostream& os, const Timer_Data& t){ 18 | os << t.n_calls << "\t" << std::chrono::duration_cast(t.elapsed).count(); 19 | return os; 20 | } 21 | 22 | class CTimer{ 23 | std::map table; 24 | std::chrono::time_point t_start; 25 | void print_table(){ 26 | for (const auto& p : table) 27 | std::cout << p.first << "\t" << p.second << std::endl; 28 | } 29 | public: 30 | CTimer() : t_start{CHRONO::now()} {} 31 | ~CTimer() noexcept { print_table(); } 32 | friend class CScoped_Timer; 33 | }; 34 | 35 | class CScoped_Timer{ 36 | CTimer& timer; 37 | std::chrono::time_point t_start; 38 | std::string section; 39 | void update_table(){ 40 | auto t_end = CHRONO::now(); 41 | auto tot = (t_end - t_start); 42 | ++timer.table[section].n_calls; 43 | timer.table[section].elapsed += std::chrono::duration_cast(tot); 44 | } 45 | public: 46 | CScoped_Timer(CTimer& t, std::string s): timer{t}, 47 | t_start{CHRONO::now()}, 48 | section{s} {} 49 | ~CScoped_Timer() noexcept { update_table();} 50 | }; 51 | 52 | //we need a global variable 53 | //if you are using headers (as you should), you can put this declaration into some "global.hpp" file, or declare it after the timer class 54 | CTimer the_timer; 55 | 56 | int main(){ 57 | double a{0}; 58 | 59 | //open the scope, initialize the timer with global variable that will "remember" timings 60 | {CScoped_Timer t{the_timer, "sleep"}; 61 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 62 | }//close the scope 63 | 64 | {CScoped_Timer t{the_timer, "test"}; 65 | for (int i=0;i<100000000;i++){ 66 | a+=std::sqrt(i*std::sqrt(i))*pow(i,0.234); 67 | } 68 | std::cout< 2 | #include // for std::numeric_limits 3 | 4 | int main () { 5 | bool var{true}; //or false 6 | double x{3.5}; 7 | float xx{3.5f}; //if precision and big numbers are not needed 8 | int a{1}; 9 | short int b{2}; 10 | long int c{3}; 11 | long long int d{4}; 12 | char s{'a'}; 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /examples/variables.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int a{3}; //global variable, avoid if possible 4 | 5 | 6 | int main(){ 7 | std::cout<<"global variable a is: "< 2 | #include 3 | #include 4 | 5 | template 6 | void print_vector(const std::vector& v){ 7 | //printing with a "normal" loop 8 | for(int i=0;i 21 | void print_array(const std::array& v){ 22 | //printing with a "normal" loop 23 | for(int i=0;i 39 | void print_whatever(const T& v){ 40 | //printing with a "normal" loop 41 | for(int i=0;i arr;//need to specify the number of elements 65 | std::vector vec; 66 | vec.resize(5); 67 | print_whatever(arr); 68 | print_whatever(vec); 69 | 70 | vec.push_back(8);//avoid if you can in hpc! 71 | vec.reserve(100000);//now you can do push_backs, but still better not 72 | 73 | print_whatever(vec); 74 | std::cout< 16 | void print(const T& x){ 17 | //all we need is the operator << be defined for the type T 18 | std::cout<(a); 27 | ``` 28 | 29 | You can also have different templated arguments if you need. 30 | 31 | Templates need to be "instantiated" by the compiler at compile time, thus if you separate the declarations and definitions into different files as is done in `C`, you have to instatiate it manually. In many cases, that almost defeats the purpose of using templates and, unless working with projects where you care for executable size, can be avoided by simply creating "a header only library", that is, putting all the function/class definitions entirely into header files. 32 | 33 | #### Class templates 34 | 35 | Your classes can have templated fields and extra templated functions inside: 36 | 37 | ``` 38 | template 39 | class CMyClass{ 40 | public: 41 | T field1; 42 | T field2; 43 | CMyClass(const T& a, const T& b); 44 | template 45 | void print_extra(const M& val); 46 | }; 47 | ``` 48 | 49 | When we define the functions outside the class, we still need to specify the `template` keyword. Or both of them if the function had an extra template: 50 | 51 | ``` 52 | template 53 | CMyClass::CMyClass ( const T& a, const T& b ) { 54 | field1=a; 55 | field2=b; 56 | } 57 | 58 | template 59 | template 60 | void CMyClass::print_extra(const M& val) { 61 | std::cout<< field1<<" "< var; 70 | ``` 71 | 72 | #### Non-type template parameters: 73 | 74 | In addition to templating functions/classes on types, we can also template them on "integer" numbers. By "integer" here is meant anything that is mathematically integer, not just `int`. 75 | 76 | ``` 77 | template 78 | void add_number(T& var){ 79 | var=var+N; 80 | } 81 | 82 | int main(){ 83 | double b{4.7}; 84 | add_number(b); 85 | std::cout< 96 | 97 | template 98 | void CMyClass::Function(){ 99 | if constexpr(std::is_same_v){ 100 | std::cout<<"we are dealing with int"<){ 103 | std::cout<<"we are dealing with double"<){ 106 | std::cout<<"something \"integer\" "< 128 | void myPrint(const T& arg){ 129 | std::cout< 137 | void myPrint(const T& arg, const Types&... args){ 138 | std::cout< 152 | ``` 153 | 154 | To define a variable, do: 155 | 156 | ``` 157 | std::array arr;//you need to pass the number of elements just like with the static array 158 | ``` 159 | 160 | *From now on, you can safely forget about "c-style" static arrays and always use std::array*. Why? It has the same performance, but causes no confusion with pointers, knows it's size and can be used with many C++ algorithms (that we'll see later). 161 | 162 | ### std::vector 163 | 164 | ``` 165 | include 166 | ``` 167 | 168 | std::vector provides dynamic array functionality that handles its own memory management. This saves a lot of time, especially on debugging stage. You don't yet know all the horrors of memory management and with vectors you will only need to know them for cuda and the like. 169 | 170 | However, it's easy to lose perfomance if you don't know what you are doing. Specifically, there is a handy function `push_back`, which should be used with caution or outright avoided when speed matters. 171 | 172 | ``` 173 | std::vector V; 174 | for (int i=0;i<100000;i++){ 175 | V.push_back(i); 176 | } 177 | ``` 178 | 179 | What happens behind the scnenes is that the vector will reserve the memory for itself with what it believs as "enough", then allocate new elemement in that area. Once it runs out of reserved memory, it will *copy eveything to a new location*, which you obvioulsy want to avoid when working with anything big. 180 | 181 | So, when working with vectors in hpc, try to treat them like arrays and awaid resizing more than once. Always use `resize(NUMBER)` function, then fill in the values normally. As an alternative, you can call `reserve(NUMBER)` and then do `push_back`, but this way it's not always clear when the vector decides it's time to "move", it's safer to stick with "resize()". 182 | 183 | When you work with C-style functions that require a pointer, you can pass vector's contents either as `&myvec[0]` or `myvec.data()`. 184 | 185 | Both `std::vector` and `std::array` have a `.size()` function, so you don't need to manually pass their size to functions that work on them. 186 | 187 | #### 2-dimentional arrays/vectors 188 | 189 | When working with matrices, you generally want the data to be contiguous in memory, so never use something like `std::vector>`. Use one-dimensional storage instead and access the `(i,j)` elements as `data[i*N+j]`. 190 | 191 | 192 | ### Test Yourself: 193 | 194 | - what's the main advantage of using templates? 195 | - why do people usually put definitions of templated functions directly into `.hpp` files? 196 | - except on types, what else can we template on? 197 | - what is template specialization? 198 | - what is a variadic template? 199 | - why using `push_back` for `std::vector` is a bad idea? 200 | - how do you pass data from `std::vector` to a "C-style" function that needs a pointer? 201 | - why you shouldn't use a "vector of vectors"? 202 | 203 | 204 | #### All the code snippets below have mistakes, find them: 205 | 206 | 207 | Snippet 1: 208 | ``` 209 | //BAD CODE AHEAD, DO NOT COPY BY ACCIDENT! 210 | template 211 | class CMyClass{ 212 | T a; 213 | T b; 214 | } 215 | 216 | int main(){ 217 | CMyClass var; 218 | ... 219 | } 220 | ``` 221 | 222 | Snippet 2: 223 | ``` 224 | //BAD CODE AHEAD, DO NOT COPY BY ACCIDENT! 225 | template 226 | void add_number(T& var){ 227 | T=T+S; 228 | } 229 | ``` 230 | 231 | 232 | Snippet 3: 233 | ``` 234 | //BAD CODE AHEAD, DO NOT COPY BY ACCIDENT! 235 | template 236 | void myPrint(const Types&... args){ 237 | std::cout< 247 | void print(const T& var){ 248 | std::cout< A,B; 297 | A.read_from_file("A.txt"); 298 | B.read_from_file("B.txt"); 299 | auto C=A*B; 300 | C.print_to_file("C.txt"); 301 | } 302 | 303 | ``` 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | -------------------------------------------------------------------------------- /lecture_notes/Lecture_notes5.md: -------------------------------------------------------------------------------- 1 | *The notes do not consitute a full reference book, please attend lectures, watch videos or read something else to fully understand the material. They are nothing more than "notes".* 2 | 3 | ### Memory management 4 | 5 | #### C-like style memory management 6 | 7 | So far we have only seen pointers in a context of pointing to an existing variable or passing something to a function. It has been mentioned that c-style arrays are actually pointers, but without going into details. 8 | 9 | The memory your program uses is divided into a "heap" and a "stack". Stack is small (and thus fast), heap is as big as your operative memory allows. 10 | To allocate the memory on a "heap", use `new`, to free it, use `delete` or `delete[]`: 11 | 12 | ``` 13 | int* p1 =new int; 14 | int* p =new int[N]; 15 | for(int i=0;i 39 | class MyClass{ 40 | public: 41 | T* data; 42 | MyClass(const int& N); 43 | ~MyClass(); 44 | }; 45 | 46 | template 47 | MyClass::MyClass(const int& N) { 48 | data=new T[N]; 49 | for(int i=0;i 55 | MyClass::~MyClass() { 56 | delete[] data; 57 | data=nullptr; 58 | } 59 | 60 | ``` 61 | 62 | This might be enough as a "minimal survival", but what happens if you do 63 | 64 | ``` 65 | MyClass A(10),B(10); 66 | A=B; 67 | ``` 68 | ? 69 | 70 | It will crash. 71 | The compiler doesn't know how to make a "deep copy", you need to tell it: 72 | 73 | ``` 74 | template 75 | CMyClass& CMyClass::operator=(const CMyClass& p){ 76 | //first check for self-assignment 77 | if (this != &p) { 78 | //copy non-dynamic variables 79 | size=p.size; 80 | //free memory of existing dynamic variables 81 | if (data != nullptr){ 82 | delete[] data; 83 | data=nullptr; 84 | } 85 | //create and copy dynamic variables 86 | if(p.data==nullptr){data=nullptr;} 87 | else{ 88 | data = new T[size]; 89 | for(int i=0;i 109 | CMyClass::CMyClass ( const CMyClass& p ) { 110 | //first check for self-assignment 111 | if (this != &p) { 112 | //copy non-dynamic variables 113 | size=p.size; 114 | //create and copy dynamic variables 115 | if(p.data==nullptr){data=nullptr;} 116 | else{ 117 | data = new T[size]; 118 | for(int i=0;i 132 | CMyClass::CMyClass ( CMyClass && p ) { 133 | //first check for self-assignment 134 | if (this != &p) { 135 | //copy non-dynamic variables 136 | size=p.size; 137 | p.size=0; 138 | //create and copy dynamic variables 139 | data=p.data; 140 | p.data=nullptr; 141 | }//of checking for self-assignment 142 | 143 | } 144 | ``` 145 | 146 | Now if you do 147 | 148 | ``` 149 | auto obj5=std::move(obj3); 150 | ``` 151 | 152 | move constructor will be called. Notice, how the above case doesn't call an assignment operator. However, 153 | 154 | ``` 155 | obj5=std::move(obj2); 156 | ``` 157 | 158 | does. 159 | 160 | 161 | 162 | #### Smart Pointers: Unique Pointer 163 | 164 | You can save yourself some typing if you use "smart pointers" from header `memory`. It is considered good practice to never use "raw pointers" if smart ones can be used. 165 | 166 | ``` 167 | std::unique_ptr p(new int[5]); 168 | ``` 169 | 170 | This object will call `delete[]` automatically when going out of scope, so you don't have to worry about freeing the memory manually. 171 | 172 | The file `unique2.cpp` has the examples of how to use it inside a class. 173 | 174 | If you need to pass the pointer to a C-Style function, use p.get() to get the raw pointer. However, you need to trust the function to not try to deallocating the memory as that would crash your program. 175 | 176 | 177 | 178 | #### Test Yourself: 179 | 180 | - how do you allocate a dynamic array in C++? 181 | - whats the difference between `delete` and `delete[]`? 182 | - when do you need to overload assignment operator for your class? 183 | - when do you need to create a copy constructor for your class? 184 | - when do you need to create a move constructor for your class? 185 | - what should you do if your class allocates resources, but you are sure you will never need a copy constructor? 186 | 187 | 188 | ### Exercise1: 189 | 190 | Rewrite your matrix multiplication exercise using raw pointers to store the data instead of vectors. 191 | 192 | ### Exercise2: 193 | 194 | Rewrite your matrix multiplication exercise using smart (unique) pointers to store the data instead of vectors. 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /lecture_notes/Lecture_notes6.md: -------------------------------------------------------------------------------- 1 | *The notes do not constitute a full reference book, please attend lectures, watch videos or read something else to fully understand the material. They are nothing more than "notes".* 2 | 3 | ### Inheritance 4 | 5 | #### simple member access and inheritance modes: 6 | 7 | We can derive a child class from the base class in different access modes: public, protected, private. For example: 8 | 9 | `class Derived : public Base` 10 | 11 | 12 | - Public inheritance makes public members of the base class public in the derived class, and the protected members ("protected" means friends and derived classes can access) of the base class remain protected in the derived class. 13 | - protected inheritance makes the public and protected members of the base class protected in the derived class. 14 | - private inheritance makes the public and protected members of the base class private in the derived class. 15 | 16 | Note: private members of the base class are inaccessible to the derived class. 17 | 18 | ``` 19 | class CBase { 20 | public: 21 | int x; 22 | protected: 23 | int y; 24 | private: 25 | int z; 26 | }; 27 | 28 | class CPublicDerived: public CBase { 29 | // x is public 30 | // y is protected 31 | // z is not accessible from CPublicDerived 32 | }; 33 | 34 | class CProtectedDerived: protected CBase { 35 | // x is protected 36 | // y is protected 37 | // z is not accessible from CProtectedDerived 38 | }; 39 | 40 | class CPrivateDerived: private CBase { 41 | // x is private 42 | // y is private 43 | // z is not accessible from CPrivateDerived 44 | }; 45 | ``` 46 | 47 | It's possible to inherit from multiple classes at once. 48 | 49 | 50 | 51 | 52 | #### Polymorphism: virtual functions 53 | 54 | One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class. This is called runtime or dynamic polymorhism and is one of the key features of the object oriented design. (It's mostly not recommended in high performace applications, as it's slow.) 55 | 56 | ``` 57 | #include 58 | 59 | class Polygon { 60 | protected: 61 | int width, height; 62 | public: 63 | void set_values (int a, int b){ 64 | width=a; height=b; 65 | } 66 | }; 67 | 68 | class Rectangle: public Polygon { 69 | public: 70 | int area(){ 71 | return width*height; 72 | } 73 | }; 74 | 75 | class Triangle: public Polygon { 76 | public: 77 | int area(){ 78 | return width*height/2; 79 | } 80 | }; 81 | 82 | int main () { 83 | Rectangle rect; 84 | Triangle trgl; 85 | Polygon * ppoly1 = ▭ 86 | Polygon * ppoly2 = &trgl; 87 | ppoly1->set_values (4,5); 88 | ppoly2->set_values (4,5); 89 | std::cout << rect.area() << '\n'; 90 | std::cout << trgl.area() << '\n'; 91 | return 0; 92 | } 93 | ``` 94 | Here you used `area()` function as an overloaded one, you knew what you called it on. 95 | 96 | Instead of overloading the functions (happens at compile time), you can override them. This requires a `virtual` keyword. 97 | 98 | 99 | A class that declares or inherits a virtual function is called a polymorphic class. 100 | 101 | ``` 102 | #include 103 | 104 | class Polygon { 105 | protected: 106 | int width, height; 107 | public: 108 | void set_values (int a, int b) 109 | { width=a; height=b; } 110 | virtual int area (){ 111 | return 0; 112 | } 113 | // virtual int area ()=0;//makes the class abstract, then you can't have an object of it 114 | 115 | }; 116 | 117 | class Rectangle: public Polygon { 118 | public: 119 | //override helps compiler and makes sure you don't type anything wrong 120 | int area() override{ 121 | return width * height; 122 | } 123 | }; 124 | 125 | class Triangle: public Polygon { 126 | public: 127 | int area() override{ 128 | return (width * height / 2); 129 | } 130 | }; 131 | 132 | int main () { 133 | Rectangle rect; 134 | Triangle trgl; 135 | Polygon poly; 136 | Polygon * ppoly1 = ▭ 137 | Polygon * ppoly2 = &trgl; 138 | Polygon * ppoly3 = &poly; 139 | ppoly1->set_values (4,5); 140 | ppoly2->set_values (4,5); 141 | ppoly3->set_values (4,5); 142 | std::cout << ppoly1->area() << std::endl; 143 | std::cout << ppoly2->area() << std::endl; 144 | std::cout << ppoly3->area() << std::endl; 145 | return 0; 146 | } 147 | ``` 148 | 149 | If a class has a pure virtual function (declared with `=0`), then it's an "abstract class" and you cannot have an object of it. It's used for interface only purposes. Virtual functions must be overriden in derived classes, otherwise they become abstract too. 150 | 151 | 152 | ### Test yourself: 153 | 154 | - what are protected class members? 155 | - what are virtual functions? 156 | - what is an abstract class? 157 | - explain dynamic (runtime) polymorphism 158 | - why destructors should be made virtual? 159 | 160 | 161 | #### All the code snippets below have mistakes, find them: 162 | 163 | Snippet 1 164 | ``` 165 | //BAD CODE AHEAD, DO NOT COPY BY ACCIDENT! 166 | class Shape{ 167 | public: 168 | virtual void print()=0; 169 | virtual ~Shape(){}; 170 | } 171 | 172 | class Circle: public Shape{ 173 | double r; 174 | void print() override {std::cout<` header also works, but is less accurate and less flexible for uses with modern interfaces, so we will not discuss any examples from it. To start the timings, do: 24 | 25 | ``` 26 | std::chrono::time_point t_start; 27 | t_start = std::chrono::steady_clock::now();//we could just use auto 28 | ``` 29 | 30 | To end: 31 | 32 | ``` 33 | auto t_end = std::chrono::steady_clock::now(); 34 | auto total = std::chrono::duration_cast(t_end - t_start).count(); 35 | ``` 36 | 37 | There are other clocks in `chrono`, for example `system_clock` and `high_resolution_clock`, but the first one depends on your laptop time and might give surprises if it changes during the execution (for example, corrected from time server) and the second one is implementation-dependent, so you never know what it really is. 38 | 39 | Since we want to write c++, let's introduce the concept of "scoped timer" - the timer that calls it's desctructor when going out of scope and saves you from typing the time difference manually every time. The simplest example is in the file `simple_timer.cpp` 40 | 41 | ``` 42 | class CSimple_Timer{ 43 | std::chrono::time_point t_start; 44 | std::string time_what; 45 | void print_time(){ 46 | auto t_end = std::chrono::steady_clock::now(); 47 | auto total = std::chrono::duration_cast(t_end - t_start).count(); 48 | std::cout<s2`. 73 | - strchr(s1, ch); // Returns a pointer to the first occurrence of character ch in string s1. 74 | - strstr(s1, s2); //Returns a pointer to the first occurrence of string s2 in string s1. 75 | 76 | They are pretty uncomfortable to work with, so, use `std::string` from the header `string`. 77 | 78 | 79 | 80 | 81 | 82 | ### Lambda functions (and some STL algorithms) 83 | 84 | There is good [book](https://books.google.it/books/about/C++_Lambda_Story.html?id=wqw2zgEACAAJ&redir_esc=y) about lambdas if you want to know more than needed for "survival". 85 | 86 | *While there is nothing to stop you from always using lambda functions instead of "normal" ones (except it being harder to write/read the code), they are usually only used with STL algorithms.* 87 | 88 | But to better understand what they do, we must start with "lambda functions in the wild". Actually, sometimes they are called "lambda expressions" or just "lambdas". 89 | 90 | The simplest lambda is just 91 | 92 | ``` 93 | []{}; 94 | ``` 95 | 96 | This defines a function that does nothing and can't even be called later as it has no name. 97 | 98 | The general possible structure of a lambda function is 99 | 100 | ``` 101 | [CAPTURES](PARAMETERS)->RETURN_TYPE{WHAT THE FUNCTION DOES}(); 102 | ``` 103 | 104 | You can "capture" existing variables. 105 | 106 | - [] Empty capture list, nothing will be captured. 107 | - [something] Capture `something` by copy. 108 | - [&something] Capture something by reference. 109 | - [x, &y] Capture y by-copy and y by-reference. 110 | - [=] Capture anything named from the enclosing scope by-copy. 111 | - [&] Capture anything named from the enclosing scope by-reference. 112 | - [&, x, y] Capture anything named from the enclosing scope by reference, except x and y which are captured by-copy. 113 | - [=, &x] Capture anything named from the enclosing scope by copy, except x which must be captured by-reference 114 | 115 | Since we are using lambdas outside of STL, we probably need to give them names. The easiest way is let the compiler decide the type for you (it's actually different for each function) 116 | 117 | ``` 118 | auto func = [](int i){ return i; }; 119 | ``` 120 | 121 | 122 | The things captured by value are captured at the moment the lambda was created, not when it was called. Also, you can't change them by default. To do that, you need a keyword `mutable` 123 | 124 | ``` 125 | int a{0}; 126 | auto very_useful_lambda = [a]() mutable {a=a+2; 127 | std::cout << a << std::endl; 128 | }; 129 | ``` 130 | 131 | Now let's look at how to use them with algorithms: 132 | 133 | ``` 134 | int count{0}; 135 | //unfortunately, you need an external variable for index 136 | std::generate(vec.begin(),vec.end(),[&count]{count++;return count*count;}); 137 | 138 | //sort wants a function that accepts two parameters and compares them 139 | std::sort(vec.begin(),vec.end(),[](int x,int y){return x>y;}); 140 | 141 | //for_each can be replaced by a range loop usually 142 | std::for_each(vec.begin(),vec.end(),[](int i){std::cout< 164 | void CMatrix::random_fill(){ 165 | constexpr auto low_bound = 0; 166 | constexpr auto up_bound = 100; 167 | //take the current time as a random value for the seed 168 | auto seed = std::chrono::system_clock::now().time_since_epoch().count(); 169 | std::default_random_engine dre(seed);//engine 170 | std::uniform_int_distribution di(low_bound,up_bound);//distribution 171 | //a lambda function to fill in the matrix 172 | std::generate(data.begin(), data.end(), [&](){ return di(dre);});//fill 173 | }; 174 | ``` 175 | 176 | 177 | 178 | ### Exercises: 179 | 180 | #### Exercise 1: 181 | 182 | Instead of reading the matrix from a file, get the matrix size from the command line parameters and use the `random_fill` function provided in the lecture to fill in a large matrix (around a 1000). Add the timing to the matrix multiplication program (you can use the easier version of it, the one with `std::vector`). *Extra exercsise for those who managed to either install openblas or can find that module on some cluster:* add the call to the `cblas_dgemm` function like in the `matrix_cblas.cpp` example and compare the timings. 183 | 184 | #### Exercise 2: 185 | 186 | Write your own "parameter parser" similar to `getops()`. Your code should accept parameters like. 187 | 188 | ``` 189 | ./code -n1 1 -n2 2 -n3 3 190 | 191 | ``` 192 | 193 | 194 | 195 | #### Exercise 3: 196 | 197 | "Play around" with examples of the lambda functions we saw, try to create a few simple lambda functions of your own to understand how they work. 198 | 199 | 200 | #### Exercise 4: 201 | 202 | Time the `std::sort` with a lambda function and your own sort implementation (there was some in previous exercises) when sorting a large vector (large enough to take a few seconds). 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /lecture_notes/bonus/DataFrame.md: -------------------------------------------------------------------------------- 1 | ### One of the C++ options for doing what pandas does: DataFrame library 2 | 3 | here is [a link](https://github.com/hosseinmoein/DataFrame) for repository. 4 | 5 | We won't do real exercise with this, as you will only need it if you actually work on something that becomes slow, but I would like you to at least install the library and try to understand it's "hello world", so that you could come back to it if needed for work. 6 | 7 | Clone the repository, go into the folder, then run 8 | 9 | ``` 10 | mkdir Release #create a folder 11 | cd [Debug | Release] 12 | cmake -DCMAKE_BUILD_TYPE=Release -DHMDF_BENCHMARKS=1 -DHMDF_EXAMPLES=1 -DHMDF_TESTING=1 .. #don't forget those .. 13 | make 14 | make install 15 | 16 | ``` 17 | 18 | Now, if you go to DataFrame/examples folder, you should be able to compile the hello world example with 19 | 20 | ``` 21 | g++ -o hello_dataframe.x -std=c++17 hello_world.cc -lDataFrame 22 | ``` 23 | 24 | If it starts complaining about the missing includes, then something went wrong at the installation stage, you might have to see where it got actually installed and compile with `-I/PATH_TO_HEADERS -L/PATH_TO_LIBRARY`. 25 | 26 | However, this hello world example was supposed to be run from the root folder, so before you can use it, fix the path to the data-files it's trying to open (you will see an error opening files, find those paths in code fix them, then recompile). 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /lecture_notes/git.md: -------------------------------------------------------------------------------- 1 | ### Crash/survival notes on git 2 | 3 | [reference material](https://git-scm.com/book/en/v2) 4 | 5 | ### Why use git? 6 | 7 | ![](pictures/final.jpg) 8 | 9 | ### What is git? 10 | 11 | Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. 12 | 13 | ### What is github? 14 | 15 | GitHub is an Internet hosting service for software development and version control using Git. 16 | 17 | ![](pictures/git_cartoon.png) 18 | 19 | ### Let's start! 20 | 21 | make sure that you have `git` installed. 22 | 23 | initialize it (or it will complain the first time you do anything): 24 | 25 | `git config --global user.name "Whatever Name"` 26 | `git config --global user.email whatever@whatever` 27 | 28 | ### Passwordless access 29 | 30 | Let's follow [instructions on github](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/checking-for-existing-ssh-keys). 31 | 32 | ### Now let's make a nice bash prompt 33 | 34 | https://github.com/magicmonty/bash-git-prompt 35 | 36 | 37 | go to https://github.com/sissa/AdvancedProgramming_dssc22 and press "fork" 38 | 39 | clone the main, sissa repo: 40 | 41 | `git clone ADDRESS_FROM_GITHUB` (choose ssh if you did the password step) 42 | 43 | go into the folder (`cd AdvancedProgramming_dssc22`) 44 | 45 | `git remote -v` to see the current remote. Whatever you cloned from, will become "origin". 46 | 47 | `git remote add THINK_OF_A_SHORT_NAME ADDRESS_FROM_GITHUB_OF_YOUR_FORK` 48 | 49 | `git remote -v` should now show more things 50 | 51 | `git pull origin main` <--- this is what you should do after every lecture 52 | 53 | Do the following to "play around": 54 | 55 | create any text file inside your folder 56 | 57 | `git status` <---- you should see the file you created listed 58 | 59 | `git add YOUR_FILE` 60 | 61 | `git commit -m "USEFUL MESSAGE"` 62 | 63 | ![](pictures/git_commit.png) 64 | 65 | `git push SHORT_NAME_YOU_CHOSE_FOR_YOUR_FORK_REMOTE main` 66 | 67 | I recommend pushing your homework to your forks to keep track of it. However, note that the SISSA repository we are using is public and thus everything, including your fork, is open to the internet. If you want to "hide", make a separate private repository. 68 | 69 | 70 | ### Make your own repository 71 | 72 | 73 | Just go to github and follow visual instructions (choose "with README"), then 74 | 75 | `git clone YOUR_REPOSITORY` 76 | 77 | add some text file to it 78 | 79 | `git push origin main` (bad practice - only for "trash repositories" and learning purposes) 80 | 81 | ### Create a branch 82 | 83 | `git checkout -b development` 84 | 85 | edit your text file, add and commit 86 | 87 | `git push origin development` 88 | 89 | go to github and you will see a "create a pull request" (that's how things should get to `main` in real repositories) 90 | 91 | `git checkout main` 92 | 93 | `git pull origin main` (to update main after github pull request has been merged) 94 | 95 | ### Merging manually 96 | 97 | `git checkout development` 98 | 99 | `git checkpout -b new_branch` 100 | 101 | edit the file again, add, commit, push to new_branch, switch back to development 102 | 103 | `git merge new_branch` 104 | 105 | check your text file 106 | 107 | ### Let's create conflict 108 | 109 | edit the file in development, add, commit, push 110 | 111 | edit the file in new_branch, add, commit, push 112 | 113 | now try, while being in new_branch, 114 | 115 | `git pull origin development` 116 | 117 | What happens? 118 | 119 | 120 | ### Gitignore 121 | 122 | [A collection of templates](https://github.com/github/gitignore) 123 | 124 | If you are sure that your `.gitignore` is good, you can just do 125 | 126 | ``` 127 | git add -A 128 | ``` 129 | 130 | instead of adding files manually. Sooner of later you will push some trash like this, so only do it on your own repositories or if there are way too many files to add. 131 | 132 | **Git has many more options, but it's better if you learn them when you need them.** 133 | 134 | 135 | ### Fun picture 136 | 137 | ![](pictures/fire.png) 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /lecture_notes/pictures/final.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sissa/AdvancedProgramming_dssc22/7d8f0a1bf07c150c40882b271c853f8ea3ae10ef/lecture_notes/pictures/final.jpg -------------------------------------------------------------------------------- /lecture_notes/pictures/fire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sissa/AdvancedProgramming_dssc22/7d8f0a1bf07c150c40882b271c853f8ea3ae10ef/lecture_notes/pictures/fire.png -------------------------------------------------------------------------------- /lecture_notes/pictures/git_cartoon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sissa/AdvancedProgramming_dssc22/7d8f0a1bf07c150c40882b271c853f8ea3ae10ef/lecture_notes/pictures/git_cartoon.png -------------------------------------------------------------------------------- /lecture_notes/pictures/git_commit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sissa/AdvancedProgramming_dssc22/7d8f0a1bf07c150c40882b271c853f8ea3ae10ef/lecture_notes/pictures/git_commit.png -------------------------------------------------------------------------------- /python/Exercises1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### **Exercise 1:**\n", 8 | "The Recamán sequence is a famous sequence invented by the Colombian mathematician, Bernardo Recamán Santos. It is defined by the following algorithm, starting at $a_0=0$:\n", 9 | "\n", 10 | "$ a_n=a_{n-1}−n$ if $a_{n-1}-n > 0 $ and has not already appeared in the sequence; \n", 11 | "\n", 12 | "$ a_n=a_{n−1}+n$ otherwise\n", 13 | "\n", 14 | "Write a function that returns the first N elements of this sequence." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "### **Exercise 2:**\n", 22 | "Write a function to solve a quadratic equation." 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "### **Exercise 3**\n", 30 | "Print the list `mylist` sorted in descending order. The original list should not be modified\n" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 1, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "mylist=[1,-99,89,0,234,77,-748,11]" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "### **Exercise 4:**\n", 47 | "Given 2 lists, produce a list containing common items between the two." 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "### **Exercise 5:**\n", 55 | "Create a function that returns a list of all pairs of factors (as tuples) of a given number using list comprehension." 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "### **Exercise 6:**\n", 63 | "Create a list of all numbers divisible by 3 and smaller than 1000 in 4 different ways:\n", 64 | " \n", 65 | " - naive way where you just create a list and append data in a loop\n", 66 | " - using list comprehension\n", 67 | " - slicing an existing list\n", 68 | " - directly with `range()`\n", 69 | "\n", 70 | "Time all of them." 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "### **Exercise 7:**\n", 78 | "Write a function to check if a string (containing spaces and capital letters, but no punctuation marks) is a palindrome (use help to see which functions are available for a string). \n" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "### **Exercise 8:**\n", 86 | "Write a function to find a character with a maximum number of occurences in a string. Return a tuple with that character and the number. You can ignore ties. Only use string's inbuilt functions and the function `max` (use help to see how to use it)." 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "### **Exercise 9:**\n", 94 | "Write a function that return the first N prime numbers using the Sieve of Eratosphenes algorithm\n", 95 | "\n", 96 | "https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": null, 102 | "metadata": {}, 103 | "outputs": [], 104 | "source": [] 105 | } 106 | ], 107 | "metadata": { 108 | "kernelspec": { 109 | "display_name": "Python3.9", 110 | "language": "python", 111 | "name": "python3.9" 112 | }, 113 | "language_info": { 114 | "codemirror_mode": { 115 | "name": "ipython", 116 | "version": 3 117 | }, 118 | "file_extension": ".py", 119 | "mimetype": "text/x-python", 120 | "name": "python", 121 | "nbconvert_exporter": "python", 122 | "pygments_lexer": "ipython3", 123 | "version": "3.6.13" 124 | } 125 | }, 126 | "nbformat": 4, 127 | "nbformat_minor": 4 128 | } 129 | -------------------------------------------------------------------------------- /python/Exercises2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### **Exercise1:**\n", 8 | "\n", 9 | "Plot a rainbow" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "### **Exercise2:**" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "Plot the recaman sequence in the following way:\n", 24 | "\n", 25 | "Add a semi-circular arc from $a_{n}$ to $a_{n-1}$.\n", 26 | "\n", 27 | "Alternate the arcs to be above and below the x-axis according to whether\n", 28 | " n is even or odd." 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "### **Exercise3:**" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "Write a matrix multiplication fucntion using lists (\"manually\", like you did in c++) and another one using numpy arrays (call matmul function). Time them both. " 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "### **Exercise4:**" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "Read the \"extra exercise from c++\" about the Jacobi method to solve the Laplace equation. Implement the solver (without defining a class and just using numpy aray as a mesh) for the equation with the same boundary conditions. Try to get the same final picture and gif as the c++ version. Hint: you can plot a matrix with plt.imshow(MATRIX_TO_PLOT). The gif creation example scipt is in the file `anym.py` (not in the Jupyterlab as it has troubles displaying and sometimes even producing gifs, rememeber that you can export your notebooks into `.py` files by `Files->Export Notebook as... -> Export Notebook as executable script`)" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "### **Exercise5:**\n", 64 | "Implement [Conway's game of life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) using numpy array to hold data and animation technique from the previous exercise (or any other if you know it)." 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "### **Exercise6 (for those from data science following statistics course):**" 72 | ] 73 | }, 74 | { 75 | "cell_type": "markdown", 76 | "metadata": {}, 77 | "source": [ 78 | "Choose some howework from the statistics course that you've done in R and try to rewrite it using numpy." 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [] 87 | } 88 | ], 89 | "metadata": { 90 | "kernelspec": { 91 | "display_name": "Python3.9", 92 | "language": "python", 93 | "name": "python3.9" 94 | }, 95 | "language_info": { 96 | "codemirror_mode": { 97 | "name": "ipython", 98 | "version": 3 99 | }, 100 | "file_extension": ".py", 101 | "mimetype": "text/x-python", 102 | "name": "python", 103 | "nbconvert_exporter": "python", 104 | "pygments_lexer": "ipython3", 105 | "version": "3.6.13" 106 | } 107 | }, 108 | "nbformat": 4, 109 | "nbformat_minor": 4 110 | } 111 | -------------------------------------------------------------------------------- /python/Exercises3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "d11517f7-d25e-4ddd-8cf5-95cf809e8bb5", 6 | "metadata": {}, 7 | "source": [ 8 | "### **Exercise1:**\n", 9 | "\n", 10 | "Create your own class for complex numbers, just like you would in c++. Make sure all the arithmetic operations work (yes, this is another useless exercise to play with the syntax)." 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "id": "ea29074e-7dd7-48c6-bfd9-03860cffc268", 16 | "metadata": {}, 17 | "source": [ 18 | "### **Exercise2:**\n", 19 | "\n", 20 | "Rewrite your jacobi solution from the previous exerxise set with classes (you can follow the same layout as the c++ solution)." 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "id": "a3f9dbca-8146-41ae-a859-792866cd4419", 26 | "metadata": {}, 27 | "source": [ 28 | "### **Exercise3:**\n", 29 | "\n", 30 | "Write a `cython` module with a function that solves the quadratic equation (you don't need to use classes here for now)" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "id": "00f9ee84-b578-4187-936a-225ddaef1f74", 36 | "metadata": {}, 37 | "source": [ 38 | "### **Exercise4:**\n", 39 | "\n", 40 | "Use `pibind` to call the c++ code for jacobi (from the the extra_exercises solutions) " 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "id": "06510615-d3b2-45e7-83c5-92f32ed88332", 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [] 50 | } 51 | ], 52 | "metadata": { 53 | "kernelspec": { 54 | "display_name": "Python 3 (ipykernel)", 55 | "language": "python", 56 | "name": "python3" 57 | }, 58 | "language_info": { 59 | "codemirror_mode": { 60 | "name": "ipython", 61 | "version": 3 62 | }, 63 | "file_extension": ".py", 64 | "mimetype": "text/x-python", 65 | "name": "python", 66 | "nbconvert_exporter": "python", 67 | "pygments_lexer": "ipython3", 68 | "version": "3.10.8" 69 | } 70 | }, 71 | "nbformat": 4, 72 | "nbformat_minor": 5 73 | } 74 | -------------------------------------------------------------------------------- /python/Exercises4.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### **Exercise1:**\n", 8 | "\n", 9 | "Create a function returning the first N terms of the tailor series of the function without using the sympy `series` function." 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "### **Exercise2:**" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "Create a decorator that checks if the passed array is empty and only calls the function if it's not" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "### **Exercise3:**" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "Create a decorator to time a function execution time. Hint: use `import time` and `time_point=time.time()`. You can check if it's correct by timing the `time.sleep` function." 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "### **Exercise4:**" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "Create a decorator to plot a function over some fixed interval." 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [] 60 | } 61 | ], 62 | "metadata": { 63 | "kernelspec": { 64 | "display_name": "Python 3", 65 | "language": "python", 66 | "name": "python3" 67 | }, 68 | "language_info": { 69 | "codemirror_mode": { 70 | "name": "ipython", 71 | "version": 3 72 | }, 73 | "file_extension": ".py", 74 | "mimetype": "text/x-python", 75 | "name": "python", 76 | "nbconvert_exporter": "python", 77 | "pygments_lexer": "ipython3", 78 | "version": "3.6.13" 79 | } 80 | }, 81 | "nbformat": 4, 82 | "nbformat_minor": 4 83 | } 84 | -------------------------------------------------------------------------------- /python/Exercises5.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### **Exercise1:**\n", 8 | "\n", 9 | "Create a dictionary out of two given lists. Then delete the elements from the second list." 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "### **Exercise2:**\n", 17 | "\n", 18 | "Use the code from the old C++ bisection exercise (lecture 1) to create a C library and call it from python." 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "### **Exercise3:**\n", 26 | "\n", 27 | "Modify the jacobi solution from the extra exercises to return a pointer to an array with the solution. Then call all that from python. " 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [] 36 | } 37 | ], 38 | "metadata": { 39 | "kernelspec": { 40 | "display_name": "Python3.9", 41 | "language": "python", 42 | "name": "python3.9" 43 | }, 44 | "language_info": { 45 | "codemirror_mode": { 46 | "name": "ipython", 47 | "version": 3 48 | }, 49 | "file_extension": ".py", 50 | "mimetype": "text/x-python", 51 | "name": "python", 52 | "nbconvert_exporter": "python", 53 | "pygments_lexer": "ipython3", 54 | "version": "3.6.13" 55 | } 56 | }, 57 | "nbformat": 4, 58 | "nbformat_minor": 4 59 | } 60 | -------------------------------------------------------------------------------- /python/Exercises6.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### **Exercise1:**\n", 8 | "\n", 9 | "Give students in the `example.csv` file a bonus of 5 for all the courses. Find a way to replace all the values that are now greater than 30 by 30. Save the new data to a file. Make a plot with histograms for every course in the example file." 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "### **Exercise2:**\n", 17 | "\n", 18 | " - Read in the `cars.csv` file as a dataframe\n", 19 | " - Remove the row with the index 3, which contains a quote in the Model column.\n", 20 | " - Add a new column called Price with the following values: [8000, 6500, 7000, 6800, 7500, 7300, 7000, 9000, 6500, 7800]\n", 21 | " - Replace all values in the Make column that are Ford with Toyota.\n", 22 | " - Find the average Length of all the vehicles.\n", 23 | " - Find the median Price of all the vehicles.\n", 24 | " - Create a new dataframe that only contains the rows where the Price is greater than 7000.\n", 25 | " - Create a new dataframe that only contains the rows where the Make is Toyota and the Price is greater than 7000.\n", 26 | " - Sort the dataframe in descending order by the Price column.\n" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [] 35 | } 36 | ], 37 | "metadata": { 38 | "kernelspec": { 39 | "display_name": "Python 3", 40 | "language": "python", 41 | "name": "python3" 42 | }, 43 | "language_info": { 44 | "codemirror_mode": { 45 | "name": "ipython", 46 | "version": 3 47 | }, 48 | "file_extension": ".py", 49 | "mimetype": "text/x-python", 50 | "name": "python", 51 | "nbconvert_exporter": "python", 52 | "pygments_lexer": "ipython3", 53 | "version": "3.6.13" 54 | } 55 | }, 56 | "nbformat": 4, 57 | "nbformat_minor": 4 58 | } 59 | -------------------------------------------------------------------------------- /python/anim.py: -------------------------------------------------------------------------------- 1 | #run this file with `python anim.py` from command line 2 | #open the .gif in whatever you usually open them with to check that it worked 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | import matplotlib.animation as animation 6 | fig=plt.figure() 7 | #you can put something depending on i here 8 | def animate(i): 9 | plt.imshow(np.random.random((50,50))) 10 | 11 | anim = animation.FuncAnimation(fig,animate,frames=10, interval=10) 12 | 13 | # save the animation as an gif 14 | anim.save("animation_example.gif") 15 | -------------------------------------------------------------------------------- /python/cars.csv: -------------------------------------------------------------------------------- 1 | Year,Make,Model,Length 2 | 1997,Ford,E350,2.34 3 | 2000,Mercury,Cougar,2.38 4 | 1993,Chevrolet,Venture "Extended Edition" ,3.2 5 | 1999,Jeep,Grand Cherokee,2.56 6 | 1998,Dodge,Intrepid,3.01 7 | 1997,Ford,E350,2.34 8 | 1999,Ford,E350,2.34 9 | 1996,Ford,Mustang,2.37 10 | 2000,Ford,Mustang,2.34 11 | 1997,Ford,Taurus,2.34 12 | -------------------------------------------------------------------------------- /python/conda.md: -------------------------------------------------------------------------------- 1 | ### conda 2 | 3 | the best way to install Python and manage the environments is using `conda`. You can choose between `anaconda` and `miniconda`, the latter being preferable as it's much smaller (doesn't install much by default). 4 | 5 | For windows, look for "anaconda prompt". 6 | 7 | Once installed, to make sure you have the latest version, run 8 | 9 | ``` 10 | conda update conda` 11 | ``` 12 | 13 | To create an environment, do: 14 | 15 | ``` 16 | conda create --name my_new_env 17 | ``` 18 | 19 | To activate: 20 | 21 | ``` 22 | conda activate my_new_env 23 | ``` 24 | 25 | To install packages (for example, numpy): 26 | 27 | ``` 28 | conda install numpy 29 | ``` 30 | 31 | To see what you have installed: 32 | 33 | ``` 34 | conda list 35 | ``` 36 | 37 | To deactivate an environment: 38 | 39 | ``` 40 | conda deactivate 41 | ``` 42 | 43 | To view all the environments: 44 | 45 | ``` 46 | conda env list 47 | ``` 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /python/example.csv: -------------------------------------------------------------------------------- 1 | name,course1,course2,course3,course4 2 | Marie,24,18,30,20 3 | John,18,27,29,27 4 | Kati,21,24,28,27 5 | Olaf,30,30,29,30 6 | Mark,24,25,27,21 7 | Olga,23,26,30,30 8 | Jean,18,28,26,24 9 | Alex,19,20,27,27 10 | Pier,24,29,23,26 11 | Bennet,24,25,26,30 12 | Luis,20,20,18,18 13 | -------------------------------------------------------------------------------- /python/example_empty.csv: -------------------------------------------------------------------------------- 1 | name,course1,course2,course3,course4 2 | Marie,24,18,30,20 3 | John,18,27,29,27 4 | Kati,21,24,28,27 5 | Olaf,30,30,29,30 6 | Mark,,25,27,21 7 | Olga,23,26,30,30 8 | Jean,18,28,26,24 9 | Alex,19,,27,27 10 | Pier,24,29,23,26 11 | Bennet,24,25,26,30 12 | Luis,20,20,18,18 13 | -------------------------------------------------------------------------------- /python/pybind11/matrix_cpp.cpp: -------------------------------------------------------------------------------- 1 | #include "matrix_cpp.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | PYBIND11_MODULE(matrix_cpp, m) { 8 | m.doc() = "This module uses the c++ code to perform simple matrix multiplications"; // optional mdule docstring 9 | 10 | m.def("test_func", &old_main, "execute old main code"); 11 | using DCMatrix = CMatrix; 12 | pybind11::class_ (m, "CMatrix") 13 | .def(pybind11::init<>()) 14 | .def("read_from_file",&DCMatrix::read_from_file) 15 | .def("print_to_file",&DCMatrix::print_to_file) 16 | .def("multiply",&DCMatrix::operator*) 17 | .def("assign", 18 | static_cast< DCMatrix&(DCMatrix::*)( const DCMatrix &) > 19 | (&DCMatrix::operator=) 20 | ) 21 | .def("get_data", [](const DCMatrix & d) 22 | { 23 | //allocate copy of matrix data and pass it to python domain 24 | //Python decides when to destroy the object. 25 | //The data is completely given to the python world 26 | 27 | if (d.size <=0 ) { 28 | throw std::runtime_error("matrix is empty"); 29 | } 30 | auto * python_data = new double[d.size*d.size]; 31 | std::copy(d.data.begin(),d.data.end(),python_data); 32 | 33 | //little routine that is called when 34 | // the object is collected by the garbage collector 35 | pybind11::capsule free_when_done(python_data, [] (void * pointer) { 36 | std::cout << "freeing memory @ " << pointer <(pointer); 38 | }); 39 | 40 | return pybind11::array_t( // array_t is in pybind11/numpy.h 41 | {{d.size,d.size}},//shape 42 | {d.size*sizeof(double),sizeof(double)}, //stride 43 | python_data, 44 | free_when_done 45 | ); 46 | 47 | } 48 | ) 49 | .def("set_data",[](DCMatrix &d, const pybind11::buffer numpy_matrix) 50 | { 51 | //get info of python array 52 | pybind11::buffer_info info{numpy_matrix.request()}; 53 | //check that we are dealing with an array of double 54 | if (info.format != pybind11::format_descriptor::format()) { 55 | throw std::runtime_error("we can accept only a matrix made with C double type"); 56 | } 57 | //sanity check 58 | if (info.ndim != 2) { 59 | throw std::runtime_error("dimension of array must be 2"); 60 | } 61 | if (info.shape[0] != info.shape[1]){ 62 | throw std::runtime_error("we implemented only square matrices, sorry"); 63 | } 64 | if (info.shape[0]<=0) { 65 | throw std::runtime_error("dimension of the matrix is zero"); 66 | } 67 | // to simplify the logic, implement only contiguous arrays. Check that the array is contiguous 68 | ssize_t stride=sizeof(double); 69 | for (int i=info.ndim-1;i>=0;--i){ 70 | if (info.strides[i] != stride) { 71 | throw std::runtime_error("sorry, we don't support non contiguous matrices"); 72 | } 73 | stride *= info.shape[i]; 74 | } 75 | 76 | //all sanity checks are passed, copy the data 77 | d = DCMatrix(info.shape[0]); //use assignment to not write other code... 78 | std::copy(static_cast(info.ptr),static_cast(info.ptr)+info.shape[0]*info.shape[1],d.data.begin()); 79 | //c++ is responsable of this data 80 | } 81 | ) 82 | ; 83 | 84 | } 85 | 86 | -------------------------------------------------------------------------------- /python/pybind11/matrix_cpp.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | 7 | template 8 | class CMatrix { 9 | public: 10 | int size; 11 | std::vector data; 12 | CMatrix(int N){ 13 | size = N; 14 | data.resize(N*N); 15 | } 16 | CMatrix(){}; 17 | void print_to_file(const std::string& file); 18 | void read_from_file(const std::string& file); 19 | CMatrix operator*(const CMatrix& B); 20 | 21 | }; 22 | 23 | 24 | template 25 | void CMatrix::read_from_file(const std::string& file){ 26 | std::ifstream filevar(file); 27 | if(filevar){ 28 | filevar>>size; 29 | data.resize(size*size); 30 | for (int i=0;i>data[i*size+j]; 33 | } 34 | } 35 | filevar.close();} 36 | else{ 37 | std::cout<<"coudn't open the file "< 44 | void CMatrix::print_to_file(const std::string& file){ 45 | std::ofstream filevar(file); 46 | filevar< 57 | CMatrix CMatrix::operator*(const CMatrix& B){ 58 | if (size != B.size) { 59 | std::cout<<"The two matrices are not of the same size! The result will be nonsense."< C(size); 62 | for (int i=0;i A,B; 76 | A.read_from_file("A.txt"); 77 | B.read_from_file("B.txt"); 78 | auto C=A*B; 79 | C.print_to_file("C.txt"); 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /python/python_exam_questions.md: -------------------------------------------------------------------------------- 1 | [I consider c++ more important, so there are less python questions than c++ ones, and no advanced questions. I will compile all the c++ questions into one file before New Year. At the exam, the questions will come in random order (to make it harder to cheat).] 2 | 3 | How do you create markdown cell in Jupyter? (with keyboard commands) 4 | 5 | How do you delete a cell in Jupyter (with keyboard command)? 6 | 7 | How do you add a cell above the current one in Jupyter (with keyboard command)? 8 | 9 | What advantage does conda environment provide over a system-wide installation of python? 10 | 11 | What does it mean that variables are dynamically typed in python? 12 | 13 | What's the difference between python and C/C++ integers? 14 | 15 | Explain the difference between lists, sets and tuples in python. 16 | 17 | What does negative index mean when accessing list elements? 18 | 19 | How do you print the first N elements of a list? 20 | 21 | How do you print every Nth element of a list? 22 | 23 | How do you print the reverse list? 24 | 25 | Give an example of a list comprehension. 26 | 27 | Give an example of cell and line magic commands in Jupyter. 28 | 29 | Write a "hello world" function in python (syntax errors are not ok in hello world even on paper). 30 | 31 | What are keyword function arguments in python and what is their advantage? 32 | 33 | Why shouldn't you do `from numpy import *`? 34 | 35 | What is the advantage of using numpy arrays over lists? What are the dangers? 36 | 37 | What's the most widely used package for plotting in python? 38 | 39 | What's the purpose of `__str__` method in a python class? 40 | 41 | What package can you use in python for symbolic calculations? 42 | 43 | What are decorators? Write an example (minor syntax errors are ok here) 44 | 45 | Name two ways of calling c++ code from python. 46 | 47 | What is pandas? Name at least 5 functions from that package. 48 | 49 | Wrong code snippets: 50 | 51 | Snippet 1 52 | ``` 53 | if x==0: 54 | print('x is zero') 55 | elif x>0: 56 | print('x is greater then zero') 57 | elif x<0: 58 | print('x is smaller than zero') 59 | ``` 60 | Snippet 2: 61 | ``` 62 | t = tuple(range(10)) 63 | t[5]=100 64 | print(t[5]) 65 | ``` 66 | 67 | Snippet 3: 68 | ``` 69 | class MySecondClass: 70 | def __init__(number): 71 | self.number = number 72 | a=MySecondClass(4) 73 | ``` 74 | 75 | -------------------------------------------------------------------------------- /python/shapes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | template 6 | struct coords { 7 | T x,y; 8 | void set_coords(const T& x0, const T& y0){ 9 | x=x0;y=y0; 10 | } 11 | void print(){ 12 | std::cout<<"("< 17 | T distance( coords p1, coords p2){ 18 | return sqrt( (p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y) ); 19 | } 20 | 21 | template 22 | class CShape { 23 | public: 24 | virtual T perimeter()=0; 25 | virtual void print_vertices ()=0; 26 | virtual ~CShape(){}; 27 | }; 28 | 29 | template 30 | class CTriangle: public CShape { 31 | public: 32 | coords p1,p2,p3; 33 | CTriangle(const std::vector& myvertices); 34 | T perimeter() override; 35 | void print_vertices() override; 36 | };//CTriangle 37 | 38 | template 39 | CTriangle::CTriangle ( const std::vector& myvertices ) { 40 | if (myvertices.size() == 6) { 41 | p1.set_coords(myvertices[0],myvertices[1]); 42 | p2.set_coords(myvertices[2],myvertices[3]); 43 | p3.set_coords(myvertices[4],myvertices[5]); 44 | } else{ 45 | std::cout << "This is not a triangle! Use polygon instead." << std::endl; exit(1); 46 | } 47 | }//constructor 48 | 49 | 50 | 51 | template 52 | T CTriangle::perimeter(){ 53 | return distance(p1,p2)+distance(p1,p3)+distance(p2,p3); 54 | }; 55 | 56 | template 57 | void CTriangle::print_vertices() { 58 | std::cout << "The vertex coordinates are" << std::endl; 59 | p1.print(); p2.print(); p3.print(); 60 | std::cout << std::endl; 61 | }//print 62 | 63 | 64 | template 65 | class CPolygon: public CShape { 66 | public: 67 | coords* vertices;//they should be given in order 68 | int Nv; 69 | 70 | CPolygon(const std::vector& myvertices); 71 | 72 | T perimeter() override; 73 | 74 | void print_vertices() override{ 75 | std::cout << "The vertex coordinates are" << std::endl; 76 | for (int i=0;i 92 | CPolygon::CPolygon ( const std::vector& myvertices ){ 93 | Nv = myvertices.size()/2; 94 | vertices = new coords[Nv]; 95 | for (int i=0;i 101 | T CPolygon::perimeter(){ 102 | T result = 0; 103 | for (int i=0;i tr({0,0,1,0,1,1}); 113 | CShape * shape1 = &tr; 114 | std::cout << shape1->perimeter() << std::endl; 115 | shape1->print_vertices(); 116 | 117 | CPolygon pol({0,0,1,0,1,1,0,1}); 118 | CShape * shape2 = &pol; 119 | std::cout << shape2->perimeter() << std::endl; 120 | shape2->print_vertices(); 121 | 122 | 123 | return 0; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /solutions/extra/jacobi/gif.gp: -------------------------------------------------------------------------------- 1 | set terminal gif animate delay 5 2 | set output 'jacobi.gif' 3 | 4 | 5 | set size square 6 | unset colorbox 7 | set palette rgb 33,13,10 8 | set yr [] reverse #otherwise it flips the image due to default axis orientation 9 | 10 | mod = 10 11 | 12 | do for [i=0:(system("ls gif_dir/ | wc -l")-1)/mod] { 13 | num=mod*i 14 | plot './gif_dir/'.num.'.dat' matrix with image title "Frame".i."/".(system("ls gif_dir/ | wc -l")/mod) 15 | } 16 | 17 | 18 | reset 19 | set output 20 | set terminal qt #just to return back to normal output terminal; MIGHT NOT BE QT ON YOUR SYSTEM 21 | 22 | 23 | -------------------------------------------------------------------------------- /solutions/extra/jacobi/include/mesh.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | template 9 | void initialize(std::vector& data, size_t Ncells){ 10 | //initialize border 11 | for (size_t i=0;i 33 | class CMesh{ 34 | public: 35 | size_t Ncells; 36 | T step; 37 | std::vector cells; 38 | std::vector field; 39 | std::vector new_field; 40 | //constructor 41 | CMesh(size_t N); 42 | void print(const std::string& file_name); 43 | }; 44 | 45 | 46 | template 47 | CMesh::CMesh (size_t N):Ncells{N}{ 48 | field.resize(N*N); 49 | new_field.resize(N*N); 50 | initialize(field, Ncells); 51 | initialize(new_field, Ncells); 52 | };//constructor 53 | 54 | 55 | template 56 | void CMesh::print(const std::string& file_name){ 57 | std::ofstream filevar(file_name); 58 | for (size_t i=0;i 4 | #include 5 | 6 | template 7 | class CSolver{ 8 | public: 9 | //Jacobi iterative solver 10 | void jacobi(CMesh& m, const int& steps); 11 | }; 12 | 13 | template 14 | void CSolver::jacobi(CMesh& m, const int& steps) { 15 | 16 | for (size_t s=0; s 2 | 3 | #include "mesh.hpp" 4 | #include "solver.hpp" 5 | 6 | int main(){ 7 | CMesh data(102); 8 | 9 | //this is here just to test that the initial function set up worked 10 | data.print("./gif_dir/0.dat"); 11 | 12 | //create a variable of a solver class 13 | CSolver solve; 14 | 15 | //actually solve the equation 16 | solve.jacobi(data,10000); 17 | 18 | return 0; 19 | }; 20 | -------------------------------------------------------------------------------- /solutions/extra/linked_list/include/list.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | template 6 | struct Node{ 7 | T val; 8 | Node *next; 9 | }; 10 | 11 | template 12 | class LinkedList{ 13 | public: 14 | Node *head = nullptr; 15 | //constructor to init faster 16 | LinkedList(const std::vector& vals); 17 | //copy constructor 18 | LinkedList(const LinkedList& LL); 19 | void push_back(const int& val); 20 | void print() const; 21 | ~LinkedList(); 22 | LinkedList& operator=(const LinkedList& LL) = delete; 23 | };//class 24 | 25 | //copy constructor 26 | template 27 | LinkedList::LinkedList (const LinkedList& LL) { 28 | Node* temp; 29 | temp=LL.head; 30 | while(temp!=nullptr){ 31 | push_back(temp->val); 32 | temp=temp->next; 33 | } 34 | }//constructor 35 | 36 | 37 | template 38 | LinkedList::LinkedList (const std::vector& vals ) { 39 | for (int i=0;i 46 | void LinkedList::print() const { 47 | Node *current = head; 48 | while (current!=nullptr) { 49 | std::cout<< current->val<<" "; 50 | current = current->next; 51 | } 52 | std::cout< 57 | void LinkedList::push_back (const int& val0 ) { 58 | if (head==nullptr){ 59 | head=new Node; 60 | head->next=nullptr; 61 | head->val=val0; 62 | }else{ 63 | Node* temp=head; 64 | while (temp->next!=nullptr) { 65 | temp=temp->next; 66 | } 67 | temp->next=new Node; 68 | temp->next->next=nullptr; 69 | temp->next->val=val0; 70 | } 71 | }//push back 72 | 73 | 74 | template 75 | LinkedList::~LinkedList() { 76 | Node *temp; 77 | while (head != nullptr) { 78 | temp=head->next; 79 | delete head; 80 | head=temp; 81 | } 82 | }//destructor 83 | 84 | -------------------------------------------------------------------------------- /solutions/extra/linked_list/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "list.hpp" 3 | 4 | int main(){ 5 | LinkedList L({5,3,1,6,7,0,99}); 6 | LinkedList M(L); 7 | L.print(); 8 | M.print(); 9 | } 10 | -------------------------------------------------------------------------------- /solutions/lecture1/convert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include //don't worry about this, it's to check the result 4 | #include 5 | 6 | int main(){ 7 | int number{78941}; 8 | //our binary shouldn't have more the 64 digits 9 | int arr[64]; 10 | int counter{0}; 11 | 12 | while(number!=0){ 13 | arr[counter] = number%2;//reminder of division by 2 14 | counter=counter+1; 15 | number =number/2; 16 | } 17 | //need to print in the inverse order 18 | for(int j=counter-1;j>=0;j--){ 19 | std::cout<(78941).to_string()< 2 | #include 3 | 4 | //the exercise came before you knew what functions are 5 | //that was by design so that you would feel the strong need for them 6 | double f(const double& x){ 7 | return x*x*x - 6*x*x + 11*x -6; 8 | }; 9 | 10 | int main(){ 11 | double a{-10},b{10},m{0}; 12 | //sanity check for different signs at the end of the interval 13 | if (((f(a)<0)&&(f(b)<0))||((f(a)>0)&&(f(b)>0))){ 14 | std::cout<<"bisection won't work in this interval, the function has the same signs at both ends"< 1e-9 ){ 18 | //to avoid potentially expensive recalculation 19 | double fa=f(a); 20 | double fb=f(b); 21 | //maybe be already found the root? 22 | if(std::fabs(fa) < 1e-9){ 23 | m=a; 24 | break; 25 | }else if(std::fabs(fb) < 1e-9){ 26 | m=b; 27 | break; 28 | } 29 | //actual bisection 30 | if ((f(m)>0)&&(fa<0)) { 31 | b=m; 32 | }else { 33 | a=m; 34 | } 35 | m=(a+b)/2; 36 | }//of while 37 | 38 | std::cout<<"The root is close to "< 2 | #include //need this for std::swap 3 | 4 | int main(){ 5 | const int N{7}; 6 | int arr[N]; 7 | //it's nice to first tell the user what your program is doing 8 | std::cout<< "This program will sort an array of size "<>arr[i]; 12 | } 13 | //don't worry about the algorithm efficiency, you will have it in the second semester 14 | //go through an array, compare numbers to the one in first place 15 | //if they are not in order, switch 16 | //repeat for the next element and so on 17 | for(int i = 0; i 2 | #include //need this for std::swap 3 | #include 4 | 5 | class CCoeffs{ 6 | public: 7 | double a; 8 | double b; 9 | double c; 10 | }; 11 | 12 | 13 | int main(){ 14 | //it's nice to first tell the user what your program is doing 15 | std::cout<<"This program solves a quadratic equation "<> coeffs.a >> coeffs.b >> coeffs.c; 19 | 20 | if(coeffs.a==0){ 21 | std::cout<<"This is not a quadratic equation, a=0, I refuse to solve this. Try again."; 22 | exit(1); 23 | } 24 | 25 | double discr = coeffs.b*coeffs.b - 4*coeffs.a*coeffs.c; 26 | double root; 27 | if (discr >= 0){ 28 | //for performance (which doesn't matter now, but can in general) 29 | //we calculate the complicated math only once 30 | double inv2a=1/(2*coeffs.a); 31 | double root_of_discr = std::sqrt(discr); 32 | double root1 = (-coeffs.b + root_of_discr)*inv2a; 33 | double root2 = (-coeffs.b - root_of_discr)*inv2a; 34 | 35 | std::cout<< "The roots are: "<< root1 << " "< 2 | #include 3 | 4 | class CCoeffs{ 5 | public: 6 | double a; 7 | double b; 8 | double c; 9 | CCoeffs(){ 10 | a=0;b=0;c=0; 11 | }; 12 | void ask_for_input(); 13 | void print(); 14 | }; 15 | 16 | void CCoeffs::ask_for_input() { 17 | std::cout<<"Please enter the ax^2+bx+c=0 equation's coefficients"<> a >> b >> c; 19 | 20 | if(a==0){ 21 | std::cout<<"This is not a quadratic equation, a=0, I refuse to solve this. Try again."; 22 | exit(1); 23 | } 24 | } 25 | 26 | void CCoeffs::print() { 27 | std::cout<<"The equation has the following coefficients:"<= 0){ 34 | //for performance (which doesn't matter now, but can in general) 35 | //we calculate the complicated math only once 36 | double inv2a=1/(2*coeffs.a); 37 | double root_of_discr = std::sqrt(discr); 38 | double root1 = (-coeffs.b + root_of_discr)*inv2a; 39 | double root2 = (-coeffs.b - root_of_discr)*inv2a; 40 | 41 | std::cout<< "The roots are: "<< root1 << " "< 3 | #include 4 | 5 | class CCoeffs{ 6 | public: 7 | double a; 8 | double b; 9 | double c; 10 | CCoeffs(){ 11 | a=0;b=0;c=0; 12 | }; 13 | void ask_for_input(); 14 | void print(); 15 | }; 16 | 17 | void CCoeffs::ask_for_input() { 18 | std::cout<<"Please enter the ax^2+bx+c=0 equation's coefficients"<> a >> b >> c; 20 | 21 | if(a==0){ 22 | std::cout<<"This is not a quadratic equation, a=0, I refuse to solve this. Try again."; 23 | exit(1); 24 | } 25 | } 26 | 27 | void CCoeffs::print() { 28 | std::cout<<"The equation has the following coefficients:"<= 0){ 53 | //for performance (which doesn't matter now, but can in general) 54 | //we calculate the complicated math only once 55 | double inv2a=1/(2*coeffs.a); 56 | double root_of_discr = std::sqrt(discr); 57 | sol1.r = (-coeffs.b + root_of_discr)*inv2a; 58 | sol2.r = (-coeffs.b - root_of_discr)*inv2a; 59 | 60 | } else { 61 | double inv2a=1/(2*coeffs.a); 62 | double root_of_discr = std::sqrt(-discr); 63 | sol1.r=-coeffs.b*inv2a; sol1.im=root_of_discr*inv2a; 64 | sol2.r=-coeffs.b*inv2a; sol2.im=-root_of_discr*inv2a; 65 | } 66 | 67 | }//solve_quadratic_equation 68 | 69 | void CQuadratic_Equation::print_solution() { 70 | //not the best printing format 71 | std::cout<<"solutions are: "< 2 | 3 | void print(int* arr, int N){ 4 | if(N==1){ 5 | std::cout< 2 | 3 | class CComplex{ 4 | public: 5 | double x; 6 | double y; 7 | CComplex(const double& x0,const double& y0):x(x0),y(y0){}; 8 | CComplex operator+(const CComplex& var); 9 | CComplex operator*(const CComplex& var); 10 | CComplex operator-(const CComplex& var); 11 | CComplex operator/(const CComplex& var);//lecturer is lazy to type this one 12 | friend std::ostream& operator<<(std::ostream& os, const CComplex& c); 13 | 14 | }; 15 | 16 | std::ostream& operator<<(std::ostream& os, const CComplex& c){ 17 | if(c.y>0){ 18 | os< 2 | 3 | #include "coeffs.hpp" 4 | #include "eq.hpp" 5 | 6 | 7 | int main(){ 8 | //it's nice to first tell the user what your program is doing 9 | std::cout<<"This program solves a quadratic equation "< 3 | 4 | void CCoeffs::ask_for_input() { 5 | std::cout<<"Please enter the ax^2+bx+c=0 equation's coefficients"<> a >> b >> c; 7 | 8 | if(a==0){ 9 | std::cout<<"This is not a quadratic equation, a=0, I refuse to solve this. Try again."; 10 | exit(1); 11 | } 12 | } 13 | 14 | void CCoeffs::print() { 15 | std::cout<<"The equation has the following coefficients:"< 4 | #include 5 | 6 | void CQuadratic_Equation::solve() { 7 | double discr = coeffs.b*coeffs.b - 4*coeffs.a*coeffs.c; 8 | if (discr >= 0){ 9 | //for performance (which doesn't matter now, but can in general) 10 | //we calculate the complicated math only once 11 | double inv2a=1/(2*coeffs.a); 12 | double root_of_discr = std::sqrt(discr); 13 | sol1.r = (-coeffs.b + root_of_discr)*inv2a; 14 | sol2.r = (-coeffs.b - root_of_discr)*inv2a; 15 | 16 | } else { 17 | double inv2a=1/(2*coeffs.a); 18 | double root_of_discr = std::sqrt(-discr); 19 | sol1.r=-coeffs.b*inv2a; sol1.im=root_of_discr*inv2a; 20 | sol2.r=-coeffs.b*inv2a; sol2.im=-root_of_discr*inv2a; 21 | } 22 | 23 | }//solve_quadratic_equation 24 | 25 | void CQuadratic_Equation::print_solution() { 26 | //not the best printing format 27 | std::cout<<"solutions are: "< 2 | //solution is in one file for the sake of presenting 3 | 4 | /*template 5 | class CComplex; 6 | 7 | template 8 | std::ostream& operator<< (std::ostream& os, const CComplex& c) ; 9 | */ 10 | 11 | template 12 | class CComplex{ 13 | public: 14 | T x; 15 | T y; 16 | CComplex(const T& x0,const T& y0):x(x0),y(y0){}; 17 | CComplex operator+(const CComplex& var); 18 | CComplex operator*(const CComplex& var); 19 | CComplex operator-(const CComplex& var); 20 | CComplex operator/(const CComplex& var);//lecturer is lazy to type this one 21 | template 22 | friend std::ostream& operator<<(std::ostream& os, const CComplex& c); 23 | 24 | }; 25 | 26 | template 27 | std::ostream& operator<<(std::ostream& os, const CComplex& c){ 28 | if(c.y>0){ 29 | os< 39 | CComplex CComplex::operator+ ( const CComplex& var ) { 40 | CComplex result(0,0); 41 | result.x=x+var.x; 42 | result.y=y+var.y; 43 | return result; 44 | } 45 | 46 | template 47 | CComplex CComplex::operator- ( const CComplex& var ) { 48 | CComplex result(0,0); 49 | result.x=x-var.x; 50 | result.y=y-var.y; 51 | return result; 52 | } 53 | 54 | template 55 | CComplex CComplex::operator* ( const CComplex& var ) { 56 | CComplex result(0,0); 57 | result.x=x*var.x-y*var.y; 58 | result.y=x*var.y+y*var.x; 59 | return result; 60 | } 61 | 62 | 63 | 64 | int main(){ 65 | 66 | CComplex a(1,2),b(3,4); 67 | std::cout< 3 | 4 | template 5 | class CCoeffs{ 6 | public: 7 | T a; 8 | T b; 9 | T c; 10 | CCoeffs(){ 11 | a=0;b=0;c=0; 12 | }; 13 | void ask_for_input(); 14 | void print(); 15 | }; 16 | 17 | template 18 | void CCoeffs::ask_for_input() { 19 | std::cout<<"Please enter the ax^2+bx+c=0 equation's coefficients"<> a >> b >> c; 21 | 22 | if(a==0){ 23 | std::cout<<"This is not a quadratic equation, a=0, I refuse to solve this. Try again."; 24 | exit(1); 25 | } 26 | } 27 | 28 | template 29 | void CCoeffs::print() { 30 | std::cout<<"The equation has the following coefficients:"< 4 | #include 5 | 6 | template 7 | struct myComplex{ 8 | T r; 9 | T im; 10 | }; 11 | 12 | template 13 | class CQuadratic_Equation{ 14 | public: 15 | CCoeffs coeffs; 16 | myComplex sol1; 17 | myComplex sol2; 18 | CQuadratic_Equation(){ 19 | sol1.r=0;sol2.r=0;sol1.im=0;sol2.im=0; 20 | }; 21 | void solve(); 22 | void print_solution(); 23 | }; 24 | 25 | template 26 | void CQuadratic_Equation::solve() { 27 | double discr = coeffs.b*coeffs.b - 4*coeffs.a*coeffs.c; 28 | if (discr >= 0){ 29 | //for performance (which doesn't matter now, but can in general) 30 | //we calculate the complicated math only once 31 | double inv2a=1/(2*coeffs.a); 32 | double root_of_discr = std::sqrt(discr); 33 | sol1.r = (-coeffs.b + root_of_discr)*inv2a; 34 | sol2.r = (-coeffs.b - root_of_discr)*inv2a; 35 | 36 | } else { 37 | double inv2a=1/(2*coeffs.a); 38 | double root_of_discr = std::sqrt(-discr); 39 | sol1.r=-coeffs.b*inv2a; sol1.im=root_of_discr*inv2a; 40 | sol2.r=-coeffs.b*inv2a; sol2.im=-root_of_discr*inv2a; 41 | } 42 | 43 | }//solve_quadratic_equation 44 | 45 | template 46 | void CQuadratic_Equation::print_solution() { 47 | //not the best printing format 48 | std::cout<<"solutions are: "< 2 | 3 | #include "coeffs.hpp" 4 | #include "eq.hpp" 5 | 6 | //you don't need a makefile anymore, compile with -Iinclude 7 | 8 | int main(){ 9 | //it's nice to first tell the user what your program is doing 10 | std::cout<<"This program solves a quadratic equation "< eq; 12 | eq.coeffs.ask_for_input(); 13 | eq.coeffs.print(); 14 | eq.solve(); 15 | eq.print_solution(); 16 | 17 | return 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /solutions/lecture4/matrix.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | 13 | template 14 | class CMatrix { 15 | public: 16 | int size; 17 | std::vector data; 18 | CMatrix(int N){ 19 | size = N; 20 | data.resize(N*N); 21 | } 22 | CMatrix(){}; 23 | void print_to_file(const std::string& file); 24 | void read_from_file(const std::string& file); 25 | CMatrix operator*(const CMatrix& B); 26 | 27 | }; 28 | 29 | 30 | template 31 | void CMatrix::read_from_file(const std::string& file){ 32 | std::ifstream filevar(file); 33 | if(filevar){ 34 | filevar>>size; 35 | data.resize(size*size); 36 | for (int i=0;i>data[i*size+j]; 39 | } 40 | } 41 | filevar.close();} 42 | else{ 43 | std::cout<<"coudn't open the file "< 50 | void CMatrix::print_to_file(const std::string& file){ 51 | std::ofstream filevar(file); 52 | filevar< 63 | CMatrix CMatrix::operator*(const CMatrix& B){ 64 | if (size != B.size) { 65 | std::cout<<"The two matrices are not of the same size! The result will be nonsense."< C(size); 68 | for (int i=0;i A,B; 82 | A.read_from_file("A.txt"); 83 | B.read_from_file("B.txt"); 84 | auto C=A*B; 85 | C.print_to_file("C.txt"); 86 | 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /solutions/lecture4/sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | template 3 | T sumall(T sum){ 4 | return sum; 5 | } 6 | 7 | template 8 | T sumall(T sum, const Types&... summands){ 9 | return sum + sumall(summands...); 10 | } 11 | 12 | 13 | int main (int argc, char **argv){ 14 | double result = sumall(6.18,1,4,6); 15 | std::cout< 3 | #include 4 | #include 5 | #include //for smart pointers 6 | 7 | 8 | template 9 | class CMatrix{ 10 | public: 11 | int size; 12 | T* data; 13 | CMatrix(){data=nullptr;size=0;}; 14 | ~CMatrix(); 15 | CMatrix(int N); 16 | //copy constructor 17 | CMatrix(const CMatrix& p); 18 | //assignment operator 19 | CMatrix& operator=(const CMatrix& B); 20 | //move constructor 21 | CMatrix ( CMatrix && p ); 22 | //move assignment operator 23 | CMatrix& operator=(CMatrix&& p); 24 | void print_to_file(const std::string& file) const; 25 | void read_from_file(const std::string& file); 26 | CMatrix operator*(const CMatrix& B); 27 | };//CMatrix 28 | 29 | //constructor with a parameter 30 | template 31 | CMatrix::CMatrix(int N){ 32 | size = N; 33 | data=nullptr; 34 | std::cout<<"called constructor with a parameter"<0){ 36 | data = new T[N*N]; 37 | }; 38 | //the next line is totally useless and bad for performance 39 | //but valgrind complains when printing data without it 40 | //it's here just to illustrate that it shows "not real" errors sometimes 41 | // for(int i=0;i 46 | CMatrix::~CMatrix() { 47 | if (data!=nullptr){ 48 | delete[] data; 49 | } 50 | }; 51 | 52 | 53 | //copy constructor 54 | template 55 | CMatrix::CMatrix ( const CMatrix& p ){ 56 | std::cout<<"Copy constructor called."< 70 | void CMatrix::print_to_file(const std::string& file) const { 71 | std::ofstream filevar(file); 72 | if(filevar){ 73 | filevar< 88 | void CMatrix::read_from_file(const std::string& file){ 89 | std::ifstream filevar(file); 90 | if(filevar){ 91 | filevar>>size; 92 | data=new T[size*size]; 93 | for (int i=0;i>data[i*size+j]; 96 | } 97 | } 98 | filevar.close();} 99 | else{ 100 | std::cout<<"couldn't open the file "< 105 | CMatrix CMatrix::operator*(const CMatrix& B){ 106 | if (size != B.size) { 107 | std::cout<<"The two matrices are not of the same size! The result will be nonsense."< C(size); 110 | for (int i=0;i 122 | CMatrix& CMatrix::operator=(const CMatrix& p){ 123 | std::cout<<"Overloaded = operator called"< 148 | CMatrix::CMatrix ( CMatrix && p ) { 149 | std::cout<<"move constructor called"< 163 | CMatrix& CMatrix::operator=(CMatrix&& p){ 164 | std::cout<<"move assignment operator called"< A,B; 182 | A.read_from_file("A.txt"); 183 | B.read_from_file("B.txt"); 184 | auto C=A*B; 185 | C.print_to_file("C.txt"); 186 | //depending on compiler, no copy/assignment has been called so far cause copy elision happened; 187 | //you might see your compiler calling move there as well 188 | C=A;//this should call assignment 189 | C.print_to_file("A_copy.txt"); 190 | CMatrix D(A);//copy constructor 191 | D.print_to_file("A_copy2.txt"); 192 | C=std::move(A);//move assignment 193 | C.print_to_file("A_copy3.txt"); 194 | A.print_to_file("A_test.txt");//has zero there, as we have destroyed A 195 | return 0; 196 | } 197 | -------------------------------------------------------------------------------- /solutions/lecture5/matrix_smart.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include //for smart pointers 5 | 6 | 7 | template 8 | class CMatrix{ 9 | public: 10 | int size; 11 | std::unique_ptr data; 12 | CMatrix()=default;//specifically say we are ok with default-generated constructor 13 | CMatrix(int N); 14 | //copy constructor 15 | CMatrix(const CMatrix& p); 16 | //assignment operator 17 | CMatrix& operator=(const CMatrix& B); 18 | //move constructor 19 | CMatrix ( CMatrix && p ); 20 | //move assignment operator 21 | CMatrix& operator=(CMatrix&& p); 22 | void print_to_file(const std::string& file) const; 23 | void read_from_file(const std::string& file); 24 | CMatrix operator*(const CMatrix& B); 25 | };//CMatrix 26 | 27 | //constructor with a parameter 28 | template 29 | CMatrix::CMatrix(int N){ 30 | size = N; 31 | //requires at least c++14 32 | data = std::make_unique(N*N); 33 | }//constructor 34 | 35 | //copy constructor 36 | template 37 | CMatrix::CMatrix ( const CMatrix& p ){ 38 | std::cout<<"Copy constructor called."<(size*size); 48 | for (int i=0;i 56 | void CMatrix::print_to_file(const std::string& file) const { 57 | std::ofstream filevar(file); 58 | filevar< 70 | void CMatrix::read_from_file(const std::string& file){ 71 | std::ifstream filevar(file); 72 | if(filevar){ 73 | filevar>>size; 74 | data = std::make_unique(size*size); 75 | for (int i=0;i>data[i*size+j]; 78 | } 79 | } 80 | filevar.close();} 81 | else{ 82 | std::cout<<"coudn't open the file "< 87 | CMatrix CMatrix::operator*(const CMatrix& B){ 88 | if (size != B.size) { 89 | std::cout<<"The two matrices are not of the same size! The result will be nonsense."< C(size); 92 | for (int i=0;i 104 | CMatrix& CMatrix::operator=(const CMatrix& p){ 105 | std::cout<<"Overloaded = operator called"<(size*size); 113 | for (int i=0;i 123 | CMatrix::CMatrix ( CMatrix && p ) { 124 | std::cout<<"move constructor called"< 138 | CMatrix& CMatrix::operator=(CMatrix&& p){ 139 | std::cout<<"move assignment operator called"< A,B; 153 | A.read_from_file("A.txt"); 154 | B.read_from_file("B.txt"); 155 | auto C=A*B; 156 | C.print_to_file("C.txt"); 157 | //depending on compiler, no copy/assignment has been called so far cause copy elision happened; 158 | //you might see your compiler calling move there as well 159 | C=A;//this should call assignment 160 | C.print_to_file("A_copy.txt"); 161 | CMatrix D(A);//copy constructor 162 | D.print_to_file("A_copy2.txt"); 163 | C=std::move(A);//move assignment 164 | C.print_to_file("A_copy3.txt"); 165 | A.print_to_file("A_test.txt");//has zero there, as we have destroyed A 166 | return 0; 167 | } 168 | -------------------------------------------------------------------------------- /solutions/lecture6/shapes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | template 6 | struct coords { 7 | T x,y; 8 | void set_coords(const T& x0, const T& y0){ 9 | x=x0;y=y0; 10 | } 11 | void print(){ 12 | std::cout<<"("< 17 | T distance( coords p1, coords p2){ 18 | return sqrt( (p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y) ); 19 | } 20 | 21 | template 22 | class CShape { 23 | public: 24 | virtual T perimeter()=0; 25 | virtual void print_vertices ()=0; 26 | virtual ~CShape(){}; 27 | }; 28 | 29 | template 30 | class CTriangle: public CShape { 31 | public: 32 | coords p1,p2,p3; 33 | CTriangle(const std::vector& myvertices); 34 | T perimeter() override; 35 | void print_vertices() override; 36 | };//CTriangle 37 | 38 | template 39 | CTriangle::CTriangle ( const std::vector& myvertices ) { 40 | if (myvertices.size() == 6) { 41 | p1.set_coords(myvertices[0],myvertices[1]); 42 | p2.set_coords(myvertices[2],myvertices[3]); 43 | p3.set_coords(myvertices[4],myvertices[5]); 44 | } else{ 45 | std::cout << "This is not a triangle! Use polygon instead." << std::endl; exit(1); 46 | } 47 | }//constructor 48 | 49 | 50 | 51 | template 52 | T CTriangle::perimeter(){ 53 | return distance(p1,p2)+distance(p1,p3)+distance(p2,p3); 54 | }; 55 | 56 | template 57 | void CTriangle::print_vertices() { 58 | std::cout << "The vertex coordinates are" << std::endl; 59 | p1.print(); p2.print(); p3.print(); 60 | std::cout << std::endl; 61 | }//print 62 | 63 | 64 | template 65 | class CPolygon: public CShape { 66 | public: 67 | coords* vertices;//they should be given in order 68 | int Nv; 69 | 70 | CPolygon(const std::vector& myvertices); 71 | 72 | T perimeter() override; 73 | 74 | void print_vertices() override{ 75 | std::cout << "The vertex coordinates are" << std::endl; 76 | for (int i=0;i 89 | CPolygon::CPolygon ( const std::vector& myvertices ){ 90 | Nv = myvertices.size()/2; 91 | vertices = new coords[Nv]; 92 | for (int i=0;i 98 | T CPolygon::perimeter(){ 99 | T result = 0; 100 | for (int i=0;i tr({0,0,1,0,1,1}); 109 | CShape * shape1 = &tr; 110 | std::cout << shape1->perimeter() << std::endl; 111 | shape1->print_vertices(); 112 | 113 | CPolygon pol({0,0,1,0,1,1,0,1}); 114 | CShape * shape2 = &pol; 115 | std::cout << shape2->perimeter() << std::endl; 116 | shape2->print_vertices(); 117 | 118 | return 0; 119 | } 120 | --------------------------------------------------------------------------------