...\\

...\\

\begin{align}
&x[\;] = \underbrace{x_0 \, x_1 \, x_2 \,\cdots\, x_{31}}_{\text{evt } 0}\, \underbrace{x_{32}\, \cdots\, x_{63}}_{\text{evt } 1}\, x_{64}\, \cdots\\
&y[\;] = \underbrace{y_0 \, y_1 \, y_2 \,\cdots\, y_{31}}_{\text{evt } 0}\, \underbrace{y_{32}\, \cdots\, y_{63}}_{\text{evt } 1}\, y_{64}\, \cdots\\
&I[\;] = \underbrace{0 \, 1 \, 2 \,\cdots\, {31}}_{\text{evt } 0}\, \underbrace{{32}\, \cdots\, {63}}_{\text{evt } 1}\, {64}\, \cdots
\end{align}
This way, $x$ and $y$ coordinates of each hit can be accessed through the same index: $x_n = x[I_n]$, and similarly $y_n = y[I_n]$.\\

For each event, an array \texttt{triplet} is defined (referred as $t$ in the following, for the sake of readability) in order to host the indices of the hits selected for the initialisation of the pattern recognition step:
\begin{align}
&\mathtt{triplet}[\;] = \underbrace{t_0\, t_1 \, t_2}_{\text{XMAX}}\, \underbrace{t_3\, t_4 \, t_5}_{\text{XMIN}}\, \underbrace{t_6\, t_7 \, t_8}_{\text{YMIN}}\, \underbrace{t_9\, t_{10} \, t_{11}}_{\text{YMAX}}\, & \left(\forall\text{ event}\right)
\end{align}
As an example, the following code shows how the \texttt{XMIN} portion of the triplet is populated.\\

\begin{lstlisting}[fontadjust]
#define sq_dist(j,k) ( pow(x[I[j]] - x[triplet[k]],2) + pow(y[I[j]] - y[triplet[k]],2) )
//I[i] = index of the i-th hit
if (i < 3)		
	triplet[i] = I[i];
	
if (x[i] < x[triplet[2]])
{
	if (x[i] > x[triplet[1]])
		triplet[2] = I[i];
	else if (x[i] < x[triplet[1]])
	{
		if (x[i] > x[triplet[0]])
		{
			triplet[2] = triplet[1];
			triplet[1] = I[i];
		}
		else
		{
			triplet[2] = triplet[1];
			triplet[1] = triplet[0];
			triplet[0] = I[i];
		}
	}	
}
\end{lstlisting}

Similarly, \texttt{XMAX}, \texttt{YMIN} and \texttt{YMAX} portions are populated. We obtain an array $\{t_n\}$ such that:
\begin{align}
&x[t_0] \leq x[t_1] \leq x[t_2] \leq x[t_3] \leq x[t_4] \leq x[t_5]\\
&y[t_6] \leq y[t_7] \leq y[t_8] \leq y[t_9] \leq y[t_{10}] \leq y[t_{11}]
\end{align}

These operations are carried out once per event. The indexes used in the code above only fit the first event of the stream, while for the subsequent events the triplet index is transformed as $t_n \longrightarrow t_n + 12 k$, where $k$ is the event index. The array containing triplets will than have the form
\begin{align}
&\mathtt{triplet}[\;] = \underbrace{t_0 \,\cdots\, t_{11}}_{\text{evt } 0}\, \underbrace{t_{12}\, \cdots\, t_{23}}_{\text{evt } 1}\, t_{24}\, \cdots
\end{align}

The operations described so far are executed on a event-y-event basis by the CPU, after reading the event from the network. In principle, this way a slightly higher level of concurrency is reached. In fact, the forming of triplets is interlaced with the readout and accumulation of the packets coming from the TEL62 board, and thus it is performed in parallel to the execution of the GPU kernel, hardly increasing the latency of the whole process.\\

...\\

...\\

The kernel is then executed via a call
\begin{lstlisting}
multiring<<<blocksPerGrid, threadsPerBlock, smemSize,stream_id>>>(gpu_ptr, r_gpu_ptr, utils );
\end{lstlisting}
where \textit{stream\_id} refers to the running stream, \textit{gpu\_ptr} is a pointer to an \texttt{Element} of data stored in the global memory, \textit{r\_gpu\_ptr} points to the memory allocated for the \texttt{Result}, and \textit{utils} provides temporary storage in an \texttt{UTILITY} structure for variables that need to be accessed while executing the circle fitting function.\\

...\\

...\\

A copy of the array \texttt{triplets} will be created in the shared memory of the device, for faster access. 