• Welcome to the new Internet Infidels Discussion Board, formerly Talk Freethought.

The Programming Thread

First a brief note on C macros. Never mind that the macro is a silly triviality: we just use it to review syntax.

Consider the following code:
#define TIMES3(p) 3*p // return the macro argument times 3 [sic]​
x = 10;​
y = TIMES3(x + 5) / 5;​
What should y now equal? What does the coder probably want it to equal?
Please answer this before reading on.

Since x is 10; and x+5 is 15; TIMES3(x+5) should yield 3*15=45; so y = TIMES3(x+5)/5 should set y to the value 45/5 = 9.
But does it? Not in the C language.
Expanding the macro in
y = TIMES3(x + 5) / 5;​
yields
y = 3*x + 5 / 5;​
which is (3*10) + (5/5) or 31.

Let's add some parentheses in the macro definition:
#define TIMES3(p) (3*p) // return the macro argument times 3 [sic]​
x = 10;​
y = TIMES3(x + 5) / 5;​
Now we get y = (3*x + 5) / 5 which is 7. Different from 31, but still not what was intended.

Try again with even more parentheses:
#define TIMES3(p) (3*(p)) // return the macro argument times 3 [works correctly!]​
x = 10;​
y = TIMES3(x + 5) / 5;​
Now we get y = (3*(x + 5)) / 5 which is 9.

Because of these problems (or "ambiguities"), practiced C coders will add parentheses around all instances of arguments in the macro definition, AND around the entire macro definition. (Out of habit or "good taste", the coder usually provides the parentheses even when they appear unnecessary.)

It MIGHT seem wrong or ill-advised that C macros work as they do. But C programmers code in the C language, and NOT in the language they wish C were! :)

...
You're right that NB was "number of bits." And M was "mask." I do pick poor overly-short names. Guilty as charged.
Yes that's the one. BTW I suspect that
((m) / ((m) % 255 + 1) / 255 % 255 * 8 + 7 - 100 / ((m) % 255 + 14))
could be simplified a bit but I'm not sure the precedence of all of the operators (e.g. maybe * is done before +), etc. It really needs lots of brackets - though I think some are unnecessary... like the ones around m.... (unless you had a long expression using M_TO_NB(m))? I wonder how it handles something like a 0xF0F0F etc mask?

{ *, / , % } all have higher precedence than { + , -}. Precedence is left-to-right within THESE equal-precedence groups.
As explained above, the useless-looking parentheses are supplied -- whether needed in a specific invocation or not -- if only out of habit.

