472,107 Members | 1,397 Online

# compare a large number of variables

Hi,

I wonder if there is a nice bit twiddling hack to compare a large
number of variables?

If you first store them in an array, you can do:

for (i = 0; i < n; i++) {
if (array[i] != value) {
/* array[i] differs from value, do something*/
}
}

but I dont have the variables in an array, and would like to figure out
a nice oneliner.

best regards.
E.

Nov 15 '05 #1
122 5010

Einar wrote:
Hi,

I wonder if there is a nice bit twiddling hack to compare a large
number of variables?

If you first store them in an array, you can do:

for (i = 0; i < n; i++) {
if (array[i] != value) {
/* array[i] differs from value, do something*/
}
}

but I dont have the variables in an array, and would like to figure out
a nice oneliner.

N nice one liners:

if (var1 != value) { /* do smth */ }
if (var2 != value) { /* do smth */ }
....
if (varN != value) { /* do smth */ }
P.Krumins

Nov 15 '05 #2

Einar wrote:
Hi,

I wonder if there is a nice bit twiddling hack to compare a large
number of variables?

If you first store them in an array, you can do:

for (i = 0; i < n; i++) {
if (array[i] != value) {
/* array[i] differs from value, do something*/
}
}

but I dont have the variables in an array, and would like to figure out
a nice oneliner.

I'm not sure what you're looking for, but it might
be one of

if (a != value || b != value || ... || z != value) {
/* at least one of a,b,...,z differs from
* value, do something */
}

or

if (a != value && b != value && ... &&& z != value) {
/* all of a,b,...,z differ from value, do
* something */
}

or

if (a != value) {
/* a differs from value, do something */
}
if (b != value) {
/* b differs from value, do something */
}
...
if (z != value) {
/* z differs from value, do something */
}

or as above but with `else' before all but the first `if'

or

int *ptr[] = { &a, &b, ..., &z };
for (i = 0; i < n; ++i) {
if (*ptr[i] != value) {
/* The i'th of a,b,...,z differs from
* value, do something */
}
}

If none of these is what you're trying to do, you'll
have to explain your intent more clearly.

--
Er*********@sun.com

Nov 15 '05 #3

Einar wrote:
Hi,

I wonder if there is a nice bit twiddling hack to compare a large
number of variables?

If you first store them in an array, you can do:

for (i = 0; i < n; i++) {
if (array[i] != value) {
/* array[i] differs from value, do something*/
}
}

but I dont have the variables in an array, and would like to figure out
a nice oneliner.

N nice one liners:

if (var1 != value) { /* do smth */ }
if (var2 != value) { /* do smth */ }
....
if (varN != value) { /* do smth */ }
P.Krumins

Nov 15 '05 #4
"Einar" <or******@yahoo.se> writes:
I wonder if there is a nice bit twiddling hack to compare a large
number of variables?

If you first store them in an array, you can do:

for (i = 0; i < n; i++) {
if (array[i] != value) {
/* array[i] differs from value, do something*/
}
}

but I dont have the variables in an array, and would like to figure out
a nice oneliner.

Perhaps they should be in an array.

If that's not an option, and you're going to be doing this a lot, you
might consider setting up an array of pointers to the variables and
looping over that.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #5
On 16 Aug 2005 08:12:35 -0700, "Einar" <or******@yahoo.se> wrote in
comp.lang.c:
Hi,

I wonder if there is a nice bit twiddling hack to compare a large
number of variables?

If you first store them in an array, you can do:

for (i = 0; i < n; i++) {
if (array[i] != value) {
/* array[i] differs from value, do something*/
}
}

but I dont have the variables in an array, and would like to figure out
a nice oneliner.

best regards.
E.

Here is a "trick" that I do not really recommend as best practice, but
I have used in small microcontrollers for embedded systems with severe
memory constraints.

Assuming you have a header that contains the following:

my_vars.h

extern int val_a;
extern int val_b;
/* ... */
extern int val_y;
extern int val_z;

....and of course you have a source file:

my_vars.c

int val_a;
int val_b;
/* ... */
int val_y;
int val_z;

....then you could change my_vars.h to:

extern int sneaky_array[];
#define val_a sneaky_array[0]
#define val_b sneaky_array[1]
/* ... */
#define val_y sneaky_array[24]
#define val_z sneaky_array[25]

....and change my_vars.c:

int sneaky_array[2];

....then you can write new code that can loop through the values as an
array, whereas older source code that refers to individual elements by
name will still compile and work with the new my_vars.h header.

But I really, really don't recommend this except for exceptional
circumstances.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 15 '05 #6
Hello Eric,

Yes, your suggestions work perfectly, but I was mor looking for a nice
bit operator to operate on all my variables and then to compare it with
the value. something like (a|b|c|d...z) != value (this wont work
however... ). This is just to get rid of a for-loop or lots of
if-statements, so it is nothing necesary, I'm just convinced that it is
possible to solve in another way, and I can't forget about it....
Ahhhrg.

best regards.
E.

Nov 15 '05 #7
Hi,

/* file.e */
USE(a)
USE(b)
USE(c)

