    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Why C++ will replace FORTRAN (or, at least, why it should)</title>
        <link>https://members.accu.org/index.php/articles/1444</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #4 - Feb 1994</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c233/">04</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-233/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+233/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Why C++ will replace FORTRAN (or, at least, why it should)</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 01 February 1994 08:53:00 +00:00 or Tue, 01 February 1994 08:53:00 +00:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<h2>1. SO WHAT'S THE PROBLEM?</h2>
<p>Since time zero, Fortran has been the <span
 style="font-weight: bold;">lingua franca</span> of the numerics
world. Yet Fortran's shortcomings have become a tired joke amongst
programmers. Its limited type checking, lack of extensibility, reliance
on global data, etc., make it extremely hard to maintain and debug. So
why does it survive?</p>
<p>The reasons are simple: momentum and efficiency. Countless
complicated algorithms have been written in Fortran. No one wants to
rewrite them. And, for all its warts, Fortran is still an extraordinary
efficient language.</p>
<p>It is not good enough to offer a language that's just better than
Fortran. If people are to switch, then this language must not only be
the equal of Fortran in terms of efficiency and reuse of old code, but
it must also be a lot better in terms of productivity, maintenance and
power.</p>
<p>A tall order! But C++ can meet these criteria, making it (in my
mind) the first serious contender to challenge Fortran's supremacy.
With care, C++ can meet Fortran's efficiency (although not exceed it,
except in the sense that it can make previously too complicated
algorithms feasible). It is also easy to call existing, known correct,
Fortran code from C++ (at least under Unix and some dialects on the
<span style="font-weight: bold;">PC</span>). The kicker is that with
C++, it can be <span style="font-weight: bold;">much</span> easier to
build and
maintain the really big, gnarly code that is being contemplated now:</p>
<ul>
  <li><span style="font-weight: bold;">Encapsulation </span>allows the
grisly details of memory allocations, <span style="font-weight: bold;">I/O</span>
parsing, &quot;<span style="font-weight: bold;">DO</span>&quot; loops, etc., to
be hidden from the user.</li>
  <li><span style="font-weight: bold;">Operator overloading</span>
allows the basic arithmetic operations&nbsp;&nbsp;
(+,-,etc.)&nbsp;&nbsp; to&nbsp;&nbsp; be extended to new, more
abstract, atomics such as vectors and matrices, allowing error prone
&quot;<span style="font-weight: bold;">DO</span> loops&quot; over vector and
matrix elements to be
eliminated.&nbsp;&nbsp; There are dialects of C and Fortran that allow
this, but at the moment, they are non-standard. Operator overloading
can also make it trivial to change the precision of a calculation from
float to double.</li>
  <li><span style="font-weight: bold;">Inheritance</span>, in
combination with encapsulation and operator overloading allows new user
defined types to be created with little extra work. If you find you
need some special kind of vector, say one that support null values,
then you need only add the functionality that is missing. The rest can
be inherited.</li>
  <li>It is easy to base these vectors and matrices on the Linpack[<a
 href="#1">1</a>]
Basic Linear Algebra (<span style="font-weight: bold;">BLA</span>)
package for which highly optimised, machine language versions have been
written.</li>
  <li>Complex numbers can be added to the language, correcting a major
deficiency of <span style="font-weight: bold;">C</span>.</li>
  <li><span style="font-weight: bold;">Dynamic binding</span> can allow
large parts of the problem to be
defined at <span style="font-weight: bold;">run-time</span> with
little increase in code complexity.<br>
  </li>
</ul>
<p>The goal here is to allow the programmer to concentrate on the
high-level architectural issues of his or her code, and not on the
implementation details. The aspiration is code that looks something
like this:</p>
<pre>ComplexVec b; // Declare a complex vector<br>cin &gt;&gt; b;&nbsp;&nbsp;&nbsp;&nbsp; // Read it in<br>FFTServer s;&nbsp; // Allocate an FFT server<br>              // Calculate the transform of b:<br>ComplexVec the Transform = s.fourier (b); <br>cout &lt;&lt; theTransform;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Print it out</pre>
<p>It should not be necessary to know the size of the complex vector b
at compile time - it should be determined automatically when the vector
is read in. Nor should it be necessary to set up the traditional &quot;work
arrays&quot; before calculating the <span style="font-weight: bold;">FFT</span>.</p>
<h2>2. BUT WONT FORTRAN 9X SAVE US?</h2>
<p>Fortran 9X offers substantial improvements over the current
standard, Fortran 77, giving the language a level of portability and
maintainability that is roughly equivalent to <span
 style="font-weight: bold;">C</span>. It is hard to imagine
the language being taken seriously at all had the X3J3 standards
committee not made such essential inclusions a recursion, dynamic
memory allocation, and pointers. In other areas they went further and
offer features from which other language designers can learn, such as
built in support for vector arithmetic, eliminating &quot;<span
 style="font-weight: bold;">DO</span>&quot; loops in many
situations (although the syntax is not pleasing). Structures (<span
 style="font-weight: bold;">TYPE</span>, in
the Fortran vernacular) are also a welcome addition.</p>
<p>But, many other modern concepts are missing. The language is far
from supporting such key &quot;object-oriented&quot; concepts as inheritance and
encapsulation, let alone polymorphism. Such useful C++ concepts as
constructors and destructors and parameterized types are also missing.
It is these key features, plus a host of other, smaller, features
(const variables come to mind) that give C++ its unique blend of
efficiency and maintainability.</p>
<p>It is my job now to show how these features can be put together to
make a language that is suitable for writing clean, pleasing numerical
code.</p>
<h2>3. NUMERICS &quot;IN THE SMALL&quot;</h2>
<p>The ability of C++ to define whole new types and an algebra to go
along with them gives the language a chameleon-like quality. A Class
designer can make the language look remarkably different, depending on
what goals s/he is trying to achieve. Now it's a database language, now
it's a graphical language. Let's look at some new types that are
particularly well suited for numerics and how to implement them.</p>
<h3>3.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vectors</h3>
<p>Encapsulating arrays inside a vector class to give them a natural,
predictable arithmetic is an obvious place to start. How might such a
class look? We will have to decide such things as how the vectors would
be constructed, what their arithmetic would look like, etc. For the
sake of concreteness, let's look at how a vector of doubles (call it
class <span style="font-weight: bold;">DoubleVec</span>) might look.
Let's start with a convenient set of
constructors to allow us to create new vectors in a predictable way:</p>
<pre>// Null vector - no elements at <br>// all, but can be resized <br>DoubleVec a:<br><br>// 8 elements long,uninitialized <br>DoubleVec b(8);<br><br>// 8 elements, initialised to 1.0<br>DoubleVec c(8,l);<br><br>// 8 elements, initialised to 1,3,5, ... <br>DoubleVec d(8,l,2);</pre>
<p>We will want to add some basic arithmetic and assignment operations:</p>
<pre>b = 2.0;&nbsp;&nbsp; //Set all elements of b to 2<br>b = c + d; //Set b to the sum of c and d<br>b *= 2;&nbsp;&nbsp;&nbsp; //Multiply each element in b by 2.</pre>
<p>Such arithmetic operations are natural and predictable. Their
concepts can be grasped in a glance.</p>
<p>We will also want to address individual elements of the vector:</p>
<pre>// Set the 3'rd element of b to 4.0<br>b[2] = 4.0;<br>// Set the 2'nd element of c to the<br>// 4'th element of b<br>c[l] = b[3];</pre>
<p>But, now suppose that we want to set every other element of a vector
to some value. It defeats the purpose of abstraction if we have to
write something like this:</p>
<pre>DoubleVec a(10, 0);&nbsp; // 10 element vector <br>for(int i = 0; i&lt;10; i+=2) <br>  a[i] = 1;</pre>
<p>Having taken the trouble to encapsulate the array elements into a
vector, alarm bells should go off in our head if we start to take the
vector back apart and address individual elements. The results are
likely to be slow and hard for the compiler to optimise. Instead, we
want to tell the program, in some abstract sense, to &quot;set every other
element to one&quot;.</p>
<p>The key to maintaining a high-level of abstraction is the <span
 style="font-weight: bold;">slice</span>.
This allows elements separated by a constant stride, say every 2'nd
element, to be addressed:</p>
<pre>// Starting with element 0;<br>// set every other element to 1 <br>a.slice (0, 2) = 1;</pre>
<p>The slice is an extremely powerful abstraction that can be used to
implement a vast variety of algorithms. As an added bonus, the <span
 style="font-weight: bold;">BLA
