\begin{abstract}
	This article introduces a generalization of  the discrete optimal transport, with applications to color image manipulations. This new formulation includes a relaxation of the mass conservation constraint and a regularization term.  These two features are crucial for image processing tasks, which necessitate to take into account families of multimodal histograms, with large mass variation across modes.
	 The corresponding relaxed and regularized transportation problem is the solution of a convex optimization problem. Depending on the regularization used, this minimization can be solved using standard linear programming methods or first order proximal splitting schemes.
	 The resulting transportation plan can be used as a color transfer map, which is robust to mass variation across image color palettes. Furthermore, the regularization of the transport plan helps remove colorization artifacts due to noise amplification.
	We also extend this framework to compute the barycenter of distributions. The barycenter is the solution of an optimization problem, which is separately convex with respect to the barycenter and the transportation plans, but not jointly convex. A block coordinate descent scheme converges to a stationary point of the energy. We show that the resulting algorithm can be used for color normalization across several images. The relaxed and regularized barycenter defines a common color palette for those images. Applying color transfer toward this average palette performs a color normalization of the input images.
\end{abstract}

\begin{keywords}Optimal Transport, color transfer, variational regularization, convex optimization, proximal splitting, manifold learning.\end{keywords}

\begin{AMS}90C25, 68U10\end{AMS}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Introduction}

A large class of image processing problems involves probability densities estimated from local or global image features. In contrast to most distances from information theory (e.g. the Kullback-Leibler divergence), optimal transport (OT) takes into account the spatial location of the density modes~\cite{Villani03}. Furthermore, it also provides as a by-product a warping (the so-called transport plan) between the densities. This plan can be used to perform image modifications such as color transfer. However, an important flaw of this OT plan is that it is in general highly irregular, thus introducing unwanted artifacts in the modified images. In this article, we propose a variational formalism to relax and regularize the transport. This novel regularized OT improves visually the results for color image modifications.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Color Normalization and Color Transfer}

The problem of imposing some histogram on an image has been tackled since the beginning of image processing. Classic problems are histogram equalization or histogram specification (see for example~\cite{Gonzalez:2001}). Given two images, the goal of color transfer is to impose on one of the images the histogram of the other one. An approach to color transfer based on matching statistical properties (mean and covariance) is proposed by Reinhard et al.~\cite{Reinhard01} for the $\ell\al\beta$ color space, and generalized by Xiao and Ma~\cite{Xiao:2006} to any color space. Wang and Huang~\cite{WangH04} use similar ideas to generate a sequence of the same image with a changing histogram.  Morovic and Sun~\cite{Morovic03} and Delon~\cite{Delon04} show that histogram transfer is directly related to the OT problem.

A special case of color transfer is color normalization where the goal is to impose the same histogram, normally some ``average'' histogram, on a set of different images. An application for the color balancing of videos is proposed by Delon~\cite{Delon:2006} to correct flickering in old movies. In the context of canceling illumination, this problem is also known as color constancy and it has been thoroughly studied by Land and McCann who propose the Retinex theory (see~\cite{Land:71} and~\cite{Amestoy09} for a modern formulation). Canceling the illumination of a scene is an important component in the computer vision pipeline, and it is regularly used as a preprocessing to register/compare several images taken with different cameras or illumination conditions, as a preprocessing before registration, see~\cite{Csink98} for instance.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Optimal Transport and Imaging}
\label{subsec-ot-imaging}

%%
\paragraph{Discrete optimal transport}

The discrete OT is the solution of a convex linear program originally introduced by Kantorovitch~\cite{Kantorovitch-OT}. It corresponds to the convex relaxation of a combinatorial problem when the densities are sums of the same number of Dirac masses. This relaxation is tight (i.e. the solution of the linear program is an assignment) and it extends the notion of OT to an arbitrary sum of weighted Diracs, see for instance~\cite{Villani03}. Although there exist dedicated linear solvers (transportation simplex~\cite{Dantzig-Book}) and combinatorial algorithms (such as the Hungarian~\cite{Kuhn-hungarian} and auction algorithms~\cite{Bertsekas1988}), computing OT is still a challenging task for densities composed of thousands of Dirac masses.

%%
\paragraph{Optimal transport and its associated distance}

The OT distance (also known as the Wasserstein distance or the Earth Mover distance) has been shown to produce state of the art results for the comparison of statistical descriptors, see for instance~\cite{Rubner98}. Image retrieval performance as well as computational time are both greatly improved by using non-convex cost functions, see~\cite{Pele-ICCV}.

Another line of applications of OT makes use of the transport plan to warp an input density onto another. OT is strongly connected to fluid dynamic partial differential equations~\cite{Benamou00}. These connections have been used to perform image registration~\cite{haker-ijcv}.  The estimation of the transport plan is also an interesting way of tackling  the challenging problem of color transfer between images, see for instance~\cite{Reinhard01,Morovic03,McCollum07}. For grayscale images, the usual histogram equalization algorithm corresponds to the application of the 1-D OT plan to an image, see for instance~\cite{Delon04}. It thus makes sense to consider the 3-D OT as a mathematically-sound way to perform color palette transfer, see for instance~\cite{Pitie07} for an approximate transport method. When doing so, it is important to cope with variations in the modes of the color palette across images, which makes the mass conservation constraint of OT problematic. A workaround is to consider parametric densities such as Gaussian mixtures and defines ad-hoc matching between the components of the mixture, see~\cite{Tai-cvpr-colortransfer}. In our work, we tackle this issue by defining a novel notion of OT well adapted to color manipulation.

%%
\paragraph{Optimal transport barycenter}

It is natural to extend the classical barycenter of points to barycenter of densities by minimizing a weighted sum of OT distances toward a family of input distributions. In the special case of two input distributions, this corresponds to the celebrated displacement interpolation defined by McCann~\cite{mccann1997convexity}. Existence and uniqueness of such a barycenter is proved by Agueh and Carlier~\cite{Carlier_wasserstein_barycenter}, which also show the equivalence with the multi-marginal transportation problem introduced by Gangbo and {\'S}wi\c{e}ch~\cite{gangbo1998optimal}.  Displacement interpolation (i.e. barycenter between a pair of distributions) is used by Bonneel et al.~\cite{Bonneel-displacement} for computer graphics applications.  Rabin et al.~\cite{Rabin_ssvm11} apply this OT barycenter for texture synthesis and mixing. The image mixing is achieved by computing OT barycenters of empirical distributions of wavelet coefficients.  A similar approach is proposed by Ferradans et al.~\cite{2013-ssvm-mixing} for static and dynamic texture mixing using Gaussian distributions. \\

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Regularized and relaxed transport}
\label{subsec-regul-intro}

% Another kind of artifacts can nevertheless be still observed with these last approaches. Pixels that were originally close in the color space can be very different after the color transfer. Generalizing the Optimal Transport framework with regularity priors on the transport map would therefore be a good solution in this case. Few theoretical results exist on the regularity of the transport map \cite{}, and no satisfying non combinatorial algorithms have been proposed up to our knowledge.

%%
\paragraph{Removing transport artifacts}

The OT map between complicated densities is usually irregular. Using directly this transport plan to perform color transfer creates artifacts and amplifies the noise in flat areas of the image. Since the transfer is computed over the 3-D color space, it does not take into account the pixel-domain regularity of the image. The visual quality of the transfer is thus improved by denoising the resulting transport using a pixel-domain regularization either as a post-processing~\cite{Papadakis_ip11} or by solving a variational problem~\cite{Papadakis_ip11,Rabin_icip11}.

% The perfect transfer of color is not satisfying in real applications and one may generally observe outliers in the final images. Indeed, as the transfer is realized in the color space, it does not take into account the fact that coherent colors should be transferred to neighbor pixels. As a consequence, methods have been proposed to consider the spatial nature of images and model some regularity priors on the image domain. In \cite{Papadakis_ip11}, the color transfer is formalized as an energy minimization problem in the image domain, which allows directly incorporating spatial regularization of the colors. The energy then involves the $L_2$ distance between cumulated color histograms instead of relying on the Wasserstein distance. The post-regularization of the  image color has also been proposed in \cite{Rabin_ip11}, where the color transfer is realized with the Sliced Wasserstein Distance.

%%
\paragraph{Transport regularization}

A more theoretically grounded way to tackle the problem of colorization artifacts should use directly a regularized OT. This corresponds to adding a regularization penalty to the OT energy. This however leads to difficult non-convex variational problems, that have not yet been solved in a satisfying manner either theoretically or numerically. The only theoretical contribution we are aware of is the recent work of Louet and Santambrogio~\cite{louet-regularizaton-1d}. They show that in 1-D the (un-regularized) OT is also the solution of the Sobolev regularized transport problem.
%%

%%
\paragraph{Graph regularization and matching}

For imaging applications, we use regularizations built on top of a graph structure connecting neighboring points in the input density. This follows ideas introduced in manifold learning~\cite{isomap}, that have been applied to various image processing problems, see for instance~\cite{elmoataz-graph}. Using graphs enables us to design regularizations that are adapted to the geometry of the input density, that often has a manifold-like structure.

This idea of graph-based regularization of OT can be interpreted as a soft version of the graph matching problem, which is at the heart of many computer vision tasks, see~\cite{Belongie-graph-match,Yefeng-graph-match}. Graph matching is a quadratic assignment problem, known to be NP-hard to solve.  Similarly to our regularized OT formulation, several convex approximations have been proposed, including for instance linear programming~\cite{Almohamad-graph-match} and SDP programming~\cite{schellewald-ivc}.

%%
\paragraph{Transport relaxation}

The result of Louet and Santambrogio~\cite{louet-regularizaton-1d} is deceiving from the applications point of view, since it shows that, in 1-D, no regularization is possible if one  maintains a 1:1 assignment between the two densities. This is our first motivation for introducing a relaxed transport which is not a bijection between the densities.  Another (more practical) motivation is that relaxation is crucial to solve imaging problems such as color transfer. Indeed, the color distributions of natural images are multi-modals. An ideal color transfer should match the modes together. This cannot be achieved by classical OT because these modes often do not have the same mass. A typical example is for two images with strong foreground and background dominant colors (thus having bi-modal densities) but where the proportion of pixels in foreground and background are not the same. Such simple examples cannot be handled properly with OT. Allowing a controlled variation of the matched densities thus requires an appropriate relaxation of the mass conservation constraint. Mass conservation relaxation is related to the relaxation of the bijectivity constraint in graph matching, for which a convex formulation is proposed in~\cite{Zaslavskiy-graph-match}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Contributions}

