Mentions légales du service

Skip to content
Snippets Groups Projects
Commit 653a3b11 authored by ROUVREAU Vincent's avatar ROUVREAU Vincent
Browse files

Explain where resolution comes from

parent 401dc4cf
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# [Getting started in C++](/) - [Object programming](/notebooks/2-ObjectProgramming/0-main.ipynb) - [TP 8](/notebooks/2-ObjectProgramming/6b-TP.ipynb) # [Getting started in C++](/) - [Object programming](/notebooks/2-ObjectProgramming/0-main.ipynb) - [TP 8](/notebooks/2-ObjectProgramming/6b-TP.ipynb)
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<h1>Table of contents<span class="tocSkip"></span></h1> <h1>Table of contents<span class="tocSkip"></span></h1>
<div class="toc"><ul class="toc-item"><li><span><a href="#EXERCICE-21:-base-class-TestDisplay" data-toc-modified-id="EXERCICE-21:-base-class-TestDisplay-1">EXERCICE 21: base class <code>TestDisplay</code></a></span></li><li><span><a href="#EXERCICE-22:-inherit-from-TestDisplayPowerOfTwoApprox" data-toc-modified-id="EXERCICE-22:-inherit-from-TestDisplayPowerOfTwoApprox-2">EXERCICE 22: inherit from <code>TestDisplayPowerOfTwoApprox</code></a></span></li><li><span><a href="#EXERCICE-23:-Toward-a-TestDisplayContainer-class" data-toc-modified-id="EXERCICE-23:-Toward-a-TestDisplayContainer-class-3">EXERCICE 23: Toward a <code>TestDisplayContainer</code> class</a></span></li><li><span><a href="#EXERCICE-24:-dynamic-allocation-of-array" data-toc-modified-id="EXERCICE-24:-dynamic-allocation-of-array-4">EXERCICE 24: dynamic allocation of array</a></span></li><li><span><a href="#EXERCICE-25:-transform-TestDisplayContainer::Do()-into-a-free-function" data-toc-modified-id="EXERCICE-25:-transform-TestDisplayContainer::Do()-into-a-free-function-5">EXERCICE 25: transform <code>TestDisplayContainer::Do()</code> into a free function</a></span></li></ul></div> <div class="toc"><ul class="toc-item"><li><span><a href="#EXERCICE-21:-base-class-TestDisplay" data-toc-modified-id="EXERCICE-21:-base-class-TestDisplay-1">EXERCICE 21: base class <code>TestDisplay</code></a></span></li><li><span><a href="#EXERCICE-22:-inherit-from-TestDisplayPowerOfTwoApprox" data-toc-modified-id="EXERCICE-22:-inherit-from-TestDisplayPowerOfTwoApprox-2">EXERCICE 22: inherit from <code>TestDisplayPowerOfTwoApprox</code></a></span></li><li><span><a href="#EXERCICE-23:-Toward-a-TestDisplayContainer-class" data-toc-modified-id="EXERCICE-23:-Toward-a-TestDisplayContainer-class-3">EXERCICE 23: Toward a <code>TestDisplayContainer</code> class</a></span></li><li><span><a href="#EXERCICE-24:-dynamic-allocation-of-array" data-toc-modified-id="EXERCICE-24:-dynamic-allocation-of-array-4">EXERCICE 24: dynamic allocation of array</a></span></li><li><span><a href="#EXERCICE-25:-transform-TestDisplayContainer::Do()-into-a-free-function" data-toc-modified-id="EXERCICE-25:-transform-TestDisplayContainer::Do()-into-a-free-function-5">EXERCICE 25: transform <code>TestDisplayContainer::Do()</code> into a free function</a></span></li></ul></div>
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### EXERCICE 21: base class `TestDisplay` ### EXERCICE 21: base class `TestDisplay`
Create a base class `TestDisplay` from which both `TestDisplayPowerOfTwoApprox` and `TestDisplaySum` will inherit publicly. Create a base class `TestDisplay` from which both `TestDisplayPowerOfTwoApprox` and `TestDisplaySum` will inherit publicly.
This class: This class:
* Should get a constructor which sets the resolution. * Should get a constructor which sets the resolution (known as `maximum_error_index` in the previous exercice).
* Includes a protected method named `PrintLine()` that will replace the `print_line()` we introduced in previous exercice. * Includes a protected method named `PrintLine()` that will replace the `print_line()` we introduced in previous exercice.
The constructors of derived classes will of course have to be modified accordingly: so far we relied on default ones. The constructors of derived classes will of course have to be modified accordingly: so far we relied on default ones.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### EXERCICE 22: inherit from `TestDisplayPowerOfTwoApprox` ### EXERCICE 22: inherit from `TestDisplayPowerOfTwoApprox`
We would like to get back former output in which we got first all outputs for 0.65, then all the ones for 0.35. We would like to get back former output in which we got first all outputs for 0.65, then all the ones for 0.35.
To do so, we will create two classes `TestDisplayPowerOfTwoApprox065` and `TestDisplayPowerOfTwoApprox035` that inherits from `TestDisplayPowerOfTwoApprox`. To do so, we will create two classes `TestDisplayPowerOfTwoApprox065` and `TestDisplayPowerOfTwoApprox035` that inherits from `TestDisplayPowerOfTwoApprox`.
Of course, we still abide by the DRY principle and we want to specialize only the code related to `Do()` method. Of course, we still abide by the DRY principle and we want to specialize only the code related to `Do()` method.
The `main()` to use: The `main()` to use:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` C++17 ``` C++17
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
static_cast<void>(argc); // to silence warning about unused argc - don't bother static_cast<void>(argc); // to silence warning about unused argc - don't bother
static_cast<void>(argv); // to silence warning about unused argv - don't bother static_cast<void>(argv); // to silence warning about unused argv - don't bother
TestDisplayPowerOfTwoApprox065 test_display_approx065(100); TestDisplayPowerOfTwoApprox065 test_display_approx065(100);
for (int Nbits = 2; Nbits <= 8; Nbits += 2) for (int Nbits = 2; Nbits <= 8; Nbits += 2)
test_display_approx065.Do(Nbits); test_display_approx065.Do(Nbits);
std::cout << std::endl; std::cout << std::endl;
TestDisplayPowerOfTwoApprox035 test_display_approx035(100); TestDisplayPowerOfTwoApprox035 test_display_approx035(100);
for (int Nbits = 2; Nbits <= 8; Nbits += 2) for (int Nbits = 2; Nbits <= 8; Nbits += 2)
test_display_approx035.Do(Nbits); test_display_approx035.Do(Nbits);
std::cout << std::endl; std::cout << std::endl;
TestDisplayMultiply test_display_multiply(1000); TestDisplayMultiply test_display_multiply(1000);
for (int Nbits = 1; Nbits <= 8; ++Nbits) for (int Nbits = 1; Nbits <= 8; ++Nbits)
test_display_multiply.Do(Nbits); test_display_multiply.Do(Nbits);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
_Expected output:_ _Expected output:_
```` ````
[With 2 bits]: 0.65 ~ 0.75 (3 / 2^2) [error = 15/100] [With 2 bits]: 0.65 ~ 0.75 (3 / 2^2) [error = 15/100]
[With 4 bits]: 0.65 ~ 0.625 (10 / 2^4) [error = 4/100] [With 4 bits]: 0.65 ~ 0.625 (10 / 2^4) [error = 4/100]
[With 6 bits]: 0.65 ~ 0.65625 (42 / 2^6) [error = 1/100] [With 6 bits]: 0.65 ~ 0.65625 (42 / 2^6) [error = 1/100]
[With 8 bits]: 0.65 ~ 0.648438 (166 / 2^8) [error = 0/100] [With 8 bits]: 0.65 ~ 0.648438 (166 / 2^8) [error = 0/100]
[With 2 bits]: 0.35 ~ 0.375 (3 / 2^3) [error = 7/100] [With 2 bits]: 0.35 ~ 0.375 (3 / 2^3) [error = 7/100]
[With 4 bits]: 0.35 ~ 0.34375 (11 / 2^5) [error = 2/100] [With 4 bits]: 0.35 ~ 0.34375 (11 / 2^5) [error = 2/100]
[With 6 bits]: 0.35 ~ 0.351562 (45 / 2^7) [error = 0/100] [With 6 bits]: 0.35 ~ 0.351562 (45 / 2^7) [error = 0/100]
[With 8 bits]: 0.35 ~ 0.349609 (179 / 2^9) [error = 0/100] [With 8 bits]: 0.35 ~ 0.349609 (179 / 2^9) [error = 0/100]
[With 1 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 2965 [error = 254/1000] [With 1 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 2965 [error = 254/1000]
[With 2 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4448 [error = 119/1000] [With 2 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4448 [error = 119/1000]
[With 3 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4008 [error = 8/1000] [With 3 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4008 [error = 8/1000]
[With 4 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3857 [error = 30/1000] [With 4 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3857 [error = 30/1000]
[With 5 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3967 [error = 2/1000] [With 5 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3967 [error = 2/1000]
[With 6 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4004 [error = 7/1000] [With 6 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4004 [error = 7/1000]
[With 7 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3977 [error = 0/1000] [With 7 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3977 [error = 0/1000]
[With 8 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3968 [error = 2/1000] [With 8 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3968 [error = 2/1000]
```` ````
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### EXERCICE 23: Toward a `TestDisplayContainer` class ### EXERCICE 23: Toward a `TestDisplayContainer` class
We would like to introduce an object which purpose is to store the various `TestDisplay` class and call for each of them the `Do` method. We would like to introduce an object which purpose is to store the various `TestDisplay` class and call for each of them the `Do` method.
The declaration of the class should look like: The declaration of the class should look like:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` C++17 ``` C++17
class TestDisplayContainer class TestDisplayContainer
{ {
public: public:
//! Add a new test_display_register. //! Add a new test_display_register.
//! At each call, the item to be registered is put at the first available position and internal current_position_ //! At each call, the item to be registered is put at the first available position and internal current_position_
//! is incremented. If the end-user attempts to register more than three items, the error() function is called. //! is incremented. If the end-user attempts to register more than three items, the error() function is called.
void Register(TestDisplay* test_display); void Register(TestDisplay* test_display);
//! For each container stored, loop oover all those bits and print the result on screen. //! For each container stored, loop oover all those bits and print the result on screen.
void Do(int initial_Nbit, int final_Nbit, int increment_Nbit) const; void Do(int initial_Nbit, int final_Nbit, int increment_Nbit) const;
private: private:
//! List of all known `TestDisplay` objects. //! List of all known `TestDisplay` objects.
TestDisplay* list_[3]; TestDisplay* list_[3];
//! Index to place the next register object. If '3', no more object may be registered. //! Index to place the next register object. If '3', no more object may be registered.
int current_position_ {}; int current_position_ {};
}; };
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
You will need to add a sanity check in constructor; in case of failure use at the moment the following function: You will need to add a sanity check in constructor; in case of failure use at the moment the following function:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` C++17 ``` C++17
//! Function for error handling. We will see later how to fulfill the same functionality more properly. //! Function for error handling. We will see later how to fulfill the same functionality more properly.
[[noreturn]] void error(std::string explanation) [[noreturn]] void error(std::string explanation)
{ {
std::cout << "ERROR: " << explanation << std::endl; std::cout << "ERROR: " << explanation << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
The `main()` to use is: The `main()` to use is:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` C++17 ``` C++17
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
static_cast<void>(argc); // to silence warning about unused argc - don't bother static_cast<void>(argc); // to silence warning about unused argc - don't bother
static_cast<void>(argv); // to silence warning about unused argv - don't bother static_cast<void>(argv); // to silence warning about unused argv - don't bother
TestDisplayContainer container; TestDisplayContainer container;
container.Register(new TestDisplayPowerOfTwoApprox065(1000000)); container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
container.Register(new TestDisplayPowerOfTwoApprox035(1000000)); container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
container.Register(new TestDisplayMultiply(10000)); container.Register(new TestDisplayMultiply(10000));
container.Do(4, 16, 4); container.Do(4, 16, 4);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
_Expected result:_ _Expected result:_
[With 4 bits]: 0.65 ~ 0.625 (10/2^4) [error = 38462/1000000] [With 4 bits]: 0.65 ~ 0.625 (10/2^4) [error = 38462/1000000]
[With 8 bits]: 0.65 ~ 0.648438 (166/2^8) [error = 2404/1000000] [With 8 bits]: 0.65 ~ 0.648438 (166/2^8) [error = 2404/1000000]
[With 12 bits]: 0.65 ~ 0.649902 (2662/2^12) [error = 150/1000000] [With 12 bits]: 0.65 ~ 0.649902 (2662/2^12) [error = 150/1000000]
[With 16 bits]: 0.65 ~ 0.649994 (42598/2^16) [error = 9/1000000] [With 16 bits]: 0.65 ~ 0.649994 (42598/2^16) [error = 9/1000000]
[With 4 bits]: 0.35 ~ 0.34375 (11/2^5) [error = 17857/1000000] [With 4 bits]: 0.35 ~ 0.34375 (11/2^5) [error = 17857/1000000]
[With 8 bits]: 0.35 ~ 0.349609 (179/2^9) [error = 1116/1000000] [With 8 bits]: 0.35 ~ 0.349609 (179/2^9) [error = 1116/1000000]
[With 12 bits]: 0.35 ~ 0.349976 (2867/2^13) [error = 70/1000000] [With 12 bits]: 0.35 ~ 0.349976 (2867/2^13) [error = 70/1000000]
[With 16 bits]: 0.35 ~ 0.349998 (45875/2^17) [error = 4/1000000] [With 16 bits]: 0.35 ~ 0.349998 (45875/2^17) [error = 4/1000000]
[With 4 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3857 [error = 299/10000] [With 4 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3857 [error = 299/10000]
[With 8 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3968 [error = 20/10000] [With 8 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3968 [error = 20/10000]
[With 12 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3975 [error = 2/10000] [With 12 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3975 [error = 2/10000]
[With 16 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3975 [error = 2/10000] [With 16 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3975 [error = 2/10000]
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### EXERCICE 24: dynamic allocation of array ### EXERCICE 24: dynamic allocation of array
Instead of setting an arbitrary size of 3, we will now add a size dynamically in `TestDisplayContainer` constructor; the internal storage will now be: Instead of setting an arbitrary size of 3, we will now add a size dynamically in `TestDisplayContainer` constructor; the internal storage will now be:
```` ````
TestDisplay** test_display_list_; TestDisplay** test_display_list_;
```` ````
meaning we will store an array of pointers (don't worry, we will see later how to avoid such monstruosities... but it is useful nonetheless to try them a bit). meaning we will store an array of pointers (don't worry, we will see later how to avoid such monstruosities... but it is useful nonetheless to try them a bit).
Constructor must now: Constructor must now:
* Allocate the array of `TestDisplay*` with a **capacity** given as its argument (the capacity being the number of elements that *might* be stored inside - we'll see the chosen name is not a whim). * Allocate the array of `TestDisplay*` with a **capacity** given as its argument (the capacity being the number of elements that *might* be stored inside - we'll see the chosen name is not a whim).
* Keep track of the capacity (the related data attribute should be constant: we don't intend to modify the capacity of the array after construction). * Keep track of the capacity (the related data attribute should be constant: we don't intend to modify the capacity of the array after construction).
* Set each element to `nullptr`. * Set each element to `nullptr`.
Destructor must of course take care of deallocating properly the memory. Destructor must of course take care of deallocating properly the memory.
**NOTE:** To avoid a warning you should use `std::size_t` when allocating the array: this is the type used for array (which is in all compilers I've used an alias to `unsigned long` but standard dictates you should use `std::size_t`). **NOTE:** To avoid a warning you should use `std::size_t` when allocating the array: this is the type used for array (which is in all compilers I've used an alias to `unsigned long` but standard dictates you should use `std::size_t`).
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### EXERCICE 25: transform `TestDisplayContainer::Do()` into a free function ### EXERCICE 25: transform `TestDisplayContainer::Do()` into a free function
We probably went a bridge too far: it is useful to provide an object which contains several `TestDisplay` together, but making it take in charge the loop might not be that good an idea (in a real program you might for instance interact with this container by another mean than the pre-defined loop). We probably went a bridge too far: it is useful to provide an object which contains several `TestDisplay` together, but making it take in charge the loop might not be that good an idea (in a real program you might for instance interact with this container by another mean than the pre-defined loop).
Replace the `Do()` method by a free function with signature: Replace the `Do()` method by a free function with signature:
```` ````
void loop(int initial_Nbit, int final_Nbit, int increment_Nbit, const TestDisplayContainer& container) void loop(int initial_Nbit, int final_Nbit, int increment_Nbit, const TestDisplayContainer& container)
```` ````
To do so, you will need to add several methods to `TestDisplayContainer`: To do so, you will need to add several methods to `TestDisplayContainer`:
- A method that returns the **size** (i.e. the number of non nullptr `TestDisplay*` stored), which will be required to loop over the relevant elements. - A method that returns the **size** (i.e. the number of non nullptr `TestDisplay*` stored), which will be required to loop over the relevant elements.
- A method to access the `i`-th element stored in the table. Signature might be: - A method to access the `i`-th element stored in the table. Signature might be:
```` ````
const TestDisplay& GetElement(std::size_t i) const const TestDisplay& GetElement(std::size_t i) const
```` ````
(but others are also possible - you may prefer to return a pointer rather than a reference). (but others are also possible - you may prefer to return a pointer rather than a reference).
New `main()` is: New `main()` is:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` C++17 ``` C++17
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
static_cast<void>(argc); // to silence warning about unused argc - don't bother static_cast<void>(argc); // to silence warning about unused argc - don't bother
static_cast<void>(argv); // to silence warning about unused argv - don't bother static_cast<void>(argv); // to silence warning about unused argv - don't bother
TestDisplayContainer container(3); TestDisplayContainer container(3);
container.Register(new TestDisplayPowerOfTwoApprox065(1000000)); container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
container.Register(new TestDisplayPowerOfTwoApprox035(1000000)); container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
container.Register(new TestDisplayMultiply(10000)); container.Register(new TestDisplayMultiply(10000));
loop(4, 16, 4, container); loop(4, 16, 4, container);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
© _CNRS 2016_ - _Inria 2018-2019_ © _CNRS 2016_ - _Inria 2018-2019_
_This notebook is an adaptation of a lecture prepared by David Chamont (CNRS) under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_ _This notebook is an adaptation of a lecture prepared by David Chamont (CNRS) under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_
_The present version has been written by Sébastien Gilles and Vincent Rouvreau (Inria)_ _The present version has been written by Sébastien Gilles and Vincent Rouvreau (Inria)_
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment