First Steps: Macros

Overview

Storing and executing C++ code in files. Functions. ACLiC compiling

The Lesson

Typing C++ statements directly into ROOT is all well and good if you are interacting directly with a ROOT based application such as MINFAST and all you want to do is to send messages to the application's objects. If you are writing new code, this method is unsatisfactory. For this purpose, ROOT supports macros, which are sets of C++ statements stored in a file. To illustrate we will start by creating a set of statements that will solve a quadratic equation. When storing an arbitrary set of statements in a macro file they must be enclosed by { ... }, i.e. they must be a compound statement. Type the following statements into a file called quad_eqn.cxx If C++ is still very new to you try to avoid cut and paste; the practice will do you good!
{

#include <iostream.h>
#include <math.h>

  Float_t a =  1.0;
  Float_t b =  2.0;
  Float_t c = -3.0;

  Float_t temp = b*b - 4.*a*c;

  if ( temp > 0. ) {
    temp = sqrt( temp );
    cout << "There are two roots: "
         << ( -b - temp ) / (2.*a)
         << " and "
         << ( -b + temp ) / (2.*a)
         << endl;
  }
  else {
    if ( temp == 0. ) {
      cout << "There are two equal roots: " << -b / (2.*a) << endl;
    }
    else {
      cout << "There are no roots" << endl;
    }
  }

}

The math.h header is needed for the sqrt function. To execute the statements in this file use the .x command:- .x quad_eqn.cxx which will either solve the equation:- X**2 + 2x - 3 = 0 or report a typo that needs to be fixed!

ROOT only looks in certain directories for macros, although this does normally include the current directory. However you cannot execute macros in other directories simply by including the directory path. To get ROOT to look in other directories involves changing the file .rootrc (see lesson Typing in C++ and modifying the line that starts:-

*.Root.Macropath Even if quad_eqn.cxx does work first time it is a good idea to deliberately introduce an error, such as not balancing the curly braces, just to see what error gets reported. Attempting to write:- Float_t temp = b**2 - 4.*a*c; instead of:- Float_t temp = b*b - 4.*a*c; is, sadly, another typo; the ** is not valid in C++ (although CINT will permit it!) Instead you have to do:- Float_t temp = pow(b,2.) - 4.*a*c; so you will probably prefer b*b! Like sqrt, exp requires math.h. To find the roots of other quadratic equations, the file can be edited and re-executed, but that quickly becomes tedious. Its better to turn the code into a function that takes the coefficients of the quadratics as arguments and returns nothing (void) by replacing:- { #include <iostream.h> #include <math.h> Float_t a = 1.0; Float_t b = 2.0; Float_t c = -3.0; by:- #include <iostream.h> #include <math.h> void quad_eqn( Float_t a, Float_t b, Float_t c ) { Note that the outer { .. } have gone now that the file contains a function, which is the unit of compilation. Indeed, macros can be one of two sorts:- In our function macro, instead of initialising the coefficients, they are now arguments to the quad_eqn function. Use the .L command to load it into memory:- .L quad_eqn.cxx Call the function directly passing in whatever values you require, e.g.:- quad_eqn( 1.0, 2.0, -3.0 ) CINT allows a shortcut in which you both load and execute the function with a single command:- .x quad_eqn.cxx(1., 2., -3.); This shortcut will only work if the file contains a function with the same name as the file once the .cxx has been removed.

You can load up multiple functions, either individually or in groups and so build up a function set that can call each other and can be called interactively. You can ask CINT what functions it currently knows about by typing:-

.func Although this will produce copious amounts of output as it lists all the ROOT functions CINT currently knows about as well. You now know enough to be able to write simple C++ programs using a book on C++, or if you haven't one to hand, the The C++ Crib although you may want to leaves classes until we cover them in the Classes lesson

In the examples so far all the C++ code has been executed using the interactive compiler CINT. It makes life very easy but it comes at a price: code runs far slower than it does if compiled. For this tutorial speed doesn't matter, but if you find your CINT programs taking far too long, ROOT can compile it for you. Consider the simple program sum.C that simply adds all the numbers up to a limit that you supply. Try the following:-

  root
  .x sum.C
  12345678   // in answer to the prompt "Type in upper limit"
It will probably take several seconds to form the sum. Now try:-
  .x sum.C+
  12345678 
The + at the end of sum.C+ tells ROOT to run the Automatic Compiler if Libraries with CINT (ACLiC) compiler system to compile this code and link it in. Now the sum will be formed far faster.

Summary


Go Back to the The First Steps Top Page


If you have any comments about this page please send them to Nick West