/* file.c */
#define USE(var) do { \
if ( ##var != value) \
{ \
} \
while(0);
#include "file.e"

you can compile the code with -E option (gcc) and see the expanded code
as follows-

do { if (a > value ) { } while (0);
do { if (b > value ) { } while (0);
do { if (c > value ) { } while (0);

Regards,
-A M

Nov 15 '05 #8
On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
Hello Eric,

Yes, your suggestions work perfectly, but I was mor looking for a nice
bit operator to operate on all my variables and then to compare it with
the value. something like (a|b|c|d...z) != value (this wont work
however... ). This is just to get rid of a for-loop or lots of
if-statements, so it is nothing necesary, I'm just convinced that it is
possible to solve in another way, and I can't forget about it....
Ahhhrg.

if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
/* one or more of a,b,c,d...z is not equal to value */

I don't think that would generally be as efficient as using multiple
comparisons against value because in that case the first mismatch will
prevent the rest from being evaluated. You never know though - on some
hardware it might be; or the compiler might rewrite it for you.

Another alternative (also untested):

if ( ((a|b|c|d...z)&a&b&c&d...z) != value )
/* one or more of a,b,c,d...z is not equal to value */

--
http://members.dodo.com.au/~netocrat

Nov 15 '05 #9
Rerwite code to have them all grouped in a user defined type and then
use memcmp().

Nov 15 '05 #10
fr***@Infectedmail.com wrote:
Rerwite code to have them all grouped in a user defined type and then
use memcmp().

All what? Learn to quote. The google interface may by broken but it is
possible, and if you had read this (or almost any other group) you would
have seen that it is the done thing.

Search this group for broken google interface and you will see *lots* of
complaints, explanations of the problem, and instructions on how to get
Google to do the right thing.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 15 '05 #11
AM wrote:
#define USE(var) do { \
if ( ##var != value) \
{ \
} \
while(0); .... you can compile the code with -E option (gcc) and see the expanded code
as follows-

do { if (a > value ) { } while (0);
do { if (b > value ) { } while (0);
do { if (c > value ) { } while (0);

That's right. You can see the expanded code. You can't compile it
though. (Missing right brace.)

Peter

Nov 15 '05 #12

In article <pa****************************@dodo.com.au>, Netocrat <ne******@dodo.com.au> writes:
On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
Yes, your suggestions work perfectly, but I was mor looking for a nice
bit operator to operate on all my variables and then to compare it with
the value. something like (a|b|c|d...z) != value (this wont work
however... ).

if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
/* one or more of a,b,c,d...z is not equal to value */

Or the similarly silly:

if (a^value|b^value|c^value|...|z^value)
/* one or more of a,b,c,...,z is not equal to value */

(Untested, but I think that's right.) Or similarly:

if (a^b|b^c|c^d|...|y^z|z^value)

All assuming that we're working with values that aren't going to
produce trap representations, or with unsigned types.

Of course this is just a bitwise version of (in the second case):

if (a!=b || b!=c || ... || z!=value)

except that the logical version can short-circuit, so fewer
operations are performed. (Though it's conceivable that on some
systems it'd be faster to perform all the bitwise operations than
to do the comparing and branching required to implement short-
circuiting.)
I don't think that would generally be as efficient as using multiple
comparisons against value because in that case the first mismatch will
prevent the rest from being evaluated.

More important, it's lousy code, and performance is rarely as
important as maintainability. And if performance *is* crucial in
this case, then it's probably time to redesign - it's unlikely that
keeping a lot of independent variables and testing them all against a
single value is actually the best way to accomplish whatever it is
that the problem requires.

That said, in some code I might find it defensible to write this as
a multiline controlling expression in an if statement (using the
logical operators, not the bitwise ones), as long as it was clear.
--
Michael Wojcik mi************@microfocus.com

Ten or ten thousand, does it much signify, Helen, how we
date fantasmal events, London or Troy? -- Basil Bunting
Nov 15 '05 #13
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
In article <pa****************************@dodo.com.au>, Netocrat
<ne******@dodo.com.au> writes:
On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
> Yes, your suggestions work perfectly, but I was mor looking for a
> nice bit operator to operate on all my variables and then to compare
> it with the value. something like (a|b|c|d...z) != value (this wont
> work however... ).

if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
/* one or more of a,b,c,d...z is not equal to value */

Or the similarly silly:

if (a^value|b^value|c^value|...|z^value)
/* one or more of a,b,c,...,z is not equal to value */

No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false. I can't see a way to rearrange it using bitwise
or/and to work.

This really calls for a multi-way equality comparison:

if ( ! (a == b == c == d == ... == z == value) )

Obviously the semantics are wrong the way the equality operator is
currently defined, but I've sometimes wanted to use an expression like
this.
(Untested, but I think that's right.) Or similarly:

if (a^b|b^c|c^d|...|y^z|z^value)
Same problem as above.
All assuming that we're working with values that aren't going to produce
trap representations, or with unsigned types.
Right, these bitwise operations on signed integers are not portable.
Of course this is just a bitwise version of (in the second case):

if (a!=b || b!=c || ... || z!=value)
Except that the logical or can't be replaced with a bitwise or.

[...]
I don't think that would generally be as efficient as using multiple
comparisons against value because in that case the first mismatch will
prevent the rest from being evaluated.

More important, it's lousy code,

Its purpose is not immediately clear and it depends on unsigned integers.
Both issues can be dealt with by appropriate commenting. More typical
expressions would avoid the need for commenting but I don't think that
makes it "lousy" code - it's perfectly serviceable, just a little atypical
and obscure.
and performance is rarely as
important as maintainability. And if performance *is* crucial in this
case, then it's probably time to redesign - it's unlikely that keeping a
lot of independent variables and testing them all against a single value
is actually the best way to accomplish whatever it is that the problem
requires.

That's quite a sweeping claim (as to likelihood of needing a multi-way
test) and I haven't given much thought to its merits but I'm curious by
what reasoning you make it.

[...]

--
http://members.dodo.com.au/~netocrat

Nov 15 '05 #14
Netocrat wrote:

On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:

if (a!=b || b!=c || ... || z!=value)

Except that the logical or can't be replaced with a bitwise or.

Logical or can be replaced with a bitwise or,
when the arguments are all boolean (either 1 or 0),
and it doesn't matter that there's no short circuiting.

(0 || 0 || 1 || 0) == (0 | 0 | 1 | 0)

--
pete
Nov 15 '05 #15
On Thu, 18 Aug 2005 19:03:32 +0000, pete wrote:
Netocrat wrote:

On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:

> if (a!=b || b!=c || ... || z!=value)

Except that the logical or can't be replaced with a bitwise or.

Logical or can be replaced with a bitwise or,
when the arguments are all boolean (either 1 or 0),
and it doesn't matter that there's no short circuiting.

(0 || 0 || 1 || 0) == (0 | 0 | 1 | 0)

The statement quoted top of post was being compared with:

if (a^b|b^c|c^d|...|y^z|z^value)

They are equivalent statements only when each variable represents a single
bit. For a single bit, a ^ b is equivalent to a != b and as you pointed
out, a | b is equivalent to a || b. But for variables comprised of
multiple bits, the equivalence no longer holds.

So yes, I agree with you, but it doesn't apply in this case because a, b,
etc aren't boolean variables.

--
http://members.dodo.com.au/~netocrat

Nov 15 '05 #16

"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa***************************@dodo.com.au...
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
In article <pa****************************@dodo.com.au>, Netocrat
<ne******@dodo.com.au> writes:
On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:

> Yes, your suggestions work perfectly, but I was mor looking for a
> nice bit operator to operate on all my variables and then to compare
> it with the value. something like (a|b|c|d...z) != value (this wont
> work however... ).

if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
/* one or more of a,b,c,d...z is not equal to value */

Or the similarly silly:

if (a^value|b^value|c^value|...|z^value)
/* one or more of a,b,c,...,z is not equal to value */

No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false. I can't see a way to rearrange it using bitwise
or/and to work.

Albeit ugly, this should work:

if(a-b|b-c|c-d|d-e /* ... */)
puts("mismatched");
else
puts("pick one... they're all the same");

Nov 15 '05 #17
Netocrat <ne******@dodo.com.au> writes:
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
In article <pa****************************@dodo.com.au>, Netocrat
<ne******@dodo.com.au> writes:
On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:

> Yes, your suggestions work perfectly, but I was mor looking for a
> nice bit operator to operate on all my variables and then to compare
> it with the value. something like (a|b|c|d...z) != value (this wont
> work however... ).

if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
/* one or more of a,b,c,d...z is not equal to value */

Or the similarly silly:

if (a^value|b^value|c^value|...|z^value)
/* one or more of a,b,c,...,z is not equal to value */

No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false.

Nov 15 '05 #18
On Fri, 19 Aug 2005 05:17:27 +1000, Netocrat wrote:
On Thu, 18 Aug 2005 19:03:32 +0000, pete wrote:
Netocrat wrote:
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:

> if (a!=b || b!=c || ... || z!=value)

Except that the logical or can't be replaced with a bitwise or.

Logical or can be replaced with a bitwise or,
when the arguments are all boolean (either 1 or 0),
and it doesn't matter that there's no short circuiting.

(0 || 0 || 1 || 0) == (0 | 0 | 1 | 0)

The statement quoted top of post was being compared with:

if (a^b|b^c|c^d|...|y^z|z^value)

They are equivalent statements only when each variable represents a single
bit. For a single bit, a ^ b is equivalent to a != b and as you pointed
out, a | b is equivalent to a || b. But for variables comprised of
multiple bits, the equivalence no longer holds.

So yes, I agree with you, but it doesn't apply in this case because a, b,
etc aren't boolean variables.

OK I've worded the concluding sentence inaccurately. Try this instead:
So your comment is valid and my original analysis should have rejected
the replacement of != with ^ rather than | with ||.

--
http://members.dodo.com.au/~netocrat

Nov 15 '05 #19
On Thu, 18 Aug 2005 13:03:34 -0700, Tim Rentsch wrote:
Netocrat <ne******@dodo.com.au> writes:
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
> In article <pa****************************@dodo.com.au>, Netocrat
> <ne******@dodo.com.au> writes:
>> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
>>
>> > Yes, your suggestions work perfectly, but I was mor looking for a
>> > nice bit operator to operate on all my variables and then to compare
>> > it with the value. something like (a|b|c|d...z) != value (this wont
>> > work however... ).
>>
>>
>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
>> /* one or more of a,b,c,d...z is not equal to value */
>
> Or the similarly silly:
>
> if (a^value|b^value|c^value|...|z^value)
> /* one or more of a,b,c,...,z is not equal to value */

No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false.

It's identical to my original comment except for the addition of a couple
of commas. Please be more specific.

--
http://members.dodo.com.au/~netocrat

Nov 15 '05 #20
Netocrat <ne******@dodo.com.au> writes:
On Thu, 18 Aug 2005 13:03:34 -0700, Tim Rentsch wrote:
Netocrat <ne******@dodo.com.au> writes:
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
> In article <pa****************************@dodo.com.au>, Netocrat
> <ne******@dodo.com.au> writes:
>> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
>>
>> > Yes, your suggestions work perfectly, but I was mor looking for a
>> > nice bit operator to operate on all my variables and then to compare
>> > it with the value. something like (a|b|c|d...z) != value (this wont
>> > work however... ).
>>
>>
>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
>> /* one or more of a,b,c,d...z is not equal to value */
>
> Or the similarly silly:
>
> if (a^value|b^value|c^value|...|z^value)
> /* one or more of a,b,c,...,z is not equal to value */

No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false.

It's identical to my original comment except for the addition of a couple
of commas. Please be more specific.

In the case of one variable with a==1, value==1 then a^value
is false. The first branch of the 'if' is not taken; all
elements of {a} are equal to value, or equivalently, none of
the elements of {a} is not equal to value.

The 'if' expression works just as the comment says it does.
The remark of "No that doesn't work" is therefore, shall
we say, less than totally accurate.
Nov 15 '05 #21
On Thu, 18 Aug 2005 20:01:31 +0000, Mark wrote:
"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa***************************@dodo.com.au...
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
In article <pa****************************@dodo.com.au>, Netocrat
<ne******@dodo.com.au> writes:
On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:

> Yes, your suggestions work perfectly, but I was mor looking for a
> nice bit operator to operate on all my variables and then to compare
> it with the value. something like (a|b|c|d...z) != value (this wont
> work however... ).

if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
/* one or more of a,b,c,d...z is not equal to value */

Or the similarly silly:

if (a^value|b^value|c^value|...|z^value)
/* one or more of a,b,c,...,z is not equal to value */

No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false. I can't see a way to rearrange it using bitwise
or/and to work.

Albeit ugly, this should work:

if(a-b|b-c|c-d|d-e /* ... */)
puts("mismatched");
else
puts("pick one... they're all the same");

All zero? Overflow?

Also it doesn't use the ^ operator - but you my not have been responding
directly to what I said (which was intended to mean that I can't see a way
to rearrange the expression so that it works as intended, keeping the ^
expressions and using other bitwise operators as required - and I wouldn't
have objected to an overall negation operator if that had been necessary).

--
http://members.dodo.com.au/~netocrat
Nov 15 '05 #22
On Thu, 18 Aug 2005 13:34:06 -0700, Tim Rentsch wrote:
Netocrat <ne******@dodo.com.au> writes:
On Thu, 18 Aug 2005 13:03:34 -0700, Tim Rentsch wrote:
> Netocrat <ne******@dodo.com.au> writes:
>> On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
>> > In article <pa****************************@dodo.com.au>, Netocrat
>> > <ne******@dodo.com.au> writes:
>> >> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
>> >>
>> >> > Yes, your suggestions work perfectly, but I was mor looking for a
>> >> > nice bit operator to operate on all my variables and then to compare
>> >> > it with the value. something like (a|b|c|d...z) != value (this wont
>> >> > work however... ).
>> >>
>> >> How about (off the top of my head and untested):
>> >>
>> >> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
>> >> /* one or more of a,b,c,d...z is not equal to value */
>> >
>> > Or the similarly silly:
>> >
>> > if (a^value|b^value|c^value|...|z^value)
>> > /* one or more of a,b,c,...,z is not equal to value */
>>
>> No that doesn't work. In the case of one variable with a==1, value==1
>> then a^value is false.
>

It's identical to my original comment except for the addition of a couple
of commas. Please be more specific.

In the case of one variable with a==1, value==1 then a^value
is false. The first branch of the 'if' is not taken; all
elements of {a} are equal to value, or equivalently, none of
the elements of {a} is not equal to value.

The 'if' expression works just as the comment says it does.
The remark of "No that doesn't work" is therefore, shall
we say, less than totally accurate.

If the comment entirely defined the expected behaviour, then you would be
right. Actually though, the code is to be read as though followed by:

else
/* all variables are equal to value */

because the context of the thread is a search for a one-liner to determine
whether all variables are equal to a value or not. The example I
provided shows that as a one-liner it fails in at least one case.

--
http://members.dodo.com.au/~netocrat

Nov 15 '05 #23
Netocrat <ne******@dodo.com.au> writes:
On Thu, 18 Aug 2005 13:34:06 -0700, Tim Rentsch wrote:
Netocrat <ne******@dodo.com.au> writes:
On Thu, 18 Aug 2005 13:03:34 -0700, Tim Rentsch wrote:
> Netocrat <ne******@dodo.com.au> writes:
>> On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
>> > In article <pa****************************@dodo.com.au>, Netocrat
>> > <ne******@dodo.com.au> writes:
>> >> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
>> >>
>> >> > Yes, your suggestions work perfectly, but I was mor looking for a
>> >> > nice bit operator to operate on all my variables and then to compare
>> >> > it with the value. something like (a|b|c|d...z) != value (this wont
>> >> > work however... ).
>> >>
>> >> How about (off the top of my head and untested):
>> >>
>> >> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
>> >> /* one or more of a,b,c,d...z is not equal to value */
>> >
>> > Or the similarly silly:
>> >
>> > if (a^value|b^value|c^value|...|z^value)
>> > /* one or more of a,b,c,...,z is not equal to value */
>>
>> No that doesn't work. In the case of one variable with a==1, value==1
>> then a^value is false.
>

It's identical to my original comment except for the addition of a couple
of commas. Please be more specific.
In the case of one variable with a==1, value==1 then a^value
is false. The first branch of the 'if' is not taken; all
elements of {a} are equal to value, or equivalently, none of
the elements of {a} is not equal to value.

The 'if' expression works just as the comment says it does.
The remark of "No that doesn't work" is therefore, shall
we say, less than totally accurate.

If the comment entirely defined the expected behaviour, then you would be
right. Actually though, the code is to be read as though followed by:

else
/* all variables are equal to value */

not necessary to understand the point being made, nor, I feel
confident, what the poster intended. In any case that's
and if you want to make presumptions about something that
*wasn't* written then the burden is on you to state what
those presumptions are. Don't expect other people to read

because the context of the thread is a search for a one-liner to determine
whether all variables are equal to a value or not. The example I
provided shows that as a one-liner it fails in at least one case.

the thread is a search for code to determine whether *any*
variables are *not* equal to a value. Which is exactly what
the posted code did.
Nov 15 '05 #24
>> >> On Thu, 18 Aug 2005 13:03:34 -0700, Tim Rentsch wrote:
>> > Netocrat <ne******@dodo.com.au> writes:
>> >> On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
>> >> > In article <pa****************************@dodo.com.au>,
>> >> > Netocrat <ne******@dodo.com.au> writes:
>> >> >> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
>> >> >>
>> >> >> > Yes, your suggestions work perfectly, but I was mor looking
>> >> >> > for a nice bit operator to operate on all my variables and
>> >> >> > then to compare it with the value. something like
>> >> >> > (a|b|c|d...z) != value (this wont work however... ).
>> >> >>
>> >> >> How about (off the top of my head and untested):
>> >> >>
>> >> >> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) )
>> >> >> )
>> >> >> /* one or more of a,b,c,d...z is not equal to value */
>> >> >
>> >> > Or the similarly silly:
>> >> >
>> >> > if (a^value|b^value|c^value|...|z^value)
>> >> > /* one or more of a,b,c,...,z is not equal to value */
>> >>
>> >> No that doesn't work. [...] > The 'if' expression works ... The remark of "No that doesn't work" is
> therefore, shall we say, less than totally accurate.

Xors have always been a weak spot in my logic. You're right, the code
works as advertised as Pete attempted to point out elsewhere in his usual
understated style.

[...]

--
http://members.dodo.com.au/~netocrat

Nov 15 '05 #25

"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa****************************@dodo.com.au...
On Thu, 18 Aug 2005 20:01:31 +0000, Mark wrote:
"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa***************************@dodo.com.au...
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
In article <pa****************************@dodo.com.au>, Netocrat
<ne******@dodo.com.au> writes:
> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
>
> > Yes, your suggestions work perfectly, but I was mor looking for a
> > nice bit operator to operate on all my variables and then to compare
> > it with the value. something like (a|b|c|d...z) != value (this wont
> > work however... ).
>
>
> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
> /* one or more of a,b,c,d...z is not equal to value */

Or the similarly silly:

if (a^value|b^value|c^value|...|z^value)
/* one or more of a,b,c,...,z is not equal to value */

No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false. I can't see a way to rearrange it using bitwise
or/and to work.
Albeit ugly, this should work:

if(a-b|b-c|c-d|d-e /* ... */)
puts("mismatched");
else
puts("pick one... they're all the same");

All zero? Overflow?

Overflow is not possible, stare at it for a while and see if you can figure
out why ;)
Also it doesn't use the ^ operator You didn't say it had to use the exclusive or operator ... you said bit
operator, no?
AFAIK the inclusive or operator is a bit operator... do you disagree?

- but you my not have been responding directly to what I said I was.
(which was intended to mean that I can't see a way
to rearrange the expression so that it works as intended, keeping the ^ No, you said using bitwise operators, which I most definately did.
expressions and using other bitwise operators as required - and I wouldn't
have objected to an overall negation operator if that had been necessary).

Whatever that means.
Do you know what the code does? Obviously not if you're worried about
overflow ;)
Nov 15 '05 #26

"Mark" <so***@localbar.com> wrote in message

"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa****************************@dodo.com.au...
On Thu, 18 Aug 2005 20:01:31 +0000, Mark wrote:
"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa***************************@dodo.com.au...
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
> In article <pa****************************@dodo.com.au>, Netocrat
> <ne******@dodo.com.au> writes:
>> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
>>
>> > Yes, your suggestions work perfectly, but I was mor looking for a
>> > nice bit operator to operate on all my variables and then to
>> > compare
>> > it with the value. something like (a|b|c|d...z) != value (this wont
>> > work however... ).
>>
>>
>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
>> /* one or more of a,b,c,d...z is not equal to value */
>
> Or the similarly silly:
>
> if (a^value|b^value|c^value|...|z^value)
> /* one or more of a,b,c,...,z is not equal to value */

No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false. I can't see a way to rearrange it using bitwise
or/and to work.

Albeit ugly, this should work:

if(a-b|b-c|c-d|d-e /* ... */)
puts("mismatched");
else
puts("pick one... they're all the same");
All zero? Overflow?

Overflow is not possible, stare at it for a while and see if you can
figure out why ;)

Rather than 'not possible' let me rephrase and say 'not an issue' ;)
unless the values are equal, there must be at least one bit set...
which will in turn cause the statement to work properly.
Also it doesn't use the ^ operator

You didn't say it had to use the exclusive or operator ... you said bit
operator, no?
AFAIK the inclusive or operator is a bit operator... do you disagree?

- but you my not have been responding
directly to what I said

I was.

Well, actually I was also responding to the OP question, which as of yet you
(which was intended to mean that I can't see a way
to rearrange the expression so that it works as intended, keeping the ^

No, you said using bitwise operators, which I most definately did.

And again, OP did not require exlusive or operator.
expressions and using other bitwise operators as required - and I
wouldn't
have objected to an overall negation operator if that had been
necessary). Whatever that means.

I realized what you meant after reading your post a 2nd time... should have
waited a minute before responding, but I do that frequently ;)
Do you know what the code does? Obviously not if you're worried about
overflow ;)

.... as it couldn't affect the outcome of the statement... it should work
properly regardless.

Much better, I'm happy now.
Mark
Nov 15 '05 #27
On Fri, 19 Aug 2005 15:11:10 +0000, Mark wrote:
"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa****************************@dodo.com.au...
On Thu, 18 Aug 2005 20:01:31 +0000, Mark wrote:
"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa***************************@dodo.com.au...
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
> In article <pa****************************@dodo.com.au>, Netocrat
> <ne******@dodo.com.au> writes:
>> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
>>
>> > Yes, your suggestions work perfectly, but I was mor looking for a
>> > nice bit operator to operate on all my variables and then to compare
>> > it with the value. something like (a|b|c|d...z) != value (this wont
>> > work however... ).
>>
>>
>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
>> /* one or more of a,b,c,d...z is not equal to value */
>
> Or the similarly silly:
>
> if (a^value|b^value|c^value|...|z^value)
> /* one or more of a,b,c,...,z is not equal to value */

No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false. I can't see a way to rearrange it using bitwise
or/and to work.

Albeit ugly, this should work:

if(a-b|b-c|c-d|d-e /* ... */)
puts("mismatched");
else
puts("pick one... they're all the same");
All zero?
Embarrassingly, my logic circuits have been malfunctioning in this
thread... as evidenced above (the xor code works contrary to my claim) and
here - the code performs correctly for all variables zero.
Overflow?