</span>routines (see above) have been programmed in terms of slices, so
we can
take advantage of existing, highly optimised versions of this package
to implement our slice arithmetic.</p>
<p>There are two architectural approaches to implementing slices: with
a helper class or building them right into the vector class. Each has
its own advantages, although it turns out that the role of slices in
algorithms is so fundamental that the second approach (builtin slices)
tends to lead to cleaner, more efficient code. Nevertheless, it is
useful to take a look at the first approach.</p>
<p>What do we mean by a &quot;helper class&quot;? Let's look at an example (the
actual vector data has not been shown in the interest of clarity):</p>
<pre>class DoubleVec { <br>...<br>public:<br>...<br>  // For type conversion <br>  operator DoubleSlice(); <br>  DoubleSlice&nbsp; slice (int start, <br>                      int step,<br>                      unsigned N)&nbsp; const; <br>};<br><br>// The &quot;helper class&quot;: <br>class DoubleSlice {<br>  DoubleVec* the Vector;<br>  int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startElement;<br>  unsigned&nbsp;&nbsp; sliceLength;<br>  int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; step; <br>public:<br>  ...<br>  friend DoubleVec operator+ <br>         (const DoubleSlice&amp;, <br>          const DoubleSlice&amp;);<br>  ...<br>};</pre>
<p>In addition to the basic vector class <span
 style="font-weight: bold;">DoubleVec</span>, we have a second,
helper, class named <span style="font-weight: bold;">DoubleSlice </span>which
contains the data necessary to
address the &quot;sliced&quot; elements. The member function <span
 style="font-weight: bold;">slice()</span> returns an
instance of this class. All of the arithmetic operators (+,-,setc.)
must be implemented using <span style="font-weight: bold;">DoubleSlice</span>s
as an argument (as per the +
operator in the code strip above) to allow expressions such as:</p>
<pre>DoubleVec b(10, 0), c(10, 1); <br>DoubleVec d = b.slice (0, 2) <br>            + c.slice (1, 2);</pre>
<p>This leads to slow code because a simple vector must continuously
undergo a type conversion to the helper class:</p>
<pre>// DoubleVec to DoubleSlice <br>// type conversion occurs <br>DoubleVec g = b + c;</pre>
<p>Alternatively, one could implement two versions of the arithmetic
operators, one taking the vector as an argument, the other the helper
class, but then this leads to type conversion ambiguities. This is why,
in practice, building slices right into the vector class leads to much
simpler code: type conversion becomes much simpler.</p>
<br>
<table class="sidebartable" style="text-align: left;">
    <tr>
      <td style="vertical-align: top;" class="title">Listing 1a</td>
    </tr>
    <tr>
      <td style="vertical-align: top;">
      <pre>// This class holds a reference count and a <br>// pointer to the vector data <br>class DataBlock { <br>private:<br>  unsigned short refs; // Number of references<br>  void* array; // Pointer to raw, untyped<br>               // data <br>public:<br>  DataBlock (unsigned nelem,<br>             size_t elemsize) {<br>    array = new char [nelem*elemsize];<br>   &nbsp;refs = 1; <br>  }<br>  ~Datablock() { <br>    if (--refs==0) delete array; <br>  }<br><br>  void addReference () {refs++} <br>  unsigned references () {return refs;} <br>  void* data () {return array;} <br>  void operator delete (void* b) {<br>    if ( ( (DataBlock* )b)-&gt;references () == 0)<br>      ::delete b; // No references: <br>                  // deallocate the <br>                  // storage <br>  }</pre>
      <pre>};</pre>
      </td>
    </tr>