The weird macro does nothing useful with 0xF0F0F. It works only with a k-bit all-ones mask, i.e. 1 less than a power of two. This is implied by the test program I supplied, but I should have been much more explicit about that. (But note that the weird macro wasn't even used by the rest of my code; it was just an example of a "weird one-liner." I'd hoped it might elicit smiles, but I'm afraid every part of the posts earned only frowns. :-( )

You're welcome to try to simplify or understand the weird macro. But I do NOT think its arithmetic is deliberately over-complicated. It's just "magic arithmetic" ! I'd try to explain what I mean by this but by now we have ample evidence that I am unable to explain things.
 
Continuing the evaluation.

Calculating the percent deviation of each bin against the theoretical flat distribution, and averaging the 10 percentages as a metric to compare performance of the three functions.



#define MASK (RAND_MAX >> 2)
double RUF(void)
{ return (rand() & MASK | 1) / (double)(MASK+1); }

bin count %deviation
214958079 -0.00098
214433792 0.00146
214958080 -0.00098
214433792 0.00146
214958080 -0.00098
214958080 -0.00098
214433792 0.00146
214958080 -0.00098
214433792 0.00146
214958080 -0.00098
average deviation .001172%

double ruf2(void){
return double(rand()|1)/double(RAND_MAX+1);
}

214695935 0.00024
214827008 -0.00037
214695936 0.00024
214827008 -0.00037
214695936 0.00024
214695936 0.00024
214827008 -0.00037
214695936 0.00024
214827008 -0.00037
214695936 0.00024
average deviation .000293%

double ruf3(void){
unsigned int x;
while(1){
if(x = rand()) return(double(x)/double(RAND_MAX+1));
}
}

214702386 0.00021
214768051 -0.00009
214767894 -0.00009
214767931 -0.00009
214702530 0.00021
214768090 -0.00009
214768155 -0.00009
214767952 -0.00009
214768091 -0.00009
214702567 0.00021
average deviation .000128%


Kind of what I expected. The first two functions affect the distribution, albeit in a small way.
 
C macros are dangerously bug-prone. Consider:

#define ADDONE(x) x+1

The expression
2*ADDONE(x)
is Intended to be 2*(x+1) but it expands into 2*x+1

So what one has to do is

#define ADDONE(x) (x+1)

Parens are also a good way to avoid having to remember operator-precedence rules, and C has a *lot* of them.


C++ has a way to avoid that problem. In fact, many C++ features are ways of avoiding using the preprocessor and avoiding doing so in safe ways.

template<typename T>
inline T& ADDONE(const T &x) {return x + 1;}

The keyword "inline" means that the content of the function should be inserted at where the function was called, just like the preprocessor macro. But this expression is much safer. 2*ADDONE(x) will be interpreted as 2*(x+1)

The & is for calling by reference, as a way of transmitting data without using a pointer.

The const indicates that the code ought not to change the value of x. Trivial for a numeric type, not so trivial for many knids of objects. The purpose of this is to try to catch such a mismatch at compile time.

C++20 introduces "concepts". Here is an example that restricts the type of x to built-in numeric types:

template<typename T>
requires std::integral<T> || std::floating_point<T>
inline T ADDONE(const T x) {return x + 1;}

But if one does not want that restriction, if one has defined a modular-arithmetic class or a finite-field class, one can add restriction to such a class to the requires statement.

For compile-time calculations using constant values, one can make some functions "constexpr".

C++20 Concepts - a Quick Introduction - C++ Stories
 
In the day macros vs functions were parially about speed.

The compiler inserts the code for the macro when it runs. Compilers used to have a speed vs memory usage option. A macro takes up more memory than a function, but it takes less time to execute than a function.

There was a time when you had to work to fit code into 64k memory and speed was a limiting factor.
Not so much anymore.
 
I converted it to JavaScript so it can be run in the console of a browser - I had to use floor to turn float division into integer division....
JavaScript:
function mask_to_num_bits(m) {return (Math.floor(m / (m % 255 + 1) / 255) % 255 * 8 + 7 - Math.floor(100 / (m % 255 + 14)));}
It seems to work.... note it is in color because I set the language in the code popup....
 
Last edited:
Binary Arithmetic

Binary addition and multiplication is dome the same as base 10

value of an 8 bit int

b7*2^7 + b6*2^6 + b5*2^5 + b4*2^4 + b3*2^3 + b2*2^2+ b1*2^1 + b0*2^0

0r 1,2,4,8......

Binary Addition

0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 0 carry 1

Binary Multiplication
0 * 0 = 0
0 * 1 = 0
1 * 0 = 0
1 * 1 = 1

adding binary 3 + 3

11 3
11 + 3
-------------
110 6

multiplying binary 3*3, multiply digit by digit shift and add
11 3
11 * 3
--------------
11
11 +
-------------
1001 9

Note that a 4x4 binary multply resuts in 4digits. So a 32x32 multiply needs a 64 bit accumulator. The hardware multiply in the processor has a shift and add function.

There are fixed point and floating point decimal Numbers. Fixed point is easier to see.

Imagine a 16 bit decimal number with 1 sign bit,7 integer bits, and 8 fractional bits.



The resolution of the integer part is 1.

The resolution of the fractional part is 1/2^fractional bits.

For an 8 bit fractional part the resolution or least significant bit lsb is 1/2^8 = 0.0039062


The value of the number is
integer part + fractional part.
b6^2^6 + b5*b5 +b4^2^4 + b3*2^3*b2*2^2 + b1*2^1+b0+2^0+
lsb*b7*2^7+ lsb*b6^2^6 +lsb*b5*b5 +lsb*b4^2^4 lsb*b3*2^3*lsb*b2*2^2

Adding 1.0 + 1.5

00000110000000 1.5
00000010000000 0.5 +
---------------------------
00001000000000 2

If you know the bounds of the numbers fixed point can execute faster for repetitive operations like the Discrete Fourier Transform.

Floating point arithmetic is the same, but the decimal points have to be tracked and aligned for operations.

When code is executing there is no base 10, it is all integer operations.

Unless a number is an exact multiple of the fractional lsb it is an approximation.


A floating point number has a fixed number of digits, so as the integer part gets bigger and the decimal point shifts bits for the fractional part are reduced.
 
Last edited:
C macros are dangerously bug-prone. Consider:

#define ADDONE(x) x+1

The expression
2*ADDONE(x)
is Intended to be 2*(x+1) but it expands into 2*x+1

So what one has to do is

#define ADDONE(x) (x+1)

Parens are also a good way to avoid having to remember operator-precedence rules, and C has a *lot* of them.


C++ has a way to avoid that problem. In fact, many C++ features are ways of avoiding using the preprocessor and avoiding doing so in safe ways.

template<typename T>
inline T& ADDONE(const T &x) {return x + 1;}

The keyword "inline" means that the content of the function should be inserted at where the function was called, just like the preprocessor macro. But this expression is much safer. 2*ADDONE(x) will be interpreted as 2*(x+1)

The & is for calling by reference, as a way of transmitting data without using a pointer.

The const indicates that the code ought not to change the value of x. Trivial for a numeric type, not so trivial for many knids of objects. The purpose of this is to try to catch such a mismatch at compile time.

C++20 introduces "concepts". Here is an example that restricts the type of x to built-in numeric types:

template<typename T>
requires std::integral<T> || std::floating_point<T>
inline T ADDONE(const T x) {return x + 1;}

But if one does not want that restriction, if one has defined a modular-arithmetic class or a finite-field class, one can add restriction to such a class to the requires statement.

For compile-time calculations using constant values, one can make some functions "constexpr".

C++20 Concepts - a Quick Introduction - C++ Stories
You know more about C++ than I do......
 
First a brief note on C macros. Never mind that the macro is a silly triviality: we just use it to review syntax.

Consider the following code:
#define TIMES3(p) 3*p // return the macro argument times 3 [sic]​
x = 10;​
y = TIMES3(x + 5) / 5;​
What should y now equal? What does the coder probably want it to equal?
Please answer this before reading on.

Since x is 10; and x+5 is 15; TIMES3(x+5) should yield 3*15=45; so y = TIMES3(x+5)/5 should set y to the value 45/5 = 9.
But does it? Not in the C language.
Expanding the macro in
y = TIMES3(x + 5) / 5;​
yields
y = 3*x + 5 / 5;​
which is (3*10) + (5/5) or 31.

Let's add some parentheses in the macro definition:
#define TIMES3(p) (3*p) // return the macro argument times 3 [sic]​
x = 10;​
y = TIMES3(x + 5) / 5;​
Now we get y = (3*x + 5) / 5 which is 7. Different from 31, but still not what was intended.

Try again with even more parentheses:
#define TIMES3(p) (3*(p)) // return the macro argument times 3 [works correctly!]​
x = 10;​
y = TIMES3(x + 5) / 5;​
Now we get y = (3*(x + 5)) / 5 which is 9.

Because of these problems (or "ambiguities"), practiced C coders will add parentheses around all instances of arguments in the macro definition, AND around the entire macro definition. (Out of habit or "good taste", the coder usually provides the parentheses even when they appear unnecessary.)

It MIGHT seem wrong or ill-advised that C macros work as they do. But C programmers code in the C language, and NOT in the language they wish C were! :)

