The Art of Computer Programming, Vol 4, Fascicle 2 typo? - knuth

At the bottom of page 5 is the phrase "changes k to k ⊕ (1j+1)2". Isn't 1 to any power still 1 even in binary? I'm thinking this must be a typo. I sent an email to Dr. Knuth to report this, but I don't expect to hear back for months. In the meantime, I'm trying to figure out what this is supposed to be.

This can be resolved by using the convention that (...)2 represents a bitwise representation. (1j+1)2 then consists solely of j+1 ones, rather than referring to an exponentiation. You can see this convention explained more explicitly in TAOCP Volume 4 Fascicle 1 at page 8, for example:
If x is almost any nonzero 2-adic
integer, we can write its bits in the
form
x =
(g01a10b)2
in other words, x consists of some
arbitrary (but infinite) binary string
g, followed by a 0, which is followed
by a+1 ones and followed by b zeros,
for some a >= 0 and b >= 0.
[I have substituted the symbol alpha by g to save encoding problems]
Going back to your original query;
k ⊕(1j+1)2 is equated with k ⊕ (2j+1 - 1)
implying that (1j+1)2 = (2j+1 - 1): this holds because the left-hand side is the integer whose significant bits are j+1 (contiguous) ones; the right-hand side is an exponentiation. For example, with j =3:
(14)2 = (1111)2 = (24 - 1)
Hope that helps.

A list of known typos can be found on the errata page:
http://www-cs-faculty.stanford.edu/~knuth/taocp.html
Your reported typo is not there. If it really is a typo, you might be eligible for a cash reward from Knuth himself.

Related

Variable length coding, how many bits to read?

Here is the snapshot from the AAC ISO standard:
How can I tell how many bits should I read for hcod_sf? What does 1..19 stands for?
VLC (Variable Length Coding) stands for a variable amount of bits being used. So in your example the current value consists of 1 to 19 bits.
This may seem confusing at first, but it follows a strict logic. There will surely be a table in the Appendix defining what bit combination represents what value.
Each value is represented by a certain - unique - bit combination which can be determined by serially reading bits.
For example this table:
0xxxxxxxxxxxxxxxxxx = value = 0 ( 1 bit length )
10xxxxxxxxxxxxxxxxx = value = 1 ( 2 bit length )
110xxxxxxxxxxxxxxxx = value = 2 ( 3 bit length )
1110xxxxxxxxxxxxxxx = value = 3 ( 4 bit length )
...
1111111111111111110 = value = 18 ( 19 bit length )
In this example a 0 denotes the end-of-the-value which, in combination with the 1s, encode the VLC value. As being said, you have to read the bitstream serially to get the length in bits of the value, so in this example you'd have to check for a trailing 0.
In reality, these tables are often constructed with Huffman Coding and hence are more complex than in this example. You will surely find the table for your translation in the aforementioned Appendix of the specification.
How can I tell how many bits should I read for hcod_sf?
You can only determine the number of bits to be read by reading them. Practically you read (at least 19) bits at once and then evaluate how many of these bits belong to the value (often by using a table).
What does 1..19 stands for?
It stands for the minimum (1) and maximum (19) amount of bits in this particular value.
Finally:
It's quite tricky to implement this, so knowing the BMI instruction set extension is really helpful for an x86 way of handling of this.

Looking for the fastest way to divide by 2

