{'fraction_non_alphanumeric': 0.03619477006311993, 'fraction_numerical': 0.008530207394048693, 'mean_word_length': 4.512575802763695, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 3, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
Selected Topics in Numerical Methods for Cosmology

The large amount of cosmological data already available (and in the near future) makes necessary the development of efficient numerical codes. Many software products have been implemented to perform cosmological analyses considering one or few probes. The need of multi-task software is rapidly increasing, in order to combine numerous cosmological probes along with their specificity (e.g., astrophysical descriptions and systematic errors). In this work we mention some of these libraries, bringing out some challenges they will face in the few-percent error era (on the cosmological parameters). We review some concepts of the standard cosmological model, and examine some specific topics on their implementation, bringing, for example, the discussion on how some quantities are numerically defined in different codes. We also consider implementation differences between public codes, mentioning their advantages/disadvantages.


Introduction
Cosmology is dedicated to study the evolution of the Universe since its primordial epoch until today. The description and modeling of its different stages and observables are, in general, divided into two classes: deterministic and stochastic predictions. The standard model of cosmology is described by the General Relativity (GR) theory of gravitation with a homogeneous and isotropic background metric, which provides deterministic predictions for some cosmological observables. On top of this background an inhomogeneous description is laid, usually through a perturbation theory, for which the predictions are of stochastic nature. For instance, the distances are among the cosmological/astrophysical observables related just with the background. In contrast, the perturbations describe all the deviations from a homogeneous and isotropic universe, for this reason, were it deterministic, it would have to describe all astrophysical object positions and properties in a given scale. Such deterministic description for perturbations is unfeasible and consequently a probabilistic approach is chosen. This means that instead of describing the exact positions and properties of each astrophysical object in a given scale, we model the probability distribution of these quantities. For example, when describing the mass distribution in the universe, we use the matter power spectrum P m , which is a simple way to express the (Gaussian) probability distribution of finding a given matter contrast function δ m (x) ≡ δρ m (x)/ρ m (δρ m denotes the perturbation of the matter energy density around its mean value ρ m ).
Furthermore, the initial conditions for the very early universe are given in terms of the quantization of its initial perturbations (e.g. in an inflationary scenario, for a review see [1]). So, apart from the problem of decoherence (the evolution from quantum to classical probability distributions, for example see [2]), the initial conditions are already given in terms of stochastic distributions. Nevertheless, observations provide positions and characteristics of actual astrophysical objects as well as the errors in these determinations. Consequently, we have two sources of indeterminacies, the probabilistic aspect of the observation errors and the stochastic nature of our modeling.
In practice we have two classes of problems in numerical cosmology. The first being related to background observables, such as the distance modulus of type Ia supernovae (SNeIa), cosmic chronometers and H 0 determination. These depend on quantities determined solely by the background model. For this reason, the numerical methods involved are simple and usually require solutions of a small set of Ordinary Differential Equations (ODEs). Once the background is computed, the comparison with data is done by taking into consideration the statistical errors in the observables' determination. Any observable in this class is extremely useful since they depend only on background modeling and, consequently, do not rely on the more sophisticated (but more complex) description of the inhomogeneous universe. The second class is composed by the observables related to the inhomogeneities. For example, Cosmic Microwave Background (CMB) radiation, Large Scale Structure (LSS) observables, such as galaxy spatial correlation, galaxy cluster counts and correlation, and gravitational lensing. For some of these observables, e.g. CMB, the linear perturbation theory is enough (up to a given scale) to compute the observable statistical distribution, whereas for others, e.g. galaxy spatial correlation, the perturbation theory must be corrected for scales beyond its validity.
In the last two decades Cosmology has became a data-driven science thanks to the large amount of high-quality observational data that has been released [3][4][5][6]. The complexity of the theoretical model of the observables along with their astrophysical features requires sophisticated numerical and statistical tools. In this chapter, we will discuss some of the numerical and statistical methods that have been largely used in Cosmology. Most of these methods can be found in the Numerical Cosmology (NumCosmo) library [7], which is a free software written in C on top of the GObject 1 and GObject Introspection 2 tools. 3 Popular codes such as CAMB (https://camb.info/) [8][9][10] and CLASS (http://class-code.net/) [11][12][13][14] are used to compute both background and perturbation (linear and non-linear) quantities. Their statistical counterparts, respectively, CosmoMC [15,16] and MontePython [17], implement not only the observable likelihoods but the tools necessary to explore the parameter space of the underlying models mainly through Markov Chain Monte Carlo (MCMC) method. In Sec 2.1 we describe the numerical approaches to solve the background model and the observables related to it. In Sec 3 we introduce the tools to solve the linear perturbation problem along with the related observable quantities. At last, in Sec 4 we discuss the most common cancellation errors found in numerical cosmology.

Numerical Methods
In the next sections we will briefly outline the theoretical aspects of the background model and then move to the discussion on how to solve them numerically.

Background
In this section we will describe the different ways to compute observables related to the background cosmology, for this reason we introduce the necessary concepts as we go, for a detailed discussion on these see for example [18,19]. The majority of the cosmological models relies on a metric theory. In particular, we consider the homogeneous and isotropic metric, also known as the Friedmann-Lemaître-Robertson-Walker metric (FLRW), where c is the speed of light and for respectively flat, spherical and hyperbolic spatial hyper-surfaces. This metric has just one function to determine, the scale factor a(t), and the Gaussian curvature K. In practice (which is the case for all cited softwares) we use instead of K, the curvature density parameter at the present day Ω 0 K ≡ −Kc 2 /(a 0 H 0 ) 2 , where the super and subscript 0 indicate the quantity today, the Hubble parameter H 0 =ȧ/a| 0 anḋ denotes the derivative with respect to the cosmic time t. Note that theoretical work usually define K ∈ {−1, 0, 1} (using a given unit, such as Mpc −2 ) generating an one-to-one relation between a 0 and Ω 0 K , while in numerical codes, such as CAMB, CLASS and NumCosmo, it is habitual to let a 0 as an arbitrary value defined by the user and use the definition above to determine K through Ω 0 K . In practice, we do not measure a(t) directly, but related quantities such as the distances to astronomical objects. Considering a null trajectory of photons emitted by a galaxy traveling along the radial direction to us, we have that where t e and t 0 are the emitted and observed times (here t 0 represent the present time). Note that r refers to the distance at the comoving hyper-surface, i.e., the hyper-surface where a(t c ) = 1 [see Eq. (1)]. This means that r is the distance between the point of departure and arrival both projected (through the Hubble flow) back to the comoving hyper-surface. In other words, using the coordinates in Eq. (1), we define a foliation of the space-time where each sheet is defined by t = constant, then the photon leaves the source at t e at the point p e within the t e hyper-surface and arrives at point p 0 at the hyper-surface t 0 . Since p e and p 0 are defined at different hyper-surfaces we need to transport them to the same hyper-surface in order to have a meaningful definition of spatial distance between them. Then we project both points p e and p 0 at the comoving hyper-surface by following the Hubble flow that passes through these points back to the hyper-surface t c [a(t c ) = 1] where r gives the spatial distance between them. In the literature it is often defined a 0 = 1 (for the flat case), that is, the comoving hyper-surface coincides with today's hyper-surface and r would provide the distance between points today. However, as discussed above in the numerical codes one needs a general definition for the whole parameter space (in this case for any value of Ω K ). For this reason, we keep a 0 arbitrary and define the comoving distance projected back to today's hyper-surface as where the Hubble radius is d H = c/H 0 , E(z) = H(z)/H 0 is the normalized Hubble function, and the distance is now written in terms of the observable z that is the redshift, Finally, similar to the comoving distance we introduce the comoving time where we chose the conformal time such that η(t = 0) = 0. The only differences between the comoving and the conformal distances are a factor of a 0 and the integration limits.

Time variables
When solving the background it is usually useful to choose which variable to use as time. This is particularly important if the evolution of the perturbations will be also computed, since it requires the evaluation of several background observables for each time step in the perturbations' integration.
We first note that there is an one-to-one relation between z, a and d c (both a 0 and t 0 are fixed quantities). 4 The relation between these variables and the cosmic time requires the choice of a reference hypersurface to anchor the time definition. For instance it is common to choose t = 0 to mark the singularity of the classical FLRW metric, i.e., a(0) = 0. This choice has some drawbacks. In order to compute t(z) or η(z), for example, we need to evaluate However, the above integrals include the whole history of the background metric, from t = 0 (z = ∞) to z. This means that, in practice, we need to know the values of H(z) for this whole range, including the matter-dominated phase, radiation phase, inflationary or bounce phase, etc. The available numerical codes include the computation of t(z) and/or η(z). But one should remark that these quantities are obtained from integrals as above and extrapolating the radiation phase till the singularity, i.e., they ignore any inflationary or bounce phases and assume a radiation dominated singularity in the past. Both NumCosmo and CAMB compute the times t and η integrating the Hubble function H(z) and extrapolating the radiation era till the singularity. CLASS uses the approximation of η(z) ≈ (1 + z)/(a 0 H) = 1/(aH) which result from assuming H(z) ∝ (1 + z) 2 for z in the radiation era. This means that there will probably be small shifts between the η variable when comparing different codes, furthermore, the choice of precision (and technique) used in the integration may also result in small differences.
Another option for time variable, used by different objects in NumCosmo, is the scale factor a or its logarithm α ≡ − ln(a). 5 Of course, such variable cannot be used when the Hubble function H change signs (for example in a bounce). But this variable is useful when describing the expansion phase since it is possible to obtain an analytic expression for H(a) in different scenarios. In these cases we do not need to solve the integrals (7) to relate H and the time variable.

Distances
The base of several cosmological observers are the cosmological distances. Besides the comoving distance [Eq. (4)] other useful distances are: the transverse comoving d M (z), the angular diameter d A (z) and luminosity distances d L (z), respectively defined as [20]: 4 The relation between z and d c is monotonic since E > 0. 5 The minus sign in the definition of α is included in order to α monotonically increases with t or η.
In its turn, the Hubble function H(z) can be recovered using observational data, which allows the model-independent approaches (see [21] and references therein) besides the usual modeling assuming a theory of Gravitation, i.e., independent of the equations of motion discussed in the last section. Figure 1 shows the comoving distance for different values of the Hubble parameter H 0 , the matter density parameter Ω m and the dark energy (DE) equation of state w DE = constant. Note that these quantities are sensitive to the cosmological parameters and, therefore, observables related to the distance measurements are important to discriminate among the possible values of these parameters. Three of these observables are the distance modulus of type Ia supernovae (SNe Ia) [22,23], the baryon acoustic oscillations (BAO) [24] and the so-called cosmic chronometers.

Equations of motion
Up to this point we discussed the kinetic aspects of our choice of metric. Nevertheless, we need a way to compute the time evolution of a(t) in order to calculate the quantities above. In this section we will discuss the equations of motion in the context of GR.
The standard cosmological model assumes GR and the FLRW on large-scales and thus, the equations of motion are given by the so-called Friedmann equations, where G is the gravitational constant, ρ and p are the energy density and pressure of the matter-energy content of the universe, which is composed by radiation (photons and relativistic neutrinos), matter (Dark Matter (DM), baryons and neutrinos) and DE. Their equation of state, p = wρ, are Matter : w m = 0 , Dark Energy : The DE component of the standard model is, in general, described by the cosmological constant Λ, in which w DE = −1. It is clear from the Friedmann equations that we need additional equations of motion to close the system, i.e., we need equations of motion that determine ρ i and p i (or w i ), where i represent the possible components. If the matter component is minimally coupled with the theory of gravitation and its energy-momentum tensor is "conserved" (satisfy ∇ µ T µν i = 0), the imposition that this tensor is compatible with a Friedmann metric results in the following equation of motion for ρ i : There are two important lessons to get from the above equation. Firstly, Eq. (15) is not enough to close the system of equations and, therefore, we still need a way to determine p i . This occurs due to the fact that Eq. (10) is a constraint equation (see Sec. 2.5 for more details ) and, consequently, Eq. (11) can be derived from Eqs. (10) and (15). One common example to solve the system and obtain ρ i (t) is to consider simple components, as discussed above, where w i is a constant. We have different options for more complicated fluids. For instance, for a scalar field ρ i and p i are functions of the field variable and the equation of motion of the scalar field can be used to close the system (in this case Eq. (15) is redundant). For a statistical description one can use the background compatible Boltzmann equation to describe the phase-space distribution f i (x µ , p µ ) and obtain ρ i and p i from it [which is the case of the equations of state Eqs. (12)- (14)]. Finally, one can model p i (or w i ) directly using a phenomenological approach.
The second lesson refers to the choice of the time variable. That is, if we rewrite Eq. (15) using a as a time variable, we obtain ∂ρ i ∂a This simple manipulation has an important consequence. The factor H that couples the original equation with all other components was eliminated. This means that, for the case where p(ρ) is a known function, this equation can be solved without knowing any of the other components present in the system. This is one of the reasons why this kind of modeling [p i (ρ i ), w i (a), . . . ] is so popular. It allows to obtain a solution for ρ i independently of the other matter components and/or the gravitational theory. Note that the density is a function of the time, , and it is not feasible to use observational data in order to recover ρ(t) as given in the present form. Therefore, similarly to the curvature parameter K (see Sec. 2.1), we rewrite Eq. (10) in terms of the redshift z and define the density parameters as where i stands for the radiation (r), matter (m) and DE components. 6 Thus, Eq. (10) now reads Computing this equation at z = 0, we obtain the constraint which reduces by one the size of the parameter space to study the recent expansion evolution of the universe. In short, in the context of GR and homogeneous and isotropic metric, one needs to estimate the following set of cosmological parameters: where Ω K is then determined by Eq. (19). Assuming a flat universe, Ω K = 0, which is largely considered in the literature given the CMB constraints [3,5], we end up with the restriction

Integrating and evaluating the background
In the last sections we described the observables related to the background model. In order to compute them we need to integrate this model and save the results in a way that they can be used in statistical calculations. Both tasks are crucial in numerical cosmology since the evolution of the perturbations 6 Note that here we are defining Ω i as a constant evaluated today, in the literature it is also frequently found the definition as a function of z, i.e., relies on several evaluations of the background model at different times and, in a statistical analysis, these quantities need to be recomputed at different points of the parameter space. For these reasons the computation and evaluation times are bottlenecks for this kind of analysis.

Integration strategies
There are different strategies to integrate the background equations of motion. First of all we need to choose how to integrate the gravitational part. The Friedmann equations comprehend a dynamical equation (11) and a constraint equation (10). This means that, in principle, we need to solve the dynamical equation and impose the constraint equation in our initial conditions. In other words, to solve Eq. (11), we need the initial conditions for both a andȧ but this choice must satisfy Eq. (10). It is worth noting that, since the choice of an initial value for a is arbitrary, Eq. (11) ends up determining the initial conditions completely. Therefore, in this context, there are no dynamical degrees of freedom left for the gravitational sector, i.e., the imposition of homogeneous and isotropic hypersurfaces removes the dynamical degrees of freedom.
In practice we want to solve the Friedmann equations in the expansion branch (H > 0). For this reason we know a priori the sign of H. Therefore, we can take the square root of Eq. (10), and solve it instead of solving Eq. (11). We can even go further, if all matter components decouples from gravity, as we discussed in Sec. 2.4, then we have an analytical solution for H given by Eq. (18) if we choose z (or a) as our time variable. It is useful to review the steps that allowed an analytical solution for H. First, all matter components decoupled from the system as we argued in Eq. (16). For this reason we were able to find solutions for ρ i as functions of a (or any other time algebraically related to a). Second, we used the first order Friedmann equation (10) to determine H 2 . Finally, we assumed that the model will always be in the expansion branch H > 0 allowing then the determination of H as a function of a. If any of these conditions were missing, i.e., one component not decoupling or the indetermination of H sign, the solution would involve the whole system.
In the general purpose code, like CLASS or CAMB, one cannot assume that all matter components decouples from H. This happens because they include the possibility of modeling the dark energy as a scalar field and the scalar field equation of motion does not decouples from H. For instance, a scalar field ϕ with canonical kinetic term and arbitrary potential V(ϕ) satisfies, In particular, CLASS chooses the conformal time in unit of mega-parsec (Mpc) to integrate all quantities. We summarize the strategy implemented in CLASS in the following. They first analytically integrate every component that decouples from the system, e.g., the cold dark matter and baryon fluids, and implement the energy density and pressure related to these quantities as functions of a. Moreover, they implement the energy density and pressure of more complicate components in terms of their internal degrees of freedom. For instance, a scalar field from the above example has where the internal degrees of freedom are ϕ andφ. They use the label 'A' to reefer to the first set, the functions of a and the internal degrees of freedom [ρ ϕ (ϕ,φ) and p ϕ (ϕ,φ) in the last example], and the label 'B' for all internal degrees of freedom [a(t), ϕ(t),φ(t) in the last example]. All other functionals of these quantities, such as the distances defined in Sec. 2.3, are labeled as 'C'. Finally they implement the equations of motion for the 'B+C' set and integrate all variables with respect to the chosen time variable η. We have two options to perform the 'B+C' integration: (i) integrate all at once or (ii) to first integrate 'B' and then use the respective results to integrate 'C'. Some possible advantages of integrating all variables 'B+C' together are: 1. simplicity, one needs to integrate a system of variables with respect to time just once; 2. less integration overhead, the integration software itself has a computational cost. Each time it is used there are the costs of initialization, step computation and destruction.
On the other hand, the possible shortcomings are: 1. step sizes smaller than the necessary. When performing the integration, the Ordinary Differential Equations (ODE) solver evaluates the steps of all components being integrated and adapts the time step such that the error bounds are respected by all components. For this reason, including the 'C' set in the integration can result in a larger set of steps for all quantities 'B+C'; 2. lack of modular format, in some analysis just a few (or just one) observables from 'C' are necessary.
When performing all integration at once you have two options, integrate everything every time, even when they are not all necessary, or to create a set of flags that control which quantities should be integrated by branching (e.g., if-statements). Naturally, the if-clauses create an unnecessary overhead if they are placed inside the integration loop. Alternatively, if one decides to create a loop for every combination to avoid this overhead, then he/she will end-up with 2 n different loops (where n is the number of variables in 'C') which creates new problems such as code repetition and harder code maintenance.
In CLASS they integrate first 'B' and then use the results to compute 'C'. However, they do not integrate the variables in 'C'. They just get the resulting knots from 'B' integration and compute at the same knots the values of 'C' , and then add to a large background table enclosing every variable in 'A+B+C'. This table is then used to compute the background variables at any time using a spline interpolation. This means that no error control were used to compute the 'A' and 'C' variables, even though it was used to compute 'B'.
In NumCosmo, they also integrate 'B' first, but the 'C' set is handled differently. First, all variables that are algebraically related to each other are identified. For example, the distances discussed in Sec. 2.3 can be computed from the comoving distance without any additional integration. Then a minimal set of variables in 'C' is identified and for each one a different object is built. For instance, the ones related to distances are included in the NcDistance object. This object, when used, integrates the comoving distance using the results from 'B' present in the basic background model described by a NcHICosmo object. The integration is done requiring the same error bounds as in 'B' and a different spline is created for the comoving distance, with different time intervals.
At this point the main differences between CLASS and NumCosmo are that the first does not integrate 'C', it simply interpolates them based on a fixed grid choice, and does not have a modular structure for the computations of 'C'. Nevertheless, the non-modular design choice is understandable. When CLASS was first conceptualized it intended to be a Boltzmann solver, thus, it is natural to always integrate all quantities in 'C' that are needed to compute the time evolution of the perturbations. But now, CLASS is slowly migrating to a general purpose code as the cosmological basis for different numerical experiments usually performed by MontePython [17]. At the same time, NumCosmo was designed from the ground-up to be a modular general purpose library to handle different cosmological computations.

Evaluating the background
As we previously described, the integration output is usually saved in memory such that it can be used latter through interpolation. In principle it would be also possible to just integrate everything necessary at once. This can work for a simple code, e.g., if we just need the conformal distance at some predefined set of redshifts. However, in many other cases this would lead to a very complicated code. For example, when integrating perturbations, we need to integrate it for different values of the mode k. This means that we would have to integrate the background and all modes k at the same time. Not only that would be complex (a multi-purpose code written like this would require a huge number of branches to accommodate the different code usage), but sometimes one does not know a priori which modes k need to be integrated.
For this reason a good interpolation method is a central part of any numerical cosmology code. The most common approach is the use of splines, which avoids the Runge phenomenon for interpolation with several knots. A spline is defined as a piecewise polynomial interpolation where each interval is described by a polynomial of order k and the whole function is required to be C k−1 , i.e., a function with k − 1 continuous derivative, see [25] for a detailed description of spline and its characteristics. It is clear that such piecewise function has (n − 1)(k + 1) degrees of freedom where n is the number of knots, imposing continuity up to the k − 1 derivative gives us (n − 2)k constrains (remember that the continuity is imposed only on the internal knots), therefore, there are (n − 1)(k + 1) − (n − 2)k = n + k − 1 degrees left to determine. In practice, we interpolate functions that we know its values at the n knots, still leaving us with k − 1 degrees of freedom to determine.
The simplest choice is the linear spline (k = 1), in this case there are no extra degrees of freedom to determine, nonetheless, the resulting function is not very smooth, it is actually only continuous (C 0 ), and the interpolation error is proportional to h 1 max | f (x)|, where h is the largest distance between two adjacent knots and f (x) is the function being interpolated and the derivative with respect to x. Hence, a linear spline is appropriated only for really small h (large number of knots) or for functions with small first derivatives. When we move to larger k we end up with the problem of choosing k and then determining the extra k − 1 degrees of freedom. The first problem is solved in a geometrical manner, the cubic splines k = 3 are the ones that minimize b a dx [ f (x)] 2 , where a and b are the endpoints of the complete interval being interpolated. This means that the cubic interpolation produces functions with small curvature that still matches f (x) at the knots. This is a reasonable requirement, we are usually interested in interpolating functions that does knot wiggle strongly between knots.
Choosing the cubic spline we then need to fix the remaining 2 degrees of freedom. This is usually done by imposing boundary conditions on the interpolation function p(x). For example, one can impose a value for p (a) = f (a) and p (b) = f (b), which requires the knowledge of the derivative of f (x) at the interval extremities. Since this information is usually not available other approaches are necessary. The so-called natural splines impose that the second derivatives of the interpolating function to be zero at a and b, i.e., p (a) = p (b) = 0, this algorithm can be found at the GNU Scientific Library (GSL) [26]. Nevertheless, the imposition of an arbitrary value for the second derivative results in a global interpolation error proportional to h 2 , instead of the original h 4 . Another approach is to estimate the derivative at the boundaries and use it to fix p (a) and p (b), this is the approach followed by CLASS (at least up to the version 2.6), however, here we need to find a procedure that will result in a O(h 4 ) error bound. Currently, CLASS uses the forward/backward three point difference method which as an error bound of only O(h 3 ) which spoils the global O(h 4 ) error bound of the spline interpolation. To keep this error bound it is necessary a higher order approximation for the derivatives [25,27]. Finally, this can also be solved by imposing an additional condition on the interpolating function, in the not-a-knot procedure we impose that the third derivative is also continuous at the second and one before last knots. This condition maintains the global O(h 4 ) error bound and can be easily integrated in the tridiagonal system used to determine the spline coefficients, see [25] and [7, ncm_spline_cubic_notaknot.c] for an implementation.
It is also worth mentioning that there are other similar choices of interpolation. For example, in the Akima interpolation [25, pg. 42] one estimates the first derivative at each knot using a simple two-points forward/backward finite difference method and then use them and the function values to determine a cubic polynomial at each interval. The resulting interpolation function is not a spline since it is only C 1 and the interpolation error O(h 2 ) is worse than a not-a-knot spline, nevertheless, it is a local algorithm since it depends only on the knots and their nearest neighbors and also simpler and faster. On the other hand, the difference in speed for a spline algorithm is usually irrelevant. Notably, the LSST-DESC Core Cosmology Library (CCL) [28] is using the Akima interpolation as its default method (up to version v1.0.0).
When using interpolation through piecewise functions we have an additional computational cost when evaluating the function. Given an evaluation point x we need to determine to which interval this point belongs to. This is usually accomplished performing a binary search (see [29], for example), which is in the worst case O(log n), where n is the number of knots. Some libraries, GSL for example, also provide an accelerated spline, i.e., in a nutshell it saves the interval of the last evaluation and tries it first in the next one. The rational here is that one usually evaluates the spline in an ascending/descending in small steps (for instance, when integrating). However, this has some disadvantages. First, if the evaluation is not done in an ascending/descending order, it becomes useless. Since it saves the last step in memory and modifies it in every step, it cannot be used in a multi-threaded environment in a simple way. 7 Finally, the determination of the interval usually contributes very little in the computation time, thus, in general, it is safer and simpler to not use this kind of optimization.
The last point about the evaluation of piecewise functions is the determination of the knots. In most codes this is done through some heuristic algorithm, in most cases the programmer uses the fixed end-points a and b and simply chooses the knots with linear/logarithm spacing, namely, where i ranges from 0 to n − 1 and n is the number of knots (sometimes a combination of these two is used). This approach has several pitfalls, first it is not clear the relation between n and the final interpolation error. Hence, the final user has to vary the value of n until he/she gets the desired precision. In a complex code there are sometimes very large number of splines and, consequently, the user has to play with a large set of control variables (for example n j where j labels the different splines in the code, the point where to change from linear to logarithm scale, etc) to attain a certain precision. Actually, the problem is even worse, the user can choose all control parameters, but in practice one does that for a given model with one fixed set of parameters (in the best case scenario a large number of parameter sets are used). In a statistical analysis the model is evaluated at different points of the parameter space and nothing guarantees that the precision at these points will remain the same as in the points where it was calibrated. This problem is magnified in large parameter spaces considering that, in this case, it is harder to check for precision in the whole parameter space. We will close this section discussing two different methods to determine the knots in a way that is adaptive to the desired precision. However, this is usually algorithm-specific and need to be dealt case by case. First, consider the case where the function to be interpolated is the result of an integral or a solution of an ODE system. When it comes from an integral, we have It is easy to transform this problem in a one-dimensional ODE, i.e., Now, the integral or the ODE system can be solved with the many available ODE integrators (see for example the excellent library SUNDIALS [30]). The ODE solvers adapt the step automatically in order to obtain the desired precision, moreover the step procedure is based in a polynomial interpolation. For these reasons we can use the same steps to define the knots to be used in the interpolation. In other words, the ODE solver computes the steps necessary to integrate a function such that inside these steps the function is well approximated by a polynomial (given the required tolerance), therefore, it is natural to use the same steps to interpolate the function afterwards. The second method is applicable when we have a function f (x) with a high computational cost. When this function needs to be evaluated several times, it is more efficient to build a spline approximation first and then evaluate the spline. As a rule of thumb, this is useful if the function f (x) will be evaluate more than n times, where n is the number of knots you need to create the spline interpolation. The method consists in comparing the value of the function f (x) and its spline approximation p(x) inside of each interval of p(x), i.e., if p(x) is defined with n knots we compute the difference for each n − 1 intervals, where x i+1/2 = (x i + x i+1 )/2. For each interval where e i does not satisfy the tolerance requirements (e i < f (x i+1/2 )r + a, where r is the relative tolerance and a the absolute tolerance), we update the spline adding this new point (creating two new intervals) and mark them as not OK (NOK). The intervals where the tolerance is satisfied are marked as OK. After the first iteration throughout all knots repeat the same procedure for all intervals marked NOK, then repeat until all intervals are marked OK. An implementation of this algorithm can be found at [7, ncm_spline_func.c]. Some variants of this algorithm are also useful, for instance, instead of using the midpoint (x i + x i+1 )/2 one can also use the log-midpoint exp [(ln x i + ln x i+1 )/2] for positive definite x i . 8 We presented above two methods to control errors when computing interpolation functions. We argue that this kind of error control based on a single tolerance parameter is essential for the numerical tools aimed for cosmology and astrophysics. 9 The sheer amount of different computations needed to evaluate the cosmological and astrophysical observables require complex codes which handles many different numerical techniques. For this reason well design local error controls are necessary to have a 8 When x i are not positive definite one can use a similar algorithm with ln x i → arctanh(x i /s) and exp → tanh, where the is a scale s controls the transition between linear and log scale. 9 Usually the relative tolerance controls the final error of the code while the absolute tolerance is application specific and, in the few cases where it is used, it serves to avoid excess in the tolerance. For example, if a given function f is zero at a point x and we want to compute its approximation p, the error control is So, without the absolute tolerance, the error control would never accept the approximation, unless it was a perfect approximation p(x) = 0. final error control based on the tolerance required by the observable. This is also crucial when evaluating non-standard models, in these cases the codes tend to be less checked and tested, and after all they are usually only used by the group that developed it. This same problem is also present in standard models but in regions of the parametric space far from the current expectations. These regions tend to be much less tested and sometimes excluded from the allowed parameters range.

Linear Perturbations
On top of the background standard model discussed in Sec. 2.1, we have the perturbation theory with which we describe the evolution of Universe from the initial primordial fluctuations to the structure formation and their imprints on the observables we measure. In this section we will have a lightning review of perturbation theory in cosmology (a full description can be found in [19]) and then we explore a single component scalar perturbation equation in order to exemplify the common numerical challenges involved in this context. First, we need to extend our assumptions about the space-time geometry. Lets call the background metric components in Eq. (1) by g µν . Now we assume that the metric describing our space-time is given by where h 00 = 2φ, where D i is the covariant derivative with respect to the spatial projection of the background metric. Here we are assuming that the metric is described by a Friedmann metric plus small deviations, all degrees of freedom but the scalars are ignored, leaving us with the fields (φ, ψ, B, E). The physical idea is that a Friedmann metric is a good approximation and all deviations from it can be described by a small perturbation. There are several important theoretical aspects of this description that we are not going to discuss here, ranging from gauge dependency [31][32][33], size validity of the approximation [34,35] and its theory of initial conditions [19]. Instead, we focus only on the numerical methods to solve the perturbation equations of motion and evaluating the result. In order to be compatible with our choice of metric we require that the energy momentum tensor must also be split into a background plus perturbations, following a similar decomposition that we made for the metric. This produces the following scalar degrees of freedom (δρ, δp, V, Π), where δρ and δp are the perturbations of the total energy density and pressure respectively, V the velocity potential and Π the anisotropic stress. Now we have a much more complicated problem than the background. There are eight degrees of freedom to determine among metric and energy momentum tensor perturbations. This problem can be simplified by writing the equations of motion in terms of geometric quantities, i.e., Here all variables are defined with respect to the background foliation, D 2 is the spatial Laplacian and D 2 K ≡ D 2 + 3K/a 2 [where K is the spatial curvature of the background metric (1)], a i represent the acceleration of the Hubble flow, σ the shear potential for the Hubble flow lines, δH the perturbation on the Hubble function and finally δR the perturbation on the spatial Ricci tensor. In terms of these variables the first order Einsteins equations are 3δ where κ ≡ 8πG and taking c = 1. The energy-momentum conservation provides two additional equationṡ However, it is easy to check that these two equations are not independent from Einsteins equations. It is a straightforward exercise to show that they can be obtained, respectively, by differentiating Eqs. (26) and (27) and combining with the Eqs. (26)- (29). Thus, we have eight variables and only four equations of motion. Note, however, that E and B do not appear explicitly in the equations of motion, actually they appear only in the variable σ. This is an artifact from the gauge dependency of the perturbations, but since these equations are invariant through spatial gauge transformation, they are automatically written in terms of variables invariant under this gauge transformation (for mode details see [33], for example). The gauge transformations with respect to the scalar degrees of freedom involve two scalar variables, one representing the spatial transformations that we just discussed and another generating time transformations. This means that, instead of fixing the gauge choosing a gauge condition we wrote the equations of motion in a gauge invariant way. Note that this is operationally equal to fix the gauge, for example, had we fixed the spatial gauge freedom by choosing B = 0, instead of σ appearing in Eqs. (26)-(29) we would have the E variable. Following this approach, we fix the temporal gauge by rewriting the system of equations using the gauge invariant variables where l ≡ 2K/[a 2 κ(ρ + p)] and we introduced an additional variable, the Mukhanov-Sasaki variable (ζ), that will be useful later. In terms of these variables, we have the Einsteins equations recast to and the energy-momentum tensor conservation tȯ Hence, we reduced the problem from eight to six variables by using the gauge dependency. Nonetheless, we still have only four independent equations of motion. Similarly to what happens to the background, Einstein's equations and energy-momentum conservation do not provide all the dynamics necessary to describe the perturbations. Naturally, the matter components have their particular degrees of freedom which in turn determine δρ, V, δp and Π. There are some codes specialized in solving these set of equations when the matter content is described by a distribution and its evolution by Boltzmann equations, including CAMB, CLASS. Here we are going to focus in a much simpler problem, which nevertheless, displays the numerical difficulties found when solving the equations of state for the perturbations.
We can simplify the problem by including two assumptions. First, the matter content does not produce anisotropic stress, i.e., Π = 0. For the second assumption we first define the entropy perturbation as This definition is convenient since it defines a gauge invariant variable. For instance, using Eqs. (32) we have S = δp − c 2 s δρ. Thus, our second assumption is simply that there is no entropy perturbation, i.e., S = 0. Note that this will be true for any barotropic fluid [a fluid satisfying p(ρ)]. We can better understand why these assumptions simplify the system by computing the equations of motion for ζ, differentiating it with respect to time and combining with the other equations. Doing so, we geṫ and to close the system we combine Eq. (35) and Eq. (37) to obtain d dt We now recast into a more familiar form. Defining the equations areζ The pair of equations above reduce to a simple second order differential equation when Π = 0 = S, this is the simplification that we are looking for.
In retrospect, we started with eight variables and six equations of motion, of the six only four equations of motion were independent. Then we used the gauge dependency to reduce the system to six variables. Furthermore, we combined the system of equations of motion to arrive at two equations (44)-(45) and four variables (ζ, P ζ , S, Π). It is also worth noting that this combination of variables ζ is not arbitrary, it comes naturally from the Hamiltonian of the system when the constraints are reduced [36][37][38]. Finally, when we apply the assumptions of S = Π = 0 we geṫ an harmonic oscillator with time dependent mass z 2 and frequency w ≡ c s k/a, where k/a is the square root of the Laplacian eigenvalue used in the mode of the harmonic decomposition. 10

Numerical solution
Equations (46) are a reduced and simplified version of the cosmological perturbation equations of motion. Nevertheless, they exhibit many of the numerical challenges also present in a more complicated scenario. For this reason in this section we discuss the numerical approaches used to solve them in different contexts, then we make a short discussion about the difficulties that arrive in a more complicated scenario.
Equation (46) has three important regimes. In order to understand them, it is easier to first rewrite the equations using the variable v ≡ zζ, producing the equation of motion A single fluid with constant equation of state (constant p/ρ) in flat hypersurfaces K = 0, has z ∝ a 3/2 . In this case, the potential appearing in the equation above is [see Eq. (43)], In other words, the potential is proportional to a combination ofḢ and H 2 and consequently to the Ricci scalar. This amounts to show that the potential in this case produces a distance scale close to the Hubble radius squared at time t, i.e., [c/H(t)] 2 . 11 Inspired by this we define the potential scale d V ≡ 1/ |V Z |. The regime I takes place when that is, when the mode physical wave-length aλ (where λ is the conformal wave-length) over the sound speed is much smaller than the potential scale. The regime II happens when the physical wave-length is much larger than the potential scale d V , i.e., and finally the regime III is characterized by Each one of these different regimes have a particular numerical approach to handle them. Moreover, there are situations where it is necessary to put initial conditions on I and evolve up to III and vice-versa. For example, in inflationary or bouncing primordial cosmological models one begins with quantum fields in vacuum state. In these cases the modes of interest are in regime I and must be evolved into regime III. Now, Boltzmann codes start the evolution in the radiation dominated expansion past, in this regime all modes of interest are in regime III, some components evolve to regime I and some stop at regime II. For these reasons it is necessary to have tools to handle both cases.
For instance, regimes II and III can be solved using common codes of numerical integration since they do not present an oscillatory behavior as regime I. To deal with this last regime, it is worth to use the Wentzel-Kramers-Brillouin (WKB) approximation, as we describe in the following. 12 Equation (47) has an approximate solution written in terms of the time-dependent coefficients and their derivatives. To understand the nature of this solution, lets first assume that all coefficients are constants. In this case the solutions would be and a general solution a linear combination of these two. Note that we wrote dt instead of t − t 0 , such that we can use it as a tentative solution for the time-dependent coefficients. Computingv k using these tentative solutions results in Naturally, our solution is not exact when the coefficients are time dependent. The expressions above match the leading term forv k in this phase (w 2 = c 2 s k 2 /a 2 ), and the extra terms represent the error present in this approximation. Moreover, if we consider the limit of our approximation (k → +∞), the error grows to infinity. For this reason we can use the freedom in choosing the function A s,c to remove the diverging term, i.e., A s,c = A w ≡ 1/ √ w. This choice has other advantage, it removed the term that mixed solutions of different phases (it mixed the cosine and sine solutions). Using this choice for A s,c = A w the second time derivatives are expressed byv s,c where we wrote explicitly the error −Ä w /A w +z/z, which is an improvement, since now it does not diverge in the limit k → +∞, but it stays constant in this limit.
We can further improve our approximation. Starting with the same functional forms in Eqs. (49) but with an arbitrary time-dependent frequency ν, we arrive at the same second derivatives in Eqs. (50) and (51) but with w → ν. Then making the equivalent choice for A s,c (A s,c We already know that the choice ν = w results in a reasonable approximation with a error O(k 0 ). Now if we can try to correct ν to improve the approximation, for example using ν = w + f 1 /(2w), we get the error Then, if we choose f 1 =Ä w /A w −z/z, our error improve to O k −2 .
In the approximations above, we note that, for an error O k 0 we need only the background variables and, for a O k −2 , second derivatives of the background variables. It is easy to see that the same pattern continues, i.e., for a O k −2n error we need the 2n derivatives of the background variables. This points out the first numerical problem with WKB approximation, the need for higher derivatives for better approximations. In practice, the background variables are most of the time determined numerically as we discussed in Sec. 2.5. This poses a natural problem for the WKB approximation since we would need to compute the derivative numerically or to obtain it during the background integration using analytic expressions. The equations of motion themselves can be used to compute derivatives from the variables states. Nevertheless, both approaches are limited, numerical differentiation usually results in increasing errors for higher order derivatives, which limits the usage of higher order WKB approximation. The analytical approach through equations of motions provide an easy way to compute low order derivatives but for high order derivatives it becomes more and more complex. The complicated expressions resulting from this analytical approach must be treated carefully, large and complicated analytical expressions frequently produce large cancellation errors when computed naively, see Sec. 4 for a discussion on cancellation errors.

Cancellation errors
In this section we discuss the most common cancellation errors that happens in numerical cosmology, for a more in-depth discussion see, for example [40]. One common pitfall that plagues numerical computations is the cancellation error. The problem is a natural consequence of the finite precision of the computer representation of real numbers, the Floating-Point (FP) numbers. In this representation a real number is decomposed in base and exponent. For example in a decimal base is 1.2345 × 10 5 , where the base is 1.2345 and the exponent is 5. In this example the base occupies 5 decimal places, which defines the precision of our number. 13 Now, the common arithmetic operations, multiplication, sum and division can produce round-off errors, i.e., operating on truncated and rounded numbers produce a different result than operating on the actual numbers and then truncating. For example, adding n positive numbers leads to a n roundoff error in the final result, where is the machine epsilon, the roundoff unit, the smallest number such that 1 + = 1 in the FP representation, see [40] for more details. In modern implementations of 64-bits double precision FP number ≈ 2 × 10 −16 . This means that, when adding positive numbers the roundoff contributes to n × 2 × 10 −16 error, usually much smaller than other sources of errors. 14 For this reason, for these operations the roundoff errors can be, in most cases, safely ignored. However, the cancellation error happens when we subtract two close numbers. Namely, using the example above with five decimal digits in the base, if we have two real numbers represented exactly by x = 1.23400000 and y = 1.23456789, their subtraction is given by δ xy ≡ y − x = 0.00056789. Now, the FP representation of these same numbers arex = 1.2340 andȳ = 1.2346 and their subtractionδ xy =ȳ −x = 0.0006. Note that δ xy = 6 × 10 −4 has now only one significant digit, while the correct result isδ xy = 5.6789 × 10 −4 . This is a very serious problem, any operation done usingδ xy will provide a result with at most one significant digit. Going further, in many cases the two numbers should be equal in the FP representation such that the result is either zero or ∝ȳ if they differ by a rounding operation.
Fortunately, there are many cases where the problem can be avoided. For instance, given the function when the computer calculates its value for a given FP value of x, it divides the task in several steps: 15 x := x;ȳ :=x ×x;ȳ :=ȳ + 1.0;ȳ := ȳ;w = 1.0;f =ȳ −w; where := represents the attribution of a variable, the bar variables the FP representations andf the final result. If x < √ then we have that the final value ofȳ is exactly 1.0, consequentlyf will be either zero or ∝ depending on rounding errors. This is a catastrophic result, for x < √ this function produces no significant digits! To make matters worse, such expressions frequently appear within more complicated calculations, e.g., integrating 1 0 dx f (x)g(x) for a numerically well behaved function g(x) produces a result with all or even no significant digits depending on where g(x) peaks (to the left or to the right of x ≈ √ ), the integration routines estimate the error assuming that all digits are significant, so the final error estimate produced by the integrator can be much lower than the actual error. Nevertheless, there is a simple solution for this problem. Multiplying the numerator and the denominator of f (x) by which is numerically well behaved for any x inside the FP representation. This shows that in some cases a simple manipulation of the expressions is enough to cure the cancellation error. A more subtle example is the spherical Bessel function of order one In this representation in terms of trigonometric functions, the function is not well behaved for x 1. For x √ , sin(x) = x and cos(x) = 1.0, again the result is either zero or ∝ /x 2 , for really small x the x 2 can underflow to zero and produce 0/0 or /0, represented as the FP nan (not a number) or inf (infinity). In this case, there is no simple trick to make this function well behaved. The solution is to split the computation in two cases x < c and x ≥ c for a large enough cut value of c. For x ≥ c we can use the expression above to compute j 1 (x), for the other branch we use the Maclaurin Series, i.e., where the cut c and the amount of terms in the series used depend on the FP precision. This last example is actually a real world case, in order to compute the top-hat filtering (see for example [41]) of the matter power spectrum, one needs to integrate the power spectrum in k times [j 1 (kR)] 2 .

Abbreviations
The following abbreviations are used in this manuscript: