High Productivity

Close to Maths

SAC aims to help application programmers' productivity. The abstraction facilities in SAC enable programs that closely reflect the underlying mathematics of scientific problems. As an example, consider naive n-body simulation. Using $m$ for planet masses, $p$ for positions (in 3D space), $v$ for velocities and $a$ for accelerations, time discretisation over $k$ yields for all bodies $i$: \begin{eqnarray} \label{eq:num:pos} \overset{\tiny k+1}{p_i} &=& \overset{k}{p_i} + \overset{k}{v_i} dt \\ \label{eq:num:vel} \overset{k+1}{v_i} &=& \overset{k}{v_i} + \overset{k}{a_i} dt \\ \label{eq:num:acc} \overset{k+1}{a_i} &=& \sum\limits_{j \neq i}^{n} \dfrac{m_j (\overset{k+1}{p_j} - \overset{k+1}{p_i})} {\left|\overset{k+1}{p_j} - \overset{k+1}{p_i} \right|^3} \end{eqnarray}

In SAC, this can be specified as:

p = p + v * dt;
v = v + a * dt;
a = {[i] -> vsum ({[j] -> (i == j  ? [0.0, 0.0, 0.0] 
                                   : m[j] * (p[j] - p[i])
                          / (l2norm (p[j] - p[i]) ^ 3) 
Note here, that $k$ is mapped into the actual compute time and that $i$ in the first two assignments as well as the 3D nature of all positions, velocities and accelerations are implicitly derived by the compiler! More details as well as further examples can be found in our case studies.

Swift FFI (Foreign Function Interface)

There is no need to re-write entire applications in SAC. SAC can be compiled into C-libraries that can be called from any C-linking-based context. Dually, SAC can easily interface with existing libraries. Many examples, including parts of C's standard OS interface such as SDL as well as interfaces to tools such as gnuplot or dislin can be found in the current standard library of SAC.

Here an example taken from our tutorial for interactively navigating through the Mandelbrot Set. Note here, that all the code that interacts with the SDL library are contained in this code snippet initDisplay generates a display, drawArray displays a SaC array, and getSelection obtains a rectangular selection made with the mouse. All arrays that are passed into or obtained as result from these functions are normal SaC arrays; there is no special treatment required.

#define XRES 6
#define YRES 4
#define EXPAND 128
#define DEPTH 2048
int main ()
  disp = initDisplay (EXPAND * [YRES,XRES]);
  cmin = [toc (-2.2, 1.0)];
  cmax = [toc (0.8, -1.0)];
  while (true) 
      expand = EXPAND;
      cur_shape = [YRES, XRES];
          plane = genComplexArray (cur_shape, cmin[[0]], cmax[[0]]);
          ts, vs = escapeTimeAndValue( plane, DEPTH);
          nvs = normalizedIterationCount( ts, vs);
          rgbs = doubleArrayToRGB( nvs);
          drawArray (disp, stretchRgb (rgbs, expand));
          expand = expand / 2;
          cur_shape = 2 * cur_shape;
      while (expand >= 1);
      zoom_coords = getSelection (disp);
      if (all( (zoom_coords[1] - zoom_coords[0]) > 0)) 
          cmin = [plane[zoom_coords[[0]]]] ++ cmin;
          cmax = [plane[zoom_coords[[1]]]] ++ cmax;
          cmin = all (shape(cmin) > 1) ? drop ([1], cmin) : cmin;
          cmax = all (shape(cmax) > 1) ? drop ([1], cmax) : cmax;
  destroyDisplay (disp);
  return 0;

Further details of the FFI and examples on how to use it, e.g. on how to call SAC libraries from FORTRAN, can be found in several FFI-related publications.

High Performance

Performance Rivals that of Hand-Optimised, Target-Architecture-Tuned C Codes

It is the central goal of SAC to achieve performance levels that rival hand-optimised C-codes. Key to achieving that goal is a highly optimising compiler sac2c which translates highly abstract SAC programs into performance-tuned C-code, CUDA-code or similar, depending on the chosen target machine.

Examples and performance figures can be found in our case studies as well as in our application-related publications.

High Portability

Single Source - Many Different Targets

sac2c supports target-hardware-specific program transformations (see publications for details). From a single, unmodified source file highly-tuned codes for a range of architectures can be generated. These include:

  • Shared-Memory Multi-Cores,
  • GPUs,
  • clusters,
  • FPGAs, as well as
  • experimental platforms.