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:
# [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:
<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>
%% Cell type:markdown id: tags:
### EXERCICE 21: base class `TestDisplay`
Create a base class `TestDisplay` from which both `TestDisplayPowerOfTwoApprox` and `TestDisplaySum` will inherit publicly.
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.
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:
### 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.
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.
The `main()` to use:
%% Cell type:code id: tags:
``` C++17
int main(int argc, char** argv)
{
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
TestDisplayPowerOfTwoApprox065 test_display_approx065(100);
for (int Nbits = 2; Nbits <= 8; Nbits += 2)
test_display_approx065.Do(Nbits);
std::cout << std::endl;
TestDisplayPowerOfTwoApprox035 test_display_approx035(100);
for (int Nbits = 2; Nbits <= 8; Nbits += 2)
test_display_approx035.Do(Nbits);
std::cout << std::endl;
TestDisplayMultiply test_display_multiply(1000);
for (int Nbits = 1; Nbits <= 8; ++Nbits)
test_display_multiply.Do(Nbits);
return EXIT_SUCCESS;
}
```
%% Cell type:markdown id: tags:
_Expected output:_
````
[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 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 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 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 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 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 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 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]
````
%% Cell type:markdown id: tags:
### 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.
The declaration of the class should look like:
%% Cell type:code id: tags:
``` C++17
class TestDisplayContainer
{
public:
//! 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_
//! is incremented. If the end-user attempts to register more than three items, the error() function is called.
void Register(TestDisplay* test_display);
//! 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;
private:
//! List of all known `TestDisplay` objects.
TestDisplay* list_[3];
//! Index to place the next register object. If '3', no more object may be registered.
int current_position_ {};
};
```
%% 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:
%% Cell type:code id: tags:
``` C++17
//! Function for error handling. We will see later how to fulfill the same functionality more properly.
[[noreturn]] void error(std::string explanation)
{
std::cout << "ERROR: " << explanation << std::endl;
exit(EXIT_FAILURE);
}
```
%% Cell type:markdown id: tags:
The `main()` to use is:
%% Cell type:code id: tags:
``` C++17
int main(int argc, char** argv)
{
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
TestDisplayContainer container;
container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
container.Register(new TestDisplayMultiply(10000));
container.Do(4, 16, 4);
return EXIT_SUCCESS;
}
```
%% Cell type:markdown id: tags:
_Expected result:_
[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 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 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 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 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 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]
%% Cell type:markdown id: tags:
### 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:
````
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).
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).
* 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`.
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`).
%% Cell type:markdown id: tags:
### 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).
Replace the `Do()` method by a free function with signature:
````
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`:
- 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:
````
const TestDisplay& GetElement(std::size_t i) const
````
(but others are also possible - you may prefer to return a pointer rather than a reference).
New `main()` is:
%% Cell type:code id: tags:
``` C++17
int main(int argc, char** argv)
{
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
TestDisplayContainer container(3);
container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
container.Register(new TestDisplayMultiply(10000));
loop(4, 16, 4, container);
return EXIT_SUCCESS;
}
```
%% Cell type:markdown id: tags:
© _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/)_
_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