Overflow is not possible, stare at it for a while and see if you can figure
out why ;)

Perhaps I don't understand the overflow requirements. And perhaps I
should have called it underflow instead of overflow. But by my
understanding, if a and b are unsigned and a == 0 and b > 0, then the
expression (a-b) results in an underflow, which is undefined behaviour.

I don't see that this would be changed by it being part of a greater
expression. But my strike rate in this thread hasn't been crash hot so
I'm not betting the bank on it...

Alternatively this could occur if both are signed int and a == INT_MIN
and b > 0, but as noted by Michael Wojcik the bitwise operators may result
in trap representations for signed types - so we should require unsigned
variables for portability.
Also it doesn't use the ^ operator

You didn't say it had to use the exclusive or operator ... you said bit
operator, no?

Right, but I wrote "rearranged" and intended that to mean retaining the
expressions with the ^ operator, but I can see how you might have
interpreted me differently. Anyhow as it turns out there is no need for
rearrangement as it works as is.

[...] Do you know what the code does?

It looks to me like it compares each variable to its neighbour by
subtracting one from the other; if any of the comparisons are unequal then
at least one bit will be set in the result and the bitwise or will
agglomerate any of these bits into the final result, which will be
non-zero only if any variable differs from its neighbour - and by chaining
neighbours this equates to if any variable differs from any of the rest.

[...]

--
http://members.dodo.com.au/~netocrat

Nov 15 '05 #28
Mark wrote:
Mark wrote:
Netocrat wrote:
Mark wrote:
>> Netocrat wrote: [...]>>>
>>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
>>> /* one or more of a,b,c,d...z is not equal to value */ [...] Albeit ugly, this should work:

if(a-b|b-c|c-d|d-e /* ... */)
puts("mismatched");
else
puts("pick one... they're all the same");

All zero? Overflow? Overflow is not possible, stare at it for a while and see if you can
figure out why ;)

Rather than 'not possible' let me rephrase and say 'not an issue' ;)
unless the values are equal, there must be at least one bit set...
which will in turn cause the statement to work properly.

As far as I understand, overflow/underflow invokes behaviour not covered
by the standard, which may include setting all bits to zero.

[...] Well, actually I was also responding to the OP question, which as of yet
What do you find deficient in my suggestion above, or the alternative
I gave which got snipped:

if ( ((a|b|c|d...z)&a&b&c&d...z) != value )
/* one or more of a,b,c,d...z is not equal to value */
?
I realized what you meant after reading your post a 2nd time... should have
waited a minute before responding, but I do that frequently ;)

I can relate. :P

[...]
--
http://members.dodo.com.au/~netocrat

Nov 15 '05 #29

"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa****************************@dodo.com.au...
Mark wrote:
Mark wrote:
Netocrat wrote:
Mark wrote:
>>> Netocrat wrote: [...]>>>>
>>>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
>>>> /* one or more of a,b,c,d...z is not equal to value */ [...]> Albeit ugly, this should work:
>
> if(a-b|b-c|c-d|d-e /* ... */)
> puts("mismatched");
> else
> puts("pick one... they're all the same");

All zero? Overflow?
Overflow is not possible, stare at it for a while and see if you can
figure out why ;) Rather than 'not possible' let me rephrase and say 'not an issue' ;)
unless the values are equal, there must be at least one bit set...
which will in turn cause the statement to work properly.

As far as I understand, overflow/underflow invokes behaviour not covered
by the standard, which may include setting all bits to zero.

I thought it was covered... no?

H.2.2 Integer types
[#1] The signed C integer types int, long int, long long
int, and the corresponding unsigned types are compatible
with LIA-1. If an implementation adds support for the LIA-1
exceptional values integer_overflow and undefined, then
those types are LIA-1 conformant types. C's unsigned
integer types are ``modulo'' in the LIA-1 sense in that
overflows or out-of-bounds results silently wrap. An
implementation that defines signed integer types as also
being modulo need not detect integer overflow, in which
case, only integer divide-by-zero need be detected.

[...]
Well, actually I was also responding to the OP question, which as of yet
What do you find deficient in my suggestion above, or the alternative
I gave which got snipped:
if ( ((a|b|c|d...z)&a&b&c&d...z) != value )
/* one or more of a,b,c,d...z is not equal to value */

I didn't see this one... it must have been elsethread. ;)
As for deficiency, consider:
a = b = d = f = INT_MAX;
c = -1;
Regarding the one above, I didn't examine it...
The text which followed your suggestion was what prompted me to post.
<repost neocrat quote> No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false. I can't see a way to rearrange it using bitwise
or/and to work.

I did see a way to arrange it using a bitwise or, so I posted my solution ;)

Mark
Nov 15 '05 #30

Flash Gordon wrote:
fr***@Infectedmail.com wrote:
Rerwite code to have them all grouped in a user defined type and then
use memcmp().

All what? Learn to quote. The google interface may by broken but it is
possible, and if you had read this (or almost any other group) you would
have seen that it is the done thing.

Search this group for broken google interface and you will see *lots* of
complaints, explanations of the problem, and instructions on how to get
Google to do the right thing.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.

Learn to think. My post, in any interface was an answer to the subject
line. Read the subject and my post. Still can't figger it out? Ccan't
find the plural word in the subject? Complain away. You are good at it.

Nov 15 '05 #31
"Mark" <so***@localbar.com> writes:
"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa****************************@dodo.com.au...
[snip]
As far as I understand, overflow/underflow invokes behaviour not covered
by the standard, which may include setting all bits to zero.

I thought it was covered... no?

H.2.2 Integer types
[#1] The signed C integer types int, long int, long long
int, and the corresponding unsigned types are compatible
with LIA-1. If an implementation adds support for the LIA-1
exceptional values integer_overflow and undefined, then
those types are LIA-1 conformant types. C's unsigned
integer types are ``modulo'' in the LIA-1 sense in that
overflows or out-of-bounds results silently wrap. An
implementation that defines signed integer types as also
being modulo need not detect integer overflow, in which
case, only integer divide-by-zero need be detected.

First: Appendix H is informative rather than normative.

Second: The paragraph above only says that signed integer
types *may* behave in a certain way ("An implementation that
defines...", etc). The standard itself says that what
happens when overflow occurs is undefined behavior (6.5 p5).
Indeed, what happens on integer overflow is cited as an
example (3.4.3 p3) in the definition of undefined behavior.
Nov 15 '05 #32
Netocrat wrote:
Mark wrote:
"Netocrat" <ne******@dodo.com.au> wrote in message
Mark wrote:
"Netocrat" <ne******@dodo.com.au> wrote in message

.... snip ...

Albeit ugly, this should work:

if(a-b|b-c|c-d|d-e /* ... */)
puts("mismatched");
else
puts("pick one... they're all the same");

All zero?
Embarrassingly, my logic circuits have been malfunctioning in this
thread... as evidenced above (the xor code works contrary to my
claim) and here - the code performs correctly for all variables zero.
Overflow?

Overflow is not possible, stare at it for a while and see if you
can figure out why ;)

Perhaps I don't understand the overflow requirements. And perhaps
I should have called it underflow instead of overflow. But by my
understanding, if a and b are unsigned and a == 0 and b > 0, then
the expression (a-b) results in an underflow, which is undefined
behaviour.

Unsigned ints do not overflow. The result is exactly defined by
using modulo arithmetic.

Assuming you want to detect 'all same' vs 'something different',
you can do it with:

if ((a-b) || (b-c) || (c-d) || .... ) different();
else (same)

If the values are in an array A[N] then you can use:

for (unequal = 0, i = 1; i < N; i++) {
if (A[i] |= A[i-1]) {
unequal = 1;
break;
}
}
if (unequal) different();
else same();

and this will function for ints as well as unsigned.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
Nov 15 '05 #33
On Fri, 19 Aug 2005 17:05:38 +0000, Mark wrote:
"Netocrat" <ne******@dodo.com.au> wrote:
Mark wrote:
Mark wrote:
Netocrat wrote:
> Mark wrote:
>>>> Netocrat wrote:

[...]
>>>>>
>>>>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
>>>>> /* one or more of a,b,c,d...z is not equal to value */

[...]
>> Albeit ugly, this should work:
>>
>> if(a-b|b-c|c-d|d-e /* ... */)
>> puts("mismatched");
>> else
>> puts("pick one... they're all the same");
>
> All zero? Overflow?
Overflow is not possible, stare at it for a while and see if you can
figure out why ;)
Rather than 'not possible' let me rephrase and say 'not an issue' ;)
unless the values are equal, there must be at least one bit set...
which will in turn cause the statement to work properly.
OK, as others have pointed out overflow only invokes undefined behaviour
for signed arithmetic, and unsigned arithmetic wraps. So for that reason
and because the bit operators are not portable on signed operands all of
the techniques proposed in this thread are restricted to unsigned
operands. Once that restriction is imposed there is no overflow problem

[...] Well, actually I was also responding to the OP question, which as of

What do you find deficient in my suggestion above, or the alternative I
gave which got snipped:
if ( ((a|b|c|d...z)&a&b&c&d...z) != value ) /* one or more of
a,b,c,d...z is not equal to value */

I didn't see this one... it must have been elsethread. ;) As for
deficiency, consider:
a = b = d = f = INT_MAX;
c = -1;

Signed operands can't portably be used, although assuming no trap
representations I can't see a problem with that particular situation. But
looking at it again, the expression is wrong (and needlessly complicated).
It should rather be:

if ( value != (a&b&c&d...z&value) )
/* one or more of a,b,c,d...z is not equal to value */

[...]

--
http://members.dodo.com.au/~netocrat

Nov 15 '05 #34
fr***@Infectedmail.com wrote:
Flash Gordon wrote:
fr***@Infectedmail.com wrote:
Rerwite code to have them all grouped in a user defined type
and then use memcmp().

All what? Learn to quote. The google interface may by broken but
it is possible, and if you had read this (or almost any other
group) you would have seen that it is the done thing.

Search this group for broken google interface and you will see
*lots* of complaints, explanations of the problem, and
instructions on how to get Google to do the right thing.

Learn to think. My post, in any interface was an answer to the
subject line. Read the subject and my post. Still can't figger
it out? Ccan't find the plural word in the subject? Complain
away. You are good at it.

The point is that in many newsreaders the subject is not easily
available to the reader, and neither are previous messages in the
thread. In fact, they may not be available at all. The cure for
this is to make each article stand by itself. Google users who are
ignorant of normal conventions, and how to implement them on
google, have become a plague on usenet.

Don't be so ready to pick a fight. If you do you will shortly find
yourself killfiled by most of the knowledgeable participants here.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
Nov 15 '05 #35

"Tim Rentsch" <tx*@alumnus.caltech.edu> wrote in message
news:kf*************@alumnus.caltech.edu...
"Mark" <so***@localbar.com> writes:
"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa****************************@dodo.com.au...
>[snip]
> As far as I understand, overflow/underflow invokes behaviour not
> covered
> by the standard, which may include setting all bits to zero.
I thought it was covered... no?

H.2.2 Integer types
[#1] The signed C integer types int, long int, long long
int, and the corresponding unsigned types are compatible
with LIA-1. If an implementation adds support for the LIA-1
exceptional values integer_overflow and undefined, then
those types are LIA-1 conformant types. C's unsigned
integer types are ``modulo'' in the LIA-1 sense in that
overflows or out-of-bounds results silently wrap. An
implementation that defines signed integer types as also
being modulo need not detect integer overflow, in which
case, only integer divide-by-zero need be detected.

First: Appendix H is informative rather than normative.

Second: The paragraph above only says that signed integer
types *may* behave in a certain way

No, it also states that unsigned integer types DO behave a certain way.
("An implementation that
defines...", etc). The standard itself says that what
happens when overflow occurs is undefined behavior (6.5 p5). It also states that the result will silently wrap...
be it informative or normative... it's still a part of the standard, no?
Indeed, what happens on integer overflow is cited as an
example (3.4.3 p3) in the definition of undefined behavior.

3.18.3 - no? But you do realize that the line to which you
refer is informative rather than normative, don't you?
If not, read the forward again (part 6 to be specific :-)
Nov 15 '05 #36

"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa***************************@dodo.com.au...
On Fri, 19 Aug 2005 17:05:38 +0000, Mark wrote:
"Netocrat" <ne******@dodo.com.au> wrote:
Mark wrote:
Mark wrote:
> Netocrat wrote:
>> Mark wrote:
>>>>> Netocrat wrote:
[...]
>>>>>>
>>>>>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
>>>>>> /* one or more of a,b,c,d...z is not equal to value */
[...]
>>> Albeit ugly, this should work:
>>>
>>> if(a-b|b-c|c-d|d-e /* ... */)
>>> puts("mismatched");
>>> else
>>> puts("pick one... they're all the same");
>>
>> All zero? Overflow?
> Overflow is not possible, stare at it for a while and see if you can
> figure out why ;)
Rather than 'not possible' let me rephrase and say 'not an issue' ;)
unless the values are equal, there must be at least one bit set...
which will in turn cause the statement to work properly.
OK, as others have pointed out overflow only invokes undefined behaviour
for signed arithmetic, and unsigned arithmetic wraps. So for that reason
and because the bit operators are not portable on signed operands all of
the techniques proposed in this thread are restricted to unsigned
operands. Once that restriction is imposed there is no overflow problem

[...] Well, actually I was also responding to the OP question, which as of

What do you find deficient in my suggestion above, or the alternative I
gave which got snipped:
if ( ((a|b|c|d...z)&a&b&c&d...z) != value ) /* one or more of
a,b,c,d...z is not equal to value */
I didn't see this one... it must have been elsethread. ;) As for
deficiency, consider:
a = b = d = f = INT_MAX;
c = -1;

Signed operands can't portably be used, although assuming no trap
representations I can't see a problem with that particular situation.

The problem is your code doesn't work... try it.
c = (unsigned) -1; can most definately be used... and your code
reports all values as being equal when passed arguments specified.
But
looking at it again, the expression is wrong (and needlessly complicated).
It should rather be:

if ( value != (a&b&c&d...z&value) )
/* one or more of a,b,c,d...z is not equal to value */

Has the same problem as the other...
try setting the values as I specified earlier...
The only example you provided which doesn't choke on it was
the first :
>>>>>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )

Which also happens to be the one you claimed was wrong up-thread!

Regards,
Mark

Nov 15 '05 #37
"Mark" <so***@localbar.com> wrote:
"Netocrat" <ne******@dodo.com.au> wrote:
Mark wrote:
"Netocrat" <ne******@dodo.com.au> wrote: if ( ((a|b|c|d...z)&a&b&c&d...z) != value ) /* one or more of
a,b,c,d...z is not equal to value */
[...]
The problem is your code doesn't work... try it. [...]
But looking at it again, the expression is wrong (and needlessly
complicated). It should rather be:

if ( value != (a&b&c&d...z&value) )
/* one or more of a,b,c,d...z is not equal to value */

Has the same problem as the other...

Yes they're both flawed after all. I was attempting to simplify my
original expression that you quote below but apparently the off-the-cuff
simplifications were lacking.

[...] The only example you provided which doesn't choke on it was
the first :>>>>>>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )

Which also happens to be the one you claimed was wrong up-thread!

Actually the one I claimed was wrong was the xor solution and I've already
retracted that claim.

--
http://members.dodo.com.au/~netocrat
Nov 15 '05 #38
"Mark" <so***@localbar.com> writes:
"Tim Rentsch" <tx*@alumnus.caltech.edu> wrote in message
news:kf*************@alumnus.caltech.edu...
"Mark" <so***@localbar.com> writes:
"Netocrat" <ne******@dodo.com.au> wrote in message
news:pa****************************@dodo.com.au...
>[snip]
> As far as I understand, overflow/underflow invokes behaviour not
> covered
> by the standard, which may include setting all bits to zero.

I thought it was covered... no?