...
You're right that NB was "number of bits." And M was "mask." I do pick poor overly-short names. Guilty as charged.
Yes that's the one. BTW I suspect that
((m) / ((m) % 255 + 1) / 255 % 255 * 8 + 7 - 100 / ((m) % 255 + 14))
could be simplified a bit but I'm not sure the precedence of all of the operators (e.g. maybe * is done before +), etc. It really needs lots of brackets - though I think some are unnecessary... like the ones around m.... (unless you had a long expression using M_TO_NB(m))? I wonder how it handles something like a 0xF0F0F etc mask?

{ *, / , % } all have higher precedence than { + , -}. Precedence is left-to-right within THESE equal-precedence groups.
As explained above, the useless-looking parentheses are supplied -- whether needed in a specific invocation or not -- if only out of habit.

The weird macro does nothing useful with 0xF0F0F. It works only with a k-bit all-ones mask, i.e. 1 less than a power of two. This is implied by the test program I supplied, but I should have been much more explicit about that. (But note that the weird macro wasn't even used by the rest of my code; it was just an example of a "weird one-liner." I'd hoped it might elicit smiles, but I'm afraid every part of the posts earned only frowns. :-( )

You're welcome to try to simplify or understand the weird macro. But I do NOT think its arithmetic is deliberately over-complicated. It's just "magic arithmetic" ! I'd try to explain what I mean by this but by now we have ample evidence that I am unable to explain things.
I wondered how C macros differed from functions, and now I know! Although I'm not sure why you would use them instead of functions.
 
I wondered how C macros differed from functions, and now I know! Although I'm not sure why you would use them instead of functions.

Many macros are very similar to functions; and you're right -- a normal function will often be just as good. As Steve points out, macros often improved performance in bygone days, but much less so nowadays.

However anything defined by #define is called a "macro" in C, and many of these are simply not functions at all. The #define in C's pre-processor does only straightforward text substitution. Sometimes that will make the facility seem primitive, but it does yield clarity and flexibility.

For example, the original source to the shell sh shows that the author didn't like using braces to delimit code blocks and preferred Algol's key-words:
#define BEGIN {​
#define END }​

Or suppose you are porting code to a VERY old C compiler that doesn't even know the keywords const or void:
#define const /* erase all instances of this keyword */​
#define void int /* replace all instances of this keyword with 'int' */​

Finally here is a weird preprocessor trick. When it comes in handy, it may be VERY handy, but I personally have NEVER used it. First let me set the stage.

Another group has supplied you with a function named specialist(). However you are unable to call the routine because your over-zealous manager is obsessed with erectile dysfunction advertisements; when he gets a match on the substring "cialis" (in "speCIALISt"), he deletes your source file! Here's a work-around:[/I]

#define FORBIDDEN_NAME special##ist // let the pre-processor use its concatenation operator to construct the name that cannot be uttered​
name = FORBIDDEN_NAME("plumber"); // get the special plumber's name without uttering the forbidden word.​

This facility is sometimes generalized via
#define __CONCAT(a, b) a##b
#define _CONCAT(a, b) __CONCAT(a, b)​
(I don't know why two definitions are nested like this: gcc doesn't seem to need it.)
 
Swmi lies to post code snippets.
Here is one.

unsigned long long YabbaDabbaDoo(unsigned long long yabba,unsigned long long dabba){
unsigned long long doo = 0,dog_breath = 1;
for (int pi = 0; pi < 32; pi++)if(yabba & (dog_breath << pi)) doo += (dabba << pii);
return doo;
}

What does YabDabbaDoo do? It performs a useful function.
 
Last edited:
Swmi lies to post code snippets.
Here is one.

unsigned long long YabbaDabbaDoo(unsigned long long yabba,unsigned long long dabba){
unsigned long long doo = 0,dog_breath = 1;
for (int pi = 0; pi < 32; pi++)if(yabba & (dog_breath << pi)) doo += (dabba << pii);
return doo;
}

What does YabDabbaDoo do? It performs a useful function.

Obviously the function is intended to multiply its two inputs.

More to the point, the code is intended as a parody of Swammi's posts. If I wanted to parody Steve's posts I'd mention that modern hardware has faster ways to implement a = b*c. And of course neglect to proofread or test the posted code.
 
What should y now equal? What does the coder probably want it to equal?
Please answer this before reading on.
I stopped after reading the macro and seeing what you did.

The common answer to this is ALWAYS wrap macro bodies inside parentheses, or else the order of operations shifting will gut you.
 
Swmi lies to post code snippets.
Here is one.

unsigned long long YabbaDabbaDoo(unsigned long long yabba,unsigned long long dabba){
unsigned long long doo = 0,dog_breath = 1;
for (int pi = 0; pi < 32; pi++)if(yabba & (dog_breath << pi)) doo += (dabba << pii);
return doo;
}

What does YabDabbaDoo do? It performs a useful function.

Obviously the function is intended to multiply its two inputs.

More to the point, the code is intended as a parody of Swammi's posts. If I wanted to parody Steve's posts I'd mention that modern hardware has faster ways to implement a = b*c. And of course neglect to proofread or test the posted code.
It is obvious if you just run it and see what it does. Can you explain in your own words how it works? I'd also like to hear how your RUFF() fubnction works. What does the mask operation do?

I know, I know as you said 'don't try to figure it out it works'....

Yabba Dabba Doo!!! Go ahead and parody as you please. I worked in intense competitive peer environemts, for me water off a ducks back. Todo esta tranquillo amigo.
 
I've mentioned that I am (or was) an idiot savant, though it is the idiot that may be most apparent. I was called "the best microprogrammer in Silicon Valley;" the best circuit designer I ever met called me the best circuit designer he'd ever met; I have more than 30 U.S. patents. For a while I flew around the world repairing mainframes no one else could fix. There are several consumer electronic items in the 1990's that run my code or my algorithms. I am the author of several peer-reviewed journal articles, two books and a newspaper column. If it weren't for the idiot part of my brain, I might be famous. Even as is, I have to be careful with my mini-resume or Google would quickly find my real name.

I have made complex changes to complex software with no source code for the complex software I needed to modify, using only the binary object and a disassembler. If you want to challenge me to understand a piece of C code, you;ll need to use some of the tricks from The Obfuscated C contest, not just write the routine badly.

Almost all my coding was done in solitary projects and, although the code I delivered was much better than the code snippets I post here, it did suffer from similar defects. But once there was a software project that had consumed 25 man-years or thereabouts; it was delivered and failed to work. (The shift-summary module took 12 hours to run, but had at most 8 hours available.) Coders had fled. I was hired to fix that system and redesigned and recoded it in a few days. Most of the code I've written was written for my own amusement. Despite this, and despite frequent long vacations I saved enough of my consulting fees to retire comfortably. Fellow Infidels may admire Steve's code more than mine, but you're wrong if you think I'm an idiot-idiot rather than an idiot-savant. This conversation is getting grotesque, and reminds me of the guy who posted frequently a few months ago pretending to be a mathematician.


Swmi lies to post code snippets.
Here is one.

unsigned long long YabbaDabbaDoo(unsigned long long yabba,unsigned long long dabba){
unsigned long long doo = 0,dog_breath = 1;
for (int pi = 0; pi < 32; pi++)if(yabba & (dog_breath << pi)) doo += (dabba << pii);
return doo;
}

What does YabDabbaDoo do? It performs a useful function.[/I]

Obviously the function is intended to multiply its two inputs.

More to the point, the code is intended as a parody of Swammi's posts. If I wanted to parody Steve's posts I'd mention that modern hardware has faster ways to implement a = b*c. And of course neglect to proofread or test the posted code.
It is obvious if you just run it and see what it does. Can you explain in your own words how it works?

Wow. You really do NOT know whom you are "debating." To multiply b*c when b = 37 = 32+4+1, you compute (c*1 + c*4 + c*32). Do you really need a more detailed description?

I'd also like to hear how your RUFF() fubnction works. What does the mask operation do?

Here is the code I posted, with some white-space and comments added:
Code:
// return a random floating-point variable x uniformly distributed in 0 < x < 1
//     For illustration, if we run this using 4 random bits we will choose with equal probability from the values
//            { 1/16 , 3/16 , 5/16 , 7/16 , 9/16 , 11/16 , 13/16 , 15/16 }
//    Do  YOU have a better way to do this?
//    The mean value is 0.5 exactly.  Most coders get this wrong, though the bias, given enough random bits, is TINY.
// (Obviously we will want many more than 4 random bits;  the above is just to illustrate the approach.)

#define MASK  (MAXRAND >> 2)  // Let's discard the two high-order bits that random() presents us with.
// we don't need them.  And the smaller maximum may avoid issues with exceeding ranges for signed or floating-point numbers

// return a random variable uniformly distributed in 0 < x < 1
double ruf(void) {
           return
                             (random() & MASK                    // modify the random integer as explained above
                                                      | 1)                      // round any even number up.  See the illustration
                                              / (double)(MASK+1);  // convert to a floating point number 0 < x < 1
}
I know, I know as you said 'don't try to figure it out it works'....

Wrong again. I advised not to try to understand the arithmetic details in the MASK_TO_NBITS macro.
The ruf() function wasn't intended to be obfuscated. I didn't know an intensely competitive programmer would need to be spoon-fed. Should I have written the code in a different language?

Yabba Dabba Doo!!! Go ahead and parody as you please. I worked in intense competitive peer environemts, for me water off a ducks back. Todo esta tranquillo amigo.
 
Here is the code I posted, with some white-space and comments added:

Code:
// return a random floating-point variable x uniformly distributed in 0 < x < 1
//     For illustration, if we run this using 4 random bits we will choose with equal probability from the values
//            { 1/16 , 3/16 , 5/16 , 7/16 , 9/16 , 11/16 , 13/16 , 15/16 }
Maybe you have such impressive coding powers because of what you focus your attention on. Were you aware that you had a space before each comma in that comment? If so do you not care that it isn't presented in the standard way? Also no-one is setting the CODE pop-up to the language so that it is color-coded.
 
I've mentioned that I am (or was) an idiot savant, though it is the idiot that may be most apparent. I was called "the best microprogrammer in Silicon Valley;" the best circuit designer I ever met called me the best circuit designer he'd ever met; I have more than 30 U.S. patents. For a while I flew around the world repairing mainframes no one else could fix. There are several consumer electronic items in the 1990's that run my code or my algorithms. I am the author of several peer-reviewed journal articles, two books and a newspaper column. If it weren't for the idiot part of my brain, I might be famous. Even as is, I have to be careful with my mini-resume or Google would quickly find my real name.

I have made complex changes to complex software with no source code for the complex software I needed to modify, using only the binary object and a disassembler. If you want to challenge me to understand a piece of C code, you;ll need to use some of the tricks from The Obfuscated C contest, not just write the routine badly.

Almost all my coding was done in solitary projects and, although the code I delivered was much better than the code snippets I post here, it did suffer from similar defects. But once there was a software project that had consumed 25 man-years or thereabouts; it was delivered and failed to work. (The shift-summary module took 12 hours to run, but had at most 8 hours available.) Coders had fled. I was hired to fix that system and redesigned and recoded it in a few days. Most of the code I've written was written for my own amusement. Despite this, and despite frequent long vacations I saved enough of my consulting fees to retire comfortably. Fellow Infidels may admire Steve's code more than mine, but you're wrong if you think I'm an idiot-idiot rather than an idiot-savant. This conversation is getting grotesque, and reminds me of the guy who posted frequently a few months ago pretending to be a mathematician.


Swmi lies to post code snippets.
Here is one.

unsigned long long YabbaDabbaDoo(unsigned long long yabba,unsigned long long dabba){
unsigned long long doo = 0,dog_breath = 1;
for (int pi = 0; pi < 32; pi++)if(yabba & (dog_breath << pi)) doo += (dabba << pii);
return doo;
}

What does YabDabbaDoo do? It performs a useful function.[/I]

Obviously the function is intended to multiply its two inputs.

More to the point, the code is intended as a parody of Swammi's posts. If I wanted to parody Steve's posts I'd mention that modern hardware has faster ways to implement a = b*c. And of course neglect to proofread or test the posted code.
It is obvious if you just run it and see what it does. Can you explain in your own words how it works?

Wow. You really do NOT know whom you are "debating." To multiply b*c when b = 37 = 32+4+1, you compute (c*1 + c*4 + c*32). Do you really need a more detailed description?

I'd also like to hear how your RUFF() fubnction works. What does the mask operation do?

Here is the code I posted, with some white-space and comments added:
Code:
// return a random floating-point variable x uniformly distributed in 0 < x < 1
//     For illustration, if we run this using 4 random bits we will choose with equal probability from the values
//            { 1/16 , 3/16 , 5/16 , 7/16 , 9/16 , 11/16 , 13/16 , 15/16 }
//    Do  YOU have a better way to do this?
//    The mean value is 0.5 exactly.  Most coders get this wrong, though the bias, given enough random bits, is TINY.
// (Obviously we will want many more than 4 random bits;  the above is just to illustrate the approach.)

#define MASK  (MAXRAND >> 2)  // Let's discard the two high-order bits that random() presents us with.
// we don't need them.  And the smaller maximum may avoid issues with exceeding ranges for signed or floating-point numbers

// return a random variable uniformly distributed in 0 < x < 1
double ruf(void) {
           return
                             (random() & MASK                    // modify the random integer as explained above
                                                      | 1)                      // round any even number up.  See the illustration
                                              / (double)(MASK+1);  // convert to a floating point number 0 < x < 1
}
I know, I know as you said 'don't try to figure it out it works'....

Wrong again. I advised not to try to understand the arithmetic details in the MASK_TO_NBITS macro.
The ruf() function wasn't intended to be obfuscated. I didn't know an intensely competitive programmer would need to be spoon-fed. Should I have written the code in a different language?

Yabba Dabba Doo!!! Go ahead and parody as you please. I worked in intense competitive peer environemts, for me water off a ducks back. Todo esta tranquillo amigo.
Some posters have a tendency to wander in, shit their pants in an attempt to shit on the floor, pretend that the smell isn't coming from them, and then ask why you keep shitting your pants.

It tends to make it REALLY hard to discuss certain things.

Also, I would LOVE to discuss the idea of RNGs where multiple users can use the same RNG to come to parallel answers without having to wait for networks to deliver those answers by merely communicating small bits of data about what the endpoints wish to calculate, and everyone deriving the answers from that.
 
I guess my code and commentary were of no interest whatsoever except as straight-lines for nit-picking. If nothing else, I thought that it was interesting that 2D gaussians are easier to work with than 1D gaussians; but that elicited no comment except about "moving goalposts."

Here is the code I posted, with some white-space and comments added:

Code:
// return a random floating-point variable x uniformly distributed in 0 < x < 1
//     For illustration, if we run this using 4 random bits we will choose with equal probability from the values
//            { 1/16 , 3/16 , 5/16 , 7/16 , 9/16 , 11/16 , 13/16 , 15/16 }
Maybe you have such impressive coding powers because of what you focus your attention on. Were you aware that you had a space before each comma in that comment? If so do you not care that it isn't presented in the standard way? Also no-one is setting the CODE pop-up to the language so that it is color-coded.

Hunh? Let me address this:
(1) The spaces you complain of were in a comment, not in code. And would be irrelevant even if code.
(2) I WAS quite aware that I added those spaces. I did it deliberately. because it seemed to make the list slightly easier to read. And the entire post was in response to complaints that my code is hard to read. Do you think those extra spaces make the comment harder to read or understand?
(3) With only very few minor exceptions I am a strict adherent to what Henry Baker calls The One True Style of C coding. (Obviously I deviated from this to show "one-liner" snippets.) Checking a folder-group with 19,000 lines of my C source (in .c) files, I see 11 instances of " ," altogether and every single one of them was in a comment (and NOT a comment intended to mimic code -- as above, they clarified delimiting). That same folder group had a comparable number of lines in .h files; there there were ZERO instances of " ,".

Any more questions?
 
Some posters have a tendency to wander in, shit their pants in an attempt to shit on the floor, pretend that the smell isn't coming from them, and then ask why you keep shitting your pants.

It tends to make it REALLY hard to discuss certain things.

Also, I would LOVE to discuss the idea of RNGs where multiple users can use the same RNG to come to parallel answers without having to wait for networks to deliver those answers by merely communicating small bits of data about what the endpoints wish to calculate, and everyone deriving the answers from that.

I do NOT understand your need. Are you saying "re-entrant" random() does not address your problem?

If you can enunciate your need in a clear semi-formal specification, I will look at the problem.
 
Multiplying fractional numbers.

A 16 bit unsigned int split int 8 integer bits and 8 fractional bits.

The res_check() function demonstrates decimal accuracy vs number of fractional bits . Went through all this in the 80s, so a trip down memory lane. One of the reasons I got my first computer was to go through numerical methods texts.

If you want a project to learn from you can expand it to 64 bits and add a sign. You could convert the fixed point multiply to a floating point routine. I might work on that .
The functions should be self evident, ask if you have questions.

Going from a number to the fractional part is analogous to digitizing a continuos voltage with an analog to digital converter.

Code:
unsigned int  fixpt16_bin_mult(unsigned int a,unsigned int  b){
    //unsigfned fixed point multiply
    unsigned int   acc = 0,mask = 1;
    int nbits = 16,i;
    for (i = 0; i < nbits; i++)if (a & (mask << i)) acc += (b << i);
    return  acc>>8;//restore decimal pont location

}
double fix2float(unsigned int x){
        // converts 16 bit fixed point number to float
        // 8 integer 8 fractional bits
        double y,lsb = 1./pow(2,8);
        y = double((x&0xff00)>>8) + lsb*double(x&0x00ff);
        return y;
}


unsigned int dec2fix(double x){
    unsigned int y,frac_cnt;
    double frac,intg,lsb = 1./pow(2,8);
    frac = modf(x,&intg);
    y =(int(intg))<<8;
    frac_cnt = int(frac/lsb);
    return  y|frac_cnt;
}

double res_check(int nbits,double x){
    double lsb = 1./pow(2,nbits);
    int cnt = int(x/lsb);
    return double(cnt)*lsb;
}

int main()
{
    unsigned  int a=0,b=0,c=0;
    double x,af,bf;
    a = 0x0080; //decimal 0.5
    b = 0xffff; //decimal 255.5
    c = fixpt16_bin_mult(a,b);
    af = fix2float(a);
    bf = fix2float(b);
    x = fix2float(c);
    printf(" a  %f  b bf); %f  x  %f \n",af,bf,af*bf);
    printf("%f\n",x);
    x = dec2fix(255.6);
    bf = fix2float(x);
    printf("%f\n",bf);
    bf = res_check(16,.123);
    printf("res check %f\n",bf);
    return 0;
}
 
I guess my code and commentary were of no interest whatsoever except as straight-lines for nit-picking.
Well my style of programming involves nitpicking - e.g. in PHP having to fit the style guide regarding spaces, etc
If nothing else, I thought that it was interesting that 2D gaussians are easier to work with than 1D gaussians; but that elicited no comment except about "moving goalposts."
Here is the code I posted, with some white-space and comments added:

Code:
// return a random floating-point variable x uniformly distributed in 0 < x < 1
//     For illustration, if we run this using 4 random bits we will choose with equal probability from the values
//            { 1/16 , 3/16 , 5/16 , 7/16 , 9/16 , 11/16 , 13/16 , 15/16 }
Maybe you have such impressive coding powers because of what you focus your attention on. Were you aware that you had a space before each comma in that comment? If so do you not care that it isn't presented in the standard way? Also no-one is setting the CODE pop-up to the language so that it is color-coded.
Hunh? Let me address this:
(1) The spaces you complain of were in a comment, not in code.
It's just that I've never come across that before in a comment so I found it to be weird...
And would be irrelevant even if code.
Not in some style guides like PHP.
(2) I WAS quite aware that I added those spaces. I did it deliberately. because it seemed to make the list slightly easier to read.
Ok thanks for the explanation.
And the entire post was in response to complaints that my code is hard to read. Do you think those extra spaces make the comment harder to read or understand?
Sorry I'm used to style guides where there are no extra spaces in the code (edit: yes it is a comment not code). Yes it is slightly easier to read. Note that setting the language to C in the code popup would also make it easier to read - due to the colors. Using /* in the comments would make it even easier to read while being a normal thing to do with comments like this:
C:
/*
return a random floating-point variable x uniformly distributed in 0 < x < 1
     For illustration, if we run this using 4 random bits we will choose with equal probability from the values
            { 1/16 , 3/16 , 5/16 , 7/16 , 9/16 , 11/16 , 13/16 , 15/16 }
*/
(3) With only very few minor exceptions I am a strict adherent to what Henry Baker calls The One True Style of C coding. (Obviously I deviated from this to show "one-liner" snippets.) Checking a folder-group with 19,000 lines of my C source (in .c) files, I see 11 instances of " ," altogether and every single one of them was in a comment (and NOT a comment intended to mimic code -- as above, they clarified delimiting). That same folder group had a comparable number of lines in .h files; there there were ZERO instances of " ,".

Any more questions?
Well you said you were an "idiot" savant and I was just wondering whether those things involving commas were part of the "idiot" side of you. If you hadn't have said that I wouldn't have tried nit picking with the comments.
It seems you sometimes think for yourself rather than always following the normal way of doing things. Some things I said might be obvious but they could be helpful to other readers.
 
Last edited:
Back
Top Bottom