int main()
{
arma::mat A = {{1, 2}, {3, 4}}; // C++11
arma::mat B = {{5, 6}, {7, 8}}; // C++11
( A * B.t() ).print("result");
return 0;
}
```
]]
.row[
.column.w45.middle[
Result:
]
.column.w50.middle[
```shell
$ g++ -std=c++11 arma_test.cpp -o arma_test -larmadillo
$ ./arma_test
result
17.0000 23.0000
39.0000 53.0000
```
]
]
---
# Manipulate rows/columns
.row[
.column.w50[
.row[
`$$A\equiv\left[\begin{array}{ccc}a_{00}&a_{01}&a_{02}\\a_{10}&a_{11}&a_{12}\\a_{20}&a_{21}&a_{22}\end{array}\right]
=\left[\begin{array}{ccc}1&2&3\\4&5&6\\7&8&9\end{array}\right]$$`
]]
.column.w45.middle[
```C++
arma::mat A = { {1, 2, 3},
{4, 5, 6},
{7, 8, 9} }; // C++11
```
]]
----
.row[
.column.w50[
.row[
`$$
B=\left[\begin{array}{ccc}a_{02}&a_{01}&a_{00}\\a_{12}&a_{11}&a_{10}\\a_{22}&a_{21}&a_{20}\end{array}\right]
$$`
]]
.column.w45.middle[
```C++
arma::mat B = A;
B.col(0) = A.col(2);
B.col(1) = A.col(1);
B.col(2) = A.col(0);
```
]]
----
.row[
.column.w50[
.row[
`$$
C=\left[\begin{array}{cccc}a_{00}&a_{01}&a_{02}&10\\a_{10}&a_{11}&a_{12}&11\\a_{20}&a_{21}&a_{22}&12\end{array}\right]
$$`
]]
.column.w45.middle[
```C++
arma::mat C = A;
C.insert_cols(3, arma::colvec({10, 11, 12}));
```
]]
----
.row[
.column.w50[
.row[
`$$
D=\left[\begin{array}{ccc}a_{10}&a_{11}&a_{12}\end{array}\right]
$$`
]]
.column.w45.middle[
```C++
arma::row D = A.row(1);
```
]]
----
.row[
.column.w50[
.row[
`$$
E=\left[\begin{array}{c}a_{20}\\a_{21}\\a_{22}\end{array}\right]
$$`
]
]
.column.w45.middle[
```C++
arma::colvec E = A.col(2);
```
]]
---
# Element-wise functions
.row[
.column.w50[
.row[
`$$A\equiv\left[\begin{array}{ccc}a_{00}&a_{01}&a_{02}\\a_{10}&a_{11}&a_{12}\\a_{20}&a_{21}&a_{22}\end{array}\right]
=\left[\begin{array}{ccc}1&2&3\\4&5&6\\7&8&9\end{array}\right]$$`
]]
.column.w45.middle[
```C++
arma::mat A = { {1, 2, 3},
{4, 5, 6},
{7, 8, 9} }; // C++11
```
]]
----
.row[
.column.w50[
.row[
`$$
B=\left[\begin{array}{ccc}e^{a_{00}}&e^{a_{01}}&e^{a_{02}}\\e^{a_{10}}&e^{a_{11}}&e^{a_{12}}\\e^{a_{20}}&e^{a_{21}}&e^{a_{22}}\end{array}\right]
$$`
]
]
.column.w45.middle[
```C++
arma::mat B = arma::exp(A);
```
]]
----
.row[
.column.w50[
.row[
`$$
C=\left[\begin{array}{ccc}a_{00}^3&a_{01}^3&a_{02}^3\\a_{10}^3&a_{11}^3&a_{12}^3\\a_{20}^3&a_{21}^3&a_{22}^3\end{array}\right]
$$`
]
]
.column.w45.middle[
```C++
arma::mat C = arma::pow(A, 3);
```
]]
----
.row[
.column.w50[
.row[
`$$
D=\left[\begin{array}{ccc}a_{00}b_{00}&a_{01}b_{01}&a_{02}b_{02}\\a_{10}b_{10}&a_{11}b_{11}&a_{12}b_{12}\\a_{20}b_{20}&a_{21}b_{21}&a_{22}b_{22}\end{array}\right]
$$`
]
]
.column.w45.middle[
```C++
arma::mat D = A % B;
```
]]
---
# Standard linear algebra operations
.row[
.column.w50[
.row[
`$$A\equiv\left[\begin{array}{ccc}a_{00}&a_{01}&a_{02}\\a_{10}&a_{11}&a_{12}\\a_{20}&a_{21}&a_{22}\end{array}\right]
=\left[\begin{array}{ccc}1&2&3\\4&5&6\\7&8&9\end{array}\right]$$`
]]
.column.w45.middle[
```C++
arma::mat A = { {1, 2, 3},
{4, 5, 6},
{7, 8, 9} }; // C++11
```
]]
----
.row[
.column.w50[
.row[
`$$
B=A^{-1}
$$`
]
]
.column.w45.middle[
```C++
arma::mat B = A.i();
```
]]
----
.row[
.column.w50.middle[
.row[
`$$C = B^t$$`
]]
.column.w45.middle[
```C++
arma::mat C = B.t();
```
]]
----
.row[
.column.w50.middle[
.row[
`$$D = \left(B C^t\right)^{-1}$$`
]]
.column.w45.middle[
```C++
arma::mat D = (B * C.t()).i();
```
]]
----
.row[
.column.w50.middle[
.row[
`$$d_A = \textrm{det}(A)$$`
]]
.column.w45.middle[
```C++
double d_A = arma::det(A);
```
]]
----
.row[
.column.w50.middle[
.row[
Solve `$$AX= EX$$`
]]
.column.w45.middle[
```C++
arma::cx_vec E;
arma::cx_mat X;
arma::eig_gen(E, X, A);
```
]]
----
.row[
.column.w50.middle[
.row[
`$$s = \sum_{ij} a_{ij}$$`
]]
.column.w45.middle[
```C++
double s = arma::accu(A);
```
]]
---
# Object initialisation
.row[
.column.w50.middle[
.row[
`$$A \equiv \left[\begin{array}{ccc}a_0&a_1&a_2\end{array}\right]
= \left[\begin{array}{cccc}1&2&3\end{array}\right]$$`
]]
.column.w45.middle[
```C++
arma::rowvec A = {1, 2, 3}; // C++11
```
]]
----
.row[
.column.w50.middle[
.row[
`$$B \equiv \left[\begin{array}{c}b_0\\b_1\\b_2\end{array}\right]
= \left[\begin{array}{c}1\\2\\3\end{array}\right]$$`
]]
.column.w45.middle[
```C++
arma::colvec B = {1, 2, 3, 4}; // C++11
```
]]
----
.row[
.column.w50.middle[
.row[
`$$C = \left[\begin{array}{cc}1&2\\3&4\end{array}\right]$$`
]]
.column.w45.middle[
```C++
arma::mat C = { {1, 2}, {3, 4} }; // C++11
```
]]
----
.row[
.column.w50.middle[
.row[
`$$D = \left[\begin{array}{ccc}a_0&0&0\\0&a_1&0\\0&0&a_2\end{array}\right]$$`
]]
.column.w45.middle[
```C++
arma::mat D = arma::diagmat(A);
```
]]
----
.row[
.column.w50.middle[
.row[
`$$E = \left[\begin{array}{ccc}b_{0}&0&0\\0&b_{1}&0\\0&0&b_{2}\end{array}\right]$$`
]]
.column.w45.middle[
```C++
arma::mat E = arma::diagmat(B);
```
]]
---
# `Armadillo` documentation
:arrow_right: We have only scratched the surface of what `Armadillo` can do.
Mandatory bookmark in your browser:
[http://arma.sourceforge.net/docs.html](http://arma.sourceforge.net/docs.html)
---
# Scientific programming
## Scientific tools presented in this course
* linear algebra libraries (usable from `C++`)
* `Boost`, `LAPACK`, `BLAS`, `MKL`, `GSL`, `Eigen`, **`Armadillo`** :+:
* scientific programming with Python
* **introduction to Python**
* **`Numpy`**
* presenting results
* write beautiful math: ** .latex[LaTeX] **
* structure your documentation: **Markdown**
* write some slides: **remark.js**
## Scientific techniques presented in this course
* numerical integration
* **Gaussian quadrature**
---
class: top
# Development tools
## Tools presented in this course
* version control system
* `subversion`, `mercurial`, `CVS`, `SVN`, `Bazaar`, **`git`** :+:
* build system
* `Distutils`, `CMake`, `Autotools`, `qmake`, **`GNU Make`** :+:
* documentation generator
* `Sphinx`, `Docutils`, **`Doxygen`** :+:
* unit testing framework
* `*test*`, **`CxxTest`** :+:
* code formatting tool
* **`astyle`** .animated.infinite.flash[:arrow_left:]
* commenting conventions
* various guidelines
* performance analysis tools
* will be presented in PSA (S4)
* binding generator
* will be presented in PSA (S4)
---
# Artistic Style (`astyle`)
## Key points
* source code indenter, formatter, and beautifier
* works with `C`, `C++`, `Objective-C`, `C#`, and `Java` source files
* cross-platform
.row[
.column.w47.middle[
```C++
#include "stdio.h"
#define PREDEFINED_VALUE 3;
int global_var = PREDEFINED_VALUE;
int main(int argc,char ** argv) {
printf("Hello, v = %d\n",global_var); return 0; }
```
]
.column.w5.middle[
:arrow_right:
]
.column.w47.middle[
```C++
#include "stdio.h"
#define PREDEFINED_VALUE 3;
int global_var = PREDEFINED_VALUE;
int main(int argc, char **argv)
{
printf("Hello, v = %d\n", global_var);
return 0;
}
```
]
]
.block[
* Repository: [https://sourceforge.net/projects/astyle](https://sourceforge.net/projects/astyle)
* Website: [http://astyle.sourceforge.net](http://astyle.sourceforge.net)
* License: `MIT`
]
---
# `astyle` usage
* the file type is determined from the file extension
* when a file is formatted, a copy of the original file is kept with the `.orig` extension
* general usage:
```shell
$ astyle [OPTIONS] SourceFile1 SourceFile2 SourceFile3 [...]
```
* example of a recursive usage for all `.cpp` and `.h` files:
```shell
$ astyle --style=allman --recursive *.cpp *.h
```
* example of a usage with redirections:
```shell
$ astyle --style=allman < source.cpp > destination.cpp
```
* example of a usage to check the formatting without updating the source file:
```shell
$ astyle --style=allman < source.cpp | less
```
---
# Usage with a default options file
* example of a usage with a default options file:
```shell
$ astyle --options=astyle.conf
```
## .hcenter[`[astyle.conf]`]
```shell
# this line is a comment
--style=allman # this is a line-end comment
# long options can be written without the preceding '--'
indent-switches # cannot do this on the command line
# short options must have the preceding '-'
-t -p
# short options can be concatenated together
-M60Ucv
```
* file is looked for at locations (in order)
1. `--options=file`
2. `ARTISTIC_STYLE_OPTIONS`
3. `$HOME/.astylerc`
4. `$USERPROFILE/astylerc`
* `options=none` will disable the default options file lookup
* command line options have precedence
---
# Disable formatting
## Disable the formatting of a block of code
```C++
// *INDENT-OFF*
#define FOO_DECLARE_int32_(name) \
FOO_API_ extern ::Int32 FOO_FLAG(name)
// *INDENT-ON*
```
## Disable the formatting of a line of code
```C++
size_t foo = (unsigned int) -1; // *NOPAD*
```
---
# Brace styles
.row[
.column.w48[
```C++
//--style=allman / --style=bsd / --style=break / -A1
int Foo(bool isBar)
{
if (isBar)
{
bar();
return 1;
}
else
return 0;
}
```]
.column.w48[
```C++
//--style=java / --style=attach / -A2
int Foo(bool isBar) {
if (isBar) {
bar();
return 1;
} else
return 0;
}
```]
]
.row[
.column.w48[
```C++
//--style=kr / --style=k&r / --style=k/r / -A3
int Foo(bool isBar)
{
if (isBar) {
bar();
return 1;
} else
return 0;
}
```]
.column.w48[
```C++
//--style=stroustrup / -A4
int Foo(bool isBar)
{
if (isBar) {
bar();
return 1;
}
else
return 0;
}
```]
]
.row[
.column.w48[
```C++
//--style=whitesmith / -A5
int Foo(bool isBar)
{
if (isBar)
{
bar();
return 1;
}
else
return 0;
}
```]
.column.w48[
```C++
//--style=banner / -A6
int Foo(bool isBar) {
if (isBar) {
bar();
return 1;
}
else
return 0;
}
```]
]
---
# Brace styles (continued)
.row[
.column.w48[
```C++
//--style=gnu / -A7
int Foo(bool isBar)
{
if (isBar)
{
bar();
return 1;
}
else
return 0;
}
```]
.column.w48[
```C++
//--style=linux / --style=knf / -A8
int Foo(bool isBar)
{
if (isFoo) {
bar();
return 1;
} else
return 0;
}
```]
]
.row[
.column.w48[
```C++
//--style=horstmann / --style=run-in / -A9
int Foo(bool isBar)
{ if (isBar)
{ bar();
return 1;
}
else
return 0;
}
```]
.column.w48[
```C++
//--style=1tbs / --style=otbs / -A10
int Foo(bool isBar)
{
if (isFoo) {
bar();
return 1;
} else {
return 0;
}
}
```]
]
.row[
.column.w48[
```C++
//--style=pico / -A11
int Foo(bool isBar)
{ if (isBar)
{ bar();
return 1; }
else
return 0; }
```]
.column.w48[
```C++
//--style=lisp / --style=python / -A12
int Foo(bool isBar) {
if (isBar) {
bar()
return 1; }
else
return 0; }
```]
]
---
# Brace styles (continued)
.row[
.column.w48[
```C++
//--style=google / -A14
int Foo(bool isBar) {
if (isBar) {
bar();
return 1;
} else
return 0;
}
```]
.column.w48[
```C++
//--style=vtk / -A15
int Foo(bool isBar)
{
if (isBar)
{
bar();
return 1;
}
else
return 0;
}
```]
]
.row[
.column.hcenter.w48[
```C++
//--style=mozilla / -A16
int Foo(bool isBar)
{
if (isBar) {
bar();
return 1;
} else
return 0;
}
```]
]
---
# Tab options
.row[
.column.w48[
```C++
// default indent
void Foo() {
....if (isBar1
............&& isBar2)
........bar();
}
```]
.column.w48[
```C++
//--indent=spaces=3 / -S3 [default 4]
void Foo() {
...if (isBar1
.........&& isBar2)
......bar();
}
```]
]
.row[
.column.w48[
```C++
//--indent=tab=4 / -t4 [default 4]
void Foo() {
> if (isBar1
> ........&& isBar2)
> > bar();
}
```]
.column.w48[
```C++
// --style=linux --indent=tab=8
void Foo()
{
> if (isBar1
> ....&& isBar2)
> > bar();
}
```]
]
.row[
.column.w48[
```C++
//--indent=force-tab=4 / -T4 [default 4]
void Foo() {
> if (isBar1
> > > && isBar2)
> > bar();
}
```]
.column.w48[
```C++
//--indent=force-tab-x=8 / -xT8 [default 8]
void Foo() {
....if (isBar1
> ....&& isBar2)
> bar();
}
```]
]
---
# Conclusions on `astyle`
* use `astyle` to be sure that your source is well formatted
* **experiment** with `astyle` options and **choose what suits you best**
* when joining a project, **follow the formatting guidelines**
* :warning: in your code, **stick with your formatting style**
* in your projects, create an `astyle.conf` style that defines your formatting style
* `astyle` will **not** refactor your code or rename your variables / classes
.vspace[]
.hcenter.w90[]
.hcenter[[source: xkcd](https://xkcd.com/1513)]
---
class: top
# Development tools
## Tools presented in this course
* version control system
* `subversion`, `mercurial`, `CVS`, `SVN`, `Bazaar`, **`git`** :+:
* build system
* `Distutils`, `CMake`, `Autotools`, `qmake`, **`GNU Make`** :+:
* documentation generator
* `Sphinx`, `Docutils`, **`Doxygen`** :+:
* unit testing framework
* `*test*`, **`CxxTest`** :+:
* code formatting tool
* **`astyle`** :+:
* commenting conventions
* various guidelines
* performance analysis tools
* will be presented in PSA (S4)
* binding generator
* will be presented in PSA (S4)
---
# Scientific programming
## Scientific tools presented in this course
* linear algebra libraries (usable from `C++`)
* `Boost`, `LAPACK`, `BLAS`, `MKL`, `GSL`, `Eigen`, **`Armadillo`** :+:
* scientific programming with Python
* **introduction to Python**
* **`Numpy`**
* presenting results
* write beautiful math: ** .latex[LaTeX] ** .animated.infinite.flash[:arrow_left:]
* structure your documentation: **Markdown**
* write some slides: **remark.js**
## Scientific techniques presented in this course
* numerical integration
* **Gaussian quadrature**
---
# .latex[LaTeX]
.hcenter.shadow.w20[]
## Key points
* created by Leslie Lamport (winner of the 2013 Turing Award) in the 80s
* used to communicate and publish scientific documents in **all scientific fields**
* markup language
* written in the `TeX` macro language
.block[
* Repository: [https://www.latex-project.org//svnroot/experimental/trunk](https://www.latex-project.org//svnroot/experimental/trunk)
* Website: [https://www.latex-project.org](https://www.latex-project.org)
* License: `LPPL` (LaTeX Project Public License, not `GPL`-compatible)
]
---
# The .latex[LaTeX] workflow
## Historical workflow
.hcenter.w80.mermaid[
graph LR
A("1. Write / modify
the source file") --> B
B("2. Generate a .dvi
with latex") --> C
C("2. Generate a .ps
with dvips") --> D
D("3. Check the result
with a ps viewer") --> A
style B fill:#090
]
## "Recent" workflow
.hcenter.w55.mermaid[
graph LR
A("1. Write / modify
the source file") --> B
B("2. Generate
with pdflatex") --> C
C("3. Check the result
with a pdf viewer") --> A
style B fill:#090
]
---
# .latex[LaTeX] example
## 1. Write / modify the source file
Use your favorite **text editor**, not a WYSIWYG one.
## .hcenter[`[example.tex]`]
```TeX
\documentclass[12pt]{article}
\begin{document}
\section{My very first \LaTeX\ example}
\subsection{Excerpt from wikipedia}
\LaTeX follows the design philosophy of separating presentation from content, so that authors can focus on the
content of what they are writing without attending simultaneously to its visual appearance. In preparing a \LaTeX
docu\-ment, the author specifies the logical structure using simple, familiar concepts such as chapter, section,
table, figure, etc., and lets the \LaTeX system worry about the formatting and layout of these structures. It
therefore encourages the separation of layout from content while still allowing manual typesetting adjustments
where needed. This concept is similar to the mechanism by which many word processors allow styles to be defined
globally for an entire document or the use of Cascading Style Sheets to style HTML. The \LaTeX system is a markup
language that also handles typesetting and rendering.
\subsection{Some math ?}
Yes, \LaTeX can do some math, either inline like $f(x)\equiv x^2e^{\sqrt{x + 1}}$, or in a math block like
\begin{equation}
A.B = \frac{-1}{\sqrt{2}} E.B^{-1}
\end{equation}
\end{document}
```
---
# .latex[LaTeX] example
## 2. Generate with `pdflatex`
```shell
*$ pdflatex example.tex
This is pdfTeX, Version 3.14159265-2.6-1.40.17 (TeX Live 2016/Debian) (preloaded format=pdflatex)
restricted \write18 enabled.
entering extended mode
(./example.tex
LaTeX2e <2017/01/01> patch level 3
Babel <3.9r> and hyphenation patterns for 3 language(s) loaded.
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size12.clo)) (./example.aux)
[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] (./example.aux) )
Output written on example.pdf (1 page, 70040 bytes).
Transcript written on example.log.
```
---
# .latex[LaTeX] example
## 3. Check the result with a `.pdf` viewer
.hcenter.border.shadow.w70[]
---
# Remarks on the usual .latex[LaTeX] workflow
## Using full .latex[LaTeX]
* some are **fine** with this workflow
* some prefer a WYSIWYM editor (`LyX`...)
* some prefer a WYSIWYG editor (`BaKoMa TeX`, `Scientific Word`...) :warning: **not free**
:arrow_right: **My advice**: for scientific papers only.
## Using only the math engine of .latex[LaTeX]
* allows to insert .latex[LaTeX] math blocks in another formatting tool / language
* examples: **`MathJax`**, **`Markdown`**, **`Doxygen`**...
:arrow_right: **My advice**: for scientific presentations, documentations, web pages...
---
# .latex[LaTeX] math syntax
.row[.column.middle.w50[```TeX
S_i = 1 + 2 + 3 + \ldots + i
```]
.column.hcenter.middle.w48[
`$$
S_i = 1 + 2 + 3 + \ldots + i
$$`
]]
----
.row[.column.middle.w50[```TeX
S_{ i } =1+2
+
3 +\ldots + i
```]
.column.hcenter.middle.w48[
`$$
S_{ i } =1+2
+
3 +\ldots + i
$$`
]]
----
.row[.column.middle.w50[```TeX
a_i^j = b_{i + 1}^{-1} + \frac{c^2 + d}
{ \sqrt{e + f + 0.4} }
```]
.column.hcenter.middle.w48[
`$$
a_i^j = b_{i + 1}^{-1} + \frac{c^2 + d}{\sqrt{e + f + 0.4}}
$$`
]]
----
.row[.column.middle.w50[```TeX
S \equiv \sum_{k = 1}^\infty \frac{1}{k^2}
= \frac{\pi^2}{6}
```]
.column.hcenter.middle.w48[
`$$
S \equiv \sum_{k = 1}^\infty \frac{1}{k^2} = \frac{\pi^2}{6}
$$`
]]
----
.row[.column.middle.w50[```TeX
\hat{\mathcal{H}}|\psi_i\rangle = E_i|\psi_i\rangle
```]
.column.hcenter.middle.w48[
`$$
\hat{\mathcal{H}}|\psi_i\rangle = E_i|\psi_i\rangle
$$`
]]
----
.row[.column.middle.w50[```TeX
\left(\frac{1}{2} + \frac{3}{4}\right) =1 + \frac{1}{4}
```]
.column.hcenter.middle.w48[
`$$
\left(\frac{1}{2} + \frac{3}{4}\right) =1 + \frac{1}{4}
$$`
]]
---
# .latex[LaTeX] math syntax
.row[.column.middle.w50[```TeX
D = \left|\begin{array}{ccc}
a & b & c\\
d & e & f\\
g & h & i
\end{array}\right|
```]
.column.hcenter.middle.w48[
`$$
D = \left|\begin{array}{ccc}
a & b & c\\
d & e & f\\
g & h & i
\end{array}\right|
$$`
]]
----
.row[.column.middle.w50[```TeX
\Psi_\alpha = \int_{-\infty}^{\infty} %
\exp \left( \sqrt{\alpha} \, -x^2\right) d x
```]
.column.hcenter.middle.w48[
`$$
\Psi_\alpha = \int_{-\infty}^{\infty} %
\exp \left( \sqrt{\alpha} \, -x^2\right) d x
$$`
]]
----
.row[.column.middle.w50[```TeX
I_{\sigma} =
\int_{z=-\infty}^{\infty}
\int_{\theta=0}^{2\pi}
\int_{r_\perp = 0}^{\infty}
e^{-\frac{r_\perp^2+z^2}{\sigma^2}}
r_\perp dr_\perp d\theta dz
```]
.column.hcenter.middle.w48[
`$$
I_{\sigma} =
\int_{z=-\infty}^{\infty}
\int_{\theta=0}^{2\pi}
\int_{r_\perp = 0}^{\infty}
e^{-\frac{r_\perp^2+z^2}{\sigma^2}}
r_\perp dr_\perp d\theta dz
$$`
]]
----
.row[.column.middle.w50[```TeX
\begin{array}{cccccccc}
\alpha&\theta&o&\tau&\beta&\vartheta&\pi&\upsilon\\
\gamma&\gamma&\varpi&\phi&\delta&\kappa&\rho&\varphi\\
\epsilon&\lambda&\varrho&\chi&\varepsilon&\mu&
\sigma&\psi\\
\zeta&\nu&\varsigma&\omega&\eta&\xi\\
\Gamma&\Lambda&\Sigma&\Psi&\Delta&\Xi&\Upsilon&\Omega\\
\Theta&\Pi&\Phi\\
\end{array}
```]
.column.hcenter.middle.w48[
`$$
\begin{array}{cccccccc}
\alpha&\theta&o&\tau&\beta&\vartheta&\pi&\upsilon\\
\gamma&\gamma&\varpi&\phi&\delta&\kappa&\rho&\varphi\\
\epsilon&\lambda&\varrho&\chi&\varepsilon&\mu&
\sigma&\psi\\
\zeta&\nu&\varsigma&\omega&\eta&\xi\\
\Gamma&\Lambda&\Sigma&\Psi&\Delta&\Xi&\Upsilon&\Omega\\
\Theta&\Pi&\Phi\\
\end{array}
$$`
]]
---
# .latex[LaTeX] math syntax
## Some math symbols
.row[.column.middle.w50[```TeX
\odot \iiint \oint \smile \fallingdotseq \simeq \subset
```]
.column.hcenter.middle.w48[
`$$
\odot \iiint \oint \smile \fallingdotseq \simeq \subset
$$`
]]
----
.row[.column.middle.w50[```TeX
\sin(\theta) \cos(\theta) \tan(\theta)
```]
.column.hcenter.middle.w48[
`$$
\sin(\theta) \cos(\theta) \tan(\theta)
$$`
]]
----
.row[.column.middle.w50[```TeX
\sinh(x) \cosh (x) \tanh(x)
```]
.column.hcenter.middle.w48[
`$$
\sinh(x) \cosh (x) \tanh(x)
$$`
]]
----
.row[.column.middle.w50[```TeX
\exp(z) \det(M)
```]
.column.hcenter.middle.w48[
`$$
\exp(z) \det(M)
$$`
]]
## List of math symbols
* [http://tug.ctan.org/info/symbols/comprehensive/symbols-a4.pdf](http://tug.ctan.org/info/symbols/comprehensive/symbols-a4.pdf) (338 pages !)
* [http://oeis.org/wiki/List_of_LaTeX_mathematical_symbols](http://oeis.org/wiki/List_of_LaTeX_mathematical_symbols)
---
# Scientific programming
## Scientific tools presented in this course
* linear algebra libraries (usable from `C++`)
* `Boost`, `LAPACK`, `BLAS`, `MKL`, `GSL`, `Eigen`, **`Armadillo`** :+:
* scientific programming with Python
* **introduction to Python**
* **`Numpy`**
* presenting results
* write beautiful math: ** .latex[LaTeX] ** :+:
* structure your documentation: **Markdown** .animated.infinite.flash[:arrow_left:]
* write some slides: **remark.js**
## Scientific techniques presented in this course
* numerical integration
* **Gaussian quadrature**
---
# `Markdown`
.row.hcenter.w60[
.column.shadow.w30.animated.fadeInLeft.wait1s[

]
.column.w30[

]
.column.shadow.w30.animated.fadeInRight.wait1s[

]
]
## Key points
* created by *John Gruber* and *Aaron Swartz* in 2004
* text-to-HTML conversion tool + plain text formatting syntax
* **easy to read and easy to write**
* generates valid `XHTML`
* no standard implementation
* variants used by GitHub, Bitbucket, Reddit, Diaspora, Stack Exchange, OpenStreetMap, SourceForge, **`remark.js`**...
.block[
* Website: [https://daringfireball.net/projects/markdown](https://daringfireball.net/projects/markdown)
* License: `BSD`
]
---
# `Markdown` example
.row[
.column.w48.middle[
## .hcenter[`[example.md]`]
```markdown
A second level header
---------------------
## Another second level header
The first level header is reserved for the title of
the slides. The quick brown fox jumped over the lazy
dog.
### Header 3
> This is a blockquote.
>
> This is the second paragraph in the blockquote.
>
> ## This is an H2 in a blockquote
| Here is a table | easy ! |
| ----------------- | -------- |
| some regular text | **bold** |
```
]
.column.w48.middle.border.shadow[
A second level header
---------------------
## Another second level header
The first level header is reserved for the title of
the slides. The quick brown fox jumped over the lazy
dog.
### Header 3
> This is a blockquote.
>
> This is the second paragraph in the blockquote.
>
> ## This is an H2 in a blockquote
| Here is a table | easy ! |
| ----------------- | -------- |
| some regular text | **bold** |
]]
---
# `Markdown` example
.row[
.column.w48.middle[
```markdown
Some `\(\LaTeX\)` thanks to **`MathJax`**:
`$$ \pi \simeq 3.1415926535 \ldots $$`
``` ]
.column.w48.middle.border.shadow[
Some `\(\LaTeX\)` thanks to **`MathJax`**:
`$$ \pi \simeq 3.1415926535 \ldots $$`
]]
----
.row[
.column.w48.middle[
```markdown
## Item list
* first item
* second item
* third item
## Enumerated list
1. first item
2. second item
3. third item
``` ]
.column.w48.middle.border.shadow[
## Item list
* first item
* second item
* third item
## Enumerated list
1. first item
2. second item
3. third item
]]
----
.row[
.column.w48.middle[
Include some code:
```C++
double calcSquare(double a)
{
double result = a + a;
return result;
}
```
]
.column.w48.middle.border.shadow[
Include some code:
```C++
double calcSquare(double a)
{
double result = a + a;
return result;
}
```
]]
---
# Scientific programming
## Scientific tools presented in this course
* linear algebra libraries (usable from `C++`)
* `Boost`, `LAPACK`, `BLAS`, `MKL`, `GSL`, `Eigen`, **`Armadillo`** :+:
* scientific programming with Python
* **introduction to Python**
* **`Numpy`**
* presenting results
* write beautiful math: ** .latex[LaTeX] ** :+:
* structure your documentation: **Markdown** :+:
* write some slides: **remark.js** .animated.infinite.flash[:arrow_left:]
## Scientific techniques presented in this course
* numerical integration
* **Gaussian quadrature**
---
# These slides use `remark.js`
:warning: Important concept in `remark.js`:
.row[
.column.w47.middle[
```markdown
.class0.class1.class2[
some text
]
```
]
.column.w5.middle[
:arrow_right:
]
.column.w47.middle[
```HTML
```]]
.row[
.column.w47.middle[
```markdown
.class0.class1.class2[ some text ]
```
]
.column.w5.middle[
:arrow_right:
]
.column.w47.middle[
```HTML
some text
```]]
.vspace[]
----
.vspace[]
:arrow_right: These slides use original or slightly modified versions of the following **opensource** projects:
* [remark.js](https://remarkjs.com): `Markdown` slides generator and presentation tool.
* [mermaid.js](https://mermaidjs.github.io): Generate diagrams with a Markdown-like syntax.
* [cinescript.js](https://github.com/arnehilmann/cinescript): Replay terminal capture.
* [highlight.js](https://highlightjs.org): Highlight source code.
* [gitgraph.js](http://gitgraphjs.com): Make nice `git` graphs.
* [mathjax](https://mathjax.org): Use .latex[LaTeX] math blocks.
* [emojify.js](https://github.com/emojione/emojify.js): Use emoticons in your `Markdown` source :-)
* [term.js](https://github.com/chjj/term.js): Display a terminal emulator in javascript.
* [plotly.js](https://plot.ly/javascript): Generate interactive plots in Javascript.
* [animate.css](https://daneden.github.io/animate.css): Pure `CSS` animations.
---
# Scientific programming
## Scientific tools presented in this course
* linear algebra libraries (usable from `C++`)
* `Boost`, `LAPACK`, `BLAS`, `MKL`, `GSL`, `Eigen`, **`Armadillo`** :+:
* scientific programming with Python
* **introduction to Python** .animated.infinite.flash[:arrow_left:]
* **`Numpy`**
* presenting results
* write beautiful math: ** .latex[LaTeX] ** :+:
* structure your documentation: **Markdown** :+:
* write some slides: **remark.js** :+:
## Scientific techniques presented in this course
* numerical integration
* **Gaussian quadrature**
---
# Python
.hcenter.w40[

]
.noflex[
.rightf.animated.middle.fadeInRight.wait1s.shadow.w20[]
## Key points
* created by **Guido van Rossum** in 1989, first released in 1991
* name comes from the series **Monty Python's Flying Circus**
* **high-level**, **interpreted** programming language
* widely used by projects **of every size**
* emphasis on **code readability** and **powerful and concise syntax**
* supports **multiple programming paradigms** (object-oriented, imperative...)
* very large **standard library**
* reference implementation and interpreter: **`CPython`**
]
.block[
* `CPython` repository: [https://github.com/python/cpython](https://github.com/python/cpython)
* `Python` website: [https://www.python.org](https://www.python.org)
* `CPython` license: `PSFL` (Python Software Foundation License, compatible with the GPL)
]
---
# Python core philosophy
.noflex[
.rightf.animated.fadeInRight.wait1s.shadow.w25[]
## The Zen of Python, by Tim Peters (PEP 20)
1. Beautiful is better than ugly.
1. Explicit is better than implicit.
1. Simple is better than complex.
1. Complex is better than complicated.
1. Flat is better than nested.
1. Sparse is better than dense.
1. Readability counts.
1. Special cases aren't special enough to break the rules.
1. Although practicality beats purity.
1. Errors should never pass silently.
1. Unless explicitly silenced.
1. In the face of ambiguity, refuse the temptation to guess.
1. There should be one *and preferably only one* obvious way to do it.
1. Although that way may not be obvious at first unless you're Dutch.
1. Now is better than never.
1. Although never is often better than *right* now.
1. If the implementation is hard to explain, it's a bad idea.
1. If the implementation is easy to explain, it may be a good idea.
1. Namespaces are one honking great idea -- let's do more of those!
]
:arrow_right: Some examples of good Python style can be found [here](http://artifex.org/~hblanks/talks/2011/pep20_by_example.pdf).
---
# Python `helloworld`
## .hcenter[`[helloworld.py]`]
```python
#!/usr/bin/env python
# ^^ use '#!/usr/bin/env python3' for python3 scripts
# declare variables
a = 2
b = 8
# add two numbers
c = a + b
# print some message
print("Hello from Python ! (c = %d)" % (c))
```
## .hcenter[Shell session]
```shell
$ chmod +x helloworld.py
$ ./helloworld.py
Hello from Python ! (c = 10)
```
.vspace[]
## Explanations
* Line 1: path to the Python interpreter
* Lines 3, 7, 10: lines starting with `#` are comments
* Lines 4, 5, 8: typing is dynamic
* Line 11: `%` allows some form of string formatting
---
# Python indentation
.alert.hcenter[
There is **no symbol** to delimitate blocks of code in `Python`.
Blocks of code are defined using **indentation**.
]
.vspace[]
.numbers[
## Valid syntaxes
.row[
.column.w30[
```python
if True:
print("Always")
```]
.column.w30[
```python
if True:
print("Always")
else:
print("Never")
```]
.column.w30[
```python
if True:
print("Almost")
print("Always")
else:
print("Almost")
print("Never")
```]
]
.vspace[]
## Invalid syntaxes
.row[
.column.w30[
```python
if True
print("Always")
```]
.column.w30[
```python
if True:
print("Almost")
print("Always")
```]
.column.w30[
```python
if True:
print("Almost")
print("Always")
else:
print("Almost")
print("Never")
```]
]
]
---
# Python identifiers
## Identifiers
* Identifiers name variables, functions, classes, modules, objects...
* They start with `[A-Za-z_]`, followed by zero or more `[A-Za-z0-9_]`.
* `Python` is **case-sensitive**.
## Reserved words
.block.hcenter[
and exec not assert finally or break for pass class def print
continue from global raise with return del import try elif in
while else is if except lambda yield False True None
]
## Naming conventions
* Class names start with an **uppercase letter**. All other identifiers start with a **lowercase letter**.
* Starting an identifier with a **single leading underscore** indicates that the identifier is **private**.
* Starting an identifier with **two leading underscores** indicates a **strongly private** identifier.
* If the identifier also ends with **two trailing underscores**, the identifier is a **language-defined special name**.
---
# Functions and classes
```python
def func0(arg0, arg1 = 6): # define a function
c = arg0 + arg1
return c
func0(2) # 8
func0(2, 3) # 5
func0("abc", "def") # "abcdef"
```
```python
class MyClass: # define a class
a = 3
def __init__(self, b = None):
print("Hello from constructor")
self.c = "toto"
print("a = %r" % (self.a))
print("b = %r" % (b))
print("c = %r" % (self.c))
d = self.myMethod(4, 4)
print("d = %r" % (d))
def myMethod(self, a, b = 2): # instance method
return self.a + a + b
@classmethod
def myClassMethod(MyClass): # class method
return 'this is like a static method'
myClass = MyClass(6)
# Output:
# Hello from constructor
# a = 3
# b = 6
# c = 'toto'
# d = 11
myClass.x = 'new value' # add a new property
print(myClass.x) # 'new value'
print(MyClass.myClassMethod()) # 'this is like a static method'
```
---
# Modules
* the `import` keyword allows to access built-in and / or custom modules
```python
import math # import the "math" module
print(math.sqrt(2)) # 1.41421356237
```
* the keyword `as` allows to import a module under an alias name
```python
import math as m # import the "math" module and name it "m"
print(m.sqrt(2)) # 1.41421356237
```
* the keyword `from` allows to select what to import from a module
```python
from math import sqrt # import only the "sqrt" function from the math module
print(sqrt(2)) # 1.41421356237
```
* the wildcard `*` allows to import everything from a module
```python
from math import * # import everything from the math module
print(sqrt(2)) # 1.41421356237
```
---
# Custom modules
* create a file containing functions, values, classes, etc...
## .hcenter[`[example.py]`]
```python
someval = 42 # a value
def func(a, b): # a function
return a + b
```
* if `example.py` is in the current directory (`./example.py`):
```python
import example
print(example.func("Hello ", "world") # "Hello world"
print(example.someval) # 42
```
* if `example.py` is in a subdirectory (`./somedir/example.py`):
```python
import somedir
print(somedir.func("Hello ", "world") # "Hello world"
print(somedir.someval) # 42
```
or use `as` keyword:
```python
import somedir as example
print(example.func("Hello ", "world") # "Hello world"
print(example.someval) # 42
```
---
# Module search path
* when looking for a module to import, python tries the following:
1. search for a built-in module
2. search directories from `sys.path`, in order
```python
import sys
print(sys.path)
# Output:
*# ['',
# '/usr/bin', '/usr/lib64/python27.zip', '/usr/lib64/python2.7',
# '/usr/lib64/python2.7/plat-linux2', '/usr/lib64/python2.7/lib-tk',
# ...
*# '.local/lib/python2.7/site-packages',
# ...
# '/usr/lib/python2.7/site-packages/IPython/Extensions',
*# '/home/dubrayn/.ipython']
```
---
# The docstrings
## What ?
```python
def mySuperSum(a, b):
"""This function adds two objects"""
return a + b
def mySuperProd(a, b):
"""This function multiplies two objects.
Of course, a and b must allow a to be multiplied by b.
Try this function with random input objects at your own risk.
"""
return a * b
```
## Why ?
* the python function `help()` will print this documentation
* some IDE can print this documentation if needed
* these docstrings can be automatically extracted ( :v: `doxygen` :v: )
* it is the standard way to document python code
* the python code can use this docstring
* some tests and / or examples can be put in the docstrings
## How to use them ?
```python
help(mySuperSum) # in interactive mode
print(mySuperSum.__doc__)
```
---
# The `dir()` built-in function
:arrow_right: this function allows to list objects defined in a module
## .hcenter[`[example.py]`]
```python
someval = 42 # a value
def func(a, b): # a function
return a + b
```
* if `example.py` is in the current directory (`./example.py`):
```python
import example
*print(dir(example))
# Output:
# ['__builtins__',
# '__doc__',
# '__file__',
# '__name__',
# '__package__',
# 'func',
# 'someval']
```
* without arguments, `dir()` returns a list of objects defined in the current namespace
```python
*print(dir())
# Output:
# ['In', 'Out', '__', '_', '__IP', '___', '__builtins__', '__name__',
# '_dh', '_i', '_i1', '_ih', '_ii', '_iii', '_ip', '_oh', '_sh', 'help' ]
```
---
# Built-in types
## Mutability
* a **mutable object** has methods to modify its content
* an **immutable object** does not have methods to modify its content
:arrow_right: immutable built-in objects are hashable !
## Mutable types
* `list`: an ordered list of objects
* `set`: an unordered list of **unique hashable objects**
* `dict`: an unordered list of (key, object) couples (key must be hashable, and should be immutable)
## Immutable types
* `tuple`: like `list`, but immutable
* `frozenset`: like `set`, but immutable
* `numbers`: regular numbers
* `string`: :warning: **strings are immutable in Python** :warning:
## Containers
* they are empty or contain references to other objects
* `list`, `tuple`, `dict`, `set`, `frozenset`, etc...
---
class: top
# Containers mutability
## Is a `set` mutable ?
```python
x = set([1, 2, 3])
x |= set([2, 3, 4]) # is Python copying an immutable object ?
print(x) # set([1, 2, 3, 4])
```
:arrow_right: **yes**, a `set` is mutable:
```python
x = set([1, 2, 3])
x.__ior__(set([2, 3, 4])) # "|=" makes Python call .__ior__() method
print(x) # set([1, 2, 3, 4])
```
## If a `tuple` is immutable, how is this possible ?
```python
tuple0 = (1, 2) # tuple declaration
list0 = [3, 4] # list declaration
print(type(tuple0)) #
tuple1 = (tuple0, list0) # tuple declaration
print(type(tuple1)) #
print(tuple1) # ((1, 2), [3, 4])
list0[0] = -1 # change list0
print(tuple1) # ((1, 2), [-1, 4])
```
--
:arrow_right: A container stores **references**, not objects.
---
# Numeric types
## Standard numeric types: `int`, `float` and `complex`
* `int` have **unlimited precision**
* `float` usually correspond to a `C` `double` (check `sys.float_info`)
* `complex` number's real and imaginary parts are `float` numbers (`z.real` and `z.imag`)
:arrow_right: other types can be found in the standard library (`fractions`, `decimal`...)
## Operations
```python
x + y # sum of x and y
x - y # difference of x and y
x * y # product of x and y
x / y # quotient of x and y
x // y # floored quotient of x and y
x % y # remainder of x / y
-x # x negated
+x # x unchanged
abs(x) # absolute value or magnitude of x
int(x) # x converted to integer
float(x) # x converted to floating point
complex(re, im) # a complex number
c.conjugate() # conjugate of the complex number c
divmod(x, y) # the pair (x // y, x % y)
pow(x, y) # x to the power y
x ** y # x to the power y
# for int and float numbers:
math.trunc(x) # x truncated to Integral
round(x[, n]) # x rounded to n digits, rounding half to even. If n is omitted, it defaults to 0.
math.floor(x) # the greatest Integral <= x
math.ceil(x) # the least Integral >= x
```
---
# Specific operations on `int` and `float` numbers
## Bitwise operations for `int`
```python
x | y # bitwise or of x and y
x ^ y # bitwise exclusive or of x and y
x & y # bitwise and of x and y
x << n # x shifted left by n bits
x >> n # x shifted right by n bits
~x # the bits of x inverted
```
## Other methods for `int`
```python
n = -37
bin(n) # '-0b100101'
n.bit_length() # 6
```
```python
(1024).to_bytes(2, byteorder='big') # b'\x04\x00'
(1024).to_bytes(10, byteorder='big') # b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00'
(-1024).to_bytes(10, byteorder='big', signed=True) # b'\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00'
```
```python
int.from_bytes(b'\x00\x10', byteorder='big') # 16
int.from_bytes(b'\x00\x10', byteorder='little') # 4096
int.from_bytes(b'\xfc\x00', byteorder='big', signed=True) # -1024
int.from_bytes(b'\xfc\x00', byteorder='big', signed=False) # 64512
int.from_bytes([255, 0, 0], byteorder='big') # 16711680
```
## Other methods for `float`
```python
# hex format: [sign] ['0x'] integer ['.' fraction] ['p' exponent]
float.fromhex('0x3.a7p10') # 3740.0
float.hex(3740.0) # '0x1.d380000000000p+11'
```
---
# Using `list` objects
```python
l1 = [] # create an empty list
l1.append(7) # append value
l2 = ['final', 'final2']
l1.extend(l2) # append another list
l1.insert(1, 8) # insert value
print(l1) # [7, 8, 'final', 'final2']
v = l1.pop() # get and remove last value
print(v) # 'final2'
print(l1) # [7, 8, 'final']
del l1[-1] # remove last value
print(len(l1)) # 2
l2 = [1, 2, "pipo"] # create another list
l3 = l2 # l3 is another name for l2 list
print(l2) # [1, 2, 'pipo']
print(l3) # [1, 2, 'pipo']
l3.append('new') # append value to l3
print(l2) # [1, 2, 'pipo', 'new']
print(l3) # [1, 2, 'pipo', 'new']
l4 = list(l2) # copy a list
l4.append(3.142) # append value to l4
print(l2) # [1, 2, 'pipo', 'new']
print(l4) # [1, 2, 'pipo', 'new', 3.1419999999999999]
l5 = list('abcdef') # create list from string
print(l5) # ['a', 'b', 'c', 'd', 'e', 'f']
l6 = [l1, l2, 3] # create a list containing lists
print(l6) # [[7, 8], [1, 2, 'pipo', 'new'], 3]
```
---
# Using `list` elements and ranges
## Element access
```python
l = range(5)
l # [0, 1, 2, 3, 4]
l[2] # 2
l[-1] # 4
l[2] = 8
l # [0, 1, 8, 3, 4]
del l[3]
l # [0, 1, 8, 4]
```
## Ranges
```python
l = [0, 1, 2, 3, 4]
l[0:3] # [0, 1, 2]
l[::2] # [0, 2, 4]
l[-1:] # [4]
l[-3:-1] # [2, 3]
l[:] # [0, 1, 2, 3, 4]
l[2:3] # [2]
l[2:3] = ['X', 'Y']
l # [0, 1, 'X', 'Y', 3, 4]
range(3, 6, 2) # [3, 5]
```
## Concatenation
```python
[1, 2] + [3, 4] # [1, 2, 3, 4]
[1, 2] * 3 # [1, 2, 1, 2, 1, 2]
```
## Searching
```python
l = [0, 1, 2, 3, 4]
3 in l # True
l.index(3) # 3
5 in l # False
```
---
# Loops and iterators
## Iterate over values
```python
l = list('abcde')
for v in l:
print(v)
# Output:
# 'a'
# 'b'
# 'c'
# 'd'
# 'e'
```
## Iterate over indices
```python
l = list('abcde')
for i in range(len(l)):
print("index: %d val: %r" % (i, l[i]))
# Output:
# index: 0 val: 'a'
# index: 1 val: 'b'
# index: 2 val: 'c'
# index: 3 val: 'd'
# index: 4 val: 'e'
```
## Iterate over indices and values
```python
l = list('abcde')
for i, v in enumerate(l):
print("index: %d val: %r" % (i, v))
# Output:
# index: 0 val: 'a'
# index: 1 val: 'b'
# index: 2 val: 'c'
# index: 3 val: 'd'
# index: 4 val: 'e'
```
---
# `filter`, `map`, `reduce`
:arrow_right: used in functionnal programming
* `filter` keeps elements matching a criterion
```python
def f(x):
return x % 3 == 0 or x % 5 == 0
l = range(2, 25)
filter(f, l) # [3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24]
```
* `map` applies a function to each element
```python
def cube(x):
return x*x*x
map(cube, range(1, 11)) # [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
# Example with two arguments
seq = range(8)
def add(x, y):
return x+y
map(add, seq, seq) # [0, 2, 4, 6, 8, 10, 12, 14]
```
* `reduce` propagates the cumulative result of a function
```python
def add(x,y):
return x+y
reduce(add, range(1, 11)) # 55
```
---
# List comprehensions
:arrow_right: allows to create lists in a **very concise way**
## Generic syntax
```python
[ expr for var in expr [for var in expr]* [if expr]* ]
```
## Examples
```python
# list of the first 6 even numbers
[i * 2 for i in range(6)] # [0, 2, 4, 6, 8, 10]
# combine elements of two lists if they differ
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y] # [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
# is equivalent to
final = []
for x in [1,2,3]:
for y in [3,1,4]:
if x != y:
final.append((x, y))
final # [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
```
---
# Using `string` objects
## Spliting / joining
```python
s = 'A simple string'
s.split() # ['A', 'simple', 'string']
' '.join(s.split()) # 'A simple string'
' some text '.strip() # 'some text'
'some' + ' ' + 'text' # 'some text'
'pipo' * 3 # 'pipopipopipo'
```
## String formatting
```python
n = 3
l = range(3)
'n: %03d l: %r' % (n, l) # 'n: 003 l: [0, 1, 2]'
```
:warning: **strings are immutable in Python** :warning:
```python
a = 'Some text'
print(a[5]) # 't'
*a[5] = 'T' # ILLEGAL
a.replace('text', 'Text') # 'Some Text'
a[:5] + 'T' + a[6:] # 'Some Text'
```
---
# Using `dict` objects
* A `dict` stores unordered (`key`, `value`) pairs
* Keys are unique and not ordered
```python
# create an empty dict
d = {}
d = dict()
# initialize a dict
other_dict = {'first': 8, 'other': ['a', 'pair'], 'toto': {'pipo': 42}}
other_dict = dict(first = 8, other = ['a', 'pair'], toto = dict(pipo = 42))
d['key0'] = 'text0'
d['key1'] = 'text1'
d['key2'] = 'text2'
print(d) # {'key2': 'text2', 'key0': 'text0', 'key1': 'text1'}
d['key0'] = 'other_text' # replace value for key 'key0'
del d['key1'] # remove key and value for key 'key1'
print(d) # {'key2': 'text2', 'key0': 'other_text'}
'key1' in d # False
'key2' in d # True
d.keys() # ['key2', 'key0']
d.values() # ['text2', 'other_text']
for k in d: # iterate over a dict
print(k)
# Output:
# key2
# key0
```
---
# Using `set` objects
* A `set` stores unordered and unique objects
```python
# create an empty set
s = set()
# initialize a set
s1 = set(['Beta', 'Gamma', 'Alpha', 'Delta', 'Gamma', 'Beta'])
s2 = set(['Beta', 'Alpha', 'Epsilon', 'Omega', 'Psi'])
s1 # set(['Alpha', 'Beta', 'Gamma', 'Delta'])
s2 # set(['Alpha', 'Beta', 'Omega', 'Psi', 'Epsilon'])
# test if a value is in a set
'Psi' in s2 # True
# remove a value
s2.remove('Psi')
'Psi' in s2 # False
s2 # set(['Alpha', 'Beta', 'Omega', 'Epsilon'])
```
## Usual `set` operations
```python
s1 = set(['Alpha', 'Beta', 'Gamma', 'Delta'])
s2 = set(['Alpha', 'Beta', 'Omega', 'Epsilon'])
s1.union(s2) # set(['Epsilon', 'Beta', 'Delta', 'Alpha', 'Omega', 'Gamma'])
s1 | s2 # set(['Epsilon', 'Beta', 'Delta', 'Alpha', 'Omega', 'Gamma'])
s1.intersection(s2) # set(['Alpha', 'Beta'])
s1 & s2 # set(['Alpha', 'Beta'])
s1.difference(s2) # set(['Gamma', 'Delta'])
s1 - s2 # set(['Gamma', 'Delta'])
s1.symmetric_difference(s2) # set(['Epsilon', 'Delta', 'Omega', 'Gamma'])
s1 ^ s2 # set(['Epsilon', 'Delta', 'Omega', 'Gamma'])
```
---
# File IO
## .hcenter[`[data.txt]`]
```text
1.0 2.1 3.0 4.9 5.9
9.0 8.2 5.7 6.2 7.1
2.2 3.6 4.4
```
## Read
```python
f = open('data.txt')
lines = f.readlines()
words = [l.split() for l in lines]
print(words)
# Output:
# [['1.0', '2.1', '3.0', '4.9', '5.9'], ['9.0', '8.2', '5.7', '6.2', '7.1'], ['2.2', '3.6', '4.4'], []]
# one-liner
[l.split() for l in open('data.txt').readlines()]
# Output:
# [['1.0', '2.1', '3.0', '4.9', '5.9'], ['9.0', '8.2', '5.7', '6.2', '7.1'], ['2.2', '3.6', '4.4'], []]
```
---
# Module `pickle`
:arrow_right: allows to serialize / deserialize data
## Write
```python
import pickle
data1 = {'a': [1, 2.0, 3, 4+6j],
'b': ('string', u'Unicode string'),
'c': None}
selfref_list = [1, 2, 3]
selfref_list.append(selfref_list)
output = open('data.pkl', 'wb')
pickle.dump(data1, output)
output.close()
```
## Read
```python
import pprint, pickle
pkl_file = open('data.pkl', 'rb')
data1 = pickle.load(pkl_file)
pprint.pprint(data1)
# Output:
# {'a': [1, 2.0, 3, (4+6j)], 'b': ('string', u'Unicode string'), 'c': None}
pkl_file.close()
```
.hcenter[:warning: `pickle` file formats differ between Python2 and Python3 versions:warning:]
---
# `True`, `False`, `not`, `and`, `or` keywords
* usual Boolean values and operations
* "`==`" tests value equality
* `True` is the same object as `1`
* `False` is the same object as `0`
```python
3 == 5 # False
2 == 2 # False
1 + 1 == 2 # True
True or False # True
True or not True # True
True and True # True
False and True # False
True == 1 # True
False == 0 # True
True + True + False # 2
```
---
# `None` keyword
* special constant representing the absence of a value
* the type of `None` is `NoneType`
* :warning: `None` does not imply `False`, `0`, or an empty container
```python
None == 0 # False
None == [] # False
None == False # False
a = None
b = None
a == b # True
```
:arrow_right: A void function without a `return` statement returns a `None` object.
```python
def void_function():
pass # do nothing
a = void_function()
a == None # True
```
---
# Scientific programming
## Scientific tools presented in this course
* linear algebra libraries (usable from `C++`)
* `Boost`, `LAPACK`, `BLAS`, `MKL`, `GSL`, `Eigen`, **`Armadillo`** :+:
* scientific programming with Python
* **introduction to Python** :+:
* **`Numpy`**
* presenting results
* write beautiful math: ** .latex[LaTeX] ** :+:
* structure your documentation: **Markdown** :+:
* present your results: **remark.js** :+:
## Scientific techniques presented in this course
* numerical integration
* **Gaussian quadrature** .animated.infinite.flash[:arrow_left:]
---
# Gaussian-type quadratures
.hcenter.shadow.w20[]
## Main author
* Carl Friedrich Gauss (30/04/1777 - 23/02/1855)
## Quadrature rule
* allows to approximate the definite integral of a function
* usual form:
`$$\int_{-1}^1 f(x) dx \simeq \sum_{i=0}^{n-1}w_if(x_i)$$`
---
# Exact Gauss quadrature
## `\(n\)`-point gaussian quadrature rule
* allows to calculate **exactly** the integral of polynomials of degree `\(2n-1\)` or less.
`$$\textrm{If }\deg{(P(x)}) \le 2n-1,$$`
`$$\int_{-1}^1 P(x) dx = \sum_{i=0}^{n-1}w_iP(x_i).$$`
* if `\(f(x)\)` is well approximated by a polynomial function on the `\([-1, 1]\)` range,
the quadrature gives a good approximation of the definite integral.
---
# Generalization
## Weighted function
* If the approximated function can be written as
`$$f(x)=\omega(x)g(x)$$`
with `\(g(x)\)` a function well approximated by a polynomial and `\(\omega(x)\)` a known function (called **weighted function**), then
`$$\int_{-1}^1 f(x) dx = \int_{-1}^1 \omega(x)g(x) dx \simeq \sum_{i=0}^{n-1}w'_ig(x'_i)$$`
may give a good approximation of the definite integral.
## Other integration intervals
* The integration interval can also be generalized to other intervals, like `\([a,b]\)`, `\((a,b)\)` or `\((-\infty,b]\)`.
## General form
`$$\int_{a}^b \omega(x)g(x) dx \simeq \sum_{i=0}^{n-1}w^\omega_ig(x^\omega_i)$$`
---
# Nodes and weights
## Definitions
* node `\(x^\omega_i\)` is the `\(i\)`-th root of the specific associated polynomial of the quadrature rule `\(P^\omega_n(x)\)` of degree `\(n\)`:
`$$P^\omega_n(x^\omega_i)=0.$$`
* weight `\(w^\omega_i\)` is then defined as
`$$w^\omega_{i} \equiv \frac{a_{n}}{a_{n-1}}\frac{\int_{a}^{b}\omega(x)P^\omega_{n-1}(x)^{2}dx}{\frac{dP^\omega_{n}}{dx}(x^\omega_{i})P^\omega_{n-1}(x^\omega_{i})}$$`
where `\(a_k\)` is the coefficient of `\(x^k\)` in `\(P^\omega_k(x)\)`.
## Usage
* the `\(\{x^\omega_i\}\)` and `\(\{w^\omega_i\}\)` values are either
* calculated using a three-term recurrence relation and a specific algorithm (e.g. Golub-Welsh)
* numerically solved using an analytic software (e.g. [Maxima](http://maxima.sourceforge.net))
* copied from tabulated values (e.g. [http://vixra.org/pdf/1303.0013v1.pdf](http://vixra.org/pdf/1303.0013v1.pdf))
* retrieved from scientific libraries (e.g. `Boost` for C++ or `Numpy` for Python)
---
# Common weighted functions and intervals
`$$\int_{a}^b \omega(x)g(x) dx \simeq \sum_{i=0}^{n-1}w^\omega_ig(x^\omega_i)$$`
.hcenter[
| `\(a\)` | `\(b\)` | `\(\omega(x)\)` | Quadrature | Associated polynomial |
| :-----------: | :-----------: | :------------------------------------------------: | :-------------: | :-------------------: |
| `\(−1\)` | `\(1\)` | `\(1\)` | Gauss–Legendre | Legendre |
| `\(−1\)` | `\(1\)` | `\((1-x)^\alpha(1+x)^\beta,\, \alpha,\beta\gt-1\)` | Gauss-Jacobi | Jacobi |
| `\(−1\)` | `\(1\)` | `\(\frac{1}{\sqrt{1-x^2}}\)` | Chebyshev-Gauss | Chebyshev (1st type) |
| `\(−1\)` | `\(1\)` | `\(\sqrt{1-x^2}\)` | Chebyshev-Gauss | Chebyshev (2nd type) |
| `\(0\)` | `\(+\infty\)` | `\(e^{-x}\)` | Gauss–Laguerre | Laguerre |
| `\(0\)` | `\(+\infty\)` | `\(x^\alpha e^{-x}, \, \alpha\gt-1\)` | Gauss–Laguerre | Generalized Laguerre |
| `\(−\infty\)` | `\(+\infty\)` | `\(e^{-x^2}\)` | Gauss–Hermite | Hermite |
]
.hcenter[
:arrow_right: the approximation is **exact** if `\(g(x)\)` is a polynomial of degree `\(2n-1\)` or less.
]
---
# Maxima code - Gauss-Legendre nodes / weights
## .hcenter[`[gauss_legendre.max]`]
```maxima
/* ===== Gauss - Legendre ===== */
fpprec: 40$
linel: 100$
gauss_legendre_coeff(n) := block([p, q, v, w],
p: expand(legendre_p(n, x)),
q: expand(n/2*diff(p, x)*legendre_p(n-1, x)),
v: map(rhs, bfallroots(p)),
w: map(lambda([z], 1/subst([x = z], q)), v),
[map(bfloat, v), map(bfloat, w)])$
a: gauss_legendre_coeff(10)$
for i:1 thru length(a[1]) do
(
print(a[1][i],a[2][i])
)$
```
## .hcenter[Shell session]
```shell
$ maxima --very-quiet < gauss_legendre.max
-1.488743389816312108848260011297199846176b-1 2.955242247147528701738929946513383294211b-1
1.488743389816312108848260011297199846176b-1 2.955242247147528701738929946513383294211b-1
-4.333953941292471907992659431657841622000b-1 2.692667193099963550912269215694693528596b-1
4.333953941292471907992659431657841622000b-1 2.692667193099963550912269215694693528587b-1
6.794095682990244062343273651148735757696b-1 2.190863625159820439955349342281631924308b-1
-6.794095682990244062343273651148735757693b-1 2.190863625159820439955349342281631923213b-1
-8.650633666889845107320966884234930485275b-1 1.494513491505805931457763396576973319076b-1
8.650633666889845107320966884234930485265b-1 1.494513491505805931457763396576973322436b-1
-9.739065285171717200779640120844520534283b-1 6.667134430868813759356880989333179286787b-2
9.739065285171717200779640120844520534291b-1 6.667134430868813759356880989333179265385b-2
```
---
# Maxima code - Gauss-Laguerre nodes / weights
## .hcenter[`[gauss_laguerre.max]`]
```maxima
/* ===== Gauss - Laguerre ===== */
fpprec: 40$
linel: 100$
gauss_laguerre_coeff(n) := block([p, q, v, w],
p: expand(laguerre(n, x)),
q: x/((n+1)^2*laguerre(n+1, x)^2),
v: map(rhs, bfallroots(p)),
w: map(lambda([z], subst([x = z],q)), v),
[map(bfloat, v), map(bfloat, w)])$
a: gauss_laguerre_coeff(10)$
for i:1 thru length(a[1]) do
(
print(a[1][i],a[2][i])
)$
```
## .hcenter[Shell session]
```shell
$ maxima --very-quiet < gauss_laguerre.max
1.377934705404924308307725056527111881080b-1 3.084411157650201415474708346778606956288b-1
7.294545495031704981603731216760787810760b-1 4.011199291552735515157803099128195147967b-1
1.808342901740316048232920075750608833284b0 2.180682876118094215886485234746467267477b-1
3.401433697854899514482532221408390679280b0 6.208745609867774739290212931351795369709b-2
5.552496140063803632417558486868762857889b0 9.501516975181100553839072194171991223032b-3
8.330152746764496700238767197274522183064b0 7.530083885875387754559643536756639014829b-4
1.184378583790006556491853891914161398504b1 2.825923349599565567422563826850021277427b-5
1.627925783137810209953265393583362233619b1 4.249313984962686372586576659747123537011b-7
2.199658581198076195127709019559449397618b1 1.839564823979630780921535224355938249463b-9
2.992069701227389155990879334079919517988b1 9.911827219609008558377547283244736073046b-13
```
---
# Maxima code - Gauss-Hermite nodes / weights
## .hcenter[`[gauss_hermite.max]`]
```maxima
/* ===== Gauss - Hermite ===== */
fpprec: 40$
linel: 100$
gauss_hermite_coeff(n) := block([p, q, v, w],
p: expand(hermite(n, x)),
q: 2^(n+1)*n!*sqrt(%pi)/(hermite(n+1, x)^2),
v: map(rhs, bfallroots(p)),
w: map(lambda([z], subst([x = z],q)), v),
[map(bfloat, v), map(bfloat, w)])$
a: gauss_hermite_coeff(10)$
for i:1 thru length(a[1]) do
(
print(a[1][i],a[2][i])
)$
```
## .hcenter[Shell session]
```shell
$ maxima --very-quiet < gauss_hermite.max
3.429013272237046087891650255572580312083b-1 6.108626337353257987835649904334197132386b-1
-3.429013272237046087891650255572580312083b-1 6.108626337353257987835649904334197132386b-1
-1.036610829789513654177491916759209016298b0 2.401386110823146864165232950058613953699b-1
1.036610829789513654177491916759209016298b0 2.4013861108231468641652329500586139537b00-1
1.756683649299881773451401220106156763296b0 3.387439445548106313616473127758597369816b-2
-1.756683649299881773451401220106156763291b0 3.387439445548106313616473127758597369824b-2
-2.532731674232789796408960797754793480315b0 1.343645746781232692201565585845913869865b-3
3.436159118837737603326725494319121384841b0 7.640432855232620629159367859595222108274b-6
2.532731674232789796408960797754793480307b0 1.343645746781232692201565585845913869867b-3
-3.436159118837737603326725494319121384838b0 7.640432855232620629159367859595222108288b-6
```
---
# Python code - nodes / weights
## Gauss-Legendre quadrature
```python
import numpy
print(numpy.polynomial.legendre.leggauss(10))
# Output:
# (array([-0.97390653, -0.86506337, -0.67940957, -0.43339539, -0.14887434,
# 0.14887434, 0.43339539, 0.67940957, 0.86506337, 0.97390653]),
# array([ 0.06667134, 0.14945135, 0.21908636, 0.26926672, 0.29552422,
# 0.29552422, 0.26926672, 0.21908636, 0.14945135, 0.06667134]))
```
## Gauss-Laguerre quadrature
```python
import numpy
print(numpy.polynomial.laguerre.laggauss(10))
# Output:
# (array([ 0.13779347, 0.72945455, 1.80834290, 3.40143370, 5.55249614,
# 8.33015275, 11.84378584, 16.27925783, 21.99658581, 29.92069701]),
# array([ 3.08441116e-01, 4.01119929e-01, 2.18068288e-01, 6.20874561e-02, 9.50151698e-03,
# 7.53008389e-04, 2.82592335e-05, 4.24931398e-07, 1.83956482e-09, 9.91182722e-13]))
```
## Gauss-Hermite quadrature
```python
import numpy
print(numpy.polynomial.hermite.hermgauss(10))
# Output:
# (array([-3.43615912, -2.53273167, -1.75668365, -1.03661083, -0.34290133,
# 0.34290133, 1.03661083, 1.75668365, 2.53273167, 3.43615912]),
# array([ 7.64043286e-06, 1.34364575e-03, 3.38743945e-02, 2.40138611e-01, 6.10862634e-01,
# 6.10862634e-01, 2.40138611e-01, 3.38743945e-02, 1.34364575e-03, 7.64043286e-06]))
```
---
# Example of use
## Calculate the following integral:
`$$I\equiv \int_{r=0}^\infty \int_{\theta=0}^{2\pi} e^{-r^2} g(r, \theta) r\, dr\, d\theta $$`
----
We introduce the following substitutions:
`$$\begin{array}{rcl}
R &=& r^2\\
dR &=& 2r\,dr\\
T &=& \frac{\theta}{\pi} - 1\\
dT &=& \frac{1}{\pi}d\theta
\end{array}
$$`
One then has
`$$I = \frac{\pi}{2} \int_{R=0}^\infty \int_{T=-1}^1 e^{-R} g(\sqrt{R}, \pi(T+1))\, dR\, dT$$`
We use GLA and GLE quadrature rules and obtain
`$$I \simeq \frac{\pi}{2} \sum_i^n w^{\textrm{GLA}}_i \sum_j^{n'} w^{\textrm{GLE}}_j g(\sqrt{x_i}, \pi(x_j + 1)).$$`
---
# Example of use - 2D-Gaussian integral
If we set `\(g(r, \theta) = 1\)`, `\(I\)` becomes the famous 2D-Gaussian integral:
`$$I = \iint_\Omega e^{-r^2} r\, dr\, d\theta,$$`
and we can calculate it **exactly** (since `\(1\)` is a polynomial :v:) with
`$$I = \frac{\pi}{2} \sum_i^n w^{\textrm{GLA}}_i \sum_j^{n'} w^{\textrm{GLE}}.$$`
```python
#!/usr/bin/env python
import numpy
sum(numpy.polynomial.laguerre.laggauss(10)[1]) # Output: 1.0
sum(numpy.polynomial.legendre.leggauss(10)[1]) # Output: 2.0
```
`$$I = \frac{\pi}{2} \underbrace{\sum_i^n w^{\textrm{GLA}}_i}_{=1} \underbrace{\sum_j^{n'} w^{\textrm{GLE}}}_{=2} = \pi.$$`
---
# Special values
## Gauss-Legendre quadrature rule
`$$\forall n\ge 1,\, \int_{-1}^{1} 1\, dx = \sum_i^{n} w^{(n)}_i = w^{(1)}_0 = 2$$`
## Gauss-Laguerre quadrature rule
`$$\forall n\ge 1,\, \int_{0}^{\infty} e^{-x}\, dx = \sum_i^{n} w^{(n)}_i = w^{(1)}_0 = 1$$`
## Gauss-Hermite quadrature rule
`$$\forall n\ge 1,\, \int_{-\infty}^{\infty} e^{-x^2}\, dx = \sum_i^{n} w^{(n)}_i = w^{(1)}_0 = \sqrt{\pi}$$`
---
# Usage in quantum mechanics
## Too short introduction to quantum mechanics
* states are described by "vectors" noted `\(|a\rangle\)`
* operators act on states to give new states:
`$$\hat{X}|a\rangle = |d\rangle$$`
* scalar product between two states is defined as
`$$\langle a|.|c \rangle = \langle a|c \rangle = \int_\Omega a^*(\mathbf{r}) c(\mathbf{r}) \mathbf{dr}$$`
---
# Usage in quantum mechanics
## Basis definition
* if you define a basis of states `\(\{|b_i\rangle\}\)` such as
`$$\begin{array}{rcl}
|b_i\rangle: b_i(\mathbf{r}) &\equiv& A.e^{-B\mathbf{r}^2} P(\mathbf{r})\\
\langle b_i|b_j \rangle &=& \delta_{ij}
\end{array}
$$`
with `\(P(\mathbf{r})\)` a polynomial function, then you can express your states in this basis and have
`$$\begin{array}{rcl}
|a \rangle &=& \sum_i a_i |b_i\rangle\\
|c \rangle &=& \sum_i c_i |b_i\rangle\\
\langle a | \hat{X} | c \rangle &=& \sum_i \sum_j a_i c_i \langle b_i| \hat{X} | b_j\rangle
\end{array}
$$`
and, if `\(\hat{X}\)` is nice enough,
`$$\langle b_i| \hat{X} | b_j\rangle = A \int_\Omega e^{-C \mathbf{r}^2} P'(\mathbf{r}) \mathbf{dr}.$$`
:arrow_right: if you use a quadrature rule to approximate the last integral, you can have an **exact** result.
---
# Which basis states ?
## Widely used in nuclear physics, chemistry, etc...
* eigenvectors with different eigenvalues of **any** operator are orthonormal
* the HO is a good first approximation of **any** potential minimum :v:
* the HO states are of the form `\(A.e^{-B\mathbf{r}^2}.P(\mathbf{r})\)`
* the HO states have an **infinite support**, like physical states
* the HO **can be deformed** without loosing its nice properties
.hcenter[
:arrow_right: Use HO states as basis states
]
.vspace[]
## Other possible choices
* `\(\mathbf{r}\)`-bases
* Finite Elements
* Wavelets
* special non-orthogonal bases (e.g. unions of different HO solution sets)
* etc...
---
# Full-space integrations
## 1D-space (GHE)
`$$\int_{\Omega} e^{-x^2}g(x) dx \simeq \sum_{i=0}^{n-1} w_i g(x_i)$$`
## 2D-space - cartesian (GHE, GHE)
`$$\iint_{\Omega} e^{-x^2-y^2}g(x, y) dx\, dy \simeq \sum_{i=0}^{n-1}w_i\sum_{j=0}^{n'-1} w'_j g(x_i, x'_j)$$`
## 2D-space - polar (GLA, GLE), COV (`\(R = r^2,\, T = \frac{\theta}{\pi} - 1\)`)
`$$\iint_{\Omega} e^{-r^2}g(r, \theta) r\, dr\, d\theta \simeq \sum_{i=0}^{n-1}w_i\sum_{j=0}^{n'-1} w'_j G(x_i, x'_j)$$`
---
# Full-space integrations
## 3D-space - cartesian (GHE, GHE, GHE)
`$$\iiint_{\Omega} e^{-x^2-y^2-z^2}g(x, y, z) dx\, dy\, dz \simeq \sum_{i=0}^{n-1}w_i\sum_{j=0}^{n'-1}w'_j\sum_{k=0}^{n''-1} w''_k g(x_i, x'_j, x''_k)$$`
## 3D-space - cylindrical (GHE, GLA, GLE), COV (`\(R=r_\perp^2,\, T = \frac{\theta}{\pi} - 1\)`)
`$$\iiint_{\Omega} e^{-x^2-r_\perp^2}g(x, r_\perp, \theta) dx\, r_\perp\, dr_\perp\, d\theta \simeq \sum_{i=0}^{n-1}w_i\sum_{j=0}^{n'-1} w'_j \sum_{k=0}^{n''-1} w''_k G(x_i, x'_j, x''_k)$$`
## 3D-space - spherical (GLA, GLE, GLE), COV (...)
`$$\iiint_{\Omega} e^{-r^2}g(r, \theta, \phi) r^2\sin{\phi}\, dr\, d\theta\, d\phi \simeq \sum_{i=0}^{n-1}w_i\sum_{j=0}^{n'-1} w'_j \sum_{k=0}^{n''-1} w''_k G(x_i, x'_j, x''_k)$$`
.hcenter[
:arrow_right: Choose `\(n\)`, `\(n'\)` and `\(n''\)` depending on the geometry of your problem.
]
---
# Conclusions on the Gaussian quadrature
* if possible, place yourself in a case where the quadratures are **exact** (COV, combinations, etc...)
.hcenter.shadow.w80.animated.fadeInRight.wait2s[]
* there are many other quadrature rules in the litterature with different pros/cons, find the ones that suit your problem.
* the rectangle and trapezoidal rules can be seen as special (very simple) Gaussian quadrature rules.
---
# Scientific programming
## Scientific tools presented in this course
* linear algebra libraries (usable from `C++`)
* `Boost`, `LAPACK`, `BLAS`, `MKL`, `GSL`, `Eigen`, **`Armadillo`** :+:
* scientific programming with Python
* **introduction to Python** :+:
* **`Numpy`**
* presenting results
* write beautiful math: ** .latex[LaTeX] ** :+:
* structure your documentation: **Markdown** :+:
* write some slides: **remark.js** :+:
## Scientific techniques presented in this course
* numerical integration
* **Gaussian quadrature** :+: