From 63a9b7024ec0bdb4cd2afe73f83df01e752f0e0b Mon Sep 17 00:00:00 2001
From: Carl Philipp Klemm <philipp@uvos.xyz>
Date: Fri, 19 Jan 2024 13:53:29 +0100
Subject: [PATCH] improve documentation some more

---
 CMakeLists.txt                 |   4 +
 README.md                      |   2 -
 doc/CompiledExecution.pdf      | Bin 0 -> 12322 bytes
 doc/DirectExecution.pdf        | Bin 0 -> 12401 bytes
 doc/TorchExecution.pdf         | Bin 0 -> 12828 bytes
 doc/_r-c_r.pdf                 | Bin 0 -> 2170 bytes
 doc/libeisgenerator.doxygen.in |   4 +-
 doc/mainpage.md.in             |   9 +-
 doc/modelspage.md.in           |  20 ++--
 doc/r-c.pdf                    | Bin 0 -> 1839 bytes
 doc/r-rc.pdf                   | Bin 0 -> 2123 bytes
 doc/rc.pdf                     | Bin 0 -> 1994 bytes
 doc/readme.md.in               |   3 +
 eisgenerator/basicmath.h       | 103 ++++++++--------
 eisgenerator/eistype.h         | 209 +++++++++++++++++----------------
 eisgenerator/log.h             |  34 ++++--
 eisgenerator/model.h           | 149 ++++++++++++-----------
 eisgenerator/normalize.h       |  23 ++--
 eisgenerator/translators.h     |  46 ++++----
 19 files changed, 332 insertions(+), 274 deletions(-)
 create mode 100644 doc/CompiledExecution.pdf
 create mode 100644 doc/DirectExecution.pdf
 create mode 100644 doc/TorchExecution.pdf
 create mode 100644 doc/_r-c_r.pdf
 create mode 100644 doc/r-c.pdf
 create mode 100644 doc/r-rc.pdf
 create mode 100644 doc/rc.pdf
 create mode 100644 doc/readme.md.in

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6918ae0..2a5733c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -152,6 +152,10 @@ if (DOXYGEN_FOUND)
 	set(MODELS_OUT ${CMAKE_CURRENT_BINARY_DIR}/doc/modelspage.md)
 	configure_file(${MODELS_IN} ${MODELS_OUT} @ONLY)
 
