Get ahold of Effective C++ by Scott Meyers, where the Law of Three is discussed. You might also want the C++ FAQ as well as the other C++ books by Scott Meyers, but definitely start with Effective C++.
Tuesday, December 30, 2008
Debug Assertion Failed! _BLOCK_TYPE_IS_VALID
Get ahold of Effective C++ by Scott Meyers, where the Law of Three is discussed. You might also want the C++ FAQ as well as the other C++ books by Scott Meyers, but definitely start with Effective C++.
Saturday, December 13, 2008
Howto Make Script More Portable With #!/usr/bin/env As a Shebang
You may have noticed that most shell and perl script starts with the following line:
#!/bin/bash
OR
#!/usr/bin/perl
It is called a shebang. It consists of a number sign and an exclamation point character (#!), followed by the full path to the interpreter such as /bin/bash. All scripts under UNIX and Linux execute using the interpreter specified on a first line.
However there is a small problem. BASH or Perl is not always in the same location (read as PATH) such as /bin/bash or /usr/bin/perl. If you want to make sure that script is portable across different UNIX like operating system you need to use /usr/bin/env command.
env command allows to run a program in a modified environment.
Find line#!/bin/bash
Replace with#!/usr/bin/env bash
For example here is a small script:
#!/usr/bin/env bash
x=5
y=10
echo "$x and $y"
OR
#!/usr/bin/env perl
use warnings;
print "Hello " x 5;
print "\\n";
Now you don’t have to search for a program via the PATH environment variable. This makes the script more portable. Also note that it is not foolproof method. Always make sure you have /usr/bin/env exists or use a softlink/symbolic link to point it to correct path. And yes your work (script) looks more professional with this hack
Monday, December 8, 2008
How to run BibTeX by hand
latex file
a couple of times, where file.tex is your .tex file. Now, you need to run bibtex too. The normal
sequence is:
latex file
bibtex file - give the name of your .tex file here.
latex file
latex file
I use a makefile (/home/mackay/tex/Makefile) to run BibTeX and LATEX at the appropriate times. After bibtex runs, and after latex runs for the third time, see if there are any error messages. The most common causes of errors are: incorrectly formatted .bib entries in the .bib file, and incorrect \cite commands in the .tex file. Sometimes when you fix an error, LATEX remains confused. If so, give LATEX a fresh start by removing the .bbl and .aux files created by BibTeX and LATEX.
How to run BibTeX in kile
button, and kile will run the necessary commands for you, giving error messages if it can’t complete
the job. (Just so you know what to expect when you press the magic button: It will run LATEX, then BibTeX, then LATEXonce or twice more.)
Splice up video into individual frames!
Video Processing: Processing video in Matlab is a bit tricky. Theoretically, there is aviread but, under linux, it will only ready uncompressed AVIs. Most current digital cameras produce video in DV AVI format. One way to deal with this is to splice up the video into individual frames and then read them into Matlab one by one. On the graphics cluster, you can do (some variant of) the following to produce the frames from a video:
mplayer -vo jpeg -jpeg quality=100 -fps 30 mymovie.avi
Sunday, December 7, 2008
Fix "Locking assertion failure" with MATLAB for Linux
OR
"sudo /etc/bash.bashrc" ----> add "export MATLAB_JAVA=/usr/lib/jvm/java-6-sun-1.6.0.10/jre" at the bottom.
Monday, December 1, 2008
Creating, compiling and linking MATLAB executables (MEX files): a tutorial
by Peter CarbonettoDept. of Computer Science
University of British Columbia
MATLAB is wonderful programming language for scientific research. Unfortunately, its kind interface comes at the cost of speed. For many of the machine learning problems I've worked on over the years, MATLAB's slowness was so severe I had to resort to implementing my algorithms with lower level languages such as C++. Implementing a numerical algorithm in C++ usually involves much more coding and painful debugging. Not fun.
The pain is eased knowing that it is possible to interface my C++ implementations back to MATLAB. By creating a MATLAB interface in my code, then compiling my code into a MEX file, my obtuse code becomes both fast and easy to use, and as a result I can run my experiments and plot the results using MATLAB's nice plotting tools. Different people may have different reasons for resorting to MEX files, but it is an important tool for almost any seasoned MATLAB user.
What's the catch? Creating a MEX file can be a harrowing experience. The purpose of this tutorial is to educate you in hopes that you will avoid the pitfalls I have encountered. Here we go.
Compiling and linking made difficult
Let's suppose we wanted to create an efficient MATLAB routine that calculates the height of the Normal probability density function (pdf) at a given point on the line. That there are at least five gazillion MATLAB implementations that already calculate this quantity is beside the point. (Normally, when you decide to write a MATLAB routine in C++, you should make sure it is worth your while!)
Before we embark on the actual C++ coding, we need to examine how MATLAB creates a MEX File. The exact procedure is system-dependent, so what I describe here may differ slightly from your setup. At school I have access to a machine installed with the Linux operating system, and I have my own Apple computer with Mac OS X. Both these operating systems are Unix-like, hence their differences will be rather cosmetic.
In order to build MEX files, we need to make sure that we have the proper compiler installed on our system. On my Linux machine, I'm using MATLAB 7.3 (R2006b), and according to MathWorks product support it was built with the GNU Compiler Collection (GCC) 3.4.5. Unfortunately, I did not have this particular version of the compiler installed on my system. Different versions of the same compiler are effectively different compilers, as they follow different conventions. You should never link libraries or object code unless they are compiled in the same way. I downloaded the GCC source from my local university FTP mirror and built the entire package on my system. GCC includes compilers for many different languages, and they can be found in the
subdirectory of the GCC software installation. MATLAB uses three of them: the C compiler
, the C++ compiler
, and the Fortran 77 compiler
. When installing GCC, it is a bad idea to blindly follow the default installation as it may overwrite the existing compilers. You should install it in a new directory. Afterward, to make things simpler, I created a symbolic link to each of the compilers like so:
cd /usr/bin
ln -s gcc-install-path/bin/gcc gcc-3.4.5
/usr/bin
is in the path (see the environment variable PATH
), I can call the program anywhere I am simply by typing gcc-3.4.5
. By including the version number in the symbolic link, I avoid calling version 3.4.5 of gcc
unless I really want to. I was much more fortunate on my Apple computer because I already had the correct version of GCC installed; both Mac OS X 10.3.9 (Panther) and MATLAB 7.2 (R2006a) have been built with the GNU compiler collection 3.3.1
Now that we've installed the compiler collection that agrees with MATLAB, let's examine the C++ code I've written to compute the Normal pdf. After we've built the MEX file, typing
in the MATLAB prompt should display the response of the Normal pdf with zero mean and unit variance at point 0.5, which is approximately 0.3521.2 The first four lines of code in the function
if (nrhs != numInputArgs)
mexErrMsgTxt("Incorrect number of input arguments");
if (nlhs != numOutputArgs)
mexErrMsgTxt("Incorrect number of output arguments");
check to make sure the user has entered the correct number of input and output arguments when calling the function in MATLAB. After that, the lines
double x = getMatlabScalar(prhs[0]);
double mu = getMatlabScalar(prhs[1]);
double v = getMatlabScalar(prhs[2]);
retrieve the point along the line, mean and variance using our function
. In order to understand exactly how this code retrieves the values of the inputs, you may want to take a look at the MATLAB documentation on "external interfaces." Next, the line
double& p = createMatlabScalar(plhs[0]);
reserves a place for the output of our function and
is a variable that refers to it. And finally, the line
p = exp(-(x-mu)*(x-mu)/(2*v)) / sqrt(2*pi*v);
uses a couple functions from the standard C math library to compute the pdf response, then stores this value in the location reserved for the single output argument. Now that we have a basic understanding of the C++ code, let's go ahead and build the MEX file so we can see if
behaves the way it is supposed to.
First, download the code and make sure you are running MATLAB in the same directory as the location of the file
(type
in the MATLAB prompt to check this). If you haven't done so already, you should set up MEX by typing
in the MATLAB prompt. I chose option 2, but in my experience it makes little difference which option I select. To create the MEX file on my Linux machine, I type the following either in the MATLAB prompt or in the UNIX command line:
mex CXX=g++-3.4.5 CXX=g++-3.4.5 LD=g++-3.4.5
-lm -output normpdf normpdf.cpp
It produces a MEX file called
. On my Apple computer, I type
mex CC=g++ CXX=g++ LD=g++ -lm
-output normpdf normpdf.cpp
to create a MEX file with the name
.3 There's a few things worth explaining here. (It might be helpful to look at the external interfaces documentation and the command line help,
, while you're reading this.) First, what I've done is set the C and C++ compiler variables so that they will call the right version of the compiler. The variable
overrides the choice of linker. Notice that the C++ compiler and linker will always be used. This is because I want to make sure that we use the C++ linker.4 The first three options override MATLAB's default choices for the compiler. The default settings can be found in the MEX options file which is created when running
. On my Linux machine, this file is
. The flag
links the MEX file to the C math library. While MATLAB tends to do link to this library by default, we include this option just to be safe. Once the MEX file is created, you can call it like any other function in MATLAB.
Including the
flag when calling
allows us to peer under the hood. What you should observe is that
is called once and
is called twice. The first call to
compiles the source file
into object code. Next,
compiles a C source file written by the MATLAB developers. And finally,
is called to link together the object code and libraries in order to build the MEX File.
After a long look under the hood, we see that it wouldn't be all that difficult to duplicate these steps ourselves by calling the compilers with the appropriate flags. In other words, we could reverse-engineer the
program. But that would be silly! The whole purpose of
is to hide the complicated details from us. Nonetheless, it will be a useful exercise to compile the object files ourselves since we will need to know how to do this when we compile and link to a library.
I cannot help but use a Makefile, a script which automates the compilation process very elegantly. If you have never used GNU make before, I suggest you read a tutorial. On my Linux machine, I wrote the following bare bones Makefile using a text editor and saved it in the same directory as the C++ source file:
MEXSUFFIX = mexglx
MATLABHOME = /cs/local/generic/lib/pkg/matlab-7.3
MEX = mex
CXX = g++-3.4.5
CFLAGS = -fPIC -ansi -pthread -DMX_COMPAT_32 \
-DMATLAB_MEX_FILE
LIBS = -lm
INCLUDE = -I$(MATLABHOME)/extern/include
MEXFLAGS = -cxx CC='$(CXX)' CXX='$(CXX)' LD='$(CXX)'
normpdf.$(MEXSUFFIX): normpdf.o
$(MEX) $(MEXFLAGS) $(LIBS) -output normpdf $^
normpdf.o: normpdf.cpp
$(CXX) $(CFLAGS) $(INCLUDE) -c $^
Simply typing
in the same directory as the Makefile as the C++ source file compiles and builds the MEX file in two steps.5 In the first step, the
compiler specified by the
variable compiles (but does not link, as indicated by the
flag) the source file into object code
. Some special options are specified according to the
variable. It is not really a mystery how I chose these. I simply peered under the hood, and copied the options displayed on the screen by running
as I did above, but with the
flag. The first flag tells the compiler to generate position-independent code, which I suspect is necessary because MATLAB loads the program dynamically. The
flag ensures that the C++ code strictly satisfies the ISO standard, and
adds support for multi-threaded processes. The last two options in
define preprocessor macros which aren't of import here. Notice that it is also important to tell the compiler where to find the
header file. This information is provided by the
Makefile variable.
In the second step,
link the object code together with the libraries and its own source files to produce the final MEX file.
This Makefile will also work on my Apple computer if I make some changes to the first five lines:
MEXSUFFIX = mexmac
MATLABHOME = /Applications/MATLAB72
MEX = mex
CXX = g++
CFLAGS = -fno-common -no-cpp-precomp -fexceptions
Again, the flags used to compile the C++ come from observing the behaviour of
on my Apple computer.
As you can see, we went through great pains to build a small MEX file. We probably made things more difficult than necessary, but this procedure should translate to much larger projects as well. In fact, we'll see that linking our project to a library is now relatively straightforward.
Linking with a C library
We're now going to act a little smarter and reuse an existing function from the GNU Scientific Library that computes the Normal pdf. (I downloaded GSL version 1.8.) In order to to use GSL's functions in MATLAB, we will have to skirt the normal build procedure and configure the install script to suit our own needs.
The first step when installing GSL (and many other libraries) is to run the "configure" script. On my Linux machine, I ran the configure script with the following options:
configure --disable-shared --prefix=gsl-install-path
CC=gcc-3.4.5 CFLAGS='-O2 -fPIC -ansi -pthread'
The configuration comes straight from our previous experiences: we need to compile the library with the options used by
. I removed some of the flags I figured would have no impact on compiling GSL, and then added the
flag to request optimized code. It can be difficult to keep track of shared libraries and their whereabouts, especially when compiling with different versions of GCC, so I disabled them with
. Static libraries are certainly less efficient, but the keep-it-simple-stupid principle takes priority here. On my Apple, I ran the configure script with the following settings:
configure --disable-shared --prefix=gsl-install-path
CC=gcc CFLAGS='-O2 -fno-common -no-cpp-precomp -fexceptions'
I then put the static libraries
and
in the
subdirectory of my home directory.
My new version of the C++ source code that uses the GSL routine
can be found here. In order to build the new MEX file, I renamed the source file to
) and made a couple changes to the Makefile:
LIBS = -L$(HOME)/lib/gcc-3.4.5 -lgsl -lgslcblas -lm
INCLUDE = -I$(HOME)/include -I$(MATLABHOME)/extern/include
I put all the GSL include files in the
subdirectory of my home directory. With these modifications, I was able to successfully create the new MEX file and call it from MATLAB. Note that I made analogous small modifications to the Makefile on my Apple.
Parting notes
The motivation behind this tutorial may have been lacking because we didn't delve into very realistic scenarios; in reality, my projects can be much larger and much more complicated and I inevitably link to many different libraries, whic may even ve written in different languages such as Fortran. Nonetheless, my words should be taken as a gentle guideline for future projects.
Footnotes
1 If you don't have GCC installed on Mac OS X, you may either have to download the Apple developer tools or use Fink to install GCC.
2 There may already exist a function called
. If so, you can make sure you are using my code by typing
in the MATLAB prompt.
3 On my Apple computer,
was not in my path so I could not call it from anywhere. I used
to create a symbolic link to
in the
directory.
4 I've noticed that in the latest release of MATLAB, version 7.3, there's an flag
which ensure that the C++ linker is used. This appears to be an available but undocumented feature in version 7.2. Another way to guarantee usage of the C++ linker to pass as the first source file to
a recognized C++ source file. Generally, there is no harm done in compiling all the C and C++ code using the C++ compiler.
5There are some rather esoteric issues in Makefiles with regards to spacing, so simply cutting and pasting the above code might fail to do the trick. I suggest you educate yourself on the basics of Makefiles before continuing further.
Monday, November 24, 2008
How to convert video into a sequence of images.
mplayer -vo jpeg quality=100 -fps 30 mymovie.avi
Tuesday, November 18, 2008
Wednesday, November 12, 2008
Creating Good Quality EPS Graphics Using OpenOffice
If you use dvips and then ps2pdf to generate your PDF documents, you're no doubt using encapsulated postscript (EPS) files for your figures. The advantage to using EPS over formats like JPEG, GIF, or PNG is that EPS is a Vector Graphics format, which means that you can scale the image up or down without getting pixelation (check out the example on the Wikipedia page). For that reason, EPS graphics are very convenient to use in your latex documents because you can resize your figures easily depending on the document type. For example, if your document is in double column format, your figures will typically be 3.5 inches wide. If you change to single column format, you may want to enlarge your figures to 4.5-6.0 inches. If your images were GIF files, you may get pixelation, but EPS files will scale easily.
Furthermore, if you are using JPG/GIF files, for best results, you typically should create them knowing what size you'll be using (eg. 3.5in x 2in), and then import them without scaling them into your document. If you decide later on to scale them, you may run into pixelation problems again.
In short, the reason EPS graphics are preferred for Latex documents is because they offer greater flexibility with regards to scaling (no pixelation). But, there's a catch, you need to generate your EPS files properly, otherwise, you may end up with fuzzy blurred figures anyway.
Fuzzy/Blurred Figures
If you use EPS, you've probably noticed that your figures sometimes look fuzzy when viewed in your final PDF. You may have one or both of the following situations:
- Lines and shapes appear fuzzy.
- Text (fonts) appear fuzzy.
In most cases, the PDF will print properly, but the electronic version looks fuzzy in PDF because of resizing (viewing at 120% or 'page width', etc). The reason for this is that your EPS file was not properly generated by whatever program you used. Quite often, when using the 'save as' or 'export' feature of a program, the resulting EPS file doesn't have fonts embedded. You can check this by doing 'ps2pdf' and then 'pdffonts' to see if your fonts were embedded.
Fonts not embedded
If you have a figure with text where the fonts have not been embedded, you'll see no fonts listed by pdffonts:
$ ps2pdf14 bad.eps
$ pdffonts bad.pdf
name type emb sub uni object ID
------------------------------------ ------------ --- --- --- ---------
Fonts properly embedded
If your fonts have been properly embedded, you'll see something like the following output when running pdffonts:
$ ps2pdf14 good.eps
$ pdffonts good.pdf
name type emb sub uni object ID
------------------------------------ ------------ --- --- --- ---------
BAAAAA+ArialMT TrueType yes yes yes 9 0
Generating 'Good' EPS Images
Many programs support EPS as a format you can save/export to, but they don't embed fonts properly. I've found two solutions to this problem, the first is to 'print-to-file' using a postscript printer driver, the second is to export to PDF using OpenOfficePrint to file
One of the easiest ways is to install a postscript printer driver and use the 'print to file' option. When you print to file, you'll end up with a postscript file which is a letter sized page. Since your figure is most likely smaller than a full page, you'll need to use something like 'ps2epsi' or 'ps2eps' to fix the bounding box. You should see after running 'pdffonts' on the resulting PDF file that all the fonts have been properly embedded.
Export to PDF (OpenOffice)
The best way I've found to create good EPS files is:
- Use OpenOffice Draw to draw my figures.
- Use the "Export to PDF" function because it embeds fonts properly.
- Use 'pdftops -eps' to generate EPS files (note: not 'pdf2ps').
- Optional: use ps2eps to fix the bounding box of the generated EPS file is needed.
Here's an example:
$ pdftops -eps test.pdf
$ cat test.eps | ps2eps > test2.eps
Input files: -
Processing: -
Rendering with existing %%BoundingBox: 0 0 792 612
Calculating Bounding Box...ready. %%BoundingBox: 32 47 760 569
Creating output file -...ready.
$ ps2pdf test.eps
$ pdffonts test.pdf
name type emb sub uni object ID
------------------------------------ ------------ --- --- --- ---------
BAAAAA+ArialMT TrueType yes yes yes 9 0
$ pdffonts test2.pdf
name type emb sub uni object ID
------------------------------------ ------------ --- --- --- ---------
MFZMRR+ArialMT TrueType yes yes no 8 0
As you can see, the 'test.pdf' and 'test2.pdf' contain embedded fonts. So if you were to use the 'test.eps' file in your latex document, the resulting figure will not have fuzzy fonts when resizing the image.
NOTE: If you simply convert a GIF to EPS, you're basically getting a GIF file embedded into the postscript file.
Saturday, October 11, 2008
When should your destructor be virtual?
First of all, what does it mean to have a virtual destructor?
Well, what does it mean to have a virtual method?
If a method is virtual, then calling the method on an object always invokes the method as implemented by the most heavily derived class. If the method is not virtual, then the implementation corresponding to the compile-time type of the object pointer.
For example, consider this: class Sample {
public:
void f();
virtual void vf();
};
class Derived : public Sample {
public:
void f();
void vf();
}
void function()
{
Derived d;
Sample* p = &d;
p->f();
p->vf();
}
The call to p->f() will result in a call to Sample::f because p is a pointer to a Sample. The actual object is of type Derived, but the pointer is merely a pointer to a Sample. The pointer type is used because f is not virtual.
On the other hand, the call to The call to p->vf() will result in a call to Derived::vf, the most heavily derived type, because vf is virtual.
Okay, you knew that.
Virtual destructors work exactly the same way. It's just that you rarely invoke the destructor explicitly. Rather, it's invoked when an automatic object goes out of scope or when you delete the object. void function()
{
Sample* p = new Derived;
delete p;
}
Since Sample does not have a virtual destructor, the delete p invokes the destructor of the class of the pointer (Sample::~Sample()), rather than the destructor of the most derived type (Derived::~Derived()). And as you can see, this is the wrong thing to do in the above scenario.
Armed with this information, you can now answer the question.
A class must have a virtual destructor if it meets both of the following criteria:
You do a delete p.
It is possible that p actually points to a derived class.
Some people say that you need a virtual destructor if and only if you have a virtual method. This is wrong in both directions.
Example of a case where a class has no virtual methods but still needs a virtual destructor: class Sample { };
class Derived : public Sample
{
CComPtr
public:
Derived() { CreateStreamOnHGlobal(NULL, TRUE, &m_p); }
};
Sample *p = new Derived;
delete p;
The delete p will invoke Sample::~Sample instead of Derived::~Derived, resulting in a leak of the stream m_p.
And here's an example of a case where a class has virtual methods but does not require a virtual destructor. class Sample { public: virtual void vf(); }
class Derived : public Sample { public: virtual void vf(); }
Derived *p = new Derived;
delete p;
Since the object deletion occurs from the pointer type that matches the type of the actual object, the correct destructor will be invoked. This pattern happens often in COM objects, which expose several virtual methods corresponding to its interfaces, but where the object itself is destroyed by its own implementation and not from a base calss pointer. (Notice that no COM interfaces contain virtual destructors.)
The problem with knowing when to make your destructor virtual or not is that you have to know how people will be using your class. If C++ had a "sealed" keyword, then the rule would be simpler: If you do a "delete p" where p is a pointer to an unsealed class, then that class needs have a virtual destructor. (The imaginary "sealed" keyword makes it explicit when a class can act as the base class for another class.)
Wednesday, September 3, 2008
How to setup an Openafs client on Ubuntu
Copy krb5.conf to /etc/krb5.conf
sudo apt-get install krb5-user openafs-krb5
- change default realm to ACM.UIUC.EDU (case matters)
- Kerberos servers are kerberos.acm.uiuc.edu and kerberos-1.acm.uiuc.edu
- admin server is kerberos.acm.uiuc.edu
sudo apt-get install gcc-3.4 build-essential openafs-client
- AFS Cell = acm.uiuc.edu (case matters)
- default cache size is fine b/c you aren't going to use it.
sudo apt-get install module-assistant
sudo m-a prepare openafs-modules
sudo module-assistant auto-build openafs-modules
sudo dpkg -i /usr/src/openafs-modules-*.deb
cd /etc/openafs
sudo vim afs.conf
- add: FNORD="-memcache -stat 10000 -blocks 65536 -chunksize 19"
This sets a 64MB in-memory cache. If you want to use a disk cache you'll need to make sure that /var/cache/openafs is ext2 and its probably a good idea to dedicate a parition to it. - set: OPTIONS=$FNORD
sudo vim afs.conf.client
- change AFS_DYNROOT=false to true
If you're running Ubuntu Dapper, there is an issue I've come across with the module not being auto-inserted upon reboot. This can be fixed by running a simple:
sudo depmod -a
sudo shutdown -r now "installing openafs"
Everything should be working!
your attribute: /afs/nd.edu/user39/jgai