H.2.2 Integer types
[#1] The signed C integer types int, long int, long long
int, and the corresponding unsigned types are compatible
with LIA-1. If an implementation adds support for the LIA-1
exceptional values integer_overflow and undefined, then
those types are LIA-1 conformant types. C's unsigned
integer types are ``modulo'' in the LIA-1 sense in that
overflows or out-of-bounds results silently wrap. An
implementation that defines signed integer types as also
being modulo need not detect integer overflow, in which
case, only integer divide-by-zero need be detected.

First: Appendix H is informative rather than normative.

Second: The paragraph above only says that signed integer
types *may* behave in a certain way

No, it also states that unsigned integer types DO behave a certain way.

The subject in question is overflow (or underflow), which
usually is understood to refer to signed integer types rather
than unsigned integer types. This understanding is consistent
with the wording of the standard, "A computation involving
unsigned operands can never overflow," 6.2.5 p9. If what is
being talked about is overflow -- which I think is a reasonable
assumption considering the context -- then the relevant portion
of the cited H.2.2 is only that about signed integer types.

("An implementation that
defines...", etc). The standard itself says that what
happens when overflow occurs is undefined behavior (6.5 p5).

It also states that the result will silently wrap...

6.5 p5 does not say that. H.2.2 says for unsigned integer
types that overflows "silently wrap" (presumably in the sense
of LIA-1, since the C standard itself uses different wording).
Neither 6.5 p5 nor H.2.2 says for signed integer types that
overflow results must "silently wrap"; for 6.5 p5, to the
contrary:

If an <i>exceptional condition</i> occurs during the
evaluation of an expression (that is, the result is
not mathematically defined or not in the range of
representable values for its type), the behavior is
undefined.

"Not in the range of representable values" is synonymous
with overflow (or underflow) for signed integer types.

be it informative or normative... it's still a part of
the standard, no?
Normative text takes precedence over informative text.

Indeed, what happens on integer overflow is cited as an
example (3.4.3 p3) in the definition of undefined behavior.

3.18.3 - no?

In my document [ISO/IEC 9899:1999 (E)], 3.18 is a definition of
the ceiling function. Section 3.4 defines different kinds of
behaviors, with 3.4.3 defining "undefined behavior". I don't
know what document you have.

But you do realize that the line to which you
refer is informative rather than normative, don't you?
If not, read the forward again (part 6 to be specific :-)

The text in 6.5 p5 is normative. The combination of an explicit
statement of undefined behavior in 6.5 p5, and being used as
_the_ definitional example (even if Examples are informative
rather than normative text) in 3.4.3 p3, makes a pretty strong
argument that overflow is undefined behavior; and that the text
in H.2.2 is talking (to be explicit, for signed integer types)
only about some implementations, not all implementations.

"An implementation that defines signed integer types as also
being modulo ..." is simply one way that the undefined behavior
of overflow may manifest. Another implementation could just as
well choose to always return zero, or all 1 bits, or a trap
representation that caused the computer to catch fire if stored
Nov 15 '05 #39
"Tim Rentsch" <tx*@alumnus.caltech.edu> wrote in message
news:kf*************@alumnus.caltech.edu...
"Mark" <so***@localbar.com> writes:
"Tim Rentsch" <tx*@alumnus.caltech.edu> wrote in message
news:kf*************@alumnus.caltech.edu...
> "Mark" <so***@localbar.com> writes:
>> "Netocrat" <ne******@dodo.com.au> wrote in message
>> news:pa****************************@dodo.com.au...
>> >[snip]
>> > As far as I understand, overflow/underflow invokes behaviour not
>> > covered
>> > by the standard, which may include setting all bits to zero.
>>
>> I thought it was covered... no?
>>
>> H.2.2 Integer types
>> [#1] The signed C integer types int, long int, long long
>> int, and the corresponding unsigned types are compatible
>> with LIA-1. If an implementation adds support for the LIA-1
>> exceptional values integer_overflow and undefined, then
>> those types are LIA-1 conformant types. C's unsigned
>> integer types are ``modulo'' in the LIA-1 sense in that
>> overflows or out-of-bounds results silently wrap. An
>> implementation that defines signed integer types as also
>> being modulo need not detect integer overflow, in which
>> case, only integer divide-by-zero need be detected.
>>
>
> First: Appendix H is informative rather than normative.
>
> Second: The paragraph above only says that signed integer
> types *may* behave in a certain way No, it also states that unsigned integer types DO behave a certain way.

The subject in question is overflow (or underflow), which
usually is understood to refer to signed integer types rather
than unsigned integer types.

Then why are we having this discussion?
This understanding is consistent
with the wording of the standard, "A computation involving
unsigned operands can never overflow," 6.2.5 p9. Then I was correct in my initial statement that in my example
'Overflow is not possible.' - I was concerned after seeing H.2.2 that
my statement was incorrect, so I ammended it to 'not an issue'.
I now retract my ammended statement and stand by my original claim.
Thanks for the citation. :-)
If what is
being talked about is overflow -- which I think is a reasonable
assumption considering the context -- then the relevant portion
of the cited H.2.2 is only that about signed integer types. But we have been dealing with bit operands the entire time,
so considering the context you should assume we are
dealing with unsigned integer types, no? I have been... which again
is why I earlier stated that 'overflow is not possible'.
> ("An implementation that
> defines...", etc). The standard itself says that what
> happens when overflow occurs is undefined behavior (6.5 p5).

It also states that the result will silently wrap...

6.5 p5 does not say that. H.2.2 says for unsigned integer
types that overflows "silently wrap" (presumably in the sense
of LIA-1, since the C standard itself uses different wording).
Neither 6.5 p5 nor H.2.2 says for signed integer types that
overflow results must "silently wrap"; for 6.5 p5, to the
contrary:

If an <i>exceptional condition</i> occurs during the
evaluation of an expression (that is, the result is
not mathematically defined or not in the range of
representable values for its type), the behavior is
undefined.

"Not in the range of representable values" is synonymous
with overflow (or underflow) for signed integer types.

be it informative or normative... it's still a part of
the standard, no?

Normative text takes precedence over informative text.

> Indeed, what happens on integer overflow is cited as an
> example (3.4.3 p3) in the definition of undefined behavior.

3.18.3 - no?

In my document [ISO/IEC 9899:1999 (E)], 3.18 is a definition of
the ceiling function.

Impossible, there is no such function in the C language.
I assume you are referring to the 'ceil' functions?
7.12.9.1 in my text... I am using the last version of the committee draft
Section 3.4 defines different kinds of
behaviors, with 3.4.3 defining "undefined behavior". I don't
know what document you have.

Nor do I know what you are reading if it truly defines a 'ceiling' function.

Regards,
Mark
Nov 15 '05 #40
CBFalconer wrote
(in article <43***************@yahoo.com>):
Don't be so ready to pick a fight. If you do you will shortly find
yourself killfiled by most of the knowledgeable participants here.

That's true. The only ones allowed to pick a fight in c.l.c are
the regulars themselves. :-)

--

Nov 15 '05 #41
--MIME VERSION -3.1415926--
Mime-type: CONTENT-TYPE text/poopli
Mime-encoding: MULTIPART-POOP DATA

My life has been so much more pleasant since I was plonked.
C programs now, and not worry about being harassed by
the peanut gallery.

I *highly* recommend that all newcomers top-post, phrase
questions in the subject line that aren't repeated in the
body, use a nonstandard quoted-text character, post in html
with mime headers, and leave out all context from messages
they reply to. The sooner these people put you in your
kill file, the happier you'll be!
In article <43***************@yahoo.com>,
CBFalconer <cb********@worldnet.att.net> wrote:
+
+ Don't be so ready to pick a fight. If you do you will shortly find
+ yourself killfiled by most of the knowledgeable participants here.

--CONTENT DELIMITER--
Mime-type: text-html
Mime-encoding: utf-8
Content-length: sqrt(-1)

<htm1>
<title>
Very important data goes into the title. Never use
body text to show information or ask questions!
</title>
<body>

<p>
My life has been so much more pleasant since I was plonked.
C programs now, and not worry about being harassed by
the peanut gallery.
<p>
I *highly* recommend that all newcomers top-post, phrase
questions in the subject line that aren't repeated in the
body, use a nonstandard quoted-text character, post in html
with mime headers, and leave out all context from messages
they reply to. The sooner these people put you in your
kill file, the happier you'll be!
<blockquote>
<pre>
In article <43***************@yahoo.com>,
CBFalconer <cb********@worldnet.att.net> wrote:
+
+ Don't be so ready to pick a fight. If you do you will shortly find
+ yourself killfiled by most of the knowledgeable participants here.
</pre>
</blockquote>
</body>
<hmt1>

--MIMES-ARE-SILENT--
Nov 15 '05 #42

In article <pa***************************@dodo.com.au>, Netocrat <ne******@dodo.com.au> writes:
On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
In article <pa****************************@dodo.com.au>, Netocrat
<ne******@dodo.com.au> writes:
On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
Or the similarly silly:

if (a^value|b^value|c^value|...|z^value)
/* one or more of a,b,c,...,z is not equal to value */

No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false.

As it should be. Try reading for comprehension.
This really calls for a multi-way equality comparison:

if ( ! (a == b == c == d == ... == z == value) )

Obviously the semantics are wrong the way the equality operator is
currently defined, but I've sometimes wanted to use an expression like
this.
Try COBOL, which does support it, and perhaps you'll see why many
COBOL experts avoid it. (Actually, the COBOL syntax would be "if
value not = a or b or c".)
Of course this is just a bitwise version of (in the second case):

if (a!=b || b!=c || ... || z!=value)

Except that the logical or can't be replaced with a bitwise or.

Who said that it could be?
More important, it's lousy code,

Its purpose is not immediately clear and it depends on unsigned integers.

The former sufficies for lousiness. The latter may as well,
depending on other constraints which are not specified here.
Both issues can be dealt with by appropriate commenting. More typical
expressions would avoid the need for commenting but I don't think that
makes it "lousy" code - it's perfectly serviceable, just a little atypical
and obscure.

I note your opinion on the matter but continue to disagree. It's
*not* "perfectly serviceable": it imposes unnecessary restrictions
on domain and comprehensibility for no clear gain.
And if performance *is* crucial in this
case, then it's probably time to redesign - it's unlikely that keeping a
lot of independent variables and testing them all against a single value
is actually the best way to accomplish whatever it is that the problem
requires.

That's quite a sweeping claim (as to likelihood of needing a multi-way
test) and I haven't given much thought to its merits but I'm curious by
what reasoning you make it.

This is a more ambitious claim than, say, your claim about efficiency
in your previous post, which did not account for, say, branch
misprediction penalties, branching overhead, and code expansion due
to the additional tests? (I'm not claiming that performing all of
the operations is necessarily faster, or even proposing any
probability that it would be, but if *I* were going to make a claim
the mechanisms at play in various processor architectures and the
like.)

My claim is based on experience, and I believe it's plausible. Feel
free to present a counterargument.

--
Michael Wojcik mi************@microfocus.com

Proverbs for Paranoids, 1: You may never get to touch the Master,
but you can tickle his creatures. -- Thomas Pynchon
Nov 15 '05 #43
mw*****@newsguy.com (Michael Wojcik) wrote:
Netocrat <ne******@dodo.com.au> writes:
No that doesn't work. In the case of one variable with a==1, value==1
then a^value is false.

As it should be. Try reading for comprehension.

Fair enough, I miscalled it - there was nothing wrong with your code.
This really calls for a multi-way equality comparison:

if ( ! (a == b == c == d == ... == z == value) )

Obviously the semantics are wrong the way the equality operator is
currently defined, but I've sometimes wanted to use an expression like
this.

Try COBOL, which does support it, and perhaps you'll see why many
COBOL experts avoid it. (Actually, the COBOL syntax would be "if
value not = a or b or c".)

I don't know COBOL. Why do COBOL experts avoid it?

[...]
> And if performance *is* crucial in this case, then it's probably time
> to redesign - it's unlikely that keeping a lot of independent
> variables and testing them all against a single value is actually the
> best way to accomplish whatever it is that the problem requires.

That's quite a sweeping claim (as to likelihood of needing a multi-way
test) and I haven't given much thought to its merits but I'm curious by
what reasoning you make it.

This is a more ambitious claim than, say, your claim about efficiency in
your previous post, which did not account for, say, branch misprediction
tests? (I'm not claiming that performing all of the operations is
necessarily faster, or even proposing any probability that it would be,
but if *I* were going to make a claim about efficiency I'd certainly
want to qualify it with comments about the mechanisms at play in various
processor architectures and the like.)

I did consider those things (although I can't prove it to you), however I
didn't feel it necessary to mention each one specifically as you would
have done. I did qualify my claim with a generic statement intended to
cover issues like that: "You never know though - on some hardware it might
be; or the compiler might rewrite it for you."
My claim is based on experience, and I believe it's plausible. Feel
free to present a counterargument.

I don't want to argue about it. My question was based on curiosity, not
my side.

--
http://members.dodo.com.au/~netocrat
Nov 15 '05 #44

In article <pa****************************@dodo.com.au>, Netocrat <ne******@dodo.com.au> writes:
This really calls for a multi-way equality comparison:

if ( ! (a == b == c == d == ... == z == value) )

Obviously the semantics are wrong the way the equality operator is
currently defined, but I've sometimes wanted to use an expression like
this.

Try COBOL, which does support it, and perhaps you'll see why many
COBOL experts avoid it. (Actually, the COBOL syntax would be "if
value not = a or b or c".)

I don't know COBOL. Why do COBOL experts avoid it?

There are various reasons, most of which are grounded in either
issues with language syntax or potential for producing unclear
code. Here are some I've read:

1. Parentheses are forbidden in abbreviated-condition expressions,
because they can introduce ambiguities. (So the standard says. I
don't have an example handy, but it's probably not hard to come up
with one.)

2. Many implementations allow parentheses in abbreviated conditions
despite the standard, but that can lead to code that silently behaves
differently on different implementations.

3. COBOL's use of operators that are composed of multiple words can
lead to confusion between some operators and abbreviated conditions.
For example:

if a equals b or a greater or equal 5

looks like it might contain one or two abbreviated conditions, but
in fact it contains none. Thus some people avoid both abbreviated
conditions and operators like "greater or equal" in favor of their
symbolic equivalents (for implementations that support the latter).

4. Similarly, because the COBOL-85 standard was ambiguous about the
behavior of "greater than or equal to" and the like in abbreviated
conditions, some didn't handle them correctly at all. There's a
comment in the 2002 standard regarding this problem.

5. They can easily be abused. Here's an example from a post to
comp.lang.cobol:

if 1 greater or equal 0 or -1 and 2 equal 0

This evaluates to true, in the implementation the poster used,
because it's parsed as:

if (1 >= 0) or (1 >= -1 and 2 = 0)

Now something like the former expression is clearly confusing for
the maintainer.

6. At least one member of the standards committee, Chuck Stevens, has
written "I believe the simple and straightforward rules of COBOL
syntax in the area of abbreviated combined conditions have actually
been broken for over forty years, and it's way too late to change
them now". I don't recall Chuck's reasons for that statement, off
the top of my head, but I believe he made a good case. One of his
objections, I think, is that abbreviating the condition in English
seems to imply (for most readers) a degree of association which COBOL
does not enforce; that's why the example in #5 is confusing.

7. COBOL already provides enough ways to obscure the evaluation of a
conditional statement, such as testing if a variable contains any of
a number of values, the set of which is represented by an identifier
declared in the data division. (And those have special behavior in
abbreviated conditions, too.) And when you get to the EVALUATE
statement and its WHEN clauses, well, discarding some of the syntactic
sugar starts to look like a good idea.

8. Part of the design of COBOL is its verbosity: data formats and
program logic are spelled out, in part so they can be compared to
specifications written in a natural language. Abbreviated conditions
often work counter to that.

Anyway, you get the idea. It's been discussed various times in
comp.lang.cobol.
[re whether a multiway test is likely not the best design]
My claim is based on experience, and I believe it's plausible. Feel
free to present a counterargument.

I don't want to argue about it. My question was based on curiosity, not
my side.

I was probably a bit too short. I tried to consider various cases
where this logic might be necessary, and in all of the ones that
occurred to me it seemed there was an easier solution. For example,
when assigning a value to c,d,e..., update a counter of the number of
variables in that list which have a value unequal to the value of a.
(Then all the values are equal iff the value of the counter is 0.)
Obviously there are concurrency issues with that, if the program is
possibly poor locality of reference) makes it a suboptimal solution
for the OP; but we don't have sufficient information to do more than
guess.

In short, it seemed to me that only under a fairly unlikely set of
constraints would all of the following be true:

1. This test would have to be performed frequently.
2. This test would be performed in a time-critical portion of the
program.
3. The outcome of the test would often vary (ie, that it wouldn't
usually be either true or false). (If this is false, then the
precomputation can generally be structured to be more efficient for
the likelier case.)

And if they're not all true, then it should be possible to compute
the outcome of the test outside the time-critical portion of the
program.
--
Michael Wojcik mi************@microfocus.com

O sometimes, nevertheless,
The labourer at his instrument or tractor,
Bending into a state of merge with objects,
Finds the same love that, from a machine of sex,
Steps down as Venus to her invoker. -- George Barker
Nov 15 '05 #45
mw*****@newsguy.com (Michael Wojcik) wrote:
Netocrat <ne******@dodo.com.au> writes:
>> This really calls for a multi-way equality comparison:
>>
>> if ( ! (a == b == c == d == ... == z == value) )
>>
>> Obviously the semantics are wrong the way the equality operator is
>> currently defined, but I've sometimes wanted to use an expression
>> like this.
>
> Try COBOL, which does support it, and perhaps you'll see why many
> COBOL experts avoid it. (Actually, the COBOL syntax would be "if
> value not = a or b or c".)
I don't know COBOL. Why do COBOL experts avoid it?

There are various reasons, most of which are grounded in either issues
with language syntax or potential for producing unclear code. Here are

[...] Anyway, you get the idea. It's been discussed various times in
comp.lang.cobol.
I do get the idea - that was some list. The main theme seems to be
confusion.

Putting aside the utility of such an operator, which I guess you would
argue against, do you think that this confusion might be avoided by
limiting a multi-way C comparison to those cases where parentheses were
absent? In other words, I'm proposing that (a == b == c) would be a
multi-way comparison whereas ((a == b) == c) would be a comparison of (a
== b) against c.

The only potential issue I can see is when a, b and c are complex
expressions rather than variables.

The alternative would be a new operator for multi-way comparisons, such as
===, which would be used similarly to the (a?b:c) construct except that
the ? and : would both be replaced by === and it could be used for more
than three operands.

Obviously the former suggestion is never going to happen because it would
break too much existing code, but the second seems workable to me - and it
would allow the compiler to generate the most efficient code - deciding
between assembly versions of the bitwise constructs suggested in this
thread vs successive "test and branch"es, taking into account branch
misprediction etc.
> [re whether a multiway test is likely not the best design]

[...] I was probably a bit too short. I tried to consider various cases where
this logic might be necessary, and in all of the ones that occurred to
me it seemed there was an easier solution. For example,

[snip rest of reasoning]

That was very cogent reasoning of the style I was hoping to elicit.

--
http://members.dodo.com.au/~netocrat
Nov 15 '05 #46

In article <pa****************************@dodo.com.au>, Netocrat <ne******@dodo.com.au> writes:
mw*****@newsguy.com (Michael Wojcik) wrote:
Netocrat <ne******@dodo.com.au> writes:

>> This really calls for a multi-way equality comparison:
>>
>> if ( ! (a == b == c == d == ... == z == value) )
>>
>> Obviously the semantics are wrong the way the equality operator is
>> currently defined, but I've sometimes wanted to use an expression
>> like this.
>
> Try COBOL, which does support it, and perhaps you'll see why many
> COBOL experts avoid it.

I do get the idea - that was some list. The main theme seems to be
confusion.

Putting aside the utility of such an operator, which I guess you would
argue against, do you think that this confusion might be avoided by
limiting a multi-way C comparison to those cases where parentheses were
absent? In other words, I'm proposing that (a == b == c) would be a
multi-way comparison whereas ((a == b) == c) would be a comparison of (a
== b) against c.

Ouch. I wouldn't want parentheses to change the behavior of the
operator.
The alternative would be a new operator for multi-way comparisons, such as
===, which would be used similarly to the (a?b:c) construct except that
the ? and : would both be replaced by === and it could be used for more
than three operands.

How would this work? The implementation can't process it as a series
of independent comparisons, as in:

op1 === op2 evaluates to the value of op2 if op1 and op2 have
the same value, or 0 otherwise

so that you have the value to compare with the next expression when
you have a chain of === expressions (which is the only time you'd
want to use them). The problem is that you can't distinguish between
the "false" value and the case where both operands have that value.
If "false" is 0 - and for consistency and correct operation of
conditional expressions it has to be - then the following doesn't
work:

int a = 0, b = 0;

if (a === b) puts("it works");

For === to work, the grammar has to expand the phrase to include all
the "===" operations in the chain, so all the operands can be
evaluated, then their values compared, then the result of all the
chained === comparisons computed. (That result will have to be 1 or
0, both for consistency with other relational operators and to
sensibly handle the case where all operands have the value 0.)

Nothing else in C works that way. It doesn't fit with the rest of
the grammar. Nor is it clear what happens with parenthesization or
complex operands that include sequence points (eg function calls),
or how it interacts with operators like comma and the short-
circuiting logicals.

If C had a notion of "false" that was distinct from any possible
operand value, then the definition of === as an operator that
returned either "false" or the value of its operands could work
nicely. But C doesn't, and it's hard to see how any language
would have such a construct - because programmers would want to
be able to store that "false" result in some kind of variable!

So while it's easy to grasp intuitively how === should work, at
least for the obvious cases, I think it's a poor fit for the formal
definition of the language. That's the problem COBOL ran into with
abbreviated conditionals (and some other features): the effort to
formalize the definition of the language came very late, and many
features proved impossible to formalize consistently and accurately
while maintaining the behavior that users intuitively expected. In
some cases that only became apparent after a feature was incorporated
into the specification, requiring revisions and clarifications in
later versions of the spec.

In APL and its relatives, you can apply the equality operator across
a vector, but that still doesn't do what you want (it does consecu-
tive evaluations, so you end up with the same result you have in C).
You can take an "outer product" of equality, though, and then if any
elements of that are 0 then at least two elements are not equal; and
it's easy to collapse that into a single boolean value.

The "outer equality product" produces a matrix of comparisons. In
the case of {1 2 2 2}, for example, it'd look like:

1 0 0 0
0 1 1 1
0 1 1 1
0 1 1 1

Then applying logical-and to the rows of that array yields a vector:

0 0 0 0

and applying it to that vector yields 1 iff all elements of the
original were equal.

Of course, we really only need one row of the outer product, since
each row compares one element in the original vector with itself and
each of the others; so I could just drop the other rows and apply
logical-and to it. That would be faster and more elegant, but I just
thought of it as I was writing this. (Another way would be to take
the minimum and maximum value in the original vector and compare
them. Those are basic APL operations, too.)

So, if you just add some APL to C, you'd be able to do what you want.
:-)

The Wikipedia article on APL conveys the flavor of the language well.

--
Michael Wojcik mi************@microfocus.com

The presence of those seeking the truth is infinitely preferable to
the presence of those who think they've found it. -- Terry Pratchett
Nov 15 '05 #47
mw*****@newsguy.com (Michael Wojcik) wrote:
Netocrat <ne******@dodo.com.au> writes:
mw*****@newsguy.com (Michael Wojcik) wrote:
> Netocrat <ne******@dodo.com.au> writes:
>>
>> >> This really calls for a multi-way equality comparison:
>> >>
>> >> if ( ! (a == b == c == d == ... == z == value) )
>> >>
>> >> Obviously the semantics are wrong the way the equality operator is
>> >> currently defined, but I've sometimes wanted to use an expression
>> >> like this.
>> >
>> > Try COBOL, which does support it, and perhaps you'll see why many
>> > COBOL experts avoid it.
I do get the idea - that was some list. The main theme seems to be
confusion.

Putting aside the utility of such an operator, which I guess you would
argue against, do you think that this confusion might be avoided by
limiting a multi-way C comparison to those cases where parentheses were
absent? In other words, I'm proposing that (a == b == c) would be a
multi-way comparison whereas ((a == b) == c) would be a comparison of (a
== b) against c.

Ouch. I wouldn't want parentheses to change the behavior of the
operator.

Fair enough - it was a somewhat inelegant hack. Existing use precludes
this change anyway.
The alternative would be a new operator for multi-way comparisons, such as
===, which would be used similarly to the (a?b:c) construct except that
the ? and : would both be replaced by === and it could be used for more
than three operands.

How would this work?

My wording was apparently unclear. By "similarly to the (a?b:c)
construct" I meant to indicate how parentheses would affect the
expression, not how its value would be determined.

[...] For === to work, the grammar has to expand the phrase to include all the
"===" operations in the chain, so all the operands can be evaluated,
then their values compared, then the result of all the chained ===
comparisons computed. (That result will have to be 1 or 0, both for
consistency with other relational operators and to sensibly handle the
case where all operands have the value 0.)
Yes, that's exactly what I intended.
Nothing else in C works that way.
On its own - which admittedly I don't think is how you intended the
statement to be read - that's not reason enough to reject the proposal.
I'd consider the question "does it contradict the spirit of C?" more
relevant in isolation. Arguably the ability to fairly easily construct a
similar statement using existing operators is cause to answer yes.

On the other hand I think that the advantage of a new operator is that it
would make it clearer to a compiler and reader what is intended and allow
for more concise code, which *is* in keeping with C's spirit.
It doesn't fit with the rest of the grammar. Nor is it clear what
happens with parenthesization
I see something of a precedent in the ?: construct - at least for
parentheses.
or complex operands that include sequence
points (eg function calls),
Is "identically as for the single-way equality operator" a sufficient
definition? I haven't given it much thought.
or how it interacts with operators like comma
Probably the comma operator would have higher precedence than the ===
operator. So, for example, the expression:
a === b, c === d, e === f

would mean:
a === (b, c) === (d, e) === f

Whereas:
a === b, c == d, e === f

would mean:
a === (b, c == d, e) === f

There may be other ways to define the precedence/rules but again I haven't
and the short- circuiting logicals.
Probably these operators would have higher precedence. So:
a === b && c || d === e && f || g === h
would mean:
a === (b && c || d) === (e && f || g) === h
If C had a notion of "false" that was distinct from any possible operand
value, then the definition of === as an operator that returned either
"false" or the value of its operands could work nicely.
Right, as I wrote above my wording was unclear and that's not what I
intended.

[...] So while it's easy to grasp intuitively how === should work, at least
for the obvious cases, I think it's a poor fit for the formal definition
of the language.
Do my above attempts to clarify and better define the semantics affect
your opinion? Granted they're not very formal and may be missing some
cases, but I can't see any glaring deficiencies.

[...] In APL and its relatives, you can apply the equality operator across a
vector, [...] The "outer equality product" produces a matrix of comparisons. [...] Then applying logical-and to the rows of that array yields a vector [...] and applying it to that vector yields 1 iff all elements of the
original were equal.
That part of the language sounds a little similar to MatLab where
variables are by default arrays, although having last used it several
years ago I can't recall how the equality operator worked.

[...] So, if you just add some APL to C, you'd be able to do what you want.
:-)
Judging from the Wikipedia article, there's only one way that any APL

Who's got the gaffer tape?
The Wikipedia article on APL conveys the flavor of the language well.

--
http://members.dodo.com.au/~netocrat
Nov 15 '05 #48
Netocrat <ne******@dodo.com.au> wrote:

[ Guys! Learn to snip... ]
mw*****@newsguy.com (Michael Wojcik) wrote:
or how it interacts with operators like comma
Probably the comma operator would have higher precedence than the ===
operator. So, for example, the expression:
a === b, c === d, e === f

(BTW: ew, Icon...)
would mean:
a === (b, c) === (d, e) === f

Right now, the comma operator has the lowest precedence of any operator.
I believe that this is for a reason, and should remain that way.

Richard
Nov 15 '05 #49
rl*@hoekstra-uitgeverij.nl (Richard Bos) wrote:
Netocrat <ne******@dodo.com.au> wrote:

[ Guys! Learn to snip... ]

I thought we kept a reasonable balance between minimal yet sufficient
content for each post to stand alone. I'll take your comment as need to
reconsider. I rather expected an OT call before a more snippage call.
mw*****@newsguy.com (Michael Wojcik) wrote:
> or how it interacts with operators like comma

Probably the comma operator would have higher precedence than the ===
operator. So, for example, the expression:
a === b, c === d, e === f

(BTW: ew, Icon...)

Indeed - I did try to come up with something more useful but the
choice of symbols is limited and the only other decent choice I could
see at short notice (~=) is afaik already used by C++.
would mean:
a === (b, c) === (d, e) === f

Right now, the comma operator has the lowest precedence of any operator.
I believe that this is for a reason, and should remain that way.

Yes you're right, perhaps precedence isn't the right word. I was
modelling the operator after the behaviour of ?: which in this respect
behaves the same way. i.e.
a ? b, c : d, e

means:
a ? (b, c) : (d, e)

(or at least that's how gcc treats it, I haven't consulted the standard to
confirm)

The alternative is that the comma operator instead delimits a multi-way
equality comparison. So now:
a === b, c === d, e === f

would mean:
(a === b), (c === d), (e === f)

Both are different to the semantics of the single equality operator, but
given that it takes more operands I don't see a way around that.

--
http://members.dodo.com.au/~netocrat
Nov 15 '05 #50

### This discussion thread is closed

Replies have been disabled for this discussion.