I've searched half the day and found some very interesting things about using fixed point data types and bit shifting in C++ to accomplish division operations while avoiding floating point math. However, I have only been able to understand a small fraction of it and I can't seem to get anything to work.
All I'm wanting to do is to take two integers, ad them up, and divide by two to get the average. I need to be able to do this very quickly though, since I'm interpolating camera pixel data on an Arduino and I also have other operations to do.
So I'm confused about shifting in general. Say the integer I want to divide by two is 27. Half of 27 is 13.5. But no matter what fixed point datatype I try, I can only get 13 as an output. For example:
uint8_t x = 27;
Serial.println( x >> 1 );
returns 13
There's got to be some simple way to do this, right?
Fixed point does give you a way to represent 13.5. The Wikipedia article on the Q number format is informative: https://en.wikipedia.org/wiki/Q_(number_format)
Think of it this way: You keep using integers, but instead of taking them at face value, divide them all implicitly by a power of 2 to obtain their semantic value.
So, if using an unsigned byte as your base type (values between 0 and 255, inclusive), you might implicitly divide by 2**3 (8). Now to represent 27, you need an integer set to 27*8=>216. To divide by two, you shift one to the right; now your integer is 108, which when divided by the implicit denominator of 8 gives 13.5, the value you're expecting.
You have to realize that fixed-point number systems (and floating point too, though it's less immediately evident) still have limits, of course; certain operations will overflow no matter what you do, and some operations cause a loss of precision. This is a normal consequence of working with limited-size types.
Say the integer I want to divide by two is 27. Half of 27 is 13.5. But
no matter what fixed point data type I try, I can only get 13 as an
output.
From wikipedia Fixed-Point Arithmetic:
The scaling factor is usually a power of 10 (for human convenience) or
a power of 2 (for computational efficiency).
You actually mentioned fixed point data type, and I think that is the best approach. But no matter what you tried? Perhaps we have different understandings of fixed-point-arithmetic.
while avoiding floating point math.
Another worth while goal, though reducing in value. Even in embedded systems, I seldom had to deal with a processor that did not have floating point parts. Floating point hardware has gotten reasonably good.
Any way, using fixed point avoids any need for floating point. Even for display purposes.
I think I need to proceed with a few examples.
Fixed point Example 1: Dollars and pennies
The unit of American money is based on the dollar. The Dollar is a fixed point data type.
So, if you have 27 dollars, how do you split it with your sibling?
One way (of several) that you all know is to convert 27 dollars into 2700 pennies. Dividing this value by 2 is trivial. Now you and your sibling can each get 1350 pennies. (i.e. the penny is a fixed point data type, that easily converts to/from dollars, and vice-vesa)
Note that this is completely integer arithmetic. Adding 2 integers, and dividing by 2 (any modern compiler will choose the fastest implementation.. either integer divide or perhaps right-shift-by-2) and on my desktop these 2 actions take less than a microsecond to complete.
You should waste no more time on measuring the relative performance of those two options (divide vs right-shift), you simply enable -O3 when your code tests correct. Your compiler should be able to choose correctly.
The choice of units in any problem is based on a scale factor that covers the range of values (in your problem) AND the understandable and quickly implemented conversion between units. And note that uint64_t can describe a large amount of cash, even in pennies. (challenge to the student.)
In General, about fixed point:
Given
uint8_t x = 27;
and the desire to divide by 2 evenly and quickly... can any scale factor be something that serves your needs? I say yes.
example 2 - 50 cent coins and a dollar
How about we try, for example, a simple scale factor of 2, i.e. the unit is a hu, or half unit. (analogous to the 50-cent-coin)
uint8_t x = 27 * 1/hu; (hu = 1/2)
This means that 54 hu represents 27 units. (ie, it takes 54 50-cent-coins to add up to 27 dollars)
The fixed point solution is to scale your integer values to achieve the arithmetic required. If you scale to even values, all your integers will divide evenly to the hu units.
example 3 - nickles and a dollar
Another possible scale might be 20, both decimal (for readability) and binary for performance. (note that there are 20 nickels in a dollar)
uint16 x = 27 * 1/tu; (tu = 1/20)
Now 540 represents a scaled 27. i.e. 540 nickles
All examples are fully integer, provide exact answers, and there is a trivial mechanism to convert the values for presentation to the user. i.e. which ever fixed point used, convert to analogue of pennies, and thus 1350 pennies.
Display the penny count as a dollar
std::cout << (pennyCount / 100) << "." << (pennyCount % 100) << std::endl;
I think this should look something like (untested)
13.50
Now your challenge is to make it look nice on the output.
The reason you only get 13 is because you are actually cutting off the least significant bits when you bit shift. Since you are cutting them off, there is no remainder to check. If you are interested in what your remainder is, you could do something like:
uint8_t x = 27;
Serial.println((x - (x >> 1) - (x >> 1));
(x - (x >> 1)) should give 14 here.
it would be pretty simple to add .5 to a number once you determine whether the remainder is 1.
The following should work and should be fast:
float y = (x >> 1) + (0.5 * (x & 0x01))
What it does
(x >> 1) Divide by 2 using the bit shift
(0.5 * (x & 0x01)) Add 0.5 if the last bit was 1 (odd number)

Double precision in FORMAT function

I don't have any programming experience in Fortran, but for one of my courses at school we have to translate a program from Fortran into Java. The line of code that I'm having an issue with is
295 FORMAT(1X,'Y(X) =',D25.16,' * X ',A1,D25.16,///)
I don't think the entire line is necessarily needed, but I wanted to give the whole line for some context. The part that says D25.16 has kind of thrown me off since I can't seem to find any information about this anywhere. I was originally thinking it was formatting a double precision number to be able to have 25 digits on the left side of the .(dot) and 16 digits on the right, but I can't seem to find any information on what that means and don't know if I'm for sure right or wrong about that. I was just seeing if anyone could give some insight to what that does.
The D edit descriptor is closely related to the E edit descriptor (which may be easier to find reading material about), but is distinct from the F edit descriptor mentioned in a comment.
E and D specify that the real number will be presented with an exponent. For output using E a number may be written as, say,
+0.1234e+12
For D25.16 you are correct that the number of digits after the decimal point is 16 (well, the fractional part), but it is the overall width of the field that is 25, not the number of digits to the left. [To the left is either a 0 or nothing.] The field width has contributions from the (obligatory) sign, (optional) leading 0, the (potentially optional) exponent marker, the (obligatory) exponent sign, and (at least) two exponent digits.
If there are three exponent digits then the exponent marker is missing (leading to such things as .1234+110).
There are differences between D and E:
D doesn't allow specification of the exponent width (cf., E15.5E5);
D allows (but doesn't oblige) use of D as the exponent marker (instead of E).

Can anyone explain how CRC works in this specific case?

I am taught that given:
message M = 101001
polynomial C = x^3 + x^2 + 1 = 1101
I should add k bits to the end of the message such that the result P is divisible by C (where k is the degree of the polynomial, 3 in this case).
I can find no 3 bit combination (XYZ) that when appended to M satisfies this criteria.
Does anyone know what is wrong with my understanding?
I'm 5 months late to this, but here goes :
Perhaps, thinking about this by integer (or binary) division is counterproductive. Better to work it out by the continuous XOR method - which gives a checksum of 001, rather than the expected 100. This, when appended to the source generates the check value 101001001.
Try this C code to see a somewhat descriptive view.
I'm no expert, but I got most of my CRC fundamentals from here. Hope that helps.

Bit twiddling for checking whether a number is in particular range

I found some interesting bit twiddling in "source\common\unicode\utf.h" file of ICU library (International Components for Unicode). The bit twiddling is intended for checking whether a number is in a particular range.
// Is a code point in a range of U+d800..U+dbff?
#define U_IS_LEAD(c) (((c)&0xfffffc00)==0xd800)
I have figured out the magic number (0xfffffc00) come from:
MagicNumber = 0xffffffff - (HighBound - LowBound)
However, I also found that the formula doesn't apply to every arbitrary range. Does somebody here know in what circumstance the formula works?
Is there another bit twiddling for checking whether a number is in particular range?
For these tricks to apply, the numbers must have some common features in their binary representation.
0xD800 == 0b1101_1000_0000_0000
0xDBFF == 0b1101_1011_1111_1111
What this test really does is to mask out the lower ten bits. This is usually written as
onlyHighBits = x & ~0x03FF
After this operation ("and not") the lower ten bits of onlyHighBits are guaranteed to be zero. That means that if this number equals the lower range of the interval now, it has been somewhere in the interval before.
This trick works in all cases where the lower and the higher limit of the interval start with the same digits in binary, and at some point the lower limit has only zeroes while the higher limit has only ones. In your example this is at the tenth position from the right.
If you do not have 2^x boundaries type might use the following trick:
if x >= 0 and x < N you can check both by:
if Longword( x ) < Longword( N ) then ...
This works due to the fact that negative numbers in signed numbers correspond to the largest numbers in unsigned datatypes.
You could extend this (when range checking is DISABLED) to:
if Longword( x - A ) < Longword ( ( B - A ) ) then ...
Now you have both tests (range [ A, B >) in a SUB and a CMP plus a single Jcc, assuming (B - A ) is precalculated.
I only use these kind of optimizations when really needed; eg they tend to make your code less readable and it only shaves off a few clock cycles per test.
Note to C like language readers: Longword is Delphi's unsigned 32bit datatype.
The formula works whenever the range you are looking for starts at a multiple of a power of 2 (that is, 1 or more bits at the low end of the binary form of the number ends in 0) and the size of the range is 2^n-1 (that is, low&high == low and low|high == high).