</table>
<br>
<table class="sidebartable" style="text-align: left;">
    <tr>
      <td style="vertical-align: top;" class="title">Listing 1b</td>
    </tr>
    <tr>
      <td style="vertical-align: top;">
      <pre>class DoubleVec {<br>  DataBlock* block; // Pointer to the DataBlock<br>  double* begin;&nbsp;&nbsp; &nbsp;// Start the data<br>  unsigned npts;&nbsp;&nbsp; &nbsp;// Length of the vector<br>  int step;&nbsp;&nbsp; &nbsp;     // Stride length<br>                    // for slices<br>  DoubleVec (const DoubleVec&amp;, <br>             int,<br>             unsigned,<br>          &nbsp;&nbsp; int);<br>public:<br>  // n elements,initialized to val <br>  DoubleVec(unsigned n, double val);<br>  // Copy constructor<br>  DoubleVec(const doubleVec&amp; a);<br>  ~DoubleVec() { delete block;}<br><br>  DoubleVec slice(int start, <br>                  int stride, <br>                  unsigned lgt) const;<br>  unsigned length() const {return npts;} <br>  int stride() const {return step;} <br>  double&amp; operator() (int i) const {<br>    return begin[i*step];<br>  }<br>  DoubleVec&amp; operator=(const DoubleVec&amp; v); <br>};<br><br>// Copy constructor:<br>DoubleVec::DoubleVec(const DoubleVec&amp; a)<br>{<br>  block = a.block;<br>  block-&gt;addReference();<br>  npts = a.npts;<br>  begin = a.begin;<br>  step = a.step;<br>}&nbsp;&nbsp; &nbsp;</pre>
      </td>
    </tr>
</table>
<br>
The constructor specifies the number of elements in the vector and
the size (in bytes) of each individual element. Note the destructor.
The reference count insures that the vector data is not prematurely
released if more than one vector is using it.&nbsp;&nbsp; Every
reference increases the count by one, every deletion decrements it by
one. The count must be zero before the data pointed to by <span
 style="font-weight: bold;">array</span> is
deleted. But what about the <span style="font-weight: bold;">DataBlock</span>
itself? Won't it be deallocated,
taking the reference count along with it, when the destructor is done?
This is the job of the overloaded delete operator - it will only
release the storage of the <span style="font-weight: bold;">DataBlock</span>
itself when the references count
is zero.[<a href="#2">2</a>]
<p>Now here's an outline of the actual vector. It includes a pointer to
the <span style="font-weight: bold;">DataBlock</span>, outlined above.</p>
<p>Contained within the <span style="font-weight: bold;">DoubleVec</span>
is not only a pointer to the
<span style="font-weight: bold;">DataBlock</span> containing the
reference count, but also a pointer to the
start of data (and the slice) called <span style="font-weight: bold;">begin</span>.
This is also where the
actual data type occurs. This approach allows multiple types to share
the same <span style="font-weight: bold;">DataBlock</span> and
eliminates one level of indirection at the
expense of some extra storage space. As we shall see, it also allows
some highly expressive statements.<br>
</p>
<p>There's one other wrinkle. Note the variable <span
 style="font-weight: bold;">step</span>. This the <span
 style="font-weight: bold;">stride</span>
length - the step size between contiguous elements of the vector. A
conventional vector is a slice that starts with the zero's element and
has a stride of one.</p>
<p>A slice of an existing vector is created by calling the member
function <span style="font-weight: bold;">slice()</span> which, in
turn, uses a special constructor. Here's
what it looks like:<br>
</p>
<table class="sidebartable" style="text-align: left;">
    <tr>
      <td style="vertical-align: top;" class="title">Listing 2<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">
      <pre>// Construct a vector that is a slice of an <br>// existing vector:<br>DoubleVec::DoubleVec(const DoubleVec&amp; v, <br>                     int start, <br>                     unsigned n, <br>                     int str) <br>{<br>  block = v.block;<br>  block-&gt;addReference();<br>  npts = n;<br>  // Add start points<br>  begin = v.begin + start*v.stride;<br>  // Accumulate strides<br>  stride = str*v.stride; <br>}</pre>
      <p><br>
      </p>
      </td>
    </tr>
</table>
<p>The combination of a generalised starting element and stride allows
for some very powerful, and intuitive expressions. For example, it's
trivial to return all of the real parts of a complex vector as a
<span style="font-weight: bold;">DoubleVec</span>: it's just a slice of
every other element in the complex
vector[<a href="#3">3</a>]. The result is that the function</p>
<pre>DoubleVec&nbsp;&nbsp; &nbsp;real(const&nbsp; ComplexVec&amp;);</pre>
<p>can be used as a lvalue:</p>
<pre>ComplexVec a(10, 0); //(0,0), (0,0), (0,0), ... <br>real(a) = 1.0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //(1.0), (1,0), (1,0), ...</pre>
<h3>3.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Matrices</h3>
<p>Matrices are an extremely important part of numerics. They can
easily be created by inheriting from a vector:</p>
<p>There is a lesson in here some place. Helper classes are fine, but
when the code will depend on them fundamentally, then the results will
be slow and type conversions will always be ambiguous. You should
re-examine your approach to see if your problem depends on what they
are trying to accomplish in some fundamental way. If so, you might be
better off finding a way to eliminate them, even if that makes the
remaining classes slightly more complex.<br>
</p>
<table class="sidebartable" style="text-align: left;">
    <tr>
      <td style="vertical-align: top;" class="title">Listing 3<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">
      <pre>class DoubleMatrix : private DoubleVec { <br>  unsigned ncols; // Number of columns <br>  unsigned nrows;&nbsp;&nbsp; // Number of rows<br>public:<br>  DoubleMatrix(); <br>  DoubleMatrix(unsigned rows, <br>               unsigned cols, <br>               double initval); <br>  // Reference to m will be made <br>  DoubleMatrix(const DoubleMatrix&amp; m);<br><br>  unsigned cols() const {return ncols;} <br>  unsigned rows() const {return nrows;}<br>  <br>  // Return col as slice<br>  DoubleVec&nbsp; col(unsigned j) const<br>  { return DoubleVec::slice(j*nrows, 1,<br>                            nrows); }<br>  <br>  // Return row as slice<br>  DoubleVec&nbsp; row(unsigned i) const;<br>  { return DoubleVec::slice(i, nrows, ncols); }<br><br>  // Return diagonal as slice<br>  DoubleVec&nbsp; diagonal() const;<br><br>  // Subscripting<br>  Double&amp; operator() (int i, int j ) const; <br>  ...&nbsp;&nbsp;&nbsp; <br>  // Other operators <br>};</pre>
      </td>
    </tr>
</table>
<p>Now it's time to see how our emerging vector class might be
implemented. Here's a schematic outline of an alternative vector class
that builds slices right into it (some things, such as error checking,
efficiency optimisation, and code dealing with a few special cases,
have been omitted in the interest of clarity). First comes the vector
data, which can be shared by more than one type of vector. It contains
a reference count and a pointer to an array of raw untyped data:</p>
<p>Note the member functions <span style="font-weight: bold;">col(unsigned)</span>
and <span style="font-weight: bold;">row(unsigned)</span>. They
return a column or row, respectively, as a vector slice, allowing
expressions such as:</p>
<pre>// 10 by 10 matrix, initialised to zero<br>DoubleMatrix&nbsp; a(10, 10, 0);<br>a.row(3) = 1;&nbsp;&nbsp; &nbsp;// Set row 3 to 1<br>// Copy column 4 to column 2<br>a.col(2) = a.col(4);</pre>
<p>With a little thought, it is even possible to return the diagonal as
a slice!</p>
<pre>// 10x10 initialized to 0 <br>DoubleMatrix I(110, 10, 0); <br>// Create an identity matrix <br>I.diagonal() = 1;</pre>
<p>(How to do this is left as an exercise to the reader!) </p>
<h3>3.3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Linear Algebra</h3>
<p>Matrix decomposition's, such as <span style="font-weight: bold;">LU
Decomposition</span> and <span style="font-weight: bold;">Singular
Value
Decomposition (SVD)</span>, occupy a central role in linear algebra.
But they
are messy things: exotica like pivot indices, conditioning numbers,
nullspace and range vectors abound.&nbsp;&nbsp;&nbsp; Gathering all
this stuff into one place as a C++ class makes them much easier to work
with. In this section, we will see how to do this with <span
 style="font-weight: bold;">LU</span>
decomposition's.</p>
The <span style="font-weight: bold;">LU</span> decomposition of a
matrix consists of finding two matrices
such that <span style="font-weight: bold;">A = LU</span> where <span
 style="font-weight: bold;">L</span> is lower triangular and <span
 style="font-weight: bold;">U</span> is an upper
triangular matrix. This decomposition can then be used to do things
like solve sets of linear equations. Here's how such an <span
 style="font-weight: bold;">LU
</span>decomposition class might be structured:<br>
<br>
<table class="sidebartable" style="text-align: left;">
    <tr>
      <td style="vertical-align: top;" class="title">Listing 5<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">
      <pre>class LUDecomp : private DoubleMatrix <br>{<br>  int* permute;&nbsp;&nbsp;&nbsp; // Row permutations <br>public:<br>  LUDecomp(const DoubleMatrix&amp;);<br>  ~LUDecomp() { delete permute; }<br>  int isSingular() const;<br>  friend double determinant(const LUDecomp&amp;);<br>  friend DoubleMatrix inverse(const LUDecomp&amp;);<br>  friend DoubleVec solve(const LUDecomp&amp;,<br>                         const DoubleVec&amp;);<br>};</pre>
      </td>
    </tr>
</table>
<br>
Note the constructor: an <span style="font-weight: bold;">LU</span>
decomposition is &quot;constructed&quot; from a
matrix. For computational reasons what is actually calculated is the <span
 style="font-weight: bold;">LU
</span>decomposition of a rowwise permutation of the original matrix.
The
vector of inst &quot;permute&quot; is used to keep track of the original index of
each row. The rest of the construction process consists of calculating
the lower and upper diagonal matrices <span style="font-weight: bold;">L</span>
and <span style="font-weight: bold;">U</span> which are then packed
into a private matrix base class of the same dimensions as the original
matrix.
<p>Note that several of the more ugly details of <span
 style="font-weight: bold;">LU</span> decomposition can
be hidden behind the veil of encapsulation. For example, it is of no
interest (or concern) to the user that the <span
 style="font-weight: bold;">L</span> and <span
 style="font-weight: bold;">U</span> matrices are being
stuffed within a single matrix - hence the private declaration of the
base class. It is also of no concern that it is a rowwise permutation
of the original matrix that is being decomposed.</p>
<p>Here's how to use such a class:</p>
<pre>DoubleMatrix a(10, 10);<br>// ...&nbsp; (initialise a somehow)<br><br>// Construct the LU decomposition of a: <br>LUDecomp aLU(a);<br><br>// Now use it:<br>double det = determinant (aLU);<br>DoubleMatrix aInverse = inverse (aLU);</pre>
<p>We can also use the<span style="font-weight: bold;"> LU</span>
decomposition to solve a set of linear
equations <span style="font-weight: bold;">a x = b</span> using the
friend function <span style="font-weight: bold;">solve()</span>.
Notice that once
we have gone to the trouble of calculating the <span
 style="font-weight: bold;">LU </span>decomposition of a
matrix, we can use it to solve as many equations as we like in a
fraction of the time it takes to work with the original matrix:</p>
<pre>// 5 difference sets of linear equations <br>// to be solved: <br>DoubleVec b[5], x[5] ;<br><br>// ... (set up the 5 vectors b and the 5 <br>//     vectors x, each with 10 elements <br>//&nbsp;&nbsp;&nbsp;&nbsp; as per the matrix as above)<br>for(int i = 0; i &lt; 5; i++) <br>  x[l] = solve(aLU, b[i]);</pre>
<p>Here, we are using the <span style="font-weight: bold;">LU </span>decomposition
to solve 5 different sets of
equations, each with 10 unknowns:</p>
<pre>a x<sub>i</sub>=b<sub>i</sub>;&nbsp;&nbsp; i = 0,..., 4.</pre>
<p>For the user that doesn't even want to worry about <span
 style="font-weight: bold;">LU
</span>decomposition's (let alone their private secrets), type
conversion can
play an attractive and convenient role. In the examples above we have
chosen to create the <span style="font-weight: bold;">LU </span>decomposition
first and then use it to
calculate, say, the inverse of the matrix, but we could have just
requested the inverse of the original matrix and let type conversion do
the work for us!</p>
<pre>DoubleMatrix&nbsp; a(10, 10); <br>// ... (initialise&nbsp; a)<br><br>// Calculate the inverse directly from a. <br>// A DoubleMatrix to LUDecomp type conversion <br>// takes place automatically: <br>DoubleMatrix aInverse = inverse(a);</pre>
<p>Seeing no prototype <span style="font-style: italic;">inverse(const
DoubleMatrix&amp;)</span> the compiler
will look around for a way to convert the <span
 style="font-style: italic;">DoubleMatrix </span>a into something
for which it has a prototype. Discovering the constructor <span
 style="font-style: italic;">LUDecomp
(const DoubleMatrix&amp;)</span> the compiler will invoke it in order
to call
<span style="font-style: italic;">inverse(const LUDecomp&amp;)</span>.
There are, of course, limitations to
this approach: if there is more than one decomposition possible (SVD,
for example) then the user must specify the conversion explicitly lest
the compiler issue an error about ambiguous type conversions:</p>
<pre>DoubleMatrix alnverse = inverse(LUDecomp(a)); </pre>
<h3>3.4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Transforms
(FFTs and all that stuff)</h3>
<table class="sidebartable" style="text-align: left;">
    <tr>
      <td style="vertical-align: top;" class="title">Listing 4<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">
      <pre>class&nbsp; FFTServer {<br>  unsigned&nbsp;&nbsp;&nbsp;&nbsp; npts;<br>  ComplexVec&nbsp;&nbsp; theRoots;<br>  void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; calculateRoots(); <br>public:<br>  FFTServer(unsigned n = 0) {setOrder(n);}<br><br>  void&nbsp;&nbsp; &nbsp;setOrder(unsigned n)<br>            { npts = n; calculateRots(); }<br>  ComplexVec&nbsp;&nbsp;&nbsp; fourier(const ComplexVec&amp; v) <br>  {<br>    if(v.length() !=npts) <br>      setOrder(v.length());<br><br>    ComplexVec tran;<br>    //(calculate transform, put it in tran) <br>    return tran; <br>  }<br>};</pre>
      </td>
    </tr>
</table>
<br>
Any algorithm that requires an expensive precalculation before use
is a good candidate to become a class. An example is the Fast Fourier
Transform. To transform a vector of length N, the M'th order complex
roots of 1 must be calculated, where M is the set of prime factors of
N. For example, if N is 30, then the 2'nd, 3'rd, and 5'th order complex
roots (2x3x5=30) of one must be calculated. This is an expensive
calculation: if you are going to transform many vectors of that length,
you don't want to throw the results away. The solution is to design a
server class which holds these roots:&nbsp; at any&nbsp; given&nbsp;
moment,&nbsp; it is configured to transform a vector of a certain
length. Here's an outline of such a class:
<p>The &quot;roots of one&quot; of all the prime factors of a vector of length
npts are packed into the complex vector theRoots. They are calculated
at three possible times: when the server is constructed, when the user
calls <span style="font-style: italic;">setOrder(unsigned)</span> or
dynamically, when the server transforms a
vector. Because of this last capability, using such a server is a
pleasure because you don't have to worry about whether it is configured
correctly to transform a given vector. If it's not, it will
automatically reconfigure:</p>
<pre>ComplexVec timeVector(30);<br>FFTServer aSvr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Allocate a server<br><br>// Will automatically reconfigure for a <br>// vector of length 30: <br>ComplexVec spectrum = <br>  aSvr.fourier(timeVector);</pre>
<p>Of course, each reconfiguration is an expensive proposition, so if
you plan to transform a bunch of vectors of varying length, you will
probably want to keep many servers on hand. The bookkeeping to do this
is far easier with self-contained servers than it is with the
equivalent Fortran approach (you could even use a hashed-table lookup
to find the correct server, making a super-server!).</p>
<h2>4. WHAT ABOUT EFFICIENCY?</h2>
<p>All of these features would be of little interest to the Fortran
programmer if the price came as reduced efficiency. This section
discusses two benchmarks designed to show that it need not be so.</p>
<p>Nearly all numerical algorithms come down to performing binary
operations on large numbers of elements - that's why pipelined
architecture's on such vectorizing machines as the <span
 style="font-weight: bold;">CRAYS </span>have been so
effective and popular. Hence, it is important to get this right.</p>
<p>Figure 1 shows the time required to multiply two vectors together as
a function of the vector length, for both C++ (using Rogue Wave's
Math.h++) and Fortran. The code required to do this is on the
accompanying disk.</p>
<p>The figure demonstrates that there is a small start-up time penalty
for C++ and, thereafter, the cost per multiply is the same. Most of
this start-up time is spent doing dynamic memory allocations (for
Math.h++'s dynamically allocated arrays, as opposed to Fortran's
statically allocated arrays). Should even this start-up time be
unacceptable, it is easy enough (through inheritance) to create a
customised vector class that uses statically allocated data. But then,
of course, you would be limited (as in Fortran) to vectors whose length
was set at compile time.</p>
<p>Figure 2 (on the accompanying disk) shows a different measure of
efficiency; the venerable Linpack benchmark. This benchmark sets up a
matrix, factors it (using <span style="font-weight: bold;">LU </span>Factorisation),
then solves a set of
linear equations using that factorisation. Only the factorisation and
solution time is actually used in the benchmark (the matrix set-up time
is not measured). Two versions are shown: one in C++ (using Math.h++)
and the standard Fortran version,&nbsp; the code listings have been set
up such that comparable statements line-up side-by-side. Some comments
are in order.<br>
</p>
<table style="text-align: left;">
    <tr align="center">
      <td colspan="2" rowspan="1" style="vertical-align: top;"><img
 style="width: 450px; height: 232px;"
 alt="Time required to multiply two vectors together"
 src="/content/images/journals/ol04/WhyC++willreplaceFORTRAN01.png"><br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;"><span style="font-weight: bold;">Figure&nbsp;1</span><br>
      </td>
      <td style="vertical-align: top;">The time required to multiply
two vectors together as a function of
vector length, using Microsoft Fortran and two different versions of
Math.h++ (both compiled with Borland C++). The first version used 8087
specific code, the second, 387 specific code.</td>
    </tr>
</table>
<p>First, note the use of inheritance to guarantee that the test matrix
and the &quot;right hand side&quot; of the sets of linear equations (called
<span style="font-style: italic;">DTestMatrix </span>and <span
 style="font-style: italic;">DTestRHS</span>, respectively) are set up
correctly. While
this uses a few extra lines of code, it recognises these two objects
for what they are: unique and &quot;special&quot;, requiring a certain (and, in
this case, intricate) initialisation matrix to be passed onto a special
function to be initialized, in a large project we might neglect to do
this, risking an improper initialisation. Yet, because of inheritance,
these &quot;special&quot; objects inherit all of the abilities of their
underlying base classes.</p>
<p>Second, note how simple and more intuitive the calculation of a
tolerance, residual, and norm becomes.</p>
<p>Finally, note that despite the extra abilities of the C++ code in
terms of type checking, dynamic memory allocations, and safe
construction of objects, the code still requires fewer lines of code.
It also executes (slightly, but probably not significantly) faster.</p>
<h2>5. NUMERICS &quot;IN THE LARGE&quot;</h2>
<p>We have seen how the encapsulation and operator-overloading
properties of C++ can give rise to an impressive, and pleasing, economy
of expression for such &quot;in the small&quot; objects as vectors, matrices, FFT
servers, etc. This is useful, but not enough for working with those
really big gnarly projects where problems expand faster than they can
be contained.</p>
<p>Let's look at an example of how we might structure a relatively
simple problem[<a href="#4">4</a>]. Suppose one wanted to model the
motions of a
vibrating string under the influence of a spatially and temporally
varying force of (as yet) unknown origin. Here is the governing
equation:</p>
<pre>

&delta;<sup>2</sup><i>u</i>     &delta;<sup>2</sup><i>u</i>
&mdash;&mdash;&mdash; - <i>c</i><sup>2</sup>&mdash;&mdash;&mdash; = <i>F</i>(<i>x</i>,<i>t</i>)
&delta;<i>t</i><sup>2</sup>     &delta;<i>x</i><sup>2</sup>

</pre>
<p>where <span style="font-weight: bold;">u</span> is the string displacement <span style="font-weight: bold;">x</span>
is space, <span style="font-weight: bold;">t</span> is time, <span
 style="font-weight: bold;">c<sup>2</sup></span> is the
string tension over the string density, and <span
 style="font-weight: bold;">F(x,t)</span> is the external
force applied to the string.</p>
<p>How might we model such a problem? Let's start by specifying two
objects: the string, and some abstract force:</p>
<pre>class Force;&nbsp;&nbsp; &nbsp;                           //1<br><br>class String {&nbsp;&nbsp; &nbsp;                         //2<br>public:<br><br>  String(double length,<br>         double tension,<br>         double density);&nbsp;&nbsp; &nbsp;              //3<br><br>  void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setPoints(int nx);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        //4<br>  void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeStep(double dt,<br>                     const Force&amp; force);  //5 <br><br>  DoubleVec&nbsp; displacement() const;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //6<br><br>private:<br><br>  DoubleVec  u;&nbsp;&nbsp; &nbsp;                        //7<br>  double&nbsp;&nbsp;&nbsp;  cSquared; <br>  double&nbsp;&nbsp;&nbsp;  length;</pre>
<pre>};</pre>
<p>Let's look at what we've done, line by line, and see how it enforces
the abstraction of the problem.</p>
<ol>
  <li>This line alerts the compiler that the keyword &quot;<span
 style="font-weight: bold;">Force</span>&quot;, which we
will define later, is actually a user-defined class.</li>
  <li>This is where the declaration for the class &quot;<span
 style="font-weight: bold;">String</span>&quot;
starts.&nbsp;&nbsp; In it, we will define all the external properties
that are needed to create, manipulate, and observe a string.</li>
  <li>This is how to construct a string. We need its length, its
tension, and its density.</li>
  <li>Here's how we specify the resolution of the numerical
representation of the string,&nbsp;&nbsp; i.e., the number of points
that will be used to represent it.</li>
  <li>This is how we will time step the problem. To calculate the new
position of the string over a time step we need to know how long the
time step is (<span style="font-weight: bold;">dt</span>), and the
forcing function (<span style="font-weight: bold;">force</span>).</li>
  <li>Here's how we ask
the string for
its current displacement. This is returned as a vector of doubles.</li>
  <li>This is the private section of the declaration where the actual
implementation details are hidden. Variables that will be obviously
useful are the string displacement, tension, and length.&nbsp;&nbsp; We
may have to introduce other variables&nbsp;&nbsp; that are used as
intermediates in the calculations.<br>
  </li>
</ol>
<p>Of course, the actual solution procedure will not be trivial and
this
is only the barest of outlines. For examples, we are starting with a
single equation second order in time -we will probably want to change
that to two equations first order in time.</p>
<p>Now let's look at the abstract class <span
 style="font-weight: bold;">FORCE</span>. A fundamental assumption
is
that we do not know much about the nature of <span
 style="font-weight: bold;">FORCE</span>. Indeed, it may even
depend on the string displacement (for example, the force of the wind
on a bridge depends on the displacement of the bridge).</p>
<pre>class Force { <br>public:<br>  virtual DoubleVec&nbsp; value() =0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 1 <br>};</pre>
<p>That's it! We will use inheritance to define the actual details of
the
force. For example, a wind type force acting on the string might look
like:</p>
<pre>class WindForceString : public Force { <br>public:<br>  WindForceString(String&amp; string,<br>                  double dragCoeff );<br>  void setVelocity(double windspeed);<br>  virtual DoubleVec&nbsp;&nbsp; value(); // 1 <br>private:<br>  String&amp; myString;// The string we are <br>                   // tracking<br>  double wind;&nbsp;&nbsp;&nbsp;&nbsp; // Present wind speed.<br>  double drag; <br>};</pre>
<p>We are explicitly recognising that the force of the wind will depend
on
the displacement of the string by <span style="font-weight: bold;">requiring
</span>that a specific string be
used in the constructor (as well as on a drag coefficient). This
<span style="font-weight: bold;">WindForceString </span>object will
then track the string, asking it for its
present displacement, before calculating the resultant force of the
wind on the string and returning it. This is done by calling the
virtual function <span style="font-weight: bold;">value()</span>, an
example of <span style="font-weight: bold;">polymorphism</span>, a
fancy word for
runtime binding. Here's how <span style="font-weight: bold;">value()</span>
might be implemented:</p>
<pre>DoubleVec WindForceString::value()<br>{<br>  // Get present string displacement: <br>  DoubleVec d = string.displacement();<br>  // Some (bogus) calculation<br>  return&nbsp; -drag*wind*wind*d; <br>}</pre>
<p>It then becomes trivial to replace the forcing function, even at run
time, with another type of force. Note how this is something more than
just passing a generic vector of doubles to the String that represents
the forcing function. We can have an actual object, complete with
feedback loops to the string act as the forcing function.</p>
<h2>6.&nbsp;&nbsp; &nbsp;CONCLUSIONS</h2>
<p>As we have seen, C++ has tremendous potential in numerics, one that
has
gone largely unnoticed by fans of object-oriented programming, perhaps
because previous <span style="font-weight: bold;">OOP </span>languages
lacked the efficiency required to do
numerics. C++ has this efficiency, plus a lot more!</p>
<p>Notes</p>
<ol>
  <li><a name="1"></a>Dongarra, JJ., Bunch, J.R., Moler, C.B., Stewart,
G.W.,LINPACK Users' Guide, Society for Industrial and Applied
Mathematics, 1979</li>
  <li><a name="2"></a>In ancient times (pre-summer 1989) the same
effect
could be accomplished by setting &quot;this&quot; to zero if the reference count
was
non-zero, disabling the automatic deallocator. The present method is a
bit less efficient locally, but allows more 'aggressive optimisations
globally.</li>
  <li><a name="3"></a>Perhaps this isn't the safest approach: it
assumes
a known structure for type complex. It would fail if someone
implemented complex using, say,
polar notation. Nevertheless, the functionality could be retained by
using a helper class.</li>
  <li><a name="4"></a>This is the problem of&nbsp;
&quot;object-oriented&nbsp;
design&quot;.&nbsp; A&nbsp; highly recommended book on the subject is Grady
Booch's &quot;Object-Oriented Design with
Applications&quot;, published&nbsp; by Benjamin Cummings, 1991, ISBN
0-8053-0091-0.
  </li>
</ol>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
