Leap year bug crashes Zune


year = ORIGINYEAR; /* = 1980 */

while (days > 365)
   if (IsLeapYear(year))
      if (days > 366)
         days -= 366;
         year += 1;
      days -= 365;
      year += 1;


Migrating to EXT4


To convert a file system from ext3 to ext4, use
tune2fs -O extents /dev/DEV

Finally do not forget to modify /etc/fstab.



cross distcc

It is possible to distribute compilations to machines with different architectures.

Here is an example, to allow distributing tasks from a 64-bit system (x86_64) to 32-bit systems (i686):

First of all, both the client and servers should have distcc installed, of course. Then run the distcc daemon at the servers. Be careful so that they are not refusing connections from the client.

The distcc servers should also have the corresponding cross toolchains installed.
In Gentoo, this is simple. Emerge crossdev and run crossdev --target x86_64-pc-linux-gnu. (Experience tells us it is better to stip -march=... from CFLAGS when building the cross toolchain, otherwise we may (or may not) encounter strange errors, though some options like -march=nocona are valid on both i686 and x86_64. The reason is beyond me...)

Then commands x86_64-pc-linux-gnu-{gcc,g++} should be available.

Most source packages are created with autotools, so they honor the environment variables CC and CXX. At the client end, export CC='distcc x86_64-pc-linux-gnu-gcc' and CXX='distcc x86_64-pc-linux-gnu-g++' before compiling.

It is important to use the full compiler name including the host architecutre (x86_64-pc-linux-gnu in this example). Otherwise the distcc servers call the native compilers, resulting in incompatible object files.

Alternatively you may want to use the “transparent” method of calling distcc: PATH="/usr/lib/distcc/bin:$PATH" make. This does not work automatically. Instead, it is necessary to use a wrapper script to make sure the architecture is explicitly specified:
# cd /usr/lib/distcc/bin
# rm cc c++ gcc g++
# echo '#!/bin/bash' > distcc-wrapper
# echo 'exec /usr/lib/distcc/bin/x86_64-pc-linux-gnu-g${0:$[-2]} "$@"' >> distcc-wrapper
# chmod +x distcc-wrapper
# ln -s distcc-wrapper cc
# ln -s distcc-wrapper c++
# ln -s distcc-wrapper gcc
# ln -s distcc-wrapper g++

[1] DistCC Cross-compiling Guide - Gentoo Documentation

How BASH Changes Terminal Window Title

In many distributions bash automatically changes the terminal title. I thought it was hardcoded in bash, but it turns out to be not. It is usually implemented with PROMPT_COMMAND.

Environment variable $PROMPT_COMMAND defines the command to be automatically executed before displaying the primary prompt (i.e. $PS1). It is set by a script that is sourced by interative instances of bash. In Gentoo it is in /etc/bash/bashrc:
case ${TERM} in

In fact, the first version above also works with newer versions of screen.

MATLAB matrices are in column-major storage

Authors of each and every high-level programming language claim you only have to care the semantics of its statements without worrying about its internal implementation. Unfortunately, this can hardly be true.

Today I was working on some MATLAB codes. One of them scales each row of a sparse matrix to make its 1-norm equal to 1. The matrix I worked on was 20000×20000, with 153306 nonzero entries.

This is the first version:
for k = 1:N
 s = sum(P(k,:));
 if s ~= 0
  P(k,:) = P(k,:)/s;
This did not stop in 20 seconds, until I pressed Control-C.

This is the second version:
P = P';
for k = 1:N
 s = sum(P(:,k));
 if s ~= 0
  P(:,k) = P(:,k)/s;
P = P';
This finished within one second.

[All entries of matrix P are known to be positive, so I simply use sum to get the 1-norm of a row/column.]

The reason is simple. MATLAB internally stores sparse matrices in compressed column format[1]. Therefore, it is many times more expensive to extract or insert a row than column.

ps. For dense matrices, MATLAB also uses column-major formats, following the FORTRAN convention, though MATLAB is itself written in C (and the GUI in Java) [1].


[1] J. Gilbert, C. Moler and R. Schreiber. Sparse matrices in MATLAB: Design and implementation. SIAM Journal on Matrix Analysis, 1992.

GCC #pragma pack bug

#pragma pack is accepted by many C/C++ compilers as the de facto standard grammar to handle alignment of variables.

However there is an old bug in GCC, reported many times, the first of which was in 2002, still not fixed now.
#include <cstdio>
using namespace std;

#pragma pack(1)
template <typename T>
struct A {
    char a;
    int b;
A<int> x;
#pragma pack(2)
A<char> y;
#pragma pack(4)
A<short> z;

int main()
    printf ("%d %d %d\n", sizeof x,sizeof y,sizeof z);
    return 0;

This gives 5 6 8 instead of 5 5 5 as we may expect. (VC++ and ICC both give the more reasonable 5 5 5.)

This example is not very bad. Even worse is, that this bug can damage programs that use STL. Here is an example:

#include <cstdio>
#include <map>
using namespace std;

#pragma pack(1)
void foo (const map<short,const char*> &x)
    for (map<short,const char*>::const_iterator it=x.begin();
            it!=x.end(); ++it)
        printf ("%d %s\n", it->first, it->second);

#include <map>
using namespace std;

void foo (const map<short,const char *> &);

int main()
    map<short, const char *> x;
    x[0] = "Hello";
    x[1] = "World";
    foo (x);

Compile a.cpp and b.cpp separately and link them together. This program segfaults if compiled with GCC, but works well with ICC or VC++.

In conclusion, for better portability and/or reliability, never use #pragma pack unless absolutely necessary. If really unavoidable, always push and pop immediately before and after the structure definition. (If the program is intended to be compiled by GCC/ICC only, it is better to use the more reliable GCC-specific __attribute__((__packed__)).)

PS. It seems Sun CC (shipped with Solaris) also has this bug. It fails for the first example here, but for the second it works well. I don't know how manages to align pair<short,const char *> correctly...