In this paper, we generalize the discrete formulation of OT to tackle the two major flaws that we just mentioned: i) the lack of regularity of the transport and ii) the need for a relaxed matching between densities. Our main contribution is the integration of these two properties in a unified variational formulation to compute a regular transport map between two empirical densities. The corresponding optimization problem is convex and can be solved using standard convex optimization procedures. We propose two optimization algorithms adapted to the different class of regularizations. We apply this framework to the color transfer problem and obtain results that are comparable to the state of the art.
Our second contribution takes advantage of the proposed regularized OT energy to compute the barycenter of several empirical densities.
We develop a block-coordinate descent method that converges to a stationary point of the non-convex barycenter energy. We show an application
 to color normalization between a set of photographs. Numerical results show the relevance of these approaches to imaging problems. The matlab code to reproduce the figures of this article is available online\footnote{\url{https://github.com/siraferradans/ColorTransfer}}.

Part of this work was presented at the conference SSVM 2013~\cite{2013-ssvm-regul-ot}.


\documentclass{article}
\usepackage{enumerate}
\usepackage{amsmath, amsthm, amssymb}
\usepackage[margin=1in]{geometry}
\usepackage[parfill]{parskip}
\DeclareMathOperator*{\argmax}{arg\,max}

\title{Econ C103 Problem Set 4}
\author{Sahil Chinoy}
\date{February 14, 2017}

\begin{document}
\maketitle{}

\subsection*{Exercise 1}

\begin{enumerate}[(a)]
	\item

	Let $\hat{m}_i = \max_{j \neq i} \{m_j\}$ denote the maximum bid submitted by agents $j \neq i$.

	\begin{itemize}

		\item

		The set of possible messages for each agent is $M_i = \mathbb{R}_+$.

		\item

		The allocation is

		$$x_i =
			\begin{cases}
		      1 & \text{if } m_i > \hat{m}_i \\
		      0 & \text{otherwise}
		   \end{cases}.
		$$

		\item

		The transfer is

		$$t_i =
			\begin{cases}
		      \hat{m}_i & \text{if } m_i > \hat{m}_i \\
		      0 & \text{otherwise}
		   \end{cases}.
		$$

	\end{itemize}

	\item

	We proceed by cases.

	\begin{enumerate}[1.]

		\item

		If $\theta_i > \hat{m}_i$, then

		\begin{itemize}
			\item Bids $m_i > \theta_i$ result in winning the auction with positive payoff $\theta_i - \hat{m}_i > 0$.
			\item Bids $\hat{m}_i < m_i < \theta_i$ result in winning the auction with positive payoff $\theta_i - \hat{m}_i > 0$.
			\item Bids $m_i < \hat{m}_i$ result in losing the auction with payoff 0.
		\end{itemize}

		So the utility-maximizing bid is any $m_i > \hat{m}_i$.

		\item

		If $\theta_i < \hat{m}_i$, then

		\begin{itemize}
			\item Bids $m_i > \hat{m}_i$ result in winning the auction with negative payoff $\theta_i - \hat{m}_i < 0$.
			\item Bids $\theta_i < m_i < \hat{m}_i$ result in losing the auction with payoff 0.
			\item Bids $m_i < \theta_i$ result in losing the auction with payoff 0.
		\end{itemize}

		So the utility-maximizing bid is any $m_i < \hat{m}_i$.

	\end{enumerate}

	\item

	Bidding truthfully, i.e. $m_i = \theta_i$, maximizes the agent's utility. We can see this from the previous section: If $\theta_i > \hat{m}_i$, then any bid $m_i > \hat{m}_i$ is optimal, so $m_i = \theta_i$ is optimal. Likewise, if $\theta_i < \hat{m}_i$, then any bid $m_i < \hat{m}_i$ is optimal, so $m_i = \theta_i$ is optimal.

	\item

	We have just shown that the strategy of bidding truthfully, $s_i(\theta_i) = \theta_i$, is optimal for each agent independent of what the other agents do. Bidding truthfully is thus by definition a dominant strategy equilibrium. It is a \textit{unique} dominant strategy equilibrium because any deviation from this bid $s_i(\theta_i) = \theta_i \pm \epsilon$ would not be optimal in some cases ($\theta_i + \epsilon$ is not optimal if $\theta_i < \hat{m}$ and $\theta_i - \epsilon$ is not optimal if $\theta_i > \hat{m}$).

	The expected revenue is thus the expected value of the second of $n$ draws from the distribution of types $F$. For $\theta$ to be the second-highest bid, we need exactly $n-2$ of the other $n-1$ agents to bid less than $\theta$, which occurs with probability $F(\theta)^{(n-2)}$, and we need exactly one of the other $n-1$ agents to bid more than $\theta$, which occurs with probability $(n-1)(1-F(\theta))$. So

	\begin{equation*}
	\mathbb{E}[t] = \int \limits_0^{\bar{\theta}} \theta f(\theta) F(\theta)^{(n-2)} (n-1)(1-F(\theta)) \; d\theta
	\end{equation*}

	\item

	No. Consider the best response of player 1. If all other players bid 0, then player 1 could bid $\bar{\theta}$ and win the auction with transfer 0. But if one other player bids $m$, and $\theta_1 < m$, then the best response is to bid $m_1 < m$. So, the best response of player 1 depends on the behavior of other players; bidding $\bar{\theta}$ is not always optimal and thus this not a dominant strategy equilibrium.

	\item

	Yes. Player 1 expects $\hat{m}_1 = 0$, so any $m_1 > 0$ results in winning the auction, with positive payoff. The other players expect $\hat{m}_i = \bar{\theta}$, so they expect to lose the auction no matter what message they send; any $m_i \in [0, \bar{\theta}]$ results in payoff 0. Each agent's strategy is optimal given their expectation of the other agents' strategies, so this is a Bayes-Nash equilibrium.

	\item

	Given this strategy profile, the good will be allocated to player 1 with transfer $\hat{m}_1 = 0$, so the expected revenue is 0.

\end{enumerate}

\subsection*{Exercise 2}

\begin{enumerate}[(a)]

	\item

	The intuition is that if $s_i$ is the best response to \textit{every} possible set of messages $m_{-i}$, it is also the best response to the expectation of the Bayes-Nash equilibrium set of messages $\mathbb{E} [s_{-i}(\theta) \; | \; \theta]$.

	Formally, if $s_i$ is a dominant strategy equilibrium, then

	\begin{equation*}
	\forall m_{-i}: s_i(\theta_i) \in \argmax_{m_i \in M_i} u(a(m_i, m_{-i}), \theta_i)
	\end{equation*}

	so

	\begin{equation*}
	\forall m_{i} \; \forall m_{-i}: u(a(s_i(\theta_i), m_{-i}), \theta_i) > u(a(m_i, m_{-i}), \theta_i).
	\end{equation*}

	Then

	\begin{equation*}
	\forall \theta_i \; \forall m_{i} : u(a(s_i(\theta_i), s_{-i}(\theta_i)), \theta_i) > u(a(m_i, s_{-i}(\theta_i)), \theta_i).
	\end{equation*}

	and if $\theta_i$ is distributed with density $f(\theta_i)$ and support $[\underline{\theta_i}, \bar{\theta_i}]$

	\begin{equation*}
	\forall m_{i}: \int \limits_{\underline{\theta_i}}^{\bar{\theta_i}} f(\theta_i) \; u(a(s_i(\theta_i), s_{-i}(\theta_i)), \theta_i) \; d\theta_i > \int \limits_{\underline{\theta_i}}^{\bar{\theta_i}} f(\theta_i) \; u(a(m_i, s_{-i}(\theta_i)), \theta_i) \; d\theta_i.
	\end{equation*}

	Thus

	\begin{equation*}
	\forall m_{i} : \mathbb{E} [u(a(s_i(\theta), s_{-i}(\theta_i)), \theta_i) \; | \; \theta_i ] > \mathbb{E} [u(a(m_i, s_{-i}(\theta_i)), \theta_i) \; | \; \theta_i ]
	\end{equation*}

	and

	\begin{equation*}
	s_i(\theta_i) \in \argmax_{m_i \in M_i} \mathbb{E} [u(a(m_i, s_{-i}(\theta_i)), \theta_i) \; | \; \theta_i ]
	\end{equation*}

	so $s_i$ is a Bayes-Nash equilibrium.

	\item

	Consider a mechanism in which two agents $A$ and $B$ are each allocated a good if and only if they send the same message from the set $\{ 0, 1 \}$. Formally, $M_i = \{0, 1\}$, $x_i = 1$ if $m_A = m_B = 0$ or $m_A = m_B = 1$, otherwise $x_i = 0$. Assume the agents both have positive valuation for the good and that there are no transfers, i.e. $t_i = 0$.

	Then the best response for $A$ is $m_A = 0$ if $m_B = 0$, or $m_A = 1$ if $m_B = 1$. The situation is symmetric for $B$. There is no response that is optimal \textit{independent} of what the other agent does, thus there is no dominant strategy equilibrium.

	There are, however, two Bayes-Nash equilibria: $m_A = m_B = 1$ and $m_A = m_B = 0$.

\end{enumerate}

\end{document}


\documentclass[letterpaper,landscape]{article}
\usepackage{minitoc}
\usepackage{fullpage,enumitem,amsmath,amssymb,graphicx,algpseudocode,algorithm,array}
\usepackage{tikz}
\usepackage{mathtools}
\usepackage{minted}
\usepackage{multicol}
\usepackage{fancyhdr}
\usepackage{lastpage}
\usepackage{setspace}
\usepackage{titlesec}
\usepackage[margin=12pt,top=30pt,headsep=6pt,headheight=12pt]{geometry}

\setminted{fontsize=\footnotesize,
           frame=single,framesep=6pt,
           linenos,numbersep=6pt,xleftmargin=12pt,
           breaklines=true}
\usemintedstyle{colorful}

\pagestyle{fancy}
\fancyhf{}
\lhead{Stanford Cardinal '16 Notebook}
\rhead{\thepage/24}
\chead{\leftmark}

\titleformat{\section}{\normalfont\large\bfseries}{\thesection}{1em}{\setstretch{0.1}}
\titleformat{\subsection}{\normalfont\large\bfseries}{\thesubsection}{1em}{\setstretch{0.1}}

%\title{Stanford Cardinal '16 Notebook}
\begin{document}

\begingroup
\let\cleardoublepage\clearpage
\endgroup

\begin{multicols*}{2}

  %\raggedcolumns

  \tableofcontents
  \clearpage

  \section{Graph Algorithms}

  \subsection{SAP Maximum flow}
  \inputminted{cpp}{src/graph_maxflow.cpp}

  \subsection{Dinic's maximum flow}
  \inputminted{cpp}{src/graph_dinic.cpp}

  \subsection{Min-cost max-flow}
  \inputminted{cpp}{src/graph_mincost_maxflow.cpp}

  \subsection{Min-cost max-flow 2}
  \inputminted{cpp}{src/graph_mincost_maxflow_2.cpp}

  \subsection{Kuhn-Munkres bipartite matching}
  \inputminted{cpp}{src/KM.cpp}

  \subsection{Hopcroft-Karp bipartite matching}
  \inputminted{cpp}{src/graph_hopcroft_karp.cpp}

  \subsection{Biconnected components}
  \inputminted{cpp}{src/graph_bcc.cpp}

  \subsection{Tarjan's SCC, articulation points, bridges}
  \inputminted{cpp}{src/graph_scc.cpp}

  \subsection{Global min-cut}
  \inputminted{cpp}{src/Stoer-Wagner.cpp}

  \subsection{Constructing Euler Tour}
  \inputminted{cpp}{src/Euler.cpp}

  \section{Math}

  \subsection{Combinatorial formulas}

   $\sum_{k=0}^{n}k^{2}=n(n+1)(2n+1)/6$\\
   $\sum_{k=0}^{n}k^{3}=n^{2}(n+1)^{2}/4$\\
   $\sum_{k=0}^{n}k^{4}=(6n^{5}+15n^{4}+10n^{3}-n)/30$\\
   $\sum_{k=0}^{n}k^{5}=(2n^{6}+6n^{5}+5n^{4}-n^{2})/12$\\
   $\sum_{k=0}^{n}x^{k}=(x^{n+1}-1)/(x-1)$\\
   $\sum_{k=0}^{n}kx^{k}=(x-(n+1)x^{n+1}+nx^{n+2})/(x-1)^{2}$\\
   ${n \choose k}=\frac{n!}{(n-k)!k!}$\\
   ${n \choose k}={n-1 \choose k}+{n-1 \choose k-1}$\\
   ${n \choose k}=\frac{n}{n-k}{n-1 \choose k}$\\
   ${n \choose k}=\frac{n-k+1}{k}{n \choose k-1}$\\
   ${n+1 \choose k}=\frac{n+1}{n-k+1}{n \choose k}$\\
   ${n \choose k+1}=\frac{n-k}{k+1}{n \choose k}$\\
   $\sum_{k=1}^{n}k\tbinom{n}{k}=n2^{n-1}$\\
   $\sum_{k=1}^{n}k^{2}\tbinom{n}{k}=(n+n^{2})2^{n-2}$\\
   ${m+n \choose r}=\sum_{k=0}^{r}{m \choose k}{n \choose r-k}$\\
   ${n \choose k}=\prod_{i=1}^{k}\frac{n-k+i}{i}$\\

%  \subsection{Miller-Rabin primality testing \& Pollard-Rho factorization}
%  \inputminted{cpp}{src/math_pollard_rho.cpp}

  \subsection{Number theory identities}
 \textbf{Lucas' Theorem:} For non-negative integers $m$ and $n$ and a prime $p$,

 $$\binom{m}{n}\equiv\prod_{i=0}^k\binom{m_i}{n_i}\pmod p,$$
where
$$m=m_kp^k+m_{k-1}p^{k-1}+\cdots +m_1p+m_0$$
is the base $p$ representation of $m$, and similarly for $n$.

  \inputminted{cpp}{src/math_finite_fields.cpp}
  \inputminted{cpp}{src/primes.cpp}

  \subsection{Burnside's Lemma}
  Let $G$ be a finite group that acts on a set $X$. For each $g$ in $G$ let $X^g$ denote the set of elements in $X$ that are fixed by $g$, which means $X^g=\{x\in X| g(x)=x\}$. Burnside's lemma assers the following formula for the number of orbits, denoted $|X/G|$:
  \begin{align*}
  |X/G|=\frac{1}{|G|} \sum_{g\in G} |X^g|
  \end{align*}

  \subsection{NTT}
  \inputminted{cpp}{src/math_ntt.cpp}

  \subsection{FFT}
  \inputminted{cpp}{src/math_fft.cpp}

  \subsection{Simplex}
  \inputminted{cpp}{src/math_simplex.cpp}

  \subsection{Numerical integration}
  RK4: to integrate $\dot{y} = f(t, y)$ with $y_0 = y(t_0)$, compute
  \begin{align*}
  	k_1 &= f(t_n, y_n) \\
    k_2 &= f(t_n + \frac h 2, y_n + \frac h 2 k_1) \\
    k_3 &= f(t_n + \frac h 2, y_n + \frac h 2 k_2) \\
    k_4 &= f(t_n + h, y_n + h k_3) \\
    y_{n+1} &= y_n + \frac h 6 (k_1 + 2k_2 + 2k_3 + k_4)
  \end{align*}

  \subsection{Partition function}
  \inputminted{cpp}{src/partition.cpp}

  \section{String Algorithms}

  \subsection{KMP}
  \inputminted{cpp}{src/string_KMP.cpp}

  \subsection{Aho-Corasick trie/automaton}
  \inputminted{cpp}{src/string_AC.cpp}

  \subsection{Suffix array}
  \inputminted{cpp}{src/string_SA.cpp}

  \subsection{Suffix array}
  \inputminted{cpp}{src/string_SA_nlogn_pear.cpp}

  \subsection{Permuted LCP}
  \inputminted{cpp}{src/string_kasai.cpp}

  \subsection{Suffix tree}
  \inputminted{cpp}{src/string_ukkonen.cpp}

  \subsection{Suffix automaton}
  \inputminted{cpp}{src/string_suffix_automaton.cpp}

  \subsection{Z-function}
  \inputminted{cpp}{src/string_z_function.cpp}

  \section{Data structures}

  \subsection{Dynamic convex hull}
  \inputminted{cpp}{src/ds_dynamic_convex_hull.cpp}

  \subsection{Treap}
  \inputminted{cpp}{src/ds_treap.cpp}

  \subsection{Splay tree}
  \inputminted{cpp}{src/ds_splay_tree.cpp}

  \subsection{Link-cut tree}
  \inputminted{cpp}{src/ds_link_cut_tree.cpp}

  \subsection{Centroid decomposition}
  \inputminted{cpp}{src/ds_centroid_decomposition.cpp}

  \subsection{Heavy-light decomposition}
  \inputminted{cpp}{src/ds_heavy_light_decomposition.cpp}

  \subsection{Hash table}
  \inputminted{cpp}{src/ds_hash_table.cpp}

  \subsection{KD-tree}
  \inputminted{cpp}{src/KDTree.cpp}

  \subsection{PB DS}
  \inputminted{cpp}{src/ds_pbds.cpp}

  \section{Geometry}

  \subsection{C++ geometry}
  \inputminted{cpp}{src/geom_library.cpp}

  \subsection{Java geometry}
  \inputminted{java}{src/JavaGeometry.java}

  \subsection{Java 3D geometry}
  \inputminted{java}{src/Geom3D.java}

  \section{Misc}

  \subsection{Virtual tree DP}
  \inputminted{cpp}{src/misc_virtual_tree.cpp}

  \subsection{Dates}
  \inputminted{cpp}{src/dates.cpp}

\end{multicols*}

\end{document}


\section{Algorithm}
\label{sect:algorithm}
\index{algorithm}

To illustrate how the event selection algorithm works
consider the decay
$B\rightarrow D^{*} \tau \bar\nu$,
$D^* \rightarrow D\pi$, and $\tau \to \pi \nu$.
The general case is a straight forward generalization of
this example. The decay amplitude can be written as
\def\AmpB{A^{B\rightarrow D^*\tau\nu}_{\lambda_{D^*}\lambda_{\tau}}}
\def\AmpDstar{A^{D^*\rightarrow D\pi}_{\lambda_{D^*}}}
\def\Amptau{A^{\tau\rightarrow \pi\nu}_{\lambda_{\tau}}}
\begin{equation}
A=\sum_{\lambda_{D^*}\lambda_{\tau}}\AmpB
\times \AmpDstar
\times \Amptau,
\label{Eq:ampeq}
\end{equation}
where $\lambda^{\phantom '}_{D^*}$ and $\lambda^{\phantom '}_{\tau}$ label the states of spin degrees of freedom of the
$D^{*}$ and the $\tau$, respectively. Thus,
$\AmpB$ represents the decay amplitude for $B \to D^* \tau \nu$
for the six different combinations of $D^*$ and
$\tau$ states.

A possible implementation of Eq.~\ref{Eq:ampeq} is to generate kinematics according to phase
space for the entire decay chain and to calculate the probability,
the amplitude squared, which is
used in an accept-reject algorithm.  This approach has two serious
limitations.  First, the maximum probability of the decay chain
must be known.  This is logicistally difficult given the large
number of potential decay chains in $B$ decays.  Second, for long
decay chains the accept-reject algorithm can be very inefficient as
the entire chain must be regenerated if the event is rejected.
We have implemented an algorithm that generates a decay chain as a
sequence of sub-decays, thus avoiding both of these limitations.

First the decay of the $B$ is considered. Kinematics are generated
according to phase space and the probability is calculated
\begin{equation}
P_B=\sum_{\lambda^{\phantom '}_{D^*}\lambda^{\phantom '}_{\tau}}|\AmpB|^2.
\end{equation}
The kinematics are regenerated until the event
passes an accept-reject algorithm based on $P_B$.
After decaying the $B$ we form the spin density matrix
\begin{equation}
\rho^{D^*}_{\lambda^{\phantom '}_{D^*}\lambda^{'}_{D^*}}=\sum_{\lambda^{\phantom '}_{\tau}}\AmpB
[{A^{B\rightarrow D^*\tau\nu}_{\lambda^{'}_{D^*}\lambda^{\phantom '}_{\tau}}}]^*,
\end{equation}
which describes a $D^*$ from the $B \to D^* \tau \nu$ decay after summing over
the degrees of freedom for the $\tau$.
To generate the $D^* \to D \pi$ decay, proceed as with the $B$,
including also $\rho^{D^*}$
\begin{equation}
P_{D^*}=
{{1} \over {{\rm Tr}\,\rho^{D^*}}}
\sum_{\lambda^{\phantom '}_{D^*} \lambda^{'}_{D^*}}
\rho^{D^*}_{\lambda^{\phantom '}_{D^*}\lambda^{'}_{D^*}}
\AmpDstar
[{A^{D^*\rightarrow D\pi}_{\lambda^{'}_{D^*}}}]^*,
\label{Eq:probdstar}
\end{equation}
where the scale factor, $1/{\rm Tr}\,\rho^{D^*}$,
is proportional to the decay rate, and does not affect the
angular distributions.  This scale factor makes
the maximum decay probability of each sub-decay
independent of the full decay chain.

Finally, we decay the $\tau$. We form the density matrix
\begin{equation}
\tilde\rho^{D^*}_{\lambda^{\phantom '}_{D^*}\lambda^{'}_{D^*}}=\AmpDstar
[{A^{D^*\rightarrow D\pi}_{\lambda^{'}_{D^*}}}]^*,
\end{equation}
which encapsulates the information about the $D^*$ decay
needed to properly decay the $\tau$ with the full correlations between
all kinematic variables in the decay.
Using the $\tilde\rho^{D^*}$ matrix we calculate the spin density
matrix of the $\tau$
\begin{equation}
\rho^{\tau}_{\lambda^{\phantom '}_{\tau}\lambda^{'}_{\tau}}=\sum_{\lambda^{\phantom '}_{D^*}\lambda^{'}_{D^*}}
\tilde\rho^{D^*}_{\lambda^{\phantom '}_{D^*}\lambda^{'}_{D^*}}
\AmpB[{A^{B\rightarrow D^*\tau\nu}_{\lambda^{'}_{D^*}\lambda^{'}_{\tau}}}]^*.
\end{equation}
As in the other decays, kinematics are generated according to phase space
and the accept-reject is based on the probability calculated
as in Eq.~\ref{Eq:probdstar}, replacing $D^*$ with $\tau$.

The algorithm was illustrated above using an example which should
convey the idea. In general consider the decay
\begin{equation}
A\rightarrow B_1B_2...B_N
\end{equation}
where the amplitudes are denoted by
\begin{equation}
A^{A\rightarrow B_1B_2...B_N}_{\lambda_A\lambda_{B_1}\lambda_{B_2}...\lambda_{B_N}}.
\end{equation}
The probability for, $P_A$, for this decay is given by
\begin{equation}
P_A=\sum_{\lambda_A\lambda'_{A}\lambda_{B_1}...\lambda_{B_N}}
	\rho^{A}_{\lambda_A\lambda'_{A}}
	A^{A\rightarrow B_1B_2...B_N}_{\lambda_A\lambda_{B_1}\lambda_{B_2}...\lambda_{B_N}}
[A^{A\rightarrow B_1B_2...B_N}_{\lambda'_{A}\lambda_{B_1}\lambda_{B_2}...\lambda_{B_N}}]^*  .
\end{equation}
The forward spin-density matrix $\rho^{B_i}$, given that $B_j$, $j<i$,
have been decayed and have backward spin-density matrices $\hat\rho^{B_j},$
is given by
\begin{equation}
\rho^{B_i}_{\lambda_{B_i}\lambda'_{B_i}}=
	\sum_{\lambda_A\lambda'_{A}
	\lambda_{B_1}...\lambda_{B_N} \atop
	\lambda'_{B_1}...\lambda'_{B_{i-1}}}
	\rho^{A}_{\lambda_A\lambda'_{A}}
	\hat\rho^{B_1}_{\lambda_{B_1}\lambda'_{B_1}}...
	\hat\rho^{B_{i-1}}_{\lambda_{B_{i-1}}\lambda'_{B_{i-1}}}
	A^{A\rightarrow B_1B_2...B_N}_{\lambda_A\lambda_{B_1}\lambda_{B_2}...\lambda_{B_N}}
[A^{A\rightarrow B_1B_2...B_N}_{\lambda'_{A}\lambda'_{B_1}...\lambda'_{B_{i}}\lambda_{B_{i+1}}...\lambda_{B_N}}]^*.
\end{equation}
After all $B_i$ are decays the backward spin-density matrix is given by
\begin{equation}
\hat\rho^{A}_{\lambda_{A}\lambda'_{A}}=
	\sum_{\lambda_{B_1}...\lambda_{B_N} \atop
	\lambda'_{B_1}...\lambda'_{B_{N}}}
	\hat\rho^{B_1}_{\lambda_{B_1}\lambda'_{B_1}}...
	\hat\rho^{B_{N}}_{\lambda_{B_{N}}\lambda'_{B_N}}
	A^{A\rightarrow B_1B_2...B_N}_{\lambda_A\lambda_{B_1}\lambda_{B_2}...\lambda_{B_N}}
[A^{A\rightarrow B_1B_2...B_N}_{\lambda'_{A}\lambda'_{B_1}...\lambda'_{B_N}}]^*.
\end{equation}

%To illustrate how the event selection algorithm works we will first
%consider an example of the decay
%\begin{equation}
%B\rightarrow D^{*}(\rightarrow D\pi)\tau(\rightarrow \pi\nu)\bar\nu.
%\end{equation}
%The amplitude for this decay can be written as
%\def\AmpB{A^{B\rightarrow D^*\tau\nu}_{\lambda_{D^*}\lambda_{\tau}}}
%\def\AmpDstar{A^{D^*\rightarrow D\pi}_{\lambda_{D^*}}}
%\def\Amptau{A^{\tau\rightarrow \pi\nu}_{\lambda_{\tau}}}
%\begin{equation}
%A=\sum_{\lambda_{D^*}\lambda_{\tau}}\AmpB
%\times \AmpDstar
%\times \Amptau
%\label{Eq:ampeq}
%\end{equation}
%Where $\lambda_{D^*}$ and $\lambda_{\tau}$ labels the states of the
%$D^{*}$ and the $\tau$, respectively, so that
%\begin{equation}
%\AmpB
%\end{equation}
%is 6 different amplitudes for the different combinations of $D^*$
%$\tau$ states. (Note here that the neutrino is treated as a
%particle with only one state, all neutrinos are assumed to be
%left-handed and anti neutrinos to be right-handed.)
%Similarly,
%\begin{equation}
%\AmpDstar\ {\rm and}\ \Amptau
%\end{equation}
%are the amplitudes for a decay of a $D^{*}\rightarrow D\pi$ and
%$\tau\rightarrow\pi\nu$ respectively.%
%
%The scheme that was originally implemented in EvtGen was to generate
%kinematics according to phasespace for the whole decay chain and then calculate that
%amplitude for the whole decay chain according to Eq.~\ref{Eq:ampeq}.
%This amplitude was squared to obtain the probability and the event was
%accepted or rejected based on this probability. This approach works, but has
%two serious flaws. First, when doing the acceptance rejection you need to know
%the maximum probability, this gets very hard to keep track of since the
%number of decay chains get very large. Secondly, as the decay chains get long
%the efficiency for the acceptance rejection gets low and the time for
%generating events long.
%
%The source of both these problems are that the decays are treated as a chain
%and all three decays in the example above are generated at once, in one
%acceptance rejection. We would like to change the algorithm such that it
%generates the decay as a sequence of sub-decay. In the example considered
%here the decay $B\rightarrow D^*\tau\nu$ would be done first, then the
%decay $D^*\rightarrow D \pi$ is done. This decay will need to incorporate
%information about how $D^*$ was produced in the $B$ decay. Further, when
%the $\tau$ is decayed it also has to incorporate the information from the
%decay of the $D^*$ as well so that correlations between all kinematic
%variables are correctly generated. This is described bellow for the
%example considered in this section.
%
%First the decay of the $B$ is considered, kinematics for the decay is generated
%according to phasespace and the and the probability is then calculated as
%\begin{equation}
%P_B=\sum_{\lambda_{D^*}\lambda_{\tau}}|\AmpB|^2.
%\end{equation}
%Acceptance-rejection is done on the the probability $P_B$ until an event is
%accepted. After decaying the $B$ we now form the spin-density matrix for the
%decay of the $D^*$, in the code this spin-density matrix is refered to as the
%forward spin-density matrix. This matrix is defined by
%\begin{equation}
%\rho^{D^*}_{\lambda_{D^*}\lambda'_{D^*}}=\sum_{\lambda_{\tau}}\AmpB
%{A^{B\rightarrow D^*\tau\nu}_{\lambda'_{D^*}\lambda_{\tau}}}^*
%\end{equation}
%The interpretation of this is that here we have summed incoherently over the
%states of the tau. This means that the spin density matrix $\rho^{D^*}$
%describes a $D^*$ in this decay that you have after summing over
%the degrees of freedom for the tau.
%
%This spin density matrix, $\rho^{D^*}$ is now used to calculate the
%probability for the $D^*$ decay, again kinematics is generated according to
%phases pace and the probability is used to accept or reject events based
%on
%\begin{equation}
%P_{D^*}=\rho^{D^*}_{\lambda_{D^*}\lambda'_{D^*}}\AmpDstar
%{A^{D^*\rightarrow D\pi}_{\lambda'_{D^*}}}^*
%\end{equation}
%
%Now we need to decay the $D^*$; to do this we form the density matrix
%\begin{equation}
%\tilde\rho^{D^*}_{\lambda_{D^*}\lambda'_{D^*}}=\AmpDstar
%{A^{D^*\rightarrow D\pi}_{\lambda'_{D^*}}}^*
%\end{equation}
%This matrix encapsulates the information about the $D^*$ decay that is
%needed to properly decay the $\tau$ with the full correlations between
%all kinematic variables in the decay. Since this matrix
%is passed ``back'' to the decay of the $B$ from the decay of the
%$D^*$ this matrix is called the backward spin-density matrix in the code.
%
%Using the $\tilde\rho^{D^*}$ matrix we can now calculate the forward spin density
%matrix of the $\tau$
%\begin{equation}
%\rho^{\tau}_{\lambda_{\tau}\lambda'_{\tau}}=\sum_{\lambda_{D^*}\lambda'_{D^*}}
%\tilde\rho^{D^*}_{\lambda_{D^*}\lambda'_{D^*}}
%\AmpB{A^{B\rightarrow D^*\tau\nu}_{\lambda'_{D^*}\lambda'_{\tau}}}^*
%\end{equation}
%Note that this spin density matrix for the decay of the $\tau$ includes the
%information about how the $D^*$ decayed through the $\tilde\rho^{D^*}$
%matrix.
%Now, as in the other decays, we generate kinematics according to phase space
%and accepts or rejects based on the probability calculated according to
%\begin{equation}
%P_{\tau}=\sum_{\lambda_{\tau}\lambda'_{\tau}}\rho^{\tau}_{\lambda_{\tau}\lambda'_{\tau}}
%\Amptau{A^{\tau\rightarrow \pi\nu}_{\lambda'_{\tau}}}^*
%\end{equation}
%
%This algorithm is implemented in the code and it solves two major problems
%that the original versions of EvtGen had. The algorithm was illustrated above
%using an example which should convey the idea. I will try to write up the
%algorithm more formally at some point but the notation for describing it is so awkward.%


\documentclass{article}
\usepackage{fullpage}
\usepackage{nopageno}
\usepackage{amsmath}
\usepackage{amssymb}
\allowdisplaybreaks

\newcommand{\abs}[1]{\left\lvert #1 \right\rvert}

\begin{document}
\title{Notes}
\date{February 24, 2014}
\maketitle

\section*{lesson 12}
\subsection*{definition}
Given $f(x)$ on $\mathbb{R}$.
\begin{align*}
  \mathcal{F}[f]&=F(\xi)=\frac{1}{\sqrt{2\pi }}\int_{-\infty}^{+\infty}{e^{-i\xi x}f(x)\,\mathrm{d}x}
\end{align*}
Inverse transform recovers $f(x)$ from $F(\xi)$:
\begin{align*}
  f(x)&=\frac{1}{\sqrt{2\pi }}\int_{-\infty}^{+\infty}{e^{+i\xi x}F(\xi)\,\mathrm{d}\xi}&\text{Deep Theorem}
\end{align*}
\subsection*{problem}
page 93
\begin{align*}
  PDE&&u_t&=\alpha ^2u_{xx}&-\infty<&x<\infty&0<&t<\infty\\
  IC&&u(x,0)&=\phi(x)&-\infty<&x<\infty
\end{align*}
apply $\mathcal{F}$ to pde. $U(\xi,t)=\mathcal{F}[u(x,t)]$. Use property 3 (derivative): $\mathcal{F}[u_{xx}]=$

How are $\mathcal{F}[f']$ and $\mathcal{F}[f]$ related? page 91.
\begin{align*}
  \mathcal{F}[f']&=\frac{1}{\sqrt{2\pi }}\int_{-\infty}^{+\infty}{e^{-i\xi x}f'(x)\,\mathrm{d}x}\\
  &=\frac{1}{\sqrt{2\pi }}\left[e^{-i\xi x}f(x)\right]_{-\infty}^{+\infty}-\int_{-\infty}^{+\infty}{(-i\xi)e^{-i\xi x}f(x)\,\mathrm{d}x}\\
  \intertext{\emph{note:} implicit conditions on $f(x)$ to insure integrals exist $f(+\infty)=f(-\infty)=0$}
  &=0+i\xi\frac{1}{\sqrt{2\pi }}\int_{-\infty}^{+\infty}{e^{-i\xi x}f(x)\,\mathrm{d}x}\\
  \intertext{property 3}
  \mathcal{F}[f']&=i\xi\mathcal{F}[f]\\
  \mathcal{F}[f'']&=\xi^2\mathcal{F}[f]
\end{align*}
So $\mathcal{F}[u_{xx}]=-\xi^2U(\xi,t)$. $\frac{\mathrm{d}U}{\mathrm{d}t}=-\alpha ^2\xi^2U$ with $U(\xi,0)=\phi(\xi)$

\subsubsection*{step 2}
solve prolem $U(\xi,t)=\phi(\xi)e^{-\alpha ^2\xi^2 t}$.
\subsubsection*{step 3}
invert transform

\subsection*{property 4}
\subsubsection*{convolution theorem}
definition: given $f(x),gx)$ on $\mathbb{R}$
\begin{align*}
  f*g(x)&=1\frac{1}{\sqrt{2\pi }}\int_{-\infty}^{+\infty}{f(x-s)g(s)\,\mathrm{d}s}\\
  \intertext{theorem}
  \mathcal{F}[f*g(x)]&=\mathcal{F}[f]\mathcal{F}[g]=F(\xi)G(\xi)&\text{deep theorem}
\end{align*}
sample calculation: find the convolution of two functions. Text example
\begin{align*}
  \left.\begin{aligned}
    f(x)&=x\\
    g(x)&=e^{-x^2}
  \end{aligned}\right\}&f*g(x)=\frac{x}{\sqrt{2}}\\
  f*g(x)&=\frac{1}{\sqrt{2\pi }}\int_{-\infty}^{+\infty}{f(x-u)g(u)\,\mathrm{d}u}\\
  &=\frac{1}{\sqrt{2\pi }}\int_{-\infty}^{+\infty}{(x-u)e^{-u^2}\,\mathrm{d}u}\\
  &=\frac{1}{\sqrt{2\pi }}\left[x\int_{-\infty}^{+\infty}{e^{-u^2}\,\mathrm{d}u}-\int_{-\infty}^{+\infty}{ue^{-u^2}\,\mathrm{d}u}\right]&\text{odd integral}\\
  &=\frac{x}{\sqrt{2\pi }}\sqrt{\pi }
  f(x)&=e^{-x^2}\\
  g(x)&=x\\
  f*g(x)&=\frac{1}{\sqrt{\pi }}\int_{-\infty}^{+\infty}{e^{-(x-u)^2}u\,\mathrm{d}u}\\
  \intertext{property:$f*g(x)=g*f(x)$ commutativity}
  f*g(x)&=\frac{1}{\sqrt{2\pi }}\int_{-\infty}^{+\infty}{f(x-u)g(u)\,\mathrm{d}u}\\
  u&=-\infty\qquad\gets x-u\\
  x-u&=+\infty
\end{align*}
note that the definition in the book has a negative $i$ and mathematica doesn't. and then that makes the signs flipped on the inverse transform as well. CAREFUL!!!
\begin{align*}
  u(x,t)&=\int_{-\infty}^{\infty}{\phi(x-u)\frac{1}{\sqrt{\pi}}\frac{1}{2\alpha \sqrt{t}}e^{-\frac{u^2}{2/\alpha ^2t}}\,\mathrm{d}u}\\
  \int_{-\infty}^{\infty}{\frac{1}{\sqrt{\pi}}\frac{1}{2\alpha \sqrt{t}}e^{-\frac{u^2}{2/\alpha ^2t}}\,\mathrm{d}u}&=\int_{-\infty}^{\infty}{\frac{1}{\sqrt{\pi}}\frac{1}{2\alpha \sqrt{t}}e^{-\frac{u^2}{2/\alpha ^2t}}\,\mathrm{d}u}\\
  u(x,t)&=\int_{-\infty}^\infty{\phi(x)f(x-u)\,\mathrm{d}u}\text{ positive with unit area}
\end{align*}
\end{document}


\documentclass[twoside]{MATH77}
\usepackage{multicol}
\usepackage[fleqn,reqno,centertags]{amsmath}
\begin{document}
\begmath 2.11 Finite Legendre Series

\silentfootnote{$^\copyright$1997 Calif. Inst. of Technology, \thisyear \ Math \`a la Carte, Inc.}

\subsection{Purpose}

This subroutine computes the value of a finite sum of Legendre polynomials,
\begin{equation*}
y=\sum_{j=0}^{\text{N}}a_jP_j(x)
\end{equation*}
for a specified summation limit, N, argument, $x$, and sequence of
coefficients, $a_j$. The Legendre polynomials are defined in \cite{ams55:or-poly}.

\subsection{Usage}

\subsubsection{Program Prototype, Single Precision}

\begin{description}
\item[INTEGER]  \ {\bf N}

\item[REAL]  \ {\bf X, Y, A}($0:m\geq $ N)
\end{description}

Assign values to X, N, and A(0), A(1), ... A(N).
$$
\fbox{{\bf CALL SLESUM (S, N, A, Y)}}
$$
The sum will be stored in Y.

\subsubsection{Argument Definitions}

\begin{description}
\item[X]  \ [in] Argument of the polynomials.

\item[N]  \ [in] Highest degree of polynomials in sum.

\item[A()]  \ [in] The coefficients must be given in A(J), J = 0, ..., N.

\item[Y]  \ [out] Computed value of the sum.
\end{description}

\subsubsection{Modifications for Double Precision}

For double precision usage, change the REAL statement to DOUBLE PRECISION
and change the subroutine name from SLESUM to DLESUM.

\subsection{Examples and Remarks}

See DRSLESUM and ODSLESUM for an example of the usage of SLESUM. DRSLESUM
evaluates the following identity, the coefficients of which were obtained
from Table~22.9, page~798, of~\cite{ams55:or-poly}.
\begin{equation*}
z = y - w = 0,
\end{equation*}
where
\begin{multline*}
y = 0.07P_0(x) + 0.27P_1(x) + 0.20P_2(x)\\
+ 0.28P_3(x) + 0.08P_4(x) + 0.08P_5(x),
\end{multline*}
and
\begin{equation*}
w = 0.35x^4 + 0.63x^5.
\end{equation*}

\subsection{Functional Description}

The sum is evaluated by the following algorithm:
\begin{gather*}
b_{N+2}=0,\quad b_{N+1}=0,\\
b_k=\frac{2k+1}{k+1}b_{k+1}x-\frac{k+1}{k+2}b_{k+2}+a_k,\ \ k=N,...,0,\\
y=b_0.
\end{gather*}
For an error analysis applying to this algorithm see \cite{Ng:1968:DSS} and
\cite{Ng:1971:RAC}. The first four Legendre polynomials are \begin{gather*}
P_0(x) = 1,\quad P_1(x) = x,\\
P_2(x) = 1.5x^2 - 0.5,\quad P_3(x) = 2.5x^3 - 1.5x.
\end{gather*}
For $k \geq 2$ the Legendre polynomials satisfy the recurrence
\begin{equation*}
kP_k(x) = (2k-1)xP_{k-1}(x) - (k-1)P_{k-2}(x).
\end{equation*}

The Legendre polynomials are orthogonal relative to integration over the
interval [$-$1,~1] and are normally used only with an argument, $x$, in this
interval.

\bibliography{math77}
\bibliographystyle{math77}

\subsection{Error Procedures and Restrictions}

The subroutine will return Y = 0 if N $< 0$. It is recommended that $x$
satisfy $|x| \leq 1.$

\subsection{Supporting Information}

The source language is ANSI Fortran

\begin{tabular}{@{\bf}l@{\hspace{5pt}}l}
\bf Entry & \hspace{.2in} {\bf Required Files}\vspace{2pt} \\
DLESUM & \hspace{.35in}DLESUM\rule[-5pt]{0pt}{8pt}\\
SLESUM & \hspace{.35in}SLESUM\\
\end{tabular}

Based on a 1974 program by E. W. Ng, JPL. Present version by C. L. Lawson
and S. Y. Chiu, JPL, 1983.

\begcodenp

\medskip

\lstset{language=[77]Fortran,showstringspaces=false}
\lstset{xleftmargin=.8in}

\centerline{\bf \large DRSLESUM}\vspace{10pt}
\lstinputlisting{\codeloc{slesum}}

\vspace{30pt}\centerline{\bf \large ODSLESUM}\vspace{10pt}
\lstset{language={}}
\lstinputlisting{\outputloc{slesum}}

\end{document}


\section{Introduction}

The {\tt{}matrix-lua} module adds simple matrix support to Lua.
Supported functions are
\begin{itemize}
  \item {\tt{}matrix(m,n)}: create a new zero matrix of size $m$ by $n$
  \item {\tt{}A(i,j)}:      get $A_{ij}$
  \item {\tt{}A[k]}:        get or set the $k$th element (column-major 1-based)
  \item {\tt{}C\ =\ A+B}:     add two matrices
  \item {\tt{}C\ =\ A-B}:     subtract two matrices
  \item {\tt{}C\ =\ -A}:      take the unary negation of a matrix
  \item {\tt{}C\ =\ A*B}:     multiply two matrices
  \item {\tt{}A.print()}:   print matrix
  \item {\tt{}A.factor()}:  factor matrix
  \item {\tt{}A.solve(x)}:  compute $x := A^{-1}x$
  \item {\tt{}A.clone()}:   create a copy of the matrix
  \item {\tt{}A.slice(i1,i2,j1,j2)}:   create a slice of the matrix
  \item {\tt{}A.free()}:    free matrix
\end{itemize}
Supported variables are
\begin{itemize}
  \item {\tt{}A.m}:  return number of rows in matrix
  \item {\tt{}A.n}:  return number of columns in matrix
\end{itemize}

\section{Interface}

\nwfilename{matrix-lua.nw}\nwbegincode{1}\sublabel{NWmatD-matC-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-matC-1}}}\moddef{matrix-lua.h~{\nwtagstyle{}\subpageref{NWmatD-matC-1}}}\endmoddef
#ifndef MATRIX_LUA_H
#define MATRIX_LUA_H

#include <lua.h>

struct lua_matrix_struct \{
    int owns_data;  /* True if this matrix owns storage  */
    int m, n, ld;   /* Array size and leading dimension  */
    double* data;   /* Array data                        */
    int* ipiv;      /* Pivot array for factored matrices */
\};

typedef struct lua_matrix_struct* lua_matrix_t;

void         lua_matrix_register(lua_State* L);
void         lua_matrix_push(lua_State* L, lua_matrix_t A);
lua_matrix_t lua_matrix_get(lua_State* L, int index);

lua_matrix_t lua_matrix_create(int m, int n);
lua_matrix_t lua_matrix_slice(lua_matrix_t A, int i1, int i2, int j1, int j2);
void         lua_matrix_destroy(lua_matrix_t self);

#endif /* MATRIX_LUA_H */
\nwnotused{matrix-lua.h}\nwendcode{}\nwbegindocs{2}\nwdocspar

The {\tt{}lua{\char95}matrix{\char95}register} function registers the functions of
the module with the Lua interpreter.  The {\tt{}lua{\char95}matrix{\char95}push}
and {\tt{}lua{\char95}matrix{\char95}get} functions add and get matrices
on the Lua stack.

The {\tt{}lua{\char95}matrix{\char95}create} and {\tt{}lua{\char95}matrix{\char95}destroy} functions create
new matrices.  The {\tt{}lua{\char95}matrix{\char95}slice} function creates a ``parasite''
matrix that uses the same storage as the original matrix but which
has different indexing.  In Matlab parlance, the slice function returns
{\tt{}A(i1:i2,\ j1:j2)}.

\section{Implementation}

\nwenddocs{}\nwbegincode{3}\sublabel{NWmatD-matC.2-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-matC.2-1}}}\moddef{matrix-lua.c~{\nwtagstyle{}\subpageref{NWmatD-matC.2-1}}}\endmoddef
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "matrix-lua.h"

\LA{}macros~{\nwtagstyle{}\subpageref{NWmatD-mac6-1}}\RA{}
\LA{}static prototypes~{\nwtagstyle{}\subpageref{NWmatD-staH-1}}\RA{}
\LA{}static data~{\nwtagstyle{}\subpageref{NWmatD-staB-1}}\RA{}
\LA{}static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}\RA{}
\LA{}functions~{\nwtagstyle{}\subpageref{NWmatD-fun9-1}}\RA{}
\nwnotused{matrix-lua.c}\nwendcode{}\nwbegindocs{4}\nwdocspar

\subsection{Matrix tag}

Lua provides \emph{tags} for user data, with semantics known only
to the host program.  The {\tt{}lua{\char95}matrix{\char95}tag} is the tag for
the Lua matrix type.  Note that you \emph{could} get into trouble
with this if multiple interpreters are simultaneously active,
since the different interpreters may not end up allocating the same
tag value.

\nwenddocs{}\nwbegincode{5}\sublabel{NWmatD-staB-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staB-1}}}\moddef{static data~{\nwtagstyle{}\subpageref{NWmatD-staB-1}}}\endmoddef
static int lua_matrix_tag;

\nwused{\\{NWmatD-matC.2-1}}\nwendcode{}\nwbegindocs{6}\nwdocspar

\subsection{Accessor macros}

We use a couple convenience macros for getting the matrix entries.
The macros use one-based indexing for consistence with the Lua
index conventions.

\nwenddocs{}\nwbegincode{7}\sublabel{NWmatD-mac6-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-mac6-1}}}\moddef{macros~{\nwtagstyle{}\subpageref{NWmatD-mac6-1}}}\endmoddef
#define Mij(M,i,j) (M->data[((j)-1)*M->ld + ((i)-1)])
#define Mrow0(M,k) ( ((k)-1) % (M->m) )
#define Mcol0(M,k) ( ((k)-1) / (M->m) )
#define Mk(M,k)    ( M->data[Mcol0(M,k) * M->ld + Mrow0(M,k)] )

\nwused{\\{NWmatD-matC.2-1}}\nwendcode{}\nwbegindocs{8}\nwdocspar

\subsection{Matrix call getter}

We use Lua tag methods to handle the case when the ``call'' syntax
is applied to a matrix object.  If there is one numeric argument $i$,
we get the $(i,1)$ matrix entry; if there are two numeric arguments,
we get the $(i,j)$ entry.

\nwenddocs{}\nwbegincode{9}\sublabel{NWmatD-regI-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-regI-1}}}\moddef{register functions~{\nwtagstyle{}\subpageref{NWmatD-regI-1}}}\endmoddef
lua_pushcclosure(L, lua_matrix_call, 0);
lua_settagmethod(L, lua_matrix_tag, "function");
\nwalsodefined{\\{NWmatD-regI-2}\\{NWmatD-regI-3}\\{NWmatD-regI-4}\\{NWmatD-regI-5}\\{NWmatD-regI-6}\\{NWmatD-regI-7}\\{NWmatD-regI-8}}\nwused{\\{NWmatD-fun9-4}}\nwendcode{}\nwbegindocs{10}\nwdocspar

\nwenddocs{}\nwbegincode{11}\sublabel{NWmatD-staG-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\endmoddef
static int lua_matrix_call(lua_State* L)
\{
    lua_matrix_t A = lua_touserdata(L,1);
    int n = lua_gettop(L);
    int i, j;

    if (n < 2 || n > 3)
        lua_error(L, "Wrong number of arguments");

    if (!lua_isnumber(L,2) || (n == 3 && !lua_isnumber(L,3)))
        lua_error(L, "Index must be a number");

    i = (int) lua_tonumber(L,2);
    j = (n == 3) ? (int) lua_tonumber(L,3) : 1;

    if (i <= 0 || i > A->m || j <= 0 || j > A->n)
        lua_error(L, "Index out of range");

    lua_settop(L,0);
    lua_pushnumber(L, Mij(A,i,j));
    return 1;
\}

\nwalsodefined{\\{NWmatD-staG-2}\\{NWmatD-staG-3}\\{NWmatD-staG-4}\\{NWmatD-staG-5}\\{NWmatD-staG-6}\\{NWmatD-staG-7}\\{NWmatD-staG-8}\\{NWmatD-staG-9}\\{NWmatD-staG-A}\\{NWmatD-staG-B}\\{NWmatD-staG-C}\\{NWmatD-staG-D}\\{NWmatD-staG-E}\\{NWmatD-staG-F}\\{NWmatD-staG-G}\\{NWmatD-staG-H}}\nwused{\\{NWmatD-matC.2-1}}\nwendcode{}\nwbegindocs{12}\nwdocspar

\subsection{Matrix table getter}

The indexed read operation does two different things.  If the index
is a number $k$, we try to return the $k$th element of the matrix
(as arranged in column-major order with one-based indexing).
If the index is a string, then we probably have a method call,
which is handled by the {\tt{}lua{\char95}matrix{\char95}getmethod} function described
later.  (Recall that the dot syntax in Lua is a type of indexing,
so that {\tt{}A.print()} is equivalent to {\tt{}A["print"]()}.)

The {\tt{}gettable} tag method receives the tagged object and the index.

\nwenddocs{}\nwbegincode{13}\sublabel{NWmatD-regI-2}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-regI-2}}}\moddef{register functions~{\nwtagstyle{}\subpageref{NWmatD-regI-1}}}\plusendmoddef
lua_pushcclosure(L, lua_matrix_gettable, 0);
lua_settagmethod(L, lua_matrix_tag, "gettable");
\nwendcode{}\nwbegindocs{14}\nwdocspar

\nwenddocs{}\nwbegincode{15}\sublabel{NWmatD-staG-2}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-2}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_gettable(lua_State* L)
\{
    lua_matrix_t A = lua_touserdata(L,1);
    int k;

    if (!lua_isnumber(L,2)) \{
        if (lua_isstring(L,2))
            return lua_matrix_getmethod(L);
        else
            lua_error(L, "Index must be a number");
    \}
    k = (int) lua_tonumber(L,2);

    if (k <= 0 || k > A->m * A->n)
        lua_error(L, "Index out of range");

    lua_settop(L,0);
    lua_pushnumber(L, Mk(A,k));
    return 1;
\}

\nwendcode{}\nwbegindocs{16}\nwdocspar

\subsection{Matrix setter}

The indexed write operation can only do one thing: set a matrix
entry.  The {\tt{}settable} tag method gets the tagged object,
the index, and the value to write on the stack.

\nwenddocs{}\nwbegincode{17}\sublabel{NWmatD-regI-3}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-regI-3}}}\moddef{register functions~{\nwtagstyle{}\subpageref{NWmatD-regI-1}}}\plusendmoddef
lua_pushcclosure(L, lua_matrix_settable, 0);
lua_settagmethod(L, lua_matrix_tag, "settable");
\nwendcode{}\nwbegindocs{18}\nwdocspar

\nwenddocs{}\nwbegincode{19}\sublabel{NWmatD-staG-3}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-3}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_settable(lua_State* L)
\{
    lua_matrix_t A = lua_touserdata(L,1);
    int k;

    if (!lua_isnumber(L,2))
        lua_error(L, "Index must be a number");

    if (!lua_isnumber(L,3))
        lua_error(L, "Value must be a number");

    k = (int) lua_tonumber(L,2);
    if (k <= 0 || k > A->m*A->n)
        lua_error(L, "Index out of range");

    Mk(A,k) = lua_tonumber(L,3);

    lua_settop(L,0);
    return 0;
\}

\nwendcode{}\nwbegindocs{20}\nwdocspar

\subsection{Matrix arithmetic operations}

The {\tt{}lua{\char95}matrix{\char95}add} and {\tt{}lua{\char95}matrix{\char95}sub} methods are attached
to the add and subtract events.  The {\tt{}lua{\char95}matrix{\char95}unm} method is
attached to the unary negation event.

\nwenddocs{}\nwbegincode{21}\sublabel{NWmatD-regI-4}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-regI-4}}}\moddef{register functions~{\nwtagstyle{}\subpageref{NWmatD-regI-1}}}\plusendmoddef
lua_pushcclosure(L, lua_matrix_add, 0);
lua_settagmethod(L, lua_matrix_tag, "add");
\nwendcode{}\nwbegindocs{22}\nwdocspar

\nwenddocs{}\nwbegincode{23}\sublabel{NWmatD-staG-4}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-4}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_add(lua_State* L)
\{
    int i, j;
    \LA{}get binary operands~{\nwtagstyle{}\subpageref{NWmatD-getJ-1}}\RA{}

    \LA{}check summand conformality~{\nwtagstyle{}\subpageref{NWmatD-cheQ-1}}\RA{}
    C = lua_matrix_create(A->m, A->n);

    for (i = 1; i <= A->m; ++i)
        for (j = 1; j <= A->n; ++j)
            Mij(C,i,j) = Mij(A,i,j) + Mij(B,i,j);

    \LA{}return \code{}C\edoc{}~{\nwtagstyle{}\subpageref{NWmatD-retC-1}}\RA{}
\}

\nwendcode{}\nwbegindocs{24}\nwdocspar

\nwenddocs{}\nwbegincode{25}\sublabel{NWmatD-regI-5}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-regI-5}}}\moddef{register functions~{\nwtagstyle{}\subpageref{NWmatD-regI-1}}}\plusendmoddef
lua_pushcclosure(L, lua_matrix_sub, 0);
lua_settagmethod(L, lua_matrix_tag, "sub");
\nwendcode{}\nwbegindocs{26}\nwdocspar

\nwenddocs{}\nwbegincode{27}\sublabel{NWmatD-staG-5}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-5}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_sub(lua_State* L)
\{
    int i, j;
    \LA{}get binary operands~{\nwtagstyle{}\subpageref{NWmatD-getJ-1}}\RA{}

    \LA{}check summand conformality~{\nwtagstyle{}\subpageref{NWmatD-cheQ-1}}\RA{}
    C = lua_matrix_create(A->m, A->n);

    for (i = 1; i <= A->m; ++i)
        for (j = 1; j <= A->n; ++j)
            Mij(C,i,j) = Mij(A,i,j) - Mij(B,i,j);

    \LA{}return \code{}C\edoc{}~{\nwtagstyle{}\subpageref{NWmatD-retC-1}}\RA{}
\}

\nwendcode{}\nwbegindocs{28}\nwdocspar

\nwenddocs{}\nwbegincode{29}\sublabel{NWmatD-regI-6}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-regI-6}}}\moddef{register functions~{\nwtagstyle{}\subpageref{NWmatD-regI-1}}}\plusendmoddef
lua_pushcclosure(L, lua_matrix_unm, 0);
lua_settagmethod(L, lua_matrix_tag, "unm");
\nwendcode{}\nwbegindocs{30}\nwdocspar

\nwenddocs{}\nwbegincode{31}\sublabel{NWmatD-staG-6}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-6}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_unm(lua_State* L)
\{
    int i, j;
    \LA{}get unary operand~{\nwtagstyle{}\subpageref{NWmatD-getH-1}}\RA{}

    C = lua_matrix_create(A->m, A->n);

    for (i = 1; i <= A->m; ++i)
        for (j = 1; j <= A->n; ++j)
            Mij(C,i,j) = -Mij(A,i,j);

    \LA{}return \code{}C\edoc{}~{\nwtagstyle{}\subpageref{NWmatD-retC-1}}\RA{}
\}

\nwendcode{}\nwbegindocs{32}\nwdocspar

\nwenddocs{}\nwbegincode{33}\sublabel{NWmatD-regI-7}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-regI-7}}}\moddef{register functions~{\nwtagstyle{}\subpageref{NWmatD-regI-1}}}\plusendmoddef
lua_pushcclosure(L, lua_matrix_mul, 0);
lua_settagmethod(L, lua_matrix_tag, "mul");
\nwendcode{}\nwbegindocs{34}\nwdocspar

\nwenddocs{}\nwbegincode{35}\sublabel{NWmatD-staG-7}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-7}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_mul(lua_State* L)
\{
    extern int dgemm_(char* transA, char* transB, int* m, int* n, int* k,
                      double* alpha, double* A, int* ldA,
                      double* B, int* ldB,
                      double* beta, double* C, int* ldC);

    double one  = 1;
    double zero = 0;
    \LA{}get binary operands~{\nwtagstyle{}\subpageref{NWmatD-getJ-1}}\RA{}

    if (A->n != B->m)
        lua_error(L, "Nonconformal matrices");

    C = lua_matrix_create(A->m, B->n);

#ifdef HAS_LAPACK

    dgemm_("N", "N", &(C->m), &(C->n), &(A->m),
           &one, A->data, &(A->ld),
           B->data, &(B->ld),
           &zero, C->data, &(C->ld));

#else
    lua_error(L, "Dense linear algebra routines not linked\\n");
#endif /* HAS_LAPACK */

    \LA{}return \code{}C\edoc{}~{\nwtagstyle{}\subpageref{NWmatD-retC-1}}\RA{}
\}

\nwendcode{}\nwbegindocs{36}\nwdocspar

\nwenddocs{}\nwbegincode{37}\sublabel{NWmatD-getJ-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-getJ-1}}}\moddef{get binary operands~{\nwtagstyle{}\subpageref{NWmatD-getJ-1}}}\endmoddef
lua_matrix_t A, B, C;

if (lua_tag(L,1) != lua_matrix_tag || lua_tag(L,2) != lua_matrix_tag)
    lua_error(L, "Invalid operands");

A = lua_touserdata(L,1);
B = lua_touserdata(L,2);
\nwused{\\{NWmatD-staG-4}\\{NWmatD-staG-5}\\{NWmatD-staG-7}}\nwendcode{}\nwbegindocs{38}\nwdocspar

\nwenddocs{}\nwbegincode{39}\sublabel{NWmatD-getH-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-getH-1}}}\moddef{get unary operand~{\nwtagstyle{}\subpageref{NWmatD-getH-1}}}\endmoddef
lua_matrix_t A = lua_touserdata(L,1);
lua_matrix_t C;
\nwused{\\{NWmatD-staG-6}}\nwendcode{}\nwbegindocs{40}\nwdocspar

\nwenddocs{}\nwbegincode{41}\sublabel{NWmatD-cheQ-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-cheQ-1}}}\moddef{check summand conformality~{\nwtagstyle{}\subpageref{NWmatD-cheQ-1}}}\endmoddef
if (A->m != B->m || A->n != B->n)
    lua_error(L, "Noncomformal matrices");

\nwused{\\{NWmatD-staG-4}\\{NWmatD-staG-5}}\nwendcode{}\nwbegindocs{42}\nwdocspar

\nwenddocs{}\nwbegincode{43}\sublabel{NWmatD-retC-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-retC-1}}}\moddef{return \code{}C\edoc{}~{\nwtagstyle{}\subpageref{NWmatD-retC-1}}}\endmoddef
lua_settop(L,0);
lua_pushusertag(L, C, lua_matrix_tag);
return 1;
\nwused{\\{NWmatD-staG-4}\\{NWmatD-staG-5}\\{NWmatD-staG-6}\\{NWmatD-staG-7}}\nwendcode{}\nwbegindocs{44}\nwdocspar

\subsection{{\tt{}matrix} command}

The {\tt{}matrix} command creates a new matrix of a specified size.
The user is allowed to leave off the second argument $n$;
if it is not explicitly specified, $n$ is assumed to be $1$.
The sizes are only somewhat sanity checked -- there is no
check to make sure that $mn$ is not humongous, and we fail
gracelessly if the memory allocations fail.

After the numeric arguments, the user may also specify a table
of array contents in \emph{row-major} order.  The idea is that
\begin{verbatim}
  A = matrix(2,2, {1, 2,
                   3, 4})
\end{verbatim}
is probably the most natural way to initialize a little two-by-two
example matrix.  It should also be possible to write
\begin{verbatim}
  A = matrix{1, 2, 3}
\end{verbatim}
to get a three-element vector.

\nwenddocs{}\nwbegincode{45}\sublabel{NWmatD-regI-8}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-regI-8}}}\moddef{register functions~{\nwtagstyle{}\subpageref{NWmatD-regI-1}}}\plusendmoddef
lua_register(L, "matrix", lua_matrix);
\nwendcode{}\nwbegindocs{46}\nwdocspar

\nwenddocs{}\nwbegincode{47}\sublabel{NWmatD-staG-8}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-8}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix(lua_State* L)
\{
    int nargs = lua_gettop(L);
    lua_matrix_t A;
    int i,j;
    int m = 0, n = 0;
    int init_table = 0;

    \LA{}get \code{}matrix\edoc{} parameters~{\nwtagstyle{}\subpageref{NWmatD-getP-1}}\RA{}

    A = lua_matrix_create(m,n);

    \LA{}initialize matrix from table~{\nwtagstyle{}\subpageref{NWmatD-iniS-1}}\RA{}

    lua_settop(L,0);
    lua_pushusertag(L, A, lua_matrix_tag);
    return 1;
\}

\nwendcode{}\nwbegindocs{48}\nwdocspar

\nwenddocs{}\nwbegincode{49}\sublabel{NWmatD-getP-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-getP-1}}}\moddef{get \code{}matrix\edoc{} parameters~{\nwtagstyle{}\subpageref{NWmatD-getP-1}}}\endmoddef
for (i = 1; i <= nargs; ++i) \{
    if (lua_isnumber(L,i)) \{
        int val = (int) lua_tonumber(L,i);
        if (val <= 0)
            lua_error(L, "Size out of bounds");

        if      (m == 0)  m = val;
        else if (n == 0)  n = val;
        else              lua_error(L, "Too many size parameters");

    \} else if (lua_istable(L,i)) \{
        if (init_table == 0)
            init_table = i;
        else
            lua_error(L, "Too many initializers");
    \}
\}

\nwalsodefined{\\{NWmatD-getP-2}}\nwused{\\{NWmatD-staG-8}}\nwendcode{}\nwbegindocs{50}\nwdocspar

\nwenddocs{}\nwbegincode{51}\sublabel{NWmatD-getP-2}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-getP-2}}}\moddef{get \code{}matrix\edoc{} parameters~{\nwtagstyle{}\subpageref{NWmatD-getP-1}}}\plusendmoddef
if (m == 0) \{
    if (init_table) \{
        m = lua_getn(L,init_table);
        if (m == 0)
            lua_error(L, "Insufficient initializer entries");
    \}
\}

if (n == 0)
    n = 1;

if (init_table && lua_getn(L,init_table) > m*n)
    lua_error(L, "Initializer too large");

\nwendcode{}\nwbegindocs{52}\nwdocspar

\nwenddocs{}\nwbegincode{53}\sublabel{NWmatD-iniS-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-iniS-1}}}\moddef{initialize matrix from table~{\nwtagstyle{}\subpageref{NWmatD-iniS-1}}}\endmoddef
if (init_table) \{
    int k = 1;
    for (i = 1; i <= m; ++i) \{
        for (j = 1; j <= n; ++j) \{
            lua_rawgeti(L,init_table, k++);
            if (lua_isnumber(L,-1))
                Mij(A,i,j) = lua_tonumber(L,-1);
            lua_pop(L,1);
        \}
    \}
\}
\nwused{\\{NWmatD-staG-8}}\nwendcode{}\nwbegindocs{54}\nwdocspar

\subsection{Matrix {\tt{}print} method}

Matlab's wrapped matrix output format is \emph{really} nice when you
have to inspect matrices of moderate size.  The {\tt{}print{\char95}matrix} routine
emulates Matlab's behavior for {\tt{}format\ short\ e}.

\nwenddocs{}\nwbegincode{55}\sublabel{NWmatD-calP-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-calP-1}}}\moddef{call Lua print for buffer~{\nwtagstyle{}\subpageref{NWmatD-calP-1}}}\endmoddef
lua_pushvalue(L, -1);
lua_pushstring(L, buf);
lua_rawcall(L, 1, 0);
\nwused{\\{NWmatD-staG-9}}\nwendcode{}\nwbegindocs{56}\nwdocspar

\nwenddocs{}\nwbegincode{57}\sublabel{NWmatD-staG-9}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-9}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static void print_matrix(lua_State* L, lua_matrix_t A)
\{
    int i, j, c;
    int m = A->m;
    int n = A->n;
    char buf[256];

    lua_getglobal(L, "print");
    for (c = 1; c <= n; c += 6) \{

        if (n > 6) \{
            sprintf(buf, "  Columns %d through %d\\n",
                    c, (c+5 > n) ? n : c+5);
            \LA{}call Lua print for buffer~{\nwtagstyle{}\subpageref{NWmatD-calP-1}}\RA{}
        \}

        for (i = 1; i <= m; ++i) \{
            char num[64];

            *buf = '\\0';
            for (j = c; j <= n && j < c+6; ++j) \{
                if (Mij(A,i,j))
                    sprintf(num, "  % .4e", Mij(A,i,j));
                else
                    sprintf(num, "            0");
                strcat(buf, num);
            \}
            \LA{}call Lua print for buffer~{\nwtagstyle{}\subpageref{NWmatD-calP-1}}\RA{}

        \}
        buf[0] = ' ';
        buf[1] = '\\0';
        \LA{}call Lua print for buffer~{\nwtagstyle{}\subpageref{NWmatD-calP-1}}\RA{}
    \}
    lua_pop(L,1);
\}

\nwendcode{}\nwbegindocs{58}\nwdocspar

The {\tt{}matrix{\char95}print} routine (also known as the {\tt{}print} method
for a matrix object) uses {\tt{}print{\char95}matrix} to output a reasonably
pretty representation of the matrix.

\nwenddocs{}\nwbegincode{59}\sublabel{NWmatD-staG-A}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-A}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_print(lua_State* L)
\{
    lua_matrix_t A = lua_touserdata(L,-1);

    if (lua_gettop(L) != 1)
        lua_error(L, "Wrong number of arguments");

    print_matrix(L, A);
    lua_settop(L, 0);
    return 0;
\}

\nwendcode{}\nwbegindocs{60}\nwdocspar

\subsection{Matrix {\tt{}factor} method}

The {\tt{}matrix{\char95}factor} function computes $A = PLU$ using LAPACK's %'
{\tt{}DGETRF} routine.

\nwenddocs{}\nwbegincode{61}\sublabel{NWmatD-staG-B}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-B}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_factor(lua_State* L)
\{
    extern int dgetrf_(int* m, int* n, double* A, int* ldA,
                       int* ipiv, int* info);

    lua_matrix_t A = lua_touserdata(L,-1);
    int info;

    if (A->m != A->n)
        lua_error(L, "Matrix must be square");

#ifdef HAS_LAPACK
    if (A->ipiv == NULL) \{
        A->ipiv = calloc(A->m, sizeof(int));
        dgetrf_(&(A->m), &(A->n), A->data, &(A->ld), A->ipiv, &info);
        if (info != 0) \{
            printf("dgetrf failed with error code %d\\n", info);
            lua_error(L, "Error during factorization");
        \}
    \}
#else
    lua_error(L, "Dense linear algebra not linked\\n");
#endif

    lua_settop(L,0);
    lua_pushusertag(L, A, lua_matrix_tag);
    return 1;
\}

\nwendcode{}\nwbegindocs{62}\nwdocspar

\subsection{Matrix {\tt{}solve} method}

The {\tt{}matrix{\char95}solve} function computes $x := A^{-1} x$ given a factored
matrix $A$.  If the matrix has not already been factored, we will factor
it.

\nwenddocs{}\nwbegincode{63}\sublabel{NWmatD-staG-C}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-C}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_solve(lua_State* L)
\{
    extern int dgetrs_(char* trans, int* n, int* nrhs, double* A, int* ldA,
                       int* ipiv, double* B, int* ldB, int* info);

    lua_matrix_t A = lua_touserdata(L,-1);
    lua_matrix_t B;
    int info;

    if (lua_gettop(L) != 2)
        lua_error(L, "Wrong number of arguments");

    if (lua_tag(L,1) != lua_matrix_tag)
        lua_error(L, "Argument must be a matrix");
    B = lua_touserdata(L,1);

    if (A->ipiv == NULL) \{
        lua_matrix_factor(L);
    \}

    if (A->n != B->m)
        lua_error(L, "Dimension mismatch");

#ifdef HAS_LAPACK
    dgetrs_("N", &(A->n), &(B->n), A->data, &(A->ld), A->ipiv,
            B->data, &(B->ld), &info);
    if (info != 0)
        printf("Solve failed with error code %d\\n", info);

#else
    lua_error(L, "Dense linear algebra libraries not linked\\n");
#endif

    lua_settop(L,0);
    lua_pushusertag(L, B, lua_matrix_tag);
    return 1;
\}

\nwendcode{}\nwbegindocs{64}\nwdocspar

\subsection{Matrix {\tt{}clone} method}

The {\tt{}matrix{\char95}clone} function ({\tt{}clone} method) makes a full
copy of a matrix object.

\nwenddocs{}\nwbegincode{65}\sublabel{NWmatD-staG-D}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-D}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_clone(lua_State* L)
\{
    lua_matrix_t A = lua_touserdata(L,-1);
    lua_matrix_t B;
    int j;

    if (lua_gettop(L) != 1)
        lua_error(L, "Too many arguments");

    B = lua_matrix_create(A->m, A->n);
    for (j = 1; j <= A->n; ++j)
        memcpy(&Mij(B,1,j), &Mij(A,1,j), A->m * sizeof(double));

    if (A->ipiv) \{
        B->ipiv = calloc(A->m, sizeof(int));
        memcpy(B->ipiv, A->ipiv, A->m * sizeof(int));
    \}

    lua_settop(L,0);
    lua_pushusertag(L, B, lua_matrix_tag);
    return 1;
\}

\nwendcode{}\nwbegindocs{66}\nwdocspar

\subsection{Matrix {\tt{}slice} method}

The matrix {\tt{}slice} command returns a copy of a subscripted slice
of the matrix $A$.

\nwenddocs{}\nwbegincode{67}\sublabel{NWmatD-staG-E}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-E}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_slice_method(lua_State* L)
\{
    lua_matrix_t A = lua_touserdata(L,-1);
    lua_matrix_t B;
    int n = lua_gettop(L);
    int i1, i2, j1 = 1, j2 = 1;

    \LA{}get slice subscript arguments~{\nwtagstyle{}\subpageref{NWmatD-getT-1}}\RA{}

    B = lua_matrix_slice(A,i1,i2,j1,j2);

    lua_settop(L,0);
    lua_pushusertag(L, B, lua_matrix_tag);
    return 1;
\}

\nwendcode{}\nwbegindocs{68}\nwdocspar

\nwenddocs{}\nwbegincode{69}\sublabel{NWmatD-getT-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-getT-1}}}\moddef{get slice subscript arguments~{\nwtagstyle{}\subpageref{NWmatD-getT-1}}}\endmoddef
if (n != 3 && n != 5)
    lua_error(L, "Wrong number of arguments");

if (!lua_isnumber(L,1) || !lua_isnumber(L,2) ||
    (n == 5 && (!lua_isnumber(L,3) || !lua_isnumber(L,4))))
    lua_error(L, "Subscripts must be numeric");

i1 = (int) lua_tonumber(L,1);
i2 = (int) lua_tonumber(L,2);
if (n == 5) \{
    j1 = (int) lua_tonumber(L,3);
    j2 = (int) lua_tonumber(L,4);
\}

if (i1 <= 0 || i2 < i1 || i2 > A->m ||
    j1 <= 0 || j2 < j1 || j2 > A->n)
    lua_error(L, "Bad subscripts");

\nwused{\\{NWmatD-staG-E}}\nwendcode{}\nwbegindocs{70}\nwdocspar

\subsection{Matrix {\tt{}free} method}

The {\tt{}matrix{\char95}free} function (also known as the {\tt{}free} method)
deallocates the object memory.  It should probably be called on
Lua garbage collection, but it isn't yet.

\nwenddocs{}\nwbegincode{71}\sublabel{NWmatD-staG-F}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-F}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_free(lua_State* L)
\{
    lua_matrix_t A = lua_touserdata(L,-1);

    if (lua_gettop(L) != 1)
        lua_error(L, "Too many arguments");

    lua_matrix_destroy(A);

    lua_settop(L,0);
    return 0;
\}

\nwendcode{}\nwbegindocs{72}\nwdocspar

\subsection{{\tt{}m} and {\tt{}n} fields}

\nwenddocs{}\nwbegincode{73}\sublabel{NWmatD-staG-G}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-G}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_m(lua_State* L)
\{
    lua_matrix_t A = lua_touserdata(L,-1);
    lua_settop(L,0);
    lua_pushnumber(L, A->m);
    return 1;
\}

static int lua_matrix_n(lua_State* L)
\{
    lua_matrix_t A = lua_touserdata(L,-1);
    lua_settop(L,0);
    lua_pushnumber(L, A->n);
    return 1;
\}

\nwendcode{}\nwbegindocs{74}\nwdocspar

\subsection{Method recall}

When a matrix object is indexed by a method name string,
we return a Lua closure that implements the method.
So when the user requests {\tt{}A.print}, for instance,
the returned closure object will have {\tt{}A} as its final
argument when it is called.

On entry, the Lua stack contains the matrix object
and the name string.

\nwenddocs{}\nwbegincode{75}\sublabel{NWmatD-staH-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staH-1}}}\moddef{static prototypes~{\nwtagstyle{}\subpageref{NWmatD-staH-1}}}\endmoddef
static int lua_matrix_getmethod(lua_State* L);

\nwused{\\{NWmatD-matC.2-1}}\nwendcode{}\nwbegindocs{76}\nwdocspar

\nwenddocs{}\nwbegincode{77}\sublabel{NWmatD-staG-H}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-staG-H}}}\moddef{static functions~{\nwtagstyle{}\subpageref{NWmatD-staG-1}}}\plusendmoddef
static int lua_matrix_getmethod(lua_State* L)
\{
    const char* name = lua_tostring(L,2);

    lua_pop(L,1);
    if (strcmp(name, "print") == 0)
        lua_pushcclosure(L, lua_matrix_print, 1);
    else if (strcmp(name, "free") == 0)
        lua_pushcclosure(L, lua_matrix_free, 1);
    else if (strcmp(name, "factor") == 0)
        lua_pushcclosure(L, lua_matrix_factor, 1);
    else if (strcmp(name, "solve") == 0)
        lua_pushcclosure(L, lua_matrix_solve, 1);
    else if (strcmp(name, "clone") == 0)
        lua_pushcclosure(L, lua_matrix_clone, 1);
    else if (strcmp(name, "slice") == 0)
        lua_pushcclosure(L, lua_matrix_slice_method, 1);
    else if (strcmp(name, "m") == 0)
        lua_matrix_m(L);
    else if (strcmp(name, "n") == 0)
        lua_matrix_n(L);
    else
        lua_error(L, "Invalid method name");

    return 1;
\}

\nwendcode{}\nwbegindocs{78}\nwdocspar

\subsection{Public matrix manipulation}

\nwenddocs{}\nwbegincode{79}\sublabel{NWmatD-fun9-1}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-fun9-1}}}\moddef{functions~{\nwtagstyle{}\subpageref{NWmatD-fun9-1}}}\endmoddef
lua_matrix_t lua_matrix_create(int m, int n)
\{
    lua_matrix_t C;

    C = calloc(1, sizeof(*C));
    C->owns_data = 1;
    C->ld = m;
    C->m  = m;
    C->n  = n;
    C->data = calloc(m*n, sizeof(double));
    return C;
\}

void lua_matrix_destroy(lua_matrix_t self)
\{
    if (self->ipiv)
        free(self->ipiv);

    if (self->owns_data)
        free(self->data);

    free(self);
\}

\nwalsodefined{\\{NWmatD-fun9-2}\\{NWmatD-fun9-3}\\{NWmatD-fun9-4}}\nwused{\\{NWmatD-matC.2-1}}\nwendcode{}\nwbegindocs{80}\nwdocspar

\nwenddocs{}\nwbegincode{81}\sublabel{NWmatD-fun9-2}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-fun9-2}}}\moddef{functions~{\nwtagstyle{}\subpageref{NWmatD-fun9-1}}}\plusendmoddef
lua_matrix_t lua_matrix_slice(lua_matrix_t A, int i1, int i2, int j1, int j2)
\{
    lua_matrix_t C;

    C = calloc(1, sizeof(*C));
    C->owns_data = 0;
    C->ld   = A->ld;
    C->m    = (i2-i1)+1;
    C->n    = (j2-j1)+1;
    C->data = &Mij(A,i1,j1);
    return C;
\}

\nwendcode{}\nwbegindocs{82}\nwdocspar

\subsection{Setting and removing vectors}

The {\tt{}lua{\char95}matrix{\char95}push} function is a thin wrapper around
{\tt{}lua{\char95}pushusertag}.  Similarly, {\tt{}lua{\char95}matrix{\char95}get} is a
thin wrapper around {\tt{}lua{\char95}touserdata}.  The only reason we
don't want the user to directly use the {\tt{}lua{\char95}pushusertag} and
{\tt{}lua{\char95}touserdata} functions is that then we would have
to expose the matrix tag value to the world.  That wouldn't
be a tragedy, but it would be nice to keep it private.

\nwenddocs{}\nwbegincode{83}\sublabel{NWmatD-fun9-3}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-fun9-3}}}\moddef{functions~{\nwtagstyle{}\subpageref{NWmatD-fun9-1}}}\plusendmoddef
void lua_matrix_push(lua_State* L, lua_matrix_t matrix)
\{
    lua_pushusertag(L, matrix, lua_matrix_tag);
\}

lua_matrix_t lua_matrix_get(lua_State* L, int index)
\{
    if (index > lua_gettop(L))
        lua_error(L, "Index out of range");

    if (lua_tag(L,index) != lua_matrix_tag)
        lua_error(L, "Variable is not a matrix");

    return lua_touserdata(L,index);
\}

\nwendcode{}\nwbegindocs{84}\nwdocspar

\subsection{Registration functions}

\nwenddocs{}\nwbegincode{85}\sublabel{NWmatD-fun9-4}\nwmargintag{{\nwtagstyle{}\subpageref{NWmatD-fun9-4}}}\moddef{functions~{\nwtagstyle{}\subpageref{NWmatD-fun9-1}}}\plusendmoddef
void lua_matrix_register(lua_State* L)
\{
    lua_matrix_tag = lua_newtag(L);
    \LA{}register functions~{\nwtagstyle{}\subpageref{NWmatD-regI-1}}\RA{}
\}

\nwendcode{}

\nwixlogsorted{c}{{call Lua print for buffer}{NWmatD-calP-1}{\nwixd{NWmatD-calP-1}\nwixu{NWmatD-staG-9}}}%
\nwixlogsorted{c}{{check summand conformality}{NWmatD-cheQ-1}{\nwixu{NWmatD-staG-4}\nwixu{NWmatD-staG-5}\nwixd{NWmatD-cheQ-1}}}%
\nwixlogsorted{c}{{functions}{NWmatD-fun9-1}{\nwixu{NWmatD-matC.2-1}\nwixd{NWmatD-fun9-1}\nwixd{NWmatD-fun9-2}\nwixd{NWmatD-fun9-3}\nwixd{NWmatD-fun9-4}}}%
\nwixlogsorted{c}{{get binary operands}{NWmatD-getJ-1}{\nwixu{NWmatD-staG-4}\nwixu{NWmatD-staG-5}\nwixu{NWmatD-staG-7}\nwixd{NWmatD-getJ-1}}}%
\nwixlogsorted{c}{{get \code{}matrix\edoc{} parameters}{NWmatD-getP-1}{\nwixu{NWmatD-staG-8}\nwixd{NWmatD-getP-1}\nwixd{NWmatD-getP-2}}}%
\nwixlogsorted{c}{{get slice subscript arguments}{NWmatD-getT-1}{\nwixu{NWmatD-staG-E}\nwixd{NWmatD-getT-1}}}%
\nwixlogsorted{c}{{get unary operand}{NWmatD-getH-1}{\nwixu{NWmatD-staG-6}\nwixd{NWmatD-getH-1}}}%
\nwixlogsorted{c}{{initialize matrix from table}{NWmatD-iniS-1}{\nwixu{NWmatD-staG-8}\nwixd{NWmatD-iniS-1}}}%
\nwixlogsorted{c}{{macros}{NWmatD-mac6-1}{\nwixu{NWmatD-matC.2-1}\nwixd{NWmatD-mac6-1}}}%
\nwixlogsorted{c}{{matrix-lua.c}{NWmatD-matC.2-1}{\nwixd{NWmatD-matC.2-1}}}%
\nwixlogsorted{c}{{matrix-lua.h}{NWmatD-matC-1}{\nwixd{NWmatD-matC-1}}}%
\nwixlogsorted{c}{{register functions}{NWmatD-regI-1}{\nwixd{NWmatD-regI-1}\nwixd{NWmatD-regI-2}\nwixd{NWmatD-regI-3}\nwixd{NWmatD-regI-4}\nwixd{NWmatD-regI-5}\nwixd{NWmatD-regI-6}\nwixd{NWmatD-regI-7}\nwixd{NWmatD-regI-8}\nwixu{NWmatD-fun9-4}}}%
\nwixlogsorted{c}{{return \code{}C\edoc{}}{NWmatD-retC-1}{\nwixu{NWmatD-staG-4}\nwixu{NWmatD-staG-5}\nwixu{NWmatD-staG-6}\nwixu{NWmatD-staG-7}\nwixd{NWmatD-retC-1}}}%
\nwixlogsorted{c}{{static data}{NWmatD-staB-1}{\nwixu{NWmatD-matC.2-1}\nwixd{NWmatD-staB-1}}}%
\nwixlogsorted{c}{{static functions}{NWmatD-staG-1}{\nwixu{NWmatD-matC.2-1}\nwixd{NWmatD-staG-1}\nwixd{NWmatD-staG-2}\nwixd{NWmatD-staG-3}\nwixd{NWmatD-staG-4}\nwixd{NWmatD-staG-5}\nwixd{NWmatD-staG-6}\nwixd{NWmatD-staG-7}\nwixd{NWmatD-staG-8}\nwixd{NWmatD-staG-9}\nwixd{NWmatD-staG-A}\nwixd{NWmatD-staG-B}\nwixd{NWmatD-staG-C}\nwixd{NWmatD-staG-D}\nwixd{NWmatD-staG-E}\nwixd{NWmatD-staG-F}\nwixd{NWmatD-staG-G}\nwixd{NWmatD-staG-H}}}%
\nwixlogsorted{c}{{static prototypes}{NWmatD-staH-1}{\nwixu{NWmatD-matC.2-1}\nwixd{NWmatD-staH-1}}}%
\nwbegindocs{86}\nwdocspar
\nwenddocs{}


\section{The \equalrange algorithm}
\Label{sec:equalrange}
\Label{sec:equalrangeii}

The \equalrange algorithm is one of the four binary search algorithms
of the \cxx Standard Library \cite[\S 28.7.3.3]{cxx-17-draft}.
As with the other binary search algorithms \equalrange requires that
its input array is in increasing order.
The specification of \equalrange states that it \emph{combines} the results of the algorithms
\specref{lowerbound} and \specref{upperbound}.

For our purposes we have modified
\equalrange
to take an array of type \valuetype.
Moreover, instead of a pair of iterators, our version returns a pair of indices.
To be more precise, the return type of \equalrange is the
struct \sizetypepair from Listing~\ref{lst:size_type_pair}.
Thus, the signature of \equalrange now reads:

\begin{lstlisting}[style = acsl-block]

  size_type_pair
  equal_range(const value_type* a, size_type n, value_type v);
\end{lstlisting}

Figure~\ref{fig:equalrange} combines Figure~\ref{fig:lowerbound} with Figure~\ref{fig:upperbound}
in order visualize the behavior of \equalrange for select test cases.
The two types of arrows~$\rightarrow$ and~$\dashrightarrow$ represent the
respective fields \inl{first} and \inl{second} of the return value.
For values that are not contained in the array, the two arrows point to the same index.
More generally, if \equalrange returns the pair $(\mathtt{lb},\mathtt{ub})$, then
the difference $\mathtt{ub} - \mathtt{lb}$ is equal to the number of occurrences of the
argument \inl{v} in the array.

\begin{figure}[hbt]
\centering
\includegraphics[width=0.60\textwidth]{Figures/equal_range.pdf}
\caption{\Label{fig:equalrange}Some examples for \equalrange}
\end{figure}

\FloatBarrier

We will provide two implementations of \equalrange and verify both of them.
The first implementation \implref{equalrange} just straightforwardly
calls \specref{lowerbound} and \specref{upperbound} and simply
returns the pair of their respective results.
The second implementation \implref{equalrangeii}, which is more elaborate, follows the
original \cxx code by attempting to minimize duplicate computations.
%
Let $(\mathtt{lb}, \mathtt{ub})$ be the return value  \equalrange, then
the conditions~\eqref{eq:lower-bound-result}--\eqref{eq:upper-bound-right} can
be merged into the inequality
%
\begin{align}
\Label{eq:equal-range-result}
0 \leq \mathtt{lb} \leq \mathtt{ub} \leq n
\end{align}

and the following three implications for a valid index $k$ of the array under
consideration
%
\begin{alignat}{3}
\Label{eq:equal-range-left}
0           &\leq  k < \mathtt{lb} && \qquad\Longrightarrow\qquad &&  a[k] < \mathtt{v} \\
\Label{eq:equal-range-middle}
\mathtt{lb} &\leq k < \mathtt{ub} && \qquad\Longrightarrow\qquad &&  a[k] = \mathtt{v} \\
\Label{eq:equal-range-right}
\mathtt{ub} &\leq k < n           && \qquad\Longrightarrow\qquad &&  a[k] > \mathtt{v}
\end{alignat}

%\clearpage

Here are some justifications for these conditions.

\begin{itemize}
\item
Conditions~\eqref{eq:equal-range-left} and~\eqref{eq:equal-range-right} are just the
Conditions~\eqref{eq:lower-bound-left} and~\eqref{eq:upper-bound-right}, respectively.

\item
The Inequality~\eqref{eq:equal-range-result} follows from the Inequalities~\eqref{eq:lower-bound-result}
and~\eqref{eq:upper-bound-result} and the following considerations:
If $\mathtt{ub}$ were less than $\mathtt{lb}$, then according to~\eqref{eq:equal-range-left}
we would have $a[\mathtt{ub}] < \mathtt{v}$.
One the other hand, we know from~\eqref{eq:equal-range-right} that opposite
inequality $\mathtt{v} < a[\mathtt{ub}]$ holds.
Therefore, we have $\mathtt{lb} \leq \mathtt{ub}$.

\item
Condition~\eqref{eq:equal-range-middle} follows from the combination of~\eqref{eq:lower-bound-right}
and~\eqref{eq:upper-bound-left} and the fact that~$\leq$ is a total order on the integers.
\end{itemize}

%\clearpage

\subsection{Formal specification of \equalrange}

The following listing show the specification of \specref{equalrange}
(and of \equalrangeii).

\input{Listings/equal_range.h.tex}

The precondition \inl{increasing} expresses
that the array values need to be in increasing order.

The postconditions reflect the conditions listed above and can be expressed
using the already introduced predicates
\logicref{AllEqual},
\logicref{StrictUpperBound} and \logicref{StrictLowerBound}.

\begin{itemize}
\item Condition~\eqref{eq:equal-range-result} becomes postcondition \inl{result}
\item Condition~\eqref{eq:equal-range-left} becomes postcondition \inl{left}
\item Condition~\eqref{eq:equal-range-middle} becomes postcondition \inl{middle}
\item Condition~\eqref{eq:equal-range-right} becomes postcondition \inl{right}
\end{itemize}

%\clearpage

\subsection{Implementation of \equalrange}

Our first implementation of \implref{equalrange} is shown in the following listing.
We just call the two functions \specref{lowerbound} and \specref{upperbound}
and return their respective results as a pair.

\input{Listings/equal_range.c.tex}

In a very early version of this document we had proven the similar assertion
\inl{first <= second} with the interactive theorem prover \coq.
After reviewing this proof we formulated the new assertion \inl{aux}
that uses a fact from the postcondition of \specref{upperbound}.
The benefit of this reformulation is that both the assertion \inl{aux}
and the postcondition \inl{first <= second} can now be verified automatically.

%\clearpage

\subsection{Implementation of \equalrangeii}

The first implementation of \implref{equalrange} does more work than needed.
In the following listing \implref{equalrangeii} we show that it is possible to
perform as much range reduction as possible before calling \specref{upperbound}
and \specref{lowerbound} on the reduced ranges.

\input{Listings/equal_range2.c.tex}

Due to the higher code complexity of the second implementation, additional
assertions had to be inserted in order to ensure that \wpframac is able to verify the
correctness of the code.
All of these assertions are related to pointer arithmetic and shifting base pointers.
They fall into three groups and are briefly discussed below.
In order to enable the automatic verification of these properties we
added the following collection of \logicref{ArrayBoundsShift}.

\input{Listings/ShiftLemmas.acsl.tex}

\subsubsection*{The \inl{increasing} properties}

Both \specref{lowerbound} and \specref{upperbound} expect that they
operate on increasingly ordered arrays.
This is of course also true for \specref{equalrange}, however,
inside our second implementation we need a more specific formulation, namely,

\begin{lstlisting}[style=acsl-block]

        Increasing(a + middle, last - middle)
\end{lstlisting}

With the three-argument form of predicate \logicref{Increasing}
we can formulate out an intermediate step.
This enables the provers to verify the preconditions of the call to
\specref{lowerbound} automatically.
A similar assertion is present before the call to \specref{upperbound}.

%\clearpage

\subsubsection*{The \inl{strict} and \inl{constant} properties}

Part of the post conditions of \specref{equalrange} is that \inl{v}
is both a strict upper and a strict lower bound.
However, the calls to \lowerbound and \upperbound only give us

\begin{lstlisting}[style=acsl-block]

        StrictUpperBound(a + first, 0, left - first, v)

        StrictLowerBound(a + middle, right - middle, last - middle, v)
\end{lstlisting}

which is not enough to reach the desired post conditions automatically.
One intermediate step for each of the assertions was sufficient to guide
the prover to the desired result.

Conceptually similar to the \inl{strict} properties
the \inl{constant} properties guide the prover towards

\begin{lstlisting}[style=acsl-block]

        LowerBound(a, left, n, v)

        UpperBound(a, 0, right, v)
\end{lstlisting}

Combining these properties allow the postcondition \inl{middle} to be derived automatically.

%\clearpage


\section{Mathematical Models}
\label{sec:mathmodel}
Based on data volume rates, we do need mathematical models to identify which are the source addresses that may be proponents of an attack.
In letterature we found different approaches, \cite{detection_by_path_analaysis} categorise data into predictable and non predictable data, their mathematical models must be able judge the data by using a threshold. These possible models are the tools for self-similarity analysis such as correlation coefficient and distance matrix. They \cite{detection_by_path_analaysis} use \textit{Pearson's correlation coefficient}, which is defined as:

\begin{equation}
\label{eq:pearson_corr}
	\rho_{X, Y} = \frac{E[(X-\mu_{X})(Y-\mu_{Y})]}{\sigma_X\sigma_Y}
\end{equation}

The correlation is used to measure dependence between two quantities (variables) $X$ and $Y$ with expected values $\mu_X$ and $\mu_Y$ and standard deviations $\sigma_X$ and $\sigma_Y$. Both value of the standard deviations are finite and nonzero ($0 < \sigma_X< \infty$ and $0 < \sigma_Y < \infty$). One of the impressive properties of the correlation is symmetric measurement, in other words, whichever data comes first, we can still get the same result as measuring. In paper \cite{detection_by_path_analaysis} they propose several methodology algorithms, we report two of them
\begin{enumerate}
	\item Correlation between arrival rate and sequence number.
	Denoted $X$ as a sample set of arrival rate ($X = {\label{_k}}$, where $k=$ 0, 1, 2, ..., N) and $Y$ as a sample set of sequence number ($Y = {k}$  where $k=$ 0, 1, 2, ..., N). Calculate the correlation value $(\rho_{X, Y})$ from the two variables: $X$ and $Y$. The expected value is between $-1$ and $1$, $-1 > \rho_{X, Y} > 1 $.
	\item Correlation of self arrival rate. Denoted $X$ as a sample sequence of arrival rate ($X = {\lambda_{(2k)}}$, where $k=$ 0, 1, 2, ..., N) and $Y$ as a sequence number of time interval ($Y = {\lambda_{(2k + 1)}}$ where $k=$ 0, 1, 2, ..., N). Calculate the correlation value $(\rho_{X, Y})$ from the two variables: $X$ and $Y$. The expected value is between $-1$ and $1$, $-1 > \rho_{X, Y} > 1 $.
\end{enumerate}
In order to use the previous mentioned methodology, \cite{detection_by_path_analaysis} define two thresholds: upper $\tau_U$ and lower $\tau_L$. The value of the upper threshold must not exceed 1 and be less than the lower threshold, on the other hand, the value of the lower threshold must not be below 0 and greater than the upper threshold.
These thresholds will help to identify the dependency degree of dependency of the arrival rate data into two categories.
\begin{enumerate}
	\item \textit{Predictable attack rate}: the data will be classified as a predictable attack rate if the correlation value is closed to 0 or 1.
	\item \textit{Nonpredictable attack rate}: the data will be classified as a nonpredictable attack rate if the correlation value is not closed to 0 or 1.
\end{enumerate}
Unfortunately, only one correlation result $\rho_{X, Y}$ cannot
determine whether arrival data is attacking or legitimate, it is
needed a series of correlation result to confirm the situation.
The attack detection must respond as quickly as possible after the attack reaches the victim by using these methods, doing an online analysis.

Since we categorise data, using big data framework in order to analyse log files offline, which may contains attacks, we can not use methodology proposed by \cite{detection_by_path_analaysis}. Using big data we elaborate the log files in order to extract features used for our analysis. For simplicity we explain each one by referring to a single entry which represents an exchange between a source IP and server.

\begin{itemize}
	\item \textit{n\_packets} \\ Represents the amount of packets.
	\item \textit{total\_volume} \\ It is the sum of all packets length.
	\item \textit{time\_difference} \\ It is the time difference between the first communication and the last one, we consider it as a time window.
	\item \textit{ratio\_vol\_td} \\ Represents the volume over seconds exchanged during the time window.
\end{itemize}

The mathematical model must be able to judge the data by using a thresholds, these ones will be provided by our mathematical tool as we will se further on this sections. Other mathematical model are treated in  \cite{detection_by_path_analaysis} even though we reported the important one.

Using \textit{python} in order to manipulate the results returned by \textit{Pig} we decide to use \textbf{standard deviation} as graphical guideline model together with the mean and  \textbf{Quantile Range Outliers} method to identify suspicious source address mathematically.
The formula for the sample standard deviation is

\begin{equation}
\label{eq:standard_dev}
	s = \sqrt{\frac{1}{N-1}\sum_{i=1}^N(x_i - \bar{x})^2}
\end{equation}
where $x_1, x_2\ ...\ x_n$ are the samples values, $\bar{x}$ is the mean and $N$ is the number of samples in the dataset generated by \textit{Pig-latin} script.

The \textit{standard deviation} is a description of the data's spread, how widely it is distributed about the mean.
A smaller standard deviation indicates that more of the data is clustered about the mean.
A larger one indicates the data are more spread out.
Using this information, we started to make inferences about the data.
For example, we could determine whether a particular point was significantly higher above data volume than all others,  whether it represented a statistical anomaly that was worth investigating, based on how many standard deviations away from the mean it was located.

The \textit{quantile range outliers} method of outlier detection uses the quantile distribution of the values in a column to locate the extreme values. Quantiles are useful for detecting outliers because there is no distributional assumption associated with them. Data are simply sorted from smallest to largest. For example, the $20^{th}$ quantile is the value at which 20\% of values are smaller. Extreme values are found using a multiplier of the interquantile range, the distance between two specified quantiles.
In statistics and probability \textit{quantiles} are cut points dividing the range of a probability distribution into continuous intervals with equal probabilities, or dividing the observations in a sample in the same way.

In our work we decide to identify outliers calculating the $25^{th}$ and the $75^{th}$ percentile then we calculate the interquantile rage by doing $Q_{75}-Q_{25}$. We chose $1.5$ as multiplicative $\alpha$ factor for the interquantile.
We use this coefficient as \textit{cut off} for determine upper and lower bound for outliers data, these will represent our thresholds.
The following listing report the code which implements this feature\footnote{In Lst. \ref{lst:qrom} we report only the method applied to data volume exchanged, we do the same for traffic volume (Kb/s)} .

 \begin{lstlisting}[numbers=left, columns=flexible, breaklines=true, frame=tb, caption={quantile range outliers method}, label={lst:qrom}]
    q25, q75 = percentile(dataframe['total_volume'], 25), percentile(dataframe['total_volume'], 75)
    inter_quartile_range = q75 - q25
    # calculate the outlier cutoff
    cut_off = inter_quartile_range * 1.5
    lower, upper = q25 - cut_off, q75 + cut_off
    # identify outliers
    data_outliers = [x for x in dataframe['total_volume'] if x < lower or x > upper]
\end{lstlisting}

We decide to output two plots and one file, \textit{data analysis} which figure out the amount of data, in terms of megabyte, exchanged between a source and the server. \textit{Volume analysis} is like the previous one but represents the data volumes per second exchanged between a source and the server. In the \texttt{.txt} file we report the outliers by IP address and values of analysis we calculates, such as traffic volume and data exchanged.
\bigskip