Primitive Math – Solution

The solution to this month’s Exercise involves two things. First, knowing how to shift bits and second how to carefully enclose operators in parentheses to get the macros to behave.

The left-shift operator, <<, represents the fastest way to multiply a value. Here’s a crib sheet:

a<<1 double the value of a or a2
a<<2 quadruple the value of a or a3
a<<3 double-quadruple the value of a or a4

Yes, it’s our old programming buddies the powers of two: Keep shifting bits and you march through all of them: *2, *4, *8, on up to however wide the bitfield. You can read more about the power of the bit-shift in this blog post.

The macros you create as a solution for BYTWO(), BYFOUR(), and BYEIGHT() are the easiest to write — assuming that you’re taking advantage of the shift operator:

#define BYTWO(a) a<<1
#define BYFOUR(a) a<<2
#define BYEIGHT(a) a<<3

And, of course, the BYONE() macro isn’t that difficult to write, but it was part of the challenge:

#define BYONE(a) a

For the rest, combine these techniques, but only with a generous application of parentheses to keep the operations tight. To wit:

#define BYTHREE(a) a+(a<<1)

Three is *1 + *2, but you must write the *2 in parentheses: (a<<1) If you don't, the compiler gets all huffy.

You can see the rest of my macros in my solution here:

#include <stdio.h>

#define BYONE(a) a
#define BYTWO(a) a<<1
#define BYTHREE(a) a+(a<<1)
#define BYFOUR(a) a<<2
#define BYFIVE(a) a+(a<<2)
#define BYSIX(a) (a<<1)+(a<<1)+(a<<1)
#define BYSEVEN(a) a+(a<<2)+(a<<1)
#define BYEIGHT(a) a<<3
#define BYNINE(a) a+(a<<3)
#define BYTEN(a) (a<<3)+(a<<1)

int main()
{
    printf("%d *  1 = %d\n",6,BYONE(6));
    printf("%d *  2 = %d\n",6,BYTWO(6));
    printf("%d *  3 = %d\n",6,BYTHREE(6));
    printf("%d *  4 = %d\n",6,BYFOUR(6));
    printf("%d *  5 = %d\n",6,BYFIVE(6));
    printf("%d *  6 = %d\n",6,BYSIX(6));
    printf("%d *  7 = %d\n",6,BYSEVEN(6));
    printf("%d *  8 = %d\n",6,BYEIGHT(6));
    printf("%d *  9 = %d\n",6,BYNINE(6));
    printf("%d * 10 = %d\n",6,BYTEN(6));

    return(0);
}

Here's sample output:

6 * 1 = 6
6 * 2 = 12
6 * 3 = 18
6 * 4 = 24
6 * 5 = 30
6 * 6 = 36
6 * 7 = 42
6 * 8 = 48
6 * 9 = 54
6 * 10 = 60

I poured over some of my old Assembly code from decades past and couldn't find a specific routine where I included similar instructions for performing basic math. Most of what I did back when was pretty direct. For example, when I needed to triple a value, I shifted it left and then added it to itself immediately as opposed to writing a specific subroutine.

Anyway, I hope you came up with some clever solutions. Obviously, such macros aren't vital to solving any specific problem in the C language; plenty of math operators and functions perform arithmetic better. Just keep in mind the macro solution for some simple problems, especially if the macro names help make your code more readable.

2 thoughts on “Primitive Math – Solution

  1. Whenever I see anything like this I start to wonder about performance, for example in this case how much faster (if at all) is << compared to *?

    Maybe one day I'll try an experiment unless you get there first.

  2. Most definitely << is faster than * at the processor level. I'm unfamiliar with the tech specs on current processors, but back in the *86 days, the << (bit shift) operation took maybe 1 or 2 clock cycles. Multiplication, however, took two dozen. Therefore, at the processor level, it's far more efficient to bitshift than to use operands. The differences in clock cycle are even more pronounced for division. The drawback to this efficiency is that modern processors move so damn fast that the difference isn't noticeable by human standards. Now in a development environment, say I'm working with a team on video compression, then yes, we can optimize processor power by hand-coding bitshifts instead of multiplication or division. I'm almost certain this task is being done.

Leave a Reply