CVM Class Library

Frequently Asked Questions

How does it share memory between objects and why?

Sharing memory (or shallow copying) is a practice allowing to avoid unnecessary memory allocations and dealocations. For example, the following code

rmatrix m(3,4);
rvector v(4);
...
m[2]=v;

assigns vector v to second row of matrix m by returning a new rvector object sharing memory with the row and assigning elements of v to it. There is just one constructor per each class making shallow copy (see documentation for more details). For example, rvector's one is

rvector::rvector (TR* pD, int nSize, int nIncr = 1);

However, since version 6.0 the library is no longer using embedded memory manager for performance reasons. It created the problem of sharing memory which no longer exists. Let's consider the following code:

cvector low_up_diag (const scmatrix& m, iarray& naPivots)
{
  return m.low_up(naPivots).diag(0);
}

Here low_up creates a temporary matrix, then diag returns a vector sharing memory with its main diagonal. Despite returning it from this function by value, copy vonstructor will not be executed here. As a result, cvector with dangling pointer inside will be returned. To resolve this issue second constructor making deep copy was added since version 6.0, here its signature for rvector:

rvector::rvector (const TR* pD, int nSize, int nIncr = 1);

This second flavor accepts pointer to const treal (treal is typedef-ed as double or float). So the code above should be written as the following:

cvector low_up_diag (const scmatrix& m, iarray& naPivots)
{
  const scmatrix lu = return m.low_up(naPivots);
  return lu.diag(0);
}

Declaring the temporary matrix lu as const guarantees calling the second version of the constructor, therefore new chunk of memory gets allocated.

Why does A=B+C; expression create a temporary object and how to avoid this?

This library was created in those times when not every C++ compiler supported templates. There are modern template-based technics allowing to avoid such temporary allocations, but CVM still uses "old fashion way" for backward compatibility and better stability (at least so far). If you compare this memory allocation cost with any algorithm you might use down he road (like eigenvalues problem) you'd see that it costs almost nothing. However, if your code deals with many small objects, this might become a performance issue. In such cases use member functions (like A.sum(B,C);) instead of operators.
Update: this issue has been resolved in 8.0 release using move semantics introduced in C++11 standard.

Why does printf("%g", m(1,1)); print garbage?

Because m(1,1) and any other matrix indexing operator do not return treal (typedef-ed as double or float) type. They return proxy type instead. That's because the library needs to make sure that by changing particular matrix element your code never changes object's integrity. For example, if you change an element of symmetric matrix outside of its main diagonal then this matrix would no longer be symmetric. To avoid this the library uses type proxies whch throw cvmexception in case of attempt to break object's integrity. Unfortunately, printf is not able to recognize those proxies (and after all this is not C++ but C style, so try to avoid it). There are two ways to resolve this: use either

std::cout << m(1,1);

or

printf("%g", m(1,1).val());

Why does Intel C++ compiler fail to compile the code under Linux?

Unfortunately version 11.1 doesn't support C++ TR1 system headers on a system with g++ version 4.3 or later installed, see more details in their official report. It works under Windows only so far. Hopefully they'll fix this in next release. Currently you may use g++ compiler (and it's perfectly mixable with Intel Fortran). Update (6.1): they fixed that in 12.0 and later versions, but now under Linux Intel-generated code is not binary compatible with g++-generated one. If you recompile the library by Intel C++ please make sure that your whole project is compiled by the same compiler.

What are those functional classes added since 7.0?

While working on Runge project I created a library allowing to parse expressions as elementary functions and to use them for solving differential equations. That includes ability to compute partial derivatives and Jacobi matrices analytically. Example:

rfunction f("{x} sin(2*x)");
rfunction fd = f.drv();
std::cout << fd << std::endl;
std::cout << fd(0.) << std::endl;


prints

{x} 2*cos(2*x)
2

This library also supports functions simplifying and fast numerical executions. This library is mostly located in cfun.h file and it doesn't create any overhead. If you don't need it simply do nothing with your code. Otherwise just include this header and enjoy. Please also note that indexing for functional vectors and matrices is 0-based because they are based on std::vector implementation.

How to fix this MS Visual Studio error : cannot open source file "cvm.h"

Some versions of Microsoft Visual Studio need to extend include and library files search path. To do this for 32 bit version open
C:\Users\<YOUR_USER_NAME>\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props
and add the following XML container inside:
<PropertyGroup>
    
<IncludePath>$(IncludePath);C:\cvmlib\cvm\src</IncludePath>
    <LibraryPath>$(LibraryPath);C:\cvmlib\lib</LibraryPath>
</PropertyGroup>

Here it's assumed that the library is installed to C:\cvmlib

For 64 bit version open
C:\Users\<YOUR_USER_NAME>\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.x64.user.props
and add the following XML container inside:
<PropertyGroup>
    
<IncludePath>$(IncludePath);C:\cvmlib\cvm\src</IncludePath>
    <LibraryPath>$(LibraryPath);C:\cvmlib\lib64</LibraryPath>
</PropertyGroup>


Copyright (c) Sergei Nikolaev, 1992-2013. Welcome to my personal page.

SourceForge.net Logo