Leap year bug crashes Zune

Microsoft’s 30GB Zune players fail to work today (Dec 31).

The problem has been identified - A bug in the freescale firmware leads to an infinite loop on the last day of a leap year.
year = ORIGINYEAR; /* = 1980 */

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

If such poor codes were found in an airplane, or a medical device, ooops, it should be terrible..

Migrating to EXT4

Ext4, the successor to ext3 which was formerly known as ext4dev, is marked stable in Linux kernel 2.6.28, meaning the Linux kernel team now recommends using ext4 in production.

To convert a file system from ext3 to ext4, use
tune2fs -O extents /dev/DEV
and remount the file system as ext4. (Two e2fsck runs are recommended before and after tune2fs.) Some documentations also include the -E test_fs option. This is not necessary now since ext4 is no longer experimental.

Finally do not forget to modify /etc/fstab.

An ext4 file system created this way is not a “true” ext4 - the extents feature, the main advantage of ext4 comapred to ext3, is not automatically applied to old files. New files created afterwards are in the extents format.

Unlike the 100% backward compatibility of ext3 with ext2, an ext4 file system can no longer be mounted as if it were an ext3, unless the extents feature is disabled. (If you want to disable extents, why not simply use ext3?)

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++

Reference
[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
    xterm*|rxvt*|Eterm|aterm|kterm|gnome*|interix)
        PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/$HOME/~}\007"'
        ;;
    screen)
        PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/$HOME/~}\033\\"'
        ;;
esac

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;
 end
end
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;
 end
end
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].

References

[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:

a.cpp:
#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);
}

b.cpp:
#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...