+	set(README_IN ${CMAKE_CURRENT_SOURCE_DIR}/doc/readme.md.in)
+	set(README_OUT ${CMAKE_CURRENT_BINARY_DIR}/doc/readme.md)
+	configure_file(${README_IN} ${README_OUT} @ONLY)
+
 	message("Doxygen build started")
 
 	add_custom_target(doc
diff --git a/README.md b/README.md
index 15b89a0..b91313a 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,3 @@
-[comment]: \page README Readme
-
 # eisgenerator
 
 eisgenerator is a shared library (libeisgenerator.so) and CLI application that allows one to generate [EIS](https://de.wikipedia.org/wiki/Impedanzspektroskopie) spectra with high performance.
diff --git a/doc/CompiledExecution.pdf b/doc/CompiledExecution.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..46e54fdf097ec008b36106fda3a69fe0d495bdbb
GIT binary patch
literal 12322
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
S8keDwftd-Hs;aBM8y5h8mmxg>

literal 0
HcmV?d00001

diff --git a/doc/DirectExecution.pdf b/doc/DirectExecution.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..90cbcf04126a6e912de468b74f68a36a9e808465
GIT binary patch
literal 12401
zcmY!laB<T$)HCH$-THRjZ!QxB1BLvgEG`=x1%02?y!4U`1ycnBg&-~k1qFS#%$$<c
zA_aZ7oWzn;m(=9^lvFM|JFeoAqSVA(u8KLvAqEUivCayKIhhO7Gg9($mQ9#*I+Ua3
zS0@|S%cESsM4xf#{fudJ;9$6Mp7R1%YF-LdYieE!$Wo9^AX-5|!NdY24dNKXT?BT6
zYek8Ba7kiGs)CITNC4!nL<0qodz~E>3>EZ~6BP^<?Cd~t5K=$FKPf9Uxdg1H!d$@|
z<R6d<J3E*iAR&-lAXA{eHZ%Y!1DS%=+aPO0DhpB-V5Wmr2A3w4fCb(1i*mstPEPq1
z3egH6!^}-g6^tz{6=J~>L8-<0rA5i9#R`^Si;%-{YeZ~*h`B)R{{4sgcY9>#^xJN$
zT(U|_QBib~`6=fuoGq{1rm$T3_h;V6>-WyahAotLIrS*AzxLdjA3byRFMsamcdM<L
zv1Zcz-~F$ChDu7S+UM5?x*hMSkNeAcTl>uK+N$qzVT;$Pua8@;Uod&)*YE%GitfGi
ziM#p0Bz5(>DZS5581Z}ioprc2-^7P|`E6nE{WZ((nXEbR?^DsHl{{rXww%n)?o0~1
zmim^NUHHn=yI=ksKKF*@<J0z+cb_GB&z}9;Km2pIxOwz+v-;fFJ9pmfue}>pv$3}R
zXV$Nup9JO$&JZp1cC7Bt<eRUuXLsWPGnX2sZOk=EzJY3wjG0$#zqKj6I-=*BVbfOr
z0>#v|S0kr=kesiOwB}ie@&U`ks?l%fHZxYMif-<^p|RmypQwAyj?A9#T>lL(@;86?
zPIuZ<v2ly?T&_La$}b$@&e=Ih`hh3A`Hq>V))?k5mYPv3o1{3qv}>WI(!+VV@mEvM
zUi9=hwa%d8%vt8ihE}SpCa7ylt4M8@UdXdt!0NV-)X|{ki)_EeR$65lu8F(M@hPG-
zW#QXfmrNXbUE~6;hxj*NThV&#XW+&+fp=H`vJAg7FW|yS#SfxA4`*E4`uEr8uV=62
zKMOkQw);#Q=f78<r0)NFCUZBx_THNh)tm3XYnt(ge~OJlMp@WI&s%{^X<mMOcQ>3l
z{HQ5^8p9%siR`CMeAu_&7Ve(U&7nB;n)K_%MVy@`jSqHromgMAYkkZ6t2WbbOi7;q
z|L4Z<KDQKpo_rxt#NFt5hxfC=0<Tqy3w-<~mo=Y%TXpyIo4si=u4P&-F1^lHilzD6
zujRCSIlP>Gh1`l=XP^IGTRgj7n#FDJ@ds0j#oYN4oHtl0Wu7(QZ$4_N)0XjaNut${
zJL|67inknCq271V!S~e7vorl=y8hd9O<CNRC)t)~d8DzRY4uX}q=;qBnLF;zi};hH
zvm|Ft;RMqzIa?bEj_X=t_PMz?V*VCRtGMZ??yNL_d4~7bQ=I$)MJIG4jQJE?)=4V(
z-g5jjM}L(MUu;a(j2CkRx9)ji^Gk1mb3m2;)5dFO8=uB(wRZYGTfF!}bCY&r)bH8~
zvs(L9_eI^V7q?1&Fw)<)GomeW-#3$OF?aHg{V`msBoLy#e)9r3W7cxLNoG1O3%5j0
z^9wb~xp=_Ue{w9_78j#Q$Ig1PHhU&6yr^qi{Lx%VRv;#Nb?(zI@(gAvij_<@({+P|
z)*cJJ^usi*|5K~ev4+!*F%4{vnre)(r%$MAX@_3vzkBY`JK1F>O4Fhw#RMkRJrTa1
zbl|Q+v)csYSE)VkPpiJ<*jDp)L9p4wQzGpQ1*HNf=bx5Y#q~6MadfpUXX(ps_Z6Ob
zSsu>rzH<t0ZeTWD7;<y23$M$O9Y=p`VbJ}&xSV&3gHC3)dhXL}f%7kSEz0R$`aWdJ
zse-}?p(l;XMI9}tWw++X3f0Hl<=#0V(kG;<UZGN|C)!PahN0@QO^MG7-h5M5sS4s(
z*_ArsfazpkJGF-|I8|zN=f9uq(51ZA<HzD(mhOw}mo4F2yJWp|*^ZFu*O`|Vh2C8_
zIiRg;@e{|RCs#eR=8@PGcwgHpB~rxEfuZTn?Zv`7ddlQ^PZ}*^Ub@+~jOmYh$!(44
zYG;l=KKgS~OIm`6kdv@&i=^^3v!$~XOXLHyk8toaoY>q_))aO?fYGCDdO2f|wC;zA
zDw{aCmOXx_-_LpEMrzO;0W%g(bziBi7kC8Ar<>hNj*h=oGM{0i>5fI^<wvY;9{qIb
zZu5cFxBYw4G6gnp_2p`vVXN2{;Jn8~%5qAC;`JHd6MN67e4fq9bnuf{);o?F(K`MW
zHL4dM?X%WuEPnAo&BL!!s_cv2wDyN}8=7xK`!!d4S8@BvzdN|jb$w)2&g|;`zY+VM
zFU!4e9DdPPc`I|>>6+y0rxz8*PwPGV^y$`BON!04+bkY=_Gnk0h>+)BU-Pc-XYRjW
zPr9#2rn0AIW}G{IY1&@S3ijJoX_I3X2_6jcSnj79=O4P>z+0)x;`OH+(=Xd!pPD>#
zQqhX~yvUso6ZXyg$Hx0+#Ys>lgjx@R>mE>jq@bW+Xli5tQUT(EY6=hysrmG=RfXxr
zkh;*xS3%z|zbH2`M?pW>H?cSy#LY`p&<9nLdIpecQqKTX4Jv?vK7mTqEk6%bgM#WV
zP~DfNYoKeOU}&fSZ5!Cxfm#C4dfWnDWh>}IDoOvOtl$zzjR>n>jbK{!{S*vA#_GFe
z78RE$m_XSCni|0d54xUpJ!N8GvtWz`1rS;gf{X`+6(|VJK=L4tA(rNiA*j`XyL|)l
zEWBC=dB)Hg<Ws0^6?5iRR>lZlzg6!vW2S+6=h~7LXG@H<vL^bzZmVW>6%-Xs4ZP!6
zHX&5Z)%8GEhlZEy61EAUf&yC?HSJj6aBEkC)CN7#)q6{K*S5{8cwe1V{r>mAkH24k
zpXslbe(uQ`o9B`H@2eNh+&R-nZ+di9i_4mh{<+(2jIJFlP7SE}@kwIlofx&rCr_p?
zI&yl6{?ke4e1t@U<cnoGX8+gu^VvxCM9SXkuS(DT9|~Wt__O?pPO*~uY3;qLj;e>t
zv|4*6onBd(ZT9xZt-==p()#}M50;gEn;h<{dbEXw_4rp=voEg&Yr|E({{8KDUsF5T
zxk>3apHlNx?Ze@&u4{UFe&3J(|9|cO?BZJA-M{UfZ`y7uy=ih&>gN8ZTsx=NEc~<L
zPs^W)f2PiCj$9DAB63RP+{oF7!VFyu;~y^P2tJ}AB$_SiRy=d(A)A{udw*(ww%5pi
zWpdTec1hhrl_+=qMY1o}XNp_R>09*prS2EADF65c>o2qYlKk8B@@Rx%?M%lWUE|)!
z^K+8kY3oj%uU+{x<EhHin$!-X_?_W5m;DL6nS1fL(}o$D5Ay}nC#Fu!56mb$`Dooy
z=Wchge4Trn#d74s5`J&~_9mvxQ2LnL=8rjc(Z|9zmc9x6rgZyI*@pg`)8ANs;}=u5
zTr`1IswL(^iHUgYVwWw<PZ!p%U<qBgd4=p=xB68nT1&kaKMMUD(j3~i>fx%3t2kFx
zu2Klyku_H<c5Ccb_od-eS80Xzu6n(y?5g+Fz_o#|ub90u%qst?^R?z{Qt1S%sJTnx
zmfu@)E_nK?{uSp}<*#_ZYW}MF(EY*Erc>B5e`Wm2V#{{RRLfYFk(Oa&>TR-c*40_P
zvvg<0_%<%{2wu7JqRd5;j9Dh(CfiN;P5VvHo31yt-Fv1g^2@8MuQ$h)?VVHQ`^vPI
zVYjMA=G`s5Gh%0d$-QB<^mxp|uRbSldRwiRO)X6S`F{WEl#dECj;;0b?(4kV+P)@Y
z^MvyF$_Hn5-s(#K`RMZ9R!h;JUMf!yTD@~TwsPy&UGtrfnespTsKCDFz_}YgBkMOX
zhCb(A(CwmLm32qJ?Dw&h#9hrDJeOYc{al;pd2j86T}$uATz+Po&G&NGA9vZ~dn;@X
zrSZHoe)D9{bVDVd?~8XO_p?=HF^BzbKmIz*UC(ds;r`F}%5@@otaj{6%Wf{R*n3sC
zK6B~*qO9O>1C1ZY?O$d4clCZ{k6M>G|7`YF&Fc>(d#`->n<)BxYk8DZJ#%Vz|J^Xz
zN#BJ9!aheB*DZTHBbo7oXUmO=9<e@}k+LgdHyB(=J$dTSqpQ10StVI#zdGT)!Rq<3
z7=elxm#==>mHd+b+R{fmYOieBJMn1gtz+`5^0r)cJ9qw?qQ=|fO0MUbIv;;%H58ca
zkgRRZ{-<?w^v{#2R{NiwIDUSM!CT%94>-Em=kZnDU2k&3CHb>^g^Ybp(H$lK!YQwn
zd>)?PYQe{1BO>-^@#1&?{C5dOzY^+|(`Mu9kWO5X{jD~B{%+mu({^`#)zk|QUrVWb
z^l0hiBZ=!S=Shl}dUeYgXY>?UZvOY=TJ@>zJ#LDv2eaSZzAU{;SZivpqp@~u#hrQ$
zv*UUdhc@rKAaA#~Ufk}qa$1pB<hB|v`;>pNKUnPSZ+|?!_OW)%Cl{5ko#G!H7TaDE
z<9?8(!zt~{x=dv$%V*8kn~NtM@jP?v(4qY9pPx>}R(BuWRLgp_y5G^Oe;L1&>K>6N
zK`HfOTPLX7q#vshuQ2ctkEqss=>G59(nW{2K5BdwYs$a%!=27Mb0>=lPhH^M$M4Jg
z(AnuT*W)8EYNb!>P2A1XRK<5{=}nQa3l<E_e5?x$oDVOoS~%PB(z1Ch=c+0$Ea`kC
za$U46K6B%z4;#+qmju7F<E=Y;*h_+6Sn)^g1O0Q`k5*6Kx9;`v$J3A9lR3j)U38|s
zGNJ$N$C@{tvKy4=*;X7ncrDXv`?dw=(xaxB#!XPR|Ie_$^($lV^1dtcvv^j-Yv`Hk
z-<>WYJbi+I^y~%tH`iZ(FMhFxaalEohW7@Z?}9q3+c#QypI@qT%W>J<j)!a5_bi@x
zZ<gzwgQ}mkgnwT7vgOK`H~HmDJEx0@xyEh?S9^bJ+RWq6^X><3iMA>Gec_|<*HedV
zZx@wieZEwl=QB%0LVDq3HKV|*_G~YI&fRJKxh(JAv={|FE1{~KpR!BqoZa%Q=5Kp>
zdyDU*n)Vw7_m`f!>KVN)=gP8Y%ii89EckwI@2*Af_x)eD$YZ7CL8A<t)hCS{`WUZC
zRo#Ez_WQ2f-D&UNM>jU^tE{@ev1;SD4f}pJee3)$c|2<F(ko>TF3jA0Ycr>MnB1kS
zEIM~ypL*=JOL}|Z2C+Lco}Kz~Bxs{fqJPW&Yxb&2R*uspglE1xoNWHbnB8*1frx$P
zCVEo#i4PYUE^@p7c$NFUrajA|wO)jUynXzt`POcY{%d_F!fjZD@=F?yY!|#6XMSY)
z`ajw3H-gjCeRbqdP4>DuKSKTDwvsEE;U91D>is!$OMAPA#a?Dnp3I#)s%~n=p5<D1
z>~-~a&nTO-Qma2q(3D%+%k8<r{?)V_d9AYD?>K^HZkf!zdd6!%Q=N|&{hxk(@bKD=
zQm2D+UbQ|ddEUHw-JK<2GM3wavGJSv-#a{|TJyQ`ESLV3ciwG~ZS>xH<5KaW$DbbT
zWmhgO{2Fs=;g?&Jqc-fhaIf}{M^eU2zQ}`t%x?pwBX_;paOr<e&2C3-zw`GGgd4p0
z>F~xxt!~l&>3LUAosj5Pcq;KJ_|4InmAd*XSA@&i#+Up~f4h0dx76pQZ{?c(zdV(7
zXE{Gd_1sM1hgagQH=TI;!Y0<$q4LgD1=Vkh1pDS5waqL#7N6i9|6EX6{0=LhUG}c;
z#uwM|eq0~EbNaf{kNtWJ-(3B3>BE7S(nq>WPWIjX$!eoyx&5NA!Mh|j|Czm0BP^eO
z%D2j#t~^uW=DjnGEhmp`)mfBiu+3A{<jCT?o$lXV3Oa6AwZH8Xes<xsdF#=tkMmw|
z-mQ6aU}}-zsw%ss8zg(5ON1xbXR@}Q&HQn%Li?I>YIFQE@y{7YZt^944O%4kHREo}
z!((~3eyqIW%lk{<qf1p%7YF0ogoRUXa_yaco_TZR&kn_|7(K?+7Ij;}8Oa47+T$$t
zEEjLJysWg~;C+rMY1-NMt$xq%sFpl&Zo%=}y|tcam&7MUdmVmQ6t1z{v@lNR)TP54
zy&V5}o7>bbZJ1dwwRy?=n|V=>&L)ai82i8HJnZ5-L!oxnbmh#gQ$tLo%ndcpDeN^`
zpsF+R-X%4)+-CFao68F-e~CQY{pak;rHhvOwkO<NKJ#qV$wMxC|AeXMybihZYvS9M
z<TLWm^Z&*KPTLl?{`UMS;=(JA{(m>+myv(kJn0vERPv5F$%YteoK}c6Ju$z`JHAYN
zUerOwSsreUd_oDPX6&-_R3AB)d}p6GdEFruHnuyPkIGeCGv8Lx&|&dd`&hc~CjVp4
z)~uB-37&Cg&)euvKgD}X?K^F=lq%i*>-X;Y5Z>`F?7;aW*DBB4>ACPk;_j*?6P`HS
zGkx$x`QwtmJZzg~CqD?@u%}+W>h+SxF3YAKDZR#V;-JT6&dFlS&MH2=xcHm8U|qq1
z<q|m`lcai_?lqYd$gXyf$=jpl8*xnKyvI!g%i6co?7AgOqBreTtiQ6d;ZDWEum#*V
zJQ^M2xxaVHOioZ|?~ti<o5u7=Cw+<L1r}eCu!}$LyLC;{IL<G4w<m4p0?XLIsQXLa
z7UgZ6yIY|ybw*xk$)`sKxpy85EqhrITO90rV$qYHCs#sZgMwb{lCZn6v&}8iKZ3=~
zV)n1zV~-ci3t8VgMfdLdSclEw?E15oZhc$C+I?Hxdv@PztySMc-r22|@$K)87BuRd
zzh}e0LraepO~}7Jb!+PMjstnJ-Dz?*GPRxc^^eOXn0y{&U$1_Y@T>81Vs*~Kx6&3@
zjZM<-ALQM&Ws=X|OkJHMf$x7lMf}lplS^*r`&`4Ycfs{mc7NBix@n((@kUSjx!}qk
zE5Q%vUDEp&EORqfknT-g?91$aAwa`gH8)%9{Z^%%ruiLu6YuaGmGNnvJ4LqFURm{}
z@P{RA7az2hPil$sv0dEQe)NN6oR4C~k%#VgZ3X*&v<V*My;AciQ&01{t4v_^Z*I@p
ziBqrKj$Hh!sbSvcS><(Srg5{1wr|tsH!e17)sb2+dt||>7f%@lFM3aRnI>x)73p>@
zjpM|vSs_|N7P4$B6ay~`pG>s35$iu@cSGLo(ZwfUPaouTI~WwvH1`0fzTipjdiAnz
zUg`^56&}u&Ide}_L1Y&bYyQI(3mmSb3VBs<%C)*bI(kFgZDK3;3By@7C&X(`UX6I;
zI>*{T$w*^^(WZ4}-3>7jmXF+|yR9-+Zf;-v{6?R&(F4og*n4$<uDNg<tm}1cHU0YN
zqw;URZJCY^Q>T`iP7FP$^y=;<PRqHI-zjxuOno*nmu1r|X@f<wC+C;m-gM%fW%na3
zmM=_o*$Wlr{=4m6{ITq%aRl4`K<11^uZl&I%G6Zzy&v7R-D?vz?YOLcWzzqNTpL#u
zrH3vSlVsoK<rsdm;cX`?=P8FJ4Vg!zg5sMu>M!wd<~jC;UvSdBgpy?!1;REh`p<N-
zV{*_2`_lP_uM)N_X`Z-jVW!*R^NE3OqS4h4+fV#mVcP9_%q3iNqT4Z%56h1kPvYx0
zd-cKN@&%K{598*{?^ydmy;z;E@JkN+>HbuYD-usOJnM8iHF;aX4e3Aa$@Onc+4gj7
zxx7?CGh>(M<SPbJrd-FShq*FI9ekIv>gLYJZTufAIHWGbRAw;Qv~54ZFq=0ZPr=c4
z%iNeZMhb<==d!MBZpbJyuF;!$@OjY;-uaVL{#bg(&es-L@?XWCQCc*BU03Fwg{0Y~
zS!>ReE^0fi=5@<?O31wl1@qKhS#lHWO}@FF>6&ZkTDa@Ns$(i9=T7H$bTFT+<2<(7
zJvL~f@T8`wi%-*DDK&E!=!iU!c*SJAd#2L5vc=wv-}0I+w|D4CMgDzjw6*j|s)dBN
zOr{QV^4b#_GLnksi6;MA^$u;kBDhN;N%P3rrmSU~)wX}xaO0En*SGZ<6Zvu+E7`U4
zEqC%2sCCSo%;sm#Cad~#wOL+#!}_uv)6WaE-xQz!l1p&P#kk|r$(#;9K5?E%l!;Qv
zkmFjOaoVlK@548~{tsgIT!ynOixrq$m%63=(%Ajt^$Cm4Nky^}Pkv0fGKHn~l&3`f
z9FefSGI{$059H1{y4TUpbnU~pHXGEgh3F`~?QXq3_uDJJ+VC0S5ldX8Z#}s*@ADkP
zqrP5>0tq@fvWweQnwMPs?zZuH>z%_>HNLI;9D6eS{_m5?1@D~fxmbQKnAgVsX{{}<
z%%)dOCMOPLE^+eMCVMa?bk0Ke<?4-k?Q4%O_;1Ks<6zHSG3(^#(>HG&FL<_*>7;a?
z*Gh9yUY7&2U-aDHQFyPeW63<m4H8G=@66oU?{08zNv244!`-<XZY%tMGx25U&HR`B
zl9Cs-3k6F1*R?Acy<_k8OltH0;MUSyz{X;^aIvqid!Na~GrQ-o%ros>#ZsRoT4Yr9
z*x{t~-D;(m^Au#Nt~Bu2_Q<_lc(h@`{?PvT{`>6qw?vFg#eEfp%l(V?T#x>L<Edd&
zV7@!2)S}te%T%_#;yZJBadgp%-AgC%EzmE#c2xiDW62a7gLo?kn=gG&oF;gx6lS0M
zRU~9w8hdDw&t0!&rknp=QPy1{arUo3?5TyH^7B6h^uE(h(Ej%9-Rvdr-5+EKO^Q4l
zEh)UorY2`mea)RUp^VnDWoJM3%#~4{+&jT{>e<OVPsgNePT7;wnA3G8`k89+l(Q3e
zo^nc&ifnq5eY4<Z%}s`zF*lzt``5YijMFvmH09YIbyl(4e5PsN*0$EM*4wSITkm(|
zHRaz5?{%L)iK?{Uxwb~JZdqpEYyFI8XT;aA@~$gPG=EurKWF}p)XJyNat;<{Oi8eO
z9`2Sb5_9AJ{qK2irS4|l<lT0%>FH~uFyr+0gtL>X?I%n<zv<q=v;UvGE<eq(@<a{q
z%(P3a84Z7Bd>Un^F!xqZ_PR1VM5$Uz?Xisw_iIh3xcv%C9~3|0Tc5FM(Hz?kH>P=r
zlvf}0Y22{D<xrE9k50y^plN&5^&BoZJh^`8u6mH3XW+r&7E8M~0ZKkG$7}YQtZrt|
zw7<4VYPEN3d`XIX&=>2UE8mF)h5quq7_*4MGOTmi+%WDZ_hy%WI`(c`o@?^?Cgz;k
zS98KHzft`&@vCU1;N!!$Hq5f;IBId#c7n~nX$8|(u=?3=%dzZM-ns5FlaC~4T7-yh
zyWdBi*`f;f(skadUz(;n!N%CBLwjNu*MZ{l2*$q?-nz-(E|^xo?yt|GJN&ncii?W2
z=ii?;eY@{ct6kOZ=f2IoU9>I#e0Jc<)N)_7IeO9B+EcHdsGDMa!u{0er$;|6|5QKw
z<_yajy~f<e-iD_QPMiF`_onM+?&j%f`Dd#{nnkvC33la+yzAoaaynY)y7bY^N3D<I
zpPh&?c%Q%Tmd#b0+j~y^nNYd-XK=CdSIwirr&oGtP5;&TYQemK^DD!zWbYDx>z95Z
zvV?E0|NSNMm(RZp_pwhicznRZc%zSE@L`D=*U#9`tk=v`4XRu8WXhtVB}F}#TwgAZ
zS;Q0Srg>e{Tzh}8n1=V1si#(-vObmf)P737uH9yd6vHD)ds<f?_2KsC&hKs&>lAw_
zc2ulg*Dt~(dd}vItuMAQT<Zzl9Jc1bt<A|dSHAHn6O=xkmtem6_RZKga%J+n=dVqe
zeWUwL?Y8dPll#(Dzr~;6Ss7?=!sP3`PeVj?vB(z5w~p)=6ib*)7oL7$wX4-CK)tH(
zpF@OdaArvSDz;T@t7SqKhdd5Fr^SEOX6pQ`RxKCNg<ZjG18Y~G3VRzUx_VVed#HLy
zdg%1fwX5VqzlZdP=!fQq)UW!tHf)uBX!g}>uMWOaeD&~E{*}vD=gGu*N-S0OJL2i!
zB-u2tY>IiT(EIIkRi5%>CfbS}WNd$RY{uaY<`RPa^DoVx;N@;p!jL#8@4>fgE;gLE
zRz2Nt_QSsluCm%B+s@iw^BQ8mPt4!AcSq@?|GPbuBaYrZy4t59Io$t<JI9>)2mdwa
zwTFtldGp{y)GV7{f~`-E%Q@FAU$nkqNpo+^vt#+2%|1@d<~rrF<4}oz_Mtm2{XZHM
z=4$@*H#eP^vs8!A&4usf0p%YDA0JMy?!2td9+@209a_qq=X3Gw-Vec7*4y~}{i|9b
z+Fe$1tLe&wtrJh(6x{5j_Mzf|KtPlAnK~YxFZ)aMEH`=S^lNtf$lE70^TY#{X-bw~
zm#oZGc>iwN8P3_C8qD}Ey*y|2fBjM2cULCO_5Q3};xP5X!QYop8^z}`h9<rJ;p}zz
z;;UnNx?koM2=iZfxSZwr<)HZD6O9$ic53M^bkT{OE5FOfIw`ZEm+x)*{k)lFg$)hs
zbmL<T=N_MS*s%LJzy7R?4|Mg`<#$=0j?Z3^VXNn6xFf%z|Lc?kU8gg51#WqJu8e=d
z&u_1n9_Q<Hm*S3EFnwCWCP_7)Yv&W*xEtKO@IT2&ys7Embk^t!-Lv|<*H}YUuFt*v
z?`&)CKTDQ552c-2n_Fd?wAzePuZ4)le(U?y>S&w2HbKmAj%n}KW6LYne3|mA>)7HG
z0SeC9QfcWM@-qr1#T}}6?9HXiRrGl8^f&hVynI%8t-p0?jZ0B*;omNs@)-@k&K1iV
z*8ZHBZPh86yCu<W%bDutC6~h<XoybSlbyRo-a+8D!!PZ{wedz0PR)Bac2qg;pVs#0
zvPDb7%=PCCKW`R39R5jrB4?7U|BeIyk6zx-Yx?m^2gkMc)|bf<Ce3^O?$>v!Ol#I%
z_HJfVKv_(Gy0dMorj%LYf%`LWNJ{EAaX)C+5Ad*`;_COt+4_}K?sVN6pEnOy%PUSe
z$zFD)^p@F#0ymoj8T~)|*B)H7Auz<jE69sue_8CezLY|x$zc&Yc6O{^abxTB8$Z`y
zdteou9q>wlO+!xE@{(Km<It?0D>(+cj3>=5nd#(`P%h4RFkyqEZKlDT*;2csD@2Um
z_2}B)v^}KmVIyw0yhg-6Gpxp8!wsb^pWnJKt~pwfcDl<{I_C1+OSQqy!Bga-Ie*UA
zR1lWUw|!<G{9T;C{!Lw-K;uKV`#j&2bbksN|J&YZ@J`jVxh^$J;l<O#CzF_;Y;`<V
zpJ`?D{6q1IM2=AN|MnrZ%Q~_@>|L2>(zB^4|JDcd35@5ytmQVWD}D5^we{V%s5g!s
zySMULUzYmer?pA&frCvqUwGMv?|ti{9G<vcdQ)-m#BK-X-soPftVt#x&E6$E*tJCM
z($7sSAMHd%HnVu<);R559vHiD-=?_g>$?+|G|!*!yzHG+?8LeAXRp`37dtQh?EF<7
zk=r!PQkQg0ioD@`>bbnF4SOcr<Fken{xz!qIrB?ob7`Je$OpBjUeAjBzMf>ib-jf{
zY}pal<Em}$!p&?C^G^u2FeeC=DIU;aQai+Q=o!<=cPI8(oSx(2ZlB{j>7L1*=}RuI
ztYCV_-h6;HW}$pU^X3%?C$`Ny|K&*Zld>Zh%P*>axw<OC{{97y^EX$YTAwGDe$n~-
z&wVw8PtP2_TzIvvx>T+9yWthL%|)6!W*=bYcv`Sx%dLbzOxq4tGuQb$%`mJnNG>R5
z`#r6WWub_OG{?mSord=U_g`KiduJPGhO^LqJ1cX2H<v<gj<d?oT;9&^V2O|YyZ3F6
z^c20c4@P_XXB|E;$5`fB#)AZ<r7vT@NzAg=m0oHh9DBomKIgpfho>Ivw<lW4wa3;U
zD|+!iIJnZgIb&zpD_J&m@6$We#g9F{$MW{EO4av=@4x>ID0-VPKbw7Z|NM*hX5O{A
zl=kot<LuJ#mv5MFe|vW({N4TFz=8?+Yj~r@<_U;yh?*mv_uP9$=izpaEi-BxZ%Lod
zH|x^l*|dlAYeC~|$vw*UZarEN(R<>n7cKl16&<^zdf_|8x%X!5vR~$OQ{chQdZ~WV
z$7%f^*G5#OP5p7P^X~tmNBegtd^{u=To4q@TA};(@du@2>c)n>AJ*~)b|&sgzrZ`8
z@#w>Nc^e`2%j<-h_aEvJ<Iny5>h4o#)!b66rY(Q1mMpAdacSIbyy9(V&ZWLds{O62
ze{-|k-(s^(@A1E5d3U!TH|j3W-hY4M_Uhx?bfrI)tgPH^{`B)x*Q27LtG}`9bMw!i
zt+a0D#!Rg;)t<^kwdpe?L<N_3bMnS)Z<@dLQ^Mz+w~8*`_x#yvDY|<qf1khDowu%A
z49v_bCYBv?UGE+{{ao3cp0$oo*}t2aWHgq&IWjH6I!EH#t4Z-PN$=)lX6?VdrC`(N
z8hiEF7dMo@oZQs&#7HppZBljly;R-%-pi9%kA1r8$|x#-UnNUTr=uWJ$1d@Le$yYv
z?~-DT*_#}0<aROU3M^4zY5ekebN4YhwRc5(YWyz>=FUFfnXgu<U-tR_=3f<4`0j2H
z^w6=Zcl3(ie4x=bEO@TZ{&V$Zlk{`?O<jU_-rW72<Av|*r{ep4_ggs}NuIc`-SC9x
zw_L@W-w)oODRL(6fWq7@-HxV*Vyb>FyAY9Ir{{Tf?b@{&ukY(_TQzHT<s!F#8@MO!
z7U5sJ%kSa@p6eQao(m>w7CO|-Y%2HTd8G3;`O>xO&C}w=l!8}(XNsM)+q#~Azjb}_
ztGbChW+)eK<X1U6b!YptqaO|?dMaLg^vm?+%8lBun|{q%t)*>sNPPOz<MARFXWp8?
zy3cW8oSkF)tXWz7a|I`gKDpqj!=m(~lQG-by5?i>8%q-*ww`0m%Y2+a?N{mLi?{LZ
z-ZUvvr96FNA>-WM(9_F$&j$3}JRNh&CamU9(%Y4L#kc)kHAO>ZXTY&N;<kc($r4{S
zN^W_PY@8wT;{a2EQak^TNvjPx`r?mX{qo|$ml+NhYa=-xZQ~AKvyFS!bEY|$7WX(i
zJ?t_GuD4d|b*;PAu;@i{c1h;ZrL((!)?U56{k^#Kj4wx8&aQ~suCAh$uGPOf{a~S#
zVA}mG9wWA`mrkrU+qCq@?>BEnRldGZ-7bCLz8P=KyAy)73l)PUZs#>=r+0ocy6IY)
zwDtd^nsmAKN{Xp@i?*3v5uJ2i*&<osmw)X4^Y(Lg%sn?p@X_Pxt4h-D<>yyU;hg5>
z;rMBCf8yih)+c(I7AgOp-?~=6c4?r0%g*5cdb6(BSnd+McTGC=d05AadHc(S3OD<H
ze9ixF-3|HQyO}KSG8K6)-rVkgU+BJ(RMj^Arzag4k33-NSo+LpdacHl)R4JJ^1k`S
zLg};T+dX>UeU5Dot8|f5<bDp0{#wT9i5pjN+omklTJdzrf|nX=irv#J<3l3@;&h(9
zKYPyZ$_kg5&`ci}m!6lwRSPz)*)r+Lj1@a}ya-h-eEL*X_36_>)j%bsrLLQP91w1n
z(y!~NaLks8vb|RlV|}AAeEM!X_1fxLpOWKWoEOP>_-||Gr}?up&PF<Z4j0`fBXv?~
zO~R>-(^f4%?daXuWYHQtX|C+HXB)TP)s~p5vgjD^8m2jyBQqNrr8^G^{f#^~^V^}_
zE4WP>(~C+jzv^&UEZ$YNT70fa)v-esEy{{PTsf-0q7^)SA|iJ9zmZ9`?d@^AEXjMb
zLg3LJ<ww_9K3vqaRGp`!^gU^Pi+Nk9wrZ!__U5m9^99d!tXbr#rXbIBBtfk)R^v5a
z&tB)GE{j&Z^vbe7Rk=ZKuYU1}sHJSw@Yl#zc)?w2y>9|XanJrK*;)NEYHg<bq7?Qn
z3cMEDxlc=d$Fq~x1%E9!UftixvU{avl`G#1v6A~i9{Pg54Q2<Er8ZWzo_r|4e>L3j
zV@!eh*Ni7GZ0fhw9krR5vNrdk4(A*34;&8*m)Z9J_-k}%+e#)LwG}!>Mg}XiHmzH>
ziR<O&h|C2iA1*n2<grQB$;(e(BwXj){UzhL{PWok^H#dB^Tpgzez$j@tZQ=hx;ypq
zxxXeq>SKKPl-Gc%_QP`1I}+yGFZ$)?&E?Nmu*}(eKkHT7f;Gjx;i_#puj?5OWtUWd
zX856V^3X*H;CX$}q`!iKf`x&(F-Qf7YiNeFIsvvA0ki-R_Zk4?wRy3V&gV57@Em(z
z*(I~v+0|nq52vE<-PXhZGIIDGgqJ%@DRO-|aQl4UYQI~If4V={9<w;<cenWY@zAvQ
zg=V&EF7@7Xi+Gl8qHw-Ia_@<)TNX#=ul{0oS-_?3SzUD446FBP7fp<QA2^%ZJNu69
z&7VB{PF^$jx^fqO5#RaS>g$|W>lObTV5ytxwPo#=2OI937Km%-Oqq7(_qj*^cH~uW
z`KxKSogrv>={en*HxCK1F&BOi7w8RIn=>bywc>ZafA+RHbAQS$$~eXBHT96ftmK&z
z%^6yAC77ROpSym<ve++Y2Jfdtj~>Ro{cmbjc(2<B{q1@kzOwFMjDonCA=?$}Yt~8E
zWITg|W!Dz{nwGX#tv0q`-j0wz`du@A>#zLZRlQ<Gd(%#jzZ>M3d0&|cN=eRr`&Z|T
zshdq(3FD<dnV%N7|CZ$}RtT@EW85}n;agCIphX!d8bEQRprBxEYy?sO;u&JDCjqTS
zaY-#sF3Kz@$uEMe7|G8o@k`82RnQNMigJx`*7nQHO)4!8PRuLT4N6Tf%}GS4b4$$4
z%&An+fGAM_snLWOl9QNT3|oSdpH~81zNu?uXrQ2LWNE2jXkculU}#`&3SGwOS(2EO
zne3RCo|CFz05-z0I5{=1M8Vw163hj;62#XvGKZ{kaZW7oNX<;oC;=M-Ruf#3nj5BI
z0nrcQc)&Oyf4XJnq#7%Lm#zeXmY%@UH)!n*D0o1NRzskxPV-722Ex{%g2W-#IwcmT
zf=nYAJfKB5&KZeC3dTlYvwRYZOTc_X6AQ2a$P|#TAYrcnjvYweam`E4Psz+nSI`g7
z%yY~u&V&ho^@V4qlw=e`7sG-U#A0G&W6)|}OmUEikvS+CfLI7@ZUkE9gWyA07En{n
z%s}Z0qz1x*$YPSFrl2Ch)WARi!~$W68Y8IbFd8HS!UhT;cY@S|+yoIZPyq2E`bZ-|
zW`QtxS+IhBNPcKuCTL}~0=S?;iE&WipvJgA#=0saP_lqThaW5<gQ8Ty$QT?8gw}9}
zPCT7;*g(Mb`@gQ6Q>;W%Jj3Mp)VeJMoHSdO>|Vybki&gTgxe(V&);P&H{M=!Rp#u)
zGp;-thqz{3YGGb}xg}VjNi~)8=IgCjC%jEvTg$|7bF*c21v8%r--mmPPnG#HOj{GS
zcVqdtJDP75LN8fx_iSKYI3dm{<FC=_swnH5aXp`o?5Z-_Y5RB!kJ#4O&kv^_+1T@>
z<#49S*}qC&%lA*)c-D=L_hs5iP4Ouko1R*VKkD4%?xlV>Yk%ScM)AIXaaOY1`zxzH
zEIRMD?yY&-l8R?e0)c1Jw>0dD5IFYyXU>_sEG4!bf%mL#Zw;8XvEyrQf<JqS%d3>f
zw=E)K+4nR*u(AyiEzA8fJ@D6tSoaP_CHstg>*ZV8YvxqC1hz)=^~?X%&sJ^zv*oL;
zR^208O|!oYLd8uUpppu;C<8|WD6T+7nV}&_0f+}qQ6L5)(?$fPrh#JyS{GSB$_;Gs
z1YV1lS(OTl%W#EgLj@xRBXH8u56aIkQ7{4}K1lR?=B4E;7=qRef)f$ceHC+(6B2&>
zpWoRyy^+zyz|cr1B_Sc@0lT2Bf+3$m_e4>Tf))nOZ>9=KToW$b;}qJ>r&1E$9FgDH
za?DrYqo7B|*M^Rx0?v|-EXIrLECPJ&`x_Y<SUY%UfV>E`16o2Amn0UIR1~GAaTyvJ
Oniz4Zs=E5SaRC5sZaUBa

literal 0
HcmV?d00001

diff --git a/doc/TorchExecution.pdf b/doc/TorchExecution.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..2363cdd4d58f4e80cc4619e17fb73c3c2f5340db
GIT binary patch
literal 12828
zcmY!laB<T$)HCH$-THRjZ!QxB1BLvgEG`=x1%02?y!4U`1ycnBg&-~k1qFS#%$$<c
zA_aZ7oWzn;m(=9^lvFM|JFeoAqSVA(u8KLvAqEUivCayK8JR26Gt&~Y5|&Jub2^lx
z<yR*g*UO_^zeJyL>HUmpbl_lkxPXg^D>W|#sy8(+1!OD8DiE!ppkQJNk_K^%;Z6cO
z!nLBrJ-8&XBvrx21|$G-SfYUf$idEz3Wf^$$%zVv3U+oNIS8pA;h&V1np^@_Q(>-P
z4)PF4g`FMD4v-MYE|4iuZyOqblz~ja>Ti&>A(aKG3NX{bDuYXtO2C3{`9-;45htho
z3WaC|kYSb<#tMd(MhdZDiJ;Wt{L-T2)M5ooutmrLxi-Q(U&K;i-|z4r7R@Go_w~+C
zyxJuy#6E53+oA+(X(5w9Cxu7v--p+grnh}*V)5vSd8>8(@oMq;M~@!YkE;8l)bnIN
zzx>mq?M2rn{r~sVD{HFJzlxu{Tdwc;?)m4dT!^lI>-795=^H*?{q?>?yNCN!wesA+
zn^Be8?1~T7A7@P699Okk!zwc;L~rsJ&!Y)XS(?J^R27?#{#EF0RM^lSu|y&_L`B~@
zOilXEdAG_v!iCytGdFp8x-H-H(MT=K@yp{QMkSyAzWF=pa%JixooiOE0ju{*P3hk3
zw^N|~l;6YUHy3xCp1oGKV&05f6M54jTe*)tdoasEII?x+UbfRyy_aQAD&X+-UcZQU
zM})4xC5=z}qQm1?ZrgtN%AX+rv&mCe{@&an@~7f+dF^`F#jh_dHZ{pTn3MJ;pj_C0
zgTcwy#T9#M6z`kuV64;UKNMj3=EG~j6%J-@(`GF0Gdp>B?T#I{UdlSZD^UG+YtPQz
zf68B*AAkG%aQ4EfPpkRfd@AT%UmyKiZkt_x*^hGL-10`xeKG(38a%FJ_{Vc0Kv-^;
z=)31qk8(C~6}H$*FJI(sY_`cyYvzRs$||V}IS;xzLY^hJ%c=$$Y)_md;JS7t^E9V~
z?bn5mcRf&8{`m)=toWI0QzFi85_Dm{`|Gw;*$V|%=F(FW-%8C|-gAflimvyRuGF*d
z3g0ZuWx3d7e?!`2))&4x|0)iLhOcc}m#N2gZg!&R#=9@Lo;{n~_xat%ZyT$EO^!W#
zqqwzg(Y~9HuZX-VeDiCYLHEQBqAX{xEf+|fF~2E|_i4(9E#{nYv5i0F&A*H9w~b>u
zBF|M(zT)7N;1ZJ!|6ctIWO}&eVb71khT9DNN1BY>JGIM<_WBt;wBWe9+Wn=Bru5sF
zk!NJCKM%SdlfWV2QaEu1-%WS<Kc6f2-LJnZwR@-b&ziq^RXcY6|0R5_ZHkEEGG&wI
z2@}*kt~?R=#8mChck<EH$DjI6RJi#vJZN%OV?Vs#Xv!alu!R}cCIYiV6#gvwr*`~%
zude(ewg;QPSZd^EO-c(Xvf=yQQRn9CzE6!|L3~5S`t-66^F+ma%p0Z@)yG*h+<J9o
zYw^tFl(et151l{VwVD3mAm8KT7q6VN<mH+mxmNPciGcTi1o}-D9x+{J&%aprmfK~%
zRR79ZQ}th3@ZOF|eAzZzsQ1x~3AZy})d}}r*c%nuetGr-xyhfhxFf<>vWA?o`rcta
z+e&WMQSLnfe5yOoD{Q%SIKWb7Ve{^-Z|rh5S8`=mUJW>RVcUo3Yl?pkZ4=W>V(=`k
zbL$iJ`gG!<-;2n344$tazx?TWZN6u0v2ROuz&DQ6a@F_KZ|=Kazw76&`-kss*|~e~
ze#<_q?|T+@cQ!M3d}4d*lN;+}ajM)~)OU-+4wgkqGoB?`<Zb8Xn|rW5>5Jy+tKFid
zRc~cp?daI%@}<Y>&(!5x6>BCg`dYPrW5A1^%uwaF;zc&uB3rdzey;8PvHEhF*u6rd
zb>F4Ad(X`XGkxVDEu}gy{;o0CM|a`BI=g$63LjpqOI~<EQds0y<C;PV;YE%UPsPL=
z|IksB%uYX5xGW+_!*0QXt%^tLmUYZDxv_4)a*b~F8buMKDXjBWZ4k?t+py@r=lt8d
zPrIw|=6<WbB7RoB>|D;iT;6A0?WgCjl;5yvji7Vne8XzX%?6nPZR$e(ks{OPNi1nq
zKi9gxQmNug+Z3O!)$=ND96NjW%lVIor+2@cSYMaM>2Uw?6oVIsV|X{P@pw6;Z!=21
z_N2A*G;5W!Uxwq29v`P*r^m-QBq#2eCC#5HTEWj9^4;c>MfFTu$MOz_n%I}glDRu|
zGBY-_?d7P9zg1Gm-PV?K;q-+^uXg50e~@0*=BDr=@Mql5&Um-^bK(~)scaN>=5%_s
z^iA6&n|N{KcG)MzkpjDyw%lA45hbfA*79m~=CTB}BRZxk52o|V<tNN9Ewx<{^?|K(
z=j~nV(r;?)+|T2^p<&sSQzrLwN~_A8og+U_mT1W=OWl7d_Us#50p}kap|x>e68QeQ
z?P%we<v)9jar&#KG7)a|*n0Mq)!EFct}L4cbmE#m1exrwu&uLGv=LLu&AEEDc=`7W
z?T*(p)kALumzunuRrKm>llz{72Jb%fwB;RK`e07}-qMVDXQx$7T%CR2xawoN+=uj^
ztZQAn&l$Ya`C|1v`s(U8E4M_nTOIrm)Ai{&!vPKlCgyq3bC-3ocAIK_4EkB3!>~y5
z&5X$6q{7AJJwdNczWq7yzqEOWM7Z@CP3e+4?SIVWSsbFEY7(`k2G@?D8dE_*!O+aY
z2&4kU1=VFB8d5jwW2>ywiy^hOldpolUw%<;Vvd4-uy0~<Hi(;-s-O?5#`O#!6}g@P
zsG?Q?1APM3yjy-AsE!BKuAtgEP1iuzK*7*Z0or`Avja6&pe+pxc%wo=A5x9`CuIef
zK<aE*3&04bRo_p+5M->rTV_#liGm4~O`tUtZ1AA#S=Uo01~v=ESWp0=1tG|IP*{P3
z5F`)c7-DIG8G_nHxSL=g&%zrXAkP>&gM13LtzypH%E}1g>%Z#T42%=~grYN7m|s4*
zVudTq*1R3z0V08dfh<R5Q}{QXTC{>ALQv3LOUblhO;^K;Qs%<@TpDY+S1@)*ExZ-I
z{dW0_&hK^pZ}#4QT3J{Bcb?+mnZ}mJ?<=pLf6lAAdCP=Ak<_<>i{eGajq6igdKO=Q
zwP44GsTYk-1*uIAd}18=DD{%~lqH)dxa_=gT!{TqoBikid;GYKBHy2{p7?qBhtA49
z4}y!PSx&s1es-^_qvm1fDMgaLfnQomqswYdOMVns=j+cu=-g)E6DvGZLRLsb=63m!
z59{5&#!kKQ{eJl`zi3%uA(4ya0+MTDW%sEC?YC0;R=@A>|Ly<QpZ#k3{#`w9D*uUV
zsm3X<Q~ob{GR1uB3@gXE3+Dx_*OAd>(sj~R(#_JD_4M1P#80e6_LVbiqUI^Y>zhZO
z(s??~bDFeneB?hz{Uzrwul<tzOFSy6<cz|xi9fpv6A#VwQ0u#S>`emC8PR9#$4=O!
z@46YchWGY#*(0|$8{g=CWBG02p{S2Lo5FiSeFAj?S~QA8*+tHF$&1E@)vjS#eKYJ|
z*v7D#VLQWqhFxFtF4}fmRnpgEuWZwgetpQY&i?s<vyZ10CB}$|AAee;8p9fXc<zIB
zMZGc7*H7+!a<8zyKq9ciEi6Nz$kF(sjYyx+1-&WFe2bJq8ub>1eUbXRa*C#?*Vakl
z--7wV_(J<a`a=DJ&V{pS9-b;aCG*tWQ-8ghH$_CQTNC_mK~CttkXa#FQ~gqxOD!)7
zKO3kUpc~4%a#2X<D&AGPt7JkqzS{9>(W`B*_Pv_<D*USTR8Qa46L<CRT3@xHs;6pF
z)vT&%x4ifI$gYZ8eQ(XZW%t&e3l?8-`fBK_$FDBGs`|=X+Wl+euHe5;f1~bRKD}sq
z==!+5cCSsBOb=eKxi^jP!8TUaycruMi(d=x=e)h(!whwkSdCp3zR&lrR{5s%|L*pu
zGIA`&CfPxg7bTZIR9t;c_u1WW`F#Z|cfF}x_ai61t}JpLlc(hd$Ilvn@BE6odtOmk
zitTg71m$VT>2Ln*vA@x{>93gq>mp%e+cJsirPZqpE(f}}y)2c!dPy}fwrHjIt>r84
z@2bBW7~B4TM(_^te)pTbhil#D%>8c^)iSfLB>YULgMRLTsQ(`<?%wKHsyXjZODnrS
zTlYkFv#?zIwGt<D%1_6}y<0yc?!F*T(Z0{_&R-)puKQN-SoiJcpT1>Ft!!5J$yI8s
zd9&$TT=L!g1sPu?H^sKEsAD>$CAV7r+&1}gBL=&R-MO4!u0C0`wegl~w{z^YwdZtW
zR^Og5ectw^ZF^W&Z^}Q<+}Lg>+q?euwEFyL9X|_?^A-Yu5sTOU-uI}ixb#Sqj%?GT
zI+;n|btaie)uhU}95=p^)}j1w_U7o9H$|=Xw{@I*9yQ}5n}r0|C-=BMw!7<jZn!3%
zR<B^PPs(~Dq+i(cTFB?|`K=aWEH*M?fA_9^_RxQqQuQyXW~-;ntV<+QQ&#cSh3~F*
zf3~f8mvv6rp=ED9|2$cGdU=O(O!}4?)3$hfTSc1q?U)x>UG|&#XmptF^g|D}KAZh{
zw$|g*qNR?TPsdi=skhj6M6cq~=Y1FC?P@FJ?M^GE6?w&NERwR%IavFH#cuzNZ{DX@
zhU!@=P5O0&vtq$X#%ylZ0#nh}-lfcwg(o-ve9{|vv-6QiS#jMz^VXWopZAzslTIGo
zbBI}8ai{xT_Flm_t|=lH=R5a4;ncrTc%My<^D=8#eE0u}`>WSJh}c@OqbUDsvhJP&
zrE=Tg#mbLMJqs6VD%N;p_|>hEC@m;HX<9VhHDGmPP^Mn*Qy#tp4bF@iXN(HAguO_b
zxMit&T(Y%M#;KITS+7?q#%FDObfe?j`qInq?78dC9?qJ<F<J3P?F0RD<wx0r_pN$)
z{PFZ<_oN~i_?|>Cd_Kr%{eblbxAmii74IH+y3a~`ac5TZt@+u3&s-Xv>i#j-b!Rib
zIw!l{He5VlcSKBHWQ~EMm6@HLn%cd9k`oCQDvMZ|&U_IFSe79BPB|jH??K76xYL$f
zx_zt#58vdgIIhsF+iv1M?X154gWyX+!Iw7eyE$7cE;>e_@~Gp)E#>ZReEX}PuWPD(
zbaJ=5|J;?KPu}03xYvF5<ZbE2kER@u*y}gzj9b`0iIfN5-`tzLIsJ9t5}U%4A1_SS
zey_<h`%?Mxk1M11dEQmhE9l|;9=k4L_Kw`!X}PD~UD><4@6GLEhwu+?%kNJU)wr_Q
zLd^Hcm6>iQ%nns0zi*HIu;KLL)4%>YOB)!KpOd$V)DDw3Hi@}t_jSL)mZ)@HQ+d0p
zhx@)I{h4{yy)=}un}5fr9epnkot28<&&zSHjB?r-A+$gK{ra!|*W8c37Fwiysixvh
zTm3Z$vm=|Yz3(mcR`ZM6lQL(8*_Rzs6V^L~mU>pke(GwTb!)*jzFUh|>OK<XZ#*I`
ztN3v3zSF<A{dhCA{;LN2uSauEE<Icsr1@L;waN|ge#`e-_jax2+`r+U8#m|j@&zr4
zz2Vo_Su9^2wRGjDf9G<$#LjOx>SdEN%f0Y!lF%FfT`KFm?OL3_v#fNvwU|?T_H)1a
zanF)xoO^swId|jhB{t_z9ew2UTsb@M&cbln{ae17@t67EKfHzg<n*s!7acD-yKh5m
z<LRw8Ze@SEF!dmNpUaD+Y}1qOmsg$7I{3>g`})eqoC{U0Qkd0ydfZE0KF&(!`rlo+
z)=k%9Zv}Jwp#|d18!zwJaq{22U8bv*7uhz6JU$V=(Y$)`t}QFpgcUw2I(T>f*7M2H
z;W5{?R`J+fo-S{tRq;*c;^pA?SK_UA9e8@ACN|O`^G&Y;>$fz4zL|?Fqu%%YZ(CbC
z*S$BcMBd~><lpA`on>!3>i6ENeH+I9|B2M8sMGrV{Bw4C?l~p$_SW>-$CW1)zrMqA
zIj-!(mYoreqL<hGUpDz0pQ^CR?P!Zh1~d1}bLQbWR;JlBt741w#}{&Y*)q4?f4nP+
z)j#d&v<(vZ_qc6SrTpaf1!_6Do?mXVEn&m*Own(X!!F*K)cD><*HG@{>_0~T%;q~v
z{dSz==w+}#ZtZM?OIME0u$#K;g`@lz|E0^HbqHM0;_JHk_QLLmMjN6<{Ua8gm@0HZ
zt>V_=<5FVm^)FfvS65w(NRDIS`7yg8EdRO8tY`n2GvnBbHqYpEKDK{Jy0QL7+qKso
z1chs)UfFn0=9I~SlSPfcmU7SAJLz!Fj+Ko^-tW+Jd!(DFuah$0R=};}m4V~0D-Md8
zYkNZs#IA4FxTdk!Xi=)n#Cx~&tV%CCo!jOA@6?veL)&*o2Y0z<?>0NQ%b$7r&q>WE
z*;Xx;E!%QBy6(xXhbq61Kb<!Jv{%q|>5_J#;zi6`f5g8HivRZVjW_e$=||5+t!d^G
zOO;wW+wE24^e?W{|IFl-N$p56d7&V8Ey?@BLrW#QQzf+zOfUJ)ICQ9i{o4)Z^FMFN
z@e52m_ND7<<n$+#_n8*|R=aCrrkwtKTg<-Q>z=7^baz$BfBiCl!KeDx6?&F`d~)U<
zKIhHv+jVWNCyyuBlUU|+c7o@v&LkOLH)FM9ecjH#aJ!$CYf6-FO#0jg8DAb@`_#f!
z>YDv>SM57L>{Yfqp0xU%qyd|*$dX2B3(HFncFn%DL^S8pnkT-&m#^i&-aN&%T=n<u
zE0fDC-}DKuVpZ$!7Kr#V^}~b{hOFN*7$zzoKXTDw&eJ9n-d79f9rI%Qf7<1;knNY|
zechq!1+F|l-Ie`%tL(YnZ=c1EuI0PDw%034YFY1Fout?OS52;jx9WI$`FnX@R8?!s
z>v+~YceTWnpHrL@+Bd(rFJZ%&<@xoN&u!zsQLHBAxgRE3M*Zds->|EC>yCd@)~zY3
z|GBTbYvY+8H$oMIf2{1zULUhsn>FkBy)(Jht}M=G1sUHaCI?>s@qK%Jd*T7MePy)@
zd}(r)vc(6&ZtZKlyw_<lzue6w-nyp@=3GA{B$gQ$Bj0a-^hENX4}x+13&g+d`t)Mv
zioC?_d3UzxcJh0jTq(%-->1Y(B;-qkSW5E7oHdmOB3DdKdHLO)cc^+j*X$?ii?UVB
zofon#J1kel(QL1*`cnAAB6h<EZQm!fM0wb!H?%MPAQ|VST(Rh&|E{Vp&L4Ayn{Kao
zcxLn6B{AX|9k-%)t6mND3wry+XO%Wn)xnkbe{Q_J?#WcyyDKe@RpoI;8U<Q+xIPWk
zX8sa*db;Zr8T-IEr)$f&Ph6W8q9tUJ>$XBE@S^a-gLM@)a^1BX?0b$SpL`wOB;3>Z
zbOVodqi~$sB=LWKZ{EyxbK-XVW6h;=@1&xL6;o^LAx_7>7q3;Od@!<M>p$kbQNKr#
zTYO@&PUQssACp#pyfNFNe1V;k#s-^3%c^EK#8_};9-GB=OH##h%OdfLj<g#M;yh)Q
zzd!D`@@n8bD|2f7Dp7w~`-*Lm+)P^f>sNNI;1COZf2{08-uxo@#(kc%{I?07Sebu#
zMVO22`%TX;Oc0mp(iILc|8wnxgUr9)y5kS#UP|A<RJWMjz~$=nj3e(neQr%WvAepm
zdW~MMZRxi&3m>N@IsTm2Wu<Gxn=`2?uZYoF_|qfNMh`yY4$~$3+=AmhrnO1>M#_Jg
zbTFeR?Sg^dro?|tCq0x^lk0yeW?woO;mN-Etn=rdS>K-oRI!HFKK<R{yh3xb^D>rj
z%|^#%DIb=rZ<@r{Z~F2>#^(z*i?5Z$&+Ezkp#E8nU;5Qmu50qAC#*0F+VE~=%&Cdn
zGCw$dknjAv@w>$bwM*xwG%Z;$GtKvsvP6jbjJR7O92p|p+t)sM<||=&=CR=l$J)mm
zB|k{qS5nR~by_)*<?DyAqK(%(j-0)j9e7@8(aE(RcBU}S4>l0DQ$P8mc+xJr>B=6z
zJFS>!KMi2+mD*FOm6LX5rlhpXR<&-8O#8r~moI;uw$W6|kp8}SrG8TQ+fKcXtF2*I
zR2OmHt2^u><MGYgAWrwy1g<#~M6R@~GrtfXIj22Yf#3ad_>G;sCWTvX%N7+B2+y&5
zVJ(sJIe+@fb&7h68$TYIcx<!5y|x~;34%q!#~#JcV3Ki`Pv=r>bDL!uaB^GtTRl59
zv%2`o@9(3QFjoiMIou_tex30gi(&SXMq^(`b&p@G`fMd0td@QG*7!`}yQ|N4)v&1c
zd|$asf=OUs1(%4ALpRIU<cBiJvF&=C+~RGo#k=HNB~Hg#tZ|>H`HM&1mHjibk?+E#
zcl&gte)U|LQsMk5az;g$NEkC~`TY|Q_0C<{<7gM^`*5vILE5zt4W-=gkL2g@z38i(
zJ%4ii0*BeNG&BFF_G;er^->c^u*s26Z*W<>#O#Zk;q=zK$4>>GseS%?()xwpFZ&g|
zbFk-P`MF@;<^C0KZI_##SjHTrD7$<Tm*UOstdm1G9+R8f$YRBM+u!N`<f0!9bz&cQ
zHb0+UbaigQ!r;CYm&=z-vHo<~<$(2zru!|N+<yf;ZJ84^yLRtVf2`1-&=h%D;~2;9
zTZ!{0{(95-Gc+=PX1}DQ;p#$xzYQx}6^!1odwV9e`F}`jX)ds0v0Nzp_3QEe>yyvy
zp2RXww^@s&zKXZVNcTwNC8sYBRxYXTDtN)EZ1imdTS|kQa??LE+dA7i`9BiHCqiOP
z+kM_JXTE5@*XB3fk0tqDpWqc2^Y3RobI#h%$al~cd9vli(!(#f=Tv^>K5Zd3lTUvF
zpD_Pk^_>DKLXLN$lB;be&fTY2=h>ELdV5M>^}9~7DQkWucIf@gcxhf<vBHJ_=>}Q-
zD>f$H_xlfAbWyo{Hd1(lRgM3a#sA~BPdJen{5b5~3u`;GihoT90&4%Pl9-vZ;!N-}
zt=W3BmANOLoxU>la>~a|2aU>a+T2v%#JH)|NPOnpo=G2#@^AXw)VP^(ljo++%=R<k
zW}(|0)MowGnzrfQCc7twi&Gw-SQHS+QhA{4rs7S>NORT2YcwWGdGIcG3wk$2eQQIM
zi|*ntSHf2HzS{8PRFY2Jy0(t>Ex-Mj-c`|Ospgtzcc;Mbt>o=(2Ncd`D!(||zj@t}
zRY?!U=iVxAOweB8d+2+URJdp0`xV8py(+7}PhMog$&_+iWybT^9lCAz%A?fFBku1o
z4&NXrrx{WG@6;sesZ43!I}gwOCLg}P(*0_wY5B?5RbsNwX5~IBdS!3)y(px5dJ5aZ
z=SeKZ2iw(kD(7;4|NZ-(uWa(|wYv}4d2XnSbz;d8)SFa(;HTf~W8D@`mkZ+>G8Z3Y
z>R$BqLuOoJG1HOuHCqp-9NQ&0DeX1uADepx5e+WpjLU007U~;LxHQ>m^?wDQ$1&F(
zKDWKso24s|H_c(k%}itS+1uuvc_)-(X=-tF8rPMT>l|G^Jb$A9S@zCPf7a^lP7}Cv
zuFrgbgpDK1-`?@A!0q^e`pGX3PTa{X^L2{Cy!@q1)|(#{9JwoZ@Wb!wCXT1NK?j2v
z!=n1$-ajWGog$^OUX4%5`o#RwQ0~S(Zr67GJh)VPdw$s3vda(oWm68-R4%qkSoSkW
z=tkcAwu9@muUF|^i{*>2%wWs6y;JIW<;~MawqbwWXBm9@KV#$fqh%Q{w!{^EbbnW8
zoE`hT@Q>4xSh<q(o@Hf?CzJ0b7p}@*lHS1aREOsf>#TMA15VHR-yLP}`tZ%dS2vVa
zD)8_5*80@2f2ZD;jgpyvpZ_|qvgT*q@po_D+_f%$cjDyDg(359Y}c-SK2P?hb@?+B
zt<X)s)7s~1M(b-&3q4u4L}um15WP?j+r|G<6Vo4N7#>tQqjXd0uF~O0*4@%#<+^cE
zd$zuq$Uo`!Y4?-+r|mv%e)99v_9st2J^z&V(_VMt(uAA$i`J%grA|w2eHwV$>U8=v
zwO_%rmWN*w{F3)eeOGUt*Zu|Z7uU~>>#?4EF2(4kk6v;6%ak~S^*8F?BwU+VnwET{
zW?Pr(ru8@LH~bGV;9By-Wno}P*Tt?vF7ej>q?t+~f-7$<xUuR-*u>=;K~uEzwBBj%
z5~&a0v-Q`RtO-{QR(FQ23){SQ&l<5P-ECeQyf$lXu}UjFw(8)kNuiTNr;8Sd&FR|w
zkmX#X^m*UsX~o_<B=Ur}PrZHe?bC0?>^q%fB*V|gK9wtyz2p7PR=x1Qi<n32uZ4jb
zY@b{gYH+G9UYlWW)zi1gc!gZ7yZr*OD{Z$fa(`hz<TW#B?H?!00LzG%D`XbWSy2*J
zrSV+*@08V36utHuh3)kF*=yvzGd^;~ngF@rd4X{uap7i~^&xfvc7gjs_67c1`DeP<
z!e1dvLvOBPTiv$OZPmW8vmuq4AF>XuZhyowheKtd<Au%JF8#`WboklkBe@gA%#s9U
z3RmRKQSGT{7M$0-{HywvDh)Zih7Wn>1=ZQh?z0q!WpB89;$MYSS#6eeYxTEz4t3uz
z=5K7?QTyq?^eTmj#XI}2&q%y}Pwua~(uCRP{?5&8H8pvYdHKOtp2{!6Qi1B$irZuF
zg*#lDXytqCS-#Qs4}z~hdAaO3Sax>B@mVM33K<=(iaF<G=Iy`fJyS|T)Nl=N|08yP
zp82nJ&&`oa>9*7jyT-G_*4O;~DgTN4KN<Y}KK((g247;3_|ld&{Q+mLp68r-<Z<I+
z2gY{>+l3=u)V~c1a%qi_n!EgeStHX-&5t5|YEz%C*;(pTTIxBiCAi9AGux#Z-=zMp
zKa%_I%O=~?#b2!!bkBI;oT)0gep{o_!m3Astsh-dW81~5{C738zxZH0>5s(9^{Oe(
zGPeUJO2w;)tv|~fyHIwk%>lo5zQX+NXLndRIBXBo)17@X`SrvZhlSn6&RFdYh>41p
zubsHRbk~}fQzTA4+Q(?O?K0Epb<1BJGx$~=W!vyDx?aPsGQ=is`gM-ITUchEGg7`>
z=N4?=<kSA&+^AGB;zNBEW7xgZ#of)Nj;Wre)3^M8$8qCtvV_Iq>#r?EbW((KOy}rs
zT&g`|Qu!BsomY|h%*7oKb0pW8+8%zqH2uqT9y#YWCdpey2Ih0C4>wHyBBVAe?ox*5
z1nK<+Hx~wHANkR>r7M@0%VnnGvFT5CDzjWE-}idOOzr;rmptD@OqR7?RrpU@W$yOI
zg+YvOPu!R#!zOUYYQoP;PcBU7X)}C~ptWH4%<Gpn)X!)W^!WZ%wahWh=|@(bsS)$p
z;E&-y_U{tC-!f~rXqD~r!w1h4%FH_Y_kc}Jr-~o*?K8G6md&<>y7RcVnk<vN(ZpDv
z{cJ_b9+q_t^81{W4;S!R7WTJa*gius^3ZW7rhRRJOfzdtTK+X|<X1T($!}np@GrS}
zi$V^M?1VWpWDc#rKVhr3=bSUko;}akeQ^5JH#vo}f2$pL9lWD3^;QQX*Ktp0$;rE4
zs@eKw8O*v9dD3^6pR&@1-Q5id1~(SY3z1kkQ*N_=g^<z1CR_WfvG0Xd;<&!+$R75e
zDJ(9aW5%_%=5?n>ykXznZCQ8KuA3}3xj*GXO6&15zSMJK6LxA|EV)#_?cMr3m*u~o
zI=1x8sJXmzb<Y#;Ge7R<PT|yl8F@y#So)|#uS$3Cgv&fH|KDBHATITXX;s7w-f90=
zCmKc{3H@=f#GLKejRV)u{>b)VPha-bYfF4@MNZ+q-OXavHM#w{r8j1Z9PWQA#CN>#
zMMS0a{|85Axw_=3ob46%*~2|2tzfdJr~gE?`$uzi{wS>MDA^}-@b7t+pE8a?Gv{4;
zFBvj9Ut|5%d+`-jTNclspWOCNEO^?~-PYmZJJy?QpJX2{wl~Ss=TnBDYT<_Y4KwVk
zDtMPj`IaAZyv06mL&)voH{U8xPCOVbvij!hn^V)}GvkG==FFFo7M(31=gK41vR}<z
zfUiOGM(crKTc0-1mdk9D?oO;M>{IRRtGh8xWv}E8eb2?0KdRi}XPa2`n(OZYu{oZW
zy$0WE(iHAF@hbN1o35FZ7k1>w&$d^4pRLo}yEAmoVV?a@esB7Hto8WwWbMCvFV6gW
zm%OI$k%s1s14|M(u09CJTzm10`3=VRy+3R@6R-U^*mRWl<(=qfoGq6EGE_>s6^~W8
z|39}Ntl+ld0^iO*$5!06yr|R_>vBTRP(ACelgf`z&)%OEzq6o1vpf7j^A>gPdEzD!
zha1?`F2A~`I`_hbyjb<6vpg>=K6Co;$0%H`-jFG{f~oAUWblRm%YR)uc6rg)UoXE$
z%u!i;#b&>e;CHn-?CM6p`)bQS{9Y98{_BoaQ01$pZ};xBT`cPs=fAOP_sJC5dxZ)9
z>mFVBw`q@ZO>F6nt`9#>G;Dpe=Y!(DmIan|7Zxv#G0$47y*F5W*M<|n_^uohJ^SWC
z?9PixDffOIa=vA}Tsz<Ny33B|ujPz0OEudUofcWnyoW>M&?nB~<3FeA?%&|{=f#nC
z^_Cy^S2q?ODl9IzbeXk6_v_^cs%!k+oU{_>&Q=mWRIz@+Z3X7l$@}f9l=#wO)Y<Dg
zBX#BO{dv0kwR`uh?2?xJA6q>S^Kx`BeP4RnT6o8iSl825t+U%dvE08Rvrg^r!)JPT
z&DD*$zGv>gJ#};b^}gKMMJ1Y+zqdX4w3M|qRWzHAbv+0F{OLODW^YZkD!Zz5`4Nw=
zlhYErFmYL_9f_j$>0c+dd0$=nO#W)o=gp_TY0Ax=rM1JlBcssA=Y!DOC9CiGTdj-D
zv6c>Q_3D?gsEy)2bD=D!cdN2n!dktRzcs4gJJr7a`|D`%T=5^4FP)Cdr=Od)M15*U
z$AP!^-hQ`y{XK2V*{J=yv=$r+j&}LF#I<Vr(nrB!f0Y9Icj*;y#7t&6^l@@;#$*Ln
zMUIrXm>8pf5{1))m;UDN%bs0(uEsX?VUYR%zuEq-uP)?THy(M^ofq^=iiOuALG<pq
zZ`uFdt$()5ZkUykReo*XU#6<dC3}BwpJ~qCQDI~BWrJH+%6+#<weo+hCpWp8^IY<*
zjto&flN^@E*&BJ{yz<IjD_3&n{x4s=anUQkz7@;l${m8*|7`R<Zpk+3fmrW<8$BI$
zzK->mKb-4ymC9~^aiy2r^0oe_i8~+Gwrbwmt6y%vU%x#2l;Xr45{c3;m_3VC-z~Jf
zSW^&@<S}JOVQiGwnOCzG*iF~+;_Ca{s+w6C?pm_YDrI7Rz>4ku7cTz#^=h%WOA7N%
zA0_rij=H3S*KTmt|JHmaB*n{o>=EPTG=*3Co{JAnKX+l#85O?3cQQu0Nt-ql9qsw}
zva68&Mz*9nw}0$fyYdI8`r<`}dR4@4O}Tt`ak<R#Mg6)PRpq0Tk`J(pH40nS9GD){
z>s;_kZC%PSw&kwuUGKD=CZsJdIGnb8L7n0OOJ*;7ttacfOv`_MT`BYFGMk9Y+?eIw
zx;poQPROshv-9(Widnwi9rwGmN`E^mZC?I)M-ktgqzP_PH&VEaSWOL2?6z98@x$&l
zb5m8mN~mnVec-++f6TkUj-5qT&Jy>t+O)+xzZvaNHBDOj|58l4+<HaD)J(M>WnXwF
zo&PEoEbz-e_W$|!dv;7cIYac(<LQeE((b>{shPxhjmyLB%1yr;cQmKpQQgWG`ETdG
zm-AmsURk`o<kkIy6K1(Dy#4U(-oR_`j0CTK;y<T!Hm3N`ujc*Q-;V!V=isO7peI@K
z@y1WFkGiYVp8dKIr}M<o<Xp2vm0b1Rb~jnIr<U(do=H<LT=(?n<A3{JBpq<wpsYUS
zXLrMgA9*+Wd{|{)7^;UlY<1(B)p_VvdFqr;qE9QAwkEx6T(f3zDc6#f8hzJZFFrf}
z(c!16N1v)3cR6;<ZLMaPuCA_@mTs?Zmx!RI?xd^i^CYg6d~M!0JJ8y!a!=;&(j{;A
z<$XW)X3N}_UHx}A+D~2>`1!nU@c%o9R_JrR+P`YU*AE<giI&k_TT66<xuT?=9MPO3
z)XsBoo6R=aPh7`Tx>n=~tFu2h@rz11qPA!QOTFLYGZl~bei3auV9a%Qqotm~is*Y;
zm+zii@La~n!GcL?$pN)R`&}m;X=`o$eWXGwOEQIP*2z^Tk2Oz7TWFUT%OF2>PV5s^
zr6T=jZWXZ+OPwZ3l$hVRu)8&&AVt{Ki1DX@0^4TJH%>FZC;YJ$3O=G)a#MTrBeN{w
z%fV*L78@u|cD8gnnc1{2;QEEUPJ`n+vUi{LU6g!e!?N)1CE+}$_GlWKYc^%i+sAx;
zzVNI+uRS-+jy__p;h=lrs?zj0r8b7#rsG$Vo@#AAtSG0IpY&+wgS>YkfiH~eH<n$k
znV7OxHc*E1O<qOQ2bRzC-2c|eCjJ&-WD^b%6BLvP5ey6tjceqYImhI}n}SPWj|#I6
z9Xs2{=Ny%|p7HIk$3?aQl3XP}K3x6#s8PObk;a<^nqTct%&1?rGu@@)X{JQ0-4Ele
zvliytH~O8;d)uF{%(cxv$LM=Yz_X>hW(#?5`x<{N_3eDnvW4Q3BGCFz=*kN4Vg=Aj
z1_cEL3nL3NkO~mj&`beiX{jM--6igY4R%OtOJjp}=N&fSx${+2>aya7Ka->m7z8Zo
zZnwLzMgD<DN!EgCtT!e9d{;fHz-o2F#<N^KD5dPpJZt-PM%DeBZ4YX-U);@cx~5m`
ziKO0Q@k+(J8P{)X{e63ded59&TXeO3=E|pCG%@;p;Bad1>^rtQfAa7<dClDG%3k<I
zeCKbgc@?iqcptK>eOMi`D0gWy<J-7jA8z?8Y*x8f&UgNJ>FvdD`akYuo!}bve9ok~
zvN{X53sl!LUevgHDorAa@!nr+ZBg%Y&41r5&d_QPS!&SX#?P7T5M#KG<9bi_p=ldk
zYcvGKwbXOEw)8uiuvUwm+?-P9`KRmWmU!Dwd;5=A8a#Kf>#7y`SzyQdG<c)Gt6ke?
zL(TbfwpteQ6!T=>T&^&GlfMLW)=s_2uO7*mJPp`f@B7cR_|=h%XD+tfbf4V+Ov?0X
z(vLXj?^$*1zV8!m2s4{L`u6CG(5$)D>))EX<rGV8xDx;B&5MV2&53+VyzcAoVA(nc
z6l-Yl3W_UGL@FpK7@NUY=Ne+JqyeqNaY-#sF3Kz@$uHspEl&Xn`6cG2D(HKMMmqWh
zYWrp8CY2TkC*~FF2BoH#<|HE2xh3Xi=2R+ZK$Iwe)M!Es$w^EvhAqCy&ntm0t<^O$
zG*Hkrvb0n%G%z+&Ff=eXRe&t9^(;xu$xL?4OV3GFFaR6jSe%@iSE68UWC`YiTnXaq
z8ks}Z_c$jOc%){gXOw`A0jmivNzDyYuz=_XaXergkf+=-b5e~Jz>9W*K#Oi*nE<rv
z2ozYL1;wBxISTq9)er+=YlK1K5Nn+hi&H`J1cL{({Kz>Yu}Hz#2yB*5VsQzWZ)jox
z766$7@)acP6~M6r$zZN|$@wXndFcxJ;hA}kdBvG90kFRC%#@OhVuff0BXdxMf|e^|
zVq;^_T5Mb@u!)-+ffhM|OfomOP(bhu6fD4Ifn-3~%*<TD47^ke#KXj<re+FYY+wMP
zP0gS#1&JCN87Y9U0holC3=#)n0|k()O$`jd>LDV??!dGQp9sh-5C*3&1^tlx(7a60
zGI#}W>4uU5KtY9?0x(yY8G(`sBzpW{2^$o}3P#4@SaBn;;68L>VD=#cf#dgoYraeM
zkz6u;OP2Ogc2SpO4kh`;{EBT+X0s+ONv``Hn{_+)$;*E`<KNY_FuU2bOS&<!oKtF?
zuuMsdt0O+Yx9x|5_gf`~j`^#*o6Q9p3R=GF-I}rO+kwSbS1I#di-}sQ>oaA|8pd-K
z#{|^E-%D@rd90_qHfP<`qBA#&toGU`Z~fA?q4w{?DN8oaQS~`csj~W?lEd@;A*rv{
zevwkUz0_f%(sN6HA;nGVPx?D9CvJ_GtXR;>Tt6YK{cW?q_?{Qus@I>*R+;EGk5lbg
zH*3)X_ei_*X&P=HZwbFqkbODVG?&>`uq)ucdf7{Xxf)wHmHEzCljppLJwMtuMEcdO
zSL?lAKF*VMGUE6dXni?qsjSN5Gs2Ch?z_tTePVyJ_sgftQ}$~AO<M2eYv1~*sT8wh
z1IGd=sz4>1p#ew%hzCx(AO<22M+Bv&fg=XGLeK)5>99l-sMHJ2tV)GNWw=7Lp@NZu
z5jf@O2j%CNC>ViK8YK2T^V0Ga3_*)0!D$Fu@>a}APDuFie|~4<^hQP(14AR7q=bZ&
z2ke4-6%6?lx+n5_6x6T_{!=(4<ME=6k@K9E!a{k*Bwq%hs73`PVUHIXO&shU3wsor
xW?q~isgb5}^Z)}xlRxJwkPo3&K+CJ*lEk8tilWpsE<+<za|13_RabvEE&$lM4)*{6

literal 0
HcmV?d00001

diff --git a/doc/_r-c_r.pdf b/doc/_r-c_r.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..39a2f6618285c735fef9a4bc1e02265ec9eb2494
GIT binary patch
literal 2170
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

literal 0
HcmV?d00001

diff --git a/doc/libeisgenerator.doxygen.in b/doc/libeisgenerator.doxygen.in
index a2e801a..a10f844 100644
--- a/doc/libeisgenerator.doxygen.in
+++ b/doc/libeisgenerator.doxygen.in
@@ -259,7 +259,7 @@ ALIASES                =
 # members will be omitted, etc.
 # The default value is: NO.
 
-OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_FOR_C  = NO
 
 # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
 # Python sources only. Doxygen will then generate output that is more tailored
@@ -864,7 +864,7 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = @CMAKE_CURRENT_SOURCE_DIR@/eisgenerator @CMAKE_CURRENT_BINARY_DIR@/doc/mainpage.md @CMAKE_CURRENT_BINARY_DIR@/doc/modelspage.md @CMAKE_CURRENT_SOURCE_DIR@/README.md
+INPUT                  = @CMAKE_CURRENT_SOURCE_DIR@/eisgenerator @CMAKE_CURRENT_BINARY_DIR@/doc/mainpage.md @CMAKE_CURRENT_BINARY_DIR@/doc/modelspage.md @CMAKE_CURRENT_SOURCE_DIR@/README.md @CMAKE_CURRENT_BINARY_DIR@/doc/readme.md
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/doc/mainpage.md.in b/doc/mainpage.md.in
index 1f306cd..8e3d70a 100644
--- a/doc/mainpage.md.in
+++ b/doc/mainpage.md.in
@@ -25,6 +25,7 @@ lib@PROJECT_NAME@ incorporates three execution models to choose from depending o
 Upon invocation of eis::Model::Model the model string is parsed into a tree of objects. In the default tree execution the model parameters and frequencies are passed down the tree with the help of the virtual function tables of the the objects in question (black arrows). The results are then passed up the tree (blue arrows), see figure below:
 
 \image html DirectExecution.svg width=80%
+\image latex DirectExecution.pdf width=\textwidth/2
 
 This execution model has the advantage of very low latency at the expense of throughput. It is most optimal if few impedances are to be calculated.
 This execution model will be chosen by default.
@@ -32,20 +33,22 @@ This execution model is always chosen by the single data point eis::Model::execu
 
 ### Compiled execution
 
-In compiled execution eis::Model::compile generates a c++ function containing an implementation of of the equivalent circuit. This code is then compiled by GCC and loaded and cached by lib@PROJECT_NAME@. Subsequent calls to eis::Model::compile will then use the cached object.
-Once a model has been compiled any subsequent use of the execute family of methods will us the compiled object instead of tree execution.
+In compiled execution eis::Model::compile generates a c++ function containing an implementation of the equivalent circuit. This code is then compiled by GCC and loaded and cached by lib@PROJECT_NAME@. Subsequent calls to eis::Model::compile will then use the cached object.
+Once a model has been compiled any, subsequent use of the execute family of methods will use the compiled object instead of tree execution.
 This results in a speedup of greater than 10x from the reduction in virtual function call overhead and the usage of auto-vectorization.
 
 \image html CompiledExecution.svg width=80%
+\image latex CompiledExecution.pdf width=\textwidth/2
 
 This execution model is the most performant option when evaluation of many impedances is desired and execution is to be performed on a CPU.
 This execution model is only available on UNIX and UNIX-like platforms providing [dlopen()](https://man7.org/linux/man-pages/man3/dlopen.3.html) and [fork()](https://www.man7.org/linux/man-pages/man2/fork.2.html).
 
 ### TorchScript execution
 
-The final execution model generates a [TorchScript](https://pytorch.org/docs/stable/jit.html) for the equivalent circuit which can be compiled using [torch::jit::compile](https://pytorch.org/cppdocs/api/function_namespacetorch_1_1jit_1a8660dc13a6b82336aadac667e6dccba1.html) into a graph of torch/rocBLAS/cuBLAS GPU kernels for GPU execution. This provides the highest possible performance. Due to the high latency associated with executing GPU kernels this methods should only be expected to outperform compiled execution if 10^8 or more data points are required and only performs well when a large batch of data points is required at a time. This version is also highly advantageous when calculating impedance spectra as part of a larger system requiring GPU execution as in this case expensive device->host->device copies are avoided. Though torch autograd this version also provides atomatic derivatives making it useful where integration into machine-learning backward passes is required. Due to deficiencies in the windows port of Torch this version massively underperforms on Microsoft Windows and another platform should be used.
+The final execution model generates a [TorchScript](https://pytorch.org/docs/stable/jit.html) for the equivalent circuit which can be compiled using [torch::jit::compile](https://pytorch.org/cppdocs/api/function_namespacetorch_1_1jit_1a8660dc13a6b82336aadac667e6dccba1.html) into a graph of torch/rocBLAS/cuBLAS GPU kernels for GPU execution. This provides the highest possible performance. Due to the high latency associated with executing GPU kernels this method should only be expected to outperform compiled execution if a total of 10^8 or more data points are required and only performs well when a large batch of these data points is required at a time. This version is also highly advantageous when calculating impedance spectra as part of a larger system requiring GPU execution as in this case expensive device->host->device copies are avoided. Though torch autograd this version also provides atomatic derivatives making it useful where integration into machine-learning backward passes is required. Due to deficiencies in the windows port of Torch this version massively underperforms on Microsoft Windows and another platform should be used. Due to MiOpen not being available on Microsoft Windows this method is unable to perform GPU execution on this platform on AMD hardware, the CPU fallback used in this case is slower than tree execution.
 
 \image html TorchExecution.svg width=80%
+\image latex TorchExecution.pdf width=\textwidth/2
 
 -----------------------------------------------------------
 
diff --git a/doc/modelspage.md.in b/doc/modelspage.md.in
index 23b4c7c..5e2dc20 100644
--- a/doc/modelspage.md.in
+++ b/doc/modelspage.md.in
@@ -1,6 +1,6 @@
 \page modelpage Model Format
 
-The model format of @PROJECT_NAME@ encodes any series/ parallel combination of implemented impedances
+The model format of @PROJECT_NAME@ encodes any series/ parallel combination of implemented impedances.
 
 Currently @PROJECT_NAME@ supports the following elements which each have a number of parameters:
 * c: cap
@@ -9,13 +9,15 @@ Currently @PROJECT_NAME@ supports the following elements which each have a numbe
 	* one parameter: resistance {R}
 * l: inductor
 	* one parameter: inductance {L}
-* w: warburg element (infinite), one parameters {A}
+* w: warburg element (infinite)
 	* one parameter: Warburg coefficient {A}
 * p: constant phase element
 	* two parameters: {Q, alpha}
 * t: finite approximation of a transition line
 	* three parameters: capacitance, resistance, approximation order {C, R, n}
 
+Element identifiers are case insensitive.
+
 ## Combinations
 
 Combinations of these elements are achieved by writing them against each other for a parallel combination, or with a '-' in between for serial combinations:
@@ -23,28 +25,32 @@ Combinations of these elements are achieved by writing them against each other f
 "r-c" is thus a serial combination of a resistor and a capacitance:
 | r-c |
 | :---- |
-| \image html r-c.svg width=300px |
+| \image html r-c.svg width=300px; |
+| \image latex r-c.pdf width=\textwidth/2 |
 
 While "cr" is a parallel combination of a resistor and a capacitance:
 | rc |
 | :---- |
-| \image html rc.svg width=300px |
+| \image html rc.svg width=300px  |
+| \image latex rc.pdf width=\textwidth/2|
 
 While "r-cr" is a parallel combination of a resistor and a capacitance in series with another resistance, not that the implicit parallel operator has operator precedence:
 | r-cr |
 | :---- |
 | \image html r-rc.svg width=300px |
+| \image latex r-rc.pdf width=\textwidth/2|
 
-Brackets ( and ) are also support and modify the order of operations as one would expect "(r-c)r" is a series combination of a resistor and a capacitance in parallel with another resistance:
+Brackets '(' and ')' are also supported and modify the order of operations as one would expect. Thus "(r-c)r" is a series combination of a resistor and a capacitance in parallel with another resistance:
 | (r-c)r |
 | :---- |
 | \image html _r-c_r.svg width=300px |
+| \image latex _r-c_r.pdf width=\textwidth/2|
 
 ## Parameters
 
-To pass circuit element parameters to @PROJECT_NAME@ a format embedded into the strings is preferred. Parameters are passed by adding them in braces behind the element thus "r{100}-c{3e-6}r{1e4}" is a 100 Ohm resistor in series with a 3 Microfarad capacitance that is in parallel with  a 3 kOhm resistance.
+To pass circuit element parameters to @PROJECT_NAME@ a format embedded into the strings is preferred. Parameters are passed by adding them in braces behind the element thus "r{100}-c{3e-6}r{1e4}" is a 100 Ohm resistor in series with a 3 microfarad capacitance that is in parallel with  a 3 kOhm resistance.
 
-When a element takes multiple parameters, those are separated by a ',' like so: r{5e4}-p{1e-5, 0.8}
+When an element takes multiple parameters, those are separated by a ',' like so: r{5e4}p{1e-5, 0.8}
 
 Ranges are also supported, here ~ is used as a separator between the start and the end of a range, thus r{1~1e3} is a resistor with a value in a linear range between 1 and 1000 Ohms. By adding a trailing 'L' the range can be marked as distributed logarithmic in base 10, thus  r{1~1e3L} is such a logarithmic range.
 
diff --git a/doc/r-c.pdf b/doc/r-c.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..92f678ba4a70ed65a991faf16aeb9bb5ee1b709a
GIT binary patch
literal 1839
zcmY!laB<T$)HCH$-THRjZ!QxB1BLvgEG`=x1%02?y!4U`1ycnBg&-~k1qFS#%$$<c
zA_aZ7oWzn;m(=9^lvFM|JFeoAqSVA(u8KLm)6eFK81gi{|146;=riZP4Wp1y`ys(X
zhX#iZIj;77c5>-zowsGvLrYb&_vcTtC^Kt5cIm$K68`50-QLeNzc06a`PonA^7m(M
zk6-)qXTCGXL7V)Hdzb&efBRWH`QWVg(FXEoCOa;>t^RUj)9ITQ>|Y!{XY@(vij+L-
z|Cu7U?Rrqdtb$2VIx5_a`>OY8TF3LKby!Z25fZ3q5ocDj{xM}?QY6R53knA-IBvcd
z)=8MW*r0WVMzf--GtbOJO)rCHN`}q(>YZw^M8!i?TzIx*SdE5ARd<(>M3{m4;|0go
zXf!7tz2&fQF-x3w^GhzLzSM;#%lvr`YDHTb*Zvf{QdzoW`Hd$1TaVZ;n_p@={5p2#
z%s4&mRD-=5Upvq8Xjex@cWnG-ciQ}R&#cL}k9<C5;IQGG%ZV>r_S=8qv%R|c@rHHQ
zSDtq+T(+&;WTktYZ(GCe$1i7mDxAM~@13adof3XeIj;5z^Ym|elYMYQ&<@7zojN%O
zCp7KJXPn}w*3xP#&ZxIKUCB!B;3{UGW&WB?@3$74E<g6A)xG22rxk)e{_A&jHocs^
zLaWuSuq1EFV~6E4tmZg96%gUkzIV;mt$Zc}=f;-CTk6hwvrHVFy>5AGEHvEfvUIJd
z@RiFG4z!*&65!FEb8^YtokB{SFI{3SjSqWiC7PNuZVXuzt?KBYV!5G2JZed_gYzZx
zFo)!-Do)M}6{q!~j9*)}7hM;&+j``RQn(*W4r|GqOM<T_wa>VuB3t+@`o2?^fcH)P
z=r9Kr)(uD3E>l;SmZY1V*%Yzr^-Io-bMwOZU%t7iTs?DJ)m876Z&Mp4eSiF~=W7pl
z$I__FS)NRfZm#9lKYb{hJ7}uU%p!|->@)R@zFbTE`Q(4{s#cfy{XG-)l>VG)+g`Bv
z$Mx0h_x>$xoU;6og_G%L_F}bpT{jf|HnqK$-|YBBa8Vhz$eDE_Rk6{%hK99M%#K%I
z-#9PgiFexi%gQ0!w`#vtS?2A~)2$qDusi70DrpvH{f3&Kmqic0IaT-SwXpD+bs_(D
zcDNd{6>(+lTG8NoQS8+ft5tjUO6=jN_BYwlx|Ti8?%g`W_dCy=4$pZNb}>hM(w<NE
zYu4A__{Z$<G3YK=YF-L77p3N<fbt(G(}8FO1qBNubC5iUXAIAs;QZ)XQQ{t4l30?e
zU}FOk0Oip{0|ijtb#_!RRM1aOR4`PqvjfT5*@3bu)O2&WISTqAl?AB^`u<5-!6msM
zg|KXI0nhe+3Wi__x6GpA5(N_|8-Gz?9BlBQ>si-RCI&VO##oU1QT+!p9pobg1qDMh
zkTi&6NrbZujgZ_0a|_5_M#e-rEOg?*EG9#Nw)ek9iZw&IZhCGCntHUEOKGXXtF_+*
zk|LZ>r+IE#y02D!_3qr0nfsocJ~O}IK##JIfv`fsq(VN|#>hygx;<uWpXRReIl-V%
zzwtRkz5+uc|9jb}o!j~jY(Bckxa{8C=v<qgEt~E!rq`SjaGNeM+u;1?zOXn`@zu=5
z`=t8wuU9Nyq?{XF&$4!fZu%rn3*KdW^HpAcxxQ&#-0F;kE%UfVSc~i)2XTD-)AC2K
z@J|0XX*Rix2T$HlG0*%pWjXWuXE|3d)dqVkF?BYZ8eAnJFzKO-mty;kQWaAN!yVG^
zZ?T;+5?#6P>+6huK9{|#oG1T!mEFHxpf>wgmh19s&rWA;zON&^<fric*$<-D`!ZO5
zv6-;qv98;K`aj~OOBekrxoWHV_o1zZ>@UWGsK&RT*g=gva2$XlOhG}x*uVm$0K_vy
zBu`kfiU>+g14j$2F0lmjuvH|W#2cJhm8xI}iPdn0XhQ`f1*2H7j-dSf5(Ps;c-(vD
zrR6Ia8i4u8RZwz5!jJ#+I~ylAGP)QT8m&)FNJx3WE_CLyW6~RiYvBq9gZPxH6kbU<
vvKTAR<_zdLJG+sQfoBh!Cdd=0zAP?DEGnreN=@T3G&3~hQdM>JcjE#8uk7ks

literal 0
HcmV?d00001

diff --git a/doc/r-rc.pdf b/doc/r-rc.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..c73d640fa284cdf75e42d08d6cdad358fa6e1fb3
GIT binary patch
literal 2123
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

literal 0
HcmV?d00001

diff --git a/doc/rc.pdf b/doc/rc.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..82ad38038195f5d9a3342e24cfa2f9298aa45f01
GIT binary patch
literal 1994
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
F0ssUfKr#RT

literal 0
HcmV?d00001

diff --git a/doc/readme.md.in b/doc/readme.md.in
new file mode 100644
index 0000000..2da6f94
--- /dev/null
+++ b/doc/readme.md.in
@@ -0,0 +1,3 @@
+\page README Readme
+
+\include{doc} @CMAKE_CURRENT_SOURCE_DIR@/README.md
diff --git a/eisgenerator/basicmath.h b/eisgenerator/basicmath.h
index b21aab8..8527fac 100644
--- a/eisgenerator/basicmath.h
+++ b/eisgenerator/basicmath.h
@@ -25,123 +25,124 @@
 namespace eis
 {
 	/**
-	Various math functions performed on eisgenerator types
+	* Various math functions performed on eisgenerator types
 	* @defgroup MATH Math
 	* @{
 	*/
 
 	/**
-	* @brief Calculates the element wise absolute gradient at the given point of the data given
+	* @brief Calculates the element wise absolute gradient at the given point of the data given.
 	*
-	* @param data the data to calculate the gradient on
-	* @param index the position in the data to calculate the gradient at
-	* @return the element wise absolute gradient abs(re(grad(a)))+abs(im(grad(a)))i
+	* @param data The data to calculate the gradient on.
+	* @param index The position in the data to calculate the gradient at.
+	* @return The element wise absolute gradient abs(re(grad(a)))+abs(im(grad(a)))i.
 	*/
 	std::complex<fvalue> absGrad(const std::vector<eis::DataPoint>& data, size_t index);
 
 	/**
-	* @brief Calculates derivative at the given point of the data given
+	* @brief Calculates derivative at the given point of the data given.
 	*
-	* @param data the data to calculate the gradient on
-	* @param index the position in the data to calculate the gradient at
-	* @return the derivative
+	* @param data The data to calculate the gradient on.
+	* @param index The position in the data to calculate the gradient at.
+	* @return The derivative.
 	*/
 	fvalue grad(const std::vector<fvalue>& data, const std::vector<fvalue>& omega, size_t index);
 
 	/**
-	* @brief Calculates the gradient at the given point of the data given
+	* @brief Calculates the gradient at the given point of the data given.
 	*
-	* @param data the data to calculate the gradient on
-	* @param index the position in the data to calculate the gradient at
-	* @return the gradient
+	* @param data The data to calculate the gradient on.
+	* @param index The position in the data to calculate the gradient at.
+	* @return The gradient.
 	*/
 	std::complex<fvalue> grad(const std::vector<eis::DataPoint>& data, size_t index);
 
 	/**
-	* @brief Calculates the mean of the given data
+	* @brief Calculates the mean of the given data.
 	*
-	* @param data the data to calculate the mean of
-	* @return the mean
+	* @param data The data to calculate the mean of.
+	* @return The mean
 	*/
 	fvalue mean(const std::vector<fvalue>& data);
 
 	/**
-	* @brief Calculates the mean of the given data
+	* @brief Calculates the mean of the given data.
 	*
-	* @param data the data to calculate the mean of
-	* @return the mean
+	* @param data The data to calculate the mean of.
+	* @return The mean
 	*/
 	std::complex<fvalue> mean(const std::vector<eis::DataPoint>& data);
 
 	/**
-	* @brief Calculates the median of the given data
+	* @brief Calculates the median of the given data.
 	*
-	* @param data the data to calculate the median of
-	* @return the median
+	* @param data The data to calculate the median of.
+	* @return The median.
 	*/
 	fvalue median(std::vector<fvalue> data);
 
 	/**
-	* @brief Calculates the median of the given data
+	* @brief Calculates the median of the given data.
 	*
-	* @param data the data to calculate the median of
-	* @return the median
+	* @param data The data to calculate the median of.
+	* @return The median.
 	*/
 	std::complex<fvalue> median(const std::vector<eis::DataPoint>& data);
 
 	/**
-	* @brief Resamples the data to the given amount of points
+	* @brief Resamples the data to the given amount of points.
 	*
-	* @param data data to resample
-	* @param outputSize size to resample to
-	* @return the resampled data
+	* @param data Data to resample.
+	* @param outputSize Size to resample to.
+	* @return The resampled data.
 	*/
 	std::vector<eis::DataPoint> rescale(const std::vector<eis::DataPoint>& data, size_t outputSize);
 
 	/**
-	* @brief Calculates the Pearson correlation between the imaginary and the real part of the data
+	* @brief Calculates the Pearson correlation between the imaginary and the real part of the data.
 	*
-	* @param data data to calculate the Pearson correlation on
-	* @return the Pearson correlation coefficient
+	* @param data Data to calculate the Pearson correlation on.
+	* @return the Pearson correlation coefficient.
 	*/
 	fvalue pearsonCorrelation(const std::vector<eis::DataPoint>& data);
 
 	/**
-	* @brief Calculates the variance of the distance of the data from a centroid in the nyquist plane
+	* @brief Calculates the variance of the distance of the data from a centroid in the nyquist plane.
 	*
-	* @param data the data to calculate on
-	* @param centroid the centroid to use, if nullptr is passed here, the mean of the data will be used as the centroid
-	* @return the Pearson correlation coefficient
+	* @param data The data to calculate on.
+	* @param centroid The centroid to use, if nullptr is passed here, the mean of the data will be used as the centroid.
+	* @return The Pearson correlation coefficient.
 	*/
 	fvalue nyquistAreaVariance(const std::vector<eis::DataPoint>& data, eis::DataPoint* centroid = nullptr);
 
 	/**
-	* @brief Finds the maximum distance between subsequent points in the data in the nyquist plane
+	* @brief Finds the maximum distance between subsequent points in the data in the nyquist plane.
 	*
-	* @param data the data to use
-	* @return the largest distance
+	* @param data The data to use.
+	* @return The largest distance.
 	*/
 	fvalue maximumNyquistJump(const std::vector<eis::DataPoint>& data);
 
 	/**
-	* @brief Adds white noise to the data
+	* @brief Adds white noise to the data.
 	*
-	* @param data the data to add noise to
-	* @param amplitude the amplitude of the noise
-	* @param relative if true the amplitude will be taken as relative to the magnitude of the data, otherwise it will be taken as an absolute value
+	* @param data The data to add noise to.
+	* @param amplitude The amplitude of the noise.
+	* @param relative If true, the amplitude will be taken as relative to the magnitude of the data, otherwise it will be taken as an absolute value.
 	*/
 	void noise(std::vector<eis::DataPoint>& data, double amplitude, bool relative);
 
 	/**
-	* @brief Removes duplicate data points form the data
-	* duplicates are detected by checking the value of omega for sameness using fvalueEq with the default ulp
+	* @brief Removes duplicate data points form the data.
+	*
+	* Duplicates are detected by checking the value of omega for sameness using fvalueEq with the default ulp.
 	*
 	* @param data the data to remove duplicates from
 	*/
 	void removeDuplicates(std::vector<eis::DataPoint>& data);
 
 	/**
-	* @brief Checks two fvalues for equality
+	* @brief Checks two fvalues for equality.
 	*
 	* Equality is considered given when the values are within ulp epsilons at the magnitude of the sum of operands.
 	*
@@ -152,15 +153,15 @@ namespace eis
 	bool fvalueEq(fvalue a, fvalue b, unsigned int ulp = 4);
 
 	/**
-	* @brief this function resamples, extrapolates and interpolates to fit the data given to the frequencies also given
+	* @brief This function resamples, extrapolates and interpolates to fit the data given to the frequencies also given.
 	*
 	* Data is resampled to the target size, interpolation for data points is performed using linear interpolation
 	* extrapolation is performed using linear or base 10 logarithmic extrapolation.
 	*
-	* @param omegas the frequencies to resample the data to
-	* @param data the data to resample
-	* @param linearExtrapolation true if linear extrapolation is to be performed, otherwise base 10 logarithmic extrapolation is used
-	* @return the resampled data
+	* @param omegas The frequencies to resample the data to.
+	* @param data The data to resample.
+	* @param linearExtrapolation true if linear extrapolation is to be performed, otherwise base 10 logarithmic extrapolation is used.
+	* @return The resampled data.
 	*/
 	std::vector<eis::DataPoint> fitToFrequencies(std::vector<fvalue> omegas,
 	                                             const std::vector<eis::DataPoint>& data,
diff --git a/eisgenerator/eistype.h b/eisgenerator/eistype.h
index 020eef1..63f227c 100644
--- a/eisgenerator/eistype.h
+++ b/eisgenerator/eistype.h
@@ -92,9 +92,9 @@ public:
 		return *this;
 	}
 	/**
-	* @brief calculates the absolute value of the complex impedance
+	* @brief Calculates the absolute value of the complex impedance.
 	*
-	* @return absolute value of the complex impedance
+	* @return The absolute value of the complex impedance.
 	*/
 	fvalue complexVectorLength() const
 	{
@@ -116,10 +116,11 @@ public:
 	bool log = false; /**< True if the elements in the range are to be spaced in log10 increments*/
 
 	/**
-	* @brief calculates the distance between elements in the range
-	* will calculate the log10 of the distance if the range is logarithmic
+	* @brief Calculates the distance between elements in the range.
 	*
-	* @return the distance between steps of this range
+	* Will calculate the log10 of the distance if the range is logarithmic.
+	*
+	* @return The linear or log distance between steps of this range.
 	*/
 	fvalue stepSize() const
 	{
@@ -129,9 +130,9 @@ public:
 	}
 
 	/**
-	* @brief calculates the value of the current step
+	* @brief Calculates the value of the current step.
 	*
-	* @return the value of the current step
+	* @return The value of the current step.
 	*/
 	fvalue stepValue() const
 	{
@@ -139,9 +140,9 @@ public:
 	}
 
 	/**
-	* @brief calculates the mean of the start and the end values
+	* @brief Calculates the mean of the start and the end values.
 	*
-	* @return the mean of the start and the end values
+	* @return The mean of the start and the end values.
 	*/
 	fvalue center() const
 	{
@@ -149,9 +150,9 @@ public:
 	}
 
 	/**
-	* @brief calculates the value at the given index
+	* @brief Calculates the value at the given index.
 	*
-	* @return the value at the given index
+	* @return The value at the given index.
 	*/
 	fvalue at(size_t index) const
 	{
@@ -185,47 +186,48 @@ public:
 	Range() = default;
 
 	/**
-	* @brief prints the range to stdout via eis::Log
+	* @brief Prints the range to stdout via eis::Log.
 	*
-	* @param level the eis::Log::Level to print at
+	* @param level The eis::Log::Level to print at.
 	*/
 	void print(int level) const;
 
 	/**
-	* @brief gets a machine parseable string encoding this range
+	* @brief Gets a machine parseable string encoding this range.
 	*
-	* @return the string
+	* @return The string.
 	*/
 	std::string getString() const;
 
 	/**
-	* @brief checks if the values of this range are sane
-	* this checks for some common errors like having a end < being
+	* @brief Checks if the values of this range are sane/
+	*
+	* This checks for some common errors like having a end < being.
 	*
-	* @return true if sane, false if not
+	* @return true if sane, false if not.
 	*/
 	bool isSane() const;
 
 	/**
-	* @brief this function constructs a vector that contains all elements of this range
+	* @brief This function constructs a vector that contains all elements of this range.
 	*
-	* @return the vector with the elements of this range
+	* @return The vector with the elements of this range.
 	*/
 	std::vector<fvalue> getRangeVector() const;
 
 	/**
-	* @brief this function creates a range from the parseable string
+	* @brief This function creates a range from the parseable string.
 	*
-	* @throw std::invalid_argument when the string syntax is incorrect
-	* @return the range that was parsed from the string
+	* @throw std::invalid_argument when the string syntax is incorrect.
+	* @return The range that was parsed from the string.
 	*/
 	[[nodiscard]] static Range fromString(std::string str, size_t count);
 
 	/**
-	* @brief this function creates a vector ranges from the parseable parameter array string
+	* @brief This function creates a vector ranges from the parseable parameter array string.
 	*
 	* @throw std::invalid_argument when the string syntax is incorrect
-	* @return the vector of ranges that was parsed from the string
+	* @return The vector of ranges that was parsed from the string.
 	*/
 	[[nodiscard]] static std::vector<Range> rangesFromParamString(const std::string& paramStr, size_t count);
 };
@@ -271,193 +273,204 @@ public:
 
 public:
 	/**
-	* @brief Constructs a EisSpectra
+	* @brief Constructs an EisSpectra.
 	*
-	* @param data vector of the data points of the spectra
-	* @param model model description string for this spectra
-	* @param header a free-form text that will be included in any save of this spectra
-	* @param labels an optional vector of giving the values of the inputs of the model to get this spectra
-	* @param labelNames an optional vector of names describing every input of the model
+	* @param data Vector of the data points of the spectra.
+	* @param model Model description string for this spectra.
+	* @param header A free-form text that will be included in any save of this spectra.
+	* @param labels An optional vector of giving the values of the inputs of the model to get this spectra.
+	* @param labelNames An optional vector of names describing every input of the model.
 	*/
 	EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header,
 			   std::vector<double> labels = std::vector<double>(),
 			   std::vector<std::string> labelNames = std::vector<std::string>());
 
 	/**
-	* @brief Constructs a EisSpectra
-	* this function differs from the above only in the datatype of the label
-	*
-	* @param data vector of the data points of the spectra
-	* @param model model description string for this spectra
-	* @param header a free-form text that will be included in any save of this spectra
-	* @param labels an optional vector of giving the values of the inputs of the model to get this spectra
-	* @param labelNames an optional vector of names describing every input of the model
+	* @brief Constructs an EisSpectra.
+	*
+	* This function differs from the above only in the datatype of the label.
+	*
+	* @param data Vector of the data points of the spectra.
+	* @param model Model description string for this spectra.
+	* @param header A free-form text that will be included in any save of this spectra.
+	* @param labels An optional vector of giving the values of the inputs of the model to get this spectra.
+	* @param labelNames An optional vector of names describing every input of the model.
 	*/
 	EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header,
 			   std::vector<float> labels, std::vector<std::string> labelNames = std::vector<std::string>());
 
 	/**
-	* @brief Constructs a EisSpectra
-	* this function differs from the above only in the datatype of the label
-	*
-	* @param data vector of the data points of the spectra
-	* @param model model description string for this spectra
-	* @param header a free-from text that will be included in any save of this spectra
-	* @param labels an optional vector of giving the values of the inputs of the model to get this spectra
-	* @param labelNames an optional vector of names describing every input of the model
+	* @brief Constructs an EisSpectra.
+	*
+	* This function differs from the above only in the datatype of the label.
+	*
+	* @param data Vector of the data points of the spectra.
+	* @param model Model description string for this spectra.
+	* @param header A free-from text that will be included in any save of this spectra.
+	* @param labels An optional vector of giving the values of the inputs of the model to get this spectra.
+	* @param labelNames An optional vector of names describing every input of the model.
 	*/
 	EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header,
 			   std::vector<size_t> labels, std::vector<std::string> labelNames = std::vector<std::string>());
 
 	/**
-	* @brief Constructs a EisSpectra
-	* this function differs from the above only in the datatype of the label
-	*
-	* @param data vector of the data points of the spectra
-	* @param model model description string for this spectra
-	* @param header a free-form text that will be included in any save of this spectra
-	* @param label a value corresponding to all inputs of the model
-	* @param maxLabel the number of inputs of the model
+	* @brief Constructs an EisSpectra.
+	*
+	* This function differs from the above only in the datatype of the label.
+	*
+	* @param data Vector of the data points of the spectra.
+	* @param model Model description string for this spectra.
+	* @param header A free-form text that will be included in any save of this spectra.
+	* @param label A value corresponding to all inputs of the model.
+	* @param maxLabel The number of inputs of the model.
 	*/
 	EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header,
 			   size_t label, size_t maxLabel, std::vector<std::string> labelNames = std::vector<std::string>());
 
 	/**
-	* @brief Constructs a EisSpectra by loading a EIS file from disk
+	* @brief Constructs a EisSpectra by loading an EIS file from disk.
 	*
 	* @throw eis::file_error if there is an error loading the file
-	* @param path the path to the file
+	* @param path The path to the file.
 	*/
 	EisSpectra(const std::filesystem::path& path){*this = loadFromDisk(path);}
 
 	EisSpectra(){}
 
 	/**
-	* @brief Constructs a EisSpectra by loading a EIS file from disk
+	* @brief Constructs a EisSpectra by loading a EIS file from disk.
+	*
+	* This function has the attribute [[nodiscard]]
 	*
 	* @throw eis::file_error if there is an error loading the file
-	* @param path the path to the file
-	* @return the EisSpectra
+	* @param path The path to the file.
+	* @return The EisSpectra parsed from the file.
 	*/
 	[[nodiscard]] static EisSpectra loadFromDisk(const std::filesystem::path& path);
 
 	/**
-	* @brief Constructs a EisSpectra by loading a EIS file from a stream
+	* @brief Constructs a EisSpectra by loading a EIS file from a stream.
+	*
+	* This function has the attribute [[nodiscard]]
 	*
 	* @throw eis::file_error if there is an error loading the file
-	* @param stream the stream that contains the EIS file
-	* @return the EisSpectra
+	* @param stream The stream that contains the EIS file.
+	* @return The EisSpectra parsed from the stream.
 	*/
 	[[nodiscard]] static EisSpectra loadFromStream(std::istream& stream);
 
 	/**
-	* @brief Constructs a EisSpectra by loading a EIS file from a stream
+	* @brief Sets all input values up to a maximum given by maxLabel to the value given by label.
 	*
-	* @param stream the stream that contains the EIS file
-	* @return the EisSpectra
+	* @param label The value to apply to all inputs.
+	* @param maxLabel The maximum number of values to set.
 	*/
 	void setLabel(size_t label, size_t maxLabel);
 
 	/**
-	* @brief Gets the input value of this model, where it is a single value
+	* @brief Gets the input value of this model, where it is a single value.
 	*
-	* @return the input value
+	* @return The input value,
 	*/
 	size_t getLabel();
 
 	/**
-	* @brief Sets the input values of this model
+	* @brief Sets the input values of this model.
 	*
-	* @param label the input values
+	* @param label The input values.
 	*/
 	void setSzLabels(std::vector<size_t> label);
 
 	/**
-	* @brief Sets the input values of this model
+	* @brief Sets the input values of this model.
 	*
-	* @param label the input values
+	* @param label The input values.
 	*/
 	void setLabels(const std::vector<double>& labelsIn);
 
 	/**
-	* @brief Sets the input values of this model
+	* @brief Sets the input values of this model.
 	*
-	* @param label the input values
+	* @param label The input values.
 	*/
 	void setLabels(const std::vector<float>& labelsIn);
 
 	/**
-	* @brief Sets the input values of this model
+	* @brief Sets the input values of this model.
 	*
-	* @param label the input values
+	* @param label The input values.
 	*/
 	std::vector<size_t> getSzLabels() const;
 
 	/**
-	* @brief Returns true if there are multiple inputs, false otherwise
+	* @brief Returns true if there are multiple inputs, false otherwise.
 	*
-	* @return true if there are multiple inputs, false otherwise
+	* @return true if there are multiple inputs, false otherwise.
 	*/
 	bool isMulticlass();
 
 	/**
-	* @brief Returns the inputs as a vector
+	* @brief Returns the inputs as a vector.
 	*
-	* @return the inputs as a vector
+	* @return The inputs as a vector.
 	*/
 	std::vector<fvalue> getFvalueLabels();
 
 	/**
-	* @brief Saves the spectra to disk
+	* @brief Saves the spectra to disk.
 	*
-	* @param path a path to the file on disk where the spectra shall be saved
-	* @return true on success, false on failure
+	* @param path A path to the file on disk where the spectra shall be saved.
+	* @return true on success, false on failure.
 	*/
 	bool saveToDisk(const std::filesystem::path& path) const;
 
 	/**
-	 * @brief Saves the spectra in the given stream
+	 * @brief Saves the spectra in the given stream.
 	 *
-	 * @param stream a std::ostream into which the spectra will be saved
+	 * @param stream A std::ostream into which the spectra will be saved.
 	 */
 	void saveToStream(std::ostream& stream) const;
 };
 
 /**
- * @brief deprecated function use eis::EisSpectra::saveToDisk instead
+ * @brief Deprecated function use eis::EisSpectra::saveToDisk instead.
  */
 [[deprecated]] bool saveToDisk(const EisSpectra& data, const std::filesystem::path& path);
 
 /**
- * @brief deprecated function use eis::EisSpectra::loadFromDisk instead
+ * @brief Deprecated function use eis::EisSpectra::loadFromDisk instead.
  */
 [[deprecated]] [[nodiscard]] EisSpectra loadFromDisk(const std::filesystem::path& path);
 
 /**
-* @brief Returns the a vector of DataPoints as a pair of valarrays
+* @brief Returns the a vector of DataPoints as a pair of valarrays.
 *
-* @return a pair of valarrays first the real part and second the imaginary part
+* @return A pair of valarrays first the real part and second the imaginary part.
 */
 std::pair<std::valarray<fvalue>, std::valarray<fvalue>> eisToValarrays(const std::vector<eis::DataPoint>& b);
 
 /**
-* @brief Returns the mean l2 element wise distance of he given spectra
+* @brief Returns the mean l2 element wise distance of he given spectra.
+*
+* This function will be moved to the math API in the future.
 *
-* @param a the first set of points
-* @param b the second set of points, must be the same length as a
-* @return the mean l2 distance
+* @param a The first set of points.
+* @param b The second set of points, must be the same length as a.
+* @return The mean l2 distance.
 */
 fvalue eisDistance(const std::vector<eis::DataPoint>& a, const std::vector<eis::DataPoint>& b);
 
 
 /**
-* @brief Returns the mean distance of the points in a to the linearly interpolated nyquist curve of b
+* @brief Returns the mean distance of the points in a to the linearly interpolated nyquist curve of b.
+*
+* This function will be moved to the math API in the future.
 *
-* This implementation is quite slow
+* This implementation is quite slow.
 *
-* @param a the first set of points
-* @param b the second set of points
-* @return the mean nyquist distance
+* @param a The first set of points.
+* @param b The second set of points.
+* @return The mean nyquist distance.
 */
 fvalue eisNyquistDistance(const std::vector<eis::DataPoint>& a, const std::vector<eis::DataPoint>& b);
 
diff --git a/eisgenerator/log.h b/eisgenerator/log.h
index 940a601..0da4594 100644
--- a/eisgenerator/log.h
+++ b/eisgenerator/log.h
@@ -25,16 +25,22 @@
 namespace eis
 {
 
+/**
+* Various math functions performed on eisgenerator types
+* @defgroup LOG Log
+* @{
+*/
+
 class Log 
 {
 public:
 	
 	enum Level
 	{
-		DEBUG,
-		INFO,
-		WARN,
-		ERROR
+		DEBUG, /**< Messages useful for debugging */
+		INFO,  /**< Messages of intrest to the user incl. progress */
+		WARN,  /**< Non fatal errors or problems affecting performance or numeric precision  */
+		ERROR  /**< Fatal errors  */
 	};
 
 private:
@@ -46,11 +52,23 @@ private:
 	
 public:
 
-	static bool headers;
-	static Level level;
+	static bool headers; /**< If true output will be prefixed with a header detailing the origin of the message */
+	static Level level;  /**< Minimum Level required for output to be printed */
 
 	Log() {}
-	Log(Level type, bool endlineI = true);
+	/**
+	* @brief Constructor
+	*
+	* This Constructor is to be used like a global stream. Thus if logging is desired
+	* the user of this api shal use Log(DEBUG)<<"This is a debugging meesage";
+	* Using this constructor to create a lvalue has some negative side effects such
+	* as: Possibly holding a global lock for the lifetime of the object and potenttaly
+	* unintuative newline behavior.
+	*
+	* @param type The Level to use for this message.
+	* @param endline If true an UNIX newline '\n' will be emmited when the oject is destroyed
+	*/
+	Log(Level type, bool endline = true);
 	~Log();
 	
 	template<class T> Log &operator<<(const T &msg) 
@@ -64,4 +82,6 @@ public:
 	}
 };
 
+/** @} */
+
 }
diff --git a/eisgenerator/model.h b/eisgenerator/model.h
index e9fde88..f4f4541 100644
--- a/eisgenerator/model.h
+++ b/eisgenerator/model.h
@@ -41,7 +41,7 @@ struct CompiledObject;
 */
 
 /**
-* @brief The main class of eisgenerator representing a equivalent circuit model
+* @brief The main class of eisgenerator representing a equivalent circuit model.
 */
 class Model
 {
@@ -69,10 +69,10 @@ public:
 	/**
 	* @brief Constructor
 	*
-	* @throws parse_errror
-	* @param str the model string to create a model object for
-	* @param paramSweepCount optionally the number of sweep point to use for parameter sweeps
-	* @param defaultToRange optionally a bool that if true, circuit elements not given in str are defaulted to a range instead of a fixed value
+	* @throws parse_errror If the model string or its parameters include invalid syntax.
+	* @param str The model string to create a model object for.
+	* @param paramSweepCount Optionally the number of sweep point to use for parameter sweeps.
+	* @param defaultToRange Optionally a bool that if true, circuit elements not given in str are defaulted to a range instead of a fixed value.
 	*/
 	Model(const std::string& str, size_t paramSweepCount = 100, bool defaultToRange = true);
 	Model(const Model& in);
@@ -80,121 +80,129 @@ public:
 	~Model();
 
 	/**
-	* @brief Adjusts the sweep count so that the total of spectra that need to be generated in the parameter sweep is close to the given value
+	* @brief Adjusts the sweep count so that the total of spectra that need to be generated in the parameter sweep is close to the given value.
 	*
-	* @param totalCount the total number of spectra to target
-	* @return the number of spectra that will be generated by a parameter sweep after calling this function, should be close to, but may not be exactly totalCount
+	* @param totalCount The total number of spectra to target.
+	* @return The number of spectra that will be generated by a parameter sweep after calling this function, should be close to, but may not be exactly, totalCount.
 	*/
 	size_t setParamSweepCountClosestTotal(size_t totalCount);
 
 	/**
-	* @brief Gets the impedance at the given frequency
-	* this method calls resolveSteps
+	* @brief Gets the impedance at the given frequency.
 	*
-	* @param omega the frequency in rad/s to calculate the impedance at
-	* @param index an optional index to the parameter sweep step at which to calculate the impedance
-	* @return a DataPoint struct containing the result
+	* This method calls resolveSteps.
+	*
+	* @param omega The frequency in rad/s to calculate the impedance at.
+	* @param index An optional index to the parameter sweep step at which to calculate the impedance.
+	* @return A DataPoint struct containing the result.
 	*/
 	DataPoint execute(fvalue omaga, size_t index = 0);
 
 	/**
-	* @brief Executes a frequency sweep along the given range
-	* this method calls resolveSteps
+	* @brief Executes a frequency sweep along the given range.
+	*
+	* This method calls resolveSteps.
 	*
-	* @param omega the range along which to execute a frequency sweep
-	* @param index an optional index to the parameter sweep step at which to calculate the impedance
-	* @return a vector of DataPoint structs containing the impedance at every frequency in the sweep
+	* @param omega The range along which to execute a frequency sweep.
+	* @param index An optional index to the parameter sweep step at which to calculate the impedance.
+	* @return A vector of DataPoint structs containing the impedance at every frequency in the sweep.
 	*/
 	std::vector<DataPoint> executeSweep(const Range& omega, size_t index = 0);
 
 	/**
-	* @brief Executes a frequency sweep with the given omega values
+	* @brief Executes a frequency sweep with the given omega values.
 	*
-	* @param omega a vector of frequencies in rad/s to calculate the impedance at
-	* @param index an optional index to the parameter sweep step at which to calculate the impedance
-	* @return a vector of DataPoint structs containing the impedance at every frequency in the sweep
+	* @param omega A vector of frequencies in rad/s to calculate the impedance at.
+	* @param index An optional index to the parameter sweep step at which to calculate the impedance.
+	* @return A vector of DataPoint structs containing the impedance at every frequency in the sweep.
 	*/
 	std::vector<DataPoint> executeSweep(const std::vector<fvalue>& omega, size_t index = 0);
 
 	/**
-	* @brief Executes a frequency sweep with the given omega values for each parameter combination in the applied parameter sweep
-	* this method calls resolveSteps
+	* @brief Executes a frequency sweep with the given omega values for each parameter combination in the applied parameter sweep.
+	*
+	* This method calls resolveSteps.
 	*
-	* @param omega the range along which to execute a frequency sweep
-	* @return a vector of vectors of DataPoint structs containing the impedance at every frequency in the sweep with every parameter combination
+	* @param omega The range along which to execute a frequency sweep.
+	* @return A vector of vectors of DataPoint structs containing the impedance at every frequency in the sweep with every parameter combination.
 	*/
 	std::vector<std::vector<DataPoint>> executeAllSweeps(const Range& omega);
 
 	/**
-	* @brief Returns the model string corresponding to this model object, without embedded parameters
+	* @brief Returns the model string corresponding to this model object, without embedded parameters.
 	*
-	* @return the model string corresponding to this model object, without embedded parameters
+	* @return The model string corresponding to this model object, without embedded parameters.
 	*/
 	std::string getModelStr() const;
 
 	/**
 	* @brief Returns the model string corresponding to this model object, with embedded parameters
-	* this method calls resolveSteps
 	*
-	* @param index the parameter sweep index for which to embed the parameters
-	* @return the model string corresponding to this model object, with embedded parameters
+	* This method calls resolveSteps.
+	*
+	* @param index The parameter sweep index for which to embed the parameters.
+	* @return The model string corresponding to this model object, with embedded parameters.
 	*/
 	std::string getModelStrWithParam(size_t index);
 
 	/**
-	* @brief Returns the model string corresponding to this model object, with embedded parameters
-	* the parameter sweep index of the last call to resolveSteps or 0 is used
+	* @brief Returns the model string corresponding to this model object, with embedded parameters.
+	*
+	* Yhe parameter sweep index of the last call to resolveSteps or 0 is used.
 	*
 	* @return the model string corresponding to this model object, with embedded parameters
 	*/
 	std::string getModelStrWithParam() const;
 
 	/**
-	* @brief Returns a unique id that is unique for this circuit, but not for this object specifically
-
-	* @return the uid
+	* @brief Returns a unique id.
+	*
+	* This id is only unique for the given circuit description string, not for this object as sutch.
+	*
+	* @return The uid.
 	*/
 	size_t getUuid();
 
 	/**
-	* @brief Returns a vector of pointers to the circuit elements in this model
-	* the pointers can only be assumed to be valid until the next member call to this model object
+	* @brief Returns a vector of pointers to the circuit elements in this model.
+	*
+	* The pointers can only be assumed to be valid until the next non-const member call to this model object.
 	*
-	* @param model for internal use only
-	* @return a vector of the circuit elements in the model
+	* @param model For internal use only.
+	* @return A vector of the circuit elements in the model.
 	*/
 	std::vector<Componant*> getFlatComponants(Componant *model = nullptr);
 
 	/**
-	* @brief gets the values of the parameters of the circuit elements at the current parameter sweep step
+	* @brief Gets the values of the parameters of the circuit elements at the current parameter sweep step.
 	*
-	* @return the values of the parameters of the circuit elements at the current parameter sweep step
+	* @return The values of the parameters of the circuit elements at the current parameter sweep step.
 	*/
 	std::vector<fvalue> getFlatParameters();
 
 	/**
-	* @brief gets the ranges of the parameters of the circuit elements
+	* @brief Gets the ranges of the parameters of the circuit elements.
 	*
-	* @return the ranges of the parameters of the circuit elements
+	* @return The ranges of the parameters of the circuit elements.
 	*/
 	std::vector<Range> getFlatParameterRanges();
 
 	/**
-	* @brief gets the default ranges of the parameters of each type of circuit element used in the model
+	* @brief Gets the default ranges of the parameters of each type of circuit element used in the model.
 	*
-	* @return the default ranges of the parameters of each type of circuit element used in the model
+	* @return The default ranges of the parameters of each type of circuit element used in the model.
 	*/
 	std::vector<Range> getDefaultParameters();
 
 	/**
-	* @brief gets the total number of parameters used by all the circuit elements in this model
+	* @brief Gets the total number of parameters used by all the circuit elements in this model.
 	*
-	* @return the total number of parameters
+	* @return The total number of parameters.
 	*/
 	size_t getParameterCount();
 
 	/**
-	* @brief this function compiles the model into native vectorized code for faster execution
+	* @brief This function compiles the model into native vectorized code for faster execution.
 	*
 	* This function compiles a shared-object for this model that is then loaded by eisgenerator to
 	* speed up execution of this model by a factor of 10 or more by employing vectorization and avoiding
@@ -206,81 +214,82 @@ public:
 	* This function is only implemented on UNIX, on other platforms this function will always return false.
 	* This function also requires that GCC be available in PATH.
 	*
-	* @return true if compile was successful, false otherwise
+	* @return true if compile was successful, false otherwise.
 	*/
 	bool compile();
 
 	/**
-	* @brief this member determines if the model is in a state ready to execute
+	* @brief This member determines if the model is in a state ready to execute.
 	*
-	* @return true if the model is ready for the execute* family of methods
+	* @return True if the model is ready for the execute family of methods.
 	*/
 	bool isReady();
 
 	/**
-	* @brief this member resolves the parameters of all circuit elements at the given parameter sweep step
+	* @brief This member resolves the parameters of all circuit elements at the given parameter sweep step.
 	*
-	* @param index the index to the sweep step to resolve to
+	* @param index The index to the sweep step to resolve to.
 	*/
 	void resolveSteps(int64_t index);
 
 	/**
-	* @brief gets the total number of parameter sweep steps for the applied sweep
+	* @brief Gets the total number of parameter sweep steps for the applied sweep.
 	*
-	* @return the total number of parameter sweep steps for the applied sweep
+	* @return The total number of parameter sweep steps for the applied sweep.
 	*/
 	size_t getRequiredStepsForSweeps();
 
 	/**
-	* @brief checks if the model is a sweep (i.e. has at least one parameter with a range)
+	* @brief Checks if the model is a sweep (i.e. has at least one parameter with a range).
 	*
-	* @return true if the model contains a parameter sweep, false otherwise
+	* @return True if the model contains a parameter sweep, false otherwise.
 	*/
 	bool isParamSweep();
 
 	/**
-	* @brief compiles this model into efficient c++ code corresponding to the circuit of this model
+	* @brief Compiles this model into efficient c++ code corresponding to the circuit of this model.
 	*
-	* @return the code or an empty string if compilation was unsuccessfully
+	* @return The code or an empty string if compilation was unsuccessfully.
 	*/
 	std::string getCode();
 
 	/**
-	* @brief compiles this model into TorchScript
-	* to be compiled by torch::jit::compile
+	* @brief Compiles this model into TorchScript
+	*
+	* Can be compiled to GPU kernel executeing bytecode by torch::jit::compile.
 	*
-	* @return the TorchScript code or an empty string if compilation was unsuccessful
+	* @return Yhe TorchScript code or an empty string if compilation was unsuccessful.
 	*/
 	std::string getTorchScript();
 
 	/**
-	* @brief Gets the function name in the code for this model
+	* @brief Gets the function name in the code for this model.
 	*
-	* @return the function name in the code for this model
+	* @return The function name in the code for this model.
 	*/
 	std::string getCompiledFunctionName();
 
 	/**
-	* @brief Gets the function name in the code returned by getTorchScript and getCode for this model
+	* @brief Gets the function name in the code returned by getTorchScript and getCode for this model.
 	*
-	* @return the function name in the code for this model
+	* @return The function name in the code for this model.
 	*/
 	std::vector<size_t> getRecommendedParamIndices(eis::Range omegaRange, double distance, bool threaded = false);
 };
 
 /**
  *  @example simple.cpp
- *  A simple example in how to use eisgenerator
+ *  A simple example in how to use eisgenerator.
  */
 
 /**
  *  @example compileing.cpp
- *  An example on how to use the eisgenerator compiled execution model
+ *  An example on how to use the eisgenerator compiled execution model.
  */
 
 /**
  *  @example torchscript.cpp
- *  An example on how to use the eisgenerator torch execution model
+ *  An example on how to use the eisgenerator torch execution model.
  */
 
 /** @} */
diff --git a/eisgenerator/normalize.h b/eisgenerator/normalize.h
index 497ca05..e1a5281 100644
--- a/eisgenerator/normalize.h
+++ b/eisgenerator/normalize.h
@@ -30,35 +30,36 @@ namespace eis
 {
 
 /**
-Functions for normalization of spectra data
+* Functions for normalization of spectra data
 * @defgroup NORM Normalization
 * @{
 */
 
 /**
-* @brief Normalizes the data to [0,1]
+* @brief Normalizes the data to [0,1].
 *
-* @param data the data to normalize
+* @param data The data to normalize.
 */
 void normalize(std::vector<eis::DataPoint>& data);
 
 /**
-* @brief Reduces the data by removing "uninteresting"  regions
-* Uninteresting regions are determined by taking the first and second derivative and removing the areas where these change very little
+* @brief Reduces the data by removing "uninteresting"  regions.
 *
-* @param data the data to reduce
-* @return the reduced data
+* Uninteresting regions are determined by taking the first and second derivative and removing the areas where these change very little.
+*
+* @param data The data to reduce.
+* @return The reduced data.
 */
 std::vector<eis::DataPoint> reduceRegion(const std::vector<eis::DataPoint>& data, fvalue gradThreshFactor = 0.01, bool useSecondDeiv = false);
 
 /**
-* @brief Removes INF and NAN from the dataset by interpolating from neighboring points
+* @brief Removes INF and NAN from the dataset by interpolating from neighboring points.
 *
-* This function is not available when this library is compiled with fast math enabled
+* The universe implodes when function is used while this library is compiled with -ffast-math enabled.
 *
-* As a side effect, this function caps spikes to +-INF to +-10 maximally
+* As a side effect, this function caps spikes to +-INF to +-10 maximally.
 *
-* @param data the data to remove INF and NAN from
+* @param data The data to remove INF and NAN from.
 */
 void eraseSingularites(std::vector<eis::DataPoint>& data);
 
diff --git a/eisgenerator/translators.h b/eisgenerator/translators.h
index 464d98f..6c7d03f 100644
--- a/eisgenerator/translators.h
+++ b/eisgenerator/translators.h
@@ -34,10 +34,10 @@ namespace eis
 */
 
 /**
-* @brief Translates a model string for RHD instruments RelaxIS to the format used by eisgenerator
+* @brief Translates a model string for RHD instruments RelaxIS to the format used by eisgenerator,
 *
-* @throws parse_errror
-* @param in the RelaxIS model string
+* @throws parse_errror if the given string contains syntax errors
+* @param in The RelaxIS model string.
 * @param params an optional vector of the parameters of the circuit elements
 * @return the eisgenerator model string
 */
@@ -49,58 +49,58 @@ std::string relaxisToEis(const std::string& in, const std::vector<double>& param
 * Note that any parameters embedded into the eisgenerator model string will be striped and
 * not included in the RelaxIS model.
 *
-* @throws parse_errror
-* @param in the eisgenerator model string
-* @return the RelaxIS model string
+* @throws parse_errror if the given string contains syntax errors
+* @param in The eisgenerator model string.
+* @return The RelaxIS model string.
 */
 std::string eisToRelaxis(const std::string& in);
 
 /**
 * @brief Translates a Boukamp Circuit Description Code (CDC) string into the format used by this library
 *
-* @throws parse_errror
-* @param in the CDC string
-* @return the eisgenerator model string
+* @throws parse_errror if the given string contains syntax errors
+* @param in The CDC string.
+* @return The eisgenerator model string.
 */
 std::string cdcToEis(std::string in);
 
 /**
-* @brief Translates a string for this library a Boukamp Circuit Description Code (CDC)
+* @brief Translates a string for this library a Boukamp Circuit Description Code (CDC).
 *
 * Note that any parameters embedded into the eisgenerator model string will be striped and
 * not included in the CDC.
 *
-* @throws parse_errror
-* @param in the eisgenerator model string
-* @return the CDC string
+* @throws parse_errror if the given string contains syntax errors
+* @param in The eisgenerator model string.
+* @return The CDC string.
 */
 std::string eisToCdc(const std::string& in);
 
 /**
-* @brief Translates a model description string as used by the MADAP library into the format used by this library
+* @brief Translates a model description string as used by the MADAP library into the format used by this library.
 
-* @param in a model description string as used by the MADAP library
-* @param parameters optionally a string containing the parameters of the model in MADAP parameter format
-* @return the eisgenerator model string optionally including embedded parameters
+* @param in A model description string as used by the MADAP library.
+* @param parameters Optionally a string containing the parameters of the model in MADAP parameter format.
+* @return The eisgenerator model string optionally including embedded parameters.
 */
 std::string madapToEis(const std::string& in, const std::string& parameters = "");
 
 /**
-* @brief Translates a string for this library a into the format used by the MADAP library
+* @brief Translates a string for this library a into the format used by the MADAP library.
 *
 * Note that any parameters embedded into the eisgenerator model string will be striped and
 * not included in the MADAP string.
 *
-* @throws parse_errror
-* @param in the eisgenerator model string
-* @return the MADAP string
+* @throws parse_errror If the given string contains syntax errors.
+* @param in The eisgenerator model string.
+* @return The MADAP string.
 */
 std::string eisToMadap(std::string in);
 
 /**
-* @brief Given a eisgenerator model description string, this function will purge all the embedded parameters
+* @brief Given a eisgenerator model description string, this function will purge all the embedded parameters.
 *
-* @param in an eisgenerator model string
+* @param in An eisgenerator model string.
 */
 void purgeEisParamBrackets(std::string& in);
 
-- 
GitLab