6b-TP.ipynb 14 KB
Newer Older
GILLES Sebastien's avatar
GILLES Sebastien committed
1 2 3 4 5 6
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
7
    "# [Getting started in C++](/) - [Object programming](/notebooks/2-ObjectProgramming/0-main.ipynb) - [TP 8](/notebooks/2-ObjectProgramming/6b-TP.ipynb)"
GILLES Sebastien's avatar
GILLES Sebastien committed
8 9 10 11 12 13 14 15 16
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "toc": true
   },
   "source": [
    "<h1>Table of contents<span class=\"tocSkip\"></span></h1>\n",
17
    "<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>"
GILLES Sebastien's avatar
GILLES Sebastien committed
18 19 20 21 22 23
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
24
    "### EXERCICE 21: base class `TestDisplay`\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
25 26 27 28 29
    "\n",
    "Create a base class `TestDisplay` from which both `TestDisplayPowerOfTwoApprox` and `TestDisplaySum` will inherit publicly.\n",
    "\n",
    "This class:\n",
    "\n",
30
    "* Should get a constructor which sets the resolution (known as `maximum_error_index` in the previous exercice).\n",
31
    "* Includes a protected method named `PrintLine()` that will replace the `print_line()` we introduced in previous exercice.\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
32 33 34 35 36 37 38 39
    "\n",
    "The constructors of derived classes will of course have to be modified accordingly: so far we relied on default ones."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
40
    "### EXERCICE 22: inherit from `TestDisplayPowerOfTwoApprox`\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
    "\n",
    "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.\n",
    "\n",
    "To do so, we will create two classes `TestDisplayPowerOfTwoApprox065` and `TestDisplayPowerOfTwoApprox035` that inherits from `TestDisplayPowerOfTwoApprox`.\n",
    "\n",
    "Of course, we still abide by the DRY principle and we want to specialize only the code related to `Do()` method. \n",
    "\n",
    "The `main()` to use:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "int main(int argc, char** argv)\n",
    "{\n",
    "    static_cast<void>(argc); // to silence warning about unused argc - don't bother \n",
    "    static_cast<void>(argv); // to silence warning about unused argv - don't bother      \n",
    "\n",
    "    TestDisplayPowerOfTwoApprox065 test_display_approx065(100);     \n",
    "\n",
    "    for (int Nbits = 2; Nbits <= 8; Nbits += 2)\n",
    "         test_display_approx065.Do(Nbits); \n",
    "\n",
    "    std::cout << std::endl;\n",
    "    \n",
    "    TestDisplayPowerOfTwoApprox035 test_display_approx035(100);     \n",
    "\n",
    "    for (int Nbits = 2; Nbits <= 8; Nbits += 2)\n",
    "         test_display_approx035.Do(Nbits); \n",
    "    \n",
    "    std::cout << std::endl;\n",
    "\n",
76
    "    TestDisplayMultiply test_display_multiply(1000);\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
77 78
    "\n",
    "    for (int Nbits = 1; Nbits <= 8; ++Nbits)\n",
79
    "        test_display_multiply.Do(Nbits);\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
    "\n",
    "    return EXIT_SUCCESS;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "_Expected output:_\n",
    "\n",
    "````\n",
    "[With 2 bits]: 0.65 ~ 0.75  (3 / 2^2)  [error = 15/100]\n",
    "[With 4 bits]: 0.65 ~ 0.625  (10 / 2^4)  [error = 4/100]\n",
    "[With 6 bits]: 0.65 ~ 0.65625  (42 / 2^6)  [error = 1/100]\n",
    "[With 8 bits]: 0.65 ~ 0.648438  (166 / 2^8)  [error = 0/100]\n",
    "\n",
    "[With 2 bits]: 0.35 ~ 0.375  (3 / 2^3)  [error = 7/100]\n",
    "[With 4 bits]: 0.35 ~ 0.34375  (11 / 2^5)  [error = 2/100]\n",
    "[With 6 bits]: 0.35 ~ 0.351562  (45 / 2^7)  [error = 0/100]\n",
    "[With 8 bits]: 0.35 ~ 0.349609  (179 / 2^9)  [error = 0/100]\n",
    "\n",
    "[With 1 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 2965  [error = 254/1000]\n",
    "[With 2 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4448  [error = 119/1000]\n",
    "[With 3 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4008  [error = 8/1000]\n",
    "[With 4 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3857  [error = 30/1000]\n",
    "[With 5 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3967  [error = 2/1000]\n",
    "[With 6 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4004  [error = 7/1000]\n",
    "[With 7 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3977  [error = 0/1000]\n",
    "[With 8 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3968  [error = 2/1000]\n",
    "````"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
117
    "### EXERCICE 23: Toward a `TestDisplayContainer` class\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
118
    "\n",
119
    "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.\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
120
    "\n",
121
    "The declaration of the class should look like:\n"
GILLES Sebastien's avatar
GILLES Sebastien committed
122 123 124 125 126 127 128 129
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
130
    "class TestDisplayContainer\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
131
    "{\n",
132
    "public:\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
133
    "\n",
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    "    //! Add a new test_display_register.\n",
    "    //! At each call, the item to be registered is put at the first available position and internal current_position_\n",
    "    //! is incremented. If the end-user attempts to register more than three items, the error() function is called.\n",
    "    void Register(TestDisplay* test_display);\n",
    "    \n",
    "    //! For each container stored, loop oover all those bits and print the result on screen.\n",
    "    void Do(int initial_Nbit, int final_Nbit, int increment_Nbit) const;\n",
    "    \n",
    "private:\n",
    "    \n",
    "    //! List of all known `TestDisplay` objects.\n",
    "    TestDisplay* list_[3];\n",
    "    \n",
    "    //! Index to place the next register object. If '3', no more object may be registered.\n",
    "    int current_position_ {};\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
149
    "\n",
150
    "};"
GILLES Sebastien's avatar
GILLES Sebastien committed
151 152 153 154 155 156
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
157
    "You will need to add a sanity check in constructor; in case of failure use at the moment the following function:"
GILLES Sebastien's avatar
GILLES Sebastien committed
158 159 160 161 162 163 164 165
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
166
    "//! Function for error handling. We will see later how to fulfill the same functionality more properly.\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
167 168 169 170 171 172 173 174 175 176 177
    "[[noreturn]] void error(std::string explanation)\n",
    "{\n",
    "    std::cout << \"ERROR: \" << explanation << std::endl;\n",
    "    exit(EXIT_FAILURE);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
178
    "The `main()` to use is:"
GILLES Sebastien's avatar
GILLES Sebastien committed
179 180 181 182 183 184 185 186 187 188 189
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "int main(int argc, char** argv)\n",
    "{\n",
    "    static_cast<void>(argc); // to silence warning about unused argc - don't bother \n",
190 191 192
    "    static_cast<void>(argv); // to silence warning about unused argv - don't bother      \n",
    "\n",
    "    TestDisplayContainer container;\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
193
    "    \n",
194 195 196 197 198
    "    container.Register(new TestDisplayPowerOfTwoApprox065(1000000));\n",
    "    container.Register(new TestDisplayPowerOfTwoApprox035(1000000));\n",
    "    container.Register(new TestDisplayMultiply(10000));\n",
    "    \n",
    "    container.Do(4, 16, 4);\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
199 200 201 202 203 204 205 206 207
    "    \n",
    "    return EXIT_SUCCESS;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
    "_Expected result:_\n",
    "\n",
    "    [With 4 bits]: 0.65 ~ 0.625  (10/2^4)  [error = 38462/1000000]\n",
    "    [With 8 bits]: 0.65 ~ 0.648438  (166/2^8)  [error = 2404/1000000]\n",
    "    [With 12 bits]: 0.65 ~ 0.649902  (2662/2^12)  [error = 150/1000000]\n",
    "    [With 16 bits]: 0.65 ~ 0.649994  (42598/2^16)  [error = 9/1000000]\n",
    "\n",
    "    [With 4 bits]: 0.35 ~ 0.34375  (11/2^5)  [error = 17857/1000000]\n",
    "    [With 8 bits]: 0.35 ~ 0.349609  (179/2^9)  [error = 1116/1000000]\n",
    "    [With 12 bits]: 0.35 ~ 0.349976  (2867/2^13)  [error = 70/1000000]\n",
    "    [With 16 bits]: 0.35 ~ 0.349998  (45875/2^17)  [error = 4/1000000]\n",
    "\n",
    "    [With 4 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3857  [error = 299/10000]\n",
    "    [With 8 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3968  [error = 20/10000]\n",
    "    [With 12 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3975  [error = 2/10000]\n",
    "    [With 16 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3975  [error = 2/10000]"
GILLES Sebastien's avatar
GILLES Sebastien committed
224 225 226 227 228 229
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
230
    "### EXERCICE 24: dynamic allocation of array\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
231
    "\n",
232
    "Instead of setting an arbitrary size of 3, we will now add a size dynamically in `TestDisplayContainer` constructor; the internal storage will now be:\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
233 234 235 236 237 238 239 240 241
    "\n",
    "````\n",
    "TestDisplay** test_display_list_;\n",
    "````\n",
    "\n",
    "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).\n",
    "\n",
    "Constructor must now:\n",
    "\n",
242 243
    "* 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).\n",
    "* 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).\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
244 245 246 247
    "* Set each element to `nullptr`.\n",
    "\n",
    "Destructor must of course take care of deallocating properly the memory.\n",
    "\n",
248
    "**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`)."
GILLES Sebastien's avatar
GILLES Sebastien committed
249 250 251 252 253 254
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
255
    "### EXERCICE 25: transform `TestDisplayContainer::Do()` into a free function\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
256
    "\n",
257
    "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).\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
258
    "\n",
259 260 261 262
    "Replace the `Do()` method by a free function with signature:\n",
    "````\n",
    "void loop(int initial_Nbit, int final_Nbit, int increment_Nbit, const TestDisplayContainer& container)\n",
    "````\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
263
    "\n",
264
    "To do so, you will need to add several methods to `TestDisplayContainer`:\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
265
    "\n",
266 267 268 269 270 271
    "- 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.\n",
    "- A method to access the `i`-th element stored in the table. Signature might be:\n",
    "````\n",
    "const TestDisplay& GetElement(std::size_t i) const\n",
    "````\n",
    "(but others are also possible - you may prefer to return a pointer rather than a reference).\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
272
    "\n",
273
    "New `main()` is:"
GILLES Sebastien's avatar
GILLES Sebastien committed
274 275 276 277 278 279 280 281 282 283 284
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "int main(int argc, char** argv)\n",
    "{\n",
    "    static_cast<void>(argc); // to silence warning about unused argc - don't bother \n",
285 286
    "    static_cast<void>(argv); // to silence warning about unused argv - don't bother      \n",
    "\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
287
    "    TestDisplayContainer container(3);\n",
288
    "    \n",
GILLES Sebastien's avatar
GILLES Sebastien committed
289 290
    "    container.Register(new TestDisplayPowerOfTwoApprox065(1000000));\n",
    "    container.Register(new TestDisplayPowerOfTwoApprox035(1000000));\n",
291
    "    container.Register(new TestDisplayMultiply(10000));\n",
GILLES Sebastien's avatar
GILLES Sebastien committed
292 293
    "    \n",
    "    loop(4, 16, 4, container);\n",
294
    "    \n",
GILLES Sebastien's avatar
GILLES Sebastien committed
295 296 297 298 299 300 301 302 303
    "    return EXIT_SUCCESS;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
304
    "© _CNRS 2016_ - _Inria 2018-2019_   \n",
305 306
    "_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/)_  \n",
    "_The present version has been written by Sébastien Gilles and Vincent Rouvreau (Inria)_"
GILLES Sebastien's avatar
GILLES Sebastien committed
307 308 309 310 311 312 313
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
314
   "name": "xcpp17"
GILLES Sebastien's avatar
GILLES Sebastien committed
315 316 317 318 319 320
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "c++",
321
   "version": "17"
GILLES Sebastien's avatar
GILLES Sebastien committed
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": true,
   "title_cell": "Table of contents",
   "title_sidebar": "Contents",
   "toc_cell": true,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}